diff mbox series

[04/11] fanotify: Expose fanotify_mark

Message ID 20210521024134.1032503-5-krisman@collabora.com (mailing list archive)
State New, archived
Headers show
Series File system wide monitoring | expand

Commit Message

Gabriel Krisman Bertazi May 21, 2021, 2:41 a.m. UTC
FAN_ERROR will require an error structure to be stored per mark.
Therefore, wrap fsnotify_mark in a fanotify specific structure in
preparation for that.

Signed-off-by: Gabriel Krisman Bertazi <krisman@collabora.com>
---
 fs/notify/fanotify/fanotify.c      |  4 +++-
 fs/notify/fanotify/fanotify.h      | 10 ++++++++++
 fs/notify/fanotify/fanotify_user.c | 14 +++++++-------
 3 files changed, 20 insertions(+), 8 deletions(-)

Comments

Amir Goldstein May 21, 2021, 9:06 a.m. UTC | #1
On Fri, May 21, 2021 at 5:42 AM Gabriel Krisman Bertazi
<krisman@collabora.com> wrote:
>
> FAN_ERROR will require an error structure to be stored per mark.
> Therefore, wrap fsnotify_mark in a fanotify specific structure in
> preparation for that.
>
> Signed-off-by: Gabriel Krisman Bertazi <krisman@collabora.com>
> ---
>  fs/notify/fanotify/fanotify.c      |  4 +++-
>  fs/notify/fanotify/fanotify.h      | 10 ++++++++++
>  fs/notify/fanotify/fanotify_user.c | 14 +++++++-------
>  3 files changed, 20 insertions(+), 8 deletions(-)
>
> diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
> index 711b36a9483e..34e2ee759b39 100644
> --- a/fs/notify/fanotify/fanotify.c
> +++ b/fs/notify/fanotify/fanotify.c
> @@ -869,7 +869,9 @@ static void fanotify_freeing_mark(struct fsnotify_mark *mark,
>
>  static void fanotify_free_mark(struct fsnotify_mark *fsn_mark)
>  {
> -       kmem_cache_free(fanotify_mark_cache, fsn_mark);
> +       struct fanotify_mark *mark = FANOTIFY_MARK(fsn_mark);
> +
> +       kmem_cache_free(fanotify_mark_cache, mark);
>  }
>
>  const struct fsnotify_ops fanotify_fsnotify_ops = {
> diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h
> index 4a5e555dc3d2..a399c5e2615d 100644
> --- a/fs/notify/fanotify/fanotify.h
> +++ b/fs/notify/fanotify/fanotify.h
> @@ -129,6 +129,16 @@ static inline void fanotify_info_copy_name(struct fanotify_info *info,
>                name->name);
>  }
>
> +struct fanotify_mark {
> +       struct fsnotify_mark fsn_mark;
> +       struct fanotify_error_event *error_event;

I don't think fanotify_error_event is defined at this point in the series.
You can add this field later in the series.

> +};
> +
> +static inline struct fanotify_mark *FANOTIFY_MARK(struct fsnotify_mark *mark)
> +{
> +       return container_of(mark, struct fanotify_mark, fsn_mark);
> +}
> +
>  /*
>   * Common structure for fanotify events. Concrete structs are allocated in
>   * fanotify_handle_event() and freed when the information is retrieved by
> diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
> index 9cc6c8808ed5..00210535a78e 100644
> --- a/fs/notify/fanotify/fanotify_user.c
> +++ b/fs/notify/fanotify/fanotify_user.c
> @@ -914,7 +914,7 @@ static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
>                                                    __kernel_fsid_t *fsid)
>  {
>         struct ucounts *ucounts = group->fanotify_data.ucounts;
> -       struct fsnotify_mark *mark;
> +       struct fanotify_mark *mark;
>         int ret;
>
>         /*
> @@ -926,20 +926,20 @@ static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
>             !inc_ucount(ucounts->ns, ucounts->uid, UCOUNT_FANOTIFY_MARKS))
>                 return ERR_PTR(-ENOSPC);
>
> -       mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL);
> +       mark = kmem_cache_zalloc(fanotify_mark_cache, GFP_KERNEL);
>         if (!mark) {
>                 ret = -ENOMEM;
>                 goto out_dec_ucounts;
>         }
>
> -       fsnotify_init_mark(mark, group);
> -       ret = fsnotify_add_mark_locked(mark, connp, type, 0, fsid);
> +       fsnotify_init_mark(&mark->fsn_mark, group);
> +       ret = fsnotify_add_mark_locked(&mark->fsn_mark, connp, type, 0, fsid);
>         if (ret) {
> -               fsnotify_put_mark(mark);
> +               fsnotify_put_mark(&mark->fsn_mark);
>                 goto out_dec_ucounts;
>         }
>
> -       return mark;
> +       return &mark->fsn_mark;
>
>  out_dec_ucounts:
>         if (!FAN_GROUP_FLAG(group, FAN_UNLIMITED_MARKS))
> @@ -1477,7 +1477,7 @@ static int __init fanotify_user_setup(void)
>         BUILD_BUG_ON(HWEIGHT32(FANOTIFY_INIT_FLAGS) != 10);
>         BUILD_BUG_ON(HWEIGHT32(FANOTIFY_MARK_FLAGS) != 9);
>
> -       fanotify_mark_cache = KMEM_CACHE(fsnotify_mark,
> +       fanotify_mark_cache = KMEM_CACHE(fanotify_mark,
>                                          SLAB_PANIC|SLAB_ACCOUNT);

Thinking out loud:

Do we want to increase the size of all fanotify marks or just the size of
sb marks?

In this WIP branch [1], I took the latter approach.

The greater question is, do we want/need to allow setting FAN_ERROR
on inode marks mask at all?

My feeling is that we should not allow that at this time, because the
use case of watching for critical errors on a specific inode is a
non-requirement IMO.

OTOH, if we treat this change as a stepping stone towards adding
writeback error events in the future then we should also think about
whether watching specific files for writeback error in a sensible use case
I don't think that it is, because when application can always keep an open
fd for file of interest and fysnc on any reported writeback error on the
filesystem, as those events are supposed to be rare.

Another point to consider - in future revisions of [1] fanotify sb marks
may grow more fields (e.g. subtree_root, userns), so while adding a single
pointer field to all fanotify inode marks may not be the end of the world,
going forward, we will need to have a separate kmem_cache for sb marks
anyway, so maybe better to split it now already.

Thoughts?

Amir.

[1] https://github.com/amir73il/linux/commits/fanotify_idmapped
diff mbox series

Patch

diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 711b36a9483e..34e2ee759b39 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -869,7 +869,9 @@  static void fanotify_freeing_mark(struct fsnotify_mark *mark,
 
 static void fanotify_free_mark(struct fsnotify_mark *fsn_mark)
 {
-	kmem_cache_free(fanotify_mark_cache, fsn_mark);
+	struct fanotify_mark *mark = FANOTIFY_MARK(fsn_mark);
+
+	kmem_cache_free(fanotify_mark_cache, mark);
 }
 
 const struct fsnotify_ops fanotify_fsnotify_ops = {
diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h
index 4a5e555dc3d2..a399c5e2615d 100644
--- a/fs/notify/fanotify/fanotify.h
+++ b/fs/notify/fanotify/fanotify.h
@@ -129,6 +129,16 @@  static inline void fanotify_info_copy_name(struct fanotify_info *info,
 	       name->name);
 }
 
+struct fanotify_mark {
+	struct fsnotify_mark fsn_mark;
+	struct fanotify_error_event *error_event;
+};
+
+static inline struct fanotify_mark *FANOTIFY_MARK(struct fsnotify_mark *mark)
+{
+	return container_of(mark, struct fanotify_mark, fsn_mark);
+}
+
 /*
  * Common structure for fanotify events. Concrete structs are allocated in
  * fanotify_handle_event() and freed when the information is retrieved by
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 9cc6c8808ed5..00210535a78e 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -914,7 +914,7 @@  static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
 						   __kernel_fsid_t *fsid)
 {
 	struct ucounts *ucounts = group->fanotify_data.ucounts;
-	struct fsnotify_mark *mark;
+	struct fanotify_mark *mark;
 	int ret;
 
 	/*
@@ -926,20 +926,20 @@  static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
 	    !inc_ucount(ucounts->ns, ucounts->uid, UCOUNT_FANOTIFY_MARKS))
 		return ERR_PTR(-ENOSPC);
 
-	mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL);
+	mark = kmem_cache_zalloc(fanotify_mark_cache, GFP_KERNEL);
 	if (!mark) {
 		ret = -ENOMEM;
 		goto out_dec_ucounts;
 	}
 
-	fsnotify_init_mark(mark, group);
-	ret = fsnotify_add_mark_locked(mark, connp, type, 0, fsid);
+	fsnotify_init_mark(&mark->fsn_mark, group);
+	ret = fsnotify_add_mark_locked(&mark->fsn_mark, connp, type, 0, fsid);
 	if (ret) {
-		fsnotify_put_mark(mark);
+		fsnotify_put_mark(&mark->fsn_mark);
 		goto out_dec_ucounts;
 	}
 
-	return mark;
+	return &mark->fsn_mark;
 
 out_dec_ucounts:
 	if (!FAN_GROUP_FLAG(group, FAN_UNLIMITED_MARKS))
@@ -1477,7 +1477,7 @@  static int __init fanotify_user_setup(void)
 	BUILD_BUG_ON(HWEIGHT32(FANOTIFY_INIT_FLAGS) != 10);
 	BUILD_BUG_ON(HWEIGHT32(FANOTIFY_MARK_FLAGS) != 9);
 
-	fanotify_mark_cache = KMEM_CACHE(fsnotify_mark,
+	fanotify_mark_cache = KMEM_CACHE(fanotify_mark,
 					 SLAB_PANIC|SLAB_ACCOUNT);
 	fanotify_fid_event_cachep = KMEM_CACHE(fanotify_fid_event,
 					       SLAB_PANIC);