summaryrefslogtreecommitdiffstats
path: root/fs/notify/fsnotify.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2017-02-01 09:21:58 +0100
committerJan Kara <jack@suse.cz>2017-04-10 17:37:35 +0200
commit08991e83b7286635167bab40927665a90fb00d81 (patch)
treee82e62c0a92193ff3af83d3d1ea60f0430c5c118 /fs/notify/fsnotify.c
parentfsnotify: Lock object list with connector lock (diff)
downloadlinux-08991e83b7286635167bab40927665a90fb00d81.tar.xz
linux-08991e83b7286635167bab40927665a90fb00d81.zip
fsnotify: Free fsnotify_mark_connector when there is no mark attached
Currently we free fsnotify_mark_connector structure only when inode / vfsmount is getting freed. This can however impose noticeable memory overhead when marks get attached to inodes only temporarily. So free the connector structure once the last mark is detached from the object. Since notification infrastructure can be working with the connector under the protection of fsnotify_mark_srcu, we have to be careful and free the fsnotify_mark_connector only after SRCU period passes. Reviewed-by: Miklos Szeredi <mszeredi@redhat.com> Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/notify/fsnotify.c')
-rw-r--r--fs/notify/fsnotify.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index eae621a18ac9..d512ef9f75fc 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -228,7 +228,8 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
if ((mask & FS_MODIFY) ||
(test_mask & to_tell->i_fsnotify_mask)) {
- inode_conn = lockless_dereference(to_tell->i_fsnotify_marks);
+ inode_conn = srcu_dereference(to_tell->i_fsnotify_marks,
+ &fsnotify_mark_srcu);
if (inode_conn)
inode_node = srcu_dereference(inode_conn->list.first,
&fsnotify_mark_srcu);
@@ -236,11 +237,13 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
if (mnt && ((mask & FS_MODIFY) ||
(test_mask & mnt->mnt_fsnotify_mask))) {
- inode_conn = lockless_dereference(to_tell->i_fsnotify_marks);
+ inode_conn = srcu_dereference(to_tell->i_fsnotify_marks,
+ &fsnotify_mark_srcu);
if (inode_conn)
inode_node = srcu_dereference(inode_conn->list.first,
&fsnotify_mark_srcu);
- vfsmount_conn = lockless_dereference(mnt->mnt_fsnotify_marks);
+ vfsmount_conn = srcu_dereference(mnt->mnt_fsnotify_marks,
+ &fsnotify_mark_srcu);
if (vfsmount_conn)
vfsmount_node = srcu_dereference(
vfsmount_conn->list.first,