summaryrefslogtreecommitdiff
path: root/fs/notify/mark.c
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2024-03-17 21:41:51 +0300
committerJan Kara <jack@suse.cz>2024-04-04 17:24:16 +0300
commit07a3b8d0bf726a1e49b050bbc6bd72f031e505fe (patch)
tree45d9153d780282b0d4f2999811a9d210b63e1d62 /fs/notify/mark.c
parentc9d4603b054f9a63c07c7012040af4c80adb2c60 (diff)
downloadlinux-07a3b8d0bf726a1e49b050bbc6bd72f031e505fe.tar.xz
fsnotify: lazy attach fsnotify_sb_info state to sb
Define a container struct fsnotify_sb_info to hold per-sb state, including the reference to sb marks connector. Allocate the fsnotify_sb_info state before attaching connector to any object on the sb and free it only when killing sb. This state is going to be used for storing per priority watched objects counters. Suggested-by: Jan Kara <jack@suse.cz> Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Jan Kara <jack@suse.cz> Message-Id: <20240317184154.1200192-8-amir73il@gmail.com>
Diffstat (limited to 'fs/notify/mark.c')
-rw-r--r--fs/notify/mark.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index 647c49c20467..b2f5d8c9cce1 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -106,7 +106,7 @@ static fsnotify_connp_t *fsnotify_object_connp(void *obj,
case FSNOTIFY_OBJ_TYPE_VFSMOUNT:
return &real_mount(obj)->mnt_fsnotify_marks;
case FSNOTIFY_OBJ_TYPE_SB:
- return &((struct super_block *)obj)->s_fsnotify_marks;
+ return fsnotify_sb_marks(obj);
default:
return NULL;
}
@@ -569,6 +569,26 @@ int fsnotify_compare_groups(struct fsnotify_group *a, struct fsnotify_group *b)
return -1;
}
+static int fsnotify_attach_info_to_sb(struct super_block *sb)
+{
+ struct fsnotify_sb_info *sbinfo;
+
+ /* sb info is freed on fsnotify_sb_delete() */
+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_KERNEL);
+ if (!sbinfo)
+ return -ENOMEM;
+
+ /*
+ * cmpxchg() provides the barrier so that callers of fsnotify_sb_info()
+ * will observe an initialized structure
+ */
+ if (cmpxchg(&sb->s_fsnotify_info, NULL, sbinfo)) {
+ /* Someone else created sbinfo for us */
+ kfree(sbinfo);
+ }
+ return 0;
+}
+
static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp,
void *obj, unsigned int obj_type)
{
@@ -640,6 +660,16 @@ static int fsnotify_add_mark_list(struct fsnotify_mark *mark, void *obj,
if (WARN_ON(!fsnotify_valid_obj_type(obj_type)))
return -EINVAL;
+ /*
+ * Attach the sb info before attaching a connector to any object on sb.
+ * The sb info will remain attached as long as sb lives.
+ */
+ if (!fsnotify_sb_info(sb)) {
+ err = fsnotify_attach_info_to_sb(sb);
+ if (err)
+ return err;
+ }
+
connp = fsnotify_object_connp(obj, obj_type);
restart:
spin_lock(&mark->lock);