diff options
Diffstat (limited to 'fs')
54 files changed, 608 insertions, 556 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index 4218e26df916..acf32054edd8 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h | |||
@@ -104,7 +104,7 @@ struct autofs_sb_info { | |||
104 | u32 magic; | 104 | u32 magic; |
105 | int pipefd; | 105 | int pipefd; |
106 | struct file *pipe; | 106 | struct file *pipe; |
107 | pid_t oz_pgrp; | 107 | struct pid *oz_pgrp; |
108 | int catatonic; | 108 | int catatonic; |
109 | int version; | 109 | int version; |
110 | int sub_version; | 110 | int sub_version; |
@@ -140,7 +140,7 @@ static inline struct autofs_info *autofs4_dentry_ino(struct dentry *dentry) | |||
140 | filesystem without "magic".) */ | 140 | filesystem without "magic".) */ |
141 | 141 | ||
142 | static inline int autofs4_oz_mode(struct autofs_sb_info *sbi) { | 142 | static inline int autofs4_oz_mode(struct autofs_sb_info *sbi) { |
143 | return sbi->catatonic || task_pgrp_nr(current) == sbi->oz_pgrp; | 143 | return sbi->catatonic || task_pgrp(current) == sbi->oz_pgrp; |
144 | } | 144 | } |
145 | 145 | ||
146 | /* Does a dentry have some pending activity? */ | 146 | /* Does a dentry have some pending activity? */ |
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c index 1818ce7f5a06..3182c0e68b42 100644 --- a/fs/autofs4/dev-ioctl.c +++ b/fs/autofs4/dev-ioctl.c | |||
@@ -346,6 +346,7 @@ static int autofs_dev_ioctl_setpipefd(struct file *fp, | |||
346 | { | 346 | { |
347 | int pipefd; | 347 | int pipefd; |
348 | int err = 0; | 348 | int err = 0; |
349 | struct pid *new_pid = NULL; | ||
349 | 350 | ||
350 | if (param->setpipefd.pipefd == -1) | 351 | if (param->setpipefd.pipefd == -1) |
351 | return -EINVAL; | 352 | return -EINVAL; |
@@ -357,7 +358,17 @@ static int autofs_dev_ioctl_setpipefd(struct file *fp, | |||
357 | mutex_unlock(&sbi->wq_mutex); | 358 | mutex_unlock(&sbi->wq_mutex); |
358 | return -EBUSY; | 359 | return -EBUSY; |
359 | } else { | 360 | } else { |
360 | struct file *pipe = fget(pipefd); | 361 | struct file *pipe; |
362 | |||
363 | new_pid = get_task_pid(current, PIDTYPE_PGID); | ||
364 | |||
365 | if (ns_of_pid(new_pid) != ns_of_pid(sbi->oz_pgrp)) { | ||
366 | AUTOFS_WARN("Not allowed to change PID namespace"); | ||
367 | err = -EINVAL; | ||
368 | goto out; | ||
369 | } | ||
370 | |||
371 | pipe = fget(pipefd); | ||
361 | if (!pipe) { | 372 | if (!pipe) { |
362 | err = -EBADF; | 373 | err = -EBADF; |
363 | goto out; | 374 | goto out; |
@@ -367,12 +378,13 @@ static int autofs_dev_ioctl_setpipefd(struct file *fp, | |||
367 | fput(pipe); | 378 | fput(pipe); |
368 | goto out; | 379 | goto out; |
369 | } | 380 | } |
370 | sbi->oz_pgrp = task_pgrp_nr(current); | 381 | swap(sbi->oz_pgrp, new_pid); |
371 | sbi->pipefd = pipefd; | 382 | sbi->pipefd = pipefd; |
372 | sbi->pipe = pipe; | 383 | sbi->pipe = pipe; |
373 | sbi->catatonic = 0; | 384 | sbi->catatonic = 0; |
374 | } | 385 | } |
375 | out: | 386 | out: |
387 | put_pid(new_pid); | ||
376 | mutex_unlock(&sbi->wq_mutex); | 388 | mutex_unlock(&sbi->wq_mutex); |
377 | return err; | 389 | return err; |
378 | } | 390 | } |
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index 3d9d3f5d5dda..394e90b02c5e 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c | |||
@@ -402,6 +402,20 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, | |||
402 | goto next; | 402 | goto next; |
403 | } | 403 | } |
404 | 404 | ||
405 | if (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)) { | ||
406 | DPRINTK("checking symlink %p %.*s", | ||
407 | dentry, (int)dentry->d_name.len, dentry->d_name.name); | ||
408 | /* | ||
409 | * A symlink can't be "busy" in the usual sense so | ||
410 | * just check last used for expire timeout. | ||
411 | */ | ||
412 | if (autofs4_can_expire(dentry, timeout, do_now)) { | ||
413 | expired = dentry; | ||
414 | goto found; | ||
415 | } | ||
416 | goto next; | ||
417 | } | ||
418 | |||
405 | if (simple_empty(dentry)) | 419 | if (simple_empty(dentry)) |
406 | goto next; | 420 | goto next; |
407 | 421 | ||
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 3b9cc9b973c2..d7bd395ab586 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c | |||
@@ -56,8 +56,11 @@ void autofs4_kill_sb(struct super_block *sb) | |||
56 | * just call kill_anon_super when we are called from | 56 | * just call kill_anon_super when we are called from |
57 | * deactivate_super. | 57 | * deactivate_super. |
58 | */ | 58 | */ |
59 | if (sbi) /* Free wait queues, close pipe */ | 59 | if (sbi) { |
60 | /* Free wait queues, close pipe */ | ||
60 | autofs4_catatonic_mode(sbi); | 61 | autofs4_catatonic_mode(sbi); |
62 | put_pid(sbi->oz_pgrp); | ||
63 | } | ||
61 | 64 | ||
62 | DPRINTK("shutting down"); | 65 | DPRINTK("shutting down"); |
63 | kill_litter_super(sb); | 66 | kill_litter_super(sb); |
@@ -80,7 +83,7 @@ static int autofs4_show_options(struct seq_file *m, struct dentry *root) | |||
80 | if (!gid_eq(root_inode->i_gid, GLOBAL_ROOT_GID)) | 83 | if (!gid_eq(root_inode->i_gid, GLOBAL_ROOT_GID)) |
81 | seq_printf(m, ",gid=%u", | 84 | seq_printf(m, ",gid=%u", |
82 | from_kgid_munged(&init_user_ns, root_inode->i_gid)); | 85 | from_kgid_munged(&init_user_ns, root_inode->i_gid)); |
83 | seq_printf(m, ",pgrp=%d", sbi->oz_pgrp); | 86 | seq_printf(m, ",pgrp=%d", pid_vnr(sbi->oz_pgrp)); |
84 | seq_printf(m, ",timeout=%lu", sbi->exp_timeout/HZ); | 87 | seq_printf(m, ",timeout=%lu", sbi->exp_timeout/HZ); |
85 | seq_printf(m, ",minproto=%d", sbi->min_proto); | 88 | seq_printf(m, ",minproto=%d", sbi->min_proto); |
86 | seq_printf(m, ",maxproto=%d", sbi->max_proto); | 89 | seq_printf(m, ",maxproto=%d", sbi->max_proto); |
@@ -124,7 +127,8 @@ static const match_table_t tokens = { | |||
124 | }; | 127 | }; |
125 | 128 | ||
126 | static int parse_options(char *options, int *pipefd, kuid_t *uid, kgid_t *gid, | 129 | static int parse_options(char *options, int *pipefd, kuid_t *uid, kgid_t *gid, |
127 | pid_t *pgrp, unsigned int *type, int *minproto, int *maxproto) | 130 | int *pgrp, bool *pgrp_set, unsigned int *type, |
131 | int *minproto, int *maxproto) | ||
128 | { | 132 | { |
129 | char *p; | 133 | char *p; |
130 | substring_t args[MAX_OPT_ARGS]; | 134 | substring_t args[MAX_OPT_ARGS]; |
@@ -132,7 +136,6 @@ static int parse_options(char *options, int *pipefd, kuid_t *uid, kgid_t *gid, | |||
132 | 136 | ||
133 | *uid = current_uid(); | 137 | *uid = current_uid(); |
134 | *gid = current_gid(); | 138 | *gid = current_gid(); |
135 | *pgrp = task_pgrp_nr(current); | ||
136 | 139 | ||
137 | *minproto = AUTOFS_MIN_PROTO_VERSION; | 140 | *minproto = AUTOFS_MIN_PROTO_VERSION; |
138 | *maxproto = AUTOFS_MAX_PROTO_VERSION; | 141 | *maxproto = AUTOFS_MAX_PROTO_VERSION; |
@@ -171,6 +174,7 @@ static int parse_options(char *options, int *pipefd, kuid_t *uid, kgid_t *gid, | |||
171 | if (match_int(args, &option)) | 174 | if (match_int(args, &option)) |
172 | return 1; | 175 | return 1; |
173 | *pgrp = option; | 176 | *pgrp = option; |
177 | *pgrp_set = true; | ||
174 | break; | 178 | break; |
175 | case Opt_minproto: | 179 | case Opt_minproto: |
176 | if (match_int(args, &option)) | 180 | if (match_int(args, &option)) |
@@ -206,10 +210,13 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
206 | int pipefd; | 210 | int pipefd; |
207 | struct autofs_sb_info *sbi; | 211 | struct autofs_sb_info *sbi; |
208 | struct autofs_info *ino; | 212 | struct autofs_info *ino; |
213 | int pgrp; | ||
214 | bool pgrp_set = false; | ||
215 | int ret = -EINVAL; | ||
209 | 216 | ||
210 | sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); | 217 | sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); |
211 | if (!sbi) | 218 | if (!sbi) |
212 | goto fail_unlock; | 219 | return -ENOMEM; |
213 | DPRINTK("starting up, sbi = %p",sbi); | 220 | DPRINTK("starting up, sbi = %p",sbi); |
214 | 221 | ||
215 | s->s_fs_info = sbi; | 222 | s->s_fs_info = sbi; |
@@ -218,7 +225,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
218 | sbi->pipe = NULL; | 225 | sbi->pipe = NULL; |
219 | sbi->catatonic = 1; | 226 | sbi->catatonic = 1; |
220 | sbi->exp_timeout = 0; | 227 | sbi->exp_timeout = 0; |
221 | sbi->oz_pgrp = task_pgrp_nr(current); | 228 | sbi->oz_pgrp = NULL; |
222 | sbi->sb = s; | 229 | sbi->sb = s; |
223 | sbi->version = 0; | 230 | sbi->version = 0; |
224 | sbi->sub_version = 0; | 231 | sbi->sub_version = 0; |
@@ -243,8 +250,10 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
243 | * Get the root inode and dentry, but defer checking for errors. | 250 | * Get the root inode and dentry, but defer checking for errors. |
244 | */ | 251 | */ |
245 | ino = autofs4_new_ino(sbi); | 252 | ino = autofs4_new_ino(sbi); |
246 | if (!ino) | 253 | if (!ino) { |
254 | ret = -ENOMEM; | ||
247 | goto fail_free; | 255 | goto fail_free; |
256 | } | ||
248 | root_inode = autofs4_get_inode(s, S_IFDIR | 0755); | 257 | root_inode = autofs4_get_inode(s, S_IFDIR | 0755); |
249 | root = d_make_root(root_inode); | 258 | root = d_make_root(root_inode); |
250 | if (!root) | 259 | if (!root) |
@@ -255,12 +264,23 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
255 | 264 | ||
256 | /* Can this call block? */ | 265 | /* Can this call block? */ |
257 | if (parse_options(data, &pipefd, &root_inode->i_uid, &root_inode->i_gid, | 266 | if (parse_options(data, &pipefd, &root_inode->i_uid, &root_inode->i_gid, |
258 | &sbi->oz_pgrp, &sbi->type, &sbi->min_proto, | 267 | &pgrp, &pgrp_set, &sbi->type, &sbi->min_proto, |
259 | &sbi->max_proto)) { | 268 | &sbi->max_proto)) { |
260 | printk("autofs: called with bogus options\n"); | 269 | printk("autofs: called with bogus options\n"); |
261 | goto fail_dput; | 270 | goto fail_dput; |
262 | } | 271 | } |
263 | 272 | ||
273 | if (pgrp_set) { | ||
274 | sbi->oz_pgrp = find_get_pid(pgrp); | ||
275 | if (!sbi->oz_pgrp) { | ||
276 | pr_warn("autofs: could not find process group %d\n", | ||
277 | pgrp); | ||
278 | goto fail_dput; | ||
279 | } | ||
280 | } else { | ||
281 | sbi->oz_pgrp = get_task_pid(current, PIDTYPE_PGID); | ||
282 | } | ||
283 | |||
264 | if (autofs_type_trigger(sbi->type)) | 284 | if (autofs_type_trigger(sbi->type)) |
265 | __managed_dentry_set_managed(root); | 285 | __managed_dentry_set_managed(root); |
266 | 286 | ||
@@ -284,14 +304,15 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
284 | sbi->version = sbi->max_proto; | 304 | sbi->version = sbi->max_proto; |
285 | sbi->sub_version = AUTOFS_PROTO_SUBVERSION; | 305 | sbi->sub_version = AUTOFS_PROTO_SUBVERSION; |
286 | 306 | ||
287 | DPRINTK("pipe fd = %d, pgrp = %u", pipefd, sbi->oz_pgrp); | 307 | DPRINTK("pipe fd = %d, pgrp = %u", pipefd, pid_nr(sbi->oz_pgrp)); |
288 | pipe = fget(pipefd); | 308 | pipe = fget(pipefd); |
289 | 309 | ||
290 | if (!pipe) { | 310 | if (!pipe) { |
291 | printk("autofs: could not open pipe file descriptor\n"); | 311 | printk("autofs: could not open pipe file descriptor\n"); |
292 | goto fail_dput; | 312 | goto fail_dput; |
293 | } | 313 | } |
294 | if (autofs_prepare_pipe(pipe) < 0) | 314 | ret = autofs_prepare_pipe(pipe); |
315 | if (ret < 0) | ||
295 | goto fail_fput; | 316 | goto fail_fput; |
296 | sbi->pipe = pipe; | 317 | sbi->pipe = pipe; |
297 | sbi->pipefd = pipefd; | 318 | sbi->pipefd = pipefd; |
@@ -316,10 +337,10 @@ fail_dput: | |||
316 | fail_ino: | 337 | fail_ino: |
317 | kfree(ino); | 338 | kfree(ino); |
318 | fail_free: | 339 | fail_free: |
340 | put_pid(sbi->oz_pgrp); | ||
319 | kfree(sbi); | 341 | kfree(sbi); |
320 | s->s_fs_info = NULL; | 342 | s->s_fs_info = NULL; |
321 | fail_unlock: | 343 | return ret; |
322 | return -EINVAL; | ||
323 | } | 344 | } |
324 | 345 | ||
325 | struct inode *autofs4_get_inode(struct super_block *sb, umode_t mode) | 346 | struct inode *autofs4_get_inode(struct super_block *sb, umode_t mode) |
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 92ef341ba0cf..2caf36ac3e93 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -558,7 +558,7 @@ static int autofs4_dir_symlink(struct inode *dir, | |||
558 | dget(dentry); | 558 | dget(dentry); |
559 | atomic_inc(&ino->count); | 559 | atomic_inc(&ino->count); |
560 | p_ino = autofs4_dentry_ino(dentry->d_parent); | 560 | p_ino = autofs4_dentry_ino(dentry->d_parent); |
561 | if (p_ino && dentry->d_parent != dentry) | 561 | if (p_ino && !IS_ROOT(dentry)) |
562 | atomic_inc(&p_ino->count); | 562 | atomic_inc(&p_ino->count); |
563 | 563 | ||
564 | dir->i_mtime = CURRENT_TIME; | 564 | dir->i_mtime = CURRENT_TIME; |
@@ -593,7 +593,7 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry) | |||
593 | 593 | ||
594 | if (atomic_dec_and_test(&ino->count)) { | 594 | if (atomic_dec_and_test(&ino->count)) { |
595 | p_ino = autofs4_dentry_ino(dentry->d_parent); | 595 | p_ino = autofs4_dentry_ino(dentry->d_parent); |
596 | if (p_ino && dentry->d_parent != dentry) | 596 | if (p_ino && !IS_ROOT(dentry)) |
597 | atomic_dec(&p_ino->count); | 597 | atomic_dec(&p_ino->count); |
598 | } | 598 | } |
599 | dput(ino->dentry); | 599 | dput(ino->dentry); |
@@ -732,7 +732,7 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, umode_t m | |||
732 | dget(dentry); | 732 | dget(dentry); |
733 | atomic_inc(&ino->count); | 733 | atomic_inc(&ino->count); |
734 | p_ino = autofs4_dentry_ino(dentry->d_parent); | 734 | p_ino = autofs4_dentry_ino(dentry->d_parent); |
735 | if (p_ino && dentry->d_parent != dentry) | 735 | if (p_ino && !IS_ROOT(dentry)) |
736 | atomic_inc(&p_ino->count); | 736 | atomic_inc(&p_ino->count); |
737 | inc_nlink(dir); | 737 | inc_nlink(dir); |
738 | dir->i_mtime = CURRENT_TIME; | 738 | dir->i_mtime = CURRENT_TIME; |
diff --git a/fs/autofs4/symlink.c b/fs/autofs4/symlink.c index f27c094a1919..1e8ea192be2b 100644 --- a/fs/autofs4/symlink.c +++ b/fs/autofs4/symlink.c | |||
@@ -14,6 +14,10 @@ | |||
14 | 14 | ||
15 | static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) | 15 | static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) |
16 | { | 16 | { |
17 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | ||
18 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | ||
19 | if (ino && !autofs4_oz_mode(sbi)) | ||
20 | ino->last_used = jiffies; | ||
17 | nd_set_link(nd, dentry->d_inode->i_private); | 21 | nd_set_link(nd, dentry->d_inode->i_private); |
18 | return NULL; | 22 | return NULL; |
19 | } | 23 | } |
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index 689e40d983ad..116fd38ee472 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c | |||
@@ -347,11 +347,23 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
347 | struct qstr qstr; | 347 | struct qstr qstr; |
348 | char *name; | 348 | char *name; |
349 | int status, ret, type; | 349 | int status, ret, type; |
350 | pid_t pid; | ||
351 | pid_t tgid; | ||
350 | 352 | ||
351 | /* In catatonic mode, we don't wait for nobody */ | 353 | /* In catatonic mode, we don't wait for nobody */ |
352 | if (sbi->catatonic) | 354 | if (sbi->catatonic) |
353 | return -ENOENT; | 355 | return -ENOENT; |
354 | 356 | ||
357 | /* | ||
358 | * Try translating pids to the namespace of the daemon. | ||
359 | * | ||
360 | * Zero means failure: we are in an unrelated pid namespace. | ||
361 | */ | ||
362 | pid = task_pid_nr_ns(current, ns_of_pid(sbi->oz_pgrp)); | ||
363 | tgid = task_tgid_nr_ns(current, ns_of_pid(sbi->oz_pgrp)); | ||
364 | if (pid == 0 || tgid == 0) | ||
365 | return -ENOENT; | ||
366 | |||
355 | if (!dentry->d_inode) { | 367 | if (!dentry->d_inode) { |
356 | /* | 368 | /* |
357 | * A wait for a negative dentry is invalid for certain | 369 | * A wait for a negative dentry is invalid for certain |
@@ -417,8 +429,8 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
417 | wq->ino = autofs4_get_ino(sbi); | 429 | wq->ino = autofs4_get_ino(sbi); |
418 | wq->uid = current_uid(); | 430 | wq->uid = current_uid(); |
419 | wq->gid = current_gid(); | 431 | wq->gid = current_gid(); |
420 | wq->pid = current->pid; | 432 | wq->pid = pid; |
421 | wq->tgid = current->tgid; | 433 | wq->tgid = tgid; |
422 | wq->status = -EINTR; /* Status return if interrupted */ | 434 | wq->status = -EINTR; /* Status return if interrupted */ |
423 | wq->wait_ctr = 2; | 435 | wq->wait_ctr = 2; |
424 | 436 | ||
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 571a42326908..67be2951b98a 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -543,9 +543,6 @@ out: | |||
543 | * libraries. There is no binary dependent code anywhere else. | 543 | * libraries. There is no binary dependent code anywhere else. |
544 | */ | 544 | */ |
545 | 545 | ||
546 | #define INTERPRETER_NONE 0 | ||
547 | #define INTERPRETER_ELF 2 | ||
548 | |||
549 | #ifndef STACK_RND_MASK | 546 | #ifndef STACK_RND_MASK |
550 | #define STACK_RND_MASK (0x7ff >> (PAGE_SHIFT - 12)) /* 8MB of VA */ | 547 | #define STACK_RND_MASK (0x7ff >> (PAGE_SHIFT - 12)) /* 8MB of VA */ |
551 | #endif | 548 | #endif |
diff --git a/fs/coredump.c b/fs/coredump.c index bc3fbcd32558..e3ad709a4232 100644 --- a/fs/coredump.c +++ b/fs/coredump.c | |||
@@ -40,7 +40,6 @@ | |||
40 | 40 | ||
41 | #include <trace/events/task.h> | 41 | #include <trace/events/task.h> |
42 | #include "internal.h" | 42 | #include "internal.h" |
43 | #include "coredump.h" | ||
44 | 43 | ||
45 | #include <trace/events/sched.h> | 44 | #include <trace/events/sched.h> |
46 | 45 | ||
diff --git a/fs/coredump.h b/fs/coredump.h deleted file mode 100644 index e39ff072110d..000000000000 --- a/fs/coredump.h +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | #ifndef _FS_COREDUMP_H | ||
2 | #define _FS_COREDUMP_H | ||
3 | |||
4 | extern int __get_dumpable(unsigned long mm_flags); | ||
5 | |||
6 | #endif | ||
@@ -62,7 +62,6 @@ | |||
62 | 62 | ||
63 | #include <trace/events/task.h> | 63 | #include <trace/events/task.h> |
64 | #include "internal.h" | 64 | #include "internal.h" |
65 | #include "coredump.h" | ||
66 | 65 | ||
67 | #include <trace/events/sched.h> | 66 | #include <trace/events/sched.h> |
68 | 67 | ||
@@ -843,7 +842,6 @@ static int exec_mmap(struct mm_struct *mm) | |||
843 | tsk->active_mm = mm; | 842 | tsk->active_mm = mm; |
844 | activate_mm(active_mm, mm); | 843 | activate_mm(active_mm, mm); |
845 | task_unlock(tsk); | 844 | task_unlock(tsk); |
846 | arch_pick_mmap_layout(mm); | ||
847 | if (old_mm) { | 845 | if (old_mm) { |
848 | up_read(&old_mm->mmap_sem); | 846 | up_read(&old_mm->mmap_sem); |
849 | BUG_ON(active_mm != old_mm); | 847 | BUG_ON(active_mm != old_mm); |
@@ -1088,8 +1086,8 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
1088 | bprm->mm = NULL; /* We're using it now */ | 1086 | bprm->mm = NULL; /* We're using it now */ |
1089 | 1087 | ||
1090 | set_fs(USER_DS); | 1088 | set_fs(USER_DS); |
1091 | current->flags &= | 1089 | current->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD | |
1092 | ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD | PF_NOFREEZE); | 1090 | PF_NOFREEZE | PF_NO_SETAFFINITY); |
1093 | flush_thread(); | 1091 | flush_thread(); |
1094 | current->personality &= ~bprm->per_clear; | 1092 | current->personality &= ~bprm->per_clear; |
1095 | 1093 | ||
@@ -1139,9 +1137,7 @@ void setup_new_exec(struct linux_binprm * bprm) | |||
1139 | 1137 | ||
1140 | /* An exec changes our domain. We are no longer part of the thread | 1138 | /* An exec changes our domain. We are no longer part of the thread |
1141 | group */ | 1139 | group */ |
1142 | |||
1143 | current->self_exec_id++; | 1140 | current->self_exec_id++; |
1144 | |||
1145 | flush_signal_handlers(current, 0); | 1141 | flush_signal_handlers(current, 0); |
1146 | do_close_on_exec(current->files); | 1142 | do_close_on_exec(current->files); |
1147 | } | 1143 | } |
@@ -1173,6 +1169,10 @@ void free_bprm(struct linux_binprm *bprm) | |||
1173 | mutex_unlock(¤t->signal->cred_guard_mutex); | 1169 | mutex_unlock(¤t->signal->cred_guard_mutex); |
1174 | abort_creds(bprm->cred); | 1170 | abort_creds(bprm->cred); |
1175 | } | 1171 | } |
1172 | if (bprm->file) { | ||
1173 | allow_write_access(bprm->file); | ||
1174 | fput(bprm->file); | ||
1175 | } | ||
1176 | /* If a binfmt changed the interp, free it. */ | 1176 | /* If a binfmt changed the interp, free it. */ |
1177 | if (bprm->interp != bprm->filename) | 1177 | if (bprm->interp != bprm->filename) |
1178 | kfree(bprm->interp); | 1178 | kfree(bprm->interp); |
@@ -1224,11 +1224,10 @@ EXPORT_SYMBOL(install_exec_creds); | |||
1224 | * - the caller must hold ->cred_guard_mutex to protect against | 1224 | * - the caller must hold ->cred_guard_mutex to protect against |
1225 | * PTRACE_ATTACH | 1225 | * PTRACE_ATTACH |
1226 | */ | 1226 | */ |
1227 | static int check_unsafe_exec(struct linux_binprm *bprm) | 1227 | static void check_unsafe_exec(struct linux_binprm *bprm) |
1228 | { | 1228 | { |
1229 | struct task_struct *p = current, *t; | 1229 | struct task_struct *p = current, *t; |
1230 | unsigned n_fs; | 1230 | unsigned n_fs; |
1231 | int res = 0; | ||
1232 | 1231 | ||
1233 | if (p->ptrace) { | 1232 | if (p->ptrace) { |
1234 | if (p->ptrace & PT_PTRACE_CAP) | 1233 | if (p->ptrace & PT_PTRACE_CAP) |
@@ -1244,31 +1243,25 @@ static int check_unsafe_exec(struct linux_binprm *bprm) | |||
1244 | if (current->no_new_privs) | 1243 | if (current->no_new_privs) |
1245 | bprm->unsafe |= LSM_UNSAFE_NO_NEW_PRIVS; | 1244 | bprm->unsafe |= LSM_UNSAFE_NO_NEW_PRIVS; |
1246 | 1245 | ||
1246 | t = p; | ||
1247 | n_fs = 1; | 1247 | n_fs = 1; |
1248 | spin_lock(&p->fs->lock); | 1248 | spin_lock(&p->fs->lock); |
1249 | rcu_read_lock(); | 1249 | rcu_read_lock(); |
1250 | for (t = next_thread(p); t != p; t = next_thread(t)) { | 1250 | while_each_thread(p, t) { |
1251 | if (t->fs == p->fs) | 1251 | if (t->fs == p->fs) |
1252 | n_fs++; | 1252 | n_fs++; |
1253 | } | 1253 | } |
1254 | rcu_read_unlock(); | 1254 | rcu_read_unlock(); |
1255 | 1255 | ||
1256 | if (p->fs->users > n_fs) { | 1256 | if (p->fs->users > n_fs) |
1257 | bprm->unsafe |= LSM_UNSAFE_SHARE; | 1257 | bprm->unsafe |= LSM_UNSAFE_SHARE; |
1258 | } else { | 1258 | else |
1259 | res = -EAGAIN; | 1259 | p->fs->in_exec = 1; |
1260 | if (!p->fs->in_exec) { | ||
1261 | p->fs->in_exec = 1; | ||
1262 | res = 1; | ||
1263 | } | ||
1264 | } | ||
1265 | spin_unlock(&p->fs->lock); | 1260 | spin_unlock(&p->fs->lock); |
1266 | |||
1267 | return res; | ||
1268 | } | 1261 | } |
1269 | 1262 | ||
1270 | /* | 1263 | /* |
1271 | * Fill the binprm structure from the inode. | 1264 | * Fill the binprm structure from the inode. |
1272 | * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes | 1265 | * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes |
1273 | * | 1266 | * |
1274 | * This may be called multiple times for binary chains (scripts for example). | 1267 | * This may be called multiple times for binary chains (scripts for example). |
@@ -1430,14 +1423,7 @@ static int exec_binprm(struct linux_binprm *bprm) | |||
1430 | audit_bprm(bprm); | 1423 | audit_bprm(bprm); |
1431 | trace_sched_process_exec(current, old_pid, bprm); | 1424 | trace_sched_process_exec(current, old_pid, bprm); |
1432 | ptrace_event(PTRACE_EVENT_EXEC, old_vpid); | 1425 | ptrace_event(PTRACE_EVENT_EXEC, old_vpid); |
1433 | current->did_exec = 1; | ||
1434 | proc_exec_connector(current); | 1426 | proc_exec_connector(current); |
1435 | |||
1436 | if (bprm->file) { | ||
1437 | allow_write_access(bprm->file); | ||
1438 | fput(bprm->file); | ||
1439 | bprm->file = NULL; /* to catch use-after-free */ | ||
1440 | } | ||
1441 | } | 1427 | } |
1442 | 1428 | ||
1443 | return ret; | 1429 | return ret; |
@@ -1453,7 +1439,6 @@ static int do_execve_common(const char *filename, | |||
1453 | struct linux_binprm *bprm; | 1439 | struct linux_binprm *bprm; |
1454 | struct file *file; | 1440 | struct file *file; |
1455 | struct files_struct *displaced; | 1441 | struct files_struct *displaced; |
1456 | bool clear_in_exec; | ||
1457 | int retval; | 1442 | int retval; |
1458 | 1443 | ||
1459 | /* | 1444 | /* |
@@ -1485,10 +1470,7 @@ static int do_execve_common(const char *filename, | |||
1485 | if (retval) | 1470 | if (retval) |
1486 | goto out_free; | 1471 | goto out_free; |
1487 | 1472 | ||
1488 | retval = check_unsafe_exec(bprm); | 1473 | check_unsafe_exec(bprm); |
1489 | if (retval < 0) | ||
1490 | goto out_free; | ||
1491 | clear_in_exec = retval; | ||
1492 | current->in_execve = 1; | 1474 | current->in_execve = 1; |
1493 | 1475 | ||
1494 | file = open_exec(filename); | 1476 | file = open_exec(filename); |
@@ -1504,7 +1486,7 @@ static int do_execve_common(const char *filename, | |||
1504 | 1486 | ||
1505 | retval = bprm_mm_init(bprm); | 1487 | retval = bprm_mm_init(bprm); |
1506 | if (retval) | 1488 | if (retval) |
1507 | goto out_file; | 1489 | goto out_unmark; |
1508 | 1490 | ||
1509 | bprm->argc = count(argv, MAX_ARG_STRINGS); | 1491 | bprm->argc = count(argv, MAX_ARG_STRINGS); |
1510 | if ((retval = bprm->argc) < 0) | 1492 | if ((retval = bprm->argc) < 0) |
@@ -1551,15 +1533,8 @@ out: | |||
1551 | mmput(bprm->mm); | 1533 | mmput(bprm->mm); |
1552 | } | 1534 | } |
1553 | 1535 | ||
1554 | out_file: | ||
1555 | if (bprm->file) { | ||
1556 | allow_write_access(bprm->file); | ||
1557 | fput(bprm->file); | ||
1558 | } | ||
1559 | |||
1560 | out_unmark: | 1536 | out_unmark: |
1561 | if (clear_in_exec) | 1537 | current->fs->in_exec = 0; |
1562 | current->fs->in_exec = 0; | ||
1563 | current->in_execve = 0; | 1538 | current->in_execve = 0; |
1564 | 1539 | ||
1565 | out_free: | 1540 | out_free: |
@@ -1609,67 +1584,22 @@ void set_binfmt(struct linux_binfmt *new) | |||
1609 | if (new) | 1584 | if (new) |
1610 | __module_get(new->module); | 1585 | __module_get(new->module); |
1611 | } | 1586 | } |
1612 | |||
1613 | EXPORT_SYMBOL(set_binfmt); | 1587 | EXPORT_SYMBOL(set_binfmt); |
1614 | 1588 | ||
1615 | /* | 1589 | /* |
1616 | * set_dumpable converts traditional three-value dumpable to two flags and | 1590 | * set_dumpable stores three-value SUID_DUMP_* into mm->flags. |
1617 | * stores them into mm->flags. It modifies lower two bits of mm->flags, but | ||
1618 | * these bits are not changed atomically. So get_dumpable can observe the | ||
1619 | * intermediate state. To avoid doing unexpected behavior, get get_dumpable | ||
1620 | * return either old dumpable or new one by paying attention to the order of | ||
1621 | * modifying the bits. | ||
1622 | * | ||
1623 | * dumpable | mm->flags (binary) | ||
1624 | * old new | initial interim final | ||
1625 | * ---------+----------------------- | ||
1626 | * 0 1 | 00 01 01 | ||
1627 | * 0 2 | 00 10(*) 11 | ||
1628 | * 1 0 | 01 00 00 | ||
1629 | * 1 2 | 01 11 11 | ||
1630 | * 2 0 | 11 10(*) 00 | ||
1631 | * 2 1 | 11 11 01 | ||
1632 | * | ||
1633 | * (*) get_dumpable regards interim value of 10 as 11. | ||
1634 | */ | 1591 | */ |
1635 | void set_dumpable(struct mm_struct *mm, int value) | 1592 | void set_dumpable(struct mm_struct *mm, int value) |
1636 | { | 1593 | { |
1637 | switch (value) { | 1594 | unsigned long old, new; |
1638 | case SUID_DUMP_DISABLE: | ||
1639 | clear_bit(MMF_DUMPABLE, &mm->flags); | ||
1640 | smp_wmb(); | ||
1641 | clear_bit(MMF_DUMP_SECURELY, &mm->flags); | ||
1642 | break; | ||
1643 | case SUID_DUMP_USER: | ||
1644 | set_bit(MMF_DUMPABLE, &mm->flags); | ||
1645 | smp_wmb(); | ||
1646 | clear_bit(MMF_DUMP_SECURELY, &mm->flags); | ||
1647 | break; | ||
1648 | case SUID_DUMP_ROOT: | ||
1649 | set_bit(MMF_DUMP_SECURELY, &mm->flags); | ||
1650 | smp_wmb(); | ||
1651 | set_bit(MMF_DUMPABLE, &mm->flags); | ||
1652 | break; | ||
1653 | } | ||
1654 | } | ||
1655 | |||
1656 | int __get_dumpable(unsigned long mm_flags) | ||
1657 | { | ||
1658 | int ret; | ||
1659 | 1595 | ||
1660 | ret = mm_flags & MMF_DUMPABLE_MASK; | 1596 | if (WARN_ON((unsigned)value > SUID_DUMP_ROOT)) |
1661 | return (ret > SUID_DUMP_USER) ? SUID_DUMP_ROOT : ret; | 1597 | return; |
1662 | } | ||
1663 | 1598 | ||
1664 | /* | 1599 | do { |
1665 | * This returns the actual value of the suid_dumpable flag. For things | 1600 | old = ACCESS_ONCE(mm->flags); |
1666 | * that are using this for checking for privilege transitions, it must | 1601 | new = (old & ~MMF_DUMPABLE_MASK) | value; |
1667 | * test against SUID_DUMP_USER rather than treating it as a boolean | 1602 | } while (cmpxchg(&mm->flags, old, new) != old); |
1668 | * value. | ||
1669 | */ | ||
1670 | int get_dumpable(struct mm_struct *mm) | ||
1671 | { | ||
1672 | return __get_dumpable(mm->flags); | ||
1673 | } | 1603 | } |
1674 | 1604 | ||
1675 | SYSCALL_DEFINE3(execve, | 1605 | SYSCALL_DEFINE3(execve, |
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index bafdd48eefde..e66e4808719f 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c | |||
@@ -309,43 +309,17 @@ struct fname { | |||
309 | */ | 309 | */ |
310 | static void free_rb_tree_fname(struct rb_root *root) | 310 | static void free_rb_tree_fname(struct rb_root *root) |
311 | { | 311 | { |
312 | struct rb_node *n = root->rb_node; | 312 | struct fname *fname, *next; |
313 | struct rb_node *parent; | 313 | |
314 | struct fname *fname; | 314 | rbtree_postorder_for_each_entry_safe(fname, next, root, rb_hash) |
315 | 315 | do { | |
316 | while (n) { | 316 | struct fname *old = fname; |
317 | /* Do the node's children first */ | ||
318 | if (n->rb_left) { | ||
319 | n = n->rb_left; | ||
320 | continue; | ||
321 | } | ||
322 | if (n->rb_right) { | ||
323 | n = n->rb_right; | ||
324 | continue; | ||
325 | } | ||
326 | /* | ||
327 | * The node has no children; free it, and then zero | ||
328 | * out parent's link to it. Finally go to the | ||
329 | * beginning of the loop and try to free the parent | ||
330 | * node. | ||
331 | */ | ||
332 | parent = rb_parent(n); | ||
333 | fname = rb_entry(n, struct fname, rb_hash); | ||
334 | while (fname) { | ||
335 | struct fname * old = fname; | ||
336 | fname = fname->next; | 317 | fname = fname->next; |
337 | kfree (old); | 318 | kfree(old); |
338 | } | 319 | } while (fname); |
339 | if (!parent) | ||
340 | *root = RB_ROOT; | ||
341 | else if (parent->rb_left == n) | ||
342 | parent->rb_left = NULL; | ||
343 | else if (parent->rb_right == n) | ||
344 | parent->rb_right = NULL; | ||
345 | n = parent; | ||
346 | } | ||
347 | } | ||
348 | 320 | ||
321 | *root = RB_ROOT; | ||
322 | } | ||
349 | 323 | ||
350 | static struct dir_private_info *ext3_htree_create_dir_info(struct file *filp, | 324 | static struct dir_private_info *ext3_htree_create_dir_info(struct file *filp, |
351 | loff_t pos) | 325 | loff_t pos) |
diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c index 3f11656bd72e..41eb9dcfac7e 100644 --- a/fs/ext4/block_validity.c +++ b/fs/ext4/block_validity.c | |||
@@ -180,37 +180,12 @@ int ext4_setup_system_zone(struct super_block *sb) | |||
180 | /* Called when the filesystem is unmounted */ | 180 | /* Called when the filesystem is unmounted */ |
181 | void ext4_release_system_zone(struct super_block *sb) | 181 | void ext4_release_system_zone(struct super_block *sb) |
182 | { | 182 | { |
183 | struct rb_node *n = EXT4_SB(sb)->system_blks.rb_node; | 183 | struct ext4_system_zone *entry, *n; |
184 | struct rb_node *parent; | ||
185 | struct ext4_system_zone *entry; | ||
186 | 184 | ||
187 | while (n) { | 185 | rbtree_postorder_for_each_entry_safe(entry, n, |
188 | /* Do the node's children first */ | 186 | &EXT4_SB(sb)->system_blks, node) |
189 | if (n->rb_left) { | ||
190 | n = n->rb_left; | ||
191 | continue; | ||
192 | } | ||
193 | if (n->rb_right) { | ||
194 | n = n->rb_right; | ||
195 | continue; | ||
196 | } | ||
197 | /* | ||
198 | * The node has no children; free it, and then zero | ||
199 | * out parent's link to it. Finally go to the | ||
200 | * beginning of the loop and try to free the parent | ||
201 | * node. | ||
202 | */ | ||
203 | parent = rb_parent(n); | ||
204 | entry = rb_entry(n, struct ext4_system_zone, node); | ||
205 | kmem_cache_free(ext4_system_zone_cachep, entry); | 187 | kmem_cache_free(ext4_system_zone_cachep, entry); |
206 | if (!parent) | 188 | |
207 | EXT4_SB(sb)->system_blks = RB_ROOT; | ||
208 | else if (parent->rb_left == n) | ||
209 | parent->rb_left = NULL; | ||
210 | else if (parent->rb_right == n) | ||
211 | parent->rb_right = NULL; | ||
212 | n = parent; | ||
213 | } | ||
214 | EXT4_SB(sb)->system_blks = RB_ROOT; | 189 | EXT4_SB(sb)->system_blks = RB_ROOT; |
215 | } | 190 | } |
216 | 191 | ||
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index 680bb3388919..d638c57e996e 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c | |||
@@ -353,41 +353,16 @@ struct fname { | |||
353 | */ | 353 | */ |
354 | static void free_rb_tree_fname(struct rb_root *root) | 354 | static void free_rb_tree_fname(struct rb_root *root) |
355 | { | 355 | { |
356 | struct rb_node *n = root->rb_node; | 356 | struct fname *fname, *next; |
357 | struct rb_node *parent; | 357 | |
358 | struct fname *fname; | 358 | rbtree_postorder_for_each_entry_safe(fname, next, root, rb_hash) |
359 | |||
360 | while (n) { | ||
361 | /* Do the node's children first */ | ||
362 | if (n->rb_left) { | ||
363 | n = n->rb_left; | ||
364 | continue; | ||
365 | } | ||
366 | if (n->rb_right) { | ||
367 | n = n->rb_right; | ||
368 | continue; | ||
369 | } | ||
370 | /* | ||
371 | * The node has no children; free it, and then zero | ||
372 | * out parent's link to it. Finally go to the | ||
373 | * beginning of the loop and try to free the parent | ||
374 | * node. | ||
375 | */ | ||
376 | parent = rb_parent(n); | ||
377 | fname = rb_entry(n, struct fname, rb_hash); | ||
378 | while (fname) { | 359 | while (fname) { |
379 | struct fname *old = fname; | 360 | struct fname *old = fname; |
380 | fname = fname->next; | 361 | fname = fname->next; |
381 | kfree(old); | 362 | kfree(old); |
382 | } | 363 | } |
383 | if (!parent) | 364 | |
384 | *root = RB_ROOT; | 365 | *root = RB_ROOT; |
385 | else if (parent->rb_left == n) | ||
386 | parent->rb_left = NULL; | ||
387 | else if (parent->rb_right == n) | ||
388 | parent->rb_right = NULL; | ||
389 | n = parent; | ||
390 | } | ||
391 | } | 366 | } |
392 | 367 | ||
393 | 368 | ||
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 37213d075f3c..3ebda928229c 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c | |||
@@ -178,64 +178,6 @@ const struct dentry_operations hfsplus_dentry_operations = { | |||
178 | .d_compare = hfsplus_compare_dentry, | 178 | .d_compare = hfsplus_compare_dentry, |
179 | }; | 179 | }; |
180 | 180 | ||
181 | static struct dentry *hfsplus_file_lookup(struct inode *dir, | ||
182 | struct dentry *dentry, unsigned int flags) | ||
183 | { | ||
184 | struct hfs_find_data fd; | ||
185 | struct super_block *sb = dir->i_sb; | ||
186 | struct inode *inode = NULL; | ||
187 | struct hfsplus_inode_info *hip; | ||
188 | int err; | ||
189 | |||
190 | if (HFSPLUS_IS_RSRC(dir) || strcmp(dentry->d_name.name, "rsrc")) | ||
191 | goto out; | ||
192 | |||
193 | inode = HFSPLUS_I(dir)->rsrc_inode; | ||
194 | if (inode) | ||
195 | goto out; | ||
196 | |||
197 | inode = new_inode(sb); | ||
198 | if (!inode) | ||
199 | return ERR_PTR(-ENOMEM); | ||
200 | |||
201 | hip = HFSPLUS_I(inode); | ||
202 | inode->i_ino = dir->i_ino; | ||
203 | INIT_LIST_HEAD(&hip->open_dir_list); | ||
204 | mutex_init(&hip->extents_lock); | ||
205 | hip->extent_state = 0; | ||
206 | hip->flags = 0; | ||
207 | hip->userflags = 0; | ||
208 | set_bit(HFSPLUS_I_RSRC, &hip->flags); | ||
209 | |||
210 | err = hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd); | ||
211 | if (!err) { | ||
212 | err = hfsplus_find_cat(sb, dir->i_ino, &fd); | ||
213 | if (!err) | ||
214 | err = hfsplus_cat_read_inode(inode, &fd); | ||
215 | hfs_find_exit(&fd); | ||
216 | } | ||
217 | if (err) { | ||
218 | iput(inode); | ||
219 | return ERR_PTR(err); | ||
220 | } | ||
221 | hip->rsrc_inode = dir; | ||
222 | HFSPLUS_I(dir)->rsrc_inode = inode; | ||
223 | igrab(dir); | ||
224 | |||
225 | /* | ||
226 | * __mark_inode_dirty expects inodes to be hashed. Since we don't | ||
227 | * want resource fork inodes in the regular inode space, we make them | ||
228 | * appear hashed, but do not put on any lists. hlist_del() | ||
229 | * will work fine and require no locking. | ||
230 | */ | ||
231 | hlist_add_fake(&inode->i_hash); | ||
232 | |||
233 | mark_inode_dirty(inode); | ||
234 | out: | ||
235 | d_add(dentry, inode); | ||
236 | return NULL; | ||
237 | } | ||
238 | |||
239 | static void hfsplus_get_perms(struct inode *inode, | 181 | static void hfsplus_get_perms(struct inode *inode, |
240 | struct hfsplus_perm *perms, int dir) | 182 | struct hfsplus_perm *perms, int dir) |
241 | { | 183 | { |
@@ -385,7 +327,6 @@ int hfsplus_file_fsync(struct file *file, loff_t start, loff_t end, | |||
385 | } | 327 | } |
386 | 328 | ||
387 | static const struct inode_operations hfsplus_file_inode_operations = { | 329 | static const struct inode_operations hfsplus_file_inode_operations = { |
388 | .lookup = hfsplus_file_lookup, | ||
389 | .setattr = hfsplus_setattr, | 330 | .setattr = hfsplus_setattr, |
390 | .setxattr = generic_setxattr, | 331 | .setxattr = generic_setxattr, |
391 | .getxattr = generic_getxattr, | 332 | .getxattr = generic_getxattr, |
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 975a1f562c10..9a5449bc3afb 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c | |||
@@ -564,25 +564,10 @@ struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_ | |||
564 | they're killed. */ | 564 | they're killed. */ |
565 | void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) | 565 | void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) |
566 | { | 566 | { |
567 | struct jffs2_node_frag *frag; | 567 | struct jffs2_node_frag *frag, *next; |
568 | struct jffs2_node_frag *parent; | ||
569 | |||
570 | if (!root->rb_node) | ||
571 | return; | ||
572 | 568 | ||
573 | dbg_fragtree("killing\n"); | 569 | dbg_fragtree("killing\n"); |
574 | 570 | rbtree_postorder_for_each_entry_safe(frag, next, root, rb) { | |
575 | frag = (rb_entry(root->rb_node, struct jffs2_node_frag, rb)); | ||
576 | while(frag) { | ||
577 | if (frag->rb.rb_left) { | ||
578 | frag = frag_left(frag); | ||
579 | continue; | ||
580 | } | ||
581 | if (frag->rb.rb_right) { | ||
582 | frag = frag_right(frag); | ||
583 | continue; | ||
584 | } | ||
585 | |||
586 | if (frag->node && !(--frag->node->frags)) { | 571 | if (frag->node && !(--frag->node->frags)) { |
587 | /* Not a hole, and it's the final remaining frag | 572 | /* Not a hole, and it's the final remaining frag |
588 | of this node. Free the node */ | 573 | of this node. Free the node */ |
@@ -591,17 +576,8 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) | |||
591 | 576 | ||
592 | jffs2_free_full_dnode(frag->node); | 577 | jffs2_free_full_dnode(frag->node); |
593 | } | 578 | } |
594 | parent = frag_parent(frag); | ||
595 | if (parent) { | ||
596 | if (frag_left(parent) == frag) | ||
597 | parent->rb.rb_left = NULL; | ||
598 | else | ||
599 | parent->rb.rb_right = NULL; | ||
600 | } | ||
601 | 579 | ||
602 | jffs2_free_node_frag(frag); | 580 | jffs2_free_node_frag(frag); |
603 | frag = parent; | ||
604 | |||
605 | cond_resched(); | 581 | cond_resched(); |
606 | } | 582 | } |
607 | } | 583 | } |
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index ae81b01e6fd7..386303dca382 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c | |||
@@ -543,33 +543,13 @@ static int jffs2_build_inode_fragtree(struct jffs2_sb_info *c, | |||
543 | 543 | ||
544 | static void jffs2_free_tmp_dnode_info_list(struct rb_root *list) | 544 | static void jffs2_free_tmp_dnode_info_list(struct rb_root *list) |
545 | { | 545 | { |
546 | struct rb_node *this; | 546 | struct jffs2_tmp_dnode_info *tn, *next; |
547 | struct jffs2_tmp_dnode_info *tn; | ||
548 | |||
549 | this = list->rb_node; | ||
550 | 547 | ||
551 | /* Now at bottom of tree */ | 548 | rbtree_postorder_for_each_entry_safe(tn, next, list, rb) { |
552 | while (this) { | ||
553 | if (this->rb_left) | ||
554 | this = this->rb_left; | ||
555 | else if (this->rb_right) | ||
556 | this = this->rb_right; | ||
557 | else { | ||
558 | tn = rb_entry(this, struct jffs2_tmp_dnode_info, rb); | ||
559 | jffs2_free_full_dnode(tn->fn); | 549 | jffs2_free_full_dnode(tn->fn); |
560 | jffs2_free_tmp_dnode_info(tn); | 550 | jffs2_free_tmp_dnode_info(tn); |
561 | |||
562 | this = rb_parent(this); | ||
563 | if (!this) | ||
564 | break; | ||
565 | |||
566 | if (this->rb_left == &tn->rb) | ||
567 | this->rb_left = NULL; | ||
568 | else if (this->rb_right == &tn->rb) | ||
569 | this->rb_right = NULL; | ||
570 | else BUG(); | ||
571 | } | ||
572 | } | 551 | } |
552 | |||
573 | *list = RB_ROOT; | 553 | *list = RB_ROOT; |
574 | } | 554 | } |
575 | 555 | ||
diff --git a/fs/logfs/segment.c b/fs/logfs/segment.c index d448a777166b..7f9b096d8d57 100644 --- a/fs/logfs/segment.c +++ b/fs/logfs/segment.c | |||
@@ -62,7 +62,8 @@ static struct page *get_mapping_page(struct super_block *sb, pgoff_t index, | |||
62 | page = read_cache_page(mapping, index, filler, sb); | 62 | page = read_cache_page(mapping, index, filler, sb); |
63 | else { | 63 | else { |
64 | page = find_or_create_page(mapping, index, GFP_NOFS); | 64 | page = find_or_create_page(mapping, index, GFP_NOFS); |
65 | unlock_page(page); | 65 | if (page) |
66 | unlock_page(page); | ||
66 | } | 67 | } |
67 | return page; | 68 | return page; |
68 | } | 69 | } |
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index b44bdb291b84..2b34021948e4 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c | |||
@@ -37,7 +37,26 @@ | |||
37 | #include "sufile.h" | 37 | #include "sufile.h" |
38 | #include "dat.h" | 38 | #include "dat.h" |
39 | 39 | ||
40 | 40 | /** | |
41 | * nilfs_ioctl_wrap_copy - wrapping function of get/set metadata info | ||
42 | * @nilfs: nilfs object | ||
43 | * @argv: vector of arguments from userspace | ||
44 | * @dir: set of direction flags | ||
45 | * @dofunc: concrete function of get/set metadata info | ||
46 | * | ||
47 | * Description: nilfs_ioctl_wrap_copy() gets/sets metadata info by means of | ||
48 | * calling dofunc() function on the basis of @argv argument. | ||
49 | * | ||
50 | * Return Value: On success, 0 is returned and requested metadata info | ||
51 | * is copied into userspace. On error, one of the following | ||
52 | * negative error codes is returned. | ||
53 | * | ||
54 | * %-EINVAL - Invalid arguments from userspace. | ||
55 | * | ||
56 | * %-ENOMEM - Insufficient amount of memory available. | ||
57 | * | ||
58 | * %-EFAULT - Failure during execution of requested operation. | ||
59 | */ | ||
41 | static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs, | 60 | static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs, |
42 | struct nilfs_argv *argv, int dir, | 61 | struct nilfs_argv *argv, int dir, |
43 | ssize_t (*dofunc)(struct the_nilfs *, | 62 | ssize_t (*dofunc)(struct the_nilfs *, |
@@ -57,6 +76,14 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs, | |||
57 | if (argv->v_size > PAGE_SIZE) | 76 | if (argv->v_size > PAGE_SIZE) |
58 | return -EINVAL; | 77 | return -EINVAL; |
59 | 78 | ||
79 | /* | ||
80 | * Reject pairs of a start item position (argv->v_index) and a | ||
81 | * total count (argv->v_nmembs) which leads position 'pos' to | ||
82 | * overflow by the increment at the end of the loop. | ||
83 | */ | ||
84 | if (argv->v_index > ~(__u64)0 - argv->v_nmembs) | ||
85 | return -EINVAL; | ||
86 | |||
60 | buf = (void *)__get_free_pages(GFP_NOFS, 0); | 87 | buf = (void *)__get_free_pages(GFP_NOFS, 0); |
61 | if (unlikely(!buf)) | 88 | if (unlikely(!buf)) |
62 | return -ENOMEM; | 89 | return -ENOMEM; |
@@ -99,6 +126,9 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs, | |||
99 | return ret; | 126 | return ret; |
100 | } | 127 | } |
101 | 128 | ||
129 | /** | ||
130 | * nilfs_ioctl_getflags - ioctl to support lsattr | ||
131 | */ | ||
102 | static int nilfs_ioctl_getflags(struct inode *inode, void __user *argp) | 132 | static int nilfs_ioctl_getflags(struct inode *inode, void __user *argp) |
103 | { | 133 | { |
104 | unsigned int flags = NILFS_I(inode)->i_flags & FS_FL_USER_VISIBLE; | 134 | unsigned int flags = NILFS_I(inode)->i_flags & FS_FL_USER_VISIBLE; |
@@ -106,6 +136,9 @@ static int nilfs_ioctl_getflags(struct inode *inode, void __user *argp) | |||
106 | return put_user(flags, (int __user *)argp); | 136 | return put_user(flags, (int __user *)argp); |
107 | } | 137 | } |
108 | 138 | ||
139 | /** | ||
140 | * nilfs_ioctl_setflags - ioctl to support chattr | ||
141 | */ | ||
109 | static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp, | 142 | static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp, |
110 | void __user *argp) | 143 | void __user *argp) |
111 | { | 144 | { |
@@ -158,11 +191,33 @@ out: | |||
158 | return ret; | 191 | return ret; |
159 | } | 192 | } |
160 | 193 | ||
194 | /** | ||
195 | * nilfs_ioctl_getversion - get info about a file's version (generation number) | ||
196 | */ | ||
161 | static int nilfs_ioctl_getversion(struct inode *inode, void __user *argp) | 197 | static int nilfs_ioctl_getversion(struct inode *inode, void __user *argp) |
162 | { | 198 | { |
163 | return put_user(inode->i_generation, (int __user *)argp); | 199 | return put_user(inode->i_generation, (int __user *)argp); |
164 | } | 200 | } |
165 | 201 | ||
202 | /** | ||
203 | * nilfs_ioctl_change_cpmode - change checkpoint mode (checkpoint/snapshot) | ||
204 | * @inode: inode object | ||
205 | * @filp: file object | ||
206 | * @cmd: ioctl's request code | ||
207 | * @argp: pointer on argument from userspace | ||
208 | * | ||
209 | * Description: nilfs_ioctl_change_cpmode() function changes mode of | ||
210 | * given checkpoint between checkpoint and snapshot state. This ioctl | ||
211 | * is used in chcp and mkcp utilities. | ||
212 | * | ||
213 | * Return Value: On success, 0 is returned and mode of a checkpoint is | ||
214 | * changed. On error, one of the following negative error codes | ||
215 | * is returned. | ||
216 | * | ||
217 | * %-EPERM - Operation not permitted. | ||
218 | * | ||
219 | * %-EFAULT - Failure during checkpoint mode changing. | ||
220 | */ | ||
166 | static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, | 221 | static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, |
167 | unsigned int cmd, void __user *argp) | 222 | unsigned int cmd, void __user *argp) |
168 | { | 223 | { |
@@ -198,6 +253,25 @@ out: | |||
198 | return ret; | 253 | return ret; |
199 | } | 254 | } |
200 | 255 | ||
256 | /** | ||
257 | * nilfs_ioctl_delete_checkpoint - remove checkpoint | ||
258 | * @inode: inode object | ||
259 | * @filp: file object | ||
260 | * @cmd: ioctl's request code | ||
261 | * @argp: pointer on argument from userspace | ||
262 | * | ||
263 | * Description: nilfs_ioctl_delete_checkpoint() function removes | ||
264 | * checkpoint from NILFS2 file system. This ioctl is used in rmcp | ||
265 | * utility. | ||
266 | * | ||
267 | * Return Value: On success, 0 is returned and a checkpoint is | ||
268 | * removed. On error, one of the following negative error codes | ||
269 | * is returned. | ||
270 | * | ||
271 | * %-EPERM - Operation not permitted. | ||
272 | * | ||
273 | * %-EFAULT - Failure during checkpoint removing. | ||
274 | */ | ||
201 | static int | 275 | static int |
202 | nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp, | 276 | nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp, |
203 | unsigned int cmd, void __user *argp) | 277 | unsigned int cmd, void __user *argp) |
@@ -229,6 +303,21 @@ out: | |||
229 | return ret; | 303 | return ret; |
230 | } | 304 | } |
231 | 305 | ||
306 | /** | ||
307 | * nilfs_ioctl_do_get_cpinfo - callback method getting info about checkpoints | ||
308 | * @nilfs: nilfs object | ||
309 | * @posp: pointer on array of checkpoint's numbers | ||
310 | * @flags: checkpoint mode (checkpoint or snapshot) | ||
311 | * @buf: buffer for storing checkponts' info | ||
312 | * @size: size in bytes of one checkpoint info item in array | ||
313 | * @nmembs: number of checkpoints in array (numbers and infos) | ||
314 | * | ||
315 | * Description: nilfs_ioctl_do_get_cpinfo() function returns info about | ||
316 | * requested checkpoints. The NILFS_IOCTL_GET_CPINFO ioctl is used in | ||
317 | * lscp utility and by nilfs_cleanerd daemon. | ||
318 | * | ||
319 | * Return value: count of nilfs_cpinfo structures in output buffer. | ||
320 | */ | ||
232 | static ssize_t | 321 | static ssize_t |
233 | nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, | 322 | nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, |
234 | void *buf, size_t size, size_t nmembs) | 323 | void *buf, size_t size, size_t nmembs) |
@@ -242,6 +331,27 @@ nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, | |||
242 | return ret; | 331 | return ret; |
243 | } | 332 | } |
244 | 333 | ||
334 | /** | ||
335 | * nilfs_ioctl_get_cpstat - get checkpoints statistics | ||
336 | * @inode: inode object | ||
337 | * @filp: file object | ||
338 | * @cmd: ioctl's request code | ||
339 | * @argp: pointer on argument from userspace | ||
340 | * | ||
341 | * Description: nilfs_ioctl_get_cpstat() returns information about checkpoints. | ||
342 | * The NILFS_IOCTL_GET_CPSTAT ioctl is used by lscp, rmcp utilities | ||
343 | * and by nilfs_cleanerd daemon. | ||
344 | * | ||
345 | * Return Value: On success, 0 is returned, and checkpoints information is | ||
346 | * copied into userspace pointer @argp. On error, one of the following | ||
347 | * negative error codes is returned. | ||
348 | * | ||
349 | * %-EIO - I/O error. | ||
350 | * | ||
351 | * %-ENOMEM - Insufficient amount of memory available. | ||
352 | * | ||
353 | * %-EFAULT - Failure during getting checkpoints statistics. | ||
354 | */ | ||
245 | static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp, | 355 | static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp, |
246 | unsigned int cmd, void __user *argp) | 356 | unsigned int cmd, void __user *argp) |
247 | { | 357 | { |
@@ -260,6 +370,21 @@ static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp, | |||
260 | return ret; | 370 | return ret; |
261 | } | 371 | } |
262 | 372 | ||
373 | /** | ||
374 | * nilfs_ioctl_do_get_suinfo - callback method getting segment usage info | ||
375 | * @nilfs: nilfs object | ||
376 | * @posp: pointer on array of segment numbers | ||
377 | * @flags: *not used* | ||
378 | * @buf: buffer for storing suinfo array | ||
379 | * @size: size in bytes of one suinfo item in array | ||
380 | * @nmembs: count of segment numbers and suinfos in array | ||
381 | * | ||
382 | * Description: nilfs_ioctl_do_get_suinfo() function returns segment usage | ||
383 | * info about requested segments. The NILFS_IOCTL_GET_SUINFO ioctl is used | ||
384 | * in lssu, nilfs_resize utilities and by nilfs_cleanerd daemon. | ||
385 | * | ||
386 | * Return value: count of nilfs_suinfo structures in output buffer. | ||
387 | */ | ||
263 | static ssize_t | 388 | static ssize_t |
264 | nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, | 389 | nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, |
265 | void *buf, size_t size, size_t nmembs) | 390 | void *buf, size_t size, size_t nmembs) |
@@ -273,6 +398,27 @@ nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, | |||
273 | return ret; | 398 | return ret; |
274 | } | 399 | } |
275 | 400 | ||
401 | /** | ||
402 | * nilfs_ioctl_get_sustat - get segment usage statistics | ||
403 | * @inode: inode object | ||
404 | * @filp: file object | ||
405 | * @cmd: ioctl's request code | ||
406 | * @argp: pointer on argument from userspace | ||
407 | * | ||
408 | * Description: nilfs_ioctl_get_sustat() returns segment usage statistics. | ||
409 | * The NILFS_IOCTL_GET_SUSTAT ioctl is used in lssu, nilfs_resize utilities | ||
410 | * and by nilfs_cleanerd daemon. | ||
411 | * | ||
412 | * Return Value: On success, 0 is returned, and segment usage information is | ||
413 | * copied into userspace pointer @argp. On error, one of the following | ||
414 | * negative error codes is returned. | ||
415 | * | ||
416 | * %-EIO - I/O error. | ||
417 | * | ||
418 | * %-ENOMEM - Insufficient amount of memory available. | ||
419 | * | ||
420 | * %-EFAULT - Failure during getting segment usage statistics. | ||
421 | */ | ||
276 | static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp, | 422 | static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp, |
277 | unsigned int cmd, void __user *argp) | 423 | unsigned int cmd, void __user *argp) |
278 | { | 424 | { |
@@ -291,6 +437,21 @@ static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp, | |||
291 | return ret; | 437 | return ret; |
292 | } | 438 | } |
293 | 439 | ||
440 | /** | ||
441 | * nilfs_ioctl_do_get_vinfo - callback method getting virtual blocks info | ||
442 | * @nilfs: nilfs object | ||
443 | * @posp: *not used* | ||
444 | * @flags: *not used* | ||
445 | * @buf: buffer for storing array of nilfs_vinfo structures | ||
446 | * @size: size in bytes of one vinfo item in array | ||
447 | * @nmembs: count of vinfos in array | ||
448 | * | ||
449 | * Description: nilfs_ioctl_do_get_vinfo() function returns information | ||
450 | * on virtual block addresses. The NILFS_IOCTL_GET_VINFO ioctl is used | ||
451 | * by nilfs_cleanerd daemon. | ||
452 | * | ||
453 | * Return value: count of nilfs_vinfo structures in output buffer. | ||
454 | */ | ||
294 | static ssize_t | 455 | static ssize_t |
295 | nilfs_ioctl_do_get_vinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, | 456 | nilfs_ioctl_do_get_vinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, |
296 | void *buf, size_t size, size_t nmembs) | 457 | void *buf, size_t size, size_t nmembs) |
@@ -303,6 +464,21 @@ nilfs_ioctl_do_get_vinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, | |||
303 | return ret; | 464 | return ret; |
304 | } | 465 | } |
305 | 466 | ||
467 | /** | ||
468 | * nilfs_ioctl_do_get_bdescs - callback method getting disk block descriptors | ||
469 | * @nilfs: nilfs object | ||
470 | * @posp: *not used* | ||
471 | * @flags: *not used* | ||
472 | * @buf: buffer for storing array of nilfs_bdesc structures | ||
473 | * @size: size in bytes of one bdesc item in array | ||
474 | * @nmembs: count of bdescs in array | ||
475 | * | ||
476 | * Description: nilfs_ioctl_do_get_bdescs() function returns information | ||
477 | * about descriptors of disk block numbers. The NILFS_IOCTL_GET_BDESCS ioctl | ||
478 | * is used by nilfs_cleanerd daemon. | ||
479 | * | ||
480 | * Return value: count of nilfs_bdescs structures in output buffer. | ||
481 | */ | ||
306 | static ssize_t | 482 | static ssize_t |
307 | nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags, | 483 | nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags, |
308 | void *buf, size_t size, size_t nmembs) | 484 | void *buf, size_t size, size_t nmembs) |
@@ -329,6 +505,29 @@ nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags, | |||
329 | return nmembs; | 505 | return nmembs; |
330 | } | 506 | } |
331 | 507 | ||
508 | /** | ||
509 | * nilfs_ioctl_get_bdescs - get disk block descriptors | ||
510 | * @inode: inode object | ||
511 | * @filp: file object | ||
512 | * @cmd: ioctl's request code | ||
513 | * @argp: pointer on argument from userspace | ||
514 | * | ||
515 | * Description: nilfs_ioctl_do_get_bdescs() function returns information | ||
516 | * about descriptors of disk block numbers. The NILFS_IOCTL_GET_BDESCS ioctl | ||
517 | * is used by nilfs_cleanerd daemon. | ||
518 | * | ||
519 | * Return Value: On success, 0 is returned, and disk block descriptors are | ||
520 | * copied into userspace pointer @argp. On error, one of the following | ||
521 | * negative error codes is returned. | ||
522 | * | ||
523 | * %-EINVAL - Invalid arguments from userspace. | ||
524 | * | ||
525 | * %-EIO - I/O error. | ||
526 | * | ||
527 | * %-ENOMEM - Insufficient amount of memory available. | ||
528 | * | ||
529 | * %-EFAULT - Failure during getting disk block descriptors. | ||
530 | */ | ||
332 | static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp, | 531 | static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp, |
333 | unsigned int cmd, void __user *argp) | 532 | unsigned int cmd, void __user *argp) |
334 | { | 533 | { |
@@ -352,6 +551,26 @@ static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp, | |||
352 | return ret; | 551 | return ret; |
353 | } | 552 | } |
354 | 553 | ||
554 | /** | ||
555 | * nilfs_ioctl_move_inode_block - prepare data/node block for moving by GC | ||
556 | * @inode: inode object | ||
557 | * @vdesc: descriptor of virtual block number | ||
558 | * @buffers: list of moving buffers | ||
559 | * | ||
560 | * Description: nilfs_ioctl_move_inode_block() function registers data/node | ||
561 | * buffer in the GC pagecache and submit read request. | ||
562 | * | ||
563 | * Return Value: On success, 0 is returned. On error, one of the following | ||
564 | * negative error codes is returned. | ||
565 | * | ||
566 | * %-EIO - I/O error. | ||
567 | * | ||
568 | * %-ENOMEM - Insufficient amount of memory available. | ||
569 | * | ||
570 | * %-ENOENT - Requested block doesn't exist. | ||
571 | * | ||
572 | * %-EEXIST - Blocks conflict is detected. | ||
573 | */ | ||
355 | static int nilfs_ioctl_move_inode_block(struct inode *inode, | 574 | static int nilfs_ioctl_move_inode_block(struct inode *inode, |
356 | struct nilfs_vdesc *vdesc, | 575 | struct nilfs_vdesc *vdesc, |
357 | struct list_head *buffers) | 576 | struct list_head *buffers) |
@@ -397,6 +616,19 @@ static int nilfs_ioctl_move_inode_block(struct inode *inode, | |||
397 | return 0; | 616 | return 0; |
398 | } | 617 | } |
399 | 618 | ||
619 | /** | ||
620 | * nilfs_ioctl_move_blocks - move valid inode's blocks during garbage collection | ||
621 | * @sb: superblock object | ||
622 | * @argv: vector of arguments from userspace | ||
623 | * @buf: array of nilfs_vdesc structures | ||
624 | * | ||
625 | * Description: nilfs_ioctl_move_blocks() function reads valid data/node | ||
626 | * blocks that garbage collector specified with the array of nilfs_vdesc | ||
627 | * structures and stores them into page caches of GC inodes. | ||
628 | * | ||
629 | * Return Value: Number of processed nilfs_vdesc structures or | ||
630 | * error code, otherwise. | ||
631 | */ | ||
400 | static int nilfs_ioctl_move_blocks(struct super_block *sb, | 632 | static int nilfs_ioctl_move_blocks(struct super_block *sb, |
401 | struct nilfs_argv *argv, void *buf) | 633 | struct nilfs_argv *argv, void *buf) |
402 | { | 634 | { |
@@ -462,6 +694,25 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb, | |||
462 | return ret; | 694 | return ret; |
463 | } | 695 | } |
464 | 696 | ||
697 | /** | ||
698 | * nilfs_ioctl_delete_checkpoints - delete checkpoints | ||
699 | * @nilfs: nilfs object | ||
700 | * @argv: vector of arguments from userspace | ||
701 | * @buf: array of periods of checkpoints numbers | ||
702 | * | ||
703 | * Description: nilfs_ioctl_delete_checkpoints() function deletes checkpoints | ||
704 | * in the period from p_start to p_end, excluding p_end itself. The checkpoints | ||
705 | * which have been already deleted are ignored. | ||
706 | * | ||
707 | * Return Value: Number of processed nilfs_period structures or | ||
708 | * error code, otherwise. | ||
709 | * | ||
710 | * %-EIO - I/O error. | ||
711 | * | ||
712 | * %-ENOMEM - Insufficient amount of memory available. | ||
713 | * | ||
714 | * %-EINVAL - invalid checkpoints. | ||
715 | */ | ||
465 | static int nilfs_ioctl_delete_checkpoints(struct the_nilfs *nilfs, | 716 | static int nilfs_ioctl_delete_checkpoints(struct the_nilfs *nilfs, |
466 | struct nilfs_argv *argv, void *buf) | 717 | struct nilfs_argv *argv, void *buf) |
467 | { | 718 | { |
@@ -479,6 +730,24 @@ static int nilfs_ioctl_delete_checkpoints(struct the_nilfs *nilfs, | |||
479 | return nmembs; | 730 | return nmembs; |
480 | } | 731 | } |
481 | 732 | ||
733 | /** | ||
734 | * nilfs_ioctl_free_vblocknrs - free virtual block numbers | ||
735 | * @nilfs: nilfs object | ||
736 | * @argv: vector of arguments from userspace | ||
737 | * @buf: array of virtual block numbers | ||
738 | * | ||
739 | * Description: nilfs_ioctl_free_vblocknrs() function frees | ||
740 | * the virtual block numbers specified by @buf and @argv->v_nmembs. | ||
741 | * | ||
742 | * Return Value: Number of processed virtual block numbers or | ||
743 | * error code, otherwise. | ||
744 | * | ||
745 | * %-EIO - I/O error. | ||
746 | * | ||
747 | * %-ENOMEM - Insufficient amount of memory available. | ||
748 | * | ||
749 | * %-ENOENT - The virtual block number have not been allocated. | ||
750 | */ | ||
482 | static int nilfs_ioctl_free_vblocknrs(struct the_nilfs *nilfs, | 751 | static int nilfs_ioctl_free_vblocknrs(struct the_nilfs *nilfs, |
483 | struct nilfs_argv *argv, void *buf) | 752 | struct nilfs_argv *argv, void *buf) |
484 | { | 753 | { |
@@ -490,6 +759,24 @@ static int nilfs_ioctl_free_vblocknrs(struct the_nilfs *nilfs, | |||
490 | return (ret < 0) ? ret : nmembs; | 759 | return (ret < 0) ? ret : nmembs; |
491 | } | 760 | } |
492 | 761 | ||
762 | /** | ||
763 | * nilfs_ioctl_mark_blocks_dirty - mark blocks dirty | ||
764 | * @nilfs: nilfs object | ||
765 | * @argv: vector of arguments from userspace | ||
766 | * @buf: array of block descriptors | ||
767 | * | ||
768 | * Description: nilfs_ioctl_mark_blocks_dirty() function marks | ||
769 | * metadata file or data blocks as dirty. | ||
770 | * | ||
771 | * Return Value: Number of processed block descriptors or | ||
772 | * error code, otherwise. | ||
773 | * | ||
774 | * %-ENOMEM - Insufficient memory available. | ||
775 | * | ||
776 | * %-EIO - I/O error | ||
777 | * | ||
778 | * %-ENOENT - the specified block does not exist (hole block) | ||
779 | */ | ||
493 | static int nilfs_ioctl_mark_blocks_dirty(struct the_nilfs *nilfs, | 780 | static int nilfs_ioctl_mark_blocks_dirty(struct the_nilfs *nilfs, |
494 | struct nilfs_argv *argv, void *buf) | 781 | struct nilfs_argv *argv, void *buf) |
495 | { | 782 | { |
@@ -571,6 +858,20 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs, | |||
571 | return ret; | 858 | return ret; |
572 | } | 859 | } |
573 | 860 | ||
861 | /** | ||
862 | * nilfs_ioctl_clean_segments - clean segments | ||
863 | * @inode: inode object | ||
864 | * @filp: file object | ||
865 | * @cmd: ioctl's request code | ||
866 | * @argp: pointer on argument from userspace | ||
867 | * | ||
868 | * Description: nilfs_ioctl_clean_segments() function makes garbage | ||
869 | * collection operation in the environment of requested parameters | ||
870 | * from userspace. The NILFS_IOCTL_CLEAN_SEGMENTS ioctl is used by | ||
871 | * nilfs_cleanerd daemon. | ||
872 | * | ||
873 | * Return Value: On success, 0 is returned or error code, otherwise. | ||
874 | */ | ||
574 | static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, | 875 | static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, |
575 | unsigned int cmd, void __user *argp) | 876 | unsigned int cmd, void __user *argp) |
576 | { | 877 | { |
@@ -682,6 +983,33 @@ out: | |||
682 | return ret; | 983 | return ret; |
683 | } | 984 | } |
684 | 985 | ||
986 | /** | ||
987 | * nilfs_ioctl_sync - make a checkpoint | ||
988 | * @inode: inode object | ||
989 | * @filp: file object | ||
990 | * @cmd: ioctl's request code | ||
991 | * @argp: pointer on argument from userspace | ||
992 | * | ||
993 | * Description: nilfs_ioctl_sync() function constructs a logical segment | ||
994 | * for checkpointing. This function guarantees that all modified data | ||
995 | * and metadata are written out to the device when it successfully | ||
996 | * returned. | ||
997 | * | ||
998 | * Return Value: On success, 0 is retured. On errors, one of the following | ||
999 | * negative error code is returned. | ||
1000 | * | ||
1001 | * %-EROFS - Read only filesystem. | ||
1002 | * | ||
1003 | * %-EIO - I/O error | ||
1004 | * | ||
1005 | * %-ENOSPC - No space left on device (only in a panic state). | ||
1006 | * | ||
1007 | * %-ERESTARTSYS - Interrupted. | ||
1008 | * | ||
1009 | * %-ENOMEM - Insufficient memory available. | ||
1010 | * | ||
1011 | * %-EFAULT - Failure during execution of requested operation. | ||
1012 | */ | ||
685 | static int nilfs_ioctl_sync(struct inode *inode, struct file *filp, | 1013 | static int nilfs_ioctl_sync(struct inode *inode, struct file *filp, |
686 | unsigned int cmd, void __user *argp) | 1014 | unsigned int cmd, void __user *argp) |
687 | { | 1015 | { |
@@ -710,6 +1038,14 @@ static int nilfs_ioctl_sync(struct inode *inode, struct file *filp, | |||
710 | return 0; | 1038 | return 0; |
711 | } | 1039 | } |
712 | 1040 | ||
1041 | /** | ||
1042 | * nilfs_ioctl_resize - resize NILFS2 volume | ||
1043 | * @inode: inode object | ||
1044 | * @filp: file object | ||
1045 | * @argp: pointer on argument from userspace | ||
1046 | * | ||
1047 | * Return Value: On success, 0 is returned or error code, otherwise. | ||
1048 | */ | ||
713 | static int nilfs_ioctl_resize(struct inode *inode, struct file *filp, | 1049 | static int nilfs_ioctl_resize(struct inode *inode, struct file *filp, |
714 | void __user *argp) | 1050 | void __user *argp) |
715 | { | 1051 | { |
@@ -735,6 +1071,17 @@ out: | |||
735 | return ret; | 1071 | return ret; |
736 | } | 1072 | } |
737 | 1073 | ||
1074 | /** | ||
1075 | * nilfs_ioctl_set_alloc_range - limit range of segments to be allocated | ||
1076 | * @inode: inode object | ||
1077 | * @argp: pointer on argument from userspace | ||
1078 | * | ||
1079 | * Decription: nilfs_ioctl_set_alloc_range() function defines lower limit | ||
1080 | * of segments in bytes and upper limit of segments in bytes. | ||
1081 | * The NILFS_IOCTL_SET_ALLOC_RANGE is used by nilfs_resize utility. | ||
1082 | * | ||
1083 | * Return Value: On success, 0 is returned or error code, otherwise. | ||
1084 | */ | ||
738 | static int nilfs_ioctl_set_alloc_range(struct inode *inode, void __user *argp) | 1085 | static int nilfs_ioctl_set_alloc_range(struct inode *inode, void __user *argp) |
739 | { | 1086 | { |
740 | struct the_nilfs *nilfs = inode->i_sb->s_fs_info; | 1087 | struct the_nilfs *nilfs = inode->i_sb->s_fs_info; |
@@ -767,6 +1114,28 @@ out: | |||
767 | return ret; | 1114 | return ret; |
768 | } | 1115 | } |
769 | 1116 | ||
1117 | /** | ||
1118 | * nilfs_ioctl_get_info - wrapping function of get metadata info | ||
1119 | * @inode: inode object | ||
1120 | * @filp: file object | ||
1121 | * @cmd: ioctl's request code | ||
1122 | * @argp: pointer on argument from userspace | ||
1123 | * @membsz: size of an item in bytes | ||
1124 | * @dofunc: concrete function of getting metadata info | ||
1125 | * | ||
1126 | * Description: nilfs_ioctl_get_info() gets metadata info by means of | ||
1127 | * calling dofunc() function. | ||
1128 | * | ||
1129 | * Return Value: On success, 0 is returned and requested metadata info | ||
1130 | * is copied into userspace. On error, one of the following | ||
1131 | * negative error codes is returned. | ||
1132 | * | ||
1133 | * %-EINVAL - Invalid arguments from userspace. | ||
1134 | * | ||
1135 | * %-ENOMEM - Insufficient amount of memory available. | ||
1136 | * | ||
1137 | * %-EFAULT - Failure during execution of requested operation. | ||
1138 | */ | ||
770 | static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp, | 1139 | static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp, |
771 | unsigned int cmd, void __user *argp, | 1140 | unsigned int cmd, void __user *argp, |
772 | size_t membsz, | 1141 | size_t membsz, |
@@ -663,10 +663,11 @@ out: | |||
663 | wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLRDNORM); | 663 | wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLRDNORM); |
664 | kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); | 664 | kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); |
665 | } | 665 | } |
666 | if (ret > 0) { | 666 | if (ret > 0 && sb_start_write_trylock(file_inode(filp)->i_sb)) { |
667 | int err = file_update_time(filp); | 667 | int err = file_update_time(filp); |
668 | if (err) | 668 | if (err) |
669 | ret = err; | 669 | ret = err; |
670 | sb_end_write(file_inode(filp)->i_sb); | ||
670 | } | 671 | } |
671 | return ret; | 672 | return ret; |
672 | } | 673 | } |
diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 021e7c069b86..551e61ba15b6 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c | |||
@@ -149,8 +149,6 @@ posix_acl_valid(const struct posix_acl *acl) | |||
149 | { | 149 | { |
150 | const struct posix_acl_entry *pa, *pe; | 150 | const struct posix_acl_entry *pa, *pe; |
151 | int state = ACL_USER_OBJ; | 151 | int state = ACL_USER_OBJ; |
152 | kuid_t prev_uid = INVALID_UID; | ||
153 | kgid_t prev_gid = INVALID_GID; | ||
154 | int needs_mask = 0; | 152 | int needs_mask = 0; |
155 | 153 | ||
156 | FOREACH_ACL_ENTRY(pa, acl, pe) { | 154 | FOREACH_ACL_ENTRY(pa, acl, pe) { |
@@ -169,10 +167,6 @@ posix_acl_valid(const struct posix_acl *acl) | |||
169 | return -EINVAL; | 167 | return -EINVAL; |
170 | if (!uid_valid(pa->e_uid)) | 168 | if (!uid_valid(pa->e_uid)) |
171 | return -EINVAL; | 169 | return -EINVAL; |
172 | if (uid_valid(prev_uid) && | ||
173 | uid_lte(pa->e_uid, prev_uid)) | ||
174 | return -EINVAL; | ||
175 | prev_uid = pa->e_uid; | ||
176 | needs_mask = 1; | 170 | needs_mask = 1; |
177 | break; | 171 | break; |
178 | 172 | ||
@@ -188,10 +182,6 @@ posix_acl_valid(const struct posix_acl *acl) | |||
188 | return -EINVAL; | 182 | return -EINVAL; |
189 | if (!gid_valid(pa->e_gid)) | 183 | if (!gid_valid(pa->e_gid)) |
190 | return -EINVAL; | 184 | return -EINVAL; |
191 | if (gid_valid(prev_gid) && | ||
192 | gid_lte(pa->e_gid, prev_gid)) | ||
193 | return -EINVAL; | ||
194 | prev_gid = pa->e_gid; | ||
195 | needs_mask = 1; | 185 | needs_mask = 1; |
196 | break; | 186 | break; |
197 | 187 | ||
diff --git a/fs/proc/array.c b/fs/proc/array.c index 1bd2077187fd..656e401794de 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -140,24 +140,15 @@ static const char * const task_state_array[] = { | |||
140 | "t (tracing stop)", /* 8 */ | 140 | "t (tracing stop)", /* 8 */ |
141 | "Z (zombie)", /* 16 */ | 141 | "Z (zombie)", /* 16 */ |
142 | "X (dead)", /* 32 */ | 142 | "X (dead)", /* 32 */ |
143 | "x (dead)", /* 64 */ | ||
144 | "K (wakekill)", /* 128 */ | ||
145 | "W (waking)", /* 256 */ | ||
146 | "P (parked)", /* 512 */ | ||
147 | }; | 143 | }; |
148 | 144 | ||
149 | static inline const char *get_task_state(struct task_struct *tsk) | 145 | static inline const char *get_task_state(struct task_struct *tsk) |
150 | { | 146 | { |
151 | unsigned int state = (tsk->state & TASK_REPORT) | tsk->exit_state; | 147 | unsigned int state = (tsk->state | tsk->exit_state) & TASK_REPORT; |
152 | const char * const *p = &task_state_array[0]; | ||
153 | 148 | ||
154 | BUILD_BUG_ON(1 + ilog2(TASK_STATE_MAX) != ARRAY_SIZE(task_state_array)); | 149 | BUILD_BUG_ON(1 + ilog2(TASK_REPORT) != ARRAY_SIZE(task_state_array)-1); |
155 | 150 | ||
156 | while (state) { | 151 | return task_state_array[fls(state)]; |
157 | p++; | ||
158 | state >>= 1; | ||
159 | } | ||
160 | return *p; | ||
161 | } | 152 | } |
162 | 153 | ||
163 | static inline void task_state(struct seq_file *m, struct pid_namespace *ns, | 154 | static inline void task_state(struct seq_file *m, struct pid_namespace *ns, |
@@ -453,8 +444,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, | |||
453 | min_flt += t->min_flt; | 444 | min_flt += t->min_flt; |
454 | maj_flt += t->maj_flt; | 445 | maj_flt += t->maj_flt; |
455 | gtime += task_gtime(t); | 446 | gtime += task_gtime(t); |
456 | t = next_thread(t); | 447 | } while_each_thread(task, t); |
457 | } while (t != task); | ||
458 | 448 | ||
459 | min_flt += sig->min_flt; | 449 | min_flt += sig->min_flt; |
460 | maj_flt += sig->maj_flt; | 450 | maj_flt += sig->maj_flt; |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 03c8d747be48..51507065263b 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -1658,13 +1658,18 @@ int pid_revalidate(struct dentry *dentry, unsigned int flags) | |||
1658 | return 0; | 1658 | return 0; |
1659 | } | 1659 | } |
1660 | 1660 | ||
1661 | static inline bool proc_inode_is_dead(struct inode *inode) | ||
1662 | { | ||
1663 | return !proc_pid(inode)->tasks[PIDTYPE_PID].first; | ||
1664 | } | ||
1665 | |||
1661 | int pid_delete_dentry(const struct dentry *dentry) | 1666 | int pid_delete_dentry(const struct dentry *dentry) |
1662 | { | 1667 | { |
1663 | /* Is the task we represent dead? | 1668 | /* Is the task we represent dead? |
1664 | * If so, then don't put the dentry on the lru list, | 1669 | * If so, then don't put the dentry on the lru list, |
1665 | * kill it immediately. | 1670 | * kill it immediately. |
1666 | */ | 1671 | */ |
1667 | return !proc_pid(dentry->d_inode)->tasks[PIDTYPE_PID].first; | 1672 | return proc_inode_is_dead(dentry->d_inode); |
1668 | } | 1673 | } |
1669 | 1674 | ||
1670 | const struct dentry_operations pid_dentry_operations = | 1675 | const struct dentry_operations pid_dentry_operations = |
@@ -3092,34 +3097,42 @@ out_no_task: | |||
3092 | * In the case of a seek we start with the leader and walk nr | 3097 | * In the case of a seek we start with the leader and walk nr |
3093 | * threads past it. | 3098 | * threads past it. |
3094 | */ | 3099 | */ |
3095 | static struct task_struct *first_tid(struct task_struct *leader, | 3100 | static struct task_struct *first_tid(struct pid *pid, int tid, loff_t f_pos, |
3096 | int tid, int nr, struct pid_namespace *ns) | 3101 | struct pid_namespace *ns) |
3097 | { | 3102 | { |
3098 | struct task_struct *pos; | 3103 | struct task_struct *pos, *task; |
3104 | unsigned long nr = f_pos; | ||
3105 | |||
3106 | if (nr != f_pos) /* 32bit overflow? */ | ||
3107 | return NULL; | ||
3099 | 3108 | ||
3100 | rcu_read_lock(); | 3109 | rcu_read_lock(); |
3101 | /* Attempt to start with the pid of a thread */ | 3110 | task = pid_task(pid, PIDTYPE_PID); |
3102 | if (tid && (nr > 0)) { | 3111 | if (!task) |
3112 | goto fail; | ||
3113 | |||
3114 | /* Attempt to start with the tid of a thread */ | ||
3115 | if (tid && nr) { | ||
3103 | pos = find_task_by_pid_ns(tid, ns); | 3116 | pos = find_task_by_pid_ns(tid, ns); |
3104 | if (pos && (pos->group_leader == leader)) | 3117 | if (pos && same_thread_group(pos, task)) |
3105 | goto found; | 3118 | goto found; |
3106 | } | 3119 | } |
3107 | 3120 | ||
3108 | /* If nr exceeds the number of threads there is nothing todo */ | 3121 | /* If nr exceeds the number of threads there is nothing todo */ |
3109 | pos = NULL; | 3122 | if (nr >= get_nr_threads(task)) |
3110 | if (nr && nr >= get_nr_threads(leader)) | 3123 | goto fail; |
3111 | goto out; | ||
3112 | 3124 | ||
3113 | /* If we haven't found our starting place yet start | 3125 | /* If we haven't found our starting place yet start |
3114 | * with the leader and walk nr threads forward. | 3126 | * with the leader and walk nr threads forward. |
3115 | */ | 3127 | */ |
3116 | for (pos = leader; nr > 0; --nr) { | 3128 | pos = task = task->group_leader; |
3117 | pos = next_thread(pos); | 3129 | do { |
3118 | if (pos == leader) { | 3130 | if (!nr--) |
3119 | pos = NULL; | 3131 | goto found; |
3120 | goto out; | 3132 | } while_each_thread(task, pos); |
3121 | } | 3133 | fail: |
3122 | } | 3134 | pos = NULL; |
3135 | goto out; | ||
3123 | found: | 3136 | found: |
3124 | get_task_struct(pos); | 3137 | get_task_struct(pos); |
3125 | out: | 3138 | out: |
@@ -3152,25 +3165,16 @@ static struct task_struct *next_tid(struct task_struct *start) | |||
3152 | /* for the /proc/TGID/task/ directories */ | 3165 | /* for the /proc/TGID/task/ directories */ |
3153 | static int proc_task_readdir(struct file *file, struct dir_context *ctx) | 3166 | static int proc_task_readdir(struct file *file, struct dir_context *ctx) |
3154 | { | 3167 | { |
3155 | struct task_struct *leader = NULL; | 3168 | struct inode *inode = file_inode(file); |
3156 | struct task_struct *task = get_proc_task(file_inode(file)); | 3169 | struct task_struct *task; |
3157 | struct pid_namespace *ns; | 3170 | struct pid_namespace *ns; |
3158 | int tid; | 3171 | int tid; |
3159 | 3172 | ||
3160 | if (!task) | 3173 | if (proc_inode_is_dead(inode)) |
3161 | return -ENOENT; | ||
3162 | rcu_read_lock(); | ||
3163 | if (pid_alive(task)) { | ||
3164 | leader = task->group_leader; | ||
3165 | get_task_struct(leader); | ||
3166 | } | ||
3167 | rcu_read_unlock(); | ||
3168 | put_task_struct(task); | ||
3169 | if (!leader) | ||
3170 | return -ENOENT; | 3174 | return -ENOENT; |
3171 | 3175 | ||
3172 | if (!dir_emit_dots(file, ctx)) | 3176 | if (!dir_emit_dots(file, ctx)) |
3173 | goto out; | 3177 | return 0; |
3174 | 3178 | ||
3175 | /* f_version caches the tgid value that the last readdir call couldn't | 3179 | /* f_version caches the tgid value that the last readdir call couldn't |
3176 | * return. lseek aka telldir automagically resets f_version to 0. | 3180 | * return. lseek aka telldir automagically resets f_version to 0. |
@@ -3178,7 +3182,7 @@ static int proc_task_readdir(struct file *file, struct dir_context *ctx) | |||
3178 | ns = file->f_dentry->d_sb->s_fs_info; | 3182 | ns = file->f_dentry->d_sb->s_fs_info; |
3179 | tid = (int)file->f_version; | 3183 | tid = (int)file->f_version; |
3180 | file->f_version = 0; | 3184 | file->f_version = 0; |
3181 | for (task = first_tid(leader, tid, ctx->pos - 2, ns); | 3185 | for (task = first_tid(proc_pid(inode), tid, ctx->pos - 2, ns); |
3182 | task; | 3186 | task; |
3183 | task = next_tid(task), ctx->pos++) { | 3187 | task = next_tid(task), ctx->pos++) { |
3184 | char name[PROC_NUMBUF]; | 3188 | char name[PROC_NUMBUF]; |
@@ -3194,8 +3198,7 @@ static int proc_task_readdir(struct file *file, struct dir_context *ctx) | |||
3194 | break; | 3198 | break; |
3195 | } | 3199 | } |
3196 | } | 3200 | } |
3197 | out: | 3201 | |
3198 | put_task_struct(leader); | ||
3199 | return 0; | 3202 | return 0; |
3200 | } | 3203 | } |
3201 | 3204 | ||
diff --git a/fs/proc/cmdline.c b/fs/proc/cmdline.c index 82676e3fcd1d..cbd82dff7e81 100644 --- a/fs/proc/cmdline.c +++ b/fs/proc/cmdline.c | |||
@@ -26,4 +26,4 @@ static int __init proc_cmdline_init(void) | |||
26 | proc_create("cmdline", 0, NULL, &cmdline_proc_fops); | 26 | proc_create("cmdline", 0, NULL, &cmdline_proc_fops); |
27 | return 0; | 27 | return 0; |
28 | } | 28 | } |
29 | module_init(proc_cmdline_init); | 29 | fs_initcall(proc_cmdline_init); |
diff --git a/fs/proc/consoles.c b/fs/proc/consoles.c index 51942d5abcec..290ba85cb900 100644 --- a/fs/proc/consoles.c +++ b/fs/proc/consoles.c | |||
@@ -109,4 +109,4 @@ static int __init proc_consoles_init(void) | |||
109 | proc_create("consoles", 0, NULL, &proc_consoles_operations); | 109 | proc_create("consoles", 0, NULL, &proc_consoles_operations); |
110 | return 0; | 110 | return 0; |
111 | } | 111 | } |
112 | module_init(proc_consoles_init); | 112 | fs_initcall(proc_consoles_init); |
diff --git a/fs/proc/cpuinfo.c b/fs/proc/cpuinfo.c index 5a1e539a234b..06f4d31e0396 100644 --- a/fs/proc/cpuinfo.c +++ b/fs/proc/cpuinfo.c | |||
@@ -21,4 +21,4 @@ static int __init proc_cpuinfo_init(void) | |||
21 | proc_create("cpuinfo", 0, NULL, &proc_cpuinfo_operations); | 21 | proc_create("cpuinfo", 0, NULL, &proc_cpuinfo_operations); |
22 | return 0; | 22 | return 0; |
23 | } | 23 | } |
24 | module_init(proc_cpuinfo_init); | 24 | fs_initcall(proc_cpuinfo_init); |
diff --git a/fs/proc/devices.c b/fs/proc/devices.c index b14347167c35..50493edc30e5 100644 --- a/fs/proc/devices.c +++ b/fs/proc/devices.c | |||
@@ -67,4 +67,4 @@ static int __init proc_devices_init(void) | |||
67 | proc_create("devices", 0, NULL, &proc_devinfo_operations); | 67 | proc_create("devices", 0, NULL, &proc_devinfo_operations); |
68 | return 0; | 68 | return 0; |
69 | } | 69 | } |
70 | module_init(proc_devices_init); | 70 | fs_initcall(proc_devices_init); |
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index cca93b6fb9a9..b7f268eb5f45 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
@@ -49,8 +49,7 @@ static int proc_notify_change(struct dentry *dentry, struct iattr *iattr) | |||
49 | setattr_copy(inode, iattr); | 49 | setattr_copy(inode, iattr); |
50 | mark_inode_dirty(inode); | 50 | mark_inode_dirty(inode); |
51 | 51 | ||
52 | de->uid = inode->i_uid; | 52 | proc_set_user(de, inode->i_uid, inode->i_gid); |
53 | de->gid = inode->i_gid; | ||
54 | de->mode = inode->i_mode; | 53 | de->mode = inode->i_mode; |
55 | return 0; | 54 | return 0; |
56 | } | 55 | } |
diff --git a/fs/proc/interrupts.c b/fs/proc/interrupts.c index 05029c0e2f24..a352d5703b41 100644 --- a/fs/proc/interrupts.c +++ b/fs/proc/interrupts.c | |||
@@ -50,4 +50,4 @@ static int __init proc_interrupts_init(void) | |||
50 | proc_create("interrupts", 0, NULL, &proc_interrupts_operations); | 50 | proc_create("interrupts", 0, NULL, &proc_interrupts_operations); |
51 | return 0; | 51 | return 0; |
52 | } | 52 | } |
53 | module_init(proc_interrupts_init); | 53 | fs_initcall(proc_interrupts_init); |
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c index 5ed0e52d6aa0..39e6ef32f0bd 100644 --- a/fs/proc/kcore.c +++ b/fs/proc/kcore.c | |||
@@ -639,4 +639,4 @@ static int __init proc_kcore_init(void) | |||
639 | 639 | ||
640 | return 0; | 640 | return 0; |
641 | } | 641 | } |
642 | module_init(proc_kcore_init); | 642 | fs_initcall(proc_kcore_init); |
diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c index bdfabdaefdce..05f8dcdb086e 100644 --- a/fs/proc/kmsg.c +++ b/fs/proc/kmsg.c | |||
@@ -61,4 +61,4 @@ static int __init proc_kmsg_init(void) | |||
61 | proc_create("kmsg", S_IRUSR, NULL, &proc_kmsg_operations); | 61 | proc_create("kmsg", S_IRUSR, NULL, &proc_kmsg_operations); |
62 | return 0; | 62 | return 0; |
63 | } | 63 | } |
64 | module_init(proc_kmsg_init); | 64 | fs_initcall(proc_kmsg_init); |
diff --git a/fs/proc/loadavg.c b/fs/proc/loadavg.c index 1afa4dd4cae2..aec66e6c2060 100644 --- a/fs/proc/loadavg.c +++ b/fs/proc/loadavg.c | |||
@@ -42,4 +42,4 @@ static int __init proc_loadavg_init(void) | |||
42 | proc_create("loadavg", 0, NULL, &loadavg_proc_fops); | 42 | proc_create("loadavg", 0, NULL, &loadavg_proc_fops); |
43 | return 0; | 43 | return 0; |
44 | } | 44 | } |
45 | module_init(proc_loadavg_init); | 45 | fs_initcall(proc_loadavg_init); |
diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c index 24270eceddbf..136e548d9567 100644 --- a/fs/proc/meminfo.c +++ b/fs/proc/meminfo.c | |||
@@ -220,4 +220,4 @@ static int __init proc_meminfo_init(void) | |||
220 | proc_create("meminfo", 0, NULL, &meminfo_proc_fops); | 220 | proc_create("meminfo", 0, NULL, &meminfo_proc_fops); |
221 | return 0; | 221 | return 0; |
222 | } | 222 | } |
223 | module_init(proc_meminfo_init); | 223 | fs_initcall(proc_meminfo_init); |
diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c index 5f9bc8a746c9..d4a35746cab9 100644 --- a/fs/proc/nommu.c +++ b/fs/proc/nommu.c | |||
@@ -131,4 +131,4 @@ static int __init proc_nommu_init(void) | |||
131 | return 0; | 131 | return 0; |
132 | } | 132 | } |
133 | 133 | ||
134 | module_init(proc_nommu_init); | 134 | fs_initcall(proc_nommu_init); |
diff --git a/fs/proc/page.c b/fs/proc/page.c index b8730d9ebaee..02174a610315 100644 --- a/fs/proc/page.c +++ b/fs/proc/page.c | |||
@@ -118,10 +118,12 @@ u64 stable_page_flags(struct page *page) | |||
118 | /* | 118 | /* |
119 | * PageTransCompound can be true for non-huge compound pages (slab | 119 | * PageTransCompound can be true for non-huge compound pages (slab |
120 | * pages or pages allocated by drivers with __GFP_COMP) because it | 120 | * pages or pages allocated by drivers with __GFP_COMP) because it |
121 | * just checks PG_head/PG_tail, so we need to check PageLRU to make | 121 | * just checks PG_head/PG_tail, so we need to check PageLRU/PageAnon |
122 | * sure a given page is a thp, not a non-huge compound page. | 122 | * to make sure a given page is a thp, not a non-huge compound page. |
123 | */ | 123 | */ |
124 | else if (PageTransCompound(page) && PageLRU(compound_trans_head(page))) | 124 | else if (PageTransCompound(page) && |
125 | (PageLRU(compound_trans_head(page)) || | ||
126 | PageAnon(compound_trans_head(page)))) | ||
125 | u |= 1 << KPF_THP; | 127 | u |= 1 << KPF_THP; |
126 | 128 | ||
127 | /* | 129 | /* |
@@ -217,4 +219,4 @@ static int __init proc_page_init(void) | |||
217 | proc_create("kpageflags", S_IRUSR, NULL, &proc_kpageflags_operations); | 219 | proc_create("kpageflags", S_IRUSR, NULL, &proc_kpageflags_operations); |
218 | return 0; | 220 | return 0; |
219 | } | 221 | } |
220 | module_init(proc_page_init); | 222 | fs_initcall(proc_page_init); |
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c index 70779b2fc209..c82dd5147845 100644 --- a/fs/proc/proc_devtree.c +++ b/fs/proc/proc_devtree.c | |||
@@ -74,9 +74,9 @@ __proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp, | |||
74 | return NULL; | 74 | return NULL; |
75 | 75 | ||
76 | if (!strncmp(name, "security-", 9)) | 76 | if (!strncmp(name, "security-", 9)) |
77 | ent->size = 0; /* don't leak number of password chars */ | 77 | proc_set_size(ent, 0); /* don't leak number of password chars */ |
78 | else | 78 | else |
79 | ent->size = pp->length; | 79 | proc_set_size(ent, pp->length); |
80 | 80 | ||
81 | return ent; | 81 | return ent; |
82 | } | 82 | } |
@@ -232,6 +232,7 @@ void __init proc_device_tree_init(void) | |||
232 | return; | 232 | return; |
233 | root = of_find_node_by_path("/"); | 233 | root = of_find_node_by_path("/"); |
234 | if (root == NULL) { | 234 | if (root == NULL) { |
235 | remove_proc_entry("device-tree", NULL); | ||
235 | pr_debug("/proc/device-tree: can't find root\n"); | 236 | pr_debug("/proc/device-tree: can't find root\n"); |
236 | return; | 237 | return; |
237 | } | 238 | } |
diff --git a/fs/proc/softirqs.c b/fs/proc/softirqs.c index 62604be9f58d..ad8a77f94beb 100644 --- a/fs/proc/softirqs.c +++ b/fs/proc/softirqs.c | |||
@@ -41,4 +41,4 @@ static int __init proc_softirqs_init(void) | |||
41 | proc_create("softirqs", 0, NULL, &proc_softirqs_operations); | 41 | proc_create("softirqs", 0, NULL, &proc_softirqs_operations); |
42 | return 0; | 42 | return 0; |
43 | } | 43 | } |
44 | module_init(proc_softirqs_init); | 44 | fs_initcall(proc_softirqs_init); |
diff --git a/fs/proc/stat.c b/fs/proc/stat.c index 1cf86c0e8689..6f599c62f0cc 100644 --- a/fs/proc/stat.c +++ b/fs/proc/stat.c | |||
@@ -221,4 +221,4 @@ static int __init proc_stat_init(void) | |||
221 | proc_create("stat", 0, NULL, &proc_stat_operations); | 221 | proc_create("stat", 0, NULL, &proc_stat_operations); |
222 | return 0; | 222 | return 0; |
223 | } | 223 | } |
224 | module_init(proc_stat_init); | 224 | fs_initcall(proc_stat_init); |
diff --git a/fs/proc/uptime.c b/fs/proc/uptime.c index 061894625903..7141b8d0ca9e 100644 --- a/fs/proc/uptime.c +++ b/fs/proc/uptime.c | |||
@@ -49,4 +49,4 @@ static int __init proc_uptime_init(void) | |||
49 | proc_create("uptime", 0, NULL, &uptime_proc_fops); | 49 | proc_create("uptime", 0, NULL, &uptime_proc_fops); |
50 | return 0; | 50 | return 0; |
51 | } | 51 | } |
52 | module_init(proc_uptime_init); | 52 | fs_initcall(proc_uptime_init); |
diff --git a/fs/proc/version.c b/fs/proc/version.c index 76817a60678c..d2154eb6d78f 100644 --- a/fs/proc/version.c +++ b/fs/proc/version.c | |||
@@ -31,4 +31,4 @@ static int __init proc_version_init(void) | |||
31 | proc_create("version", 0, NULL, &version_proc_fops); | 31 | proc_create("version", 0, NULL, &version_proc_fops); |
32 | return 0; | 32 | return 0; |
33 | } | 33 | } |
34 | module_init(proc_version_init); | 34 | fs_initcall(proc_version_init); |
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c index 9100d6959886..2ca7ba047f04 100644 --- a/fs/proc/vmcore.c +++ b/fs/proc/vmcore.c | |||
@@ -1082,7 +1082,7 @@ static int __init vmcore_init(void) | |||
1082 | proc_vmcore->size = vmcore_size; | 1082 | proc_vmcore->size = vmcore_size; |
1083 | return 0; | 1083 | return 0; |
1084 | } | 1084 | } |
1085 | module_init(vmcore_init) | 1085 | fs_initcall(vmcore_init); |
1086 | 1086 | ||
1087 | /* Cleanup function for vmcore module. */ | 1087 | /* Cleanup function for vmcore module. */ |
1088 | void vmcore_cleanup(void) | 1088 | void vmcore_cleanup(void) |
diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c index 439406e081af..7be26f03a3f5 100644 --- a/fs/proc_namespace.c +++ b/fs/proc_namespace.c | |||
@@ -234,17 +234,12 @@ static int mounts_open_common(struct inode *inode, struct file *file, | |||
234 | 234 | ||
235 | rcu_read_lock(); | 235 | rcu_read_lock(); |
236 | nsp = task_nsproxy(task); | 236 | nsp = task_nsproxy(task); |
237 | if (!nsp) { | 237 | if (!nsp || !nsp->mnt_ns) { |
238 | rcu_read_unlock(); | 238 | rcu_read_unlock(); |
239 | put_task_struct(task); | 239 | put_task_struct(task); |
240 | goto err; | 240 | goto err; |
241 | } | 241 | } |
242 | ns = nsp->mnt_ns; | 242 | ns = nsp->mnt_ns; |
243 | if (!ns) { | ||
244 | rcu_read_unlock(); | ||
245 | put_task_struct(task); | ||
246 | goto err; | ||
247 | } | ||
248 | get_mnt_ns(ns); | 243 | get_mnt_ns(ns); |
249 | rcu_read_unlock(); | 244 | rcu_read_unlock(); |
250 | task_lock(task); | 245 | task_lock(task); |
diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c index 4884ac5ae9be..1e56a4e8cf7c 100644 --- a/fs/ramfs/file-mmu.c +++ b/fs/ramfs/file-mmu.c | |||
@@ -30,13 +30,6 @@ | |||
30 | 30 | ||
31 | #include "internal.h" | 31 | #include "internal.h" |
32 | 32 | ||
33 | const struct address_space_operations ramfs_aops = { | ||
34 | .readpage = simple_readpage, | ||
35 | .write_begin = simple_write_begin, | ||
36 | .write_end = simple_write_end, | ||
37 | .set_page_dirty = __set_page_dirty_no_writeback, | ||
38 | }; | ||
39 | |||
40 | const struct file_operations ramfs_file_operations = { | 33 | const struct file_operations ramfs_file_operations = { |
41 | .read = do_sync_read, | 34 | .read = do_sync_read, |
42 | .aio_read = generic_file_aio_read, | 35 | .aio_read = generic_file_aio_read, |
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index 8d5b438cc188..0b3d8e4cb2fa 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c | |||
@@ -27,13 +27,12 @@ | |||
27 | #include "internal.h" | 27 | #include "internal.h" |
28 | 28 | ||
29 | static int ramfs_nommu_setattr(struct dentry *, struct iattr *); | 29 | static int ramfs_nommu_setattr(struct dentry *, struct iattr *); |
30 | 30 | static unsigned long ramfs_nommu_get_unmapped_area(struct file *file, | |
31 | const struct address_space_operations ramfs_aops = { | 31 | unsigned long addr, |
32 | .readpage = simple_readpage, | 32 | unsigned long len, |
33 | .write_begin = simple_write_begin, | 33 | unsigned long pgoff, |
34 | .write_end = simple_write_end, | 34 | unsigned long flags); |
35 | .set_page_dirty = __set_page_dirty_no_writeback, | 35 | static int ramfs_nommu_mmap(struct file *file, struct vm_area_struct *vma); |
36 | }; | ||
37 | 36 | ||
38 | const struct file_operations ramfs_file_operations = { | 37 | const struct file_operations ramfs_file_operations = { |
39 | .mmap = ramfs_nommu_mmap, | 38 | .mmap = ramfs_nommu_mmap, |
@@ -197,7 +196,7 @@ static int ramfs_nommu_setattr(struct dentry *dentry, struct iattr *ia) | |||
197 | * - the pages to be mapped must exist | 196 | * - the pages to be mapped must exist |
198 | * - the pages be physically contiguous in sequence | 197 | * - the pages be physically contiguous in sequence |
199 | */ | 198 | */ |
200 | unsigned long ramfs_nommu_get_unmapped_area(struct file *file, | 199 | static unsigned long ramfs_nommu_get_unmapped_area(struct file *file, |
201 | unsigned long addr, unsigned long len, | 200 | unsigned long addr, unsigned long len, |
202 | unsigned long pgoff, unsigned long flags) | 201 | unsigned long pgoff, unsigned long flags) |
203 | { | 202 | { |
@@ -256,7 +255,7 @@ out: | |||
256 | /* | 255 | /* |
257 | * set up a mapping for shared memory segments | 256 | * set up a mapping for shared memory segments |
258 | */ | 257 | */ |
259 | int ramfs_nommu_mmap(struct file *file, struct vm_area_struct *vma) | 258 | static int ramfs_nommu_mmap(struct file *file, struct vm_area_struct *vma) |
260 | { | 259 | { |
261 | if (!(vma->vm_flags & VM_SHARED)) | 260 | if (!(vma->vm_flags & VM_SHARED)) |
262 | return -ENOSYS; | 261 | return -ENOSYS; |
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index 6a3e2c420180..d365b1c4eb3c 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c | |||
@@ -43,6 +43,13 @@ | |||
43 | static const struct super_operations ramfs_ops; | 43 | static const struct super_operations ramfs_ops; |
44 | static const struct inode_operations ramfs_dir_inode_operations; | 44 | static const struct inode_operations ramfs_dir_inode_operations; |
45 | 45 | ||
46 | static const struct address_space_operations ramfs_aops = { | ||
47 | .readpage = simple_readpage, | ||
48 | .write_begin = simple_write_begin, | ||
49 | .write_end = simple_write_end, | ||
50 | .set_page_dirty = __set_page_dirty_no_writeback, | ||
51 | }; | ||
52 | |||
46 | static struct backing_dev_info ramfs_backing_dev_info = { | 53 | static struct backing_dev_info ramfs_backing_dev_info = { |
47 | .name = "ramfs", | 54 | .name = "ramfs", |
48 | .ra_pages = 0, /* No readahead */ | 55 | .ra_pages = 0, /* No readahead */ |
diff --git a/fs/ramfs/internal.h b/fs/ramfs/internal.h index 6b330639b51d..a9d8ae88fa15 100644 --- a/fs/ramfs/internal.h +++ b/fs/ramfs/internal.h | |||
@@ -10,5 +10,4 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | 12 | ||
13 | extern const struct address_space_operations ramfs_aops; | ||
14 | extern const struct inode_operations ramfs_file_inode_operations; | 13 | extern const struct inode_operations ramfs_file_inode_operations; |
diff --git a/fs/reiserfs/reiserfs.h b/fs/reiserfs/reiserfs.h index f8adaee537c2..dfb617b2bad2 100644 --- a/fs/reiserfs/reiserfs.h +++ b/fs/reiserfs/reiserfs.h | |||
@@ -1958,8 +1958,6 @@ struct treepath var = {.path_length = ILLEGAL_PATH_ELEMENT_OFFSET, .reada = 0,} | |||
1958 | #define MAX_US_INT 0xffff | 1958 | #define MAX_US_INT 0xffff |
1959 | 1959 | ||
1960 | // reiserfs version 2 has max offset 60 bits. Version 1 - 32 bit offset | 1960 | // reiserfs version 2 has max offset 60 bits. Version 1 - 32 bit offset |
1961 | #define U32_MAX (~(__u32)0) | ||
1962 | |||
1963 | static inline loff_t max_reiserfs_offset(struct inode *inode) | 1961 | static inline loff_t max_reiserfs_offset(struct inode *inode) |
1964 | { | 1962 | { |
1965 | if (get_inode_item_key_version(inode) == KEY_FORMAT_3_5) | 1963 | if (get_inode_item_key_version(inode) == KEY_FORMAT_3_5) |
diff --git a/fs/romfs/super.c b/fs/romfs/super.c index ff1d3d42e72a..d8418782862b 100644 --- a/fs/romfs/super.c +++ b/fs/romfs/super.c | |||
@@ -533,16 +533,14 @@ static int romfs_fill_super(struct super_block *sb, void *data, int silent) | |||
533 | 533 | ||
534 | root = romfs_iget(sb, pos); | 534 | root = romfs_iget(sb, pos); |
535 | if (IS_ERR(root)) | 535 | if (IS_ERR(root)) |
536 | goto error; | 536 | return PTR_ERR(root); |
537 | 537 | ||
538 | sb->s_root = d_make_root(root); | 538 | sb->s_root = d_make_root(root); |
539 | if (!sb->s_root) | 539 | if (!sb->s_root) |
540 | goto error; | 540 | return -ENOMEM; |
541 | 541 | ||
542 | return 0; | 542 | return 0; |
543 | 543 | ||
544 | error: | ||
545 | return -EINVAL; | ||
546 | error_rsb_inval: | 544 | error_rsb_inval: |
547 | ret = -EINVAL; | 545 | ret = -EINVAL; |
548 | error_rsb: | 546 | error_rsb: |
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index cc1febd8fadf..5157b866a853 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c | |||
@@ -2118,26 +2118,10 @@ out_free: | |||
2118 | */ | 2118 | */ |
2119 | static void free_inodes(struct fsck_data *fsckd) | 2119 | static void free_inodes(struct fsck_data *fsckd) |
2120 | { | 2120 | { |
2121 | struct rb_node *this = fsckd->inodes.rb_node; | 2121 | struct fsck_inode *fscki, *n; |
2122 | struct fsck_inode *fscki; | ||
2123 | 2122 | ||
2124 | while (this) { | 2123 | rbtree_postorder_for_each_entry_safe(fscki, n, &fsckd->inodes, rb) |
2125 | if (this->rb_left) | 2124 | kfree(fscki); |
2126 | this = this->rb_left; | ||
2127 | else if (this->rb_right) | ||
2128 | this = this->rb_right; | ||
2129 | else { | ||
2130 | fscki = rb_entry(this, struct fsck_inode, rb); | ||
2131 | this = rb_parent(this); | ||
2132 | if (this) { | ||
2133 | if (this->rb_left == &fscki->rb) | ||
2134 | this->rb_left = NULL; | ||
2135 | else | ||
2136 | this->rb_right = NULL; | ||
2137 | } | ||
2138 | kfree(fscki); | ||
2139 | } | ||
2140 | } | ||
2141 | } | 2125 | } |
2142 | 2126 | ||
2143 | /** | 2127 | /** |
diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c index 36bd4efd0819..a902c5919e42 100644 --- a/fs/ubifs/log.c +++ b/fs/ubifs/log.c | |||
@@ -574,27 +574,10 @@ static int done_already(struct rb_root *done_tree, int lnum) | |||
574 | */ | 574 | */ |
575 | static void destroy_done_tree(struct rb_root *done_tree) | 575 | static void destroy_done_tree(struct rb_root *done_tree) |
576 | { | 576 | { |
577 | struct rb_node *this = done_tree->rb_node; | 577 | struct done_ref *dr, *n; |
578 | struct done_ref *dr; | ||
579 | 578 | ||
580 | while (this) { | 579 | rbtree_postorder_for_each_entry_safe(dr, n, done_tree, rb) |
581 | if (this->rb_left) { | ||
582 | this = this->rb_left; | ||
583 | continue; | ||
584 | } else if (this->rb_right) { | ||
585 | this = this->rb_right; | ||
586 | continue; | ||
587 | } | ||
588 | dr = rb_entry(this, struct done_ref, rb); | ||
589 | this = rb_parent(this); | ||
590 | if (this) { | ||
591 | if (this->rb_left == &dr->rb) | ||
592 | this->rb_left = NULL; | ||
593 | else | ||
594 | this->rb_right = NULL; | ||
595 | } | ||
596 | kfree(dr); | 580 | kfree(dr); |
597 | } | ||
598 | } | 581 | } |
599 | 582 | ||
600 | /** | 583 | /** |
diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c index ba32da3fe08a..f1c3e5a1b315 100644 --- a/fs/ubifs/orphan.c +++ b/fs/ubifs/orphan.c | |||
@@ -815,27 +815,10 @@ static int dbg_find_check_orphan(struct rb_root *root, ino_t inum) | |||
815 | 815 | ||
816 | static void dbg_free_check_tree(struct rb_root *root) | 816 | static void dbg_free_check_tree(struct rb_root *root) |
817 | { | 817 | { |
818 | struct rb_node *this = root->rb_node; | 818 | struct check_orphan *o, *n; |
819 | struct check_orphan *o; | ||
820 | 819 | ||
821 | while (this) { | 820 | rbtree_postorder_for_each_entry_safe(o, n, root, rb) |
822 | if (this->rb_left) { | ||
823 | this = this->rb_left; | ||
824 | continue; | ||
825 | } else if (this->rb_right) { | ||
826 | this = this->rb_right; | ||
827 | continue; | ||
828 | } | ||
829 | o = rb_entry(this, struct check_orphan, rb); | ||
830 | this = rb_parent(this); | ||
831 | if (this) { | ||
832 | if (this->rb_left == &o->rb) | ||
833 | this->rb_left = NULL; | ||
834 | else | ||
835 | this->rb_right = NULL; | ||
836 | } | ||
837 | kfree(o); | 821 | kfree(o); |
838 | } | ||
839 | } | 822 | } |
840 | 823 | ||
841 | static int dbg_orphan_check(struct ubifs_info *c, struct ubifs_zbranch *zbr, | 824 | static int dbg_orphan_check(struct ubifs_info *c, struct ubifs_zbranch *zbr, |
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index 065096e36ed9..c14adb2f420c 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c | |||
@@ -1335,29 +1335,14 @@ static void remove_ino(struct ubifs_info *c, ino_t inum) | |||
1335 | */ | 1335 | */ |
1336 | void ubifs_destroy_size_tree(struct ubifs_info *c) | 1336 | void ubifs_destroy_size_tree(struct ubifs_info *c) |
1337 | { | 1337 | { |
1338 | struct rb_node *this = c->size_tree.rb_node; | 1338 | struct size_entry *e, *n; |
1339 | struct size_entry *e; | ||
1340 | 1339 | ||
1341 | while (this) { | 1340 | rbtree_postorder_for_each_entry_safe(e, n, &c->size_tree, rb) { |
1342 | if (this->rb_left) { | ||
1343 | this = this->rb_left; | ||
1344 | continue; | ||
1345 | } else if (this->rb_right) { | ||
1346 | this = this->rb_right; | ||
1347 | continue; | ||
1348 | } | ||
1349 | e = rb_entry(this, struct size_entry, rb); | ||
1350 | if (e->inode) | 1341 | if (e->inode) |
1351 | iput(e->inode); | 1342 | iput(e->inode); |
1352 | this = rb_parent(this); | ||
1353 | if (this) { | ||
1354 | if (this->rb_left == &e->rb) | ||
1355 | this->rb_left = NULL; | ||
1356 | else | ||
1357 | this->rb_right = NULL; | ||
1358 | } | ||
1359 | kfree(e); | 1343 | kfree(e); |
1360 | } | 1344 | } |
1345 | |||
1361 | c->size_tree = RB_ROOT; | 1346 | c->size_tree = RB_ROOT; |
1362 | } | 1347 | } |
1363 | 1348 | ||
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index f69daa514a57..5ded8490c0c6 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
@@ -873,26 +873,10 @@ static void free_orphans(struct ubifs_info *c) | |||
873 | */ | 873 | */ |
874 | static void free_buds(struct ubifs_info *c) | 874 | static void free_buds(struct ubifs_info *c) |
875 | { | 875 | { |
876 | struct rb_node *this = c->buds.rb_node; | 876 | struct ubifs_bud *bud, *n; |
877 | struct ubifs_bud *bud; | 877 | |
878 | 878 | rbtree_postorder_for_each_entry_safe(bud, n, &c->buds, rb) | |
879 | while (this) { | 879 | kfree(bud); |
880 | if (this->rb_left) | ||
881 | this = this->rb_left; | ||
882 | else if (this->rb_right) | ||
883 | this = this->rb_right; | ||
884 | else { | ||
885 | bud = rb_entry(this, struct ubifs_bud, rb); | ||
886 | this = rb_parent(this); | ||
887 | if (this) { | ||
888 | if (this->rb_left == &bud->rb) | ||
889 | this->rb_left = NULL; | ||
890 | else | ||
891 | this->rb_right = NULL; | ||
892 | } | ||
893 | kfree(bud); | ||
894 | } | ||
895 | } | ||
896 | } | 880 | } |
897 | 881 | ||
898 | /** | 882 | /** |
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index 349f31a30f40..9083bc7ed4ae 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c | |||
@@ -178,27 +178,11 @@ static int ins_clr_old_idx_znode(struct ubifs_info *c, | |||
178 | */ | 178 | */ |
179 | void destroy_old_idx(struct ubifs_info *c) | 179 | void destroy_old_idx(struct ubifs_info *c) |
180 | { | 180 | { |
181 | struct rb_node *this = c->old_idx.rb_node; | 181 | struct ubifs_old_idx *old_idx, *n; |
182 | struct ubifs_old_idx *old_idx; | ||
183 | 182 | ||
184 | while (this) { | 183 | rbtree_postorder_for_each_entry_safe(old_idx, n, &c->old_idx, rb) |
185 | if (this->rb_left) { | ||
186 | this = this->rb_left; | ||
187 | continue; | ||
188 | } else if (this->rb_right) { | ||
189 | this = this->rb_right; | ||
190 | continue; | ||
191 | } | ||
192 | old_idx = rb_entry(this, struct ubifs_old_idx, rb); | ||
193 | this = rb_parent(this); | ||
194 | if (this) { | ||
195 | if (this->rb_left == &old_idx->rb) | ||
196 | this->rb_left = NULL; | ||
197 | else | ||
198 | this->rb_right = NULL; | ||
199 | } | ||
200 | kfree(old_idx); | 184 | kfree(old_idx); |
201 | } | 185 | |
202 | c->old_idx = RB_ROOT; | 186 | c->old_idx = RB_ROOT; |
203 | } | 187 | } |
204 | 188 | ||