bind mount patch (patch-2.6.8.1-bme0.05.1.diff)
authorMarc Fiuczynski <mef@cs.princeton.edu>
Sat, 18 Sep 2004 10:53:07 +0000 (10:53 +0000)
committerMarc Fiuczynski <mef@cs.princeton.edu>
Sat, 18 Sep 2004 10:53:07 +0000 (10:53 +0000)
22 files changed:
arch/sparc64/solaris/fs.c
fs/ext2/acl.c
fs/ext2/ioctl.c
fs/ext3/acl.c
fs/ext3/ioctl.c
fs/hfsplus/ioctl.c
fs/inode.c
fs/jfs/acl.c
fs/namei.c
fs/namespace.c
fs/ncpfs/file.c
fs/ncpfs/mmap.c
fs/nfs/dir.c
fs/nfsd/vfs.c
fs/open.c
fs/pipe.c
fs/reiserfs/file.c
fs/reiserfs/ioctl.c
fs/reiserfs/xattr.c
include/linux/fs.h
include/linux/mount.h
mm/filemap.c

index a237c68..6fe66f8 100644 (file)
@@ -362,7 +362,7 @@ static int report_statvfs(struct vfsmount *mnt, struct inode *inode, u32 buf)
                int j = strlen (p);
                
                if (j > 15) j = 15;
-               if (IS_RDONLY(inode)) i = 1;
+               if (IS_RDONLY(inode) || (mnt && MNT_IS_RDONLY(mnt))) i = 1;
                if (mnt->mnt_flags & MNT_NOSUID) i |= 2;
                if (!sysv_valid_dev(inode->i_sb->s_dev))
                        return -EOVERFLOW;
@@ -398,7 +398,7 @@ static int report_statvfs64(struct vfsmount *mnt, struct inode *inode, u32 buf)
                int j = strlen (p);
                
                if (j > 15) j = 15;
-               if (IS_RDONLY(inode)) i = 1;
+               if (IS_RDONLY(inode) || (mnt && MNT_IS_RDONLY(mnt))) i = 1;
                if (mnt->mnt_flags & MNT_NOSUID) i |= 2;
                if (!sysv_valid_dev(inode->i_sb->s_dev))
                        return -EOVERFLOW;
index 89d1df9..74acc78 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
+#include <linux/namei.h> 
 #include "ext2.h"
 #include "xattr.h"
 #include "acl.h"
@@ -291,7 +292,8 @@ ext2_permission(struct inode *inode, int mask, struct nameidata *nd)
        int mode = inode->i_mode;
 
        /* Nobody gets write access to a read-only fs */
-       if ((mask & MAY_WRITE) && IS_RDONLY(inode) &&
+       if ((mask & MAY_WRITE) && (IS_RDONLY(inode) ||
+           (nd && MNT_IS_RDONLY(nd->mnt))) &&
            (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
                return -EROFS;
        /* Nobody gets write access to an immutable file */
index 2520c2f..f6043a6 100644 (file)
@@ -29,7 +29,8 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
        case EXT2_IOC_SETFLAGS: {
                unsigned int oldflags;
 
-               if (IS_RDONLY(inode))
+               if (IS_RDONLY(inode) ||
+                       (filp && MNT_IS_RDONLY(filp->f_vfsmnt)))
                        return -EROFS;
 
                if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
@@ -70,7 +71,8 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
        case EXT2_IOC_SETVERSION:
                if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
                        return -EPERM;
-               if (IS_RDONLY(inode))
+               if (IS_RDONLY(inode) ||
+                       (filp && MNT_IS_RDONLY(filp->f_vfsmnt)))
                        return -EROFS;
                if (get_user(inode->i_generation, (int __user *) arg))
                        return -EFAULT; 
index a3cf77d..cc26948 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
+#include <linux/namei.h> 
 #include <linux/ext3_jbd.h>
 #include <linux/ext3_fs.h>
 #include "xattr.h"
@@ -296,7 +297,8 @@ ext3_permission(struct inode *inode, int mask, struct nameidata *nd)
        int mode = inode->i_mode;
 
        /* Nobody gets write access to a read-only fs */
-       if ((mask & MAY_WRITE) && IS_RDONLY(inode) &&
+       if ((mask & MAY_WRITE) && (IS_RDONLY(inode) ||
+           (nd && nd->mnt && MNT_IS_RDONLY(nd->mnt))) &&
            (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
                return -EROFS;
        /* Nobody gets write access to an immutable file */
index 7765ab0..37bd450 100644 (file)
@@ -35,7 +35,8 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
                unsigned int oldflags;
                unsigned int jflag;
 
-               if (IS_RDONLY(inode))
+               if (IS_RDONLY(inode) ||
+                       (filp && MNT_IS_RDONLY(filp->f_vfsmnt)))
                        return -EROFS;
 
                if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
@@ -113,7 +114,8 @@ flags_err:
 
                if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
                        return -EPERM;
-               if (IS_RDONLY(inode))
+               if (IS_RDONLY(inode) ||
+                       (filp && MNT_IS_RDONLY(filp->f_vfsmnt)))
                        return -EROFS;
                if (get_user(generation, (int __user *) arg))
                        return -EFAULT;
index bd05477..cf0118e 100644 (file)
@@ -33,7 +33,8 @@ int hfsplus_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                        flags |= EXT2_FLAG_NODUMP; /* EXT2_NODUMP_FL */
                return put_user(flags, (int __user *)arg);
        case HFSPLUS_IOC_EXT2_SETFLAGS: {
-               if (IS_RDONLY(inode))
+               if (IS_RDONLY(inode) ||
+                       (filp && MNT_IS_RDONLY(filp->f_vfsmnt)))
                        return -EROFS;
 
                if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
index 899805f..d858616 100644 (file)
@@ -1210,14 +1210,14 @@ EXPORT_SYMBOL(update_atime);
  *     When ctime_too is specified update the ctime too.
  */
 
-void inode_update_time(struct inode *inode, int ctime_too)
+void inode_update_time(struct inode *inode, struct vfsmount *mnt, int ctime_too)
 {
        struct timespec now;
        int sync_it = 0;
 
        if (IS_NOCMTIME(inode))
                return;
-       if (IS_RDONLY(inode))
+       if (IS_RDONLY(inode) || MNT_IS_RDONLY(mnt))
                return;
 
        now = current_kernel_time();
index 8353f48..a1cef90 100644 (file)
@@ -136,7 +136,7 @@ int jfs_permission(struct inode * inode, int mask, struct nameidata *nd)
                /*
                 * Nobody gets write access to a read-only fs.
                 */
-               if (IS_RDONLY(inode) &&
+               if ((IS_RDONLY(inode) || (nd && MNT_IS_RDONLY(nd->mnt))) &&
                    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
                        return -EROFS;
 
index 44262f3..34da5b4 100644 (file)
@@ -228,10 +228,15 @@ int permission(struct inode * inode,int mask, struct nameidata *nd)
 {
        int retval;
        int submask;
+       umode_t mode = inode->i_mode;
 
        /* Ordinary permission routines do not understand MAY_APPEND. */
        submask = mask & ~MAY_APPEND;
 
+       if (nd && (mask & MAY_WRITE) && MNT_IS_RDONLY(nd->mnt) &&
+               (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
+               return -EROFS;
+
        if ((retval = xid_permission(inode, mask, nd)))
                return retval;
        if (inode->i_op && inode->i_op->permission)
@@ -1166,6 +1171,24 @@ static inline int may_create(struct inode *dir, struct dentry *child,
        return permission(dir,MAY_WRITE | MAY_EXEC, nd);
 }
 
+static inline int mnt_may_create(struct vfsmount *mnt, struct inode *dir, struct dentry *child) {
+       if (child->d_inode)
+               return -EEXIST;
+       if (IS_DEADDIR(dir))
+               return -ENOENT;
+       if (mnt->mnt_flags & MNT_RDONLY)
+               return -EROFS;
+       return 0;
+}
+
+static inline int mnt_may_unlink(struct vfsmount *mnt, struct inode *dir, struct dentry *child) {
+       if (!child->d_inode)
+               return -ENOENT;
+       if (mnt->mnt_flags & MNT_RDONLY)
+               return -EROFS;
+       return 0;
+}
+
 /* 
  * Special case: O_CREAT|O_EXCL implies O_NOFOLLOW for security
  * reasons.
@@ -1289,7 +1312,8 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
                        return -EACCES;
 
                flag &= ~O_TRUNC;
-       } else if (IS_RDONLY(inode) && (flag & FMODE_WRITE))
+       } else if ((IS_RDONLY(inode) || (nd && MNT_IS_RDONLY(nd->mnt)))
+               && (flag & FMODE_WRITE))
                return -EROFS;
        /*
         * An append-only file must be opened in append mode for writing.
@@ -1527,23 +1551,28 @@ do_link:
 struct dentry *lookup_create(struct nameidata *nd, int is_dir)
 {
        struct dentry *dentry;
+       int error;
 
        down(&nd->dentry->d_inode->i_sem);
-       dentry = ERR_PTR(-EEXIST);
+       error = -EEXIST;
        if (nd->last_type != LAST_NORM)
-               goto fail;
+               goto out;
        nd->flags &= ~LOOKUP_PARENT;
        dentry = lookup_hash(&nd->last, nd->dentry);
        if (IS_ERR(dentry))
+               goto ret;
+       error = mnt_may_create(nd->mnt, nd->dentry->d_inode, dentry);
+       if (error)
                goto fail;
+       error = -ENOENT;
        if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
-               goto enoent;
+               goto fail;
+ret:
        return dentry;
-enoent:
-       dput(dentry);
-       dentry = ERR_PTR(-ENOENT);
 fail:
-       return dentry;
+       dput(dentry);
+out:
+       return ERR_PTR(error);
 }
 
 int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
@@ -1772,7 +1801,11 @@ asmlinkage long sys_rmdir(const char __user * pathname)
        dentry = lookup_hash(&nd.last, nd.dentry);
        error = PTR_ERR(dentry);
        if (!IS_ERR(dentry)) {
+               error = mnt_may_unlink(nd.mnt, nd.dentry->d_inode, dentry);
+               if (error)
+                       goto exit2;
                error = vfs_rmdir(nd.dentry->d_inode, dentry);
+       exit2:
                dput(dentry);
        }
        up(&nd.dentry->d_inode->i_sem);
@@ -1844,6 +1877,9 @@ asmlinkage long sys_unlink(const char __user * pathname)
                /* Why not before? Because we want correct error value */
                if (nd.last.name[nd.last.len])
                        goto slashes;
+               error = mnt_may_unlink(nd.mnt, nd.dentry->d_inode, dentry);
+               if (error)
+                       goto exit2;
                inode = dentry->d_inode;
                if (inode)
                        atomic_inc(&inode->i_count);
@@ -2208,6 +2244,9 @@ static inline int do_rename(const char * oldname, const char * newname)
        error = -EINVAL;
        if (old_dentry == trap)
                goto exit4;
+       error = -EROFS;
+       if (MNT_IS_RDONLY(newnd.mnt))
+               goto exit4;
        new_dentry = lookup_hash(&newnd.last, new_dir);
        error = PTR_ERR(new_dentry);
        if (IS_ERR(new_dentry))
index 9b7d73b..96a4d73 100644 (file)
@@ -223,24 +223,26 @@ static int show_vfsmnt(struct seq_file *m, void *v)
        struct vfsmount *mnt = v;
        int err = 0;
        static struct proc_fs_info {
-               int flag;
-               char *str;
+               int s_flag;
+               int mnt_flag;
+               char *set_str;
+               char *unset_str;
        } fs_info[] = {
-               { MS_SYNCHRONOUS, ",sync" },
-               { MS_DIRSYNC, ",dirsync" },
-               { MS_MANDLOCK, ",mand" },
-               { MS_NOATIME, ",noatime" },
-               { MS_NODIRATIME, ",nodiratime" },
-               { MS_TAGXID, ",tagxid" },
-               { 0, NULL }
+               { MS_RDONLY, MNT_RDONLY, "ro", "rw" },
+               { MS_SYNCHRONOUS, 0, ",sync", NULL },
+               { MS_DIRSYNC, 0, ",dirsync", NULL },
+               { MS_MANDLOCK, 0, ",mand", NULL },
+               { MS_NOATIME, MNT_NOATIME, ",noatime", NULL },
+               { MS_NODIRATIME, MNT_NODIRATIME, ",nodiratime", NULL },
+               { MS_TAGXID, MS_TAGXID, ",tagxid", NULL },
+               { 0, MNT_NOSUID, ",nosuid", NULL },
+               { 0, MNT_NODEV, ",nodev", NULL },
+               { 0, MNT_NOEXEC, ",noexec", NULL },
+               { 0, 0, NULL, NULL }
        };
-       static struct proc_fs_info mnt_info[] = {
-               { MNT_NOSUID, ",nosuid" },
-               { MNT_NODEV, ",nodev" },
-               { MNT_NOEXEC, ",noexec" },
-               { 0, NULL }
-       };
-       struct proc_fs_info *fs_infop;
+       struct proc_fs_info *p;
+       unsigned long s_flags = mnt->mnt_sb->s_flags;
+       int mnt_flags = mnt->mnt_flags;
 
        if (vx_flags(VXF_HIDE_MOUNT, 0))
                return 0;
@@ -250,14 +252,15 @@ static int show_vfsmnt(struct seq_file *m, void *v)
        seq_path(m, mnt, mnt->mnt_root, " \t\n\\");
        seq_putc(m, ' ');
        mangle(m, mnt->mnt_sb->s_type->name);
-       seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? " ro" : " rw");
-       for (fs_infop = fs_info; fs_infop->flag; fs_infop++) {
-               if (mnt->mnt_sb->s_flags & fs_infop->flag)
-                       seq_puts(m, fs_infop->str);
-       }
-       for (fs_infop = mnt_info; fs_infop->flag; fs_infop++) {
-               if (mnt->mnt_flags & fs_infop->flag)
-                       seq_puts(m, fs_infop->str);
+       seq_putc(m, ' ');
+       for (p = fs_info; (p->s_flag | p->mnt_flag) ; p++) {
+               if ((s_flags & p->s_flag) || (mnt_flags & p->mnt_flag)) {
+                       if (p->set_str)
+                               seq_puts(m, p->set_str);
+               } else {
+                       if (p->unset_str)
+                               seq_puts(m, p->unset_str);
+               }
        }
        if (mnt->mnt_sb->s_op->show_options)
                err = mnt->mnt_sb->s_op->show_options(m, mnt);
@@ -644,11 +647,13 @@ out_unlock:
 /*
  * do loopback mount.
  */
-static int do_loopback(struct nameidata *nd, char *old_name, int recurse)
+static int do_loopback(struct nameidata *nd, char *old_name, unsigned long flags, int mnt_flags)
 {
        struct nameidata old_nd;
        struct vfsmount *mnt = NULL;
+       int recurse = flags & MS_REC;
        int err = mount_is_safe(nd);
+
        if (err)
                return err;
        if (!old_name || !*old_name)
@@ -680,6 +685,7 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse)
                        spin_unlock(&vfsmount_lock);
                } else
                        mntput(mnt);
+               mnt->mnt_flags = mnt_flags;
        }
 
        up_write(&current->namespace->sem);
@@ -1025,12 +1031,18 @@ long do_mount(char * dev_name, char * dir_name, char *type_page,
                ((char *)data_page)[PAGE_SIZE - 1] = 0;
 
        /* Separate the per-mountpoint flags */
+       if (flags & MS_RDONLY)
+               mnt_flags |= MNT_RDONLY;
        if (flags & MS_NOSUID)
                mnt_flags |= MNT_NOSUID;
        if (flags & MS_NODEV)
                mnt_flags |= MNT_NODEV;
        if (flags & MS_NOEXEC)
                mnt_flags |= MNT_NOEXEC;
+       if (flags & MS_NOATIME)
+               mnt_flags |= MNT_NOATIME;
+       if (flags & MS_NODIRATIME)
+               mnt_flags |= MNT_NODIRATIME;
        flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_ACTIVE);
 
        if (vx_ccaps(VXC_SECURE_MOUNT))
@@ -1049,7 +1061,7 @@ long do_mount(char * dev_name, char * dir_name, char *type_page,
                retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
                                    data_page);
        else if (flags & MS_BIND)
-               retval = do_loopback(&nd, dev_name, flags & MS_REC);
+               retval = do_loopback(&nd, dev_name, flags, mnt_flags);
        else if (flags & MS_MOVE)
                retval = do_move_mount(&nd, dev_name);
        else
index c1745b6..ed1009d 100644 (file)
@@ -175,7 +175,7 @@ ncp_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 
        *ppos = pos;
 
-       if (!IS_RDONLY(inode)) {
+       if (!IS_RDONLY(inode) || (file && MNT_IS_RDONLY(file->f_vfsmnt))) {
                inode->i_atime = CURRENT_TIME;
        }
        
index 5fb8e87..bae04d6 100644 (file)
@@ -123,7 +123,7 @@ int ncp_mmap(struct file *file, struct vm_area_struct *vma)
        if (((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff 
           > (1U << (32 - PAGE_SHIFT)))
                return -EFBIG;
-       if (!IS_RDONLY(inode)) {
+       if (!IS_RDONLY(inode) || (file && MNT_IS_RDONLY(file->f_vfsmnt))) {
                inode->i_atime = CURRENT_TIME;
        }
 
index f061e70..5f9aa3a 100644 (file)
@@ -778,7 +778,8 @@ static int is_atomic_open(struct inode *dir, struct nameidata *nd)
        if (nd->flags & LOOKUP_DIRECTORY)
                return 0;
        /* Are we trying to write to a read only partition? */
-       if (IS_RDONLY(dir) && (nd->intent.open.flags & (O_CREAT|O_TRUNC|FMODE_WRITE)))
+       if ((IS_RDONLY(dir) || (nd && MNT_IS_RDONLY(nd->mnt))) &&
+               (nd->intent.open.flags & (O_CREAT|O_TRUNC|FMODE_WRITE)))
                return 0;
        return 1;
 }
@@ -1514,7 +1515,7 @@ nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
                 * Nobody gets write access to a read-only fs.
                 *
                 */
-               if (IS_RDONLY(inode) &&
+               if ((IS_RDONLY(inode) || (nd && MNT_IS_RDONLY(nd->mnt))) &&
                    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
                        return -EROFS;
 
index d50269b..6ad7bc7 100644 (file)
@@ -1556,7 +1556,8 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
         */
        if (!(acc & MAY_LOCAL_ACCESS))
                if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) {
-                       if (EX_RDONLY(exp) || IS_RDONLY(inode))
+                       if (EX_RDONLY(exp) || IS_RDONLY(inode)
+                               || (exp && MNT_IS_RDONLY(exp->ex_mnt)))
                                return nfserr_rofs;
                        if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode))
                                return nfserr_perm;
index f19fe19..6c81173 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -245,7 +245,7 @@ static inline long do_sys_truncate(const char __user * path, loff_t length)
                goto dput_and_out;
 
        error = -EROFS;
-       if (IS_RDONLY(inode))
+       if (IS_RDONLY(inode) || MNT_IS_RDONLY(nd.mnt))
                goto dput_and_out;
 
        error = -EPERM;
@@ -369,7 +369,7 @@ asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times)
        inode = nd.dentry->d_inode;
 
        error = -EROFS;
-       if (IS_RDONLY(inode))
+       if (IS_RDONLY(inode) || MNT_IS_RDONLY(nd.mnt))
                goto dput_and_out;
 
        /* Don't worry, the checks are done in inode_change_ok() */
@@ -426,7 +426,7 @@ long do_utimes(char __user * filename, struct timeval * times)
        inode = nd.dentry->d_inode;
 
        error = -EROFS;
-       if (IS_RDONLY(inode))
+       if (IS_RDONLY(inode) || MNT_IS_RDONLY(nd.mnt))
                goto dput_and_out;
 
        /* Don't worry, the checks are done in inode_change_ok() */
@@ -508,7 +508,8 @@ asmlinkage long sys_access(const char __user * filename, int mode)
        if (!res) {
                res = permission(nd.dentry->d_inode, mode, &nd);
                /* SuS v2 requires we report a read only fs too */
-               if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
+               if(!res && (mode & S_IWOTH)
+                  && (IS_RDONLY(nd.dentry->d_inode) || MNT_IS_RDONLY(nd.mnt))
                   && !special_file(nd.dentry->d_inode->i_mode))
                        res = -EROFS;
                path_release(&nd);
@@ -614,7 +615,7 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
        inode = dentry->d_inode;
 
        err = -EROFS;
-       if (IS_RDONLY(inode))
+       if (IS_RDONLY(inode) || (file && MNT_IS_RDONLY(file->f_vfsmnt)))
                goto out_putf;
        err = -EPERM;
        if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
@@ -646,7 +647,7 @@ asmlinkage long sys_chmod(const char __user * filename, mode_t mode)
        inode = nd.dentry->d_inode;
 
        error = -EROFS;
-       if (IS_RDONLY(inode))
+       if (IS_RDONLY(inode) || MNT_IS_RDONLY(nd.mnt))
                goto dput_and_out;
 
        error = -EPERM;
@@ -667,7 +668,8 @@ out:
        return error;
 }
 
-static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
+static int chown_common(struct dentry *dentry, struct vfsmount *mnt,
+       uid_t user, gid_t group)
 {
        struct inode * inode;
        int error;
@@ -679,7 +681,7 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
                goto out;
        }
        error = -EROFS;
-       if (IS_RDONLY(inode))
+       if (IS_RDONLY(inode) || MNT_IS_RDONLY(mnt))
                goto out;
        error = -EPERM;
        if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
@@ -710,7 +712,7 @@ asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group)
 
        error = user_path_walk(filename, &nd);
        if (!error) {
-               error = chown_common(nd.dentry, user, group);
+               error = chown_common(nd.dentry, nd.mnt, user, group);
                path_release(&nd);
        }
        return error;
@@ -723,7 +725,7 @@ asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group
 
        error = user_path_walk_link(filename, &nd);
        if (!error) {
-               error = chown_common(nd.dentry, user, group);
+               error = chown_common(nd.dentry, nd.mnt, user, group);
                path_release(&nd);
        }
        return error;
@@ -737,7 +739,7 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
 
        file = fget(fd);
        if (file) {
-               error = chown_common(file->f_dentry, user, group);
+               error = chown_common(file->f_dentry, file->f_vfsmnt, user, group);
                fput(file);
        }
        return error;
index 36264d5..3e3e2e5 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -255,7 +255,7 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
                kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
        }
        if (ret > 0)
-               inode_update_time(inode, 1);    /* mtime and ctime */
+               inode_update_time(inode, filp->f_vfsmnt, 1);    /* mtime and ctime */
        return ret;
 }
 
index f52b701..11ce15e 100644 (file)
@@ -1160,7 +1160,7 @@ ssize_t reiserfs_file_write( struct file *file, /* the file we are going to writ
     if (res)
        goto out;
 
-    inode_update_time(inode, 1); /* Both mtime and ctime */
+    inode_update_time(inode, file->f_vfsmnt, 1); /* Both mtime and ctime */
 
     // Ok, we are done with all the checks.
 
index 6885230..201cf8b 100644 (file)
@@ -39,7 +39,8 @@ int reiserfs_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
                flags &= REISERFS_FL_USER_VISIBLE;
                return put_user(flags, (int __user *) arg);
        case REISERFS_IOC_SETFLAGS: {
-               if (IS_RDONLY(inode))
+               if (IS_RDONLY(inode) ||
+                       (filp && MNT_IS_RDONLY(filp->f_vfsmnt)))
                        return -EROFS;
 
                if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
@@ -78,7 +79,8 @@ int reiserfs_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
        case REISERFS_IOC_SETVERSION:
                if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
                        return -EPERM;
-               if (IS_RDONLY(inode))
+               if (IS_RDONLY(inode) ||
+                       (filp && MNT_IS_RDONLY(filp->f_vfsmnt)))
                        return -EROFS;
                if (get_user(inode->i_generation, (int __user *) arg))
                        return -EFAULT; 
index 7ef7b45..f8babe6 100644 (file)
@@ -1342,7 +1342,7 @@ __reiserfs_permission (struct inode *inode, int mask, struct nameidata *nd,
                /*
                 * Nobody gets write access to a read-only fs.
                 */
-               if (IS_RDONLY(inode) &&
+               if ((IS_RDONLY(inode) || (nd && MNT_IS_RDONLY(nd->mnt))) &&
                    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
                        return -EROFS;
 
@@ -1397,7 +1397,9 @@ __reiserfs_permission (struct inode *inode, int mask, struct nameidata *nd,
                 }
 #endif
        } else {
+#ifdef CONFIG_REISERFS_FS_POSIX_ACL
 check_groups:
+#endif
                if (in_group_p(inode->i_gid))
                        mode >>= 3;
        }
@@ -1408,7 +1410,9 @@ check_groups:
        if (((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask))
                return 0;
 
+#ifdef CONFIG_REISERFS_FS_POSIX_ACL
 check_capabilities:
+#endif
        /*
         * Read/write DACs are always overridable.
         * Executable DACs are overridable if at least one exec bit is set.
index f2b9326..e83d8e4 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/cache.h>
 #include <linux/prio_tree.h>
 #include <linux/kobject.h>
+#include <linux/mount.h>
 #include <asm/atomic.h>
 
 struct iovec;
@@ -164,7 +165,7 @@ extern int leases_enable, dir_notify_enable, lease_break_time;
  */
 #define __IS_FLG(inode,flg) ((inode)->i_sb->s_flags & (flg))
 
-#define IS_RDONLY(inode) ((inode)->i_sb->s_flags & MS_RDONLY)
+#define IS_RDONLY(inode)       __IS_FLG(inode, MS_RDONLY)
 #define IS_SYNC(inode)         (__IS_FLG(inode, MS_SYNCHRONOUS) || \
                                        ((inode)->i_flags & S_SYNC))
 #define IS_DIRSYNC(inode)      (__IS_FLG(inode, MS_SYNCHRONOUS|MS_DIRSYNC) || \
@@ -993,8 +994,16 @@ static inline void mark_inode_dirty_sync(struct inode *inode)
 
 static inline void touch_atime(struct vfsmount *mnt, struct dentry *dentry)
 {
-       /* per-mountpoint checks will go here */
-       update_atime(dentry->d_inode);
+       struct inode *inode = dentry->d_inode;
+
+       if (MNT_IS_NOATIME(mnt))
+               return;
+       if (S_ISDIR(inode->i_mode) && MNT_IS_NODIRATIME(mnt))
+               return;
+       if (IS_RDONLY(inode) || MNT_IS_RDONLY(mnt))
+               return;
+
+       update_atime(inode);
 }
 
 static inline void file_accessed(struct file *file)
@@ -1548,7 +1557,7 @@ extern ssize_t simple_read_from_buffer(void __user *, size_t, loff_t *, const vo
 extern int inode_change_ok(struct inode *, struct iattr *);
 extern int __must_check inode_setattr(struct inode *, struct iattr *);
 
-extern void inode_update_time(struct inode *inode, int ctime_too);
+extern void inode_update_time(struct inode *inode, struct vfsmount *mnt, int ctime_too);
 
 static inline ino_t parent_ino(struct dentry *dentry)
 {
index 42e2c94..c69739b 100644 (file)
@@ -17,6 +17,9 @@
 #define MNT_NOSUID     1
 #define MNT_NODEV      2
 #define MNT_NOEXEC     4
+#define MNT_RDONLY     8
+#define MNT_NOATIME    16
+#define MNT_NODIRATIME 32
 
 struct vfsmount
 {
@@ -36,6 +39,10 @@ struct vfsmount
        struct namespace *mnt_namespace; /* containing namespace */
 };
 
+#define        MNT_IS_RDONLY(m)        ((m) && ((m)->mnt_flags & MNT_RDONLY))
+#define        MNT_IS_NOATIME(m)       ((m) && ((m)->mnt_flags & MNT_NOATIME))
+#define        MNT_IS_NODIRATIME(m)    ((m) && ((m)->mnt_flags & MNT_NODIRATIME))
+
 static inline struct vfsmount *mntget(struct vfsmount *mnt)
 {
        if (mnt)
index a1d56de..c6d2f66 100644 (file)
@@ -1887,7 +1887,7 @@ generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
        if (err)
                goto out;
 
-       inode_update_time(inode, 1);
+       inode_update_time(inode, file->f_vfsmnt, 1);
 
        /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
        if (unlikely(file->f_flags & O_DIRECT)) {