Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

Al Viro efb170c2 1629d0eb

+129 -100
+1 -1
fs/Makefile
··· 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
+77
fs/fs_pin.c
··· 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 + }
+2 -4
include/linux/acct.h
··· 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:
+17
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 *);
+32 -95
kernel/acct.c
··· 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 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; ··· 88 99 struct work_struct work; 89 100 struct completion done; 90 101 }; 91 - 92 - static void pin_free_rcu(struct rcu_head *head) 93 - { 94 - kfree(container_of(head, struct fs_pin, rcu)); 95 - } 96 - 97 - static DEFINE_SPINLOCK(acct_lock); 98 102 99 103 /* 100 104 * Check the amount of free space and suspend/resume accordingly. ··· 124 142 return acct->active; 125 143 } 126 144 127 - static void pin_put(struct fs_pin *p) 128 - { 129 - if (atomic_long_dec_and_test(&p->count)) 130 - call_rcu(&p->rcu, pin_free_rcu); 131 - } 132 - 133 - static struct bsd_acct_struct *__acct_get(struct bsd_acct_struct *res) 134 - { 135 - if (!atomic_long_inc_not_zero(&res->pin.count)) { 136 - rcu_read_unlock(); 137 - cpu_relax(); 138 - return NULL; 139 - } 140 - rcu_read_unlock(); 141 - mutex_lock(&res->lock); 142 - if (!res->ns) { 143 - mutex_unlock(&res->lock); 144 - pin_put(&res->pin); 145 - return NULL; 146 - } 147 - return res; 148 - } 149 - 150 145 static struct bsd_acct_struct *acct_get(struct pid_namespace *ns) 151 146 { 152 147 struct bsd_acct_struct *res; ··· 135 176 rcu_read_unlock(); 136 177 return NULL; 137 178 } 138 - res = __acct_get(res); 139 - if (!res) 179 + if (!atomic_long_inc_not_zero(&res->pin.count)) { 180 + rcu_read_unlock(); 181 + cpu_relax(); 140 182 goto again; 183 + } 184 + rcu_read_unlock(); 185 + mutex_lock(&res->lock); 186 + if (!res->ns) { 187 + mutex_unlock(&res->lock); 188 + pin_put(&res->pin); 189 + goto again; 190 + } 141 191 return res; 142 192 } 143 193 ··· 171 203 init_completion(&acct->done); 172 204 schedule_work(&acct->work); 173 205 wait_for_completion(&acct->done); 174 - spin_lock(&acct_lock); 175 - hlist_del(&acct->pin.m_list); 176 - hlist_del(&acct->pin.s_list); 177 - spin_unlock(&acct_lock); 206 + pin_remove(&acct->pin); 178 207 ns->bacct = new; 179 - if (new) { 180 - struct vfsmount *m = new->file->f_path.mnt; 181 - spin_lock(&acct_lock); 182 - hlist_add_head(&new->pin.s_list, &m->mnt_sb->s_pins); 183 - hlist_add_head(&new->pin.m_list, &real_mount(m)->mnt_pins); 184 - spin_unlock(&acct_lock); 185 - mutex_unlock(&new->lock); 186 - } 187 208 acct->ns = NULL; 188 209 atomic_long_dec(&acct->pin.count); 189 210 mutex_unlock(&acct->lock); 190 211 pin_put(&acct->pin); 191 212 } 213 + } 214 + 215 + static void acct_pin_kill(struct fs_pin *pin) 216 + { 217 + struct bsd_acct_struct *acct; 218 + acct = container_of(pin, struct bsd_acct_struct, pin); 219 + mutex_lock(&acct->lock); 220 + if (!acct->ns) { 221 + mutex_unlock(&acct->lock); 222 + pin_put(pin); 223 + acct = NULL; 224 + } 225 + acct_kill(acct, NULL); 192 226 } 193 227 194 228 static int acct_on(struct filename *pathname) ··· 224 254 } 225 255 226 256 atomic_long_set(&acct->pin.count, 1); 257 + acct->pin.kill = acct_pin_kill; 227 258 acct->file = file; 228 259 acct->needcheck = jiffies; 229 260 acct->ns = ns; 230 261 mutex_init(&acct->lock); 231 262 mnt = file->f_path.mnt; 232 263 mnt_pin(mnt); 264 + mutex_lock_nested(&acct->lock, 1); /* nobody has seen it yet */ 265 + pin_insert(&acct->pin, mnt); 233 266 234 267 old = acct_get(ns); 235 - mutex_lock_nested(&acct->lock, 1); /* nobody has seen it yet */ 236 - if (old) { 268 + if (old) 237 269 acct_kill(old, acct); 238 - } else { 270 + else 239 271 ns->bacct = acct; 240 - spin_lock(&acct_lock); 241 - hlist_add_head(&acct->pin.s_list, &mnt->mnt_sb->s_pins); 242 - hlist_add_head(&acct->pin.m_list, &real_mount(mnt)->mnt_pins); 243 - spin_unlock(&acct_lock); 244 - mutex_unlock(&acct->lock); 245 - } 272 + mutex_unlock(&acct->lock); 246 273 mntput(mnt); /* it's pinned, now give up active reference */ 247 274 return 0; 248 275 } ··· 277 310 } 278 311 279 312 return error; 280 - } 281 - 282 - void acct_auto_close_mnt(struct hlist_head *list) 283 - { 284 - rcu_read_lock(); 285 - while (1) { 286 - struct hlist_node *p = ACCESS_ONCE(list->first); 287 - if (!p) 288 - break; 289 - acct_kill(__acct_get(hlist_entry(p, 290 - struct bsd_acct_struct, 291 - pin.m_list)), NULL); 292 - rcu_read_lock(); 293 - } 294 - rcu_read_unlock(); 295 - } 296 - 297 - void acct_auto_close(struct hlist_head *list) 298 - { 299 - rcu_read_lock(); 300 - while (1) { 301 - struct hlist_node *p = ACCESS_ONCE(list->first); 302 - if (!p) 303 - break; 304 - acct_kill(__acct_get(hlist_entry(p, 305 - struct bsd_acct_struct, 306 - pin.s_list)), NULL); 307 - rcu_read_lock(); 308 - } 309 - rcu_read_unlock(); 310 313 } 311 314 312 315 void acct_exit_ns(struct pid_namespace *ns)