Skip to content

Commit

Permalink
DAOS-14476 dfs: update root stbuf on lookup of root (#13597)
Browse files Browse the repository at this point in the history
- In order to avoid stale root stat data, update the root stbuf on lookup.
- add mtime/ctime proper querying for dfs_lookup()
- destroy the uns container after the link is remove since dfuse looks
  up the root if the container of being destroyed.

Required-githooks: true

Signed-off-by: Mohamad Chaarawi <mohamad.chaarawi@intel.com>
  • Loading branch information
mchaarawi committed Jan 22, 2024
1 parent fd618df commit 3ae8561
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 30 deletions.
92 changes: 72 additions & 20 deletions src/client/dfs/dfs.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* (C) Copyright 2018-2023 Intel Corporation.
* (C) Copyright 2018-2024 Intel Corporation.
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
Expand Down Expand Up @@ -3548,13 +3548,10 @@ lookup_rel_path(dfs_t *dfs, dfs_obj_t *root, const char *path, int flags,
lookup_rel_path_loop:

/*
* Open the directory object one level up.
* Since fetch_entry does not support ".",
* we can't support ".." as the last entry,
* nor can we support "../.." because we don't
* have parent.parent_oid and parent.mode.
* For now, represent this partial state with
* parent_fully_valid.
* Open the directory object one level up. Since fetch_entry does not support ".",
* we can't support ".." as the last entry, nor can we support "../.." because we
* don't have parent.parent_oid and parent.mode. For now, represent this partial
* state with parent_fully_valid.
*/
parent_fully_valid = true;
if (strcmp(token, "..") == 0) {
Expand Down Expand Up @@ -3632,15 +3629,23 @@ lookup_rel_path(dfs_t *dfs, dfs_obj_t *root, const char *path, int flags,
}

if (stbuf) {
daos_size_t size;
daos_array_stbuf_t array_stbuf = {0};

rc = daos_array_get_size(obj->oh, DAOS_TX_NONE, &size, NULL);
rc = daos_array_stat(obj->oh, DAOS_TX_NONE, &array_stbuf, NULL);
if (rc) {
daos_array_close(obj->oh, NULL);
D_GOTO(err_obj, rc = daos_der2errno(rc));
}
stbuf->st_size = size;

stbuf->st_size = array_stbuf.st_size;
stbuf->st_blocks = (stbuf->st_size + (1 << 9) - 1) >> 9;

rc = update_stbuf_times(entry, array_stbuf.st_max_epoch, stbuf,
NULL);
if (rc) {
daos_array_close(obj->oh, NULL);
D_GOTO(err_obj, rc);
}
}
break;
}
Expand Down Expand Up @@ -3741,31 +3746,78 @@ lookup_rel_path(dfs_t *dfs, dfs_obj_t *root, const char *path, int flags,
}

obj->d.chunk_size = entry.chunk_size;
obj->d.oclass = entry.oclass;
if (stbuf)
stbuf->st_size = sizeof(entry);

obj->d.oclass = entry.oclass;
oid_cp(&parent.oid, obj->oid);
oid_cp(&parent.parent_oid, obj->parent_oid);
parent.oh = obj->oh;
parent.mode = entry.mode;

if (stbuf) {
daos_epoch_t ep;

rc = daos_obj_query_max_epoch(obj->oh, DAOS_TX_NONE, &ep, NULL);
if (rc) {
daos_obj_close(obj->oh, NULL);
D_GOTO(err_obj, rc = daos_der2errno(rc));
}

rc = update_stbuf_times(entry, ep, stbuf, NULL);
if (rc) {
daos_obj_close(obj->oh, NULL);
D_GOTO(err_obj, rc = daos_der2errno(rc));
}
stbuf->st_size = sizeof(entry);
}
}

if (mode)
*mode = obj->mode;

if (stbuf) {
if (is_root) {
daos_epoch_t ep;

/** refresh possibly stale root stbuf */
rc = fetch_entry(dfs->layout_v, dfs->super_oh, DAOS_TX_NONE, "/", 1, false,
&exists, &entry, 0, NULL, NULL, NULL);
if (rc) {
D_ERROR("fetch_entry() failed: %d (%s)\n", rc, strerror(rc));
D_GOTO(err_obj, rc);
}

if (!exists || !S_ISDIR(entry.mode)) {
/** something really bad happened! */
D_ERROR("Root object corrupted!");
D_GOTO(err_obj, rc = EIO);
}

if (mode)
*mode = entry.mode;
dfs->root_stbuf.st_mode = entry.mode;
dfs->root_stbuf.st_uid = entry.uid;
dfs->root_stbuf.st_gid = entry.gid;

rc = daos_obj_query_max_epoch(dfs->root.oh, DAOS_TX_NONE, &ep, NULL);
if (rc)
D_GOTO(err_obj, rc = daos_der2errno(rc));

/** object was updated since creation */
rc = update_stbuf_times(entry, ep, &dfs->root_stbuf, NULL);
if (rc)
D_GOTO(err_obj, rc);
if (tspec_gt(dfs->root_stbuf.st_ctim, dfs->root_stbuf.st_mtim)) {
dfs->root_stbuf.st_atim.tv_sec = entry.ctime;
dfs->root_stbuf.st_atim.tv_nsec = entry.ctime_nano;
} else {
dfs->root_stbuf.st_atim.tv_sec = entry.mtime;
dfs->root_stbuf.st_atim.tv_nsec = entry.mtime_nano;
}
memcpy(stbuf, &dfs->root_stbuf, sizeof(struct stat));
} else {
stbuf->st_nlink = 1;
stbuf->st_mode = obj->mode;
stbuf->st_uid = entry.uid;
stbuf->st_gid = entry.gid;
stbuf->st_mtim.tv_sec = entry.mtime;
stbuf->st_mtim.tv_nsec = entry.mtime_nano;
stbuf->st_ctim.tv_sec = entry.ctime;
stbuf->st_ctim.tv_nsec = entry.ctime_nano;
stbuf->st_gid = entry.gid;
if (dfs->layout_v > 2) {
if (tspec_gt(stbuf->st_ctim, stbuf->st_mtim)) {
stbuf->st_atim.tv_sec = entry.ctime;
Expand Down
16 changes: 8 additions & 8 deletions src/client/dfs/duns.c
Original file line number Diff line number Diff line change
Expand Up @@ -1331,14 +1331,6 @@ duns_destroy_path(daos_handle_t poh, const char *path)
return rc;
}

/** Destroy the container */
rc = daos_cont_destroy(poh, dattr.da_cont, 1, NULL);
if (rc) {
D_ERROR("Failed to destroy container (%d)\n", rc);
/** recreate the link ? */
return daos_der2errno(rc);
}

if (dattr.da_type == DAOS_PROP_CO_LAYOUT_POSIX) {
#ifdef LUSTRE_INCLUDE
if (dattr.da_on_lustre)
Expand Down Expand Up @@ -1369,6 +1361,14 @@ duns_destroy_path(daos_handle_t poh, const char *path)
}
}

/** Destroy the container */
rc = daos_cont_destroy(poh, dattr.da_cont, 1, NULL);
if (rc) {
D_ERROR("Failed to destroy container (%d)\n", rc);
/** recreate the link ? */
return daos_der2errno(rc);
}

return 0;
}

Expand Down
34 changes: 32 additions & 2 deletions src/tests/suite/dfs_unit_test.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* (C) Copyright 2019-2023 Intel Corporation.
* (C) Copyright 2019-2024 Intel Corporation.
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
Expand Down Expand Up @@ -1344,15 +1344,45 @@ dfs_test_chown(void **state)
char *filename_file2 = "open_stat2";
mode_t create_mode = S_IWUSR | S_IRUSR;
int create_flags = O_RDWR | O_CREAT | O_EXCL;
struct timespec ctime_orig, mtime_orig;
mode_t orig_mode;
int rc;

if (arg->myrank != 0)
return;

rc = dfs_lookup(dfs_mt, "/", O_RDWR, &dir, NULL, &stbuf);
rc = dfs_lookup(dfs_mt, "/", O_RDWR, &dir, &orig_mode, &stbuf);
assert_int_equal(rc, 0);
assert_int_equal(stbuf.st_uid, geteuid());
assert_int_equal(stbuf.st_gid, getegid());
mtime_orig.tv_sec = stbuf.st_mtim.tv_sec;
mtime_orig.tv_nsec = stbuf.st_mtim.tv_nsec;
ctime_orig.tv_sec = stbuf.st_ctim.tv_sec;
ctime_orig.tv_nsec = stbuf.st_ctim.tv_nsec;

/** chown of root and see if visible */
print_message("Running chown tests on root object...\n");
memset(&stbuf, 0, sizeof(stbuf));
stbuf.st_uid = 3;
stbuf.st_gid = 4;
stbuf.st_mtim.tv_sec = mtime_orig.tv_sec + 10;
stbuf.st_mtim.tv_nsec = mtime_orig.tv_nsec;
stbuf.st_mode = orig_mode | S_IROTH | S_IWOTH | S_IXOTH;
rc = dfs_osetattr(dfs_mt, dir, &stbuf,
DFS_SET_ATTR_UID | DFS_SET_ATTR_GID | DFS_SET_ATTR_MTIME |
DFS_SET_ATTR_MODE);
assert_int_equal(rc, 0);
rc = dfs_release(dir);
assert_int_equal(rc, 0);

memset(&stbuf, 0, sizeof(stbuf));
rc = dfs_lookup(dfs_mt, "/", O_RDWR, &dir, NULL, &stbuf);
assert_int_equal(rc, 0);
assert_int_equal(stbuf.st_mode, orig_mode | S_IROTH | S_IWOTH | S_IXOTH);
assert_int_equal(stbuf.st_uid, 3);
assert_int_equal(stbuf.st_gid, 4);
assert_true(check_ts(ctime_orig, stbuf.st_ctim));
assert_int_equal(mtime_orig.tv_sec + 10, stbuf.st_mtim.tv_sec);
rc = dfs_release(dir);
assert_int_equal(rc, 0);

Expand Down
1 change: 1 addition & 0 deletions utils/node_local_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2588,6 +2588,7 @@ def test_uns_link(self):
print(os.listdir(path))
cmd = ['cont', 'destroy', '--path', path]
rc = run_daos_cmd(self.conf, cmd)
assert rc.returncode == 0

path = join(self.dfuse.dir, 'uns_link2')
cmd = ['cont', 'link', self.pool.id(), container2.id(), '--path', path]
Expand Down

0 comments on commit 3ae8561

Please sign in to comment.