@@ -154,20 +154,23 @@ static void fsnotify_put_inode_ref(struct inode *inode)
154
154
iput (inode );
155
155
}
156
156
157
- static void fsnotify_get_sb_watchers (struct fsnotify_mark_connector * conn )
157
+ /*
158
+ * Grab or drop watched objects reference depending on whether the connector
159
+ * is attached and has any marks attached.
160
+ */
161
+ static void fsnotify_update_sb_watchers (struct super_block * sb ,
162
+ struct fsnotify_mark_connector * conn )
158
163
{
159
- struct super_block * sb = fsnotify_connector_sb (conn );
164
+ bool is_watched = conn -> flags & FSNOTIFY_CONN_FLAG_IS_WATCHED ;
165
+ bool has_marks = conn -> obj && !hlist_empty (& conn -> list );
160
166
161
- if (sb )
167
+ if (has_marks && !is_watched ) {
168
+ conn -> flags |= FSNOTIFY_CONN_FLAG_IS_WATCHED ;
162
169
fsnotify_get_sb_watched_objects (sb );
163
- }
164
-
165
- static void fsnotify_put_sb_watchers (struct fsnotify_mark_connector * conn )
166
- {
167
- struct super_block * sb = fsnotify_connector_sb (conn );
168
-
169
- if (sb )
170
+ } else if (!has_marks && is_watched ) {
171
+ conn -> flags &= ~FSNOTIFY_CONN_FLAG_IS_WATCHED ;
170
172
fsnotify_put_sb_watched_objects (sb );
173
+ }
171
174
}
172
175
173
176
/*
@@ -266,6 +269,7 @@ static void *fsnotify_detach_connector_from_object(
266
269
unsigned int * type )
267
270
{
268
271
fsnotify_connp_t * connp = fsnotify_object_connp (conn -> obj , conn -> type );
272
+ struct super_block * sb = fsnotify_connector_sb (conn );
269
273
struct inode * inode = NULL ;
270
274
271
275
* type = conn -> type ;
@@ -285,10 +289,10 @@ static void *fsnotify_detach_connector_from_object(
285
289
fsnotify_conn_sb (conn )-> s_fsnotify_mask = 0 ;
286
290
}
287
291
288
- fsnotify_put_sb_watchers (conn );
289
292
rcu_assign_pointer (* connp , NULL );
290
293
conn -> obj = NULL ;
291
294
conn -> type = FSNOTIFY_OBJ_TYPE_DETACHED ;
295
+ fsnotify_update_sb_watchers (sb , conn );
292
296
293
297
return inode ;
294
298
}
@@ -340,6 +344,11 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
340
344
objp = fsnotify_detach_connector_from_object (conn , & type );
341
345
free_conn = true;
342
346
} else {
347
+ struct super_block * sb = fsnotify_connector_sb (conn );
348
+
349
+ /* Update watched objects after detaching mark */
350
+ if (sb )
351
+ fsnotify_update_sb_watchers (sb , conn );
343
352
objp = __fsnotify_recalc_mask (conn );
344
353
type = conn -> type ;
345
354
}
@@ -581,10 +590,7 @@ static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp,
581
590
if (cmpxchg (connp , NULL , conn )) {
582
591
/* Someone else created list structure for us */
583
592
kmem_cache_free (fsnotify_mark_connector_cachep , conn );
584
- return 0 ;
585
593
}
586
-
587
- fsnotify_get_sb_watchers (conn );
588
594
return 0 ;
589
595
}
590
596
@@ -624,6 +630,7 @@ static struct fsnotify_mark_connector *fsnotify_grab_connector(
624
630
static int fsnotify_add_mark_list (struct fsnotify_mark * mark , void * obj ,
625
631
unsigned int obj_type , int add_flags )
626
632
{
633
+ struct super_block * sb = fsnotify_object_sb (obj , obj_type );
627
634
struct fsnotify_mark * lmark , * last = NULL ;
628
635
struct fsnotify_mark_connector * conn ;
629
636
fsnotify_connp_t * connp ;
@@ -673,6 +680,7 @@ static int fsnotify_add_mark_list(struct fsnotify_mark *mark, void *obj,
673
680
/* mark should be the last entry. last is the current last entry */
674
681
hlist_add_behind_rcu (& mark -> obj_list , & last -> obj_list );
675
682
added :
683
+ fsnotify_update_sb_watchers (sb , conn );
676
684
/*
677
685
* Since connector is attached to object using cmpxchg() we are
678
686
* guaranteed that connector initialization is fully visible by anyone
0 commit comments