Commit efb170c22867cdc6f770de441bdefecec6712199

Authored by Al Viro
1 parent 1629d0eb3e

take fs_pin stuff to fs/*

Add a new field to fs_pin - kill(pin).  That's what umount and r/o remount
will be calling for all pins attached to vfsmount and superblock resp.
Called after bumping the refcount, so it won't go away under us.  Dropping
the refcount is responsibility of the instance.  All generic stuff moved to
fs/fs_pin.c; the next step will rip all the knowledge of kernel/acct.c from
fs/super.c and fs/namespace.c.  After that - death to mnt_pin(); it was
intended to be usable as generic mechanism for code that wants to attach
objects to vfsmount, so that they would not make the sucker busy and
would get killed on umount.  Never got it right; it remained acct.c-specific
all along.  Now it's very close to being killable.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Showing 5 changed files with 129 additions and 100 deletions Side-by-side Diff

... ... @@ -11,7 +11,7 @@
11 11 attr.o bad_inode.o file.o filesystems.o namespace.o \
12 12 seq_file.o xattr.o libfs.o fs-writeback.o \
13 13 pnode.o splice.o sync.o utimes.o \
14   - stack.o fs_struct.o statfs.o
  14 + stack.o fs_struct.o statfs.o fs_pin.o
15 15  
16 16 ifeq ($(CONFIG_BLOCK),y)
17 17 obj-y += buffer.o block_dev.o direct-io.o mpage.o
  1 +#include <linux/fs.h>
  2 +#include <linux/slab.h>
  3 +#include <linux/fs_pin.h>
  4 +#include "mount.h"
  5 +
  6 +static void pin_free_rcu(struct rcu_head *head)
  7 +{
  8 + kfree(container_of(head, struct fs_pin, rcu));
  9 +}
  10 +
  11 +static DEFINE_SPINLOCK(pin_lock);
  12 +
  13 +void pin_put(struct fs_pin *p)
  14 +{
  15 + if (atomic_long_dec_and_test(&p->count))
  16 + call_rcu(&p->rcu, pin_free_rcu);
  17 +}
  18 +
  19 +void pin_remove(struct fs_pin *pin)
  20 +{
  21 + spin_lock(&pin_lock);
  22 + hlist_del(&pin->m_list);
  23 + hlist_del(&pin->s_list);
  24 + spin_unlock(&pin_lock);
  25 +}
  26 +
  27 +void pin_insert(struct fs_pin *pin, struct vfsmount *m)
  28 +{
  29 + spin_lock(&pin_lock);
  30 + hlist_add_head(&pin->s_list, &m->mnt_sb->s_pins);
  31 + hlist_add_head(&pin->m_list, &real_mount(m)->mnt_pins);
  32 + spin_unlock(&pin_lock);
  33 +}
  34 +
  35 +void acct_auto_close_mnt(struct hlist_head *list)
  36 +{
  37 + while (1) {
  38 + struct hlist_node *p;
  39 + struct fs_pin *pin;
  40 + rcu_read_lock();
  41 + p = ACCESS_ONCE(list->first);
  42 + if (!p) {
  43 + rcu_read_unlock();
  44 + break;
  45 + }
  46 + pin = hlist_entry(p, struct fs_pin, m_list);
  47 + if (!atomic_long_inc_not_zero(&pin->count)) {
  48 + rcu_read_unlock();
  49 + cpu_relax();
  50 + continue;
  51 + }
  52 + rcu_read_unlock();
  53 + pin->kill(pin);
  54 + }
  55 +}
  56 +
  57 +void acct_auto_close(struct hlist_head *list)
  58 +{
  59 + while (1) {
  60 + struct hlist_node *p;
  61 + struct fs_pin *pin;
  62 + rcu_read_lock();
  63 + p = ACCESS_ONCE(list->first);
  64 + if (!p) {
  65 + rcu_read_unlock();
  66 + break;
  67 + }
  68 + pin = hlist_entry(p, struct fs_pin, s_list);
  69 + if (!atomic_long_inc_not_zero(&pin->count)) {
  70 + rcu_read_unlock();
  71 + cpu_relax();
  72 + continue;
  73 + }
  74 + rcu_read_unlock();
  75 + pin->kill(pin);
  76 + }
  77 +}
include/linux/acct.h
... ... @@ -24,18 +24,16 @@
24 24 struct pacct_struct;
25 25 struct pid_namespace;
26 26 extern int acct_parm[]; /* for sysctl */
27   -extern void acct_auto_close(struct hlist_head *);
28   -extern void acct_auto_close_mnt(struct hlist_head *);
29 27 extern void acct_collect(long exitcode, int group_dead);
30 28 extern void acct_process(void);
31 29 extern void acct_exit_ns(struct pid_namespace *);
32 30 #else
33   -#define acct_auto_close(x) do { } while (0)
34   -#define acct_auto_close_mnt(x) do { } while (0)
35 31 #define acct_collect(x,y) do { } while (0)
36 32 #define acct_process() do { } while (0)
37 33 #define acct_exit_ns(ns) do { } while (0)
38 34 #endif
  35 +extern void acct_auto_close(struct hlist_head *);
  36 +extern void acct_auto_close_mnt(struct hlist_head *);
39 37  
40 38 /*
41 39 * ACCT_VERSION numbers as yet defined:
include/linux/fs_pin.h
  1 +#include <linux/fs.h>
  2 +
  3 +struct fs_pin {
  4 + atomic_long_t count;
  5 + union {
  6 + struct {
  7 + struct hlist_node s_list;
  8 + struct hlist_node m_list;
  9 + };
  10 + struct rcu_head rcu;
  11 + };
  12 + void (*kill)(struct fs_pin *);
  13 +};
  14 +
  15 +void pin_put(struct fs_pin *);
  16 +void pin_remove(struct fs_pin *);
  17 +void pin_insert(struct fs_pin *, struct vfsmount *);
... ... @@ -59,7 +59,7 @@
59 59 #include <asm/div64.h>
60 60 #include <linux/blkdev.h> /* sector_div */
61 61 #include <linux/pid_namespace.h>
62   -#include <../fs/mount.h> /* will go away when we refactor */
  62 +#include <linux/fs_pin.h>
63 63  
64 64 /*
65 65 * These constants control the amount of freespace that suspend and
... ... @@ -78,17 +78,6 @@
78 78 */
79 79 static void do_acct_process(struct bsd_acct_struct *acct);
80 80  
81   -struct fs_pin {
82   - atomic_long_t count;
83   - union {
84   - struct {
85   - struct hlist_node s_list;
86   - struct hlist_node m_list;
87   - };
88   - struct rcu_head rcu;
89   - };
90   -};
91   -
92 81 struct bsd_acct_struct {
93 82 struct fs_pin pin;
94 83 struct mutex lock;
... ... @@ -100,13 +89,6 @@
100 89 struct completion done;
101 90 };
102 91  
103   -static void pin_free_rcu(struct rcu_head *head)
104   -{
105   - kfree(container_of(head, struct fs_pin, rcu));
106   -}
107   -
108   -static DEFINE_SPINLOCK(acct_lock);
109   -
110 92 /*
111 93 * Check the amount of free space and suspend/resume accordingly.
112 94 */
... ... @@ -142,29 +124,6 @@
142 124 return acct->active;
143 125 }
144 126  
145   -static void pin_put(struct fs_pin *p)
146   -{
147   - if (atomic_long_dec_and_test(&p->count))
148   - call_rcu(&p->rcu, pin_free_rcu);
149   -}
150   -
151   -static struct bsd_acct_struct *__acct_get(struct bsd_acct_struct *res)
152   -{
153   - if (!atomic_long_inc_not_zero(&res->pin.count)) {
154   - rcu_read_unlock();
155   - cpu_relax();
156   - return NULL;
157   - }
158   - rcu_read_unlock();
159   - mutex_lock(&res->lock);
160   - if (!res->ns) {
161   - mutex_unlock(&res->lock);
162   - pin_put(&res->pin);
163   - return NULL;
164   - }
165   - return res;
166   -}
167   -
168 127 static struct bsd_acct_struct *acct_get(struct pid_namespace *ns)
169 128 {
170 129 struct bsd_acct_struct *res;
171 130  
... ... @@ -176,9 +135,18 @@
176 135 rcu_read_unlock();
177 136 return NULL;
178 137 }
179   - res = __acct_get(res);
180   - if (!res)
  138 + if (!atomic_long_inc_not_zero(&res->pin.count)) {
  139 + rcu_read_unlock();
  140 + cpu_relax();
181 141 goto again;
  142 + }
  143 + rcu_read_unlock();
  144 + mutex_lock(&res->lock);
  145 + if (!res->ns) {
  146 + mutex_unlock(&res->lock);
  147 + pin_put(&res->pin);
  148 + goto again;
  149 + }
182 150 return res;
183 151 }
184 152  
185 153  
... ... @@ -203,19 +171,8 @@
203 171 init_completion(&acct->done);
204 172 schedule_work(&acct->work);
205 173 wait_for_completion(&acct->done);
206   - spin_lock(&acct_lock);
207   - hlist_del(&acct->pin.m_list);
208   - hlist_del(&acct->pin.s_list);
209   - spin_unlock(&acct_lock);
  174 + pin_remove(&acct->pin);
210 175 ns->bacct = new;
211   - if (new) {
212   - struct vfsmount *m = new->file->f_path.mnt;
213   - spin_lock(&acct_lock);
214   - hlist_add_head(&new->pin.s_list, &m->mnt_sb->s_pins);
215   - hlist_add_head(&new->pin.m_list, &real_mount(m)->mnt_pins);
216   - spin_unlock(&acct_lock);
217   - mutex_unlock(&new->lock);
218   - }
219 176 acct->ns = NULL;
220 177 atomic_long_dec(&acct->pin.count);
221 178 mutex_unlock(&acct->lock);
... ... @@ -223,6 +180,19 @@
223 180 }
224 181 }
225 182  
  183 +static void acct_pin_kill(struct fs_pin *pin)
  184 +{
  185 + struct bsd_acct_struct *acct;
  186 + acct = container_of(pin, struct bsd_acct_struct, pin);
  187 + mutex_lock(&acct->lock);
  188 + if (!acct->ns) {
  189 + mutex_unlock(&acct->lock);
  190 + pin_put(pin);
  191 + acct = NULL;
  192 + }
  193 + acct_kill(acct, NULL);
  194 +}
  195 +
226 196 static int acct_on(struct filename *pathname)
227 197 {
228 198 struct file *file;
229 199  
230 200  
231 201  
232 202  
... ... @@ -254,25 +224,22 @@
254 224 }
255 225  
256 226 atomic_long_set(&acct->pin.count, 1);
  227 + acct->pin.kill = acct_pin_kill;
257 228 acct->file = file;
258 229 acct->needcheck = jiffies;
259 230 acct->ns = ns;
260 231 mutex_init(&acct->lock);
261 232 mnt = file->f_path.mnt;
262 233 mnt_pin(mnt);
  234 + mutex_lock_nested(&acct->lock, 1); /* nobody has seen it yet */
  235 + pin_insert(&acct->pin, mnt);
263 236  
264 237 old = acct_get(ns);
265   - mutex_lock_nested(&acct->lock, 1); /* nobody has seen it yet */
266   - if (old) {
  238 + if (old)
267 239 acct_kill(old, acct);
268   - } else {
  240 + else
269 241 ns->bacct = acct;
270   - spin_lock(&acct_lock);
271   - hlist_add_head(&acct->pin.s_list, &mnt->mnt_sb->s_pins);
272   - hlist_add_head(&acct->pin.m_list, &real_mount(mnt)->mnt_pins);
273   - spin_unlock(&acct_lock);
274   - mutex_unlock(&acct->lock);
275   - }
  242 + mutex_unlock(&acct->lock);
276 243 mntput(mnt); /* it's pinned, now give up active reference */
277 244 return 0;
278 245 }
... ... @@ -310,36 +277,6 @@
310 277 }
311 278  
312 279 return error;
313   -}
314   -
315   -void acct_auto_close_mnt(struct hlist_head *list)
316   -{
317   - rcu_read_lock();
318   - while (1) {
319   - struct hlist_node *p = ACCESS_ONCE(list->first);
320   - if (!p)
321   - break;
322   - acct_kill(__acct_get(hlist_entry(p,
323   - struct bsd_acct_struct,
324   - pin.m_list)), NULL);
325   - rcu_read_lock();
326   - }
327   - rcu_read_unlock();
328   -}
329   -
330   -void acct_auto_close(struct hlist_head *list)
331   -{
332   - rcu_read_lock();
333   - while (1) {
334   - struct hlist_node *p = ACCESS_ONCE(list->first);
335   - if (!p)
336   - break;
337   - acct_kill(__acct_get(hlist_entry(p,
338   - struct bsd_acct_struct,
339   - pin.s_list)), NULL);
340   - rcu_read_lock();
341   - }
342   - rcu_read_unlock();
343 280 }
344 281  
345 282 void acct_exit_ns(struct pid_namespace *ns)