Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fuse: new work queue to invalidate dentries from old epochs

With the infrastructure introduced to periodically invalidate expired
dentries, it is now possible to add an extra work queue to invalidate
dentries when an epoch is incremented. This work queue will only be
triggered when the 'inval_wq' parameter is set.

Signed-off-by: Luis Henriques <luis@igalia.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>

authored by

Luis Henriques and committed by
Miklos Szeredi
64becd22 ab84ad59

+31 -3
+4 -3
fs/fuse/dev.c
··· 2041 2041 2042 2042 /* 2043 2043 * Increments the fuse connection epoch. This will result of dentries from 2044 - * previous epochs to be invalidated. 2045 - * 2046 - * XXX optimization: add call to shrink_dcache_sb()? 2044 + * previous epochs to be invalidated. Additionally, if inval_wq is set, a work 2045 + * queue is scheduled to trigger the invalidation. 2047 2046 */ 2048 2047 static int fuse_notify_inc_epoch(struct fuse_conn *fc) 2049 2048 { 2050 2049 atomic_inc(&fc->epoch); 2050 + if (inval_wq) 2051 + schedule_work(&fc->epoch_work); 2051 2052 2052 2053 return 0; 2053 2054 }
+21
fs/fuse/dir.c
··· 189 189 secs_to_jiffies(inval_wq)); 190 190 } 191 191 192 + void fuse_epoch_work(struct work_struct *work) 193 + { 194 + struct fuse_conn *fc = container_of(work, struct fuse_conn, 195 + epoch_work); 196 + struct fuse_mount *fm; 197 + struct inode *inode; 198 + 199 + down_read(&fc->killsb); 200 + 201 + inode = fuse_ilookup(fc, FUSE_ROOT_ID, &fm); 202 + iput(inode); 203 + 204 + if (fm) { 205 + /* Remove all possible active references to cached inodes */ 206 + shrink_dcache_sb(fm->sb); 207 + } else 208 + pr_warn("Failed to get root inode"); 209 + 210 + up_read(&fc->killsb); 211 + } 212 + 192 213 void fuse_dentry_tree_init(void) 193 214 { 194 215 int i;
+4
fs/fuse/fuse_i.h
··· 649 649 /** Current epoch for up-to-date dentries */ 650 650 atomic_t epoch; 651 651 652 + struct work_struct epoch_work; 653 + 652 654 struct rcu_head rcu; 653 655 654 656 /** The user id for this mount */ ··· 1288 1286 1289 1287 void fuse_dentry_tree_init(void); 1290 1288 void fuse_dentry_tree_cleanup(void); 1289 + 1290 + void fuse_epoch_work(struct work_struct *work); 1291 1291 1292 1292 /** 1293 1293 * Invalidate inode attributes
+2
fs/fuse/inode.c
··· 977 977 refcount_set(&fc->count, 1); 978 978 atomic_set(&fc->dev_count, 1); 979 979 atomic_set(&fc->epoch, 1); 980 + INIT_WORK(&fc->epoch_work, fuse_epoch_work); 980 981 init_waitqueue_head(&fc->blocked_waitq); 981 982 fuse_iqueue_init(&fc->iq, fiq_ops, fiq_priv); 982 983 INIT_LIST_HEAD(&fc->bg_queue); ··· 1030 1029 fuse_dax_conn_free(fc); 1031 1030 if (fc->timeout.req_timeout) 1032 1031 cancel_delayed_work_sync(&fc->timeout.work); 1032 + cancel_work_sync(&fc->epoch_work); 1033 1033 if (fiq->ops->release) 1034 1034 fiq->ops->release(fiq); 1035 1035 put_pid_ns(fc->pid_ns);