http://forum.openvz.org/index.php?t=tree&goto=3027&#msg_3027

diff -ruN linux-2.6.16-openvz-026.009/arch/sparc64/solaris/fs.c /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/arch/sparc64/solaris/fs.c
--- linux-2.6.16-openvz-026.009/arch/sparc64/solaris/fs.c	2006-04-27 20:37:06.000000000 +0200
+++ /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/arch/sparc64/solaris/fs.c	2006-05-08 23:43:24.161270500 +0200
@@ -363,7 +363,7 @@
 		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;
@@ -399,7 +399,7 @@
 		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;
diff -ruN linux-2.6.16-openvz-026.009/fs/ext2/ioctl.c /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/ext2/ioctl.c
--- linux-2.6.16-openvz-026.009/fs/ext2/ioctl.c	2006-04-27 20:37:06.000000000 +0200
+++ /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/ext2/ioctl.c	2006-05-08 23:43:24.161270500 +0200
@@ -11,6 +11,7 @@
 #include <linux/capability.h>
 #include <linux/time.h>
 #include <linux/sched.h>
+#include <linux/mount.h>
 #include <asm/current.h>
 #include <asm/uaccess.h>
 
@@ -30,7 +31,8 @@
 	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))
@@ -69,7 +71,8 @@
 	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;	
diff -ruN linux-2.6.16-openvz-026.009/fs/ext3/ioctl.c /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/ext3/ioctl.c
--- linux-2.6.16-openvz-026.009/fs/ext3/ioctl.c	2006-04-27 20:37:06.000000000 +0200
+++ /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/ext3/ioctl.c	2006-05-08 23:43:24.161270500 +0200
@@ -13,6 +13,7 @@
 #include <linux/ext3_fs.h>
 #include <linux/ext3_jbd.h>
 #include <linux/time.h>
+#include <linux/mount.h>
 #include <asm/uaccess.h>
 
 
@@ -36,7 +37,8 @@
 		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))
@@ -112,7 +114,8 @@
 
 		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;
@@ -166,7 +169,8 @@
 		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))
@@ -201,7 +205,8 @@
 		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))
@@ -222,7 +227,8 @@
 		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,
diff -ruN linux-2.6.16-openvz-026.009/fs/hfsplus/ioctl.c /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/hfsplus/ioctl.c
--- linux-2.6.16-openvz-026.009/fs/hfsplus/ioctl.c	2006-04-27 20:37:06.000000000 +0200
+++ /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/hfsplus/ioctl.c	2006-05-08 23:43:24.161270500 +0200
@@ -35,7 +35,8 @@
 			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))
diff -ruN linux-2.6.16-openvz-026.009/fs/inode.c /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/inode.c
--- linux-2.6.16-openvz-026.009/fs/inode.c	2006-04-27 20:37:06.000000000 +0200
+++ /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/inode.c	2006-05-08 23:43:24.165270750 +0200
@@ -1260,7 +1260,8 @@
 	 */
 	if (mnt &&
 	    ((mnt->mnt_flags & MNT_NOATIME) ||
-	     ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))))
+	     ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode)) ||
+	     (MNT_IS_RDONLY(mnt))))
 		return;
 
 	now = current_fs_time(inode->i_sb);
diff -ruN linux-2.6.16-openvz-026.009/fs/namei.c /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/namei.c
--- linux-2.6.16-openvz-026.009/fs/namei.c	2006-04-27 20:37:06.000000000 +0200
+++ /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/namei.c	2006-05-08 23:43:24.165270750 +0200
@@ -254,7 +254,7 @@
 		/*
 		 * 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;
 
@@ -1037,6 +1037,24 @@
 	return link_path_walk(name, 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_IS_RDONLY(mnt))
+               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_IS_RDONLY(mnt))
+               return -EROFS;
+       return 0;
+}
+
 /* 
  * SMP-safe: Returns 1 and nd will have valid dentry and mnt, if
  * everything is done. Returns 0 and drops input nd, if lookup failed;
@@ -1546,7 +1564,8 @@
 			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.
@@ -1777,15 +1796,17 @@
  */
 struct dentry *lookup_create(struct nameidata *nd, int is_dir)
 {
-	struct dentry *dentry = ERR_PTR(-EEXIST);
-
+	struct dentry *dentry;
+	int error;
+  
 	mutex_lock(&nd->dentry->d_inode->i_mutex);
 	/*
 	 * Yucky last component or no last component at all?
 	 * (foo/., foo/.., /////)
 	 */
+	error = -EEXIST;
 	if (nd->last_type != LAST_NORM)
-		goto fail;
+		goto out;
 	nd->flags &= ~LOOKUP_PARENT;
 
 	/*
@@ -1793,6 +1814,10 @@
 	 */
 	dentry = lookup_hash(nd);
 	if (IS_ERR(dentry))
+		goto ret;
+
+	error = mnt_may_create(nd->mnt, nd->dentry->d_inode, dentry);
+	if (error)
 		goto fail;
 
 	/*
@@ -1801,14 +1826,15 @@
 	 * all is fine. Let's be bastards - you had / on the end, you've
 	 * been asking for (non-existent) directory. -ENOENT for you.
 	 */
+	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);
 }
 EXPORT_SYMBOL_GPL(lookup_create);
 
@@ -2042,7 +2068,11 @@
 	dentry = lookup_hash(&nd);
 	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);
 	}
 	mutex_unlock(&nd.dentry->d_inode->i_mutex);
@@ -2120,6 +2150,9 @@
 		/* 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);
@@ -2514,6 +2547,9 @@
 	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))
diff -ruN linux-2.6.16-openvz-026.009/fs/namespace.c /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/namespace.c
--- linux-2.6.16-openvz-026.009/fs/namespace.c	2006-04-27 20:37:06.000000000 +0200
+++ /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/namespace.c	2006-05-08 23:51:33.519853500 +0200
@@ -356,23 +356,25 @@
 	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" },
-		{ 0, NULL }
+		{ MS_RDONLY, MNT_RDONLY, "ro", "rw" },
+		{ MS_SYNCHRONOUS, 0, ",sync", NULL },
+		{ MS_DIRSYNC, 0, ",dirsync", NULL },
+		{ MS_MANDLOCK, 0, ",mand", NULL },
+		{ 0, MNT_NOSUID, ",nosuid", NULL },
+		{ 0, MNT_NODEV, ",nodev", NULL },
+		{ 0, MNT_NOEXEC, ",noexec", NULL },
+		{ 0, MNT_NOATIME, ",noatime", NULL },
+		{ 0, MNT_NODIRATIME, ",nodiratime", NULL },
+		{ 0, 0, NULL, NULL }
 	};
-	static struct proc_fs_info mnt_info[] = {
-		{ MNT_NOSUID, ",nosuid" },
-		{ MNT_NODEV, ",nodev" },
-		{ MNT_NOEXEC, ",noexec" },
-		{ MNT_NOATIME, ",noatime" },
-		{ MNT_NODIRATIME, ",nodiratime" },
-		{ 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;
 	char *path_buf, *path;
 
 	/* skip FS_NOMOUNT mounts (rootfs) */
@@ -401,14 +403,15 @@
 	free_page((unsigned long) path_buf);
 	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);
@@ -887,11 +890,13 @@
 /*
  * 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)
@@ -925,6 +930,7 @@
 		spin_unlock(&vfsmount_lock);
 		release_mounts(&umount_list);
 	}
+	mnt->mnt_flags = mnt_flags;
 
 out:
 	up_write(&namespace_sem);
@@ -1315,6 +1321,8 @@
 		((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)
@@ -1342,7 +1350,7 @@
 		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_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
 		retval = do_change_type(&nd, flags);
 	else if (flags & MS_MOVE)
diff -ruN linux-2.6.16-openvz-026.009/fs/nfs/dir.c /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/nfs/dir.c
--- linux-2.6.16-openvz-026.009/fs/nfs/dir.c	2006-04-27 20:37:06.000000000 +0200
+++ /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/nfs/dir.c	2006-05-08 23:43:24.173271250 +0200
@@ -902,7 +902,8 @@
 	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;
 }
diff -ruN linux-2.6.16-openvz-026.009/fs/nfsd/vfs.c /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/nfsd/vfs.c
--- linux-2.6.16-openvz-026.009/fs/nfsd/vfs.c	2006-04-27 20:37:06.000000000 +0200
+++ /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/nfsd/vfs.c	2006-05-08 23:43:24.173271250 +0200
@@ -1781,7 +1781,8 @@
 	 */
 	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;
diff -ruN linux-2.6.16-openvz-026.009/fs/open.c /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/open.c
--- linux-2.6.16-openvz-026.009/fs/open.c	2006-04-27 20:37:06.000000000 +0200
+++ /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/open.c	2006-05-08 23:43:24.181271750 +0200
@@ -285,7 +285,7 @@
 		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;
@@ -409,7 +409,7 @@
 	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() */
@@ -466,7 +466,7 @@
 	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() */
@@ -553,7 +553,8 @@
 	if (!res) {
 		res = vfs_permission(&nd, mode, NULL);
 		/* 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);
@@ -664,7 +665,7 @@
 	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))
@@ -697,7 +698,7 @@
 	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;
@@ -723,7 +724,8 @@
 	return sys_fchmodat(AT_FDCWD, filename, mode);
 }
 
-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;
@@ -735,7 +737,7 @@
 		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))
@@ -765,7 +767,7 @@
 
 	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;
@@ -785,7 +787,7 @@
 	follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
 	error = __user_walk_fd(dfd, filename, follow, &nd);
 	if (!error) {
-		error = chown_common(nd.dentry, user, group);
+		error = chown_common(nd.dentry, nd.mnt, user, group);
 		path_release(&nd);
 	}
 out:
@@ -799,7 +801,7 @@
 
 	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;
@@ -813,7 +815,7 @@
 
 	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;
diff -ruN linux-2.6.16-openvz-026.009/fs/pipe.c /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/pipe.c
--- linux-2.6.16-openvz-026.009/fs/pipe.c	2006-04-27 20:37:06.000000000 +0200
+++ /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/pipe.c	2006-05-08 23:43:24.181271750 +0200
@@ -346,7 +346,7 @@
 		wake_up_interruptible(PIPE_WAIT(*inode));
 		kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
 	}
-	if (ret > 0)
+	if ((ret > 0) && !MNT_IS_RDONLY(filp->f_vfsmnt))
 		file_update_time(filp);
 	return ret;
 }
diff -ruN linux-2.6.16-openvz-026.009/fs/reiserfs/ioctl.c /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/reiserfs/ioctl.c
--- linux-2.6.16-openvz-026.009/fs/reiserfs/ioctl.c	2006-04-27 20:37:06.000000000 +0200
+++ /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/reiserfs/ioctl.c	2006-05-09 00:00:10.504163000 +0200
@@ -9,6 +9,7 @@
 #include <asm/uaccess.h>
 #include <linux/pagemap.h>
 #include <linux/smp_lock.h>
+#include <linux/mount.h>
 
 static int reiserfs_unpack(struct inode *inode, struct file *filp);
 
@@ -47,7 +48,8 @@
 			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)
@@ -82,7 +84,8 @@
 	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;
diff -ruN linux-2.6.16-openvz-026.009/fs/xattr.c /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/xattr.c
--- linux-2.6.16-openvz-026.009/fs/xattr.c	2006-04-27 20:37:06.000000000 +0200
+++ /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/fs/xattr.c	2006-05-08 23:43:24.185272000 +0200
@@ -17,6 +17,7 @@
 #include <linux/syscalls.h>
 #include <linux/module.h>
 #include <linux/fsnotify.h>
+#include <linux/mount.h>
 #include <asm/uaccess.h>
 
 
@@ -63,7 +64,7 @@
 
 int
 vfs_setxattr(struct dentry *dentry, char *name, void *value,
-		size_t size, int flags)
+		size_t size, int flags, struct vfsmount *mnt)
 {
 	struct inode *inode = dentry->d_inode;
 	int error;
@@ -76,6 +77,9 @@
 	error = security_inode_setxattr(dentry, name, value, size, flags);
 	if (error)
 		goto out;
+	error = -EROFS;
+	if (MNT_IS_RDONLY(mnt))
+		goto out;
 	error = -EOPNOTSUPP;
 	if (inode->i_op->setxattr) {
 		error = inode->i_op->setxattr(dentry, name, value, size, flags);
@@ -135,7 +139,7 @@
 EXPORT_SYMBOL_GPL(vfs_getxattr);
 
 int
-vfs_removexattr(struct dentry *dentry, char *name)
+vfs_removexattr(struct dentry *dentry, char *name, struct vfsmount *mnt)
 {
 	struct inode *inode = dentry->d_inode;
 	int error;
@@ -151,6 +155,10 @@
 	if (error)
 		return error;
 
+	error = -EROFS;
+	if (MNT_IS_RDONLY(mnt))
+		return error;
+
 	mutex_lock(&inode->i_mutex);
 	error = inode->i_op->removexattr(dentry, name);
 	mutex_unlock(&inode->i_mutex);
@@ -167,7 +175,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;
@@ -194,7 +202,7 @@
 		}
 	}
 
-	error = vfs_setxattr(d, kname, kvalue, size, flags);
+	error = vfs_setxattr(d, kname, kvalue, size, flags, mnt);
 	kfree(kvalue);
 	return error;
 }
@@ -209,7 +217,7 @@
 	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;
 }
@@ -224,7 +232,7 @@
 	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;
 }
@@ -239,7 +247,7 @@
 	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;
 }
@@ -412,7 +420,7 @@
  * 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];
@@ -423,7 +431,7 @@
 	if (error < 0)
 		return error;
 
-	return vfs_removexattr(d, kname);
+	return vfs_removexattr(d, kname, mnt);
 }
 
 asmlinkage long
@@ -435,7 +443,7 @@
 	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;
 }
@@ -449,7 +457,7 @@
 	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;
 }
@@ -463,7 +471,7 @@
 	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;
 }
diff -ruN linux-2.6.16-openvz-026.009/include/linux/autoconf.h /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/include/linux/autoconf.h
--- linux-2.6.16-openvz-026.009/include/linux/autoconf.h	2006-04-28 20:49:06.792443750 +0200
+++ /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/include/linux/autoconf.h	2006-05-08 23:51:54.213146750 +0200
@@ -1,7 +1,7 @@
 /*
  * Automatically generated C config: don't edit
  * Linux kernel version: 2.6.16-026test009
- * Fri Apr 28 20:49:06 2006
+ * Mon May  8 23:51:54 2006
  */
 #define AUTOCONF_INCLUDED
 #define CONFIG_X86_32 1
diff -ruN linux-2.6.16-openvz-026.009/include/linux/fs.h /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/include/linux/fs.h
--- linux-2.6.16-openvz-026.009/include/linux/fs.h	2006-04-27 20:37:06.000000000 +0200
+++ /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/include/linux/fs.h	2006-05-08 23:43:24.185272000 +0200
@@ -154,7 +154,7 @@
  */
 #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) || \
diff -ruN linux-2.6.16-openvz-026.009/include/linux/mount.h /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/include/linux/mount.h
--- linux-2.6.16-openvz-026.009/include/linux/mount.h	2006-04-27 20:37:06.000000000 +0200
+++ /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/include/linux/mount.h	2006-05-08 23:43:24.185272000 +0200
@@ -20,8 +20,9 @@
 #define MNT_NOSUID	0x01
 #define MNT_NODEV	0x02
 #define MNT_NOEXEC	0x04
-#define MNT_NOATIME	0x08
-#define MNT_NODIRATIME	0x10
+#define MNT_RDONLY	0x08
+#define MNT_NOATIME	0x10
+#define MNT_NODIRATIME	0x20
 
 #define MNT_SHARED	0x1000	/* if the vfsmount is a shared mount */
 #define MNT_UNBINDABLE	0x2000	/* if the vfsmount is a unbindable mount */
@@ -49,6 +50,10 @@
 	int mnt_pinned;
 };
 
+#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)
diff -ruN linux-2.6.16-openvz-026.009/include/linux/xattr.h /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/include/linux/xattr.h
--- linux-2.6.16-openvz-026.009/include/linux/xattr.h	2006-04-27 20:37:06.000000000 +0200
+++ /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/include/linux/xattr.h	2006-05-08 23:43:24.189272250 +0200
@@ -41,8 +41,8 @@
 };
 
 ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t);
-int vfs_setxattr(struct dentry *, char *, void *, size_t, int);
-int vfs_removexattr(struct dentry *, char *);
+int vfs_setxattr(struct dentry *, char *, void *, size_t, int, struct vfsmount *);
+int vfs_removexattr(struct dentry *, char *, struct vfsmount *);
 
 ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
 ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
diff -ruN linux-2.6.16-openvz-026.009/mm/filemap.c /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/mm/filemap.c
--- linux-2.6.16-openvz-026.009/mm/filemap.c	2006-04-27 20:37:06.000000000 +0200
+++ /home/griffon26/test/linux/linux-2.6.16-openvz-026.009/mm/filemap.c	2006-05-08 23:43:24.189272250 +0200
@@ -29,6 +29,7 @@
 #include <linux/blkdev.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
+#include <linux/mount.h>
 #include "filemap.h"
 /*
  * FIXME: remove all knowledge of the buffer layer from the core VM
@@ -1804,6 +1805,8 @@
                 return -EINVAL;
 
 	if (!isblk) {
+		if (MNT_IS_RDONLY(file->f_vfsmnt))
+			return -EROFS;
 		/* FIXME: this is for backwards compatibility with 2.4 */
 		if (file->f_flags & O_APPEND)
                         *pos = i_size_read(inode);
