Skip to content

Commit efb170c

Browse files
author
Al Viro
committed
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 <[email protected]>
1 parent 1629d0e commit efb170c

File tree

5 files changed

+129
-100
lines changed

5 files changed

+129
-100
lines changed

fs/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ obj-y := open.o read_write.o file_table.o super.o \
1111
attr.o bad_inode.o file.o filesystems.o namespace.o \
1212
seq_file.o xattr.o libfs.o fs-writeback.o \
1313
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
1515

1616
ifeq ($(CONFIG_BLOCK),y)
1717
obj-y += buffer.o block_dev.o direct-io.o mpage.o

fs/fs_pin.c

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
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

+2-4
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,16 @@ struct super_block;
2424
struct pacct_struct;
2525
struct pid_namespace;
2626
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 *);
2927
extern void acct_collect(long exitcode, int group_dead);
3028
extern void acct_process(void);
3129
extern void acct_exit_ns(struct pid_namespace *);
3230
#else
33-
#define acct_auto_close(x) do { } while (0)
34-
#define acct_auto_close_mnt(x) do { } while (0)
3531
#define acct_collect(x,y) do { } while (0)
3632
#define acct_process() do { } while (0)
3733
#define acct_exit_ns(ns) do { } while (0)
3834
#endif
35+
extern void acct_auto_close(struct hlist_head *);
36+
extern void acct_auto_close_mnt(struct hlist_head *);
3937

4038
/*
4139
* ACCT_VERSION numbers as yet defined:

include/linux/fs_pin.h

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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 *);

kernel/acct.c

+32-95
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
#include <asm/div64.h>
6060
#include <linux/blkdev.h> /* sector_div */
6161
#include <linux/pid_namespace.h>
62-
#include <../fs/mount.h> /* will go away when we refactor */
62+
#include <linux/fs_pin.h>
6363

6464
/*
6565
* These constants control the amount of freespace that suspend and
@@ -78,17 +78,6 @@ int acct_parm[3] = {4, 2, 30};
7878
*/
7979
static void do_acct_process(struct bsd_acct_struct *acct);
8080

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-
9281
struct bsd_acct_struct {
9382
struct fs_pin pin;
9483
struct mutex lock;
@@ -100,13 +89,6 @@ struct bsd_acct_struct {
10089
struct completion done;
10190
};
10291

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-
11092
/*
11193
* Check the amount of free space and suspend/resume accordingly.
11294
*/
@@ -142,29 +124,6 @@ static int check_free_space(struct bsd_acct_struct *acct)
142124
return acct->active;
143125
}
144126

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-
168127
static struct bsd_acct_struct *acct_get(struct pid_namespace *ns)
169128
{
170129
struct bsd_acct_struct *res;
@@ -176,9 +135,18 @@ static struct bsd_acct_struct *acct_get(struct pid_namespace *ns)
176135
rcu_read_unlock();
177136
return NULL;
178137
}
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();
181141
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+
}
182150
return res;
183151
}
184152

@@ -203,26 +171,28 @@ static void acct_kill(struct bsd_acct_struct *acct,
203171
init_completion(&acct->done);
204172
schedule_work(&acct->work);
205173
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);
210175
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-
}
219176
acct->ns = NULL;
220177
atomic_long_dec(&acct->pin.count);
221178
mutex_unlock(&acct->lock);
222179
pin_put(&acct->pin);
223180
}
224181
}
225182

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+
226196
static int acct_on(struct filename *pathname)
227197
{
228198
struct file *file;
@@ -254,25 +224,22 @@ static int acct_on(struct filename *pathname)
254224
}
255225

256226
atomic_long_set(&acct->pin.count, 1);
227+
acct->pin.kill = acct_pin_kill;
257228
acct->file = file;
258229
acct->needcheck = jiffies;
259230
acct->ns = ns;
260231
mutex_init(&acct->lock);
261232
mnt = file->f_path.mnt;
262233
mnt_pin(mnt);
234+
mutex_lock_nested(&acct->lock, 1); /* nobody has seen it yet */
235+
pin_insert(&acct->pin, mnt);
263236

264237
old = acct_get(ns);
265-
mutex_lock_nested(&acct->lock, 1); /* nobody has seen it yet */
266-
if (old) {
238+
if (old)
267239
acct_kill(old, acct);
268-
} else {
240+
else
269241
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);
276243
mntput(mnt); /* it's pinned, now give up active reference */
277244
return 0;
278245
}
@@ -312,36 +279,6 @@ SYSCALL_DEFINE1(acct, const char __user *, name)
312279
return error;
313280
}
314281

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-
}
344-
345282
void acct_exit_ns(struct pid_namespace *ns)
346283
{
347284
acct_kill(acct_get(ns), NULL);

0 commit comments

Comments
 (0)