@@ -27,40 +27,199 @@ module_param(allow_sys_admin_access, bool, 0644);
2727MODULE_PARM_DESC (allow_sys_admin_access ,
2828 "Allow users with CAP_SYS_ADMIN in initial userns to bypass allow_other access check" );
2929
30+ struct dentry_bucket {
31+ struct rb_root tree ;
32+ spinlock_t lock ;
33+ };
34+
35+ #define HASH_BITS 5
36+ #define HASH_SIZE (1 << HASH_BITS)
37+ static struct dentry_bucket dentry_hash [HASH_SIZE ];
38+ struct delayed_work dentry_tree_work ;
39+
40+ /* Minimum invalidation work queue frequency */
41+ #define FUSE_DENTRY_INVAL_FREQ_MIN 5
42+
43+ unsigned __read_mostly inval_wq ;
44+ static int inval_wq_set (const char * val , const struct kernel_param * kp )
45+ {
46+ unsigned int num ;
47+ unsigned int old = inval_wq ;
48+ int ret ;
49+
50+ if (!val )
51+ return - EINVAL ;
52+
53+ ret = kstrtouint (val , 0 , & num );
54+ if (ret )
55+ return ret ;
56+
57+ if ((num < FUSE_DENTRY_INVAL_FREQ_MIN ) && (num != 0 ))
58+ return - EINVAL ;
59+
60+ /* This should prevent overflow in secs_to_jiffies() */
61+ if (num > USHRT_MAX )
62+ return - EINVAL ;
63+
64+ * ((unsigned int * )kp -> arg ) = num ;
65+
66+ if (num && !old )
67+ schedule_delayed_work (& dentry_tree_work ,
68+ secs_to_jiffies (num ));
69+ else if (!num && old )
70+ cancel_delayed_work_sync (& dentry_tree_work );
71+
72+ return 0 ;
73+ }
74+ static const struct kernel_param_ops inval_wq_ops = {
75+ .set = inval_wq_set ,
76+ .get = param_get_uint ,
77+ };
78+ module_param_cb (inval_wq , & inval_wq_ops , & inval_wq , 0644 );
79+ __MODULE_PARM_TYPE (inval_wq , "uint" );
80+ MODULE_PARM_DESC (inval_wq ,
81+ "Dentries invalidation work queue period in secs (>= "
82+ __stringify (FUSE_DENTRY_INVAL_FREQ_MIN ) ")." );
83+
84+ static inline struct dentry_bucket * get_dentry_bucket (struct dentry * dentry )
85+ {
86+ int i = hash_ptr (dentry , HASH_BITS );
87+
88+ return & dentry_hash [i ];
89+ }
90+
3091static void fuse_advise_use_readdirplus (struct inode * dir )
3192{
3293 struct fuse_inode * fi = get_fuse_inode (dir );
3394
3495 set_bit (FUSE_I_ADVISE_RDPLUS , & fi -> state );
3596}
3697
37- #if BITS_PER_LONG >= 64
38- static inline void __fuse_dentry_settime (struct dentry * entry , u64 time )
98+ struct fuse_dentry {
99+ u64 time ;
100+ union {
101+ struct rcu_head rcu ;
102+ struct rb_node node ;
103+ };
104+ struct dentry * dentry ;
105+ };
106+
107+ static void __fuse_dentry_tree_del_node (struct fuse_dentry * fd ,
108+ struct dentry_bucket * bucket )
39109{
40- entry -> d_fsdata = (void * ) time ;
110+ if (!RB_EMPTY_NODE (& fd -> node )) {
111+ rb_erase (& fd -> node , & bucket -> tree );
112+ RB_CLEAR_NODE (& fd -> node );
113+ }
41114}
42115
43- static inline u64 fuse_dentry_time ( const struct dentry * entry )
116+ static void fuse_dentry_tree_del_node ( struct dentry * dentry )
44117{
45- return (u64 )entry -> d_fsdata ;
118+ struct fuse_dentry * fd = dentry -> d_fsdata ;
119+ struct dentry_bucket * bucket = get_dentry_bucket (dentry );
120+
121+ spin_lock (& bucket -> lock );
122+ __fuse_dentry_tree_del_node (fd , bucket );
123+ spin_unlock (& bucket -> lock );
46124}
47125
48- #else
49- union fuse_dentry {
50- u64 time ;
51- struct rcu_head rcu ;
52- };
126+ static void fuse_dentry_tree_add_node (struct dentry * dentry )
127+ {
128+ struct fuse_dentry * fd = dentry -> d_fsdata ;
129+ struct dentry_bucket * bucket ;
130+ struct fuse_dentry * cur ;
131+ struct rb_node * * p , * parent = NULL ;
132+
133+ if (!inval_wq )
134+ return ;
135+
136+ bucket = get_dentry_bucket (dentry );
137+
138+ spin_lock (& bucket -> lock );
139+
140+ __fuse_dentry_tree_del_node (fd , bucket );
141+
142+ p = & bucket -> tree .rb_node ;
143+ while (* p ) {
144+ parent = * p ;
145+ cur = rb_entry (* p , struct fuse_dentry , node );
146+ if (fd -> time < cur -> time )
147+ p = & (* p )-> rb_left ;
148+ else
149+ p = & (* p )-> rb_right ;
150+ }
151+ rb_link_node (& fd -> node , parent , p );
152+ rb_insert_color (& fd -> node , & bucket -> tree );
153+ spin_unlock (& bucket -> lock );
154+ }
155+
156+ /*
157+ * work queue which, when enabled, will periodically check for expired dentries
158+ * in the dentries tree.
159+ */
160+ static void fuse_dentry_tree_work (struct work_struct * work )
161+ {
162+ LIST_HEAD (dispose );
163+ struct fuse_dentry * fd ;
164+ struct rb_node * node ;
165+ int i ;
166+
167+ for (i = 0 ; i < HASH_SIZE ; i ++ ) {
168+ spin_lock (& dentry_hash [i ].lock );
169+ node = rb_first (& dentry_hash [i ].tree );
170+ while (node ) {
171+ fd = rb_entry (node , struct fuse_dentry , node );
172+ if (time_after64 (get_jiffies_64 (), fd -> time )) {
173+ rb_erase (& fd -> node , & dentry_hash [i ].tree );
174+ RB_CLEAR_NODE (& fd -> node );
175+ spin_unlock (& dentry_hash [i ].lock );
176+ d_dispose_if_unused (fd -> dentry , & dispose );
177+ cond_resched ();
178+ spin_lock (& dentry_hash [i ].lock );
179+ } else
180+ break ;
181+ node = rb_first (& dentry_hash [i ].tree );
182+ }
183+ spin_unlock (& dentry_hash [i ].lock );
184+ shrink_dentry_list (& dispose );
185+ }
186+
187+ if (inval_wq )
188+ schedule_delayed_work (& dentry_tree_work ,
189+ secs_to_jiffies (inval_wq ));
190+ }
191+
192+ void fuse_dentry_tree_init (void )
193+ {
194+ int i ;
195+
196+ for (i = 0 ; i < HASH_SIZE ; i ++ ) {
197+ spin_lock_init (& dentry_hash [i ].lock );
198+ dentry_hash [i ].tree = RB_ROOT ;
199+ }
200+ INIT_DELAYED_WORK (& dentry_tree_work , fuse_dentry_tree_work );
201+ }
202+
203+ void fuse_dentry_tree_cleanup (void )
204+ {
205+ int i ;
206+
207+ inval_wq = 0 ;
208+ cancel_delayed_work_sync (& dentry_tree_work );
209+
210+ for (i = 0 ; i < HASH_SIZE ; i ++ )
211+ WARN_ON_ONCE (!RB_EMPTY_ROOT (& dentry_hash [i ].tree ));
212+ }
53213
54214static inline void __fuse_dentry_settime (struct dentry * dentry , u64 time )
55215{
56- ((union fuse_dentry * ) dentry -> d_fsdata )-> time = time ;
216+ ((struct fuse_dentry * ) dentry -> d_fsdata )-> time = time ;
57217}
58218
59219static inline u64 fuse_dentry_time (const struct dentry * entry )
60220{
61- return ((union fuse_dentry * ) entry -> d_fsdata )-> time ;
221+ return ((struct fuse_dentry * ) entry -> d_fsdata )-> time ;
62222}
63- #endif
64223
65224static void fuse_dentry_settime (struct dentry * dentry , u64 time )
66225{
@@ -81,6 +240,7 @@ static void fuse_dentry_settime(struct dentry *dentry, u64 time)
81240 }
82241
83242 __fuse_dentry_settime (dentry , time );
243+ fuse_dentry_tree_add_node (dentry );
84244}
85245
86246/*
@@ -283,21 +443,36 @@ static int fuse_dentry_revalidate(struct inode *dir, const struct qstr *name,
283443 goto out ;
284444}
285445
286- #if BITS_PER_LONG < 64
287446static int fuse_dentry_init (struct dentry * dentry )
288447{
289- dentry -> d_fsdata = kzalloc (sizeof (union fuse_dentry ),
290- GFP_KERNEL_ACCOUNT | __GFP_RECLAIMABLE );
448+ struct fuse_dentry * fd ;
291449
292- return dentry -> d_fsdata ? 0 : - ENOMEM ;
450+ fd = kzalloc (sizeof (struct fuse_dentry ),
451+ GFP_KERNEL_ACCOUNT | __GFP_RECLAIMABLE );
452+ if (!fd )
453+ return - ENOMEM ;
454+
455+ fd -> dentry = dentry ;
456+ RB_CLEAR_NODE (& fd -> node );
457+ dentry -> d_fsdata = fd ;
458+
459+ return 0 ;
460+ }
461+
462+ static void fuse_dentry_prune (struct dentry * dentry )
463+ {
464+ struct fuse_dentry * fd = dentry -> d_fsdata ;
465+
466+ if (!RB_EMPTY_NODE (& fd -> node ))
467+ fuse_dentry_tree_del_node (dentry );
293468}
469+
294470static void fuse_dentry_release (struct dentry * dentry )
295471{
296- union fuse_dentry * fd = dentry -> d_fsdata ;
472+ struct fuse_dentry * fd = dentry -> d_fsdata ;
297473
298474 kfree_rcu (fd , rcu );
299475}
300- #endif
301476
302477static int fuse_dentry_delete (const struct dentry * dentry )
303478{
@@ -331,10 +506,9 @@ static struct vfsmount *fuse_dentry_automount(struct path *path)
331506const struct dentry_operations fuse_dentry_operations = {
332507 .d_revalidate = fuse_dentry_revalidate ,
333508 .d_delete = fuse_dentry_delete ,
334- #if BITS_PER_LONG < 64
335509 .d_init = fuse_dentry_init ,
510+ .d_prune = fuse_dentry_prune ,
336511 .d_release = fuse_dentry_release ,
337- #endif
338512 .d_automount = fuse_dentry_automount ,
339513};
340514
0 commit comments