162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Directory notifications for Linux.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2000,2001,2002 Stephen Rothwell
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Copyright (C) 2009 Eric Paris <Red Hat Inc>
862306a36Sopenharmony_ci * dnotify was largly rewritten to use the new fsnotify infrastructure
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci#include <linux/fs.h>
1162306a36Sopenharmony_ci#include <linux/module.h>
1262306a36Sopenharmony_ci#include <linux/sched.h>
1362306a36Sopenharmony_ci#include <linux/sched/signal.h>
1462306a36Sopenharmony_ci#include <linux/dnotify.h>
1562306a36Sopenharmony_ci#include <linux/init.h>
1662306a36Sopenharmony_ci#include <linux/security.h>
1762306a36Sopenharmony_ci#include <linux/spinlock.h>
1862306a36Sopenharmony_ci#include <linux/slab.h>
1962306a36Sopenharmony_ci#include <linux/fdtable.h>
2062306a36Sopenharmony_ci#include <linux/fsnotify_backend.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cistatic int dir_notify_enable __read_mostly = 1;
2362306a36Sopenharmony_ci#ifdef CONFIG_SYSCTL
2462306a36Sopenharmony_cistatic struct ctl_table dnotify_sysctls[] = {
2562306a36Sopenharmony_ci	{
2662306a36Sopenharmony_ci		.procname	= "dir-notify-enable",
2762306a36Sopenharmony_ci		.data		= &dir_notify_enable,
2862306a36Sopenharmony_ci		.maxlen		= sizeof(int),
2962306a36Sopenharmony_ci		.mode		= 0644,
3062306a36Sopenharmony_ci		.proc_handler	= proc_dointvec,
3162306a36Sopenharmony_ci	},
3262306a36Sopenharmony_ci	{}
3362306a36Sopenharmony_ci};
3462306a36Sopenharmony_cistatic void __init dnotify_sysctl_init(void)
3562306a36Sopenharmony_ci{
3662306a36Sopenharmony_ci	register_sysctl_init("fs", dnotify_sysctls);
3762306a36Sopenharmony_ci}
3862306a36Sopenharmony_ci#else
3962306a36Sopenharmony_ci#define dnotify_sysctl_init() do { } while (0)
4062306a36Sopenharmony_ci#endif
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_cistatic struct kmem_cache *dnotify_struct_cache __read_mostly;
4362306a36Sopenharmony_cistatic struct kmem_cache *dnotify_mark_cache __read_mostly;
4462306a36Sopenharmony_cistatic struct fsnotify_group *dnotify_group __read_mostly;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci/*
4762306a36Sopenharmony_ci * dnotify will attach one of these to each inode (i_fsnotify_marks) which
4862306a36Sopenharmony_ci * is being watched by dnotify.  If multiple userspace applications are watching
4962306a36Sopenharmony_ci * the same directory with dnotify their information is chained in dn
5062306a36Sopenharmony_ci */
5162306a36Sopenharmony_cistruct dnotify_mark {
5262306a36Sopenharmony_ci	struct fsnotify_mark fsn_mark;
5362306a36Sopenharmony_ci	struct dnotify_struct *dn;
5462306a36Sopenharmony_ci};
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci/*
5762306a36Sopenharmony_ci * When a process starts or stops watching an inode the set of events which
5862306a36Sopenharmony_ci * dnotify cares about for that inode may change.  This function runs the
5962306a36Sopenharmony_ci * list of everything receiving dnotify events about this directory and calculates
6062306a36Sopenharmony_ci * the set of all those events.  After it updates what dnotify is interested in
6162306a36Sopenharmony_ci * it calls the fsnotify function so it can update the set of all events relevant
6262306a36Sopenharmony_ci * to this inode.
6362306a36Sopenharmony_ci */
6462306a36Sopenharmony_cistatic void dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark)
6562306a36Sopenharmony_ci{
6662306a36Sopenharmony_ci	__u32 new_mask = 0;
6762306a36Sopenharmony_ci	struct dnotify_struct *dn;
6862306a36Sopenharmony_ci	struct dnotify_mark *dn_mark  = container_of(fsn_mark,
6962306a36Sopenharmony_ci						     struct dnotify_mark,
7062306a36Sopenharmony_ci						     fsn_mark);
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	assert_spin_locked(&fsn_mark->lock);
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	for (dn = dn_mark->dn; dn != NULL; dn = dn->dn_next)
7562306a36Sopenharmony_ci		new_mask |= (dn->dn_mask & ~FS_DN_MULTISHOT);
7662306a36Sopenharmony_ci	if (fsn_mark->mask == new_mask)
7762306a36Sopenharmony_ci		return;
7862306a36Sopenharmony_ci	fsn_mark->mask = new_mask;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	fsnotify_recalc_mask(fsn_mark->connector);
8162306a36Sopenharmony_ci}
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci/*
8462306a36Sopenharmony_ci * Mains fsnotify call where events are delivered to dnotify.
8562306a36Sopenharmony_ci * Find the dnotify mark on the relevant inode, run the list of dnotify structs
8662306a36Sopenharmony_ci * on that mark and determine which of them has expressed interest in receiving
8762306a36Sopenharmony_ci * events of this type.  When found send the correct process and signal and
8862306a36Sopenharmony_ci * destroy the dnotify struct if it was not registered to receive multiple
8962306a36Sopenharmony_ci * events.
9062306a36Sopenharmony_ci */
9162306a36Sopenharmony_cistatic int dnotify_handle_event(struct fsnotify_mark *inode_mark, u32 mask,
9262306a36Sopenharmony_ci				struct inode *inode, struct inode *dir,
9362306a36Sopenharmony_ci				const struct qstr *name, u32 cookie)
9462306a36Sopenharmony_ci{
9562306a36Sopenharmony_ci	struct dnotify_mark *dn_mark;
9662306a36Sopenharmony_ci	struct dnotify_struct *dn;
9762306a36Sopenharmony_ci	struct dnotify_struct **prev;
9862306a36Sopenharmony_ci	struct fown_struct *fown;
9962306a36Sopenharmony_ci	__u32 test_mask = mask & ~FS_EVENT_ON_CHILD;
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	/* not a dir, dnotify doesn't care */
10262306a36Sopenharmony_ci	if (!dir && !(mask & FS_ISDIR))
10362306a36Sopenharmony_ci		return 0;
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	dn_mark = container_of(inode_mark, struct dnotify_mark, fsn_mark);
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	spin_lock(&inode_mark->lock);
10862306a36Sopenharmony_ci	prev = &dn_mark->dn;
10962306a36Sopenharmony_ci	while ((dn = *prev) != NULL) {
11062306a36Sopenharmony_ci		if ((dn->dn_mask & test_mask) == 0) {
11162306a36Sopenharmony_ci			prev = &dn->dn_next;
11262306a36Sopenharmony_ci			continue;
11362306a36Sopenharmony_ci		}
11462306a36Sopenharmony_ci		fown = &dn->dn_filp->f_owner;
11562306a36Sopenharmony_ci		send_sigio(fown, dn->dn_fd, POLL_MSG);
11662306a36Sopenharmony_ci		if (dn->dn_mask & FS_DN_MULTISHOT)
11762306a36Sopenharmony_ci			prev = &dn->dn_next;
11862306a36Sopenharmony_ci		else {
11962306a36Sopenharmony_ci			*prev = dn->dn_next;
12062306a36Sopenharmony_ci			kmem_cache_free(dnotify_struct_cache, dn);
12162306a36Sopenharmony_ci			dnotify_recalc_inode_mask(inode_mark);
12262306a36Sopenharmony_ci		}
12362306a36Sopenharmony_ci	}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	spin_unlock(&inode_mark->lock);
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	return 0;
12862306a36Sopenharmony_ci}
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_cistatic void dnotify_free_mark(struct fsnotify_mark *fsn_mark)
13162306a36Sopenharmony_ci{
13262306a36Sopenharmony_ci	struct dnotify_mark *dn_mark = container_of(fsn_mark,
13362306a36Sopenharmony_ci						    struct dnotify_mark,
13462306a36Sopenharmony_ci						    fsn_mark);
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	BUG_ON(dn_mark->dn);
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	kmem_cache_free(dnotify_mark_cache, dn_mark);
13962306a36Sopenharmony_ci}
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cistatic const struct fsnotify_ops dnotify_fsnotify_ops = {
14262306a36Sopenharmony_ci	.handle_inode_event = dnotify_handle_event,
14362306a36Sopenharmony_ci	.free_mark = dnotify_free_mark,
14462306a36Sopenharmony_ci};
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci/*
14762306a36Sopenharmony_ci * Called every time a file is closed.  Looks first for a dnotify mark on the
14862306a36Sopenharmony_ci * inode.  If one is found run all of the ->dn structures attached to that
14962306a36Sopenharmony_ci * mark for one relevant to this process closing the file and remove that
15062306a36Sopenharmony_ci * dnotify_struct.  If that was the last dnotify_struct also remove the
15162306a36Sopenharmony_ci * fsnotify_mark.
15262306a36Sopenharmony_ci */
15362306a36Sopenharmony_civoid dnotify_flush(struct file *filp, fl_owner_t id)
15462306a36Sopenharmony_ci{
15562306a36Sopenharmony_ci	struct fsnotify_mark *fsn_mark;
15662306a36Sopenharmony_ci	struct dnotify_mark *dn_mark;
15762306a36Sopenharmony_ci	struct dnotify_struct *dn;
15862306a36Sopenharmony_ci	struct dnotify_struct **prev;
15962306a36Sopenharmony_ci	struct inode *inode;
16062306a36Sopenharmony_ci	bool free = false;
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	inode = file_inode(filp);
16362306a36Sopenharmony_ci	if (!S_ISDIR(inode->i_mode))
16462306a36Sopenharmony_ci		return;
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	fsn_mark = fsnotify_find_mark(&inode->i_fsnotify_marks, dnotify_group);
16762306a36Sopenharmony_ci	if (!fsn_mark)
16862306a36Sopenharmony_ci		return;
16962306a36Sopenharmony_ci	dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark);
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	fsnotify_group_lock(dnotify_group);
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	spin_lock(&fsn_mark->lock);
17462306a36Sopenharmony_ci	prev = &dn_mark->dn;
17562306a36Sopenharmony_ci	while ((dn = *prev) != NULL) {
17662306a36Sopenharmony_ci		if ((dn->dn_owner == id) && (dn->dn_filp == filp)) {
17762306a36Sopenharmony_ci			*prev = dn->dn_next;
17862306a36Sopenharmony_ci			kmem_cache_free(dnotify_struct_cache, dn);
17962306a36Sopenharmony_ci			dnotify_recalc_inode_mask(fsn_mark);
18062306a36Sopenharmony_ci			break;
18162306a36Sopenharmony_ci		}
18262306a36Sopenharmony_ci		prev = &dn->dn_next;
18362306a36Sopenharmony_ci	}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	spin_unlock(&fsn_mark->lock);
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	/* nothing else could have found us thanks to the dnotify_groups
18862306a36Sopenharmony_ci	   mark_mutex */
18962306a36Sopenharmony_ci	if (dn_mark->dn == NULL) {
19062306a36Sopenharmony_ci		fsnotify_detach_mark(fsn_mark);
19162306a36Sopenharmony_ci		free = true;
19262306a36Sopenharmony_ci	}
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	fsnotify_group_unlock(dnotify_group);
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	if (free)
19762306a36Sopenharmony_ci		fsnotify_free_mark(fsn_mark);
19862306a36Sopenharmony_ci	fsnotify_put_mark(fsn_mark);
19962306a36Sopenharmony_ci}
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci/* this conversion is done only at watch creation */
20262306a36Sopenharmony_cistatic __u32 convert_arg(unsigned int arg)
20362306a36Sopenharmony_ci{
20462306a36Sopenharmony_ci	__u32 new_mask = FS_EVENT_ON_CHILD;
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	if (arg & DN_MULTISHOT)
20762306a36Sopenharmony_ci		new_mask |= FS_DN_MULTISHOT;
20862306a36Sopenharmony_ci	if (arg & DN_DELETE)
20962306a36Sopenharmony_ci		new_mask |= (FS_DELETE | FS_MOVED_FROM);
21062306a36Sopenharmony_ci	if (arg & DN_MODIFY)
21162306a36Sopenharmony_ci		new_mask |= FS_MODIFY;
21262306a36Sopenharmony_ci	if (arg & DN_ACCESS)
21362306a36Sopenharmony_ci		new_mask |= FS_ACCESS;
21462306a36Sopenharmony_ci	if (arg & DN_ATTRIB)
21562306a36Sopenharmony_ci		new_mask |= FS_ATTRIB;
21662306a36Sopenharmony_ci	if (arg & DN_RENAME)
21762306a36Sopenharmony_ci		new_mask |= FS_RENAME;
21862306a36Sopenharmony_ci	if (arg & DN_CREATE)
21962306a36Sopenharmony_ci		new_mask |= (FS_CREATE | FS_MOVED_TO);
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	return new_mask;
22262306a36Sopenharmony_ci}
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci/*
22562306a36Sopenharmony_ci * If multiple processes watch the same inode with dnotify there is only one
22662306a36Sopenharmony_ci * dnotify mark in inode->i_fsnotify_marks but we chain a dnotify_struct
22762306a36Sopenharmony_ci * onto that mark.  This function either attaches the new dnotify_struct onto
22862306a36Sopenharmony_ci * that list, or it |= the mask onto an existing dnofiy_struct.
22962306a36Sopenharmony_ci */
23062306a36Sopenharmony_cistatic int attach_dn(struct dnotify_struct *dn, struct dnotify_mark *dn_mark,
23162306a36Sopenharmony_ci		     fl_owner_t id, int fd, struct file *filp, __u32 mask)
23262306a36Sopenharmony_ci{
23362306a36Sopenharmony_ci	struct dnotify_struct *odn;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	odn = dn_mark->dn;
23662306a36Sopenharmony_ci	while (odn != NULL) {
23762306a36Sopenharmony_ci		/* adding more events to existing dnofiy_struct? */
23862306a36Sopenharmony_ci		if ((odn->dn_owner == id) && (odn->dn_filp == filp)) {
23962306a36Sopenharmony_ci			odn->dn_fd = fd;
24062306a36Sopenharmony_ci			odn->dn_mask |= mask;
24162306a36Sopenharmony_ci			return -EEXIST;
24262306a36Sopenharmony_ci		}
24362306a36Sopenharmony_ci		odn = odn->dn_next;
24462306a36Sopenharmony_ci	}
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	dn->dn_mask = mask;
24762306a36Sopenharmony_ci	dn->dn_fd = fd;
24862306a36Sopenharmony_ci	dn->dn_filp = filp;
24962306a36Sopenharmony_ci	dn->dn_owner = id;
25062306a36Sopenharmony_ci	dn->dn_next = dn_mark->dn;
25162306a36Sopenharmony_ci	dn_mark->dn = dn;
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	return 0;
25462306a36Sopenharmony_ci}
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci/*
25762306a36Sopenharmony_ci * When a process calls fcntl to attach a dnotify watch to a directory it ends
25862306a36Sopenharmony_ci * up here.  Allocate both a mark for fsnotify to add and a dnotify_struct to be
25962306a36Sopenharmony_ci * attached to the fsnotify_mark.
26062306a36Sopenharmony_ci */
26162306a36Sopenharmony_ciint fcntl_dirnotify(int fd, struct file *filp, unsigned int arg)
26262306a36Sopenharmony_ci{
26362306a36Sopenharmony_ci	struct dnotify_mark *new_dn_mark, *dn_mark;
26462306a36Sopenharmony_ci	struct fsnotify_mark *new_fsn_mark, *fsn_mark;
26562306a36Sopenharmony_ci	struct dnotify_struct *dn;
26662306a36Sopenharmony_ci	struct inode *inode;
26762306a36Sopenharmony_ci	fl_owner_t id = current->files;
26862306a36Sopenharmony_ci	struct file *f;
26962306a36Sopenharmony_ci	int destroy = 0, error = 0;
27062306a36Sopenharmony_ci	__u32 mask;
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	/* we use these to tell if we need to kfree */
27362306a36Sopenharmony_ci	new_fsn_mark = NULL;
27462306a36Sopenharmony_ci	dn = NULL;
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	if (!dir_notify_enable) {
27762306a36Sopenharmony_ci		error = -EINVAL;
27862306a36Sopenharmony_ci		goto out_err;
27962306a36Sopenharmony_ci	}
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	/* a 0 mask means we are explicitly removing the watch */
28262306a36Sopenharmony_ci	if ((arg & ~DN_MULTISHOT) == 0) {
28362306a36Sopenharmony_ci		dnotify_flush(filp, id);
28462306a36Sopenharmony_ci		error = 0;
28562306a36Sopenharmony_ci		goto out_err;
28662306a36Sopenharmony_ci	}
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	/* dnotify only works on directories */
28962306a36Sopenharmony_ci	inode = file_inode(filp);
29062306a36Sopenharmony_ci	if (!S_ISDIR(inode->i_mode)) {
29162306a36Sopenharmony_ci		error = -ENOTDIR;
29262306a36Sopenharmony_ci		goto out_err;
29362306a36Sopenharmony_ci	}
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	/*
29662306a36Sopenharmony_ci	 * convert the userspace DN_* "arg" to the internal FS_*
29762306a36Sopenharmony_ci	 * defined in fsnotify
29862306a36Sopenharmony_ci	 */
29962306a36Sopenharmony_ci	mask = convert_arg(arg);
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	error = security_path_notify(&filp->f_path, mask,
30262306a36Sopenharmony_ci			FSNOTIFY_OBJ_TYPE_INODE);
30362306a36Sopenharmony_ci	if (error)
30462306a36Sopenharmony_ci		goto out_err;
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	/* expect most fcntl to add new rather than augment old */
30762306a36Sopenharmony_ci	dn = kmem_cache_alloc(dnotify_struct_cache, GFP_KERNEL);
30862306a36Sopenharmony_ci	if (!dn) {
30962306a36Sopenharmony_ci		error = -ENOMEM;
31062306a36Sopenharmony_ci		goto out_err;
31162306a36Sopenharmony_ci	}
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	/* new fsnotify mark, we expect most fcntl calls to add a new mark */
31462306a36Sopenharmony_ci	new_dn_mark = kmem_cache_alloc(dnotify_mark_cache, GFP_KERNEL);
31562306a36Sopenharmony_ci	if (!new_dn_mark) {
31662306a36Sopenharmony_ci		error = -ENOMEM;
31762306a36Sopenharmony_ci		goto out_err;
31862306a36Sopenharmony_ci	}
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	/* set up the new_fsn_mark and new_dn_mark */
32162306a36Sopenharmony_ci	new_fsn_mark = &new_dn_mark->fsn_mark;
32262306a36Sopenharmony_ci	fsnotify_init_mark(new_fsn_mark, dnotify_group);
32362306a36Sopenharmony_ci	new_fsn_mark->mask = mask;
32462306a36Sopenharmony_ci	new_dn_mark->dn = NULL;
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	/* this is needed to prevent the fcntl/close race described below */
32762306a36Sopenharmony_ci	fsnotify_group_lock(dnotify_group);
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	/* add the new_fsn_mark or find an old one. */
33062306a36Sopenharmony_ci	fsn_mark = fsnotify_find_mark(&inode->i_fsnotify_marks, dnotify_group);
33162306a36Sopenharmony_ci	if (fsn_mark) {
33262306a36Sopenharmony_ci		dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark);
33362306a36Sopenharmony_ci		spin_lock(&fsn_mark->lock);
33462306a36Sopenharmony_ci	} else {
33562306a36Sopenharmony_ci		error = fsnotify_add_inode_mark_locked(new_fsn_mark, inode, 0);
33662306a36Sopenharmony_ci		if (error) {
33762306a36Sopenharmony_ci			fsnotify_group_unlock(dnotify_group);
33862306a36Sopenharmony_ci			goto out_err;
33962306a36Sopenharmony_ci		}
34062306a36Sopenharmony_ci		spin_lock(&new_fsn_mark->lock);
34162306a36Sopenharmony_ci		fsn_mark = new_fsn_mark;
34262306a36Sopenharmony_ci		dn_mark = new_dn_mark;
34362306a36Sopenharmony_ci		/* we used new_fsn_mark, so don't free it */
34462306a36Sopenharmony_ci		new_fsn_mark = NULL;
34562306a36Sopenharmony_ci	}
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	rcu_read_lock();
34862306a36Sopenharmony_ci	f = lookup_fd_rcu(fd);
34962306a36Sopenharmony_ci	rcu_read_unlock();
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	/* if (f != filp) means that we lost a race and another task/thread
35262306a36Sopenharmony_ci	 * actually closed the fd we are still playing with before we grabbed
35362306a36Sopenharmony_ci	 * the dnotify_groups mark_mutex and fsn_mark->lock.  Since closing the
35462306a36Sopenharmony_ci	 * fd is the only time we clean up the marks we need to get our mark
35562306a36Sopenharmony_ci	 * off the list. */
35662306a36Sopenharmony_ci	if (f != filp) {
35762306a36Sopenharmony_ci		/* if we added ourselves, shoot ourselves, it's possible that
35862306a36Sopenharmony_ci		 * the flush actually did shoot this fsn_mark.  That's fine too
35962306a36Sopenharmony_ci		 * since multiple calls to destroy_mark is perfectly safe, if
36062306a36Sopenharmony_ci		 * we found a dn_mark already attached to the inode, just sod
36162306a36Sopenharmony_ci		 * off silently as the flush at close time dealt with it.
36262306a36Sopenharmony_ci		 */
36362306a36Sopenharmony_ci		if (dn_mark == new_dn_mark)
36462306a36Sopenharmony_ci			destroy = 1;
36562306a36Sopenharmony_ci		error = 0;
36662306a36Sopenharmony_ci		goto out;
36762306a36Sopenharmony_ci	}
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	__f_setown(filp, task_pid(current), PIDTYPE_TGID, 0);
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci	error = attach_dn(dn, dn_mark, id, fd, filp, mask);
37262306a36Sopenharmony_ci	/* !error means that we attached the dn to the dn_mark, so don't free it */
37362306a36Sopenharmony_ci	if (!error)
37462306a36Sopenharmony_ci		dn = NULL;
37562306a36Sopenharmony_ci	/* -EEXIST means that we didn't add this new dn and used an old one.
37662306a36Sopenharmony_ci	 * that isn't an error (and the unused dn should be freed) */
37762306a36Sopenharmony_ci	else if (error == -EEXIST)
37862306a36Sopenharmony_ci		error = 0;
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	dnotify_recalc_inode_mask(fsn_mark);
38162306a36Sopenharmony_ciout:
38262306a36Sopenharmony_ci	spin_unlock(&fsn_mark->lock);
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci	if (destroy)
38562306a36Sopenharmony_ci		fsnotify_detach_mark(fsn_mark);
38662306a36Sopenharmony_ci	fsnotify_group_unlock(dnotify_group);
38762306a36Sopenharmony_ci	if (destroy)
38862306a36Sopenharmony_ci		fsnotify_free_mark(fsn_mark);
38962306a36Sopenharmony_ci	fsnotify_put_mark(fsn_mark);
39062306a36Sopenharmony_ciout_err:
39162306a36Sopenharmony_ci	if (new_fsn_mark)
39262306a36Sopenharmony_ci		fsnotify_put_mark(new_fsn_mark);
39362306a36Sopenharmony_ci	if (dn)
39462306a36Sopenharmony_ci		kmem_cache_free(dnotify_struct_cache, dn);
39562306a36Sopenharmony_ci	return error;
39662306a36Sopenharmony_ci}
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_cistatic int __init dnotify_init(void)
39962306a36Sopenharmony_ci{
40062306a36Sopenharmony_ci	dnotify_struct_cache = KMEM_CACHE(dnotify_struct,
40162306a36Sopenharmony_ci					  SLAB_PANIC|SLAB_ACCOUNT);
40262306a36Sopenharmony_ci	dnotify_mark_cache = KMEM_CACHE(dnotify_mark, SLAB_PANIC|SLAB_ACCOUNT);
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	dnotify_group = fsnotify_alloc_group(&dnotify_fsnotify_ops,
40562306a36Sopenharmony_ci					     FSNOTIFY_GROUP_NOFS);
40662306a36Sopenharmony_ci	if (IS_ERR(dnotify_group))
40762306a36Sopenharmony_ci		panic("unable to allocate fsnotify group for dnotify\n");
40862306a36Sopenharmony_ci	dnotify_sysctl_init();
40962306a36Sopenharmony_ci	return 0;
41062306a36Sopenharmony_ci}
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_cimodule_init(dnotify_init)
413