13e0a4e85SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2272eb014SEric Paris /*
3272eb014SEric Paris * Directory notifications for Linux.
4272eb014SEric Paris *
5272eb014SEric Paris * Copyright (C) 2000,2001,2002 Stephen Rothwell
6272eb014SEric Paris *
73c5119c0SEric Paris * Copyright (C) 2009 Eric Paris <Red Hat Inc>
83c5119c0SEric Paris * dnotify was largly rewritten to use the new fsnotify infrastructure
9272eb014SEric Paris */
10272eb014SEric Paris #include <linux/fs.h>
11272eb014SEric Paris #include <linux/module.h>
12272eb014SEric Paris #include <linux/sched.h>
1301919134SEric W. Biederman #include <linux/sched/signal.h>
14272eb014SEric Paris #include <linux/dnotify.h>
15272eb014SEric Paris #include <linux/init.h>
16ac5656d8SAaron Goidel #include <linux/security.h>
17272eb014SEric Paris #include <linux/spinlock.h>
18272eb014SEric Paris #include <linux/slab.h>
19272eb014SEric Paris #include <linux/fdtable.h>
203c5119c0SEric Paris #include <linux/fsnotify_backend.h>
21272eb014SEric Paris
2249a4de75SXiaoming Ni static int dir_notify_enable __read_mostly = 1;
2349a4de75SXiaoming Ni #ifdef CONFIG_SYSCTL
2449a4de75SXiaoming Ni static struct ctl_table dnotify_sysctls[] = {
2549a4de75SXiaoming Ni {
2649a4de75SXiaoming Ni .procname = "dir-notify-enable",
2749a4de75SXiaoming Ni .data = &dir_notify_enable,
2849a4de75SXiaoming Ni .maxlen = sizeof(int),
2949a4de75SXiaoming Ni .mode = 0644,
3049a4de75SXiaoming Ni .proc_handler = proc_dointvec,
3149a4de75SXiaoming Ni },
3249a4de75SXiaoming Ni {}
3349a4de75SXiaoming Ni };
dnotify_sysctl_init(void)3449a4de75SXiaoming Ni static void __init dnotify_sysctl_init(void)
3549a4de75SXiaoming Ni {
3649a4de75SXiaoming Ni register_sysctl_init("fs", dnotify_sysctls);
3749a4de75SXiaoming Ni }
3849a4de75SXiaoming Ni #else
3949a4de75SXiaoming Ni #define dnotify_sysctl_init() do { } while (0)
4049a4de75SXiaoming Ni #endif
41272eb014SEric Paris
423c5119c0SEric Paris static struct kmem_cache *dnotify_struct_cache __read_mostly;
43ef5e2b78SEric Paris static struct kmem_cache *dnotify_mark_cache __read_mostly;
443c5119c0SEric Paris static struct fsnotify_group *dnotify_group __read_mostly;
45272eb014SEric Paris
463c5119c0SEric Paris /*
47e61ce867SEric Paris * dnotify will attach one of these to each inode (i_fsnotify_marks) which
483c5119c0SEric Paris * is being watched by dnotify. If multiple userspace applications are watching
493c5119c0SEric Paris * the same directory with dnotify their information is chained in dn
503c5119c0SEric Paris */
51ef5e2b78SEric Paris struct dnotify_mark {
52ef5e2b78SEric Paris struct fsnotify_mark fsn_mark;
53272eb014SEric Paris struct dnotify_struct *dn;
543c5119c0SEric Paris };
55272eb014SEric Paris
563c5119c0SEric Paris /*
573c5119c0SEric Paris * When a process starts or stops watching an inode the set of events which
583c5119c0SEric Paris * dnotify cares about for that inode may change. This function runs the
593c5119c0SEric Paris * list of everything receiving dnotify events about this directory and calculates
603c5119c0SEric Paris * the set of all those events. After it updates what dnotify is interested in
613c5119c0SEric Paris * it calls the fsnotify function so it can update the set of all events relevant
623c5119c0SEric Paris * to this inode.
633c5119c0SEric Paris */
dnotify_recalc_inode_mask(struct fsnotify_mark * fsn_mark)64ef5e2b78SEric Paris static void dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark)
653c5119c0SEric Paris {
6666d2b81bSJan Kara __u32 new_mask = 0;
673c5119c0SEric Paris struct dnotify_struct *dn;
68ef5e2b78SEric Paris struct dnotify_mark *dn_mark = container_of(fsn_mark,
69ef5e2b78SEric Paris struct dnotify_mark,
70ef5e2b78SEric Paris fsn_mark);
713c5119c0SEric Paris
72ef5e2b78SEric Paris assert_spin_locked(&fsn_mark->lock);
733c5119c0SEric Paris
74ef5e2b78SEric Paris for (dn = dn_mark->dn; dn != NULL; dn = dn->dn_next)
753c5119c0SEric Paris new_mask |= (dn->dn_mask & ~FS_DN_MULTISHOT);
7666d2b81bSJan Kara if (fsn_mark->mask == new_mask)
77272eb014SEric Paris return;
7866d2b81bSJan Kara fsn_mark->mask = new_mask;
793c5119c0SEric Paris
80a242677bSJan Kara fsnotify_recalc_mask(fsn_mark->connector);
81272eb014SEric Paris }
82272eb014SEric Paris
833c5119c0SEric Paris /*
843c5119c0SEric Paris * Mains fsnotify call where events are delivered to dnotify.
853c5119c0SEric Paris * Find the dnotify mark on the relevant inode, run the list of dnotify structs
863c5119c0SEric Paris * on that mark and determine which of them has expressed interest in receiving
873c5119c0SEric Paris * events of this type. When found send the correct process and signal and
883c5119c0SEric Paris * destroy the dnotify struct if it was not registered to receive multiple
893c5119c0SEric Paris * events.
903c5119c0SEric Paris */
dnotify_handle_event(struct fsnotify_mark * inode_mark,u32 mask,struct inode * inode,struct inode * dir,const struct qstr * name,u32 cookie)91b9a1b977SAmir Goldstein static int dnotify_handle_event(struct fsnotify_mark *inode_mark, u32 mask,
92b9a1b977SAmir Goldstein struct inode *inode, struct inode *dir,
93950cc0d2SAmir Goldstein const struct qstr *name, u32 cookie)
94272eb014SEric Paris {
95ef5e2b78SEric Paris struct dnotify_mark *dn_mark;
96272eb014SEric Paris struct dnotify_struct *dn;
97272eb014SEric Paris struct dnotify_struct **prev;
98272eb014SEric Paris struct fown_struct *fown;
997053aee2SJan Kara __u32 test_mask = mask & ~FS_EVENT_ON_CHILD;
100272eb014SEric Paris
101b9a1b977SAmir Goldstein /* not a dir, dnotify doesn't care */
102b9a1b977SAmir Goldstein if (!dir && !(mask & FS_ISDIR))
103b9a1b977SAmir Goldstein return 0;
104b9a1b977SAmir Goldstein
105ce8f76fbSEric Paris dn_mark = container_of(inode_mark, struct dnotify_mark, fsn_mark);
1063c5119c0SEric Paris
107ce8f76fbSEric Paris spin_lock(&inode_mark->lock);
108ef5e2b78SEric Paris prev = &dn_mark->dn;
109272eb014SEric Paris while ((dn = *prev) != NULL) {
11094552684SAndreas Gruenbacher if ((dn->dn_mask & test_mask) == 0) {
111272eb014SEric Paris prev = &dn->dn_next;
112272eb014SEric Paris continue;
113272eb014SEric Paris }
114272eb014SEric Paris fown = &dn->dn_filp->f_owner;
115272eb014SEric Paris send_sigio(fown, dn->dn_fd, POLL_MSG);
1163c5119c0SEric Paris if (dn->dn_mask & FS_DN_MULTISHOT)
117272eb014SEric Paris prev = &dn->dn_next;
118272eb014SEric Paris else {
119272eb014SEric Paris *prev = dn->dn_next;
1203c5119c0SEric Paris kmem_cache_free(dnotify_struct_cache, dn);
121ce8f76fbSEric Paris dnotify_recalc_inode_mask(inode_mark);
122272eb014SEric Paris }
123272eb014SEric Paris }
124272eb014SEric Paris
125ce8f76fbSEric Paris spin_unlock(&inode_mark->lock);
1263c5119c0SEric Paris
1273c5119c0SEric Paris return 0;
1283c5119c0SEric Paris }
129272eb014SEric Paris
dnotify_free_mark(struct fsnotify_mark * fsn_mark)130ef5e2b78SEric Paris static void dnotify_free_mark(struct fsnotify_mark *fsn_mark)
1313c5119c0SEric Paris {
132ef5e2b78SEric Paris struct dnotify_mark *dn_mark = container_of(fsn_mark,
133ef5e2b78SEric Paris struct dnotify_mark,
134ef5e2b78SEric Paris fsn_mark);
1353c5119c0SEric Paris
136ef5e2b78SEric Paris BUG_ON(dn_mark->dn);
1373c5119c0SEric Paris
138ef5e2b78SEric Paris kmem_cache_free(dnotify_mark_cache, dn_mark);
1393c5119c0SEric Paris }
1403c5119c0SEric Paris
141c9ea9df3SBhumika Goyal static const struct fsnotify_ops dnotify_fsnotify_ops = {
142b9a1b977SAmir Goldstein .handle_inode_event = dnotify_handle_event,
143054c636eSJan Kara .free_mark = dnotify_free_mark,
1443c5119c0SEric Paris };
1453c5119c0SEric Paris
1463c5119c0SEric Paris /*
1473c5119c0SEric Paris * Called every time a file is closed. Looks first for a dnotify mark on the
148e61ce867SEric Paris * inode. If one is found run all of the ->dn structures attached to that
1493c5119c0SEric Paris * mark for one relevant to this process closing the file and remove that
1503c5119c0SEric Paris * dnotify_struct. If that was the last dnotify_struct also remove the
151e61ce867SEric Paris * fsnotify_mark.
1523c5119c0SEric Paris */
dnotify_flush(struct file * filp,fl_owner_t id)1533c5119c0SEric Paris void dnotify_flush(struct file *filp, fl_owner_t id)
1543c5119c0SEric Paris {
155ef5e2b78SEric Paris struct fsnotify_mark *fsn_mark;
156ef5e2b78SEric Paris struct dnotify_mark *dn_mark;
1573c5119c0SEric Paris struct dnotify_struct *dn;
1583c5119c0SEric Paris struct dnotify_struct **prev;
1593c5119c0SEric Paris struct inode *inode;
1604712e722SJan Kara bool free = false;
1613c5119c0SEric Paris
162496ad9aaSAl Viro inode = file_inode(filp);
1633c5119c0SEric Paris if (!S_ISDIR(inode->i_mode))
164272eb014SEric Paris return;
165272eb014SEric Paris
166b1362edfSJan Kara fsn_mark = fsnotify_find_mark(&inode->i_fsnotify_marks, dnotify_group);
167ef5e2b78SEric Paris if (!fsn_mark)
1683c5119c0SEric Paris return;
169ef5e2b78SEric Paris dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark);
1703c5119c0SEric Paris
171aabb45fdSAmir Goldstein fsnotify_group_lock(dnotify_group);
1723c5119c0SEric Paris
173ef5e2b78SEric Paris spin_lock(&fsn_mark->lock);
174ef5e2b78SEric Paris prev = &dn_mark->dn;
1753c5119c0SEric Paris while ((dn = *prev) != NULL) {
1763c5119c0SEric Paris if ((dn->dn_owner == id) && (dn->dn_filp == filp)) {
1773c5119c0SEric Paris *prev = dn->dn_next;
1783c5119c0SEric Paris kmem_cache_free(dnotify_struct_cache, dn);
179ef5e2b78SEric Paris dnotify_recalc_inode_mask(fsn_mark);
1803c5119c0SEric Paris break;
1813c5119c0SEric Paris }
1823c5119c0SEric Paris prev = &dn->dn_next;
1833c5119c0SEric Paris }
1843c5119c0SEric Paris
185ef5e2b78SEric Paris spin_unlock(&fsn_mark->lock);
1863c5119c0SEric Paris
18752f85729SLino Sanfilippo /* nothing else could have found us thanks to the dnotify_groups
18852f85729SLino Sanfilippo mark_mutex */
1894712e722SJan Kara if (dn_mark->dn == NULL) {
1904712e722SJan Kara fsnotify_detach_mark(fsn_mark);
1914712e722SJan Kara free = true;
1924712e722SJan Kara }
1933c5119c0SEric Paris
194aabb45fdSAmir Goldstein fsnotify_group_unlock(dnotify_group);
1953c5119c0SEric Paris
1964712e722SJan Kara if (free)
1974712e722SJan Kara fsnotify_free_mark(fsn_mark);
198ef5e2b78SEric Paris fsnotify_put_mark(fsn_mark);
1993c5119c0SEric Paris }
2003c5119c0SEric Paris
2013c5119c0SEric Paris /* this conversion is done only at watch creation */
convert_arg(unsigned int arg)202*f4ae4081SLuca Vizzarro static __u32 convert_arg(unsigned int arg)
2033c5119c0SEric Paris {
2043c5119c0SEric Paris __u32 new_mask = FS_EVENT_ON_CHILD;
2053c5119c0SEric Paris
2063c5119c0SEric Paris if (arg & DN_MULTISHOT)
2073c5119c0SEric Paris new_mask |= FS_DN_MULTISHOT;
2083c5119c0SEric Paris if (arg & DN_DELETE)
2093c5119c0SEric Paris new_mask |= (FS_DELETE | FS_MOVED_FROM);
2103c5119c0SEric Paris if (arg & DN_MODIFY)
2113c5119c0SEric Paris new_mask |= FS_MODIFY;
2123c5119c0SEric Paris if (arg & DN_ACCESS)
2133c5119c0SEric Paris new_mask |= FS_ACCESS;
2143c5119c0SEric Paris if (arg & DN_ATTRIB)
2153c5119c0SEric Paris new_mask |= FS_ATTRIB;
2163c5119c0SEric Paris if (arg & DN_RENAME)
217e54183faSAmir Goldstein new_mask |= FS_RENAME;
2183c5119c0SEric Paris if (arg & DN_CREATE)
2193c5119c0SEric Paris new_mask |= (FS_CREATE | FS_MOVED_TO);
2203c5119c0SEric Paris
2213c5119c0SEric Paris return new_mask;
2223c5119c0SEric Paris }
2233c5119c0SEric Paris
2243c5119c0SEric Paris /*
2253c5119c0SEric Paris * If multiple processes watch the same inode with dnotify there is only one
226e61ce867SEric Paris * dnotify mark in inode->i_fsnotify_marks but we chain a dnotify_struct
2273c5119c0SEric Paris * onto that mark. This function either attaches the new dnotify_struct onto
2283c5119c0SEric Paris * that list, or it |= the mask onto an existing dnofiy_struct.
2293c5119c0SEric Paris */
attach_dn(struct dnotify_struct * dn,struct dnotify_mark * dn_mark,fl_owner_t id,int fd,struct file * filp,__u32 mask)230ef5e2b78SEric Paris static int attach_dn(struct dnotify_struct *dn, struct dnotify_mark *dn_mark,
2313c5119c0SEric Paris fl_owner_t id, int fd, struct file *filp, __u32 mask)
2323c5119c0SEric Paris {
2333c5119c0SEric Paris struct dnotify_struct *odn;
2343c5119c0SEric Paris
235ef5e2b78SEric Paris odn = dn_mark->dn;
2363c5119c0SEric Paris while (odn != NULL) {
2373c5119c0SEric Paris /* adding more events to existing dnofiy_struct? */
2383c5119c0SEric Paris if ((odn->dn_owner == id) && (odn->dn_filp == filp)) {
2393c5119c0SEric Paris odn->dn_fd = fd;
2403c5119c0SEric Paris odn->dn_mask |= mask;
2413c5119c0SEric Paris return -EEXIST;
2423c5119c0SEric Paris }
2433c5119c0SEric Paris odn = odn->dn_next;
2443c5119c0SEric Paris }
2453c5119c0SEric Paris
2463c5119c0SEric Paris dn->dn_mask = mask;
2473c5119c0SEric Paris dn->dn_fd = fd;
2483c5119c0SEric Paris dn->dn_filp = filp;
2493c5119c0SEric Paris dn->dn_owner = id;
250ef5e2b78SEric Paris dn->dn_next = dn_mark->dn;
251ef5e2b78SEric Paris dn_mark->dn = dn;
2523c5119c0SEric Paris
2533c5119c0SEric Paris return 0;
2543c5119c0SEric Paris }
2553c5119c0SEric Paris
2563c5119c0SEric Paris /*
2573c5119c0SEric Paris * When a process calls fcntl to attach a dnotify watch to a directory it ends
2583c5119c0SEric Paris * up here. Allocate both a mark for fsnotify to add and a dnotify_struct to be
2593c5119c0SEric Paris * attached to the fsnotify_mark.
2603c5119c0SEric Paris */
fcntl_dirnotify(int fd,struct file * filp,unsigned int arg)261*f4ae4081SLuca Vizzarro int fcntl_dirnotify(int fd, struct file *filp, unsigned int arg)
2623c5119c0SEric Paris {
263ef5e2b78SEric Paris struct dnotify_mark *new_dn_mark, *dn_mark;
264ef5e2b78SEric Paris struct fsnotify_mark *new_fsn_mark, *fsn_mark;
2653c5119c0SEric Paris struct dnotify_struct *dn;
2663c5119c0SEric Paris struct inode *inode;
2673c5119c0SEric Paris fl_owner_t id = current->files;
2683c5119c0SEric Paris struct file *f;
2693c5119c0SEric Paris int destroy = 0, error = 0;
2703c5119c0SEric Paris __u32 mask;
2713c5119c0SEric Paris
2723c5119c0SEric Paris /* we use these to tell if we need to kfree */
273ef5e2b78SEric Paris new_fsn_mark = NULL;
2743c5119c0SEric Paris dn = NULL;
2753c5119c0SEric Paris
2763c5119c0SEric Paris if (!dir_notify_enable) {
2773c5119c0SEric Paris error = -EINVAL;
2783c5119c0SEric Paris goto out_err;
2793c5119c0SEric Paris }
2803c5119c0SEric Paris
2813c5119c0SEric Paris /* a 0 mask means we are explicitly removing the watch */
2823c5119c0SEric Paris if ((arg & ~DN_MULTISHOT) == 0) {
2833c5119c0SEric Paris dnotify_flush(filp, id);
2843c5119c0SEric Paris error = 0;
2853c5119c0SEric Paris goto out_err;
2863c5119c0SEric Paris }
2873c5119c0SEric Paris
2883c5119c0SEric Paris /* dnotify only works on directories */
289496ad9aaSAl Viro inode = file_inode(filp);
2903c5119c0SEric Paris if (!S_ISDIR(inode->i_mode)) {
2913c5119c0SEric Paris error = -ENOTDIR;
2923c5119c0SEric Paris goto out_err;
2933c5119c0SEric Paris }
2943c5119c0SEric Paris
295ac5656d8SAaron Goidel /*
296ac5656d8SAaron Goidel * convert the userspace DN_* "arg" to the internal FS_*
297ac5656d8SAaron Goidel * defined in fsnotify
298ac5656d8SAaron Goidel */
299ac5656d8SAaron Goidel mask = convert_arg(arg);
300ac5656d8SAaron Goidel
301ac5656d8SAaron Goidel error = security_path_notify(&filp->f_path, mask,
302ac5656d8SAaron Goidel FSNOTIFY_OBJ_TYPE_INODE);
303ac5656d8SAaron Goidel if (error)
304ac5656d8SAaron Goidel goto out_err;
305ac5656d8SAaron Goidel
3063c5119c0SEric Paris /* expect most fcntl to add new rather than augment old */
3073c5119c0SEric Paris dn = kmem_cache_alloc(dnotify_struct_cache, GFP_KERNEL);
3083c5119c0SEric Paris if (!dn) {
3093c5119c0SEric Paris error = -ENOMEM;
3103c5119c0SEric Paris goto out_err;
3113c5119c0SEric Paris }
3123c5119c0SEric Paris
3133c5119c0SEric Paris /* new fsnotify mark, we expect most fcntl calls to add a new mark */
314ef5e2b78SEric Paris new_dn_mark = kmem_cache_alloc(dnotify_mark_cache, GFP_KERNEL);
315ef5e2b78SEric Paris if (!new_dn_mark) {
3163c5119c0SEric Paris error = -ENOMEM;
3173c5119c0SEric Paris goto out_err;
3183c5119c0SEric Paris }
3193c5119c0SEric Paris
320ef5e2b78SEric Paris /* set up the new_fsn_mark and new_dn_mark */
321ef5e2b78SEric Paris new_fsn_mark = &new_dn_mark->fsn_mark;
322054c636eSJan Kara fsnotify_init_mark(new_fsn_mark, dnotify_group);
323ef5e2b78SEric Paris new_fsn_mark->mask = mask;
324ef5e2b78SEric Paris new_dn_mark->dn = NULL;
3253c5119c0SEric Paris
3263c5119c0SEric Paris /* this is needed to prevent the fcntl/close race described below */
327aabb45fdSAmir Goldstein fsnotify_group_lock(dnotify_group);
3283c5119c0SEric Paris
329ef5e2b78SEric Paris /* add the new_fsn_mark or find an old one. */
330b1362edfSJan Kara fsn_mark = fsnotify_find_mark(&inode->i_fsnotify_marks, dnotify_group);
331ef5e2b78SEric Paris if (fsn_mark) {
332ef5e2b78SEric Paris dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark);
333ef5e2b78SEric Paris spin_lock(&fsn_mark->lock);
334272eb014SEric Paris } else {
335b249f5beSAmir Goldstein error = fsnotify_add_inode_mark_locked(new_fsn_mark, inode, 0);
336b3a00660SJan Kara if (error) {
337aabb45fdSAmir Goldstein fsnotify_group_unlock(dnotify_group);
338b3a00660SJan Kara goto out_err;
339b3a00660SJan Kara }
340ef5e2b78SEric Paris spin_lock(&new_fsn_mark->lock);
341ef5e2b78SEric Paris fsn_mark = new_fsn_mark;
342ef5e2b78SEric Paris dn_mark = new_dn_mark;
343ef5e2b78SEric Paris /* we used new_fsn_mark, so don't free it */
344ef5e2b78SEric Paris new_fsn_mark = NULL;
345272eb014SEric Paris }
3463c5119c0SEric Paris
3473c5119c0SEric Paris rcu_read_lock();
348460b4f81SEric W. Biederman f = lookup_fd_rcu(fd);
3493c5119c0SEric Paris rcu_read_unlock();
3503c5119c0SEric Paris
3513c5119c0SEric Paris /* if (f != filp) means that we lost a race and another task/thread
3523c5119c0SEric Paris * actually closed the fd we are still playing with before we grabbed
35352f85729SLino Sanfilippo * the dnotify_groups mark_mutex and fsn_mark->lock. Since closing the
35452f85729SLino Sanfilippo * fd is the only time we clean up the marks we need to get our mark
35552f85729SLino Sanfilippo * off the list. */
3563c5119c0SEric Paris if (f != filp) {
3573c5119c0SEric Paris /* if we added ourselves, shoot ourselves, it's possible that
358ef5e2b78SEric Paris * the flush actually did shoot this fsn_mark. That's fine too
3593c5119c0SEric Paris * since multiple calls to destroy_mark is perfectly safe, if
360ef5e2b78SEric Paris * we found a dn_mark already attached to the inode, just sod
3613c5119c0SEric Paris * off silently as the flush at close time dealt with it.
3623c5119c0SEric Paris */
363ef5e2b78SEric Paris if (dn_mark == new_dn_mark)
3643c5119c0SEric Paris destroy = 1;
365b3a00660SJan Kara error = 0;
3663c5119c0SEric Paris goto out;
367272eb014SEric Paris }
3683c5119c0SEric Paris
36901919134SEric W. Biederman __f_setown(filp, task_pid(current), PIDTYPE_TGID, 0);
3703c5119c0SEric Paris
371ef5e2b78SEric Paris error = attach_dn(dn, dn_mark, id, fd, filp, mask);
372ef5e2b78SEric Paris /* !error means that we attached the dn to the dn_mark, so don't free it */
3733c5119c0SEric Paris if (!error)
3743c5119c0SEric Paris dn = NULL;
3753c5119c0SEric Paris /* -EEXIST means that we didn't add this new dn and used an old one.
3763c5119c0SEric Paris * that isn't an error (and the unused dn should be freed) */
3773c5119c0SEric Paris else if (error == -EEXIST)
3783c5119c0SEric Paris error = 0;
3793c5119c0SEric Paris
380ef5e2b78SEric Paris dnotify_recalc_inode_mask(fsn_mark);
3813c5119c0SEric Paris out:
382ef5e2b78SEric Paris spin_unlock(&fsn_mark->lock);
3833c5119c0SEric Paris
3843c5119c0SEric Paris if (destroy)
3854712e722SJan Kara fsnotify_detach_mark(fsn_mark);
386aabb45fdSAmir Goldstein fsnotify_group_unlock(dnotify_group);
3874712e722SJan Kara if (destroy)
3884712e722SJan Kara fsnotify_free_mark(fsn_mark);
389ef5e2b78SEric Paris fsnotify_put_mark(fsn_mark);
3903c5119c0SEric Paris out_err:
391ef5e2b78SEric Paris if (new_fsn_mark)
392ef5e2b78SEric Paris fsnotify_put_mark(new_fsn_mark);
3933c5119c0SEric Paris if (dn)
3943c5119c0SEric Paris kmem_cache_free(dnotify_struct_cache, dn);
3953c5119c0SEric Paris return error;
3963c5119c0SEric Paris }
397272eb014SEric Paris
dnotify_init(void)398272eb014SEric Paris static int __init dnotify_init(void)
399272eb014SEric Paris {
400d46eb14bSShakeel Butt dnotify_struct_cache = KMEM_CACHE(dnotify_struct,
401d46eb14bSShakeel Butt SLAB_PANIC|SLAB_ACCOUNT);
402d46eb14bSShakeel Butt dnotify_mark_cache = KMEM_CACHE(dnotify_mark, SLAB_PANIC|SLAB_ACCOUNT);
4033c5119c0SEric Paris
404aabb45fdSAmir Goldstein dnotify_group = fsnotify_alloc_group(&dnotify_fsnotify_ops,
405aabb45fdSAmir Goldstein FSNOTIFY_GROUP_NOFS);
4063c5119c0SEric Paris if (IS_ERR(dnotify_group))
4073c5119c0SEric Paris panic("unable to allocate fsnotify group for dnotify\n");
40849a4de75SXiaoming Ni dnotify_sysctl_init();
409272eb014SEric Paris return 0;
410272eb014SEric Paris }
411272eb014SEric Paris
412272eb014SEric Paris module_init(dnotify_init)
413