fsnotify.c 11.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 *  Copyright (C) 2008 Red Hat, Inc., Eric Paris <eparis@redhat.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <linux/dcache.h>
#include <linux/fs.h>
21
#include <linux/gfp.h>
22 23
#include <linux/init.h>
#include <linux/module.h>
24
#include <linux/mount.h>
25 26 27 28 29
#include <linux/srcu.h>

#include <linux/fsnotify_backend.h>
#include "fsnotify.h"

30 31 32 33 34 35 36 37 38
/*
 * Clear all of the marks on an inode when it is being evicted from core
 */
void __fsnotify_inode_delete(struct inode *inode)
{
	fsnotify_clear_marks_by_inode(inode);
}
EXPORT_SYMBOL_GPL(__fsnotify_inode_delete);

39 40 41 42 43
void __fsnotify_vfsmount_delete(struct vfsmount *mnt)
{
	fsnotify_clear_marks_by_mount(mnt);
}

J
Jan Kara 已提交
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
/**
 * fsnotify_unmount_inodes - an sb is unmounting.  handle any watched inodes.
 * @sb: superblock being unmounted.
 *
 * Called during unmount with no locks held, so needs to be safe against
 * concurrent modifiers. We temporarily drop sb->s_inode_list_lock and CAN block.
 */
void fsnotify_unmount_inodes(struct super_block *sb)
{
	struct inode *inode, *iput_inode = NULL;

	spin_lock(&sb->s_inode_list_lock);
	list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
		/*
		 * We cannot __iget() an inode in state I_FREEING,
		 * I_WILL_FREE, or I_NEW which is fine because by that point
		 * the inode cannot have any associated watches.
		 */
		spin_lock(&inode->i_lock);
		if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) {
			spin_unlock(&inode->i_lock);
			continue;
		}

		/*
		 * If i_count is zero, the inode cannot have any watches and
		 * doing an __iget/iput with MS_ACTIVE clear would actually
		 * evict all inodes with zero i_count from icache which is
		 * unnecessarily violent and may in fact be illegal to do.
		 */
		if (!atomic_read(&inode->i_count)) {
			spin_unlock(&inode->i_lock);
			continue;
		}

		__iget(inode);
		spin_unlock(&inode->i_lock);
		spin_unlock(&sb->s_inode_list_lock);

		if (iput_inode)
			iput(iput_inode);

		/* for each watch, send FS_UNMOUNT and then remove it */
		fsnotify(inode, FS_UNMOUNT, inode, FSNOTIFY_EVENT_INODE, NULL, 0);

		fsnotify_inode_delete(inode);

		iput_inode = inode;

		spin_lock(&sb->s_inode_list_lock);
	}
	spin_unlock(&sb->s_inode_list_lock);

	if (iput_inode)
		iput(iput_inode);
}

E
Eric Paris 已提交
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
/*
 * Given an inode, first check if we care what happens to our children.  Inotify
 * and dnotify both tell their parents about events.  If we care about any event
 * on a child we run all of our children and set a dentry flag saying that the
 * parent cares.  Thus when an event happens on a child it can quickly tell if
 * if there is a need to find a parent and send the event to the parent.
 */
void __fsnotify_update_child_dentry_flags(struct inode *inode)
{
	struct dentry *alias;
	int watched;

	if (!S_ISDIR(inode->i_mode))
		return;

	/* determine if the children should tell inode about their events */
	watched = fsnotify_inode_watches_children(inode);

119
	spin_lock(&inode->i_lock);
E
Eric Paris 已提交
120 121
	/* run all of the dentries associated with this inode.  Since this is a
	 * directory, there damn well better only be one item on this list */
122
	hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
E
Eric Paris 已提交
123 124 125 126 127
		struct dentry *child;

		/* run all of the children of the original inode and fix their
		 * d_flags to indicate parental interest (their parent is the
		 * original inode) */
N
Nick Piggin 已提交
128
		spin_lock(&alias->d_lock);
129
		list_for_each_entry(child, &alias->d_subdirs, d_child) {
E
Eric Paris 已提交
130 131 132
			if (!child->d_inode)
				continue;

N
Nick Piggin 已提交
133
			spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
E
Eric Paris 已提交
134 135 136 137 138 139
			if (watched)
				child->d_flags |= DCACHE_FSNOTIFY_PARENT_WATCHED;
			else
				child->d_flags &= ~DCACHE_FSNOTIFY_PARENT_WATCHED;
			spin_unlock(&child->d_lock);
		}
N
Nick Piggin 已提交
140
		spin_unlock(&alias->d_lock);
E
Eric Paris 已提交
141
	}
142
	spin_unlock(&inode->i_lock);
E
Eric Paris 已提交
143 144 145
}

/* Notify this dentry's parent about a child's events. */
A
Al Viro 已提交
146
int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask)
E
Eric Paris 已提交
147 148 149
{
	struct dentry *parent;
	struct inode *p_inode;
150
	int ret = 0;
E
Eric Paris 已提交
151

152
	if (!dentry)
153
		dentry = path->dentry;
154

E
Eric Paris 已提交
155
	if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED))
156
		return 0;
E
Eric Paris 已提交
157

C
Christoph Hellwig 已提交
158
	parent = dget_parent(dentry);
E
Eric Paris 已提交
159 160
	p_inode = parent->d_inode;

C
Christoph Hellwig 已提交
161 162 163
	if (unlikely(!fsnotify_inode_watches_children(p_inode)))
		__fsnotify_update_child_dentry_flags(p_inode);
	else if (p_inode->i_fsnotify_mask & mask) {
A
Al Viro 已提交
164 165
		struct name_snapshot name;

E
Eric Paris 已提交
166 167 168 169
		/* we are notifying a parent so come up with the new mask which
		 * specifies these are events which came from a child. */
		mask |= FS_EVENT_ON_CHILD;

A
Al Viro 已提交
170
		take_dentry_name_snapshot(&name, dentry);
171
		if (path)
172
			ret = fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH,
A
Al Viro 已提交
173
				       name.name, 0);
174
		else
175
			ret = fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE,
A
Al Viro 已提交
176 177
				       name.name, 0);
		release_dentry_name_snapshot(&name);
E
Eric Paris 已提交
178 179
	}

C
Christoph Hellwig 已提交
180
	dput(parent);
181 182

	return ret;
E
Eric Paris 已提交
183 184 185
}
EXPORT_SYMBOL_GPL(__fsnotify_parent);

186
static int send_to_group(struct inode *to_tell,
187 188
			 struct fsnotify_mark *inode_mark,
			 struct fsnotify_mark *vfsmount_mark,
A
Al Viro 已提交
189
			 __u32 mask, const void *data,
190
			 int data_is, u32 cookie,
191 192
			 const unsigned char *file_name,
			 struct fsnotify_iter_info *iter_info)
193
{
194
	struct fsnotify_group *group = NULL;
195 196
	__u32 inode_test_mask = 0;
	__u32 vfsmount_test_mask = 0;
197

198 199 200 201
	if (unlikely(!inode_mark && !vfsmount_mark)) {
		BUG();
		return 0;
	}
202 203 204 205 206 207 208 209 210 211

	/* clear ignored on inode modification */
	if (mask & FS_MODIFY) {
		if (inode_mark &&
		    !(inode_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))
			inode_mark->ignored_mask = 0;
		if (vfsmount_mark &&
		    !(vfsmount_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))
			vfsmount_mark->ignored_mask = 0;
	}
E
Eric Paris 已提交
212

213 214
	/* does the inode mark tell us to do something? */
	if (inode_mark) {
215
		group = inode_mark->group;
216
		inode_test_mask = (mask & ~FS_EVENT_ON_CHILD);
217 218 219
		inode_test_mask &= inode_mark->mask;
		inode_test_mask &= ~inode_mark->ignored_mask;
	}
220

221 222
	/* does the vfsmount_mark tell us to do something? */
	if (vfsmount_mark) {
223
		vfsmount_test_mask = (mask & ~FS_EVENT_ON_CHILD);
224
		group = vfsmount_mark->group;
225 226 227 228 229 230
		vfsmount_test_mask &= vfsmount_mark->mask;
		vfsmount_test_mask &= ~vfsmount_mark->ignored_mask;
		if (inode_mark)
			vfsmount_test_mask &= ~inode_mark->ignored_mask;
	}

231
	pr_debug("%s: group=%p to_tell=%p mask=%x inode_mark=%p"
232
		 " inode_test_mask=%x vfsmount_mark=%p vfsmount_test_mask=%x"
233
		 " data=%p data_is=%d cookie=%d\n",
234
		 __func__, group, to_tell, mask, inode_mark,
235
		 inode_test_mask, vfsmount_mark, vfsmount_test_mask, data,
236
		 data_is, cookie);
237

238
	if (!inode_test_mask && !vfsmount_test_mask)
239 240
		return 0;

241 242
	return group->ops->handle_event(group, to_tell, inode_mark,
					vfsmount_mark, mask, data, data_is,
243
					file_name, cookie, iter_info);
244 245
}

246 247 248 249 250 251
/*
 * This is the main call to fsnotify.  The VFS calls into hook specific functions
 * in linux/fsnotify.h.  Those functions then in turn call here.  Here will call
 * out to all of the registered fsnotify_group.  Those groups can then use the
 * notification event in whatever means they feel necessary.
 */
A
Al Viro 已提交
252
int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
253
	     const unsigned char *file_name, u32 cookie)
254
{
255
	struct hlist_node *inode_node = NULL, *vfsmount_node = NULL;
256 257
	struct fsnotify_mark *inode_mark = NULL, *vfsmount_mark = NULL;
	struct fsnotify_group *inode_group, *vfsmount_group;
258
	struct fsnotify_mark_connector *inode_conn, *vfsmount_conn;
259
	struct fsnotify_iter_info iter_info;
260
	struct mount *mnt;
261
	int ret = 0;
262 263
	/* global tests shouldn't care about events on child only the specific event */
	__u32 test_mask = (mask & ~FS_EVENT_ON_CHILD);
264

265
	if (data_is == FSNOTIFY_EVENT_PATH)
A
Al Viro 已提交
266
		mnt = real_mount(((const struct path *)data)->mnt);
267 268 269
	else
		mnt = NULL;

270 271 272 273 274 275 276
	/*
	 * Optimization: srcu_read_lock() has a memory barrier which can
	 * be expensive.  It protects walking the *_fsnotify_marks lists.
	 * However, if we do not walk the lists, we do not have to do
	 * SRCU because we have no references to any objects and do not
	 * need SRCU to keep them "alive".
	 */
277 278
	if (!to_tell->i_fsnotify_marks &&
	    (!mnt || !mnt->mnt_fsnotify_marks))
279
		return 0;
280 281 282 283 284 285 286 287 288
	/*
	 * if this is a modify event we may need to clear the ignored masks
	 * otherwise return if neither the inode nor the vfsmount care about
	 * this type of event.
	 */
	if (!(mask & FS_MODIFY) &&
	    !(test_mask & to_tell->i_fsnotify_mask) &&
	    !(mnt && test_mask & mnt->mnt_fsnotify_mask))
		return 0;
289

290
	iter_info.srcu_idx = srcu_read_lock(&fsnotify_mark_srcu);
291

292
	if ((mask & FS_MODIFY) ||
293
	    (test_mask & to_tell->i_fsnotify_mask)) {
294 295
		inode_conn = srcu_dereference(to_tell->i_fsnotify_marks,
					      &fsnotify_mark_srcu);
296 297 298 299
		if (inode_conn)
			inode_node = srcu_dereference(inode_conn->list.first,
						      &fsnotify_mark_srcu);
	}
300

301 302
	if (mnt && ((mask & FS_MODIFY) ||
		    (test_mask & mnt->mnt_fsnotify_mask))) {
303 304
		inode_conn = srcu_dereference(to_tell->i_fsnotify_marks,
					      &fsnotify_mark_srcu);
305 306 307
		if (inode_conn)
			inode_node = srcu_dereference(inode_conn->list.first,
						      &fsnotify_mark_srcu);
308 309
		vfsmount_conn = srcu_dereference(mnt->mnt_fsnotify_marks,
					         &fsnotify_mark_srcu);
310 311 312 313
		if (vfsmount_conn)
			vfsmount_node = srcu_dereference(
						vfsmount_conn->list.first,
						&fsnotify_mark_srcu);
314
	}
315

316 317 318 319 320
	/*
	 * We need to merge inode & vfsmount mark lists so that inode mark
	 * ignore masks are properly reflected for mount mark notifications.
	 * That's why this traversal is so complicated...
	 */
321
	while (inode_node || vfsmount_node) {
322 323 324 325
		inode_group = NULL;
		inode_mark = NULL;
		vfsmount_group = NULL;
		vfsmount_mark = NULL;
326

327 328
		if (inode_node) {
			inode_mark = hlist_entry(srcu_dereference(inode_node, &fsnotify_mark_srcu),
329
						 struct fsnotify_mark, obj_list);
330
			inode_group = inode_mark->group;
E
Eric Paris 已提交
331
		}
332 333 334

		if (vfsmount_node) {
			vfsmount_mark = hlist_entry(srcu_dereference(vfsmount_node, &fsnotify_mark_srcu),
335
						    struct fsnotify_mark, obj_list);
336
			vfsmount_group = vfsmount_mark->group;
E
Eric Paris 已提交
337
		}
338 339 340 341 342 343 344
		/*
		 * Need to protect both marks against freeing so that we can
		 * continue iteration from this place, regardless of which mark
		 * we actually happen to send an event for.
		 */
		iter_info.inode_mark = inode_mark;
		iter_info.vfsmount_mark = vfsmount_mark;
345

346 347 348 349 350 351 352 353 354 355
		if (inode_group && vfsmount_group) {
			int cmp = fsnotify_compare_groups(inode_group,
							  vfsmount_group);
			if (cmp > 0) {
				inode_group = NULL;
				inode_mark = NULL;
			} else if (cmp < 0) {
				vfsmount_group = NULL;
				vfsmount_mark = NULL;
			}
356
		}
357

358
		ret = send_to_group(to_tell, inode_mark, vfsmount_mark, mask,
359 360
				    data, data_is, cookie, file_name,
				    &iter_info);
361

362 363 364
		if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS))
			goto out;

365
		if (inode_group)
366 367
			inode_node = srcu_dereference(inode_node->next,
						      &fsnotify_mark_srcu);
368
		if (vfsmount_group)
369 370
			vfsmount_node = srcu_dereference(vfsmount_node->next,
							 &fsnotify_mark_srcu);
371
	}
372 373
	ret = 0;
out:
374
	srcu_read_unlock(&fsnotify_mark_srcu, iter_info.srcu_idx);
375

376
	return ret;
377 378 379
}
EXPORT_SYMBOL_GPL(fsnotify);

380 381
extern struct kmem_cache *fsnotify_mark_connector_cachep;

382 383
static __init int fsnotify_init(void)
{
384 385
	int ret;

386 387
	BUG_ON(hweight32(ALL_FSNOTIFY_EVENTS) != 23);

388 389 390 391
	ret = init_srcu_struct(&fsnotify_mark_srcu);
	if (ret)
		panic("initializing fsnotify_mark_srcu");

392 393 394
	fsnotify_mark_connector_cachep = KMEM_CACHE(fsnotify_mark_connector,
						    SLAB_PANIC);

395
	return 0;
396
}
397
core_initcall(fsnotify_init);