Skip to content

Commit

Permalink
DAOS-14474,14219,14476,15049 dfs: dfs bug fixes (#13646)
Browse files Browse the repository at this point in the history
* DAOS-14474 dfs: remove unused --evict option from checker (#13616)

The dfs fs check command already allows evicting containers using the
--flags=evict option. the --evict option was added by mistake and does
not do anything today, so remove it.

* DAOS-14219 dfs: checker should not follow symlinks (#13625)

The DFS checker should mark the symlink oid and not dereference the
symlink value. the value can be invalid anyway and if a valid path in
the container, it would be reachable from the hardlink path.

* DAOS-14476 dfs: update root stbuf on lookup of root (#13597)

- 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.

* DAOS-15049 dfs: fix bug in setattr when mtime and size are being set (#13640)

- in dfs_osetattr(), if user sets both mtime and size, the hlc for the
  mtime is not being update on storage. To fix that, use the hlc
  reported from the array_stat and update that when updating the mtime in
  the entry.

Signed-off-by: Mohamad Chaarawi <mohamad.chaarawi@intel.com>
  • Loading branch information
mchaarawi authored Jan 26, 2024
1 parent e212dc2 commit e95ee32
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 64 deletions.
150 changes: 105 additions & 45 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 Expand Up @@ -5313,11 +5365,12 @@ dfs_osetattr(dfs_t *dfs, dfs_obj_t *obj, struct stat *stbuf, int flags)
bool set_size = false;
bool set_mtime = false;
bool set_ctime = false;
int i = 0;
size_t len;
int rc;
int i = 0, hlc_recx_idx = 0;
size_t len;
uint64_t obj_hlc = 0;
struct stat rstat = {};
daos_array_stbuf_t array_stbuf = {0};
int rc;

if (dfs == NULL || !dfs->mounted)
return EINVAL;
Expand Down Expand Up @@ -5414,6 +5467,10 @@ dfs_osetattr(dfs_t *dfs, dfs_obj_t *obj, struct stat *stbuf, int flags)
d_iov_set(&sg_iovs[i], &obj_hlc, sizeof(uint64_t));
recxs[i].rx_idx = HLC_IDX;
recxs[i].rx_nr = sizeof(uint64_t);
if (flags & DFS_SET_ATTR_SIZE) {
/** we need to update this again after the set size */
hlc_recx_idx = i;
}
i++;

set_mtime = true;
Expand Down Expand Up @@ -5463,38 +5520,41 @@ dfs_osetattr(dfs_t *dfs, dfs_obj_t *obj, struct stat *stbuf, int flags)
rstat.st_blocks = (stbuf->st_size + (1 << 9) - 1) >> 9;
rstat.st_size = stbuf->st_size;

/* mtime and ctime need to be updated too only if not set earlier */
if (!set_mtime || !set_ctime) {
daos_array_stbuf_t array_stbuf = {0};
/**
* if mtime is set, we need to to just update the hlc on the entry. if mtime and/or
* ctime were not set, we need to update the stat buf returned. both cases require
* an array stat for the hlc.
*/
/** TODO - need an array API to just stat the max epoch without size */
rc = daos_array_stat(obj->oh, th, &array_stbuf, NULL);
if (rc)
D_GOTO(out_obj, rc = daos_der2errno(rc));

/** TODO - need an array API to just stat the max epoch without size */
rc = daos_array_stat(obj->oh, th, &array_stbuf, NULL);
if (rc)
if (!set_mtime) {
rc = d_hlc2timespec(array_stbuf.st_max_epoch, &rstat.st_mtim);
if (rc) {
D_ERROR("d_hlc2timespec() failed " DF_RC "\n", DP_RC(rc));
D_GOTO(out_obj, rc = daos_der2errno(rc));

if (!set_mtime) {
rc = d_hlc2timespec(array_stbuf.st_max_epoch, &rstat.st_mtim);
if (rc) {
D_ERROR("d_hlc2timespec() failed "DF_RC"\n", DP_RC(rc));
D_GOTO(out_obj, rc = daos_der2errno(rc));
}
}
} else {
D_ASSERT(hlc_recx_idx > 0);
D_ASSERT(recxs[hlc_recx_idx].rx_idx == HLC_IDX);
d_iov_set(&sg_iovs[hlc_recx_idx], &array_stbuf.st_max_epoch,
sizeof(uint64_t));
}

if (!set_ctime) {
rc = d_hlc2timespec(array_stbuf.st_max_epoch, &rstat.st_ctim);
if (rc) {
D_ERROR("d_hlc2timespec() failed "DF_RC"\n", DP_RC(rc));
D_GOTO(out_obj, rc = daos_der2errno(rc));
}
if (!set_ctime) {
rc = d_hlc2timespec(array_stbuf.st_max_epoch, &rstat.st_ctim);
if (rc) {
D_ERROR("d_hlc2timespec() failed " DF_RC "\n", DP_RC(rc));
D_GOTO(out_obj, rc = daos_der2errno(rc));
}
}
}

iod.iod_nr = i;

if (i == 0)
D_GOTO(out_stat, rc = 0);

sgl.sg_nr = i;
sgl.sg_nr_out = 0;
sgl.sg_iovs = &sg_iovs[0];
Expand Down Expand Up @@ -6591,7 +6651,7 @@ oit_mark_cb(dfs_t *dfs, dfs_obj_t *parent, const char name[], void *args)
}

/** open the entry name and get the oid */
rc = dfs_lookup_rel(dfs, parent, name, O_RDONLY, &obj, NULL, NULL);
rc = dfs_lookup_rel(dfs, parent, name, O_RDONLY | O_NOFOLLOW, &obj, NULL, NULL);
if (rc) {
D_ERROR("dfs_lookup_rel() of %s failed: %d\n", name, rc);
return rc;
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
1 change: 0 additions & 1 deletion src/control/cmd/daos/filesystem.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,6 @@ type fsCheckCmd struct {

FsckFlags FsCheckFlag `long:"flags" short:"f" description:"comma-separated flags: print, remove, relink, verify, evict"`
DirName string `long:"dir-name" short:"n" description:"directory name under lost+found to store leaked oids (a timestamp dir would be created if this is not specified)"`
Evict bool `long:"evict" short:"e" description:"evict all open handles on the container"`
}

func (cmd *fsCheckCmd) Execute(_ []string) error {
Expand Down
Loading

0 comments on commit e95ee32

Please sign in to comment.