Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
711 changes: 683 additions & 28 deletions src/client/dfs/common.c

Large diffs are not rendered by default.

619 changes: 588 additions & 31 deletions src/client/dfs/cont.c

Large diffs are not rendered by default.

46 changes: 45 additions & 1 deletion src/client/dfs/dfs_internal.h
Original file line number Diff line number Diff line change
@@ -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
*/
Expand Down Expand Up @@ -63,6 +64,8 @@

/** Number of A-keys for attributes in any object entry */
#define INODE_AKEYS 12
/** Number of A-keys for HLM entries (includes ref_cnt) */
#define HLM_INODE_AKEYS 13
#define INODE_AKEY_NAME "DFS_INODE"
#define SLINK_AKEY_NAME "DFS_SLINK"
#define MODE_IDX 0
Expand All @@ -78,6 +81,8 @@
#define SIZE_IDX (GID_IDX + sizeof(gid_t))
#define HLC_IDX (SIZE_IDX + sizeof(daos_size_t))
#define END_IDX (HLC_IDX + sizeof(uint64_t))
#define REF_CNT_IDX END_IDX
#define END_HLM_IDX (REF_CNT_IDX + sizeof(uint64_t))

/*
* END IDX for layout V2 (2.0) is at the current offset where we store the mtime nsec, but also need
Expand All @@ -94,10 +99,21 @@
#define RESERVED_LO 0
#define SB_HI 0
#define ROOT_HI 1
#define HLM_HI 2

/** DFS mode mask (3rd bit) */
#define MODE_MASK (1 << 2)

/** Hardlink mode bit - highest bit in mode_t to indicate file is a hardlink */
#define MODE_HARDLINK_BIT (1U << 31)

/** Check if a mode indicates this is a hardlinked regular file */
static inline bool
dfs_is_hardlink(mode_t mode)
{
return S_ISREG(mode) && (mode & MODE_HARDLINK_BIT);
}

/** Max recursion depth for symlinks */
#define DFS_MAX_RECURSION 40

Expand Down Expand Up @@ -175,6 +191,10 @@ struct dfs {
daos_obj_id_t super_oid;
/** Open object handle of SB */
daos_handle_t super_oh;
/** Hardlink metadata object OID */
daos_obj_id_t hlm_oid;
/** Open object handle of HLM */
daos_handle_t hlm_oh;
/** Root object info */
dfs_obj_t root;
/** DFS container attributes (Default chunk size, oclass, etc.) */
Expand Down Expand Up @@ -223,6 +243,8 @@ struct dfs_entry {
gid_t gid;
/** Sym Link value */
char *value;
/** Number of hardlinks to the same file object */
uint64_t ref_cnt;
};

/** enum for hash entry type */
Expand Down Expand Up @@ -411,8 +433,30 @@ fetch_entry(dfs_layout_ver_t ver, daos_handle_t oh, daos_handle_t th, const char
bool fetch_sym, bool *exists, struct dfs_entry *entry, int xnr, char *xnames[],
void *xvals[], daos_size_t *xsizes);
int
hlm_fetch_entry(daos_handle_t hlm_oh, daos_handle_t th, daos_obj_id_t *oid,
struct dfs_entry *entry);
int
dfsobj_fetch_entry(dfs_t *dfs, daos_handle_t th, dfs_obj_t *obj, daos_handle_t *parent_oh,
struct dfs_entry *entry);
int
hlm_update_ref_cnt(dfs_t *dfs, daos_handle_t th, struct dfs_entry *entry, int delta);
int
remove_entry(dfs_t *dfs, daos_handle_t th, daos_handle_t parent_oh, const char *name, size_t len,
struct dfs_entry entry);
struct dfs_entry entry, bool *deleted);
int
hlm_copy_xattr(daos_handle_t src_oh, const char *src_name, daos_handle_t hlm_oh,
daos_obj_id_t *dst_oid, daos_handle_t th);
int
hlm_copy_entry(dfs_t *dfs, daos_handle_t th, daos_handle_t parent_oh, const char *name,
struct dfs_entry *entry);
int
remove_xattrs_from_entry(dfs_t *dfs, daos_handle_t th, daos_handle_t parent_oh, const char *name);
int
set_hardlink_bit(dfs_t *dfs, daos_handle_t th, daos_handle_t parent_oh, dfs_obj_t *obj,
mode_t mode);
int
clear_hardlink_bit(dfs_t *dfs, daos_handle_t th, daos_handle_t parent_oh, dfs_obj_t *obj,
mode_t mode);
int
open_dir(dfs_t *dfs, dfs_obj_t *parent, int flags, daos_oclass_id_t cid, struct dfs_entry *entry,
size_t len, dfs_obj_t *dir);
Expand Down
14 changes: 11 additions & 3 deletions src/client/dfs/dir.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/**
* (C) Copyright 2018-2024 Intel Corporation.
* (C) Copyright 2026 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
Expand Down Expand Up @@ -123,7 +124,7 @@ remove_dir_contents(dfs_t *dfs, daos_handle_t th, struct dfs_entry entry)
D_GOTO(out, rc);
}

rc = remove_entry(dfs, th, oh, ptr, kds[i].kd_key_len, child_entry);
rc = remove_entry(dfs, th, oh, ptr, kds[i].kd_key_len, child_entry, NULL);
if (rc)
D_GOTO(out, rc);
}
Expand All @@ -135,7 +136,8 @@ remove_dir_contents(dfs_t *dfs, daos_handle_t th, struct dfs_entry entry)
}

int
dfs_remove(dfs_t *dfs, dfs_obj_t *parent, const char *name, bool force, daos_obj_id_t *oid)
dfs_remove_internal(dfs_t *dfs, dfs_obj_t *parent, const char *name, bool force, daos_obj_id_t *oid,
bool *deleted)
{
struct dfs_entry entry = {0};
daos_handle_t th = DAOS_TX_NONE;
Expand Down Expand Up @@ -205,7 +207,7 @@ dfs_remove(dfs_t *dfs, dfs_obj_t *parent, const char *name, bool force, daos_obj
}
}

rc = remove_entry(dfs, th, parent->oh, name, len, entry);
rc = remove_entry(dfs, th, parent->oh, name, len, entry, deleted);
if (rc)
D_GOTO(out, rc);

Expand All @@ -229,6 +231,12 @@ dfs_remove(dfs_t *dfs, dfs_obj_t *parent, const char *name, bool force, daos_obj
return rc;
}

int
dfs_remove(dfs_t *dfs, dfs_obj_t *parent, const char *name, bool force, daos_obj_id_t *oid)
{
return dfs_remove_internal(dfs, parent, name, force, oid, NULL);
}

int
dfs_obj_set_oclass(dfs_t *dfs, dfs_obj_t *obj, int flags, daos_oclass_id_t cid)
{
Expand Down
83 changes: 60 additions & 23 deletions src/client/dfs/file.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/**
* (C) Copyright 2018-2024 Intel Corporation.
* (C) Copyright 2026 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
Expand Down Expand Up @@ -47,21 +48,15 @@ dfs_get_chunk_size(dfs_obj_t *obj, daos_size_t *chunk_size)
static int
set_chunk_size(dfs_t *dfs, dfs_obj_t *obj, daos_size_t csize)
{
daos_handle_t oh;
d_sg_list_t sgl;
d_iov_t sg_iov;
daos_iod_t iod;
daos_recx_t recx;
daos_key_t dkey;
int rc;

/** Open parent object and fetch entry of obj from it */
rc = daos_obj_open(dfs->coh, obj->parent_oid, DAOS_OO_RW, &oh, NULL);
if (rc)
return daos_der2errno(rc);

/** set dkey as the entry name */
d_iov_set(&dkey, (void *)obj->name, strlen(obj->name));
daos_handle_t oh = DAOS_HDL_INVAL;
d_sg_list_t sgl;
d_iov_t sg_iov;
daos_iod_t iod;
daos_recx_t recx;
daos_key_t dkey;
struct dfs_entry entry = {0};
bool exists;
int rc;

/** set akey as the inode name */
d_iov_set(&iod.iod_name, INODE_AKEY_NAME, sizeof(INODE_AKEY_NAME) - 1);
Expand All @@ -78,15 +73,57 @@ set_chunk_size(dfs_t *dfs, dfs_obj_t *obj, daos_size_t csize)
sgl.sg_nr_out = 0;
sgl.sg_iovs = &sg_iov;

rc = daos_obj_update(oh, DAOS_TX_NONE, DAOS_COND_DKEY_UPDATE, &dkey, 1, &iod, &sgl, NULL);
if (rc) {
D_ERROR("Failed to update chunk size: " DF_RC "\n", DP_RC(rc));
D_GOTO(out, rc = daos_der2errno(rc));
retry:
if (dfs_is_hardlink(obj->mode)) {
/* For hardlinks, update chunk size in HLM with OID as dkey */
d_iov_set(&dkey, &obj->oid, sizeof(daos_obj_id_t));

rc = daos_obj_update(dfs->hlm_oh, DAOS_TX_NONE, DAOS_COND_DKEY_UPDATE, &dkey, 1,
&iod, &sgl, NULL);
if (rc) {
D_ERROR("Failed to update chunk size in HLM: " DF_RC "\n", DP_RC(rc));
return daos_der2errno(rc);
}
} else {
/** Open parent object and fetch entry of obj from it */
rc = daos_obj_open(dfs->coh, obj->parent_oid, DAOS_OO_RW, &oh, NULL);
if (rc)
return daos_der2errno(rc);

/** set dkey as the entry name */
d_iov_set(&dkey, (void *)obj->name, strlen(obj->name));

rc = daos_obj_update(oh, DAOS_TX_NONE, DAOS_COND_DKEY_UPDATE, &dkey, 1, &iod, &sgl,
NULL);
if (rc) {
D_ERROR("Failed to update chunk size: " DF_RC "\n", DP_RC(rc));
daos_obj_close(oh, NULL);
return daos_der2errno(rc);
}

if (S_ISREG(obj->mode)) {
/*
* Check if the entry became a hardlink (another DFS instance may have
* converted it)
*/
rc = fetch_entry(dfs->layout_v, oh, dfs->th, obj->name, strlen(obj->name),
false, &exists, &entry, 0, NULL, NULL, NULL);
daos_obj_close(oh, NULL);
if (rc) {
D_ERROR("Failed to fetch entry: %d\n", rc);
return rc;
}
if (exists && dfs_is_hardlink(entry.mode)) {
/* Entry became a hardlink, update obj->mode and retry from HLM */
obj->mode = entry.mode;
goto retry;
}
} else {
daos_obj_close(oh, NULL);
}
}

out:
daos_obj_close(oh, NULL);
return rc;
return 0;
}

int
Expand Down Expand Up @@ -126,7 +163,7 @@ dfs_file_update_chunk_size(dfs_t *dfs, dfs_obj_t *obj, daos_size_t csize)

rc = set_chunk_size(dfs, obj, csize);
if (rc)
return daos_der2errno(rc);
return rc;

/* need to update the array handle chunk size */
rc = daos_array_update_chunk_size(obj->oh, csize);
Expand Down
33 changes: 29 additions & 4 deletions src/client/dfs/lookup.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/**
* (C) Copyright 2018-2024 Intel Corporation.
* (C) Copyright 2026 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
Expand Down Expand Up @@ -136,6 +137,18 @@ lookup_rel_path(dfs_t *dfs, dfs_obj_t *root, const char *path, int flags, dfs_ob

/** if entry is a file, open the array object and return */
if (S_ISREG(entry.mode)) {
/* If entry is a hardlink, fetch metadata from HLM */
if (dfs_is_hardlink(entry.mode)) {
rc = hlm_fetch_entry(dfs->hlm_oh, dfs->th, &entry.oid, &entry);
if (rc) {
D_ERROR("Failed to fetch entry '%s' oid=" DF_OID
" from HLM (%d)\n",
token, DP_OID(entry.oid), rc);
D_GOTO(err_obj, rc);
}
obj->mode = entry.mode;
}

/* if there are more entries, then file is not a dir */
if (strtok_r(NULL, "/", &sptr) != NULL) {
D_ERROR("%s is not a directory\n", obj->name);
Expand Down Expand Up @@ -168,6 +181,8 @@ lookup_rel_path(dfs_t *dfs, dfs_obj_t *root, const char *path, int flags, dfs_ob
D_GOTO(err_obj, rc = daos_der2errno(rc));
}

stbuf->st_nlink = entry.ref_cnt;
stbuf->st_mode = entry.mode & ~MODE_HARDLINK_BIT;
stbuf->st_size = array_stbuf.st_size;
stbuf->st_blocks = (stbuf->st_size + (1 << 9) - 1) >> 9;

Expand Down Expand Up @@ -339,8 +354,8 @@ lookup_rel_path(dfs_t *dfs, dfs_obj_t *root, const char *path, int flags, dfs_ob
}
memcpy(stbuf, &dfs->root_stbuf, sizeof(struct stat));
} else {
stbuf->st_nlink = 1;
stbuf->st_mode = obj->mode;
stbuf->st_nlink = entry.ref_cnt;
stbuf->st_mode = obj->mode & ~MODE_HARDLINK_BIT;
stbuf->st_uid = entry.uid;
stbuf->st_gid = entry.gid;
if (tspec_gt(stbuf->st_ctim, stbuf->st_mtim)) {
Expand Down Expand Up @@ -429,6 +444,16 @@ lookup_rel_int(dfs_t *dfs, dfs_obj_t *parent, const char *name, int flags, dfs_o
if (!exists)
return ENOENT;

/* If entry is a hardlink, fetch metadata from HLM */
if (dfs_is_hardlink(entry.mode)) {
rc = hlm_fetch_entry(dfs->hlm_oh, dfs->th, &entry.oid, &entry);
if (rc) {
D_ERROR("Failed to fetch entry '%s' oid=" DF_OID " from HLM (%d)\n", name,
DP_OID(entry.oid), rc);
return rc;
}
}

if (stbuf)
memset(stbuf, 0, sizeof(struct stat));

Expand Down Expand Up @@ -557,8 +582,8 @@ lookup_rel_int(dfs_t *dfs, dfs_obj_t *parent, const char *name, int flags, dfs_o
*mode = obj->mode;

if (stbuf) {
stbuf->st_nlink = 1;
stbuf->st_mode = obj->mode;
stbuf->st_nlink = entry.ref_cnt;
stbuf->st_mode = obj->mode & ~MODE_HARDLINK_BIT;
stbuf->st_uid = entry.uid;
stbuf->st_gid = entry.gid;
if (tspec_gt(stbuf->st_ctim, stbuf->st_mtim)) {
Expand Down
2 changes: 2 additions & 0 deletions src/client/dfs/metrics.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/**
* (C) Copyright 2024 Intel Corporation.
* (C) Copyright 2026 Hewlett Packard Enterprise Development LP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
Expand Down Expand Up @@ -45,6 +46,7 @@ extern "C" {
ACTION(SETXATTR) \
ACTION(STAT) \
ACTION(SYMLINK) \
ACTION(LINK) \
ACTION(SYNC) \
ACTION(TRUNCATE) \
ACTION(UNLINK) \
Expand Down
Loading
Loading