Skip to content

Commit

Permalink
DAOS-12751 tool: Add a daos filesystem evict command.
Browse files Browse the repository at this point in the history
Add a command to tell dfuse and the kernel to evict a
path in dfuse.  This is implemented via a ioctl that
sets a flag on the file handle, when the file is then
closed the kernel is then told the dentry for the file
is no longer valid which should cause the kernel to
forget the entry and any contents if the entry is
a directory.

Required-githooks: true

Signed-off-by: Ashley Pittman <ashley.m.pittman@intel.com>
  • Loading branch information
ashleypittman committed Jun 9, 2023
1 parent 15d9951 commit 5fdc6a7
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 8 deletions.
2 changes: 2 additions & 0 deletions src/client/dfuse/dfuse.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ struct dfuse_obj_hdl {
bool doh_kreaddir_started;
/* Set to true if readdir calls reach EOF made on this handle */
bool doh_kreaddir_finished;

bool doh_evict_on_close;
};

/* Readdir support.
Expand Down
6 changes: 6 additions & 0 deletions src/client/dfuse/ops/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,12 @@ void dfuse_cb_ioctl(fuse_req_t req, fuse_ino_t ino, unsigned int cmd, void *arg,

DFUSE_TRA_DEBUG(oh, "ioctl cmd=%#x", cmd);

if (cmd == DFUSE_IOCTL_DFUSE_EVICT) {
oh->doh_evict_on_close = true;
DFUSE_REPLY_IOCTL_SIZE(oh, req, NULL, 0);
return;
}

if (cmd == DFUSE_IOCTL_IL) {
if (out_bufsz < sizeof(struct dfuse_il_reply))
D_GOTO(out_err, rc = EIO);
Expand Down
19 changes: 15 additions & 4 deletions src/client/dfuse/ops/open.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ dfuse_cb_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
{
struct dfuse_projection_info *fs_handle = fuse_req_userdata(req);
struct dfuse_inode_entry *ie;
d_list_t *rlink;
d_list_t *rlink;
struct dfuse_obj_hdl *oh = NULL;
struct fuse_file_info fi_out = {0};
int rc;
Expand Down Expand Up @@ -99,9 +99,10 @@ dfuse_cb_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
void
dfuse_cb_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
{
struct dfuse_obj_hdl *oh = (struct dfuse_obj_hdl *)fi->fh;
int rc;
uint32_t il_calls;
struct dfuse_projection_info *fs_handle = fuse_req_userdata(req);
struct dfuse_obj_hdl *oh = (struct dfuse_obj_hdl *)fi->fh;
int rc;
uint32_t il_calls;

/* Perform the opposite of what the ioctl call does, always change the open handle count
* but the inode only tracks number of open handles with non-zero ioctl counts
Expand Down Expand Up @@ -152,5 +153,15 @@ dfuse_cb_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
DFUSE_REPLY_ZERO(oh, req);
else
DFUSE_REPLY_ERR_RAW(oh, req, rc);

if (oh->doh_evict_on_close) {
rc = fuse_lowlevel_notify_inval_entry(fs_handle->dpi_info->di_session,
oh->doh_ie->ie_parent, oh->doh_ie->ie_name,
strnlen(oh->doh_ie->ie_name, NAME_MAX));

if (rc != 0)
DFUSE_TRA_ERROR(oh->doh_ie, "inval_entry() returned: %d (%s)", rc,
strerror(-rc));
}
D_FREE(oh);
}
25 changes: 25 additions & 0 deletions src/control/cmd/daos/filesystem.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type fsCmd struct {
ResetAttr fsResetAttrCmd `command:"reset-attr" description:"reset fs attributes"`
ResetChunkSize fsResetChunkSizeCmd `command:"reset-chunk-size" description:"reset fs chunk size"`
ResetObjClass fsResetOclassCmd `command:"reset-oclass" description:"reset fs obj class"`
DfuseEvict fsDfuseEvictCmd `command:"evict" description:"Evict object from dfuse"`
}

type fsCopyCmd struct {
Expand Down Expand Up @@ -428,3 +429,27 @@ func (cmd *fsFixRootCmd) Execute(_ []string) error {

return nil
}

type fsDfuseEvictCmd struct {
daosCmd

Path string `long:"path" description:"Path to evict from dfuse" required:"1"`
}

func (cmd *fsDfuseEvictCmd) Execute(_ []string) error {
ap, deallocCmdArgs, err := allocCmdArgs(cmd.Logger)
if err != nil {
return err
}

ap.path = C.CString(cmd.Path)
defer freeString(ap.path)
defer deallocCmdArgs()

rc := C.dfuse_evict(ap)
if err := daosError(rc); err != nil {
return errors.Wrapf(err, "failed to evict %s", cmd.Path)
}

return nil
}
8 changes: 4 additions & 4 deletions src/include/dfuse_ioctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@

#define DFUSE_IOCTL_REPLY_CORE (DFUSE_IOCTL_REPLY_BASE)

/* (DFUSE_IOCTL_REPLY_BASE + 1) is reserved by an older version of
* IOCTL_REPLY_SIZE
*/
/* (DFUSE_IOCTL_REPLY_BASE + 1) is reserved by an older version of IOCTL_REPLY_SIZE */

#define DFUSE_IOCTL_REPLY_POH (DFUSE_IOCTL_REPLY_BASE + 2)
#define DFUSE_IOCTL_REPLY_COH (DFUSE_IOCTL_REPLY_BASE + 3)
Expand All @@ -26,8 +24,8 @@
#define DFUSE_IOCTL_REPLY_SIZE (DFUSE_IOCTL_REPLY_BASE + 6)
#define DFUSE_IOCTL_REPLY_DSIZE (DFUSE_IOCTL_REPLY_BASE + 7)
#define DFUSE_IOCTL_REPLY_PFILE (DFUSE_IOCTL_REPLY_BASE + 8)

#define DFUSE_IOCTL_R_DFUSE_USER (DFUSE_IOCTL_REPLY_BASE + 9)
#define DFUSE_IOCTL_EVICT_NR (DFUSE_IOCTL_REPLY_BASE + 10)

/** Metadada caching is enabled for this file */
#define DFUSE_IOCTL_FLAGS_MCACHE (0x1)
Expand Down Expand Up @@ -76,4 +74,6 @@ struct dfuse_user_reply {
#define DFUSE_IOCTL_DFUSE_USER \
((int)_IOR(DFUSE_IOCTL_TYPE, DFUSE_IOCTL_R_DFUSE_USER, struct dfuse_user_reply))

#define DFUSE_IOCTL_DFUSE_EVICT ((int)_IO(DFUSE_IOCTL_TYPE, DFUSE_IOCTL_EVICT_NR))

#endif /* __DFUSE_IOCTL_H__ */
35 changes: 35 additions & 0 deletions src/utils/daos_hdlr.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <sys/xattr.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <daos.h>
Expand All @@ -40,6 +41,8 @@

#include "daos_hdlr.h"

#include "dfuse_ioctl.h"

struct file_dfs {
enum {POSIX, DAOS} type;
int fd;
Expand Down Expand Up @@ -2423,3 +2426,35 @@ cont_clone_hdlr(struct cmd_args_s *ap)
}
return rc;
}

int
dfuse_evict(struct cmd_args_s *ap)
{
struct stat buf;
int rc;
int fd;

fd = open(ap->path, O_NOFOLLOW, O_RDONLY);
if (fd < 0) {
rc = errno;
DH_PERROR_SYS(ap, rc, "Failed to open path");
return daos_errno2der(rc);
}

rc = fstat(fd, &buf);
if (rc < 0) {
rc = errno;
DH_PERROR_SYS(ap, rc, "Failed to stat file");
return daos_errno2der(rc);
}

rc = ioctl(fd, DFUSE_IOCTL_DFUSE_EVICT);
if (rc < 0) {
rc = errno;
DH_PERROR_SYS(ap, rc, "ioctl failed");
return daos_errno2der(rc);
}

close(fd);
return -DER_SUCCESS;
}
4 changes: 4 additions & 0 deletions src/utils/daos_hdlr.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,10 @@ int fs_relink_root_hdlr(struct cmd_args_s *ap);
int cont_check_hdlr(struct cmd_args_s *ap);
int cont_clone_hdlr(struct cmd_args_s *ap);

/* Dfuse operations */
int
dfuse_evict(struct cmd_args_s *ap);

/* TODO implement the following container op functions
* all with signatures similar to this:
* int cont_FN_hdlr(struct cmd_args_s *ap)
Expand Down
12 changes: 12 additions & 0 deletions utils/node_local_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2475,6 +2475,18 @@ def test_xattr(self):
for (key, value) in xattr.get_all(fd):
print(f'xattr is {key}:{value}')

@needs_dfuse
def test_evict(self):
"""Evict a file from dfuse"""
new_file = join(self.dfuse.dir, 'e_file')
with open(new_file, 'w'):
pass

rc = run_daos_cmd(self.conf, ['filesystem', 'evict', '--path', new_file])
print(rc)
assert rc.returncode == 0, rc
time.sleep(5)

@needs_dfuse
def test_list_xattr(self):
"""Perform tests with listing extended attributes.
Expand Down

0 comments on commit 5fdc6a7

Please sign in to comment.