Skip to content

Commit

Permalink
fuse: add "expire only" mode to FUSE_NOTIFY_INVAL_ENTRY
Browse files Browse the repository at this point in the history
Add a flag to entry expiration that lets the filesystem expire a dentry
without kicking it out from the cache immediately.

This makes a difference for overmounted dentries, where plain invalidation
would detach all submounts before dropping the dentry from the cache.  If
only expiry is set on the dentry, then any overmounts are left alone and
until ->d_revalidate() is called.

Note: ->d_revalidate() is not called for the case of following a submount,
so invalidation will only be triggered for the non-overmounted case.  The
dentry could also be mounted in a different mount instance, in which case
any submounts will still be detached.

Suggested-by: Jakob Blomer <jblomer@cern.ch>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
  • Loading branch information
Miklos Szeredi committed Nov 23, 2022
1 parent a1db2f7 commit 4f8d370
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 7 deletions.
4 changes: 2 additions & 2 deletions fs/fuse/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1498,7 +1498,7 @@ static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size,
buf[outarg.namelen] = 0;

down_read(&fc->killsb);
err = fuse_reverse_inval_entry(fc, outarg.parent, 0, &name);
err = fuse_reverse_inval_entry(fc, outarg.parent, 0, &name, outarg.flags);
up_read(&fc->killsb);
kfree(buf);
return err;
Expand Down Expand Up @@ -1546,7 +1546,7 @@ static int fuse_notify_delete(struct fuse_conn *fc, unsigned int size,
buf[outarg.namelen] = 0;

down_read(&fc->killsb);
err = fuse_reverse_inval_entry(fc, outarg.parent, outarg.child, &name);
err = fuse_reverse_inval_entry(fc, outarg.parent, outarg.child, &name, 0);
up_read(&fc->killsb);
kfree(buf);
return err;
Expand Down
6 changes: 4 additions & 2 deletions fs/fuse/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -1170,7 +1170,7 @@ int fuse_update_attributes(struct inode *inode, struct file *file, u32 mask)
}

int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid,
u64 child_nodeid, struct qstr *name)
u64 child_nodeid, struct qstr *name, u32 flags)
{
int err = -ENOTDIR;
struct inode *parent;
Expand All @@ -1197,7 +1197,9 @@ int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid,
goto unlock;

fuse_dir_changed(parent);
fuse_invalidate_entry(entry);
if (!(flags & FUSE_EXPIRE_ONLY))
d_invalidate(entry);
fuse_invalidate_entry_cache(entry);

if (child_nodeid != 0 && d_really_is_positive(entry)) {
inode_lock(d_inode(entry));
Expand Down
2 changes: 1 addition & 1 deletion fs/fuse/fuse_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -1220,7 +1220,7 @@ int fuse_reverse_inval_inode(struct fuse_conn *fc, u64 nodeid,
* then the dentry is unhashed (d_delete()).
*/
int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid,
u64 child_nodeid, struct qstr *name);
u64 child_nodeid, struct qstr *name, u32 flags);

int fuse_do_open(struct fuse_mount *fm, u64 nodeid, struct file *file,
bool isdir);
Expand Down
13 changes: 11 additions & 2 deletions include/uapi/linux/fuse.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,9 @@
*
* 7.37
* - add FUSE_TMPFILE
*
* 7.38
* - add FUSE_EXPIRE_ONLY flag to fuse_notify_inval_entry
*/

#ifndef _LINUX_FUSE_H
Expand Down Expand Up @@ -232,7 +235,7 @@
#define FUSE_KERNEL_VERSION 7

/** Minor version number of this interface */
#define FUSE_KERNEL_MINOR_VERSION 37
#define FUSE_KERNEL_MINOR_VERSION 38

/** The node ID of the root inode */
#define FUSE_ROOT_ID 1
Expand Down Expand Up @@ -491,6 +494,12 @@ struct fuse_file_lock {
*/
#define FUSE_SETXATTR_ACL_KILL_SGID (1 << 0)

/**
* notify_inval_entry flags
* FUSE_EXPIRE_ONLY
*/
#define FUSE_EXPIRE_ONLY (1 << 0)

enum fuse_opcode {
FUSE_LOOKUP = 1,
FUSE_FORGET = 2, /* no reply */
Expand Down Expand Up @@ -919,7 +928,7 @@ struct fuse_notify_inval_inode_out {
struct fuse_notify_inval_entry_out {
uint64_t parent;
uint32_t namelen;
uint32_t padding;
uint32_t flags;
};

struct fuse_notify_delete_out {
Expand Down

0 comments on commit 4f8d370

Please sign in to comment.