The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/fs_struct.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 #include <linux/export.h>
    2 #include <linux/sched.h>
    3 #include <linux/fs.h>
    4 #include <linux/path.h>
    5 #include <linux/slab.h>
    6 #include <linux/fs_struct.h>
    7 #include "internal.h"
    8 
    9 /*
   10  * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
   11  * It can block.
   12  */
   13 void set_fs_root(struct fs_struct *fs, struct path *path)
   14 {
   15         struct path old_root;
   16 
   17         path_get(path);
   18         spin_lock(&fs->lock);
   19         write_seqcount_begin(&fs->seq);
   20         old_root = fs->root;
   21         fs->root = *path;
   22         write_seqcount_end(&fs->seq);
   23         spin_unlock(&fs->lock);
   24         if (old_root.dentry)
   25                 path_put(&old_root);
   26 }
   27 
   28 /*
   29  * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
   30  * It can block.
   31  */
   32 void set_fs_pwd(struct fs_struct *fs, struct path *path)
   33 {
   34         struct path old_pwd;
   35 
   36         path_get(path);
   37         spin_lock(&fs->lock);
   38         write_seqcount_begin(&fs->seq);
   39         old_pwd = fs->pwd;
   40         fs->pwd = *path;
   41         write_seqcount_end(&fs->seq);
   42         spin_unlock(&fs->lock);
   43 
   44         if (old_pwd.dentry)
   45                 path_put(&old_pwd);
   46 }
   47 
   48 static inline int replace_path(struct path *p, const struct path *old, const struct path *new)
   49 {
   50         if (likely(p->dentry != old->dentry || p->mnt != old->mnt))
   51                 return 0;
   52         *p = *new;
   53         return 1;
   54 }
   55 
   56 void chroot_fs_refs(struct path *old_root, struct path *new_root)
   57 {
   58         struct task_struct *g, *p;
   59         struct fs_struct *fs;
   60         int count = 0;
   61 
   62         read_lock(&tasklist_lock);
   63         do_each_thread(g, p) {
   64                 task_lock(p);
   65                 fs = p->fs;
   66                 if (fs) {
   67                         int hits = 0;
   68                         spin_lock(&fs->lock);
   69                         write_seqcount_begin(&fs->seq);
   70                         hits += replace_path(&fs->root, old_root, new_root);
   71                         hits += replace_path(&fs->pwd, old_root, new_root);
   72                         write_seqcount_end(&fs->seq);
   73                         while (hits--) {
   74                                 count++;
   75                                 path_get(new_root);
   76                         }
   77                         spin_unlock(&fs->lock);
   78                 }
   79                 task_unlock(p);
   80         } while_each_thread(g, p);
   81         read_unlock(&tasklist_lock);
   82         while (count--)
   83                 path_put(old_root);
   84 }
   85 
   86 void free_fs_struct(struct fs_struct *fs)
   87 {
   88         path_put(&fs->root);
   89         path_put(&fs->pwd);
   90         kmem_cache_free(fs_cachep, fs);
   91 }
   92 
   93 void exit_fs(struct task_struct *tsk)
   94 {
   95         struct fs_struct *fs = tsk->fs;
   96 
   97         if (fs) {
   98                 int kill;
   99                 task_lock(tsk);
  100                 spin_lock(&fs->lock);
  101                 tsk->fs = NULL;
  102                 kill = !--fs->users;
  103                 spin_unlock(&fs->lock);
  104                 task_unlock(tsk);
  105                 if (kill)
  106                         free_fs_struct(fs);
  107         }
  108 }
  109 
  110 struct fs_struct *copy_fs_struct(struct fs_struct *old)
  111 {
  112         struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
  113         /* We don't need to lock fs - think why ;-) */
  114         if (fs) {
  115                 fs->users = 1;
  116                 fs->in_exec = 0;
  117                 spin_lock_init(&fs->lock);
  118                 seqcount_init(&fs->seq);
  119                 fs->umask = old->umask;
  120 
  121                 spin_lock(&old->lock);
  122                 fs->root = old->root;
  123                 path_get(&fs->root);
  124                 fs->pwd = old->pwd;
  125                 path_get(&fs->pwd);
  126                 spin_unlock(&old->lock);
  127         }
  128         return fs;
  129 }
  130 
  131 int unshare_fs_struct(void)
  132 {
  133         struct fs_struct *fs = current->fs;
  134         struct fs_struct *new_fs = copy_fs_struct(fs);
  135         int kill;
  136 
  137         if (!new_fs)
  138                 return -ENOMEM;
  139 
  140         task_lock(current);
  141         spin_lock(&fs->lock);
  142         kill = !--fs->users;
  143         current->fs = new_fs;
  144         spin_unlock(&fs->lock);
  145         task_unlock(current);
  146 
  147         if (kill)
  148                 free_fs_struct(fs);
  149 
  150         return 0;
  151 }
  152 EXPORT_SYMBOL_GPL(unshare_fs_struct);
  153 
  154 int current_umask(void)
  155 {
  156         return current->fs->umask;
  157 }
  158 EXPORT_SYMBOL(current_umask);
  159 
  160 /* to be mentioned only in INIT_TASK */
  161 struct fs_struct init_fs = {
  162         .users          = 1,
  163         .lock           = __SPIN_LOCK_UNLOCKED(init_fs.lock),
  164         .seq            = SEQCNT_ZERO,
  165         .umask          = 0022,
  166 };

Cache object: 1a75dac3084be94d61dc6dd95210cc1d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.