Skip to content
Open
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
2 changes: 1 addition & 1 deletion Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -999,7 +999,7 @@ pipeline {
inst_repos: daosRepos(),
test_script: 'ci/unit/test_nlt.sh' +
' --system-ram-reserved 4' +
' --max-log-size 1950MiB' +
' --max-log-size 2500MiB' +

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this needed?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the new set of tests added, I had seen failure related to log-size not sufficient. Hence increased the size.

' --dfuse-dir /localhome/jenkins/' +
' --log-usage-save nltir.xml' +
' --log-usage-export nltr.json' +
Expand Down
16 changes: 12 additions & 4 deletions src/client/dfs/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ fetch_entry(dfs_layout_ver_t ver, daos_handle_t oh, daos_handle_t th, const char

static int
remove_hardlink(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)
{
daos_key_t dkey;
daos_key_t git_dkey;
Expand Down Expand Up @@ -373,9 +373,13 @@ remove_hardlink(dfs_t *dfs, daos_handle_t th, daos_handle_t parent_oh, const cha
* directory entry still has its hardlink bit set, and the inode metadata
* remains in GIT.
*/
if (new_link_cnt > 0)
if (new_link_cnt > 0) {
if (deleted)
*deleted = false;
D_GOTO(out,
rc = git_update_link_cnt(dfs->git_oh, th, &entry.oid, new_link_cnt, NULL));
} else if (deleted)
*deleted = true;

d_iov_set(&git_dkey, &entry.oid, sizeof(daos_obj_id_t));
rc = daos_obj_punch_dkeys(dfs->git_oh, th, 0, 1, &git_dkey, NULL);
Expand Down Expand Up @@ -415,14 +419,18 @@ remove_hardlink(dfs_t *dfs, daos_handle_t th, daos_handle_t parent_oh, const cha

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)
{
daos_key_t dkey;
daos_handle_t oh;
int rc;

/* Default: the object is removed unless a surviving hardlink is found below. */
if (deleted)
*deleted = true;

if (DFS_IS_HARDLINK(entry.mode))
return remove_hardlink(dfs, th, parent_oh, name, len, entry);
return remove_hardlink(dfs, th, parent_oh, name, len, entry, deleted);

if (S_ISLNK(entry.mode))
goto punch_entry;
Expand Down
2 changes: 1 addition & 1 deletion src/client/dfs/dfs_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ fetch_entry(dfs_layout_ver_t ver, daos_handle_t oh, daos_handle_t th, const char
void *xvals[], daos_size_t *xsizes);
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
git_fetch_entry(daos_handle_t git_oh, daos_handle_t th, daos_obj_id_t *oid, struct dfs_entry *entry,
int xnr, char *xnames[], void *xvals[], daos_size_t *xsizes);
Expand Down
15 changes: 12 additions & 3 deletions src/client/dfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ dfs_mkdir(dfs_t *dfs, dfs_obj_t *parent, const char *name, mode_t mode, daos_ocl
if (rc)
return rc;

mode = DFS_EXTERNAL_MODE(mode);

strncpy(new_dir.name, name, len + 1);

rc = create_dir(dfs, parent, cid, &new_dir);
Expand Down Expand Up @@ -124,7 +126,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 @@ -138,7 +140,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 @@ -208,7 +211,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 @@ -232,6 +235,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
15 changes: 9 additions & 6 deletions src/client/dfs/obj.c
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,8 @@ open_stat(dfs_t *dfs, dfs_obj_t *parent, const char *name, mode_t mode, int flag
if (rc)
return rc;

mode = DFS_EXTERNAL_MODE(mode);

/** default for newly created entries; fetch_entry/git_fetch_entry overwrite for existing */
entry.link_cnt = 1;

Expand Down Expand Up @@ -1757,7 +1759,7 @@ dfs_osetattr(dfs_t *dfs, dfs_obj_t *obj, struct stat *stbuf, int flags)
i++;

flags &= ~DFS_SET_ATTR_MODE;
rstat.st_mode = stbuf->st_mode;
rstat.st_mode = DFS_EXTERNAL_MODE(stbuf->st_mode);
}
if (flags & DFS_SET_ATTR_ATIME) {
flags &= ~DFS_SET_ATTR_ATIME;
Expand Down Expand Up @@ -2220,11 +2222,6 @@ dfs_link(dfs_t *dfs, dfs_obj_t *obj, dfs_obj_t *parent, const char *new_name, df
stbuf->st_mode = DFS_EXTERNAL_MODE(link_entry->mode);
stbuf->st_uid = link_entry->uid;
stbuf->st_gid = link_entry->gid;
stbuf->st_mtim.tv_sec = link_entry->mtime;
stbuf->st_mtim.tv_nsec = link_entry->mtime_nano;
stbuf->st_ctim.tv_sec = link_entry->ctime;
stbuf->st_ctim.tv_nsec = link_entry->ctime_nano;
stbuf->st_atim = stbuf->st_mtim;
stbuf->st_blksize =
link_entry->chunk_size ? link_entry->chunk_size : dfs->attr.da_chunk_size;

Expand All @@ -2250,6 +2247,12 @@ dfs_link(dfs_t *dfs, dfs_obj_t *obj, dfs_obj_t *parent, const char *new_name, df
if (!(new_obj && *new_obj))
daos_array_close(arr_oh, NULL);

/** Reconcile entry times with the array's modification epoch, as normal stat does.
*/
rc = update_stbuf_times(*link_entry, array_stbuf.st_max_epoch, stbuf, NULL);
if (rc)
D_GOTO(out, rc);
stbuf->st_atim = stbuf->st_mtim;
stbuf->st_size = array_stbuf.st_size;
stbuf->st_blocks = (array_stbuf.st_size + (1 << 9) - 1) >> 9;
}
Expand Down
11 changes: 7 additions & 4 deletions src/client/dfs/rename.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ xattr_copy(daos_handle_t src_oh, const char *src_name, daos_handle_t dst_oh, con
int
dfs_move_internal(dfs_t *dfs, unsigned int flags, dfs_obj_t *parent, const char *name,
dfs_obj_t *new_parent, const char *new_name, daos_obj_id_t *moid,
daos_obj_id_t *oid)
daos_obj_id_t *oid, bool *deleted)
{
struct dfs_entry entry = {0}, new_entry = {0};
daos_handle_t th = DAOS_TX_NONE;
Expand All @@ -127,6 +127,9 @@ dfs_move_internal(dfs_t *dfs, unsigned int flags, dfs_obj_t *parent, const char
size_t new_len;
int rc;

if (deleted)
*deleted = false;

if (dfs == NULL || !dfs->mounted)
return EINVAL;
if (dfs->amode != O_RDWR)
Expand Down Expand Up @@ -244,7 +247,7 @@ dfs_move_internal(dfs_t *dfs, unsigned int flags, dfs_obj_t *parent, const char
D_GOTO(out, rc = ENOTEMPTY);
}

rc = remove_entry(dfs, th, new_parent->oh, new_name, new_len, new_entry);
rc = remove_entry(dfs, th, new_parent->oh, new_name, new_len, new_entry, deleted);
if (rc) {
D_ERROR("Failed to remove entry %s (%d)\n", new_name, rc);
D_GOTO(out, rc);
Expand All @@ -256,7 +259,7 @@ dfs_move_internal(dfs_t *dfs, unsigned int flags, dfs_obj_t *parent, const char

/** rename symlink */
if (S_ISLNK(entry.mode)) {
rc = remove_entry(dfs, th, parent->oh, name, len, entry);
rc = remove_entry(dfs, th, parent->oh, name, len, entry, NULL);
if (rc) {
D_ERROR("Failed to remove entry %s (%d)\n", name, rc);
D_GOTO(out, rc);
Expand Down Expand Up @@ -346,7 +349,7 @@ int
dfs_move(dfs_t *dfs, dfs_obj_t *parent, const char *name, dfs_obj_t *new_parent,
const char *new_name, daos_obj_id_t *oid)
{
return dfs_move_internal(dfs, 0, parent, name, new_parent, new_name, NULL, oid);
return dfs_move_internal(dfs, 0, parent, name, new_parent, new_name, NULL, oid, NULL);
}

int
Expand Down
1 change: 1 addition & 0 deletions src/client/dfuse/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ OPS_SRC = ['create',
'fgetattr',
'forget',
'getxattr',
'link',
'listxattr',
'ioctl',
'lookup',
Expand Down
81 changes: 75 additions & 6 deletions src/client/dfuse/dfuse.h
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,8 @@ struct dfuse_inode_ops {
const char *newname, unsigned int flags);
void (*symlink)(fuse_req_t req, const char *link,
struct dfuse_inode_entry *parent, const char *name);
void (*hardlink)(fuse_req_t req, struct dfuse_inode_entry *inode,
struct dfuse_inode_entry *parent, const char *name);
void (*unlink)(fuse_req_t req, struct dfuse_inode_entry *parent,
const char *name);
void (*setxattr)(fuse_req_t req, struct dfuse_inode_entry *inode,
Expand Down Expand Up @@ -486,6 +488,7 @@ struct dfuse_pool {
ACTION(UNLINK) \
ACTION(READDIR) \
ACTION(SYMLINK) \
ACTION(LINK) \
ACTION(READLINK) \
ACTION(OPENDIR) \
ACTION(SETXATTR) \
Expand Down Expand Up @@ -941,6 +944,15 @@ dfuse_loop(struct dfuse_info *dfuse_info);

#define DFUSE_REPLY_IOCTL(desc, req, arg) DFUSE_REPLY_IOCTL_SIZE(desc, req, &(arg), sizeof(arg))

/* A (parent, name) dentry. A file may have multiple hardlinks, all sharing one inode entry; the
* primary link is stored inline on the inode and any additional links are tracked on ie_dentries.
*/
struct dfuse_dentry {
fuse_ino_t dd_parent;
char dd_name[NAME_MAX + 1];
d_list_t dd_list;
};

/**
* Inode handle.
*
Expand Down Expand Up @@ -977,6 +989,12 @@ struct dfuse_inode_entry {
*/
fuse_ino_t ie_parent;

/** Additional hardlink dentries beyond the primary ie_parent/ie_name. */
d_list_t ie_dentries;

/** Protects ie_parent, ie_name and ie_dentries. */
pthread_spinlock_t ie_dentry_lock;

struct dfuse_cont *ie_dfs;

/** Hash table of inodes
Expand Down Expand Up @@ -1189,12 +1207,6 @@ ival_drop_inode(struct dfuse_inode_entry *inode);
int
ival_update_inode(struct dfuse_inode_entry *inode, double timeout);

/* Queue an on-demand dentry invalidation (parent/name) to be issued from the invalidation thread.
* ie_drop, if non-NULL, is a reference that is released after the invalidation has been issued.
*/
int
dfuse_mark_inval_entry(fuse_ino_t parent, const char *name, struct dfuse_inode_entry *ie_drop);

int
ival_init(struct dfuse_info *dfuse_info);

Expand Down Expand Up @@ -1250,6 +1262,53 @@ dfuse_ie_init(struct dfuse_info *dfuse_info, struct dfuse_inode_entry *ie);
void
dfuse_ie_close(struct dfuse_info *dfuse_info, struct dfuse_inode_entry *ie);

/* Track an additional hardlink name for a shared inode. */
int
dfuse_ie_dentry_add(struct dfuse_inode_entry *ie, fuse_ino_t parent, const char *name);

/* Drop one tracked name; promotes a secondary to primary if the primary was removed. */
void
dfuse_ie_dentry_remove(struct dfuse_inode_entry *ie, fuse_ino_t parent, const char *name);

/* Rename a tracked name. If the old name is unknown, release all tracked names into released and
* set the new name as the sole primary.
*/
void
dfuse_ie_dentry_replace(struct dfuse_inode_entry *ie, fuse_ino_t old_parent, const char *old_name,
fuse_ino_t new_parent, const char *new_name, struct dfuse_dentry *released);

/* Make (parent, name) the inode's sole tracked name, moving every other name into released. Used
* for a single-link file where all other cached names are stale.
*/
void
dfuse_ie_dentry_set_single(struct dfuse_inode_entry *ie, fuse_ino_t parent, const char *name,
struct dfuse_dentry *released);

/* Snapshot every tracked name into released, moving secondaries out of the inode. */
void
dfuse_ie_dentry_snapshot(struct dfuse_inode_entry *ie, struct dfuse_dentry *released);

/* Issue fuse_lowlevel_notify_inval_entry() for every name in released and free secondaries. Must
* only be called from the invalidation thread. Returns -EBADF if the session is dead.
*/
int
dfuse_ie_dentry_inval(struct dfuse_info *dfuse_info, struct dfuse_dentry *released);

/* Queue every name in released for invalidation on the invalidation thread, consuming released.
* ie_drop, if set, is released after the final name is invalidated.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be worth of it to mention that there is some actions which are always taken even in case of error.
For example removing the entries and calling dfuse_inode_decref()

*/
int
dfuse_queue_inval_dentries(struct dfuse_dentry *released, struct dfuse_inode_entry *ie_drop);

/* Invalidate cached data/attrs synchronously, then queue a delete on the invalidation thread for
* every name in released, skipping (exclude_parent, exclude_name) which the kernel already handled.
* Consumes released.
*/
void
dfuse_ie_inode_delete(struct dfuse_info *dfuse_info, struct dfuse_inode_entry *ie,
struct dfuse_dentry *released, fuse_ino_t exclude_parent,
const char *exclude_name);

/* ops/...c */

void
Expand Down Expand Up @@ -1312,6 +1371,9 @@ void
dfuse_cb_symlink(fuse_req_t, const char *, struct dfuse_inode_entry *,
const char *);

void
dfuse_cb_link(fuse_req_t, struct dfuse_inode_entry *, struct dfuse_inode_entry *, const char *);

void
dfuse_cb_setxattr(fuse_req_t, struct dfuse_inode_entry *, const char *,
const char *, size_t, int);
Expand Down Expand Up @@ -1358,6 +1420,13 @@ void
dfuse_oid_unlinked(struct dfuse_info *dfuse_info, fuse_req_t req, daos_obj_id_t *oid,
struct dfuse_inode_entry *parent, const char *name);

/* Handle removal of one hardlink where the file still exists (other links remain). The inode is
* left intact; only the fuse reply is issued.
*/
void
dfuse_hardlink_removed(struct dfuse_info *dfuse_info, fuse_req_t req, daos_obj_id_t *oid,
struct dfuse_inode_entry *parent, const char *name);

/* dfuse_cont.c */
void
dfuse_cont_lookup(fuse_req_t req, struct dfuse_inode_entry *parent,
Expand Down
Loading
Loading