summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/notify/fanotify/fanotify.c154
1 files changed, 89 insertions, 65 deletions
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 921ff05e1877..41f5fc9a8f19 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -344,15 +344,84 @@ static struct inode *fanotify_fid_inode(struct inode *to_tell, u32 event_mask,
return fsnotify_data_inode(data, data_type);
}
+static struct fanotify_event *fanotify_alloc_path_event(const struct path *path,
+ gfp_t gfp)
+{
+ struct fanotify_path_event *pevent;
+
+ pevent = kmem_cache_alloc(fanotify_path_event_cachep, gfp);
+ if (!pevent)
+ return NULL;
+
+ pevent->fae.type = FANOTIFY_EVENT_TYPE_PATH;
+ pevent->path = *path;
+ path_get(path);
+
+ return &pevent->fae;
+}
+
+static struct fanotify_event *fanotify_alloc_perm_event(const struct path *path,
+ gfp_t gfp)
+{
+ struct fanotify_perm_event *pevent;
+
+ pevent = kmem_cache_alloc(fanotify_perm_event_cachep, gfp);
+ if (!pevent)
+ return NULL;
+
+ pevent->fae.type = FANOTIFY_EVENT_TYPE_PATH_PERM;
+ pevent->response = 0;
+ pevent->state = FAN_EVENT_INIT;
+ pevent->path = *path;
+ path_get(path);
+
+ return &pevent->fae;
+}
+
+static struct fanotify_event *fanotify_alloc_fid_event(struct inode *id,
+ __kernel_fsid_t *fsid,
+ gfp_t gfp)
+{
+ struct fanotify_fid_event *ffe;
+
+ ffe = kmem_cache_alloc(fanotify_fid_event_cachep, gfp);
+ if (!ffe)
+ return NULL;
+
+ ffe->fae.type = FANOTIFY_EVENT_TYPE_FID;
+ ffe->fsid = *fsid;
+ fanotify_encode_fh(&ffe->object_fh, id, gfp);
+
+ return &ffe->fae;
+}
+
+static struct fanotify_event *fanotify_alloc_name_event(struct inode *id,
+ __kernel_fsid_t *fsid,
+ const struct qstr *file_name,
+ gfp_t gfp)
+{
+ struct fanotify_name_event *fne;
+
+ fne = kmalloc(sizeof(*fne) + file_name->len + 1, gfp);
+ if (!fne)
+ return NULL;
+
+ fne->fae.type = FANOTIFY_EVENT_TYPE_FID_NAME;
+ fne->fsid = *fsid;
+ fanotify_encode_fh(&fne->dir_fh, id, gfp);
+ fne->name_len = file_name->len;
+ strcpy(fne->name, file_name->name);
+
+ return &fne->fae;
+}
+
static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
- struct inode *inode, u32 mask,
- const void *data, int data_type,
- const struct qstr *file_name,
- __kernel_fsid_t *fsid)
+ struct inode *inode, u32 mask,
+ const void *data, int data_type,
+ const struct qstr *file_name,
+ __kernel_fsid_t *fsid)
{
struct fanotify_event *event = NULL;
- struct fanotify_fid_event *ffe = NULL;
- struct fanotify_name_event *fne = NULL;
gfp_t gfp = GFP_KERNEL_ACCOUNT;
struct inode *id = fanotify_fid_inode(inode, mask, data, data_type);
const struct path *path = fsnotify_data_path(data, data_type);
@@ -372,55 +441,23 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
memalloc_use_memcg(group->memcg);
if (fanotify_is_perm_event(mask)) {
- struct fanotify_perm_event *pevent;
-
- pevent = kmem_cache_alloc(fanotify_perm_event_cachep, gfp);
- if (!pevent)
- goto out;
-
- event = &pevent->fae;
- event->type = FANOTIFY_EVENT_TYPE_PATH_PERM;
- pevent->response = 0;
- pevent->state = FAN_EVENT_INIT;
- goto init;
- }
-
- /*
- * For FAN_DIR_MODIFY event, we report the fid of the directory and
- * the name of the modified entry.
- * Allocate an fanotify_name_event struct and copy the name.
- */
- if (mask & FAN_DIR_MODIFY && !(WARN_ON_ONCE(!file_name))) {
- fne = kmalloc(sizeof(*fne) + file_name->len + 1, gfp);
- if (!fne)
- goto out;
-
- event = &fne->fae;
- event->type = FANOTIFY_EVENT_TYPE_FID_NAME;
- fne->name_len = file_name->len;
- strcpy(fne->name, file_name->name);
- goto init;
- }
-
- if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
- ffe = kmem_cache_alloc(fanotify_fid_event_cachep, gfp);
- if (!ffe)
- goto out;
-
- event = &ffe->fae;
- event->type = FANOTIFY_EVENT_TYPE_FID;
+ event = fanotify_alloc_perm_event(path, gfp);
+ } else if (mask & FAN_DIR_MODIFY && !(WARN_ON_ONCE(!file_name))) {
+ /*
+ * For FAN_DIR_MODIFY event, we report the fid of the directory
+ * and the name of the modified entry.
+ * Allocate an fanotify_name_event struct and copy the name.
+ */
+ event = fanotify_alloc_name_event(id, fsid, file_name, gfp);
+ } else if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
+ event = fanotify_alloc_fid_event(id, fsid, gfp);
} else {
- struct fanotify_path_event *pevent;
-
- pevent = kmem_cache_alloc(fanotify_path_event_cachep, gfp);
- if (!pevent)
- goto out;
-
- event = &pevent->fae;
- event->type = FANOTIFY_EVENT_TYPE_PATH;
+ event = fanotify_alloc_path_event(path, gfp);
}
-init:
+ if (!event)
+ goto out;
+
/*
* Use the victim inode instead of the watching inode as the id for
* event queue, so event reported on parent is merged with event
@@ -432,19 +469,6 @@ init:
else
event->pid = get_pid(task_tgid(current));
- if (fsid && fanotify_event_fsid(event))
- *fanotify_event_fsid(event) = *fsid;
-
- if (fanotify_event_object_fh(event))
- fanotify_encode_fh(fanotify_event_object_fh(event), id, gfp);
-
- if (fanotify_event_dir_fh(event))
- fanotify_encode_fh(fanotify_event_dir_fh(event), id, gfp);
-
- if (fanotify_event_has_path(event)) {
- *fanotify_event_path(event) = *path;
- path_get(path);
- }
out:
memalloc_unuse_memcg();
return event;