Skip to content
Merged
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: 2 additions & 0 deletions fs/fuse/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -3497,6 +3497,8 @@ static int fuse_get_page_mkwrite_lock(struct file *file, loff_t offset, size_t l
fuse_abort_conn(fc);
err = -EINVAL;
}
if (!err && fc->dlm)
fuse_dlm_attr_timeout(get_fuse_inode(inode));
return err;
}

Expand Down
2 changes: 2 additions & 0 deletions fs/fuse/fuse_dlm_cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,8 @@ int fuse_get_dlm_lock(struct file *file, loff_t offset,
if (err)
return err;

fuse_dlm_attr_timeout(fi);

if (inarg.start < outarg.start || inarg.end > outarg.end) {
/* fuse server is seriously broken */
pr_warn("fuse: dlm lock request for %llu:%llu returned %llu:%llu bytes\n",
Expand Down
9 changes: 9 additions & 0 deletions fs/fuse/fuse_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,12 @@ enum {
* See fuse_reverse_inval_inode()/fuse_file_io_open().
*/
FUSE_I_FORCE_DIO,
/*
* A DLM lock was taken on this inode and no attribute reply has
* arrived since: i_time is bounded to dlm_attr_timeout seconds from
* the lock, see fuse_dlm_attr_timeout().
*/
FUSE_I_DLM_LOCKED,
};

struct fuse_conn;
Expand Down Expand Up @@ -1633,6 +1639,9 @@ struct inode *fuse_ilookup(struct fuse_conn *fc, u64 nodeid,
int fuse_reverse_inval_inode(struct fuse_conn *fc, u64 nodeid,
loff_t offset, loff_t len);

/* A DLM lock was taken on @fi: bound its attribute timeout until the next reply */
void fuse_dlm_attr_timeout(struct fuse_inode *fi);

/**
* File-system tells the kernel to invalidate parent attributes and
* the dentry matching parent/name.
Expand Down
36 changes: 36 additions & 0 deletions fs/fuse/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,39 @@ module_param(enable_notify_dio, bool, 0644);
MODULE_PARM_DESC(enable_notify_dio,
"Latch a contended inode to direct IO on an invalidation notify storm");

/*
* Attribute timeout of an inode once a DLM lock was taken on it, in
* seconds: i_time is bounded to it until the next attribute reply from
* the server, so a GETATTR goes out at most this long after the lock.
* 0 leaves the server's timeout alone.
*/
static unsigned int __read_mostly dlm_attr_timeout = 30;
module_param(dlm_attr_timeout, uint, 0644);
MODULE_PARM_DESC(dlm_attr_timeout,
"Seconds until the attributes of an inode a DLM lock was taken on are fetched again (0 = server's timeout)");

void fuse_dlm_attr_timeout(struct fuse_inode *fi)
{
struct fuse_conn *fc = get_fuse_conn(&fi->inode);
unsigned int timeout = READ_ONCE(dlm_attr_timeout);
u64 valid;

if (!timeout)
return;
valid = get_jiffies_64() + secs_to_jiffies(timeout);

spin_lock(&fi->lock);
/*
* Only a reply to a request sent after the lock may end the bound:
* one to an earlier request is discarded by fuse_change_attributes_i().
*/
if (!test_and_set_bit(FUSE_I_DLM_LOCKED, &fi->state))
fi->attr_version = atomic64_inc_return(&fc->attr_version);
if (time_after64(fi->i_time, valid))
fi->i_time = valid;
spin_unlock(&fi->lock);
}

static struct kmem_cache *fuse_inode_cachep;
struct list_head fuse_conn_list;
DEFINE_MUTEX(fuse_mutex);
Expand Down Expand Up @@ -402,6 +435,9 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,

lockdep_assert_held(&fi->lock);

/* The first attribute reply after a DLM lock ends the bounded timeout */
clear_bit(FUSE_I_DLM_LOCKED, &fi->state);

if (sx) {
return fuse_change_attributes_common_sx(inode, attr, sx,
attr_valid, cache_mask,
Expand Down
Loading