Commit 3e93cd671813e204c258f1e6c797959920cf7772

Authored by Al Viro
1 parent f8ef3ed2be

Take fs_struct handling to new file (fs/fs_struct.c)

Pure code move; two new helper functions for nfsd and daemonize
(unshare_fs_struct() and daemonize_fs_struct() resp.; for now -
the same code as used to be in callers).  unshare_fs_struct()
exported (for nfsd, as copy_fs_struct()/exit_fs() used to be),
copy_fs_struct() and exit_fs() don't need exports anymore.

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

Showing 9 changed files with 155 additions and 138 deletions Side-by-side Diff

... ... @@ -11,7 +11,7 @@
11 11 attr.o bad_inode.o file.o filesystems.o namespace.o \
12 12 seq_file.o xattr.o libfs.o fs-writeback.o \
13 13 pnode.o drop_caches.o splice.o sync.o utimes.o \
14   - stack.o
  14 + stack.o fs_struct.o
15 15  
16 16 ifeq ($(CONFIG_BLOCK),y)
17 17 obj-y += buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o
  1 +#include <linux/module.h>
  2 +#include <linux/sched.h>
  3 +#include <linux/fs.h>
  4 +#include <linux/path.h>
  5 +#include <linux/slab.h>
  6 +
  7 +/*
  8 + * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
  9 + * It can block.
  10 + */
  11 +void set_fs_root(struct fs_struct *fs, struct path *path)
  12 +{
  13 + struct path old_root;
  14 +
  15 + write_lock(&fs->lock);
  16 + old_root = fs->root;
  17 + fs->root = *path;
  18 + path_get(path);
  19 + write_unlock(&fs->lock);
  20 + if (old_root.dentry)
  21 + path_put(&old_root);
  22 +}
  23 +
  24 +/*
  25 + * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
  26 + * It can block.
  27 + */
  28 +void set_fs_pwd(struct fs_struct *fs, struct path *path)
  29 +{
  30 + struct path old_pwd;
  31 +
  32 + write_lock(&fs->lock);
  33 + old_pwd = fs->pwd;
  34 + fs->pwd = *path;
  35 + path_get(path);
  36 + write_unlock(&fs->lock);
  37 +
  38 + if (old_pwd.dentry)
  39 + path_put(&old_pwd);
  40 +}
  41 +
  42 +void chroot_fs_refs(struct path *old_root, struct path *new_root)
  43 +{
  44 + struct task_struct *g, *p;
  45 + struct fs_struct *fs;
  46 + int count = 0;
  47 +
  48 + read_lock(&tasklist_lock);
  49 + do_each_thread(g, p) {
  50 + task_lock(p);
  51 + fs = p->fs;
  52 + if (fs) {
  53 + write_lock(&fs->lock);
  54 + if (fs->root.dentry == old_root->dentry
  55 + && fs->root.mnt == old_root->mnt) {
  56 + path_get(new_root);
  57 + fs->root = *new_root;
  58 + count++;
  59 + }
  60 + if (fs->pwd.dentry == old_root->dentry
  61 + && fs->pwd.mnt == old_root->mnt) {
  62 + path_get(new_root);
  63 + fs->pwd = *new_root;
  64 + count++;
  65 + }
  66 + write_unlock(&fs->lock);
  67 + }
  68 + task_unlock(p);
  69 + } while_each_thread(g, p);
  70 + read_unlock(&tasklist_lock);
  71 + while (count--)
  72 + path_put(old_root);
  73 +}
  74 +
  75 +void put_fs_struct(struct fs_struct *fs)
  76 +{
  77 + /* No need to hold fs->lock if we are killing it */
  78 + if (atomic_dec_and_test(&fs->count)) {
  79 + path_put(&fs->root);
  80 + path_put(&fs->pwd);
  81 + kmem_cache_free(fs_cachep, fs);
  82 + }
  83 +}
  84 +
  85 +void exit_fs(struct task_struct *tsk)
  86 +{
  87 + struct fs_struct * fs = tsk->fs;
  88 +
  89 + if (fs) {
  90 + task_lock(tsk);
  91 + tsk->fs = NULL;
  92 + task_unlock(tsk);
  93 + put_fs_struct(fs);
  94 + }
  95 +}
  96 +
  97 +struct fs_struct *copy_fs_struct(struct fs_struct *old)
  98 +{
  99 + struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
  100 + /* We don't need to lock fs - think why ;-) */
  101 + if (fs) {
  102 + atomic_set(&fs->count, 1);
  103 + rwlock_init(&fs->lock);
  104 + fs->umask = old->umask;
  105 + read_lock(&old->lock);
  106 + fs->root = old->root;
  107 + path_get(&old->root);
  108 + fs->pwd = old->pwd;
  109 + path_get(&old->pwd);
  110 + read_unlock(&old->lock);
  111 + }
  112 + return fs;
  113 +}
  114 +
  115 +int unshare_fs_struct(void)
  116 +{
  117 + struct fs_struct *fsp = copy_fs_struct(current->fs);
  118 + if (!fsp)
  119 + return -ENOMEM;
  120 + exit_fs(current);
  121 + current->fs = fsp;
  122 + return 0;
  123 +}
  124 +EXPORT_SYMBOL_GPL(unshare_fs_struct);
  125 +
  126 +/* to be mentioned only in INIT_TASK */
  127 +struct fs_struct init_fs = {
  128 + .count = ATOMIC_INIT(1),
  129 + .lock = __RW_LOCK_UNLOCKED(init_fs.lock),
  130 + .umask = 0022,
  131 +};
  132 +
  133 +void daemonize_fs_struct(void)
  134 +{
  135 + struct fs_struct *fs;
  136 +
  137 + exit_fs(current); /* current->fs->count--; */
  138 + fs = &init_fs;
  139 + current->fs = fs;
  140 + atomic_inc(&fs->count);
  141 +}
... ... @@ -11,6 +11,7 @@
11 11  
12 12 struct super_block;
13 13 struct linux_binprm;
  14 +struct path;
14 15  
15 16 /*
16 17 * block_dev.c
... ... @@ -60,4 +61,9 @@
60 61 extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int);
61 62  
62 63 extern void __init mnt_init(void);
  64 +
  65 +/*
  66 + * fs_struct.c
  67 + */
  68 +extern void chroot_fs_refs(struct path *, struct path *);
... ... @@ -2897,11 +2897,4 @@
2897 2897 EXPORT_SYMBOL(vfs_unlink);
2898 2898 EXPORT_SYMBOL(dentry_unhash);
2899 2899 EXPORT_SYMBOL(generic_readlink);
2900   -
2901   -/* to be mentioned only in INIT_TASK */
2902   -struct fs_struct init_fs = {
2903   - .count = ATOMIC_INIT(1),
2904   - .lock = __RW_LOCK_UNLOCKED(init_fs.lock),
2905   - .umask = 0022,
2906   -};
... ... @@ -2093,74 +2093,6 @@
2093 2093 }
2094 2094  
2095 2095 /*
2096   - * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
2097   - * It can block. Requires the big lock held.
2098   - */
2099   -void set_fs_root(struct fs_struct *fs, struct path *path)
2100   -{
2101   - struct path old_root;
2102   -
2103   - write_lock(&fs->lock);
2104   - old_root = fs->root;
2105   - fs->root = *path;
2106   - path_get(path);
2107   - write_unlock(&fs->lock);
2108   - if (old_root.dentry)
2109   - path_put(&old_root);
2110   -}
2111   -
2112   -/*
2113   - * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
2114   - * It can block. Requires the big lock held.
2115   - */
2116   -void set_fs_pwd(struct fs_struct *fs, struct path *path)
2117   -{
2118   - struct path old_pwd;
2119   -
2120   - write_lock(&fs->lock);
2121   - old_pwd = fs->pwd;
2122   - fs->pwd = *path;
2123   - path_get(path);
2124   - write_unlock(&fs->lock);
2125   -
2126   - if (old_pwd.dentry)
2127   - path_put(&old_pwd);
2128   -}
2129   -
2130   -static void chroot_fs_refs(struct path *old_root, struct path *new_root)
2131   -{
2132   - struct task_struct *g, *p;
2133   - struct fs_struct *fs;
2134   - int count = 0;
2135   -
2136   - read_lock(&tasklist_lock);
2137   - do_each_thread(g, p) {
2138   - task_lock(p);
2139   - fs = p->fs;
2140   - if (fs) {
2141   - write_lock(&fs->lock);
2142   - if (fs->root.dentry == old_root->dentry
2143   - && fs->root.mnt == old_root->mnt) {
2144   - path_get(new_root);
2145   - fs->root = *new_root;
2146   - count++;
2147   - }
2148   - if (fs->pwd.dentry == old_root->dentry
2149   - && fs->pwd.mnt == old_root->mnt) {
2150   - path_get(new_root);
2151   - fs->pwd = *new_root;
2152   - count++;
2153   - }
2154   - write_unlock(&fs->lock);
2155   - }
2156   - task_unlock(p);
2157   - } while_each_thread(g, p);
2158   - read_unlock(&tasklist_lock);
2159   - while (count--)
2160   - path_put(old_root);
2161   -}
2162   -
2163   -/*
2164 2096 * pivot_root Semantics:
2165 2097 * Moves the root file system of the current process to the directory put_old,
2166 2098 * makes new_root as the new root file system of the current process, and sets
... ... @@ -404,7 +404,6 @@
404 404 nfsd(void *vrqstp)
405 405 {
406 406 struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp;
407   - struct fs_struct *fsp;
408 407 int err, preverr = 0;
409 408  
410 409 /* Lock module and set up kernel thread */
411 410  
... ... @@ -413,13 +412,11 @@
413 412 /* At this point, the thread shares current->fs
414 413 * with the init process. We need to create files with a
415 414 * umask of 0 instead of init's umask. */
416   - fsp = copy_fs_struct(current->fs);
417   - if (!fsp) {
  415 + if (unshare_fs_struct() < 0) {
418 416 printk("Unable to start nfsd thread: out of memory\n");
419 417 goto out;
420 418 }
421   - exit_fs(current);
422   - current->fs = fsp;
  419 +
423 420 current->fs->umask = 0;
424 421  
425 422 /*
include/linux/fs_struct.h
... ... @@ -20,6 +20,8 @@
20 20 extern void set_fs_pwd(struct fs_struct *, struct path *);
21 21 extern struct fs_struct *copy_fs_struct(struct fs_struct *);
22 22 extern void put_fs_struct(struct fs_struct *);
  23 +extern void daemonize_fs_struct(void);
  24 +extern int unshare_fs_struct(void);
23 25  
24 26 #endif /* _LINUX_FS_STRUCT_H */
... ... @@ -429,7 +429,6 @@
429 429 void daemonize(const char *name, ...)
430 430 {
431 431 va_list args;
432   - struct fs_struct *fs;
433 432 sigset_t blocked;
434 433  
435 434 va_start(args, name);
... ... @@ -462,11 +461,7 @@
462 461  
463 462 /* Become as one with the init task */
464 463  
465   - exit_fs(current); /* current->fs->count--; */
466   - fs = init_task.fs;
467   - current->fs = fs;
468   - atomic_inc(&fs->count);
469   -
  464 + daemonize_fs_struct();
470 465 exit_files(current);
471 466 current->files = init_task.files;
472 467 atomic_inc(&current->files->count);
... ... @@ -564,30 +559,6 @@
564 559 put_files_struct(files);
565 560 }
566 561 }
567   -
568   -void put_fs_struct(struct fs_struct *fs)
569   -{
570   - /* No need to hold fs->lock if we are killing it */
571   - if (atomic_dec_and_test(&fs->count)) {
572   - path_put(&fs->root);
573   - path_put(&fs->pwd);
574   - kmem_cache_free(fs_cachep, fs);
575   - }
576   -}
577   -
578   -void exit_fs(struct task_struct *tsk)
579   -{
580   - struct fs_struct * fs = tsk->fs;
581   -
582   - if (fs) {
583   - task_lock(tsk);
584   - tsk->fs = NULL;
585   - task_unlock(tsk);
586   - put_fs_struct(fs);
587   - }
588   -}
589   -
590   -EXPORT_SYMBOL_GPL(exit_fs);
591 562  
592 563 #ifdef CONFIG_MM_OWNER
593 564 /*
... ... @@ -681,38 +681,13 @@
681 681 return retval;
682 682 }
683 683  
684   -static struct fs_struct *__copy_fs_struct(struct fs_struct *old)
685   -{
686   - struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
687   - /* We don't need to lock fs - think why ;-) */
688   - if (fs) {
689   - atomic_set(&fs->count, 1);
690   - rwlock_init(&fs->lock);
691   - fs->umask = old->umask;
692   - read_lock(&old->lock);
693   - fs->root = old->root;
694   - path_get(&old->root);
695   - fs->pwd = old->pwd;
696   - path_get(&old->pwd);
697   - read_unlock(&old->lock);
698   - }
699   - return fs;
700   -}
701   -
702   -struct fs_struct *copy_fs_struct(struct fs_struct *old)
703   -{
704   - return __copy_fs_struct(old);
705   -}
706   -
707   -EXPORT_SYMBOL_GPL(copy_fs_struct);
708   -
709 684 static int copy_fs(unsigned long clone_flags, struct task_struct *tsk)
710 685 {
711 686 if (clone_flags & CLONE_FS) {
712 687 atomic_inc(&current->fs->count);
713 688 return 0;
714 689 }
715   - tsk->fs = __copy_fs_struct(current->fs);
  690 + tsk->fs = copy_fs_struct(current->fs);
716 691 if (!tsk->fs)
717 692 return -ENOMEM;
718 693 return 0;
... ... @@ -1545,7 +1520,7 @@
1545 1520  
1546 1521 if ((unshare_flags & CLONE_FS) &&
1547 1522 (fs && atomic_read(&fs->count) > 1)) {
1548   - *new_fsp = __copy_fs_struct(current->fs);
  1523 + *new_fsp = copy_fs_struct(current->fs);
1549 1524 if (!*new_fsp)
1550 1525 return -ENOMEM;
1551 1526 }