aboutsummaryrefslogtreecommitdiffstats
path: root/fs/notify/mark.c
diff options
context:
space:
mode:
authorLino Sanfilippo <LinoSanfilippo@gmx.de>2013-07-08 18:59:46 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-09 13:33:20 -0400
commit9756b9187eebb093b9f6a154ecceb67648e53391 (patch)
tree8423dc500a48cd33b0acb7d3cfc592020d5c4d7c /fs/notify/mark.c
parente1e5a9f84e4dbd3567bb8b0d5e79db6e1e5ebc35 (diff)
fsnotify: update comments concerning locking scheme
There have been changes in the locking scheme of fsnotify but the comments in the source code have not been updated yet. This patch corrects this. Signed-off-by: Lino Sanfilippo <LinoSanfilippo@gmx.de> Cc: Eric Paris <eparis@redhat.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/notify/mark.c')
-rw-r--r--fs/notify/mark.c50
1 files changed, 22 insertions, 28 deletions
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index fc6b49bf7360..923fe4a5f503 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -20,28 +20,29 @@
20 * fsnotify inode mark locking/lifetime/and refcnting 20 * fsnotify inode mark locking/lifetime/and refcnting
21 * 21 *
22 * REFCNT: 22 * REFCNT:
23 * The mark->refcnt tells how many "things" in the kernel currently are 23 * The group->recnt and mark->refcnt tell how many "things" in the kernel
24 * referencing this object. The object typically will live inside the kernel 24 * currently are referencing the objects. Both kind of objects typically will
25 * with a refcnt of 2, one for each list it is on (i_list, g_list). Any task 25 * live inside the kernel with a refcnt of 2, one for its creation and one for
26 * which can find this object holding the appropriete locks, can take a reference 26 * the reference a group and a mark hold to each other.
27 * and the object itself is guaranteed to survive until the reference is dropped. 27 * If you are holding the appropriate locks, you can take a reference and the
28 * object itself is guaranteed to survive until the reference is dropped.
28 * 29 *
29 * LOCKING: 30 * LOCKING:
30 * There are 3 spinlocks involved with fsnotify inode marks and they MUST 31 * There are 3 locks involved with fsnotify inode marks and they MUST be taken
31 * be taken in order as follows: 32 * in order as follows:
32 * 33 *
34 * group->mark_mutex
33 * mark->lock 35 * mark->lock
34 * group->mark_lock
35 * inode->i_lock 36 * inode->i_lock
36 * 37 *
37 * mark->lock protects 2 things, mark->group and mark->inode. You must hold 38 * group->mark_mutex protects the marks_list anchored inside a given group and
38 * that lock to dereference either of these things (they could be NULL even with 39 * each mark is hooked via the g_list. It also protects the groups private
39 * the lock) 40 * data (i.e group limits).
40 * 41
41 * group->mark_lock protects the marks_list anchored inside a given group 42 * mark->lock protects the marks attributes like its masks and flags.
42 * and each mark is hooked via the g_list. It also sorta protects the 43 * Furthermore it protects the access to a reference of the group that the mark
43 * free_g_list, which when used is anchored by a private list on the stack of the 44 * is assigned to as well as the access to a reference of the inode/vfsmount
44 * task which held the group->mark_lock. 45 * that is being watched by the mark.
45 * 46 *
46 * inode->i_lock protects the i_fsnotify_marks list anchored inside a 47 * inode->i_lock protects the i_fsnotify_marks list anchored inside a
47 * given inode and each mark is hooked via the i_list. (and sorta the 48 * given inode and each mark is hooked via the i_list. (and sorta the
@@ -64,18 +65,11 @@
64 * inode. We take i_lock and walk the i_fsnotify_marks safely. For each 65 * inode. We take i_lock and walk the i_fsnotify_marks safely. For each
65 * mark on the list we take a reference (so the mark can't disappear under us). 66 * mark on the list we take a reference (so the mark can't disappear under us).
66 * We remove that mark form the inode's list of marks and we add this mark to a 67 * We remove that mark form the inode's list of marks and we add this mark to a
67 * private list anchored on the stack using i_free_list; At this point we no 68 * private list anchored on the stack using i_free_list; we walk i_free_list
68 * longer fear anything finding the mark using the inode's list of marks. 69 * and before we destroy the mark we make sure that we dont race with a
69 * 70 * concurrent destroy_group by getting a ref to the marks group and taking the
70 * We can safely and locklessly run the private list on the stack of everything 71 * groups mutex.
71 * we just unattached from the original inode. For each mark on the private list 72
72 * we grab the mark-> and can thus dereference mark->group and mark->inode. If
73 * we see the group and inode are not NULL we take those locks. Now holding all
74 * 3 locks we can completely remove the mark from other tasks finding it in the
75 * future. Remember, 10 things might already be referencing this mark, but they
76 * better be holding a ref. We drop our reference we took before we unhooked it
77 * from the inode. When the ref hits 0 we can free the mark.
78 *
79 * Very similarly for freeing by group, except we use free_g_list. 73 * Very similarly for freeing by group, except we use free_g_list.
80 * 74 *
81 * This has the very interesting property of being able to run concurrently with 75 * This has the very interesting property of being able to run concurrently with