Blame view

fs/notify/inode_mark.c 6.32 KB
3be25f49b   Eric Paris   fsnotify: add mar...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   *  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.
   */
3be25f49b   Eric Paris   fsnotify: add mar...
18
19
20
21
22
  #include <linux/fs.h>
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/mutex.h>
3be25f49b   Eric Paris   fsnotify: add mar...
23
  #include <linux/spinlock.h>
60063497a   Arun Sharma   atomic: use <linu...
24
  #include <linux/atomic.h>
3be25f49b   Eric Paris   fsnotify: add mar...
25
26
27
  
  #include <linux/fsnotify_backend.h>
  #include "fsnotify.h"
55fa6091d   Dave Chinner   fs: move i_sb_lis...
28
  #include "../internal.h"
3be25f49b   Eric Paris   fsnotify: add mar...
29
  /*
3be25f49b   Eric Paris   fsnotify: add mar...
30
31
32
33
34
35
   * Recalculate the inode->i_fsnotify_mask, or the mask of all FS_* event types
   * any notifier is interested in hearing for this inode.
   */
  void fsnotify_recalc_inode_mask(struct inode *inode)
  {
  	spin_lock(&inode->i_lock);
0809ab69a   Jan Kara   fsnotify: unify i...
36
  	inode->i_fsnotify_mask = fsnotify_recalc_mask(&inode->i_fsnotify_marks);
3be25f49b   Eric Paris   fsnotify: add mar...
37
  	spin_unlock(&inode->i_lock);
c28f7e56e   Eric Paris   fsnotify: parent ...
38
39
  
  	__fsnotify_update_child_dentry_flags(inode);
3be25f49b   Eric Paris   fsnotify: add mar...
40
  }
5444e2981   Eric Paris   fsnotify: split g...
41
  void fsnotify_destroy_inode_mark(struct fsnotify_mark *mark)
3be25f49b   Eric Paris   fsnotify: add mar...
42
  {
0809ab69a   Jan Kara   fsnotify: unify i...
43
  	struct inode *inode = mark->inode;
3be25f49b   Eric Paris   fsnotify: add mar...
44

986ab0980   Lino Sanfilippo   fsnotify: use a m...
45
  	BUG_ON(!mutex_is_locked(&mark->group->mark_mutex));
5444e2981   Eric Paris   fsnotify: split g...
46
  	assert_spin_locked(&mark->lock);
3be25f49b   Eric Paris   fsnotify: add mar...
47

3be25f49b   Eric Paris   fsnotify: add mar...
48
  	spin_lock(&inode->i_lock);
0809ab69a   Jan Kara   fsnotify: unify i...
49
50
  	hlist_del_init_rcu(&mark->obj_list);
  	mark->inode = NULL;
3be25f49b   Eric Paris   fsnotify: add mar...
51
52
  
  	/*
e61ce8673   Eric Paris   fsnotify: rename ...
53
  	 * this mark is now off the inode->i_fsnotify_marks list and we
3be25f49b   Eric Paris   fsnotify: add mar...
54
55
56
  	 * hold the inode->i_lock, so this is the perfect time to update the
  	 * inode->i_fsnotify_mask
  	 */
0809ab69a   Jan Kara   fsnotify: unify i...
57
  	inode->i_fsnotify_mask = fsnotify_recalc_mask(&inode->i_fsnotify_marks);
3be25f49b   Eric Paris   fsnotify: add mar...
58
  	spin_unlock(&inode->i_lock);
3be25f49b   Eric Paris   fsnotify: add mar...
59
60
61
  }
  
  /*
4d92604cc   Eric Paris   fanotify: clear a...
62
63
64
65
66
67
68
69
   * Given a group clear all of the inode marks associated with that group.
   */
  void fsnotify_clear_inode_marks_by_group(struct fsnotify_group *group)
  {
  	fsnotify_clear_marks_by_group_flags(group, FSNOTIFY_MARK_FLAG_INODE);
  }
  
  /*
3be25f49b   Eric Paris   fsnotify: add mar...
70
71
72
   * given a group and inode, find the mark associated with that combination.
   * if found take a reference to that mark and return it, else return NULL
   */
5444e2981   Eric Paris   fsnotify: split g...
73
74
  struct fsnotify_mark *fsnotify_find_inode_mark(struct fsnotify_group *group,
  					       struct inode *inode)
355660870   Andreas Gruenbacher   fsnotify: take in...
75
76
77
78
  {
  	struct fsnotify_mark *mark;
  
  	spin_lock(&inode->i_lock);
0809ab69a   Jan Kara   fsnotify: unify i...
79
  	mark = fsnotify_find_mark(&inode->i_fsnotify_marks, group);
355660870   Andreas Gruenbacher   fsnotify: take in...
80
81
82
83
  	spin_unlock(&inode->i_lock);
  
  	return mark;
  }
3be25f49b   Eric Paris   fsnotify: add mar...
84

3be25f49b   Eric Paris   fsnotify: add mar...
85
  /*
90b1e7a57   Eric Paris   fsnotify: allow m...
86
87
88
89
90
   * If we are setting a mark mask on an inode mark we should pin the inode
   * in memory.
   */
  void fsnotify_set_inode_mark_mask_locked(struct fsnotify_mark *mark,
  					 __u32 mask)
3be25f49b   Eric Paris   fsnotify: add mar...
91
  {
90b1e7a57   Eric Paris   fsnotify: allow m...
92
93
94
95
96
  	struct inode *inode;
  
  	assert_spin_locked(&mark->lock);
  
  	if (mask &&
0809ab69a   Jan Kara   fsnotify: unify i...
97
  	    mark->inode &&
90b1e7a57   Eric Paris   fsnotify: allow m...
98
99
  	    !(mark->flags & FSNOTIFY_MARK_FLAG_OBJECT_PINNED)) {
  		mark->flags |= FSNOTIFY_MARK_FLAG_OBJECT_PINNED;
0809ab69a   Jan Kara   fsnotify: unify i...
100
  		inode = igrab(mark->inode);
90b1e7a57   Eric Paris   fsnotify: allow m...
101
102
103
104
105
106
107
  		/*
  		 * we shouldn't be able to get here if the inode wasn't
  		 * already safely held in memory.  But bug in case it
  		 * ever is wrong.
  		 */
  		BUG_ON(!inode);
  	}
3be25f49b   Eric Paris   fsnotify: add mar...
108
109
110
  }
  
  /*
0c6532e4e   Eric Paris   fsnotify: place m...
111
   * Attach an initialized mark to a given inode.
3be25f49b   Eric Paris   fsnotify: add mar...
112
   * These marks may be used for the fsnotify backend to determine which
0c6532e4e   Eric Paris   fsnotify: place m...
113
   * event types should be delivered to which group and for which inodes.  These
6ad2d4e3e   Eric Paris   fsnotify: impleme...
114
115
   * marks are ordered according to priority, highest number first, and then by
   * the group's location in memory.
3be25f49b   Eric Paris   fsnotify: add mar...
116
   */
5444e2981   Eric Paris   fsnotify: split g...
117
118
119
  int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
  			    struct fsnotify_group *group, struct inode *inode,
  			    int allow_dups)
3be25f49b   Eric Paris   fsnotify: add mar...
120
  {
0809ab69a   Jan Kara   fsnotify: unify i...
121
  	int ret;
3be25f49b   Eric Paris   fsnotify: add mar...
122

700307a29   Eric Paris   fsnotify: use an ...
123
  	mark->flags |= FSNOTIFY_MARK_FLAG_INODE;
098cf2fc7   Eric Paris   fsnotify: add fla...
124

986ab0980   Lino Sanfilippo   fsnotify: use a m...
125
  	BUG_ON(!mutex_is_locked(&group->mark_mutex));
5444e2981   Eric Paris   fsnotify: split g...
126
  	assert_spin_locked(&mark->lock);
1ef5f13c6   Eric Paris   fsnotify: fsnotif...
127

3be25f49b   Eric Paris   fsnotify: add mar...
128
  	spin_lock(&inode->i_lock);
0809ab69a   Jan Kara   fsnotify: unify i...
129
130
131
132
  	mark->inode = inode;
  	ret = fsnotify_add_mark_list(&inode->i_fsnotify_marks, mark,
  				     allow_dups);
  	inode->i_fsnotify_mask = fsnotify_recalc_mask(&inode->i_fsnotify_marks);
3be25f49b   Eric Paris   fsnotify: add mar...
133
  	spin_unlock(&inode->i_lock);
3be25f49b   Eric Paris   fsnotify: add mar...
134
135
136
  
  	return ret;
  }
164bc6195   Eric Paris   fsnotify: handle ...
137
138
139
  
  /**
   * fsnotify_unmount_inodes - an sb is unmounting.  handle any watched inodes.
74278da9f   Dave Chinner   inode: convert in...
140
   * @sb: superblock being unmounted.
164bc6195   Eric Paris   fsnotify: handle ...
141
   *
55fa6091d   Dave Chinner   fs: move i_sb_lis...
142
   * Called during unmount with no locks held, so needs to be safe against
74278da9f   Dave Chinner   inode: convert in...
143
   * concurrent modifiers. We temporarily drop sb->s_inode_list_lock and CAN block.
164bc6195   Eric Paris   fsnotify: handle ...
144
   */
74278da9f   Dave Chinner   inode: convert in...
145
  void fsnotify_unmount_inodes(struct super_block *sb)
164bc6195   Eric Paris   fsnotify: handle ...
146
147
  {
  	struct inode *inode, *next_i, *need_iput = NULL;
74278da9f   Dave Chinner   inode: convert in...
148
149
  	spin_lock(&sb->s_inode_list_lock);
  	list_for_each_entry_safe(inode, next_i, &sb->s_inodes, i_sb_list) {
164bc6195   Eric Paris   fsnotify: handle ...
150
151
152
  		struct inode *need_iput_tmp;
  
  		/*
a4ffdde6e   Al Viro   simplify checks f...
153
  		 * We cannot __iget() an inode in state I_FREEING,
164bc6195   Eric Paris   fsnotify: handle ...
154
155
156
  		 * I_WILL_FREE, or I_NEW which is fine because by that point
  		 * the inode cannot have any associated watches.
  		 */
250df6ed2   Dave Chinner   fs: protect inode...
157
158
159
  		spin_lock(&inode->i_lock);
  		if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) {
  			spin_unlock(&inode->i_lock);
164bc6195   Eric Paris   fsnotify: handle ...
160
  			continue;
250df6ed2   Dave Chinner   fs: protect inode...
161
  		}
164bc6195   Eric Paris   fsnotify: handle ...
162
163
164
165
166
167
168
  
  		/*
  		 * 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.
  		 */
250df6ed2   Dave Chinner   fs: protect inode...
169
170
  		if (!atomic_read(&inode->i_count)) {
  			spin_unlock(&inode->i_lock);
164bc6195   Eric Paris   fsnotify: handle ...
171
  			continue;
250df6ed2   Dave Chinner   fs: protect inode...
172
  		}
164bc6195   Eric Paris   fsnotify: handle ...
173
174
175
176
177
178
179
180
181
  
  		need_iput_tmp = need_iput;
  		need_iput = NULL;
  
  		/* In case fsnotify_inode_delete() drops a reference. */
  		if (inode != need_iput_tmp)
  			__iget(inode);
  		else
  			need_iput_tmp = NULL;
250df6ed2   Dave Chinner   fs: protect inode...
182
  		spin_unlock(&inode->i_lock);
164bc6195   Eric Paris   fsnotify: handle ...
183
184
  
  		/* In case the dropping of a reference would nuke next_i. */
74278da9f   Dave Chinner   inode: convert in...
185
  		while (&next_i->i_sb_list != &sb->s_inodes) {
250df6ed2   Dave Chinner   fs: protect inode...
186
  			spin_lock(&next_i->i_lock);
6424babfd   Jerry Hoemann   fsnotify: next_i ...
187
188
  			if (!(next_i->i_state & (I_FREEING | I_WILL_FREE)) &&
  						atomic_read(&next_i->i_count)) {
250df6ed2   Dave Chinner   fs: protect inode...
189
190
  				__iget(next_i);
  				need_iput = next_i;
6424babfd   Jerry Hoemann   fsnotify: next_i ...
191
192
  				spin_unlock(&next_i->i_lock);
  				break;
250df6ed2   Dave Chinner   fs: protect inode...
193
194
  			}
  			spin_unlock(&next_i->i_lock);
1deaf9d19   Geliang Tang   fs/notify/inode_m...
195
  			next_i = list_next_entry(next_i, i_sb_list);
164bc6195   Eric Paris   fsnotify: handle ...
196
197
198
  		}
  
  		/*
74278da9f   Dave Chinner   inode: convert in...
199
  		 * We can safely drop s_inode_list_lock here because either
6424babfd   Jerry Hoemann   fsnotify: next_i ...
200
201
202
  		 * we actually hold references on both inode and next_i or
  		 * end of list.  Also no new inodes will be added since the
  		 * umount has begun.
164bc6195   Eric Paris   fsnotify: handle ...
203
  		 */
74278da9f   Dave Chinner   inode: convert in...
204
  		spin_unlock(&sb->s_inode_list_lock);
164bc6195   Eric Paris   fsnotify: handle ...
205
206
207
208
209
210
211
212
213
214
  
  		if (need_iput_tmp)
  			iput(need_iput_tmp);
  
  		/* 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);
74278da9f   Dave Chinner   inode: convert in...
215
  		spin_lock(&sb->s_inode_list_lock);
164bc6195   Eric Paris   fsnotify: handle ...
216
  	}
74278da9f   Dave Chinner   inode: convert in...
217
  	spin_unlock(&sb->s_inode_list_lock);
164bc6195   Eric Paris   fsnotify: handle ...
218
  }