2006-01-21 08:38:45

by Herbert Poetzl

[permalink] [raw]
Subject: [PATCH 0/6] vfs: extend loopback (bind) mounts by mnt_flags


The following set of patches extends the per device
'noatime', 'nodiratime' and last but not least the
'ro' (read only) mount option to the vfs --bind mounts,
allowing them to behave like any other mount, by
honoring those mount flags (which are silently ignored
by the current implementation in 2.4.x and 2.6.x)

the patch makes the following syscall variations behave
as expected:

- open (read/write/trunc), create
- link, symlink, unlink
- mknod (reg/block/char/fifo)
- mkfifo, mkdir, rmdir, rename
- (f,l)chown, (f)chmod, utime
- access, truncate, mmap
- ioctl (gen/ext2/ext3/reiser)
- (f,l)setxattr, (f,l)removexattr

an older version of this patch was included in
2.6.0-test6-mm2, and v2.6.4-wolk2.0, the patches are
in use by several people, without any issues ...

please consider inclusion (in -mm ?) and/or let me know
what needs to be changed to get this functionality into
mainline ...

TIA,
Herbert


2006-01-21 08:40:19

by Herbert Poetzl

[permalink] [raw]
Subject: [PATCH 1/6] vfs: add missing MNT_RDONLY and macro to check


;
; Bind Mount Extensions
;
; Copyright (C) 2003-2006 Herbert P?tzl <[email protected]>
;
; the missing MNT_RDONLY mount flag is added together with
; a macro MNT_IS_RDONLY(m) to check it on a vfsmount
;
; the separate flag to string structures in show_vfsmnt are
; combined and adjusted to honor the new flag, which is set
; at do_mount time
;
;
; Changelog:
;
; 0.01 - broken out part from bme0.05
; 0.02 - moved the loopback mounts into separate patch
;

Signed-off-by: Herbert P?tzl <[email protected]>

diff -NurpP --minimal linux-2.6.16-rc1/fs/namespace.c linux-2.6.16-rc1-bme0.06.2-bm0.02/fs/namespace.c
--- linux-2.6.16-rc1/fs/namespace.c 2006-01-18 06:08:30 +0100
+++ linux-2.6.16-rc1-bme0.06.2-bm0.02/fs/namespace.c 2006-01-21 09:08:20 +0100
@@ -354,37 +354,40 @@ 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" },
- { 0, 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 }
+ { 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 },
+ { 0, 0, NULL, 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;

mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none");
seq_putc(m, ' ');
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);
@@ -1285,6 +1288,8 @@ long do_mount(char *dev_name, char *dir_
((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)
diff -NurpP --minimal linux-2.6.16-rc1/include/linux/fs.h linux-2.6.16-rc1-bme0.06.2-bm0.02/include/linux/fs.h
--- linux-2.6.16-rc1/include/linux/fs.h 2006-01-18 06:08:43 +0100
+++ linux-2.6.16-rc1-bme0.06.2-bm0.02/include/linux/fs.h 2006-01-21 09:08:20 +0100
@@ -150,7 +150,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) || \
diff -NurpP --minimal linux-2.6.16-rc1/include/linux/mount.h linux-2.6.16-rc1-bme0.06.2-bm0.02/include/linux/mount.h
--- linux-2.6.16-rc1/include/linux/mount.h 2006-01-18 06:08:43 +0100
+++ linux-2.6.16-rc1-bme0.06.2-bm0.02/include/linux/mount.h 2006-01-21 09:08:20 +0100
@@ -22,6 +22,9 @@
#define MNT_NOEXEC 0x04
#define MNT_NOATIME 0x08
#define MNT_NODIRATIME 0x10
+#define MNT_RDONLY 0x20
+
+#define MNT_IS_RDONLY(m) ((m) && ((m)->mnt_flags & MNT_RDONLY))

#define MNT_SHARED 0x1000 /* if the vfsmount is a shared mount */
#define MNT_UNBINDABLE 0x2000 /* if the vfsmount is a unbindable mount */

2006-01-21 08:40:57

by Herbert Poetzl

[permalink] [raw]
Subject: [PATCH 2/6] vfs: propagate mnt_flags into do_loopback/vfsmount


;
; Bind Mount Extensions
;
; Copyright (C) 2003-2006 Herbert P?tzl <[email protected]>
;
; the mnt_flags are propagated into do_loopback(), so that
; they can be stored with the vfsmount
;
;
; Changelog:
;
; 0.01 - broken out from bm0.01
;

Signed-off-by: Herbert P?tzl <[email protected]>

diff -NurpP --minimal linux-2.6.16-rc1/fs/namespace.c linux-2.6.16-rc1-bme0.06.2-lo0.01/fs/namespace.c
--- linux-2.6.16-rc1/fs/namespace.c 2006-01-18 06:08:30 +0100
+++ linux-2.6.16-rc1-bme0.06.2-lo0.01/fs/namespace.c 2006-01-21 09:08:29 +0100
@@ -861,11 +861,13 @@ static int do_change_type(struct nameida
/*
* 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)
@@ -899,6 +901,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);
@@ -1312,7 +1315,7 @@ long do_mount(char *dev_name, char *dir_
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)

2006-01-21 08:41:29

by Herbert Poetzl

[permalink] [raw]
Subject: [PATCH 3/6] vfs: propagate vfsmount into chown_common()


;
; Bind Mount Extensions
;
; Copyright (C) 2003-2006 Herbert P?tzl <[email protected]>
;
; the vfsmount is propagated into chown_common() to allow
; for vfsmount based checks there, in this case the
; MNT_IS_RDONLY() check to disallow changes
;
;
; Changelog:
;
; 0.01 - broken out from bme0.05
;

Signed-off-by: Herbert P?tzl <[email protected]>

diff -NurpP --minimal linux-2.6.16-rc1/fs/open.c linux-2.6.16-rc1-bme0.06.2-cc0.01/fs/open.c
--- linux-2.6.16-rc1/fs/open.c 2006-01-18 06:08:34 +0100
+++ linux-2.6.16-rc1-bme0.06.2-cc0.01/fs/open.c 2006-01-21 09:08:38 +0100
@@ -669,7 +669,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;
@@ -681,7 +682,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))
@@ -711,7 +712,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;
@@ -724,7 +725,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;
@@ -738,7 +739,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;

2006-01-21 08:42:15

by Herbert Poetzl

[permalink] [raw]
Subject: [PATCH 4/6] vfs: propagate the nameidata into the relevant vfs_*()


;
; Bind Mount Extensions
;
; Copyright (C) 2003-2006 Herbert P?tzl <[email protected]>
;
; propagate the nameidata into the relevant vfs_*() functions
; similar to the existing vfs_create() to allow for proper
; checks via may_create(), may_delete() and permission()
;
;
; Changelog:
;
; 0.01 - initial version
;

Signed-off-by: Herbert P?tzl <[email protected]>

diff -NurpP --minimal linux-2.6.16-rc1/fs/namei.c linux-2.6.16-rc1-bme0.06.2-nd0.01/fs/namei.c
--- linux-2.6.16-rc1/fs/namei.c 2006-01-18 06:08:30 +0100
+++ linux-2.6.16-rc1-bme0.06.2-nd0.01/fs/namei.c 2006-01-21 09:08:56 +0100
@@ -1294,7 +1294,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 int may_delete(struct inode *dir,struct dentry *victim,int isdir)
+static int may_delete(struct inode *dir, struct dentry *victim,
+ int isdir, struct nameidata *nd)
{
int error;

@@ -1303,7 +1304,7 @@ static int may_delete(struct inode *dir,

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))
@@ -1720,9 +1721,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;
@@ -1771,11 +1773,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;
@@ -1793,9 +1796,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;
@@ -1834,7 +1838,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);
}
mutex_unlock(&nd.dentry->d_inode->i_mutex);
@@ -1874,9 +1879,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;
@@ -1937,7 +1943,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);
}
mutex_unlock(&nd.dentry->d_inode->i_mutex);
@@ -1948,9 +1954,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;
@@ -2012,7 +2019,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);
}
@@ -2031,9 +2038,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;
@@ -2073,7 +2081,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);
}
mutex_unlock(&nd.dentry->d_inode->i_mutex);
@@ -2085,7 +2094,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;
@@ -2093,7 +2103,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;

@@ -2155,7 +2165,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);
}
mutex_unlock(&nd.dentry->d_inode->i_mutex);
@@ -2282,14 +2293,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;

diff -NurpP --minimal linux-2.6.16-rc1/fs/nfsd/vfs.c linux-2.6.16-rc1-bme0.06.2-nd0.01/fs/nfsd/vfs.c
--- linux-2.6.16-rc1/fs/nfsd/vfs.c 2006-01-18 06:08:34 +0100
+++ linux-2.6.16-rc1-bme0.06.2-nd0.01/fs/nfsd/vfs.c 2006-01-21 09:08:56 +0100
@@ -1159,13 +1159,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);
@@ -1441,11 +1441,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))
@@ -1503,7 +1505,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);
@@ -1664,9 +1666,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);
diff -NurpP --minimal linux-2.6.16-rc1/fs/reiserfs/xattr.c linux-2.6.16-rc1-bme0.06.2-nd0.01/fs/reiserfs/xattr.c
--- linux-2.6.16-rc1/fs/reiserfs/xattr.c 2006-01-18 06:08:34 +0100
+++ linux-2.6.16-rc1-bme0.06.2-nd0.01/fs/reiserfs/xattr.c 2006-01-21 09:08:56 +0100
@@ -35,6 +35,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>
@@ -827,7 +828,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 {
diff -NurpP --minimal linux-2.6.16-rc1/include/linux/fs.h linux-2.6.16-rc1-bme0.06.2-nd0.01/include/linux/fs.h
--- linux-2.6.16-rc1/include/linux/fs.h 2006-01-18 06:08:43 +0100
+++ linux-2.6.16-rc1-bme0.06.2-nd0.01/include/linux/fs.h 2006-01-21 09:08:56 +0100
@@ -901,12 +901,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 *);

/*
diff -NurpP --minimal linux-2.6.16-rc1/ipc/mqueue.c linux-2.6.16-rc1-bme0.06.2-nd0.01/ipc/mqueue.c
--- linux-2.6.16-rc1/ipc/mqueue.c 2006-01-18 06:08:45 +0100
+++ linux-2.6.16-rc1-bme0.06.2-nd0.01/ipc/mqueue.c 2006-01-21 09:08:59 +0100
@@ -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);

diff -NurpP --minimal linux-2.6.16-rc1/net/unix/af_unix.c linux-2.6.16-rc1-bme0.06.2-nd0.01/net/unix/af_unix.c
--- linux-2.6.16-rc1/net/unix/af_unix.c 2006-01-18 06:08:56 +0100
+++ linux-2.6.16-rc1-bme0.06.2-nd0.01/net/unix/af_unix.c 2006-01-21 09:09:04 +0100
@@ -781,7 +781,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;
mutex_unlock(&nd.dentry->d_inode->i_mutex);

2006-01-21 08:43:04

by Herbert Poetzl

[permalink] [raw]
Subject: [PATCH 5/6] vfs: propagate the vfsmount into *xattr()


;
; Bind Mount Extensions
;
; Copyright (C) 2003-2006 Herbert P?tzl <[email protected]>
;
; propagate the vfsmount into both setxattr() and removexattr()
; to allow for vfsmount based checks there ensuring that
; the vfsmount isn't read-only
;
;
; Changelog:
;
; 0.01 - broken out part from bme0.05
;

Signed-off-by: Herbert P?tzl <[email protected]>

diff -NurpP --minimal linux-2.6.16-rc1/fs/xattr.c linux-2.6.16-rc1-bme0.06.2-xa0.01/fs/xattr.c
--- linux-2.6.16-rc1/fs/xattr.c 2006-01-18 06:08:35 +0100
+++ linux-2.6.16-rc1-bme0.06.2-xa0.01/fs/xattr.c 2006-01-21 09:09:20 +0100
@@ -17,6 +17,7 @@
#include <linux/syscalls.h>
#include <linux/module.h>
#include <linux/fsnotify.h>
+#include <linux/mount.h>
#include <asm/uaccess.h>


@@ -167,7 +168,7 @@ EXPORT_SYMBOL_GPL(vfs_removexattr);
*/
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,6 +195,9 @@ setxattr(struct dentry *d, char __user *
}
}

+ if (MNT_IS_RDONLY(mnt))
+ return -EROFS;
+
error = vfs_setxattr(d, kname, kvalue, size, flags);
kfree(kvalue);
return error;
@@ -209,7 +213,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;
}
@@ -224,7 +228,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;
}
@@ -239,7 +243,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;
}
@@ -412,7 +416,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];
@@ -423,6 +427,9 @@ removexattr(struct dentry *d, char __use
if (error < 0)
return error;

+ if (MNT_IS_RDONLY(mnt))
+ return -EROFS;
+
return vfs_removexattr(d, kname);
}

@@ -435,7 +442,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;
}
@@ -449,7 +456,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;
}
@@ -463,7 +470,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;
}

2006-01-21 08:43:40

by Herbert Poetzl

[permalink] [raw]
Subject: [PATCH 6/6] vfs: extend IS_RDONLY() checks to MNT_IS_RDONLY()


;
; Bind Mount Extensions
;
; Copyright (C) 2003-2006 Herbert P?tzl <[email protected]>
;
; wherever checks for IS_RDONLY(inode) happen, this adds
; the proper MNT_IS_RDONLY(mnt) checks to ensure that the
; vfsmount isn't read-only
;
;
; Changelog:
;
; 0.01 - broken out part from bme0.05
; 0.02 - removed redundant checks
;

Signed-off-by: Herbert P?tzl <[email protected]>

diff -NurpP --minimal linux-2.6.16-rc1/arch/sparc64/solaris/fs.c linux-2.6.16-rc1-bme0.06.2-ro0.02/arch/sparc64/solaris/fs.c
--- linux-2.6.16-rc1/arch/sparc64/solaris/fs.c 2006-01-18 06:07:57 +0100
+++ linux-2.6.16-rc1-bme0.06.2-ro0.02/arch/sparc64/solaris/fs.c 2006-01-21 09:09:32 +0100
@@ -363,7 +363,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;
@@ -399,7 +399,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;
diff -NurpP --minimal linux-2.6.16-rc1/fs/ext2/ioctl.c linux-2.6.16-rc1-bme0.06.2-ro0.02/fs/ext2/ioctl.c
--- linux-2.6.16-rc1/fs/ext2/ioctl.c 2006-01-18 06:08:29 +0100
+++ linux-2.6.16-rc1-bme0.06.2-ro0.02/fs/ext2/ioctl.c 2006-01-21 09:09:32 +0100
@@ -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 @@ 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))
@@ -69,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;
diff -NurpP --minimal linux-2.6.16-rc1/fs/ext3/ioctl.c linux-2.6.16-rc1-bme0.06.2-ro0.02/fs/ext3/ioctl.c
--- linux-2.6.16-rc1/fs/ext3/ioctl.c 2006-01-18 06:08:29 +0100
+++ linux-2.6.16-rc1-bme0.06.2-ro0.02/fs/ext3/ioctl.c 2006-01-21 09:09:32 +0100
@@ -8,6 +8,7 @@
*/

#include <linux/fs.h>
+#include <linux/mount.h>
#include <linux/jbd.h>
#include <linux/capability.h>
#include <linux/ext3_fs.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))
@@ -112,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;
@@ -166,7 +169,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))
@@ -201,7 +205,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))
@@ -222,7 +227,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,
diff -NurpP --minimal linux-2.6.16-rc1/fs/hfsplus/ioctl.c linux-2.6.16-rc1-bme0.06.2-ro0.02/fs/hfsplus/ioctl.c
--- linux-2.6.16-rc1/fs/hfsplus/ioctl.c 2006-01-18 06:08:30 +0100
+++ linux-2.6.16-rc1-bme0.06.2-ro0.02/fs/hfsplus/ioctl.c 2006-01-21 09:09:32 +0100
@@ -35,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))
diff -NurpP --minimal linux-2.6.16-rc1/fs/namei.c linux-2.6.16-rc1-bme0.06.2-ro0.02/fs/namei.c
--- linux-2.6.16-rc1/fs/namei.c 2006-01-18 06:08:30 +0100
+++ linux-2.6.16-rc1-bme0.06.2-ro0.02/fs/namei.c 2006-01-21 09:09:32 +0100
@@ -233,7 +233,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;

@@ -1456,7 +1456,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.
@@ -2366,6 +2367,9 @@ static int do_rename(const char * oldnam
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 -NurpP --minimal linux-2.6.16-rc1/fs/nfs/dir.c linux-2.6.16-rc1-bme0.06.2-ro0.02/fs/nfs/dir.c
--- linux-2.6.16-rc1/fs/nfs/dir.c 2006-01-18 06:08:30 +0100
+++ linux-2.6.16-rc1-bme0.06.2-ro0.02/fs/nfs/dir.c 2006-01-21 09:09:32 +0100
@@ -902,7 +902,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;
}
diff -NurpP --minimal linux-2.6.16-rc1/fs/nfsd/vfs.c linux-2.6.16-rc1-bme0.06.2-ro0.02/fs/nfsd/vfs.c
--- linux-2.6.16-rc1/fs/nfsd/vfs.c 2006-01-18 06:08:34 +0100
+++ linux-2.6.16-rc1-bme0.06.2-ro0.02/fs/nfsd/vfs.c 2006-01-21 09:09:32 +0100
@@ -1778,7 +1778,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;
diff -NurpP --minimal linux-2.6.16-rc1/fs/open.c linux-2.6.16-rc1-bme0.06.2-ro0.02/fs/open.c
--- linux-2.6.16-rc1/fs/open.c 2006-01-18 06:08:34 +0100
+++ linux-2.6.16-rc1-bme0.06.2-ro0.02/fs/open.c 2006-01-21 09:09:32 +0100
@@ -247,7 +247,7 @@ static long do_sys_truncate(const char _
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;
@@ -371,7 +371,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() */
@@ -428,7 +428,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() */
@@ -510,7 +510,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);
@@ -616,7 +617,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))
@@ -648,7 +649,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;
diff -NurpP --minimal linux-2.6.16-rc1/fs/reiserfs/ioctl.c linux-2.6.16-rc1-bme0.06.2-ro0.02/fs/reiserfs/ioctl.c
--- linux-2.6.16-rc1/fs/reiserfs/ioctl.c 2006-01-18 06:08:34 +0100
+++ linux-2.6.16-rc1-bme0.06.2-ro0.02/fs/reiserfs/ioctl.c 2006-01-21 09:09:32 +0100
@@ -4,6 +4,7 @@

#include <linux/capability.h>
#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)
@@ -82,7 +84,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;
diff -NurpP --minimal linux-2.6.16-rc1/fs/reiserfs/xattr.c linux-2.6.16-rc1-bme0.06.2-ro0.02/fs/reiserfs/xattr.c
--- linux-2.6.16-rc1/fs/reiserfs/xattr.c 2006-01-18 06:08:34 +0100
+++ linux-2.6.16-rc1-bme0.06.2-ro0.02/fs/reiserfs/xattr.c 2006-01-21 09:09:32 +0100
@@ -1332,7 +1332,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;


2006-01-22 10:06:19

by Suleiman Souhlal

[permalink] [raw]
Subject: Re: [PATCH 2/6] vfs: propagate mnt_flags into do_loopback/vfsmount

Herbert Poetzl wrote:
> @@ -1312,7 +1315,7 @@ long do_mount(char *dev_name, char *dir_
> 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);

Shouldn't it be retval = do_loopback(&nd, dev_name, recurse, mnt_flags); ?

-- Suleiman

2006-01-22 10:59:27

by Suleiman Souhlal

[permalink] [raw]
Subject: Re: [PATCH 2/6] vfs: propagate mnt_flags into do_loopback/vfsmount

Suleiman Souhlal wrote:
> Shouldn't it be retval = do_loopback(&nd, dev_name, recurse, mnt_flags); ?

Nevermind.
-- Suleiman

2006-01-24 19:02:58

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 2/6] vfs: propagate mnt_flags into do_loopback/vfsmount

This one looks good, it's an obvious fix. But please follow the proper
patch format, see http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt
for details.

2006-01-24 19:06:35

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 0/6] vfs: extend loopback (bind) mounts by mnt_flags

On Sat, Jan 21, 2006 at 09:38:43AM +0100, Herbert Poetzl wrote:
>
> The following set of patches extends the per device
> 'noatime', 'nodiratime' and last but not least the
> 'ro' (read only) mount option to the vfs --bind mounts,
> allowing them to behave like any other mount, by
> honoring those mount flags (which are silently ignored
> by the current implementation in 2.4.x and 2.6.x)
>
> the patch makes the following syscall variations behave
> as expected:
>
> - open (read/write/trunc), create
> - link, symlink, unlink
> - mknod (reg/block/char/fifo)
> - mkfifo, mkdir, rmdir, rename
> - (f,l)chown, (f)chmod, utime
> - access, truncate, mmap
> - ioctl (gen/ext2/ext3/reiser)
> - (f,l)setxattr, (f,l)removexattr
>
> an older version of this patch was included in
> 2.6.0-test6-mm2, and v2.6.4-wolk2.0, the patches are
> in use by several people, without any issues ...
>
> please consider inclusion (in -mm ?) and/or let me know
> what needs to be changed to get this functionality into
> mainline ...

Please see the original mail from Al on this subject. We need to
split the "am I allowed to write to the fs" part out of permission().
Once we're at it we can pair it with the "don't need to write to fs anymore"
even and get saner unmount/remount semantics.

To get there we will still need the vfsmount propagatios, so these should
come first in the series. Then the get/release write access helpers and
last the actual per-mount ro bit. Your mnt_flags propagation fix is fine
on it's own and should go in asap.

And please send the patches to -fsdevel and in the proper patch format.
I have planned to look at this again in February, tell me if you want to
finish it before or at the same time, then I won't spend time on it.

2006-01-26 21:04:55

by Herbert Poetzl

[permalink] [raw]
Subject: Re: [PATCH 2/6] vfs: propagate mnt_flags into do_loopback/vfsmount

On Tue, Jan 24, 2006 at 07:02:56PM +0000, Christoph Hellwig wrote:
> This one looks good, it's an obvious fix. But please follow the proper
> patch format, see http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt
> for details.

huh? please help me figure out what's wrong this time ...

TIA,
Herbert

>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/

2006-01-26 21:08:55

by Herbert Poetzl

[permalink] [raw]
Subject: Re: [PATCH 0/6] vfs: extend loopback (bind) mounts by mnt_flags

On Tue, Jan 24, 2006 at 07:06:32PM +0000, Christoph Hellwig wrote:
> On Sat, Jan 21, 2006 at 09:38:43AM +0100, Herbert Poetzl wrote:
> >
> > The following set of patches extends the per device
> > 'noatime', 'nodiratime' and last but not least the
> > 'ro' (read only) mount option to the vfs --bind mounts,
> > allowing them to behave like any other mount, by
> > honoring those mount flags (which are silently ignored
> > by the current implementation in 2.4.x and 2.6.x)
> >
> > the patch makes the following syscall variations behave
> > as expected:
> >
> > - open (read/write/trunc), create
> > - link, symlink, unlink
> > - mknod (reg/block/char/fifo)
> > - mkfifo, mkdir, rmdir, rename
> > - (f,l)chown, (f)chmod, utime
> > - access, truncate, mmap
> > - ioctl (gen/ext2/ext3/reiser)
> > - (f,l)setxattr, (f,l)removexattr
> >
> > an older version of this patch was included in
> > 2.6.0-test6-mm2, and v2.6.4-wolk2.0, the patches are
> > in use by several people, without any issues ...
> >
> > please consider inclusion (in -mm ?) and/or let me know
> > what needs to be changed to get this functionality into
> > mainline ...
>
> Please see the original mail from Al on this subject. We need to
> split the "am I allowed to write to the fs" part out of permission().
> Once we're at it we can pair it with the "don't need to write to fs
> anymore" even and get saner unmount/remount semantics.

could you point me to this thread/email, so that I can
(re)read it?

> To get there we will still need the vfsmount propagatios, so these
> should come first in the series. Then the get/release write access
> helpers and last the actual per-mount ro bit. Your mnt_flags
> propagation fix is fine on it's own and should go in asap.
>
> And please send the patches to -fsdevel and in the proper patch

will do so, once I figure out what was improper ...
(as I tried to follow Andrew's tpp document in the first palce)

> format. I have planned to look at this again in February, tell me if
> you want to finish it before or at the same time, then I won't spend
> time on it.

once I figured out what is desired/wanted/acceptable, I'm
willing to do it ...

best,
Herbert

> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/

2006-01-27 20:03:06

by Herbert Poetzl

[permalink] [raw]
Subject: Re: [PATCH 2/6] vfs: propagate mnt_flags into do_loopback/vfsmount


the mnt_flags are propagated into do_loopback(), so that
they can be stored with the vfsmount

Signed-off-by: Herbert P?tzl <[email protected]>
Acked-by: Christoph Hellwig <[email protected]>
---
; Bind Mount Extensions
; 02_2.6.16-rc1_lo0.01.diff

diff -NurpP --minimal linux-2.6.16-rc1/fs/namespace.c linux-2.6.16-rc1-bme0.06.2-lo0.01/fs/namespace.c
--- linux-2.6.16-rc1/fs/namespace.c 2006-01-18 06:08:30 +0100
+++ linux-2.6.16-rc1-bme0.06.2-lo0.01/fs/namespace.c 2006-01-21 09:08:29 +0100
@@ -861,11 +861,13 @@ static int do_change_type(struct nameida
/*
* 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)
@@ -899,6 +901,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);
@@ -1312,7 +1315,7 @@ long do_mount(char *dev_name, char *dir_
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)