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/statfs.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/syscalls.h>
    2 #include <linux/export.h>
    3 #include <linux/fs.h>
    4 #include <linux/file.h>
    5 #include <linux/mount.h>
    6 #include <linux/namei.h>
    7 #include <linux/statfs.h>
    8 #include <linux/security.h>
    9 #include <linux/uaccess.h>
   10 #include "internal.h"
   11 
   12 static int flags_by_mnt(int mnt_flags)
   13 {
   14         int flags = 0;
   15 
   16         if (mnt_flags & MNT_READONLY)
   17                 flags |= ST_RDONLY;
   18         if (mnt_flags & MNT_NOSUID)
   19                 flags |= ST_NOSUID;
   20         if (mnt_flags & MNT_NODEV)
   21                 flags |= ST_NODEV;
   22         if (mnt_flags & MNT_NOEXEC)
   23                 flags |= ST_NOEXEC;
   24         if (mnt_flags & MNT_NOATIME)
   25                 flags |= ST_NOATIME;
   26         if (mnt_flags & MNT_NODIRATIME)
   27                 flags |= ST_NODIRATIME;
   28         if (mnt_flags & MNT_RELATIME)
   29                 flags |= ST_RELATIME;
   30         return flags;
   31 }
   32 
   33 static int flags_by_sb(int s_flags)
   34 {
   35         int flags = 0;
   36         if (s_flags & MS_SYNCHRONOUS)
   37                 flags |= ST_SYNCHRONOUS;
   38         if (s_flags & MS_MANDLOCK)
   39                 flags |= ST_MANDLOCK;
   40         return flags;
   41 }
   42 
   43 static int calculate_f_flags(struct vfsmount *mnt)
   44 {
   45         return ST_VALID | flags_by_mnt(mnt->mnt_flags) |
   46                 flags_by_sb(mnt->mnt_sb->s_flags);
   47 }
   48 
   49 static int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf)
   50 {
   51         int retval;
   52 
   53         if (!dentry->d_sb->s_op->statfs)
   54                 return -ENOSYS;
   55 
   56         memset(buf, 0, sizeof(*buf));
   57         retval = security_sb_statfs(dentry);
   58         if (retval)
   59                 return retval;
   60         retval = dentry->d_sb->s_op->statfs(dentry, buf);
   61         if (retval == 0 && buf->f_frsize == 0)
   62                 buf->f_frsize = buf->f_bsize;
   63         return retval;
   64 }
   65 
   66 int vfs_statfs(struct path *path, struct kstatfs *buf)
   67 {
   68         int error;
   69 
   70         error = statfs_by_dentry(path->dentry, buf);
   71         if (!error)
   72                 buf->f_flags = calculate_f_flags(path->mnt);
   73         return error;
   74 }
   75 EXPORT_SYMBOL(vfs_statfs);
   76 
   77 int user_statfs(const char __user *pathname, struct kstatfs *st)
   78 {
   79         struct path path;
   80         int error;
   81         unsigned int lookup_flags = LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT;
   82 retry:
   83         error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
   84         if (!error) {
   85                 error = vfs_statfs(&path, st);
   86                 path_put(&path);
   87                 if (retry_estale(error, lookup_flags)) {
   88                         lookup_flags |= LOOKUP_REVAL;
   89                         goto retry;
   90                 }
   91         }
   92         return error;
   93 }
   94 
   95 int fd_statfs(int fd, struct kstatfs *st)
   96 {
   97         struct fd f = fdget(fd);
   98         int error = -EBADF;
   99         if (f.file) {
  100                 error = vfs_statfs(&f.file->f_path, st);
  101                 fdput(f);
  102         }
  103         return error;
  104 }
  105 
  106 static int do_statfs_native(struct kstatfs *st, struct statfs __user *p)
  107 {
  108         struct statfs buf;
  109 
  110         if (sizeof(buf) == sizeof(*st))
  111                 memcpy(&buf, st, sizeof(*st));
  112         else {
  113                 if (sizeof buf.f_blocks == 4) {
  114                         if ((st->f_blocks | st->f_bfree | st->f_bavail |
  115                              st->f_bsize | st->f_frsize) &
  116                             0xffffffff00000000ULL)
  117                                 return -EOVERFLOW;
  118                         /*
  119                          * f_files and f_ffree may be -1; it's okay to stuff
  120                          * that into 32 bits
  121                          */
  122                         if (st->f_files != -1 &&
  123                             (st->f_files & 0xffffffff00000000ULL))
  124                                 return -EOVERFLOW;
  125                         if (st->f_ffree != -1 &&
  126                             (st->f_ffree & 0xffffffff00000000ULL))
  127                                 return -EOVERFLOW;
  128                 }
  129 
  130                 buf.f_type = st->f_type;
  131                 buf.f_bsize = st->f_bsize;
  132                 buf.f_blocks = st->f_blocks;
  133                 buf.f_bfree = st->f_bfree;
  134                 buf.f_bavail = st->f_bavail;
  135                 buf.f_files = st->f_files;
  136                 buf.f_ffree = st->f_ffree;
  137                 buf.f_fsid = st->f_fsid;
  138                 buf.f_namelen = st->f_namelen;
  139                 buf.f_frsize = st->f_frsize;
  140                 buf.f_flags = st->f_flags;
  141                 memset(buf.f_spare, 0, sizeof(buf.f_spare));
  142         }
  143         if (copy_to_user(p, &buf, sizeof(buf)))
  144                 return -EFAULT;
  145         return 0;
  146 }
  147 
  148 static int do_statfs64(struct kstatfs *st, struct statfs64 __user *p)
  149 {
  150         struct statfs64 buf;
  151         if (sizeof(buf) == sizeof(*st))
  152                 memcpy(&buf, st, sizeof(*st));
  153         else {
  154                 buf.f_type = st->f_type;
  155                 buf.f_bsize = st->f_bsize;
  156                 buf.f_blocks = st->f_blocks;
  157                 buf.f_bfree = st->f_bfree;
  158                 buf.f_bavail = st->f_bavail;
  159                 buf.f_files = st->f_files;
  160                 buf.f_ffree = st->f_ffree;
  161                 buf.f_fsid = st->f_fsid;
  162                 buf.f_namelen = st->f_namelen;
  163                 buf.f_frsize = st->f_frsize;
  164                 buf.f_flags = st->f_flags;
  165                 memset(buf.f_spare, 0, sizeof(buf.f_spare));
  166         }
  167         if (copy_to_user(p, &buf, sizeof(buf)))
  168                 return -EFAULT;
  169         return 0;
  170 }
  171 
  172 SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct statfs __user *, buf)
  173 {
  174         struct kstatfs st;
  175         int error = user_statfs(pathname, &st);
  176         if (!error)
  177                 error = do_statfs_native(&st, buf);
  178         return error;
  179 }
  180 
  181 SYSCALL_DEFINE3(statfs64, const char __user *, pathname, size_t, sz, struct statfs64 __user *, buf)
  182 {
  183         struct kstatfs st;
  184         int error;
  185         if (sz != sizeof(*buf))
  186                 return -EINVAL;
  187         error = user_statfs(pathname, &st);
  188         if (!error)
  189                 error = do_statfs64(&st, buf);
  190         return error;
  191 }
  192 
  193 SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct statfs __user *, buf)
  194 {
  195         struct kstatfs st;
  196         int error = fd_statfs(fd, &st);
  197         if (!error)
  198                 error = do_statfs_native(&st, buf);
  199         return error;
  200 }
  201 
  202 SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user *, buf)
  203 {
  204         struct kstatfs st;
  205         int error;
  206 
  207         if (sz != sizeof(*buf))
  208                 return -EINVAL;
  209 
  210         error = fd_statfs(fd, &st);
  211         if (!error)
  212                 error = do_statfs64(&st, buf);
  213         return error;
  214 }
  215 
  216 int vfs_ustat(dev_t dev, struct kstatfs *sbuf)
  217 {
  218         struct super_block *s = user_get_super(dev);
  219         int err;
  220         if (!s)
  221                 return -EINVAL;
  222 
  223         err = statfs_by_dentry(s->s_root, sbuf);
  224         drop_super(s);
  225         return err;
  226 }
  227 
  228 SYSCALL_DEFINE2(ustat, unsigned, dev, struct ustat __user *, ubuf)
  229 {
  230         struct ustat tmp;
  231         struct kstatfs sbuf;
  232         int err = vfs_ustat(new_decode_dev(dev), &sbuf);
  233         if (err)
  234                 return err;
  235 
  236         memset(&tmp,0,sizeof(struct ustat));
  237         tmp.f_tfree = sbuf.f_bfree;
  238         tmp.f_tinode = sbuf.f_ffree;
  239 
  240         return copy_to_user(ubuf, &tmp, sizeof(struct ustat)) ? -EFAULT : 0;
  241 }

Cache object: f9ced9a8d00cd24e7abe942866aa4e24


[ 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.