Commit 9c61f3b5 authored by Amir Goldstein's avatar Amir Goldstein Committed by Jan Kara
Browse files

fanotify: break up fanotify_alloc_event()



Break up fanotify_alloc_event() into helpers by event struct type.

Suggested-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent b8a6c3a2
Loading
Loading
Loading
Loading
+89 −65
Original line number Diff line number Diff line
@@ -344,6 +344,77 @@ 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,
@@ -351,8 +422,6 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
						   __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;
	}

		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.
		 * 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;
		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 {
		event = fanotify_alloc_path_event(path, gfp);
	}

	if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
		ffe = kmem_cache_alloc(fanotify_fid_event_cachep, gfp);
		if (!ffe)
	if (!event)
		goto out;

		event = &ffe->fae;
		event->type = FANOTIFY_EVENT_TYPE_FID;
	} 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;
	}

init:
	/*
	 * 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 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
	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;