diff options
Diffstat (limited to 'vserver-sources/old/2.0-r1/4915_vs2.0-bme-0.06.1.patch')
-rw-r--r-- | vserver-sources/old/2.0-r1/4915_vs2.0-bme-0.06.1.patch | 894 |
1 files changed, 894 insertions, 0 deletions
diff --git a/vserver-sources/old/2.0-r1/4915_vs2.0-bme-0.06.1.patch b/vserver-sources/old/2.0-r1/4915_vs2.0-bme-0.06.1.patch new file mode 100644 index 0000000..e030778 --- /dev/null +++ b/vserver-sources/old/2.0-r1/4915_vs2.0-bme-0.06.1.patch @@ -0,0 +1,894 @@ +Index: vserver-sources/arch/sparc64/solaris/fs.c +=================================================================== +--- vserver-sources.orig/arch/sparc64/solaris/fs.c ++++ vserver-sources/arch/sparc64/solaris/fs.c +@@ -362,7 +362,7 @@ static int report_statvfs(struct vfsmoun + int j = strlen (p); + + if (j > 15) j = 15; +- if (IS_RDONLY(inode)) i = 1; ++ if (IS_RDONLY(inode) || 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 vfsmo + int j = strlen (p); + + if (j > 15) j = 15; +- if (IS_RDONLY(inode)) i = 1; ++ if (IS_RDONLY(inode) || 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: vserver-sources/fs/ext2/ioctl.c +=================================================================== +--- vserver-sources.orig/fs/ext2/ioctl.c ++++ vserver-sources/fs/ext2/ioctl.c +@@ -29,7 +29,8 @@ int ext2_ioctl (struct inode * inode, st + 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, st + 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: vserver-sources/fs/ext3/ioctl.c +=================================================================== +--- vserver-sources.orig/fs/ext3/ioctl.c ++++ vserver-sources/fs/ext3/ioctl.c +@@ -36,7 +36,8 @@ int ext3_ioctl (struct inode * inode, st + 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)) +@@ -114,7 +115,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; +@@ -168,7 +170,8 @@ flags_err: + if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode)) + return -ENOTTY; + +- 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)) +@@ -203,7 +206,8 @@ flags_err: + if (!capable(CAP_SYS_RESOURCE)) + return -EPERM; + +- if (IS_RDONLY(inode)) ++ if (IS_RDONLY(inode) || ++ (filp && MNT_IS_RDONLY(filp->f_vfsmnt))) + return -EROFS; + + if (get_user(n_blocks_count, (__u32 __user *)arg)) +@@ -224,7 +228,8 @@ flags_err: + if (!capable(CAP_SYS_RESOURCE)) + return -EPERM; + +- if (IS_RDONLY(inode)) ++ if (IS_RDONLY(inode) || ++ (filp && MNT_IS_RDONLY(filp->f_vfsmnt))) + return -EROFS; + + if (copy_from_user(&input, (struct ext3_new_group_input __user *)arg, +Index: vserver-sources/fs/hfsplus/ioctl.c +=================================================================== +--- vserver-sources.orig/fs/hfsplus/ioctl.c ++++ vserver-sources/fs/hfsplus/ioctl.c +@@ -34,7 +34,8 @@ int hfsplus_ioctl(struct inode *inode, s + 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: vserver-sources/fs/namei.c +=================================================================== +--- vserver-sources.orig/fs/namei.c ++++ vserver-sources/fs/namei.c +@@ -252,7 +252,7 @@ int permission(struct inode *inode, int + /* + * 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; + +@@ -1221,7 +1221,8 @@ static inline int check_sticky(struct in + * 10. We don't allow removal of NFS sillyrenamed files; it's handled by + * nfs_async_unlink(). + */ +-static inline int may_delete(struct inode *dir,struct dentry *victim,int isdir) ++static inline int may_delete(struct inode *dir, struct dentry *victim, ++ int isdir, struct nameidata *nd) + { + int error; + +@@ -1230,7 +1231,7 @@ static inline int may_delete(struct inod + + BUG_ON(victim->d_parent->d_inode != dir); + +- error = permission(dir,MAY_WRITE | MAY_EXEC, NULL); ++ error = permission(dir,MAY_WRITE | MAY_EXEC, nd); + if (error) + return error; + if (IS_APPEND(dir)) +@@ -1391,7 +1392,8 @@ int may_open(struct nameidata *nd, int a + return -EACCES; + + flag &= ~O_TRUNC; +- } else if (IS_RDONLY(inode) && (flag & FMODE_WRITE)) ++ } else if ((IS_RDONLY(inode) || MNT_IS_RDONLY(nd->mnt)) ++ && (flag & FMODE_WRITE)) + return -EROFS; + /* + * An append-only file must be opened in append mode for writing. +@@ -1643,9 +1645,10 @@ fail: + } + EXPORT_SYMBOL_GPL(lookup_create); + +-int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) ++int vfs_mknod(struct inode *dir, struct dentry *dentry, ++ int mode, dev_t dev, struct nameidata *nd) + { +- int error = may_create(dir, dentry, NULL); ++ int error = may_create(dir, dentry, nd); + + if (error) + return error; +@@ -1687,7 +1690,6 @@ asmlinkage long sys_mknod(const char __u + goto out; + dentry = lookup_create(&nd, 0); + error = PTR_ERR(dentry); +- + if (!IS_POSIXACL(nd.dentry->d_inode)) + mode &= ~current->fs->umask; + if (!IS_ERR(dentry)) { +@@ -1696,11 +1698,12 @@ asmlinkage long sys_mknod(const char __u + error = vfs_create(nd.dentry->d_inode,dentry,mode,&nd); + break; + case S_IFCHR: case S_IFBLK: +- error = vfs_mknod(nd.dentry->d_inode,dentry,mode, +- new_decode_dev(dev)); ++ error = vfs_mknod(nd.dentry->d_inode, dentry, mode, ++ new_decode_dev(dev), &nd); + break; + case S_IFIFO: case S_IFSOCK: +- error = vfs_mknod(nd.dentry->d_inode,dentry,mode,0); ++ error = vfs_mknod(nd.dentry->d_inode, dentry, mode, ++ 0, &nd); + break; + case S_IFDIR: + error = -EPERM; +@@ -1718,9 +1721,10 @@ out: + return error; + } + +-int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) ++int vfs_mkdir(struct inode *dir, struct dentry *dentry, ++ int mode, struct nameidata *nd) + { +- int error = may_create(dir, dentry, NULL); ++ int error = may_create(dir, dentry, nd); + + if (error) + return error; +@@ -1761,7 +1765,8 @@ asmlinkage long sys_mkdir(const char __u + if (!IS_ERR(dentry)) { + if (!IS_POSIXACL(nd.dentry->d_inode)) + mode &= ~current->fs->umask; +- error = vfs_mkdir(nd.dentry->d_inode, dentry, mode); ++ error = vfs_mkdir(nd.dentry->d_inode, dentry, ++ mode, &nd); + dput(dentry); + } + up(&nd.dentry->d_inode->i_sem); +@@ -1801,9 +1806,10 @@ void dentry_unhash(struct dentry *dentry + spin_unlock(&dcache_lock); + } + +-int vfs_rmdir(struct inode *dir, struct dentry *dentry) ++int vfs_rmdir(struct inode *dir, struct dentry *dentry, ++ struct nameidata *nd) + { +- int error = may_delete(dir, dentry, 1); ++ int error = may_delete(dir, dentry, 1, nd); + + if (error) + return error; +@@ -1865,7 +1871,7 @@ asmlinkage long sys_rmdir(const char __u + dentry = lookup_hash(&nd.last, nd.dentry); + error = PTR_ERR(dentry); + if (!IS_ERR(dentry)) { +- error = vfs_rmdir(nd.dentry->d_inode, dentry); ++ error = vfs_rmdir(nd.dentry->d_inode, dentry, &nd); + dput(dentry); + } + up(&nd.dentry->d_inode->i_sem); +@@ -1876,9 +1882,10 @@ exit: + return error; + } + +-int vfs_unlink(struct inode *dir, struct dentry *dentry) ++int vfs_unlink(struct inode *dir, struct dentry *dentry, ++ struct nameidata *nd) + { +- int error = may_delete(dir, dentry, 0); ++ int error = may_delete(dir, dentry, 0, nd); + + if (error) + return error; +@@ -1941,7 +1948,7 @@ asmlinkage long sys_unlink(const char __ + inode = dentry->d_inode; + if (inode) + atomic_inc(&inode->i_count); +- error = vfs_unlink(nd.dentry->d_inode, dentry); ++ error = vfs_unlink(nd.dentry->d_inode, dentry, &nd); + exit2: + dput(dentry); + } +@@ -1960,9 +1967,10 @@ slashes: + goto exit2; + } + +-int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, int mode) ++int vfs_symlink(struct inode *dir, struct dentry *dentry, ++ const char *oldname, int mode, struct nameidata *nd) + { +- int error = may_create(dir, dentry, NULL); ++ int error = may_create(dir, dentry, nd); + + if (error) + return error; +@@ -2004,7 +2012,8 @@ asmlinkage long sys_symlink(const char _ + dentry = lookup_create(&nd, 0); + error = PTR_ERR(dentry); + if (!IS_ERR(dentry)) { +- error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO); ++ error = vfs_symlink(nd.dentry->d_inode, dentry, ++ from, S_IALLUGO, &nd); + dput(dentry); + } + up(&nd.dentry->d_inode->i_sem); +@@ -2016,7 +2025,8 @@ out: + return error; + } + +-int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) ++int vfs_link(struct dentry *old_dentry, struct inode *dir, ++ struct dentry *new_dentry, struct nameidata *nd) + { + struct inode *inode = old_dentry->d_inode; + int error; +@@ -2024,7 +2034,7 @@ int vfs_link(struct dentry *old_dentry, + if (!inode) + return -ENOENT; + +- error = may_create(dir, new_dentry, NULL); ++ error = may_create(dir, new_dentry, nd); + if (error) + return error; + +@@ -2088,7 +2098,8 @@ asmlinkage long sys_link(const char __us + new_dentry = lookup_create(&nd, 0); + error = PTR_ERR(new_dentry); + if (!IS_ERR(new_dentry)) { +- error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); ++ error = vfs_link(old_nd.dentry, nd.dentry->d_inode, ++ new_dentry, &nd); + dput(new_dentry); + } + up(&nd.dentry->d_inode->i_sem); +@@ -2219,14 +2230,14 @@ int vfs_rename(struct inode *old_dir, st + if (old_dentry->d_inode == new_dentry->d_inode) + return 0; + +- error = may_delete(old_dir, old_dentry, is_dir); ++ error = may_delete(old_dir, old_dentry, is_dir, NULL); + if (error) + return error; + + if (!new_dentry->d_inode) + error = may_create(new_dir, new_dentry, NULL); + else +- error = may_delete(new_dir, new_dentry, is_dir); ++ error = may_delete(new_dir, new_dentry, is_dir, NULL); + if (error) + return error; + +@@ -2302,6 +2313,9 @@ static inline int do_rename(const char * + 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: vserver-sources/fs/namespace.c +=================================================================== +--- vserver-sources.orig/fs/namespace.c ++++ vserver-sources/fs/namespace.c +@@ -249,24 +249,26 @@ static int show_vfsmnt(struct seq_file * + 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 }, ++ { 0, MNT_NOSUID, ",nosuid", NULL }, ++ { 0, MNT_NODEV, ",nodev", NULL }, ++ { 0, MNT_NOEXEC, ",noexec", NULL }, ++ { MS_TAGXID, 0, ",tagxid", 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; +@@ -283,14 +285,15 @@ static int show_vfsmnt(struct seq_file * + 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_flags & MNT_XID) + seq_printf(m, ",xid=%d", mnt->mnt_xid); +@@ -682,7 +685,8 @@ out_unlock: + /* + * do loopback mount. + */ +-static int do_loopback(struct nameidata *nd, char *old_name, xid_t xid, int flags) ++static int do_loopback(struct nameidata *nd, char *old_name, ++ xid_t xid, int flags, int mnt_flags) + { + struct nameidata old_nd; + struct vfsmount *mnt = NULL; +@@ -723,6 +727,7 @@ static int do_loopback(struct nameidata + spin_unlock(&vfsmount_lock); + } else + mntput(mnt); ++ mnt->mnt_flags = mnt_flags; + } + + up_write(¤t->namespace->sem); +@@ -1110,12 +1115,18 @@ long do_mount(char * dev_name, char * di + } + + /* 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)) +@@ -1134,7 +1145,7 @@ long do_mount(char * dev_name, char * di + retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags, + data_page, xid); + else if (flags & MS_BIND) +- retval = do_loopback(&nd, dev_name, xid, flags); ++ retval = do_loopback(&nd, dev_name, xid, flags, mnt_flags); + else if (flags & MS_MOVE) + retval = do_move_mount(&nd, dev_name); + else +Index: vserver-sources/fs/nfs/dir.c +=================================================================== +--- vserver-sources.orig/fs/nfs/dir.c ++++ vserver-sources/fs/nfs/dir.c +@@ -806,7 +806,8 @@ static int is_atomic_open(struct inode * + 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) || MNT_IS_RDONLY(nd->mnt)) && ++ (nd->intent.open.flags & (O_CREAT|O_TRUNC|FMODE_WRITE))) + return 0; + return 1; + } +Index: vserver-sources/fs/nfsd/vfs.c +=================================================================== +--- vserver-sources.orig/fs/nfsd/vfs.c ++++ vserver-sources/fs/nfsd/vfs.c +@@ -1155,13 +1155,13 @@ nfsd_create(struct svc_rqst *rqstp, stru + err = vfs_create(dirp, dchild, iap->ia_mode, NULL); + break; + case S_IFDIR: +- err = vfs_mkdir(dirp, dchild, iap->ia_mode); ++ err = vfs_mkdir(dirp, dchild, iap->ia_mode, NULL); + break; + case S_IFCHR: + case S_IFBLK: + case S_IFIFO: + case S_IFSOCK: +- err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); ++ err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev, NULL); + break; + default: + printk("nfsd: bad file type %o in nfsd_create\n", type); +@@ -1437,11 +1437,13 @@ nfsd_symlink(struct svc_rqst *rqstp, str + else { + strncpy(path_alloced, path, plen); + path_alloced[plen] = 0; +- err = vfs_symlink(dentry->d_inode, dnew, path_alloced, mode); ++ err = vfs_symlink(dentry->d_inode, dnew, ++ path_alloced, mode, NULL); + kfree(path_alloced); + } + } else +- err = vfs_symlink(dentry->d_inode, dnew, path, mode); ++ err = vfs_symlink(dentry->d_inode, dnew, ++ path, mode, NULL); + + if (!err) { + if (EX_ISSYNC(fhp->fh_export)) +@@ -1499,7 +1501,7 @@ nfsd_link(struct svc_rqst *rqstp, struct + dold = tfhp->fh_dentry; + dest = dold->d_inode; + +- err = vfs_link(dold, dirp, dnew); ++ err = vfs_link(dold, dirp, dnew, NULL); + if (!err) { + if (EX_ISSYNC(ffhp->fh_export)) { + nfsd_sync_dir(ddir); +@@ -1660,9 +1662,9 @@ nfsd_unlink(struct svc_rqst *rqstp, stru + err = nfserr_perm; + } else + #endif +- err = vfs_unlink(dirp, rdentry); ++ err = vfs_unlink(dirp, rdentry, NULL); + } else { /* It's RMDIR */ +- err = vfs_rmdir(dirp, rdentry); ++ err = vfs_rmdir(dirp, rdentry, NULL); + } + + dput(rdentry); +@@ -1774,7 +1776,8 @@ nfsd_permission(struct svc_export *exp, + */ + 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) ++ || MNT_IS_RDONLY(exp->ex_mnt)) + return nfserr_rofs; + if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode)) + return nfserr_perm; +Index: vserver-sources/fs/open.c +=================================================================== +--- vserver-sources.orig/fs/open.c ++++ vserver-sources/fs/open.c +@@ -244,7 +244,7 @@ static inline long do_sys_truncate(const + 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; +@@ -368,7 +368,7 @@ asmlinkage long sys_utime(char __user * + 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() */ +@@ -425,7 +425,7 @@ long do_utimes(char __user * filename, s + 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() */ +@@ -507,7 +507,8 @@ asmlinkage long sys_access(const char __ + 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); +@@ -613,7 +614,7 @@ asmlinkage long sys_fchmod(unsigned int + inode = dentry->d_inode; + + err = -EROFS; +- if (IS_RDONLY(inode)) ++ if (IS_RDONLY(inode) || MNT_IS_RDONLY(file->f_vfsmnt)) + goto out_putf; + err = -EPERM; + if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) +@@ -645,7 +646,7 @@ asmlinkage long sys_chmod(const char __u + 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; +@@ -666,7 +667,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; +@@ -678,7 +680,7 @@ static int chown_common(struct dentry * + 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)) +@@ -708,7 +710,7 @@ asmlinkage long sys_chown(const char __u + + 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; +@@ -721,7 +723,7 @@ asmlinkage long sys_lchown(const char __ + + 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; +@@ -735,7 +737,7 @@ asmlinkage long sys_fchown(unsigned int + + 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: vserver-sources/fs/reiserfs/ioctl.c +=================================================================== +--- vserver-sources.orig/fs/reiserfs/ioctl.c ++++ vserver-sources/fs/reiserfs/ioctl.c +@@ -41,7 +41,8 @@ int reiserfs_ioctl (struct inode * inode + 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)) +@@ -80,7 +81,8 @@ int reiserfs_ioctl (struct inode * inode + 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: vserver-sources/fs/reiserfs/xattr.c +=================================================================== +--- vserver-sources.orig/fs/reiserfs/xattr.c ++++ vserver-sources/fs/reiserfs/xattr.c +@@ -830,7 +830,7 @@ reiserfs_delete_xattrs (struct inode *in + if (dir->d_inode->i_nlink <= 2) { + root = get_xa_root (inode->i_sb); + reiserfs_write_lock_xattrs (inode->i_sb); +- err = vfs_rmdir (root->d_inode, dir); ++ err = vfs_rmdir (root->d_inode, dir, NULL); + reiserfs_write_unlock_xattrs (inode->i_sb); + dput (root); + } else { +@@ -1351,7 +1351,7 @@ __reiserfs_permission (struct inode *ino + /* + * 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: vserver-sources/fs/xattr.c +=================================================================== +--- vserver-sources.orig/fs/xattr.c ++++ vserver-sources/fs/xattr.c +@@ -24,7 +24,7 @@ + */ + static long + setxattr(struct dentry *d, char __user *name, void __user *value, +- size_t size, int flags) ++ size_t size, int flags, struct vfsmount *mnt) + { + int error; + void *kvalue = NULL; +@@ -57,6 +57,9 @@ setxattr(struct dentry *d, char __user * + error = security_inode_setxattr(d, kname, kvalue, size, flags); + if (error) + goto out; ++ error = -EROFS; ++ if (MNT_IS_RDONLY(mnt)) ++ goto out; + error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags); + if (!error) { + fsnotify_xattr(d); +@@ -80,7 +83,7 @@ sys_setxattr(char __user *path, char __u + error = user_path_walk(path, &nd); + if (error) + return error; +- error = setxattr(nd.dentry, name, value, size, flags); ++ error = setxattr(nd.dentry, name, value, size, flags, nd.mnt); + path_release(&nd); + return error; + } +@@ -95,7 +98,7 @@ sys_lsetxattr(char __user *path, char __ + error = user_path_walk_link(path, &nd); + if (error) + return error; +- error = setxattr(nd.dentry, name, value, size, flags); ++ error = setxattr(nd.dentry, name, value, size, flags, nd.mnt); + path_release(&nd); + return error; + } +@@ -110,7 +113,7 @@ sys_fsetxattr(int fd, char __user *name, + f = fget(fd); + if (!f) + return error; +- error = setxattr(f->f_dentry, name, value, size, flags); ++ error = setxattr(f->f_dentry, name, value, size, flags, f->f_vfsmnt); + fput(f); + return error; + } +@@ -288,7 +291,7 @@ sys_flistxattr(int fd, char __user *list + * Extended attribute REMOVE operations + */ + static long +-removexattr(struct dentry *d, char __user *name) ++removexattr(struct dentry *d, char __user *name, struct vfsmount *mnt) + { + int error; + char kname[XATTR_NAME_MAX + 1]; +@@ -304,6 +307,9 @@ removexattr(struct dentry *d, char __use + error = security_inode_removexattr(d, kname); + if (error) + goto out; ++ error = -EROFS; ++ if (MNT_IS_RDONLY(mnt)) ++ goto out; + down(&d->d_inode->i_sem); + error = d->d_inode->i_op->removexattr(d, kname); + up(&d->d_inode->i_sem); +@@ -321,7 +327,7 @@ sys_removexattr(char __user *path, char + error = user_path_walk(path, &nd); + if (error) + return error; +- error = removexattr(nd.dentry, name); ++ error = removexattr(nd.dentry, name, nd.mnt); + path_release(&nd); + return error; + } +@@ -335,7 +341,7 @@ sys_lremovexattr(char __user *path, char + error = user_path_walk_link(path, &nd); + if (error) + return error; +- error = removexattr(nd.dentry, name); ++ error = removexattr(nd.dentry, name, nd.mnt); + path_release(&nd); + return error; + } +@@ -349,7 +355,7 @@ sys_fremovexattr(int fd, char __user *na + f = fget(fd); + if (!f) + return error; +- error = removexattr(f->f_dentry, name); ++ error = removexattr(f->f_dentry, name, f->f_vfsmnt); + fput(f); + return error; + } +Index: vserver-sources/include/linux/fs.h +=================================================================== +--- vserver-sources.orig/include/linux/fs.h ++++ vserver-sources/include/linux/fs.h +@@ -9,6 +9,7 @@ + #include <linux/config.h> + #include <linux/limits.h> + #include <linux/ioctl.h> ++#include <linux/mount.h> + + /* + * It's silly to have NR_OPEN bigger than NR_FILE, but you can change +@@ -150,7 +151,7 @@ extern int dir_notify_enable; + */ + #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) || \ +@@ -858,12 +859,12 @@ static inline void unlock_super(struct s + * VFS helper functions.. + */ + extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *); +-extern int vfs_mkdir(struct inode *, struct dentry *, int); +-extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t); +-extern int vfs_symlink(struct inode *, struct dentry *, const char *, int); +-extern int vfs_link(struct dentry *, struct inode *, struct dentry *); +-extern int vfs_rmdir(struct inode *, struct dentry *); +-extern int vfs_unlink(struct inode *, struct dentry *); ++extern int vfs_mkdir(struct inode *, struct dentry *, int, struct nameidata *); ++extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t, struct nameidata *); ++extern int vfs_symlink(struct inode *, struct dentry *, const char *, int, struct nameidata *); ++extern int vfs_link(struct dentry *, struct inode *, struct dentry *, struct nameidata *); ++extern int vfs_rmdir(struct inode *, struct dentry *, struct nameidata *); ++extern int vfs_unlink(struct inode *, struct dentry *, struct nameidata *); + extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); + + /* +@@ -1061,8 +1062,16 @@ static inline void mark_inode_dirty_sync + + 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) +Index: vserver-sources/include/linux/mount.h +=================================================================== +--- vserver-sources.orig/include/linux/mount.h ++++ vserver-sources/include/linux/mount.h +@@ -19,6 +19,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 + #define MNT_XID 256 + + struct vfsmount +@@ -40,6 +43,10 @@ struct vfsmount + xid_t mnt_xid; /* xid tagging used for vfsmount */ + }; + ++#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: vserver-sources/ipc/mqueue.c +=================================================================== +--- vserver-sources.orig/ipc/mqueue.c ++++ vserver-sources/ipc/mqueue.c +@@ -738,7 +738,7 @@ asmlinkage long sys_mq_unlink(const char + if (inode) + atomic_inc(&inode->i_count); + +- err = vfs_unlink(dentry->d_parent->d_inode, dentry); ++ err = vfs_unlink(dentry->d_parent->d_inode, dentry, NULL); + out_err: + dput(dentry); + +Index: vserver-sources/net/unix/af_unix.c +=================================================================== +--- vserver-sources.orig/net/unix/af_unix.c ++++ vserver-sources/net/unix/af_unix.c +@@ -784,7 +784,7 @@ static int unix_bind(struct socket *sock + */ + mode = S_IFSOCK | + (SOCK_INODE(sock)->i_mode & ~current->fs->umask); +- err = vfs_mknod(nd.dentry->d_inode, dentry, mode, 0); ++ err = vfs_mknod(nd.dentry->d_inode, dentry, mode, 0, NULL); + if (err) + goto out_mknod_dput; + up(&nd.dentry->d_inode->i_sem); |