diff --git a/src/client/dfs/common.c b/src/client/dfs/common.c index e16d6beb9a0..afd514be6d0 100644 --- a/src/client/dfs/common.c +++ b/src/client/dfs/common.c @@ -788,7 +788,7 @@ set_sb_params(bool for_update, daos_iod_t *iods, daos_key_t *dkey) int open_sb(daos_handle_t coh, bool create, bool punch, int omode, daos_obj_id_t super_oid, - dfs_attr_t *attr, daos_handle_t *oh, dfs_layout_ver_t *ver) + dfs_attr_t *attr, daos_handle_t *oh, dfs_layout_ver_t *ver, dfs_sb_ver_t *sb_ver_out) { d_sg_list_t sgls[SB_AKEYS]; d_iov_t sg_iovs[SB_AKEYS]; @@ -919,6 +919,8 @@ open_sb(daos_handle_t coh, bool create, bool punch, int omode, daos_obj_id_t sup D_DEBUG(DB_ALL, "DFS Library Layout version: %d\n", DFS_LAYOUT_VERSION); *ver = layout_ver; + if (sb_ver_out) + *sb_ver_out = sb_ver; attr->da_chunk_size = (chunk_size) ? chunk_size : DFS_DEFAULT_CHUNK_SIZE; attr->da_oclass_id = oclass; attr->da_dir_oclass_id = dir_oclass; diff --git a/src/client/dfs/cont.c b/src/client/dfs/cont.c index 917012c3055..5b0a80a3c31 100644 --- a/src/client/dfs/cont.c +++ b/src/client/dfs/cont.c @@ -1,6 +1,6 @@ /** - * (C) Copyright 2018-2024 Intel Corporation. - * (C) Copyright 2025-2026 Hewlett Packard Enterprise Development LP + * Copyright 2018-2024 Intel Corporation. + * Copyright 2025-2026 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -290,8 +290,18 @@ dfs_cont_create(daos_handle_t poh, uuid_t *cuuid, dfs_attr_t *attr, daos_handle_ D_GOTO(err_prop, rc = daos_der2errno(rc)); } - /* store SB & root OIDs as container property */ - roots.cr_oids[2] = roots.cr_oids[3] = DAOS_OBJ_NIL; + /* select oclass and generate GIT (Global Inode Table) OID */ + roots.cr_oids[2].lo = RESERVED_LO; + roots.cr_oids[2].hi = GIT_HI; + rc = daos_obj_generate_oid_by_rf(poh, rf, &roots.cr_oids[2], 0, dattr.da_dir_oclass_id, + dir_oclass_hint, 0, pa_domain); + if (rc) { + D_ERROR("Failed to generate GIT OID " DF_RC "\n", DP_RC(rc)); + D_GOTO(err_prop, rc = daos_der2errno(rc)); + } + + /* store SB, root & GIT OIDs as container property */ + roots.cr_oids[3] = DAOS_OBJ_NIL; if (roots_entry == NULL) { /* need to add roots prop to list */ @@ -330,7 +340,7 @@ dfs_cont_create(daos_handle_t poh, uuid_t *cuuid, dfs_attr_t *attr, daos_handle_ } /** Create SB */ - rc = open_sb(coh, true, false, DAOS_OO_RW, roots.cr_oids[0], &dattr, &super_oh, NULL); + rc = open_sb(coh, true, false, DAOS_OO_RW, roots.cr_oids[0], &dattr, &super_oh, NULL, NULL); if (rc) D_GOTO(err_close, rc); @@ -1179,7 +1189,7 @@ dfs_recreate_sb(daos_handle_t coh, dfs_attr_t *attr) } /** Recreate SB */ - rc = open_sb(coh, true, true, DAOS_OO_RW, roots->cr_oids[0], attr, &super_oh, NULL); + rc = open_sb(coh, true, true, DAOS_OO_RW, roots->cr_oids[0], attr, &super_oh, NULL, NULL); if (rc) D_GOTO(out_prop, rc); @@ -1255,7 +1265,8 @@ dfs_relink_root(daos_handle_t coh) } /** Verify SB */ - rc = open_sb(coh, false, false, DAOS_OO_RW, roots->cr_oids[0], &attr, &super_oh, &layout_v); + rc = open_sb(coh, false, false, DAOS_OO_RW, roots->cr_oids[0], &attr, &super_oh, &layout_v, + NULL); if (rc) D_GOTO(out_prop, rc); diff --git a/src/client/dfs/dfs_internal.h b/src/client/dfs/dfs_internal.h index 41be576c349..0ed825aa759 100644 --- a/src/client/dfs/dfs_internal.h +++ b/src/client/dfs/dfs_internal.h @@ -1,5 +1,6 @@ /** * (C) Copyright 2019-2024 Intel Corporation. + * (C) Copyright 2026 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -53,7 +54,7 @@ /** Magic Value */ #define DFS_SB_MAGIC 0xda05df50da05df50 /** DFS SB version value */ -#define DFS_SB_VERSION 2 +#define DFS_SB_VERSION 3 /** DFS Layout Version Value */ #define DFS_LAYOUT_VERSION 3 /** Magic value for serializing / deserializing a DFS handle */ @@ -94,6 +95,10 @@ #define RESERVED_LO 0 #define SB_HI 0 #define ROOT_HI 1 +#define GIT_HI 2 + +/** SB version that introduced hardlink support (GIT object) */ +#define DFS_MIN_GIT_SB_VERSION 3 /** DFS mode mask (3rd bit) */ #define MODE_MASK (1 << 2) @@ -175,6 +180,10 @@ struct dfs { daos_obj_id_t super_oid; /** Open object handle of SB */ daos_handle_t super_oh; + /** Global Index Table object OID */ + daos_obj_id_t git_oid; + /** Open object handle of GIT */ + daos_handle_t git_oh; /** Root object info */ dfs_obj_t root; /** DFS container attributes (Default chunk size, oclass, etc.) */ @@ -361,7 +370,7 @@ oid_gen(dfs_t *dfs, daos_oclass_id_t oclass, bool file, daos_obj_id_t *oid) /** set oid and lo, bump the current hi value */ oid->lo = dfs->oid.lo; daos_obj_oid_cycle(&dfs->oid); - if (unlikely(dfs->oid.lo == RESERVED_LO && dfs->oid.hi <= 1)) + if (unlikely(dfs->oid.lo == RESERVED_LO && dfs->oid.hi <= GIT_HI)) daos_obj_oid_cycle(&dfs->oid); /* Avoid reserved oids */ oid->hi = dfs->oid.hi; D_MUTEX_UNLOCK(&dfs->lock); @@ -402,7 +411,7 @@ get_oclass_hints(const char *hints, daos_oclass_hints_t *dir_hints, daos_oclass_ uint64_t rf); int open_sb(daos_handle_t coh, bool create, bool punch, int omode, daos_obj_id_t super_oid, - dfs_attr_t *attr, daos_handle_t *oh, dfs_layout_ver_t *ver); + dfs_attr_t *attr, daos_handle_t *oh, dfs_layout_ver_t *ver, dfs_sb_ver_t *sb_ver); int insert_entry(dfs_layout_ver_t ver, daos_handle_t oh, daos_handle_t th, const char *name, size_t len, uint64_t flags, struct dfs_entry *entry); diff --git a/src/client/dfs/mnt.c b/src/client/dfs/mnt.c index ec0b5f8a282..0a179b6f014 100644 --- a/src/client/dfs/mnt.c +++ b/src/client/dfs/mnt.c @@ -1,6 +1,6 @@ /** - * (C) Copyright 2018-2024 Intel Corporation. - * (C) Copyright 2026 Hewlett Packard Enterprise Development LP + * Copyright 2018-2024 Intel Corporation. + * Copyright 2026 Hewlett Packard Enterprise Development LP * * SPDX-License-Identifier: BSD-2-Clause-Patent */ @@ -573,6 +573,7 @@ dfs_mount_int(daos_handle_t poh, daos_handle_t coh, int flags, daos_epoch_t epoc struct daos_prop_entry *entry; struct daos_prop_co_roots *roots; struct dfs_entry root_dir; + dfs_sb_ver_t sb_ver; int amode, omode; int rc; int i; @@ -642,10 +643,14 @@ dfs_mount_int(daos_handle_t poh, daos_handle_t coh, int flags, daos_epoch_t epoc /** Verify SB */ rc = open_sb(coh, false, false, omode, dfs->super_oid, &dfs->attr, &dfs->super_oh, - &dfs->layout_v); + &dfs->layout_v, &sb_ver); if (rc) D_GOTO(err_dfs, rc); + /** Load GIT OID only if SB version supports hardlinks */ + if (sb_ver >= DFS_MIN_GIT_SB_VERSION) + dfs->git_oid = roots->cr_oids[2]; + /** set oid hints for files and dirs */ if (dfs->attr.da_hints[0] != 0) { entry = daos_prop_entry_get(prop, DAOS_PROP_CO_REDUN_FAC); @@ -717,17 +722,26 @@ dfs_mount_int(daos_handle_t poh, daos_handle_t coh, int flags, daos_epoch_t epoc dfs->root_stbuf.st_atim.tv_nsec = root_dir.mtime_nano; } + /** Open Global Index Table object */ + if (!daos_obj_id_is_nil(dfs->git_oid)) { + rc = daos_obj_open(dfs->coh, dfs->git_oid, omode, &dfs->git_oh, NULL); + if (rc) { + D_ERROR("Failed to open GIT object: " DF_RC "\n", DP_RC(rc)); + D_GOTO(err_root, rc = daos_der2errno(rc)); + } + } + /** if RW, allocate an OID for the namespace */ if (amode == O_RDWR) { dfs->last_hi = (unsigned int)d_rand(); - /** Avoid potential conflict with SB or ROOT */ - if (dfs->last_hi <= 1) - dfs->last_hi = 2; + /** Avoid potential conflict with SB, ROOT, or GIT */ + if (dfs->last_hi <= GIT_HI) + dfs->last_hi = GIT_HI + 1; rc = daos_cont_alloc_oids(coh, 1, &dfs->oid.lo, NULL); if (rc) { D_ERROR("daos_cont_alloc_oids() Failed, " DF_RC "\n", DP_RC(rc)); - D_GOTO(err_root, rc = daos_der2errno(rc)); + D_GOTO(err_git, rc = daos_der2errno(rc)); } dfs->oid.hi = dfs->last_hi; @@ -743,6 +757,9 @@ dfs_mount_int(daos_handle_t poh, daos_handle_t coh, int flags, daos_epoch_t epoc daos_prop_free(prop); return rc; +err_git: + if (daos_handle_is_valid(dfs->git_oh)) + daos_obj_close(dfs->git_oh, NULL); err_root: daos_obj_close(dfs->root.oh, NULL); err_super: @@ -850,6 +867,8 @@ dfs_umount(dfs_t *dfs) if (daos_handle_is_valid(dfs->th)) daos_tx_close(dfs->th, NULL); + if (daos_handle_is_valid(dfs->git_oh)) + daos_obj_close(dfs->git_oh, NULL); daos_obj_close(dfs->root.oh, NULL); daos_obj_close(dfs->super_oh, NULL); @@ -983,6 +1002,7 @@ struct dfs_glob { daos_obj_id_t super_oid; daos_obj_id_t root_oid; daos_epoch_t th_epoch; + daos_obj_id_t git_oid; }; static inline void @@ -1065,6 +1085,7 @@ dfs_local2global(dfs_t *dfs, d_iov_t *glob) dfs_params->amode = dfs->amode; dfs_params->super_oid = dfs->super_oid; dfs_params->root_oid = dfs->root.oid; + dfs_params->git_oid = dfs->git_oid; dfs_params->uid = dfs->uid; dfs_params->gid = dfs->gid; dfs_params->id = dfs->attr.da_id; @@ -1144,6 +1165,7 @@ dfs_global2local(daos_handle_t poh, daos_handle_t coh, int flags, d_iov_t glob, dfs->super_oid = dfs_params->super_oid; dfs->root.oid = dfs_params->root_oid; dfs->root.parent_oid = dfs->super_oid; + dfs->git_oid = dfs_params->git_oid; if (daos_obj_id_is_nil(dfs->super_oid) || daos_obj_id_is_nil(dfs->root.oid)) { D_ERROR("Invalid superblock or root object ID\n"); D_FREE(dfs); @@ -1179,6 +1201,17 @@ dfs_global2local(daos_handle_t poh, daos_handle_t coh, int flags, d_iov_t glob, D_GOTO(err_dfs, rc = daos_der2errno(rc)); } + /* Open GIT (Global Index Table) Object */ + if (!daos_obj_id_is_nil(dfs->git_oid)) { + rc = daos_obj_open(coh, dfs->git_oid, obj_mode, &dfs->git_oh, NULL); + if (rc) { + D_ERROR("daos_obj_open() failed for GIT, " DF_RC "\n", DP_RC(rc)); + daos_obj_close(dfs->super_oh, NULL); + daos_obj_close(dfs->root.oh, NULL); + D_GOTO(err_dfs, rc = daos_der2errno(rc)); + } + } + /** Create transaction handle */ dfs->th_epoch = dfs_params->th_epoch; if (dfs->th_epoch == DAOS_EPOCH_MAX) { @@ -1189,6 +1222,8 @@ dfs_global2local(daos_handle_t poh, daos_handle_t coh, int flags, d_iov_t glob, D_ERROR("daos_tx_open_snap() failed, " DF_RC "\n", DP_RC(rc)); daos_obj_close(dfs->super_oh, NULL); daos_obj_close(dfs->root.oh, NULL); + if (daos_handle_is_valid(dfs->git_oh)) + daos_obj_close(dfs->git_oh, NULL); D_GOTO(err_dfs, rc = daos_der2errno(rc)); } }