summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'vserver-sources/old/2.0.1-r5/4914_vs2.0.1-bme-0.06.2.patch')
-rw-r--r--vserver-sources/old/2.0.1-r5/4914_vs2.0.1-bme-0.06.2.patch939
1 files changed, 939 insertions, 0 deletions
diff --git a/vserver-sources/old/2.0.1-r5/4914_vs2.0.1-bme-0.06.2.patch b/vserver-sources/old/2.0.1-r5/4914_vs2.0.1-bme-0.06.2.patch
new file mode 100644
index 0000000..a1ff79c
--- /dev/null
+++ b/vserver-sources/old/2.0.1-r5/4914_vs2.0.1-bme-0.06.2.patch
@@ -0,0 +1,939 @@
+Index: linux-2.6.15/arch/sparc64/solaris/fs.c
+===================================================================
+--- linux-2.6.15.orig/arch/sparc64/solaris/fs.c
++++ linux-2.6.15/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: linux-2.6.15/fs/ext2/ioctl.c
+===================================================================
+--- linux-2.6.15.orig/fs/ext2/ioctl.c
++++ linux-2.6.15/fs/ext2/ioctl.c
+@@ -10,6 +10,7 @@
+ #include "ext2.h"
+ #include <linux/time.h>
+ #include <linux/sched.h>
++#include <linux/mount.h>
+ #include <asm/current.h>
+ #include <asm/uaccess.h>
+
+@@ -29,7 +30,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 +72,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: linux-2.6.15/fs/ext3/ioctl.c
+===================================================================
+--- linux-2.6.15.orig/fs/ext3/ioctl.c
++++ linux-2.6.15/fs/ext3/ioctl.c
+@@ -8,6 +8,7 @@
+ */
+
+ #include <linux/fs.h>
++#include <linux/mount.h>
+ #include <linux/jbd.h>
+ #include <linux/ext3_fs.h>
+ #include <linux/ext3_jbd.h>
+@@ -36,7 +37,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 +116,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 +171,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 +207,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 +229,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: linux-2.6.15/fs/hfsplus/ioctl.c
+===================================================================
+--- linux-2.6.15.orig/fs/hfsplus/ioctl.c
++++ linux-2.6.15/fs/hfsplus/ioctl.c
+@@ -15,6 +15,7 @@
+ #include <linux/fs.h>
+ #include <linux/sched.h>
+ #include <linux/xattr.h>
++#include <linux/mount.h>
+ #include <asm/uaccess.h>
+ #include "hfsplus_fs.h"
+
+@@ -34,7 +35,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: linux-2.6.15/fs/namei.c
+===================================================================
+--- linux-2.6.15.orig/fs/namei.c
++++ linux-2.6.15/fs/namei.c
+@@ -253,7 +253,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;
+
+@@ -1335,7 +1335,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;
+
+@@ -1344,7 +1345,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))
+@@ -1497,7 +1498,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.
+@@ -1761,9 +1763,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;
+@@ -1812,11 +1815,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;
+@@ -1834,9 +1838,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;
+@@ -1875,7 +1880,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);
+@@ -1915,9 +1921,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;
+@@ -1978,7 +1985,7 @@ asmlinkage long sys_rmdir(const char __u
+ dentry = lookup_hash(&nd);
+ 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);
+@@ -1989,9 +1996,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;
+@@ -2053,7 +2061,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);
+ }
+@@ -2072,9 +2080,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;
+@@ -2114,7 +2123,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);
+@@ -2126,7 +2136,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;
+@@ -2134,7 +2145,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;
+
+@@ -2196,7 +2207,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);
+@@ -2323,14 +2335,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;
+
+@@ -2407,6 +2419,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);
+ error = PTR_ERR(new_dentry);
+ if (IS_ERR(new_dentry))
+Index: linux-2.6.15/fs/namespace.c
+===================================================================
+--- linux-2.6.15.orig/fs/namespace.c
++++ linux-2.6.15/fs/namespace.c
+@@ -378,24 +378,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_TAGXID, 0, ",tagxid", 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 },
++ { 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;
+@@ -412,14 +414,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);
+@@ -923,7 +926,8 @@ static int do_change_type(struct nameida
+ /*
+ * 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,
++ unsigned long flags, int mnt_flags)
+ {
+ struct nameidata old_nd;
+ struct vfsmount *mnt = NULL;
+@@ -966,6 +970,7 @@ static int do_loopback(struct nameidata
+ spin_unlock(&vfsmount_lock);
+ release_mounts(&umount_list);
+ }
++ mnt->mnt_flags = mnt_flags;
+
+ out:
+ up_write(&namespace_sem);
+@@ -1361,6 +1366,8 @@ long do_mount(char *dev_name, char *dir_
+ }
+
+ /* 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)
+@@ -1385,7 +1392,7 @@ long do_mount(char *dev_name, char *dir_
+ retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
+ data_page, xid);
+ else if (flags & MS_BIND)
+- retval = do_loopback(&nd, dev_name, flags & MS_REC, xid);
++ retval = do_loopback(&nd, dev_name, xid, flags, mnt_flags);
+ else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
+ retval = do_change_type(&nd, flags);
+ else if (flags & MS_MOVE)
+Index: linux-2.6.15/fs/nfs/dir.c
+===================================================================
+--- linux-2.6.15.orig/fs/nfs/dir.c
++++ linux-2.6.15/fs/nfs/dir.c
+@@ -28,6 +28,7 @@
+ #include <linux/sunrpc/clnt.h>
+ #include <linux/nfs_fs.h>
+ #include <linux/nfs_mount.h>
++#include <linux/mount.h>
+ #include <linux/pagemap.h>
+ #include <linux/smp_lock.h>
+ #include <linux/namei.h>
+@@ -904,7 +905,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: linux-2.6.15/fs/nfsd/vfs.c
+===================================================================
+--- linux-2.6.15.orig/fs/nfsd/vfs.c
++++ linux-2.6.15/fs/nfsd/vfs.c
+@@ -1161,13 +1161,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);
+@@ -1443,11 +1443,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))
+@@ -1505,7 +1507,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);
+@@ -1666,9 +1668,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);
+@@ -1780,7 +1782,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: linux-2.6.15/fs/open.c
+===================================================================
+--- linux-2.6.15.orig/fs/open.c
++++ linux-2.6.15/fs/open.c
+@@ -250,7 +250,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;
+@@ -374,7 +374,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() */
+@@ -431,7 +431,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() */
+@@ -513,7 +513,8 @@ asmlinkage long sys_access(const char __
+ if (!res) {
+ res = vfs_permission(&nd, mode);
+ /* 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);
+@@ -619,7 +620,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))
+@@ -651,7 +652,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;
+@@ -672,7 +673,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;
+@@ -684,7 +686,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))
+@@ -714,7 +716,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;
+@@ -727,7 +729,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;
+@@ -741,7 +743,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: linux-2.6.15/fs/reiserfs/ioctl.c
+===================================================================
+--- linux-2.6.15.orig/fs/reiserfs/ioctl.c
++++ linux-2.6.15/fs/reiserfs/ioctl.c
+@@ -3,6 +3,7 @@
+ */
+
+ #include <linux/fs.h>
++#include <linux/mount.h>
+ #include <linux/reiserfs_fs.h>
+ #include <linux/time.h>
+ #include <asm/uaccess.h>
+@@ -47,7 +48,8 @@ int reiserfs_ioctl(struct inode *inode,
+ if (!reiserfs_attrs(inode->i_sb))
+ 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)
+@@ -87,7 +89,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: linux-2.6.15/fs/reiserfs/xattr.c
+===================================================================
+--- linux-2.6.15.orig/fs/reiserfs/xattr.c
++++ linux-2.6.15/fs/reiserfs/xattr.c
+@@ -34,6 +34,7 @@
+ #include <linux/namei.h>
+ #include <linux/errno.h>
+ #include <linux/fs.h>
++#include <linux/mount.h>
+ #include <linux/file.h>
+ #include <linux/pagemap.h>
+ #include <linux/xattr.h>
+@@ -835,7 +836,7 @@ int reiserfs_delete_xattrs(struct inode
+ 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 {
+@@ -1352,7 +1353,7 @@ __reiserfs_permission(struct inode *inod
+ /*
+ * 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: linux-2.6.15/fs/xattr.c
+===================================================================
+--- linux-2.6.15.orig/fs/xattr.c
++++ linux-2.6.15/fs/xattr.c
+@@ -17,6 +17,7 @@
+ #include <linux/syscalls.h>
+ #include <linux/module.h>
+ #include <linux/fsnotify.h>
++#include <linux/mount.h>
+ #include <asm/uaccess.h>
+
+ /*
+@@ -24,7 +25,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;
+@@ -51,6 +52,9 @@ setxattr(struct dentry *d, char __user *
+ }
+ }
+
++ if (MNT_IS_RDONLY(mnt))
++ return -EROFS;
++
+ down(&d->d_inode->i_sem);
+ error = security_inode_setxattr(d, kname, kvalue, size, flags);
+ if (error)
+@@ -88,7 +92,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;
+ }
+@@ -103,7 +107,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;
+ }
+@@ -118,7 +122,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;
+ }
+@@ -307,7 +311,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];
+@@ -318,6 +322,9 @@ removexattr(struct dentry *d, char __use
+ if (error < 0)
+ return error;
+
++ if (MNT_IS_RDONLY(mnt))
++ return -EROFS;
++
+ error = -EOPNOTSUPP;
+ if (d->d_inode->i_op && d->d_inode->i_op->removexattr) {
+ error = security_inode_removexattr(d, kname);
+@@ -342,7 +349,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;
+ }
+@@ -356,7 +363,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;
+ }
+@@ -370,7 +377,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: linux-2.6.15/include/linux/fs.h
+===================================================================
+--- linux-2.6.15.orig/include/linux/fs.h
++++ linux-2.6.15/include/linux/fs.h
+@@ -156,7 +156,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) || \
+@@ -892,12 +892,12 @@ static inline void unlock_super(struct s
+ */
+ extern int vfs_permission(struct nameidata *, int);
+ 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 *);
+
+ /*
+Index: linux-2.6.15/include/linux/mount.h
+===================================================================
+--- linux-2.6.15.orig/include/linux/mount.h
++++ linux-2.6.15/include/linux/mount.h
+@@ -20,9 +20,12 @@
+ #define MNT_NOSUID 0x01
+ #define MNT_NODEV 0x02
+ #define MNT_NOEXEC 0x04
++#define MNT_RDONLY 0x08
+ #define MNT_SHARED 0x10 /* if the vfsmount is a shared mount */
+ #define MNT_UNBINDABLE 0x20 /* if the vfsmount is a unbindable mount */
+ #define MNT_PNODE_MASK 0x30 /* propogation flag mask */
++#define MNT_NOATIME 0x40
++#define MNT_NODIRATIME 0x80
+ #define MNT_XID 0x100
+
+ struct vfsmount {
+@@ -48,6 +51,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: linux-2.6.15/ipc/mqueue.c
+===================================================================
+--- linux-2.6.15.orig/ipc/mqueue.c
++++ linux-2.6.15/ipc/mqueue.c
+@@ -746,7 +746,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: linux-2.6.15/net/unix/af_unix.c
+===================================================================
+--- linux-2.6.15.orig/net/unix/af_unix.c
++++ linux-2.6.15/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);
+Index: linux-2.6.15/fs/nfsd/nfs4recover.c
+===================================================================
+--- linux-2.6.15.orig/fs/nfsd/nfs4recover.c
++++ linux-2.6.15/fs/nfsd/nfs4recover.c
+@@ -155,7 +155,7 @@ nfsd4_create_clid_dir(struct nfs4_client
+ dprintk("NFSD: nfsd4_create_clid_dir: DIRECTORY EXISTS\n");
+ goto out_put;
+ }
+- status = vfs_mkdir(rec_dir.dentry->d_inode, dentry, S_IRWXU);
++ status = vfs_mkdir(rec_dir.dentry->d_inode, dentry, S_IRWXU, NULL);
+ out_put:
+ dput(dentry);
+ out_unlock:
+@@ -260,7 +260,7 @@ nfsd4_remove_clid_file(struct dentry *di
+ return -EINVAL;
+ }
+ down(&dir->d_inode->i_sem);
+- status = vfs_unlink(dir->d_inode, dentry);
++ status = vfs_unlink(dir->d_inode, dentry, NULL);
+ up(&dir->d_inode->i_sem);
+ return status;
+ }
+@@ -275,7 +275,7 @@ nfsd4_clear_clid_dir(struct dentry *dir,
+ * a kernel from the future.... */
+ nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file);
+ down(&dir->d_inode->i_sem);
+- status = vfs_rmdir(dir->d_inode, dentry);
++ status = vfs_rmdir(dir->d_inode, dentry, NULL);
+ up(&dir->d_inode->i_sem);
+ return status;
+ }