;
; Bind Mount Extensions
;
; this patch adds some functionality to the --bind
; type of vfs mounts.
;
; (C) 2003-2004 Herbert P?tzl <[email protected]>
;
; Changelog:
;
; 0.01 - readonly bind mounts
; 0.02 - added ro truncate handling
; - added ro (f)chown, (f)chmod handling
; 0.03 - added ro utime(s) handling
; - added ro access and *_ioctl
; 0.04 - added noatime and nodiratime
; - made autofs4 update_atime uncond
;
; this patch is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version 2
; of the License, or (at your option) any later version.
;
; this patch is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
diff -NurpP --minimal linux-2.6.4/drivers/char/random.c linux-2.6.4-bme0.04/drivers/char/random.c
--- linux-2.6.4/drivers/char/random.c 2004-03-11 03:55:22.000000000 +0100
+++ linux-2.6.4-bme0.04/drivers/char/random.c 2004-03-12 20:51:58.000000000 +0100
@@ -1641,7 +1641,7 @@ random_read(struct file * file, char * b
* If we gave the user some bytes, update the access time.
*/
if (count != 0) {
- update_atime(file->f_dentry->d_inode);
+ update_atime(file->f_dentry->d_inode, file->f_vfsmnt);
}
return (count ? count : retval);
diff -NurpP --minimal linux-2.6.4/fs/autofs4/root.c linux-2.6.4-bme0.04/fs/autofs4/root.c
--- linux-2.6.4/fs/autofs4/root.c 2004-03-11 03:55:21.000000000 +0100
+++ linux-2.6.4-bme0.04/fs/autofs4/root.c 2004-03-12 20:51:58.000000000 +0100
@@ -61,7 +61,8 @@ static void autofs4_update_usage(struct
struct autofs_info *ino = autofs4_dentry_ino(dentry);
if (ino) {
- update_atime(dentry->d_inode);
+ /* Al Viro said: unconditional */
+ update_atime(dentry->d_inode, 0);
ino->last_used = jiffies;
}
}
diff -NurpP --minimal linux-2.6.4/fs/bfs/dir.c linux-2.6.4-bme0.04/fs/bfs/dir.c
--- linux-2.6.4/fs/bfs/dir.c 2004-03-11 03:55:44.000000000 +0100
+++ linux-2.6.4-bme0.04/fs/bfs/dir.c 2004-03-12 20:51:58.000000000 +0100
@@ -65,7 +65,7 @@ static int bfs_readdir(struct file * f,
brelse(bh);
}
- update_atime(dir);
+ update_atime(dir, f->f_vfsmnt);
unlock_kernel();
return 0;
}
diff -NurpP --minimal linux-2.6.4/fs/ext2/dir.c linux-2.6.4-bme0.04/fs/ext2/dir.c
--- linux-2.6.4/fs/ext2/dir.c 2004-03-11 03:55:28.000000000 +0100
+++ linux-2.6.4-bme0.04/fs/ext2/dir.c 2004-03-12 20:51:58.000000000 +0100
@@ -310,7 +310,7 @@ ext2_readdir (struct file * filp, void *
done:
filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
filp->f_version = inode->i_version;
- update_atime(inode);
+ update_atime(inode, filp->f_vfsmnt);
return 0;
}
diff -NurpP --minimal linux-2.6.4/fs/ext2/ioctl.c linux-2.6.4-bme0.04/fs/ext2/ioctl.c
--- linux-2.6.4/fs/ext2/ioctl.c 2004-03-11 03:55:54.000000000 +0100
+++ linux-2.6.4-bme0.04/fs/ext2/ioctl.c 2004-03-12 20:51:58.000000000 +0100
@@ -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,7 @@ int ext2_ioctl (struct inode * inode, st
case EXT2_IOC_SETFLAGS: {
unsigned int oldflags;
- if (IS_RDONLY(inode))
+ if (IS_RDONLY(inode) || MNT_IS_RDONLY(filp->f_vfsmnt))
return -EROFS;
if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
@@ -68,7 +69,7 @@ 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) || MNT_IS_RDONLY(filp->f_vfsmnt))
return -EROFS;
if (get_user(inode->i_generation, (int *) arg))
return -EFAULT;
diff -NurpP --minimal linux-2.6.4/fs/ext3/dir.c linux-2.6.4-bme0.04/fs/ext3/dir.c
--- linux-2.6.4/fs/ext3/dir.c 2004-03-11 03:55:28.000000000 +0100
+++ linux-2.6.4-bme0.04/fs/ext3/dir.c 2004-03-12 20:51:58.000000000 +0100
@@ -224,7 +224,7 @@ revalidate:
offset = 0;
brelse (bh);
}
- update_atime(inode);
+ update_atime(inode, filp->f_vfsmnt);
out:
return ret;
}
@@ -506,7 +506,7 @@ static int ext3_dx_readdir(struct file *
}
finished:
info->last_pos = filp->f_pos;
- update_atime(inode);
+ update_atime(inode, filp->f_vfsmnt);
return 0;
}
diff -NurpP --minimal linux-2.6.4/fs/ext3/ioctl.c linux-2.6.4-bme0.04/fs/ext3/ioctl.c
--- linux-2.6.4/fs/ext3/ioctl.c 2004-03-11 03:55:26.000000000 +0100
+++ linux-2.6.4-bme0.04/fs/ext3/ioctl.c 2004-03-12 20:51:58.000000000 +0100
@@ -12,6 +12,7 @@
#include <linux/ext3_fs.h>
#include <linux/ext3_jbd.h>
#include <linux/time.h>
+#include <linux/mount.h>
#include <asm/uaccess.h>
@@ -34,7 +35,7 @@ int ext3_ioctl (struct inode * inode, st
unsigned int oldflags;
unsigned int jflag;
- if (IS_RDONLY(inode))
+ if (IS_RDONLY(inode) || MNT_IS_RDONLY(filp->f_vfsmnt))
return -EROFS;
if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
@@ -110,7 +111,7 @@ flags_err:
if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
return -EPERM;
- if (IS_RDONLY(inode))
+ if (IS_RDONLY(inode) || MNT_IS_RDONLY(filp->f_vfsmnt))
return -EROFS;
if (get_user(generation, (int *) arg))
return -EFAULT;
diff -NurpP --minimal linux-2.6.4/fs/hugetlbfs/inode.c linux-2.6.4-bme0.04/fs/hugetlbfs/inode.c
--- linux-2.6.4/fs/hugetlbfs/inode.c 2004-03-11 03:55:44.000000000 +0100
+++ linux-2.6.4-bme0.04/fs/hugetlbfs/inode.c 2004-03-12 20:51:58.000000000 +0100
@@ -62,7 +62,7 @@ static int hugetlbfs_file_mmap(struct fi
vma_len = (loff_t)(vma->vm_end - vma->vm_start);
down(&inode->i_sem);
- update_atime(inode);
+ update_atime(inode, file->f_vfsmnt);
vma->vm_flags |= VM_HUGETLB | VM_RESERVED;
vma->vm_ops = &hugetlb_vm_ops;
ret = hugetlb_prefault(mapping, vma);
diff -NurpP --minimal linux-2.6.4/fs/inode.c linux-2.6.4-bme0.04/fs/inode.c
--- linux-2.6.4/fs/inode.c 2004-03-11 03:55:51.000000000 +0100
+++ linux-2.6.4-bme0.04/fs/inode.c 2004-03-12 20:51:58.000000000 +0100
@@ -20,6 +20,7 @@
#include <linux/security.h>
#include <linux/pagemap.h>
#include <linux/cdev.h>
+#include <linux/mount.h>
/*
* This is needed for the following functions:
@@ -1141,15 +1142,16 @@ static int inode_times_differ(struct ino
* This function automatically handles read only file systems and media,
* as well as the "noatime" flag and inode specific "noatime" markers.
*/
-void update_atime(struct inode *inode)
+void update_atime(struct inode *inode, struct vfsmount *mnt)
{
struct timespec now;
- if (IS_NOATIME(inode))
+ if (IS_NOATIME(inode) || MNT_IS_NOATIME(mnt))
return;
- if (IS_NODIRATIME(inode) && S_ISDIR(inode->i_mode))
+ if (S_ISDIR(inode->i_mode) &&
+ (IS_NODIRATIME(inode) || MNT_IS_NODIRATIME(mnt)))
return;
- if (IS_RDONLY(inode))
+ if (IS_RDONLY(inode) || MNT_IS_RDONLY(mnt))
return;
now = current_kernel_time();
diff -NurpP --minimal linux-2.6.4/fs/libfs.c linux-2.6.4-bme0.04/fs/libfs.c
--- linux-2.6.4/fs/libfs.c 2004-03-11 03:55:21.000000000 +0100
+++ linux-2.6.4-bme0.04/fs/libfs.c 2004-03-12 20:51:58.000000000 +0100
@@ -155,7 +155,7 @@ int dcache_readdir(struct file * filp, v
}
spin_unlock(&dcache_lock);
}
- update_atime(dentry->d_inode);
+ update_atime(dentry->d_inode, filp->f_vfsmnt);
return 0;
}
diff -NurpP --minimal linux-2.6.4/fs/minix/dir.c linux-2.6.4-bme0.04/fs/minix/dir.c
--- linux-2.6.4/fs/minix/dir.c 2004-03-11 03:55:37.000000000 +0100
+++ linux-2.6.4-bme0.04/fs/minix/dir.c 2004-03-12 20:51:58.000000000 +0100
@@ -127,7 +127,7 @@ static int minix_readdir(struct file * f
done:
filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
- update_atime(inode);
+ update_atime(inode, filp->f_vfsmnt);
unlock_kernel();
return 0;
}
diff -NurpP --minimal linux-2.6.4/fs/namei.c linux-2.6.4-bme0.04/fs/namei.c
--- linux-2.6.4/fs/namei.c 2004-03-11 03:55:25.000000000 +0100
+++ linux-2.6.4-bme0.04/fs/namei.c 2004-03-12 20:51:58.000000000 +0100
@@ -209,10 +209,14 @@ int permission(struct inode * inode,int
{
int retval;
int submask;
+ umode_t mode = inode->i_mode;
/* Ordinary permission routines do not understand MAY_APPEND. */
submask = mask & ~MAY_APPEND;
+ if (nd && (mask & MAY_WRITE) && MNT_IS_RDONLY(nd->mnt) &&
+ (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
+ return -EROFS;
if (inode->i_op && inode->i_op->permission)
retval = inode->i_op->permission(inode, submask, nd);
else
@@ -412,7 +416,7 @@ static inline int do_follow_link(struct
goto loop;
current->link_count++;
current->total_link_count++;
- update_atime(dentry->d_inode);
+ update_atime(dentry->d_inode, nd->mnt);
err = dentry->d_inode->i_op->follow_link(dentry, nd);
current->link_count--;
return err;
@@ -1062,6 +1066,24 @@ static inline int may_create(struct inod
return permission(dir,MAY_WRITE | MAY_EXEC, nd);
}
+static inline int mnt_may_create(struct vfsmount *mnt, struct inode *dir, struct dentry *child) {
+ if (child->d_inode)
+ return -EEXIST;
+ if (IS_DEADDIR(dir))
+ return -ENOENT;
+ if (mnt->mnt_flags & MNT_RDONLY)
+ return -EROFS;
+ return 0;
+}
+
+static inline int mnt_may_unlink(struct vfsmount *mnt, struct inode *dir, struct dentry *child) {
+ if (!child->d_inode)
+ return -ENOENT;
+ if (mnt->mnt_flags & MNT_RDONLY)
+ return -EROFS;
+ return 0;
+}
+
/*
* Special case: O_CREAT|O_EXCL implies O_NOFOLLOW for security
* reasons.
@@ -1183,7 +1205,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.
@@ -1368,7 +1391,7 @@ do_link:
error = security_inode_follow_link(dentry, nd);
if (error)
goto exit_dput;
- update_atime(dentry->d_inode);
+ update_atime(dentry->d_inode, nd->mnt);
error = dentry->d_inode->i_op->follow_link(dentry, nd);
dput(dentry);
if (error)
@@ -1408,23 +1431,28 @@ do_link:
struct dentry *lookup_create(struct nameidata *nd, int is_dir)
{
struct dentry *dentry;
+ int error;
down(&nd->dentry->d_inode->i_sem);
- dentry = ERR_PTR(-EEXIST);
+ error = -EEXIST;
if (nd->last_type != LAST_NORM)
- goto fail;
+ goto out;
nd->flags &= ~LOOKUP_PARENT;
dentry = lookup_hash(&nd->last, nd->dentry);
if (IS_ERR(dentry))
+ goto ret;
+ error = mnt_may_create(nd->mnt, nd->dentry->d_inode, dentry);
+ if (error)
goto fail;
+ error = -ENOENT;
if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
- goto enoent;
+ goto fail;
+ret:
return dentry;
-enoent:
- dput(dentry);
- dentry = ERR_PTR(-ENOENT);
fail:
- return dentry;
+ dput(dentry);
+out:
+ return ERR_PTR(error);
}
int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
@@ -1653,7 +1681,11 @@ asmlinkage long sys_rmdir(const char __u
dentry = lookup_hash(&nd.last, nd.dentry);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
+ error = mnt_may_unlink(nd.mnt, nd.dentry->d_inode, dentry);
+ if (error)
+ goto exit2;
error = vfs_rmdir(nd.dentry->d_inode, dentry);
+ exit2:
dput(dentry);
}
up(&nd.dentry->d_inode->i_sem);
@@ -1725,6 +1757,9 @@ asmlinkage long sys_unlink(const char __
/* 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);
@@ -2089,6 +2124,9 @@ static inline int do_rename(const char *
error = -EINVAL;
if (old_dentry == trap)
goto exit4;
+ error = -EROFS;
+ if (MNT_IS_RDONLY(newnd.mnt))
+ goto exit4;
new_dentry = lookup_hash(&newnd.last, new_dir);
error = PTR_ERR(new_dentry);
if (IS_ERR(new_dentry))
diff -NurpP --minimal linux-2.6.4/fs/namespace.c linux-2.6.4-bme0.04/fs/namespace.c
--- linux-2.6.4/fs/namespace.c 2004-03-11 03:55:35.000000000 +0100
+++ linux-2.6.4-bme0.04/fs/namespace.c 2004-03-12 20:51:58.000000000 +0100
@@ -229,7 +229,8 @@ static int show_vfsmnt(struct seq_file *
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");
+ seq_puts(m, (MNT_IS_RDONLY(mnt) ||
+ (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);
@@ -522,11 +523,13 @@ out_unlock:
/*
* do loopback mount.
*/
-static int do_loopback(struct nameidata *nd, char *old_name, int recurse)
+static int do_loopback(struct nameidata *nd, char *old_name, unsigned long flags, int mnt_flags)
{
struct nameidata old_nd;
struct vfsmount *mnt = NULL;
+ int recurse = flags & MS_REC;
int err = mount_is_safe(nd);
+
if (err)
return err;
if (!old_name || !*old_name)
@@ -553,6 +556,7 @@ static int do_loopback(struct nameidata
spin_unlock(&vfsmount_lock);
} else
mntput(mnt);
+ mnt->mnt_flags = mnt_flags;
}
up_write(¤t->namespace->sem);
@@ -759,12 +763,18 @@ long do_mount(char * dev_name, char * di
((char *)data_page)[PAGE_SIZE - 1] = 0;
/* Separate the per-mountpoint flags */
+ if (flags & MS_RDONLY)
+ mnt_flags |= MNT_RDONLY;
if (flags & MS_NOSUID)
mnt_flags |= MNT_NOSUID;
if (flags & MS_NODEV)
mnt_flags |= MNT_NODEV;
if (flags & MS_NOEXEC)
mnt_flags |= MNT_NOEXEC;
+ if (flags & MS_NOATIME)
+ mnt_flags |= MNT_NOATIME;
+ if (flags & MS_NODIRATIME)
+ mnt_flags |= MNT_NODIRATIME;
flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV);
/* ... and get the mountpoint */
@@ -780,7 +790,7 @@ long do_mount(char * dev_name, char * di
retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
data_page);
else if (flags & MS_BIND)
- retval = do_loopback(&nd, dev_name, flags & MS_REC);
+ retval = do_loopback(&nd, dev_name, flags, mnt_flags);
else if (flags & MS_MOVE)
retval = do_move_mount(&nd, dev_name);
else
diff -NurpP --minimal linux-2.6.4/fs/nfsd/vfs.c linux-2.6.4-bme0.04/fs/nfsd/vfs.c
--- linux-2.6.4/fs/nfsd/vfs.c 2004-03-11 03:55:26.000000000 +0100
+++ linux-2.6.4-bme0.04/fs/nfsd/vfs.c 2004-03-12 20:51:58.000000000 +0100
@@ -1143,7 +1143,7 @@ nfsd_readlink(struct svc_rqst *rqstp, st
if (!inode->i_op || !inode->i_op->readlink)
goto out;
- update_atime(inode);
+ update_atime(inode, fhp->fh_export->ex_mnt);
/* N.B. Why does this call need a get_fs()??
* Remove the set_fs and watch the fireworks:-) --okir
*/
diff -NurpP --minimal linux-2.6.4/fs/open.c linux-2.6.4-bme0.04/fs/open.c
--- linux-2.6.4/fs/open.c 2004-03-11 03:55:21.000000000 +0100
+++ linux-2.6.4-bme0.04/fs/open.c 2004-03-12 20:51:58.000000000 +0100
@@ -226,7 +226,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;
@@ -350,7 +350,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() */
@@ -407,7 +407,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() */
@@ -489,8 +489,9 @@ asmlinkage long sys_access(const char __
if (!res) {
res = permission(nd.dentry->d_inode, mode, &nd);
/* SuS v2 requires we report a read only fs too */
- if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
- && !special_file(nd.dentry->d_inode->i_mode))
+ if (!res && (mode & S_IWOTH)
+ && !special_file(nd.dentry->d_inode->i_mode)
+ && (IS_RDONLY(nd.dentry->d_inode) || MNT_IS_RDONLY(nd.mnt)))
res = -EROFS;
path_release(&nd);
}
@@ -595,7 +596,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))
@@ -627,7 +628,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;
@@ -648,7 +649,7 @@ out:
return error;
}
-static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
+static int chown_common(struct vfsmount *mnt, struct dentry * dentry, uid_t user, gid_t group)
{
struct inode * inode;
int error;
@@ -660,7 +661,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))
@@ -690,7 +691,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.mnt, nd.dentry, user, group);
path_release(&nd);
}
return error;
@@ -703,7 +704,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.mnt, nd.dentry, user, group);
path_release(&nd);
}
return error;
@@ -717,7 +718,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_vfsmnt, file->f_dentry, user, group);
fput(file);
}
return error;
diff -NurpP --minimal linux-2.6.4/fs/pipe.c linux-2.6.4-bme0.04/fs/pipe.c
--- linux-2.6.4/fs/pipe.c 2004-03-11 03:55:28.000000000 +0100
+++ linux-2.6.4-bme0.04/fs/pipe.c 2004-03-12 20:51:58.000000000 +0100
@@ -165,7 +165,7 @@ pipe_readv(struct file *filp, const stru
kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
}
if (ret > 0)
- update_atime(inode);
+ update_atime(inode, filp->f_vfsmnt);
return ret;
}
diff -NurpP --minimal linux-2.6.4/fs/qnx4/dir.c linux-2.6.4-bme0.04/fs/qnx4/dir.c
--- linux-2.6.4/fs/qnx4/dir.c 2004-03-11 03:55:35.000000000 +0100
+++ linux-2.6.4-bme0.04/fs/qnx4/dir.c 2004-03-12 20:51:58.000000000 +0100
@@ -76,7 +76,7 @@ static int qnx4_readdir(struct file *fil
}
brelse(bh);
}
- update_atime(inode);
+ update_atime(inode, filp->f_vfsmnt);
out:
unlock_kernel();
diff -NurpP --minimal linux-2.6.4/fs/reiserfs/dir.c linux-2.6.4-bme0.04/fs/reiserfs/dir.c
--- linux-2.6.4/fs/reiserfs/dir.c 2004-03-11 03:55:28.000000000 +0100
+++ linux-2.6.4-bme0.04/fs/reiserfs/dir.c 2004-03-12 20:51:58.000000000 +0100
@@ -186,7 +186,7 @@ static int reiserfs_readdir (struct file
filp->f_pos = next_pos;
pathrelse (&path_to_entry);
reiserfs_check_path(&path_to_entry) ;
- update_atime(inode) ;
+ update_atime(inode, filp->f_vfsmnt) ;
out:
reiserfs_write_unlock(inode->i_sb);
return ret;
diff -NurpP --minimal linux-2.6.4/fs/reiserfs/ioctl.c linux-2.6.4-bme0.04/fs/reiserfs/ioctl.c
--- linux-2.6.4/fs/reiserfs/ioctl.c 2004-03-11 03:55:26.000000000 +0100
+++ linux-2.6.4-bme0.04/fs/reiserfs/ioctl.c 2004-03-12 20:51:58.000000000 +0100
@@ -5,6 +5,7 @@
#include <linux/fs.h>
#include <linux/reiserfs_fs.h>
#include <linux/time.h>
+#include <linux/mount.h>
#include <asm/uaccess.h>
#include <linux/pagemap.h>
#include <linux/smp_lock.h>
@@ -38,7 +39,7 @@ int reiserfs_ioctl (struct inode * inode
i_attrs_to_sd_attrs( inode, ( __u16 * ) &flags );
return put_user(flags, (int *) arg);
case REISERFS_IOC_SETFLAGS: {
- if (IS_RDONLY(inode))
+ if (IS_RDONLY(inode) || MNT_IS_RDONLY(filp->f_vfsmnt))
return -EROFS;
if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
@@ -70,7 +71,7 @@ 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) || MNT_IS_RDONLY(filp->f_vfsmnt))
return -EROFS;
if (get_user(inode->i_generation, (int *) arg))
return -EFAULT;
diff -NurpP --minimal linux-2.6.4/fs/stat.c linux-2.6.4-bme0.04/fs/stat.c
--- linux-2.6.4/fs/stat.c 2004-03-11 03:55:23.000000000 +0100
+++ linux-2.6.4-bme0.04/fs/stat.c 2004-03-12 20:51:58.000000000 +0100
@@ -272,7 +272,7 @@ asmlinkage long sys_readlink(const char
if (inode->i_op && inode->i_op->readlink) {
error = security_inode_readlink(nd.dentry);
if (!error) {
- update_atime(inode);
+ update_atime(inode, nd.mnt);
error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
}
}
diff -NurpP --minimal linux-2.6.4/fs/sysv/dir.c linux-2.6.4-bme0.04/fs/sysv/dir.c
--- linux-2.6.4/fs/sysv/dir.c 2004-03-11 03:55:24.000000000 +0100
+++ linux-2.6.4-bme0.04/fs/sysv/dir.c 2004-03-12 20:51:58.000000000 +0100
@@ -116,7 +116,7 @@ static int sysv_readdir(struct file * fi
done:
filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
- update_atime(inode);
+ update_atime(inode, filp->f_vfsmnt);
unlock_kernel();
return 0;
}
diff -NurpP --minimal linux-2.6.4/fs/udf/dir.c linux-2.6.4-bme0.04/fs/udf/dir.c
--- linux-2.6.4/fs/udf/dir.c 2004-03-11 03:55:24.000000000 +0100
+++ linux-2.6.4-bme0.04/fs/udf/dir.c 2004-03-12 20:51:58.000000000 +0100
@@ -98,7 +98,7 @@ int udf_readdir(struct file *filp, void
}
result = do_udf_readdir(dir, filp, filldir, dirent);
- update_atime(dir);
+ update_atime(dir, filp->f_vfsmnt);
unlock_kernel();
return result;
}
diff -NurpP --minimal linux-2.6.4/fs/ufs/dir.c linux-2.6.4-bme0.04/fs/ufs/dir.c
--- linux-2.6.4/fs/ufs/dir.c 2004-03-11 03:55:43.000000000 +0100
+++ linux-2.6.4-bme0.04/fs/ufs/dir.c 2004-03-12 20:51:58.000000000 +0100
@@ -166,7 +166,7 @@ revalidate:
offset = 0;
brelse (bh);
}
- update_atime(inode);
+ update_atime(inode, filp->f_vfsmnt);
unlock_kernel();
return 0;
}
diff -NurpP --minimal linux-2.6.4/include/linux/fs.h linux-2.6.4-bme0.04/include/linux/fs.h
--- linux-2.6.4/include/linux/fs.h 2004-03-11 03:55:24.000000000 +0100
+++ linux-2.6.4-bme0.04/include/linux/fs.h 2004-03-12 20:51:58.000000000 +0100
@@ -211,7 +211,7 @@ extern int leases_enable, dir_notify_ena
#include <asm/byteorder.h>
/* Used to be a macro which just called the function, now just a function */
-extern void update_atime (struct inode *);
+extern void update_atime (struct inode *, struct vfsmount *);
extern void inode_init(unsigned long);
extern void mnt_init(unsigned long);
diff -NurpP --minimal linux-2.6.4/include/linux/mount.h linux-2.6.4-bme0.04/include/linux/mount.h
--- linux-2.6.4/include/linux/mount.h 2004-03-11 03:55:22.000000000 +0100
+++ linux-2.6.4-bme0.04/include/linux/mount.h 2004-03-12 20:51:58.000000000 +0100
@@ -14,9 +14,12 @@
#include <linux/list.h>
-#define MNT_NOSUID 1
-#define MNT_NODEV 2
-#define MNT_NOEXEC 4
+#define MNT_RDONLY 1
+#define MNT_NOSUID 2
+#define MNT_NODEV 4
+#define MNT_NOEXEC 8
+#define MNT_NOATIME 1024
+#define MNT_NODIRATIME 2048
struct vfsmount
{
@@ -33,6 +36,11 @@ struct vfsmount
struct list_head mnt_list;
};
+ /* remove (m) with fixmes */
+#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 -NurpP --minimal linux-2.6.4/ipc/shm.c linux-2.6.4-bme0.04/ipc/shm.c
--- linux-2.6.4/ipc/shm.c 2004-03-11 03:55:27.000000000 +0100
+++ linux-2.6.4-bme0.04/ipc/shm.c 2004-03-12 20:51:58.000000000 +0100
@@ -149,7 +149,7 @@ static void shm_close (struct vm_area_st
static int shm_mmap(struct file * file, struct vm_area_struct * vma)
{
- update_atime(file->f_dentry->d_inode);
+ update_atime(file->f_dentry->d_inode, file->f_vfsmnt);
vma->vm_ops = &shm_vm_ops;
shm_inc(file->f_dentry->d_inode->i_ino);
return 0;
diff -NurpP --minimal linux-2.6.4/mm/filemap.c linux-2.6.4-bme0.04/mm/filemap.c
--- linux-2.6.4/mm/filemap.c 2004-03-11 03:55:25.000000000 +0100
+++ linux-2.6.4-bme0.04/mm/filemap.c 2004-03-12 20:51:58.000000000 +0100
@@ -725,7 +725,7 @@ no_cached_page:
*ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
if (cached_page)
page_cache_release(cached_page);
- update_atime(inode);
+ update_atime(inode, filp->f_vfsmnt);
}
EXPORT_SYMBOL(do_generic_mapping_read);
@@ -820,7 +820,7 @@ __generic_file_aio_read(struct kiocb *io
if (retval > 0)
*ppos = pos + retval;
}
- update_atime(filp->f_dentry->d_inode);
+ update_atime(filp->f_dentry->d_inode, filp->f_vfsmnt);
goto out;
}
@@ -1357,7 +1357,7 @@ int generic_file_mmap(struct file * file
if (!mapping->a_ops->readpage)
return -ENOEXEC;
- update_atime(inode);
+ update_atime(inode, file->f_vfsmnt);
vma->vm_ops = &generic_file_vm_ops;
return 0;
}
diff -NurpP --minimal linux-2.6.4/mm/shmem.c linux-2.6.4-bme0.04/mm/shmem.c
--- linux-2.6.4/mm/shmem.c 2004-03-11 03:55:26.000000000 +0100
+++ linux-2.6.4-bme0.04/mm/shmem.c 2004-03-12 20:51:58.000000000 +0100
@@ -1067,7 +1067,7 @@ static int shmem_mmap(struct file *file,
ops = &shmem_vm_ops;
if (!S_ISREG(inode->i_mode))
return -EACCES;
- update_atime(inode);
+ update_atime(inode, file->f_vfsmnt);
vma->vm_ops = ops;
return 0;
}
@@ -1363,7 +1363,7 @@ static void do_shmem_file_read(struct fi
}
*ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
- update_atime(inode);
+ update_atime(inode, filp->f_vfsmnt);
}
static ssize_t shmem_file_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
diff -NurpP --minimal linux-2.6.4/net/unix/af_unix.c linux-2.6.4-bme0.04/net/unix/af_unix.c
--- linux-2.6.4/net/unix/af_unix.c 2004-03-11 03:55:35.000000000 +0100
+++ linux-2.6.4-bme0.04/net/unix/af_unix.c 2004-03-12 20:51:58.000000000 +0100
@@ -691,7 +691,7 @@ static struct sock *unix_find_other(stru
goto put_fail;
if (u->sk_type == type)
- update_atime(nd.dentry->d_inode);
+ update_atime(nd.dentry->d_inode, nd.mnt);
path_release(&nd);
@@ -707,7 +707,7 @@ static struct sock *unix_find_other(stru
struct dentry *dentry;
dentry = unix_sk(u)->dentry;
if (dentry)
- update_atime(dentry->d_inode);
+ update_atime(dentry->d_inode, nd.mnt);
} else
goto fail;
}
Herbert Poetzl <[email protected]> wrote:
>
> ; this patch adds some functionality to the --bind
> ; type of vfs mounts.
This won't apply any more. We very recently changed a large number of
filesystems to not call update_atime() from within their readdir functions.
That operation was hoisted up to vfs_readdir().
Also, rather than adding MNT_IS_RDONLY() and having to remember to check
both the inode and the mount all over the kernel it would be better to
change IS_RDONLY() to take two arguments - the inode and the vfsmnt. That
way we won't miss places, and unconverted code simpy won't compile, thus
drawing attention to itself. I don't know if this is feasible, but please
consider it.
On Sun, Mar 14, 2004 at 08:14:57PM -0800, Andrew Morton wrote:
> Herbert Poetzl <[email protected]> wrote:
> >
> > ; this patch adds some functionality to the --bind
> > ; type of vfs mounts.
>
> This won't apply any more. We very recently changed a large number of
> filesystems to not call update_atime() from within their readdir functions.
> That operation was hoisted up to vfs_readdir().
good decision, very recently probably means in the bk repository,
is there any link where I could download those changes?
> Also, rather than adding MNT_IS_RDONLY() and having to remember to check
> both the inode and the mount all over the kernel it would be better to
> change IS_RDONLY() to take two arguments - the inode and the vfsmnt. That
> way we won't miss places, and unconverted code simpy won't compile, thus
> drawing attention to itself. I don't know if this is feasible, but please
> consider it.
I don't have a problem with that, and it sounds good to me so
far, so I'll have a look at it, and will update the patch
accordingly ...
thanks for the response,
Herbert
Herbert Poetzl <[email protected]> wrote:
>
> On Sun, Mar 14, 2004 at 08:14:57PM -0800, Andrew Morton wrote:
> > Herbert Poetzl <[email protected]> wrote:
> > >
> > > ; this patch adds some functionality to the --bind
> > > ; type of vfs mounts.
> >
> > This won't apply any more. We very recently changed a large number of
> > filesystems to not call update_atime() from within their readdir functions.
> > That operation was hoisted up to vfs_readdir().
>
> good decision, very recently probably means in the bk repository,
> is there any link where I could download those changes?
The latest diff against the most-recently-release kernel is always at
http://www.kernel.org/pub/linux/kernel/v2.5/testing/cset/
the topmost link.
> > Also, rather than adding MNT_IS_RDONLY() and having to remember to check
> > both the inode and the mount all over the kernel it would be better to
> > change IS_RDONLY() to take two arguments - the inode and the vfsmnt. That
> > way we won't miss places, and unconverted code simpy won't compile, thus
> > drawing attention to itself. I don't know if this is feasible, but please
> > consider it.
>
> I don't have a problem with that, and it sounds good to me so
> far, so I'll have a look at it, and will update the patch
> accordingly ...
Thanks.
On Sun, Mar 14, 2004 at 08:34:27PM -0800, Andrew Morton wrote:
> Herbert Poetzl <[email protected]> wrote:
> > On Sun, Mar 14, 2004 at 08:14:57PM -0800, Andrew Morton wrote:
> > >
> > > This won't apply any more. We very recently changed a large
> > > number of filesystems to not call update_atime() from within
> > > their readdir functions.
> > > That operation was hoisted up to vfs_readdir().
okay, patches do reflect this change now ...
> > > Also, rather than adding MNT_IS_RDONLY() and having to
> > > remember to check both the inode and the mount all over
> > > the kernel it would be better to change IS_RDONLY() to
> > > take two arguments - the inode and the vfsmnt. That
> > > way we won't miss places, and unconverted code simpy
> > > won't compile, thus drawing attention to itself.
> > > I don't know if this is feasible, but please consider it.
I decided to split this up into five parts, a simple base
patch, a patch doing the noatime stuff, and three patches
for the IS_RDONLY changes ...
bme0.04.1-ro1 ... are the completely resolved ones
bme0.04.1-ro2 ... acl stuff, needs checking for nd
bme0.04.1-ro3 ... unresolved/legacy
currently I do not know where to get the vfsmnt for the
cases in bme0.04.1-ro3, so they use the legacy define
IS_RDONLY_INODE() for their checks ...
I hope this is what you had in mind, but anyways, let me
know how to proceed ...
best,
Herbert
PS: basic functionality has been verified.
http://www.13thfloor.at/patches/patch-2.6.4-20040314_2308-bme0.04.1.diff
http://www.13thfloor.at/patches/patch-2.6.4-20040314_2308-bme0.04.1-atime.diff
http://www.13thfloor.at/patches/patch-2.6.4-20040314_2308-bme0.04.1-ro1.diff
http://www.13thfloor.at/patches/patch-2.6.4-20040314_2308-bme0.04.1-ro2.diff
http://www.13thfloor.at/patches/patch-2.6.4-20040314_2308-bme0.04.1-ro3.diff
diff -NurpP --minimal linux-2.6.4-20040314_2308/include/linux/fs.h linux-2.6.4-20040314_2308-bme0.04.1/include/linux/fs.h
--- linux-2.6.4-20040314_2308/include/linux/fs.h 2004-03-15 05:41:50.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/include/linux/fs.h 2004-03-15 06:42:13.000000000 +0100
@@ -214,7 +216,7 @@ extern int leases_enable, dir_notify_ena
#include <asm/byteorder.h>
/* Used to be a macro which just called the function, now just a function */
-extern void update_atime (struct inode *);
+extern void update_atime (struct inode *, struct vfsmount *);
extern void inode_init(unsigned long);
extern void mnt_init(unsigned long);
@@ -1409,7 +1411,7 @@ extern void simple_release_fs(struct vfs
extern int inode_change_ok(struct inode *, struct iattr *);
extern int inode_setattr(struct inode *, struct iattr *);
-extern void inode_update_time(struct inode *inode, int ctime_too);
+extern void inode_update_time(struct inode *inode, int ctime_too, struct vfsmount *mount);
static inline ino_t parent_ino(struct dentry *dentry)
{
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/inode.c linux-2.6.4-20040314_2308-bme0.04.1/fs/inode.c
--- linux-2.6.4-20040314_2308/fs/inode.c 2004-03-15 05:41:49.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/inode.c 2004-03-15 06:32:33.000000000 +0100
@@ -1141,15 +1142,16 @@ static int inode_times_differ(struct ino
* This function automatically handles read only file systems and media,
* as well as the "noatime" flag and inode specific "noatime" markers.
*/
-void update_atime(struct inode *inode)
+void update_atime(struct inode *inode, struct vfsmount *mnt)
{
struct timespec now;
- if (IS_NOATIME(inode))
+ if (IS_NOATIME(inode) || MNT_IS_NOATIME(mnt))
return;
- if (IS_NODIRATIME(inode) && S_ISDIR(inode->i_mode))
+ if (S_ISDIR(inode->i_mode) &&
+ (IS_NODIRATIME(inode) || MNT_IS_NODIRATIME(mnt)))
return;
- if (IS_RDONLY(inode))
+ if (IS_RDONLY(inode, mnt))
return;
now = current_kernel_time();
diff -NurpP --minimal linux-2.6.4-20040314_2308/drivers/char/random.c linux-2.6.4-20040314_2308-bme0.04.1/drivers/char/random.c
--- linux-2.6.4-20040314_2308/drivers/char/random.c 2004-03-11 03:55:22.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/drivers/char/random.c 2004-03-15 06:02:34.000000000 +0100
@@ -1641,7 +1641,7 @@ random_read(struct file * file, char * b
* If we gave the user some bytes, update the access time.
*/
if (count != 0) {
- update_atime(file->f_dentry->d_inode);
+ update_atime(file->f_dentry->d_inode, file->f_vfsmnt);
}
return (count ? count : retval);
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/autofs4/root.c linux-2.6.4-20040314_2308-bme0.04.1/fs/autofs4/root.c
--- linux-2.6.4-20040314_2308/fs/autofs4/root.c 2004-03-11 03:55:21.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/autofs4/root.c 2004-03-15 06:02:34.000000000 +0100
@@ -61,7 +61,8 @@ static void autofs4_update_usage(struct
struct autofs_info *ino = autofs4_dentry_ino(dentry);
if (ino) {
- update_atime(dentry->d_inode);
+ /* Al Viro said: unconditional */
+ update_atime(dentry->d_inode, 0);
ino->last_used = jiffies;
}
}
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/coda/dir.c linux-2.6.4-20040314_2308-bme0.04.1/fs/coda/dir.c
--- linux-2.6.4-20040314_2308/fs/coda/dir.c 2004-03-15 05:41:49.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/coda/dir.c 2004-03-15 06:59:42.000000000 +0100
@@ -512,7 +512,7 @@ int coda_readdir(struct file *coda_file,
ret = -ENOENT;
if (!IS_DEADDIR(host_inode)) {
ret = host_file->f_op->readdir(host_file, filldir, dirent);
- update_atime(host_inode);
+ update_atime(host_inode, host_file->f_vfsmnt);
}
}
out:
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/hugetlbfs/inode.c linux-2.6.4-20040314_2308-bme0.04.1/fs/hugetlbfs/inode.c
--- linux-2.6.4-20040314_2308/fs/hugetlbfs/inode.c 2004-03-11 03:55:44.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/hugetlbfs/inode.c 2004-03-15 06:02:34.000000000 +0100
@@ -62,7 +62,7 @@ static int hugetlbfs_file_mmap(struct fi
vma_len = (loff_t)(vma->vm_end - vma->vm_start);
down(&inode->i_sem);
- update_atime(inode);
+ update_atime(inode, file->f_vfsmnt);
vma->vm_flags |= VM_HUGETLB | VM_RESERVED;
vma->vm_ops = &hugetlb_vm_ops;
ret = hugetlb_prefault(mapping, vma);
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/namei.c linux-2.6.4-20040314_2308-bme0.04.1/fs/namei.c
--- linux-2.6.4-20040314_2308/fs/namei.c 2004-03-11 03:55:25.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/namei.c 2004-03-15 07:29:50.000000000 +0100
@@ -412,7 +416,7 @@ static inline int do_follow_link(struct
goto loop;
current->link_count++;
current->total_link_count++;
- update_atime(dentry->d_inode);
+ update_atime(dentry->d_inode, nd->mnt);
err = dentry->d_inode->i_op->follow_link(dentry, nd);
current->link_count--;
return err;
@@ -1368,7 +1390,7 @@ do_link:
error = security_inode_follow_link(dentry, nd);
if (error)
goto exit_dput;
- update_atime(dentry->d_inode);
+ update_atime(dentry->d_inode, nd->mnt);
error = dentry->d_inode->i_op->follow_link(dentry, nd);
dput(dentry);
if (error)
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/nfsd/vfs.c linux-2.6.4-20040314_2308-bme0.04.1/fs/nfsd/vfs.c
--- linux-2.6.4-20040314_2308/fs/nfsd/vfs.c 2004-03-11 03:55:26.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/nfsd/vfs.c 2004-03-15 06:19:48.000000000 +0100
@@ -1143,7 +1143,7 @@ nfsd_readlink(struct svc_rqst *rqstp, st
if (!inode->i_op || !inode->i_op->readlink)
goto out;
- update_atime(inode);
+ update_atime(inode, fhp->fh_export->ex_mnt);
/* N.B. Why does this call need a get_fs()??
* Remove the set_fs and watch the fireworks:-) --okir
*/
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/pipe.c linux-2.6.4-20040314_2308-bme0.04.1/fs/pipe.c
--- linux-2.6.4-20040314_2308/fs/pipe.c 2004-03-11 03:55:28.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/pipe.c 2004-03-15 06:30:26.000000000 +0100
@@ -165,7 +165,7 @@ pipe_readv(struct file *filp, const stru
kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
}
if (ret > 0)
- update_atime(inode);
+ update_atime(inode, filp->f_vfsmnt);
return ret;
}
@@ -263,7 +263,7 @@ pipe_writev(struct file *filp, const str
kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
}
if (ret > 0)
- inode_update_time(inode, 1); /* mtime and ctime */
+ inode_update_time(inode, 1, filp->f_vfsmnt); /* mtime and ctime */
return ret;
}
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/readdir.c linux-2.6.4-20040314_2308-bme0.04.1/fs/readdir.c
--- linux-2.6.4-20040314_2308/fs/readdir.c 2004-03-15 05:41:49.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/readdir.c 2004-03-15 06:54:08.000000000 +0100
@@ -32,7 +32,7 @@ int vfs_readdir(struct file *file, filld
res = -ENOENT;
if (!IS_DEADDIR(inode)) {
res = file->f_op->readdir(file, buf, filler);
- update_atime(inode);
+ update_atime(inode, file->f_vfsmnt);
}
up(&inode->i_sem);
out:
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/reiserfs/file.c linux-2.6.4-20040314_2308-bme0.04.1/fs/reiserfs/file.c
--- linux-2.6.4-20040314_2308/fs/reiserfs/file.c 2004-03-11 03:55:21.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/reiserfs/file.c 2004-03-15 06:30:43.000000000 +0100
@@ -1061,7 +1061,7 @@ ssize_t reiserfs_file_write( struct file
goto out;
remove_suid(file->f_dentry);
- inode_update_time(inode, 1); /* Both mtime and ctime */
+ inode_update_time(inode, 1, file->f_vfsmnt); /* Both mtime and ctime */
// Ok, we are done with all the checks.
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/stat.c linux-2.6.4-20040314_2308-bme0.04.1/fs/stat.c
--- linux-2.6.4-20040314_2308/fs/stat.c 2004-03-11 03:55:23.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/stat.c 2004-03-15 06:02:34.000000000 +0100
@@ -272,7 +272,7 @@ asmlinkage long sys_readlink(const char
if (inode->i_op && inode->i_op->readlink) {
error = security_inode_readlink(nd.dentry);
if (!error) {
- update_atime(inode);
+ update_atime(inode, nd.mnt);
error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
}
}
diff -NurpP --minimal linux-2.6.4-20040314_2308/ipc/shm.c linux-2.6.4-20040314_2308-bme0.04.1/ipc/shm.c
--- linux-2.6.4-20040314_2308/ipc/shm.c 2004-03-11 03:55:27.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/ipc/shm.c 2004-03-15 06:02:34.000000000 +0100
@@ -149,7 +149,7 @@ static void shm_close (struct vm_area_st
static int shm_mmap(struct file * file, struct vm_area_struct * vma)
{
- update_atime(file->f_dentry->d_inode);
+ update_atime(file->f_dentry->d_inode, file->f_vfsmnt);
vma->vm_ops = &shm_vm_ops;
shm_inc(file->f_dentry->d_inode->i_ino);
return 0;
diff -NurpP --minimal linux-2.6.4-20040314_2308/mm/filemap.c linux-2.6.4-20040314_2308-bme0.04.1/mm/filemap.c
--- linux-2.6.4-20040314_2308/mm/filemap.c 2004-03-11 03:55:25.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/mm/filemap.c 2004-03-15 06:31:00.000000000 +0100
@@ -725,7 +725,7 @@ no_cached_page:
*ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
if (cached_page)
page_cache_release(cached_page);
- update_atime(inode);
+ update_atime(inode, filp->f_vfsmnt);
}
EXPORT_SYMBOL(do_generic_mapping_read);
@@ -820,7 +820,7 @@ __generic_file_aio_read(struct kiocb *io
if (retval > 0)
*ppos = pos + retval;
}
- update_atime(filp->f_dentry->d_inode);
+ update_atime(filp->f_dentry->d_inode, filp->f_vfsmnt);
goto out;
}
@@ -1357,7 +1357,7 @@ int generic_file_mmap(struct file * file
if (!mapping->a_ops->readpage)
return -ENOEXEC;
- update_atime(inode);
+ update_atime(inode, file->f_vfsmnt);
vma->vm_ops = &generic_file_vm_ops;
return 0;
}
@@ -1783,7 +1783,7 @@ generic_file_aio_write_nolock(struct kio
goto out;
remove_suid(file->f_dentry);
- inode_update_time(inode, 1);
+ inode_update_time(inode, 1, file->f_vfsmnt);
/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
if (unlikely(file->f_flags & O_DIRECT)) {
diff -NurpP --minimal linux-2.6.4-20040314_2308/mm/shmem.c linux-2.6.4-20040314_2308-bme0.04.1/mm/shmem.c
--- linux-2.6.4-20040314_2308/mm/shmem.c 2004-03-11 03:55:26.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/mm/shmem.c 2004-03-15 06:02:34.000000000 +0100
@@ -1067,7 +1067,7 @@ static int shmem_mmap(struct file *file,
ops = &shmem_vm_ops;
if (!S_ISREG(inode->i_mode))
return -EACCES;
- update_atime(inode);
+ update_atime(inode, file->f_vfsmnt);
vma->vm_ops = ops;
return 0;
}
@@ -1363,7 +1363,7 @@ static void do_shmem_file_read(struct fi
}
*ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
- update_atime(inode);
+ update_atime(inode, filp->f_vfsmnt);
}
static ssize_t shmem_file_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
diff -NurpP --minimal linux-2.6.4-20040314_2308/net/unix/af_unix.c linux-2.6.4-20040314_2308-bme0.04.1/net/unix/af_unix.c
--- linux-2.6.4-20040314_2308/net/unix/af_unix.c 2004-03-11 03:55:35.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/net/unix/af_unix.c 2004-03-15 06:02:34.000000000 +0100
@@ -691,7 +691,7 @@ static struct sock *unix_find_other(stru
goto put_fail;
if (u->sk_type == type)
- update_atime(nd.dentry->d_inode);
+ update_atime(nd.dentry->d_inode, nd.mnt);
path_release(&nd);
@@ -707,7 +707,7 @@ static struct sock *unix_find_other(stru
struct dentry *dentry;
dentry = unix_sk(u)->dentry;
if (dentry)
- update_atime(dentry->d_inode);
+ update_atime(dentry->d_inode, nd.mnt);
} else
goto fail;
}
;
; Bind Mount Extensions
;
; this patch adds some functionality to the --bind
; type of vfs mounts.
;
; (C) 2003-2004 Herbert P?tzl <[email protected]>
;
; Changelog:
;
; 0.01 - readonly bind mounts
; 0.02 - added ro truncate handling
; - added ro (f)chown, (f)chmod handling
; 0.03 - added ro utime(s) handling
; - added ro access and *_ioctl
; 0.04 - added noatime and nodiratime
; - made autofs4 update_atime uncond
;
; 0.04.1 IS_RDONLY extended by vfsmnt
; - IS_RDONLY_INODE() added for legacy
; - update_atime() updated (20040314_2308)
;
; this patch is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version 2
; of the License, or (at your option) any later version.
;
; this patch is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/namespace.c linux-2.6.4-20040314_2308-bme0.04.1/fs/namespace.c
--- linux-2.6.4-20040314_2308/fs/namespace.c 2004-03-11 03:55:35.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/namespace.c 2004-03-15 07:51:27.000000000 +0100
@@ -229,7 +229,8 @@ static int show_vfsmnt(struct seq_file *
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");
+ seq_puts(m, (MNT_IS_RDONLY(mnt) ||
+ (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);
@@ -522,11 +523,13 @@ out_unlock:
/*
* do loopback mount.
*/
-static int do_loopback(struct nameidata *nd, char *old_name, int recurse)
+static int do_loopback(struct nameidata *nd, char *old_name, unsigned long flags, int mnt_flags)
{
struct nameidata old_nd;
struct vfsmount *mnt = NULL;
+ int recurse = flags & MS_REC;
int err = mount_is_safe(nd);
+
if (err)
return err;
if (!old_name || !*old_name)
@@ -553,6 +556,7 @@ static int do_loopback(struct nameidata
spin_unlock(&vfsmount_lock);
} else
mntput(mnt);
+ mnt->mnt_flags = mnt_flags;
}
up_write(¤t->namespace->sem);
@@ -759,12 +763,18 @@ long do_mount(char * dev_name, char * di
((char *)data_page)[PAGE_SIZE - 1] = 0;
/* Separate the per-mountpoint flags */
+ if (flags & MS_RDONLY)
+ mnt_flags |= MNT_RDONLY;
if (flags & MS_NOSUID)
mnt_flags |= MNT_NOSUID;
if (flags & MS_NODEV)
mnt_flags |= MNT_NODEV;
if (flags & MS_NOEXEC)
mnt_flags |= MNT_NOEXEC;
+ if (flags & MS_NOATIME)
+ mnt_flags |= MNT_NOATIME;
+ if (flags & MS_NODIRATIME)
+ mnt_flags |= MNT_NODIRATIME;
flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV);
/* ... and get the mountpoint */
@@ -780,7 +790,7 @@ long do_mount(char * dev_name, char * di
retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
data_page);
else if (flags & MS_BIND)
- retval = do_loopback(&nd, dev_name, flags & MS_REC);
+ retval = do_loopback(&nd, dev_name, flags, mnt_flags);
else if (flags & MS_MOVE)
retval = do_move_mount(&nd, dev_name);
else
diff -NurpP --minimal linux-2.6.4-20040314_2308/include/linux/mount.h linux-2.6.4-20040314_2308-bme0.04.1/include/linux/mount.h
--- linux-2.6.4-20040314_2308/include/linux/mount.h 2004-03-11 03:55:22.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/include/linux/mount.h 2004-03-15 05:58:04.000000000 +0100
@@ -14,9 +14,12 @@
#include <linux/list.h>
-#define MNT_NOSUID 1
-#define MNT_NODEV 2
-#define MNT_NOEXEC 4
+#define MNT_RDONLY 1
+#define MNT_NOSUID 2
+#define MNT_NODEV 4
+#define MNT_NOEXEC 8
+#define MNT_NOATIME 1024
+#define MNT_NODIRATIME 2048
struct vfsmount
{
@@ -33,6 +36,11 @@ struct vfsmount
struct list_head mnt_list;
};
+ /* remove (m) when done */
+#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 -NurpP --minimal linux-2.6.4-20040314_2308/include/linux/posix_acl.h linux-2.6.4-20040314_2308-bme0.04.1/include/linux/posix_acl.h
--- linux-2.6.4-20040314_2308/include/linux/posix_acl.h 2004-03-11 03:55:54.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/include/linux/posix_acl.h 2004-03-15 07:45:19.000000000 +0100
@@ -9,6 +9,7 @@
#define __LINUX_POSIX_ACL_H
#include <linux/slab.h>
+#include <linux/namei.h>
#define ACL_UNDEFINED_ID (-1)
diff -NurpP --minimal linux-2.6.4-20040314_2308/include/linux/fs.h linux-2.6.4-20040314_2308-bme0.04.1/include/linux/fs.h
--- linux-2.6.4-20040314_2308/include/linux/fs.h 2004-03-15 05:41:50.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/include/linux/fs.h 2004-03-15 06:42:13.000000000 +0100
@@ -19,6 +19,7 @@
#include <linux/cache.h>
#include <linux/radix-tree.h>
#include <linux/kobject.h>
+#include <linux/mount.h>
#include <asm/atomic.h>
struct iovec;
@@ -155,7 +156,8 @@ extern int leases_enable, dir_notify_ena
*/
#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(inode) ((inode)->i_sb->s_flags & MS_RDONLY)
+#define IS_RDONLY(inode,mount) (IS_RDONLY_INODE(inode) || MNT_IS_RDONLY(mount))
#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) || \
@@ -1226,7 +1228,7 @@ extern sector_t bmap(struct inode *, sec
extern int setattr_mask(unsigned int);
extern int notify_change(struct dentry *, struct iattr *);
extern int permission(struct inode *, int, struct nameidata *);
-extern int vfs_permission(struct inode *, int);
+extern int vfs_permission(struct inode *, int, struct nameidata *);
extern int get_write_access(struct inode *);
extern int deny_write_access(struct file *);
static inline void put_write_access(struct inode * inode)
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/open.c linux-2.6.4-20040314_2308-bme0.04.1/fs/open.c
--- linux-2.6.4-20040314_2308/fs/open.c 2004-03-15 05:41:49.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/open.c 2004-03-15 05:58:51.000000000 +0100
@@ -226,7 +226,7 @@ static inline long do_sys_truncate(const
goto dput_and_out;
error = -EROFS;
- if (IS_RDONLY(inode))
+ if (IS_RDONLY(inode, nd.mnt))
goto dput_and_out;
error = -EPERM;
@@ -350,7 +350,7 @@ asmlinkage long sys_utime(char __user *
inode = nd.dentry->d_inode;
error = -EROFS;
- if (IS_RDONLY(inode))
+ if (IS_RDONLY(inode, nd.mnt))
goto dput_and_out;
/* Don't worry, the checks are done in inode_change_ok() */
@@ -407,7 +407,7 @@ long do_utimes(char __user * filename, s
inode = nd.dentry->d_inode;
error = -EROFS;
- if (IS_RDONLY(inode))
+ if (IS_RDONLY(inode, nd.mnt))
goto dput_and_out;
/* Don't worry, the checks are done in inode_change_ok() */
@@ -489,8 +489,9 @@ asmlinkage long sys_access(const char __
if (!res) {
res = permission(nd.dentry->d_inode, mode, &nd);
/* SuS v2 requires we report a read only fs too */
- if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
- && !special_file(nd.dentry->d_inode->i_mode))
+ if (!res && (mode & S_IWOTH)
+ && !special_file(nd.dentry->d_inode->i_mode)
+ && (IS_RDONLY(nd.dentry->d_inode, nd.mnt)))
res = -EROFS;
path_release(&nd);
}
@@ -595,7 +596,7 @@ asmlinkage long sys_fchmod(unsigned int
inode = dentry->d_inode;
err = -EROFS;
- if (IS_RDONLY(inode))
+ if (IS_RDONLY(inode, file->f_vfsmnt))
goto out_putf;
err = -EPERM;
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
@@ -627,7 +628,7 @@ asmlinkage long sys_chmod(const char __u
inode = nd.dentry->d_inode;
error = -EROFS;
- if (IS_RDONLY(inode))
+ if (IS_RDONLY(inode, nd.mnt))
goto dput_and_out;
error = -EPERM;
@@ -648,7 +649,7 @@ out:
return error;
}
-static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
+static int chown_common(struct vfsmount *mnt, struct dentry * dentry, uid_t user, gid_t group)
{
struct inode * inode;
int error;
@@ -660,7 +661,7 @@ static int chown_common(struct dentry *
goto out;
}
error = -EROFS;
- if (IS_RDONLY(inode))
+ if (IS_RDONLY(inode, mnt))
goto out;
error = -EPERM;
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
@@ -690,7 +691,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.mnt, nd.dentry, user, group);
path_release(&nd);
}
return error;
@@ -703,7 +704,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.mnt, nd.dentry, user, group);
path_release(&nd);
}
return error;
@@ -717,7 +718,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_vfsmnt, file->f_dentry, user, group);
fput(file);
}
return error;
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/namei.c linux-2.6.4-20040314_2308-bme0.04.1/fs/namei.c
--- linux-2.6.4-20040314_2308/fs/namei.c 2004-03-11 03:55:25.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/namei.c 2004-03-15 07:29:50.000000000 +0100
@@ -209,14 +209,18 @@ int permission(struct inode * inode,int
{
int retval;
int submask;
+ umode_t mode = inode->i_mode;
/* Ordinary permission routines do not understand MAY_APPEND. */
submask = mask & ~MAY_APPEND;
+ if (nd && (mask & MAY_WRITE) && MNT_IS_RDONLY(nd->mnt) &&
+ (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
+ return -EROFS;
if (inode->i_op && inode->i_op->permission)
retval = inode->i_op->permission(inode, submask, nd);
else
- retval = vfs_permission(inode, submask);
+ retval = vfs_permission(inode, submask, nd);
if (retval)
return retval;
@@ -1062,6 +1066,24 @@ static inline int may_create(struct inod
return permission(dir,MAY_WRITE | MAY_EXEC, nd);
}
+static inline int mnt_may_create(struct vfsmount *mnt, struct inode *dir, struct dentry *child) {
+ if (child->d_inode)
+ return -EEXIST;
+ if (IS_DEADDIR(dir))
+ return -ENOENT;
+ if (mnt->mnt_flags & MNT_RDONLY)
+ return -EROFS;
+ return 0;
+}
+
+static inline int mnt_may_unlink(struct vfsmount *mnt, struct inode *dir, struct dentry *child) {
+ if (!child->d_inode)
+ return -ENOENT;
+ if (mnt->mnt_flags & MNT_RDONLY)
+ return -EROFS;
+ return 0;
+}
+
/*
* Special case: O_CREAT|O_EXCL implies O_NOFOLLOW for security
* reasons.
@@ -1183,7 +1205,7 @@ 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, nd->mnt)) && (flag & FMODE_WRITE))
return -EROFS;
/*
* An append-only file must be opened in append mode for writing.
@@ -1408,23 +1430,28 @@ do_link:
struct dentry *lookup_create(struct nameidata *nd, int is_dir)
{
struct dentry *dentry;
+ int error;
down(&nd->dentry->d_inode->i_sem);
- dentry = ERR_PTR(-EEXIST);
+ error = -EEXIST;
if (nd->last_type != LAST_NORM)
- goto fail;
+ goto out;
nd->flags &= ~LOOKUP_PARENT;
dentry = lookup_hash(&nd->last, nd->dentry);
if (IS_ERR(dentry))
+ goto ret;
+ error = mnt_may_create(nd->mnt, nd->dentry->d_inode, dentry);
+ if (error)
goto fail;
+ error = -ENOENT;
if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
- goto enoent;
+ goto fail;
+ret:
return dentry;
-enoent:
- dput(dentry);
- dentry = ERR_PTR(-ENOENT);
fail:
- return dentry;
+ dput(dentry);
+out:
+ return ERR_PTR(error);
}
int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
@@ -1653,7 +1680,11 @@ asmlinkage long sys_rmdir(const char __u
dentry = lookup_hash(&nd.last, nd.dentry);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
+ error = mnt_may_unlink(nd.mnt, nd.dentry->d_inode, dentry);
+ if (error)
+ goto exit2;
error = vfs_rmdir(nd.dentry->d_inode, dentry);
+ exit2:
dput(dentry);
}
up(&nd.dentry->d_inode->i_sem);
@@ -1725,6 +1756,9 @@ asmlinkage long sys_unlink(const char __
/* 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);
@@ -2089,6 +2123,9 @@ static inline int do_rename(const char *
error = -EINVAL;
if (old_dentry == trap)
goto exit4;
+ error = -EROFS;
+ if (MNT_IS_RDONLY(newnd.mnt))
+ goto exit4;
new_dentry = lookup_hash(&newnd.last, new_dir);
error = PTR_ERR(new_dentry);
if (IS_ERR(new_dentry))
diff -NurpP --minimal linux-2.6.4-20040314_2308/arch/sparc64/solaris/fs.c linux-2.6.4-20040314_2308-bme0.04.1/arch/sparc64/solaris/fs.c
--- linux-2.6.4-20040314_2308/arch/sparc64/solaris/fs.c 2004-03-11 03:55:24.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/arch/sparc64/solaris/fs.c 2004-03-15 06:26:55.000000000 +0100
@@ -405,7 +405,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)) i = 1;
if (mnt->mnt_flags & MNT_NOSUID) i |= 2;
if (!sysv_valid_dev(inode->i_sb->s_dev))
return -EOVERFLOW;
@@ -441,7 +441,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)) 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.4-20040314_2308/fs/ext2/ioctl.c linux-2.6.4-20040314_2308-bme0.04.1/fs/ext2/ioctl.c
--- linux-2.6.4-20040314_2308/fs/ext2/ioctl.c 2004-03-11 03:55:54.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/ext2/ioctl.c 2004-03-15 05:58:51.000000000 +0100
@@ -29,7 +30,7 @@ int ext2_ioctl (struct inode * inode, st
case EXT2_IOC_SETFLAGS: {
unsigned int oldflags;
- if (IS_RDONLY(inode))
+ if (IS_RDONLY(inode, filp->f_vfsmnt))
return -EROFS;
if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
@@ -68,7 +69,7 @@ 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->f_vfsmnt))
return -EROFS;
if (get_user(inode->i_generation, (int *) arg))
return -EFAULT;
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/ext2/xattr.c linux-2.6.4-20040314_2308-bme0.04.1/fs/ext2/xattr.c
--- linux-2.6.4-20040314_2308/fs/ext2/xattr.c 2004-03-11 03:55:34.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/ext2/xattr.c 2004-03-15 06:27:13.000000000 +0100
@@ -496,7 +496,7 @@ ext2_xattr_set(struct inode *inode, int
ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
name_index, name, value, (long)value_len);
- if (IS_RDONLY(inode))
+ if (IS_RDONLY_INODE(inode))
return -EROFS;
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
return -EPERM;
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/ext3/ioctl.c linux-2.6.4-20040314_2308-bme0.04.1/fs/ext3/ioctl.c
--- linux-2.6.4-20040314_2308/fs/ext3/ioctl.c 2004-03-11 03:55:26.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/ext3/ioctl.c 2004-03-15 05:58:51.000000000 +0100
@@ -34,7 +35,7 @@ int ext3_ioctl (struct inode * inode, st
unsigned int oldflags;
unsigned int jflag;
- if (IS_RDONLY(inode))
+ if (IS_RDONLY(inode, filp->f_vfsmnt))
return -EROFS;
if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
@@ -110,7 +111,7 @@ flags_err:
if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
return -EPERM;
- if (IS_RDONLY(inode))
+ if (IS_RDONLY(inode, filp->f_vfsmnt))
return -EROFS;
if (get_user(generation, (int *) arg))
return -EFAULT;
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/ext3/xattr.c linux-2.6.4-20040314_2308-bme0.04.1/fs/ext3/xattr.c
--- linux-2.6.4-20040314_2308/fs/ext3/xattr.c 2004-03-11 03:55:28.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/ext3/xattr.c 2004-03-15 06:28:18.000000000 +0100
@@ -496,7 +496,7 @@ ext3_xattr_set_handle(handle_t *handle,
ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
name_index, name, value, (long)value_len);
- if (IS_RDONLY(inode))
+ if (IS_RDONLY_INODE(inode))
return -EROFS;
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
return -EPERM;
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/hfs/inode.c linux-2.6.4-20040314_2308-bme0.04.1/fs/hfs/inode.c
--- linux-2.6.4-20040314_2308/fs/hfs/inode.c 2004-03-11 03:55:54.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/hfs/inode.c 2004-03-15 06:23:57.000000000 +0100
@@ -516,7 +516,7 @@ static int hfs_permission(struct inode *
{
if (S_ISREG(inode->i_mode) && mask & MAY_EXEC)
return 0;
- return vfs_permission(inode, mask);
+ return vfs_permission(inode, mask, nd);
}
static int hfs_file_open(struct inode *inode, struct file *file)
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/hfsplus/inode.c linux-2.6.4-20040314_2308-bme0.04.1/fs/hfsplus/inode.c
--- linux-2.6.4-20040314_2308/fs/hfsplus/inode.c 2004-03-11 03:55:24.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/hfsplus/inode.c 2004-03-15 06:23:48.000000000 +0100
@@ -260,7 +260,7 @@ static int hfsplus_permission(struct ino
*/
if (S_ISREG(inode->i_mode) && mask & MAY_EXEC && !(inode->i_mode & 0111))
return 0;
- return vfs_permission(inode, mask);
+ return vfs_permission(inode, mask, nd);
}
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/intermezzo/dir.c linux-2.6.4-20040314_2308-bme0.04.1/fs/intermezzo/dir.c
--- linux-2.6.4-20040314_2308/fs/intermezzo/dir.c 2004-03-11 03:55:24.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/intermezzo/dir.c 2004-03-15 06:23:38.000000000 +0100
@@ -864,7 +864,7 @@ int presto_permission(struct inode *inod
/* The cache filesystem doesn't have its own permission function,
* so we call the default one.
*/
- rc = vfs_permission(inode, mask);
+ rc = vfs_permission(inode, mask, nd);
EXIT;
return rc;
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/intermezzo/vfs.c linux-2.6.4-20040314_2308-bme0.04.1/fs/intermezzo/vfs.c
--- linux-2.6.4-20040314_2308/fs/intermezzo/vfs.c 2004-03-11 03:55:25.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/intermezzo/vfs.c 2004-03-15 06:40:07.000000000 +0100
@@ -258,7 +258,7 @@ int presto_settime(struct presto_file_se
inode = dentry->d_inode;
error = -EROFS;
- if (IS_RDONLY(inode)) {
+ if (IS_RDONLY_INODE(inode)) {
EXIT;
return -EROFS;
}
@@ -373,7 +373,7 @@ int presto_do_setattr(struct presto_file
ENTRY;
error = -EROFS;
- if (IS_RDONLY(inode)) {
+ if (IS_RDONLY_INODE(inode)) {
EXIT;
return -EROFS;
}
@@ -2316,7 +2316,7 @@ int presto_do_set_ext_attr(struct presto
ENTRY;
error = -EROFS;
- if (IS_RDONLY(inode)) {
+ if (IS_RDONLY_INODE(inode)) {
EXIT;
return -EROFS;
}
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/hfsplus/ioctl.c linux-2.6.4-20040314_2308-bme0.04.1/fs/hfsplus/ioctl.c
--- linux-2.6.4-20040314_2308/fs/hfsplus/ioctl.c 2004-03-11 03:55:24.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/hfsplus/ioctl.c 2004-03-15 06:29:01.000000000 +0100
@@ -33,7 +33,7 @@ int hfsplus_ioctl(struct inode *inode, s
flags |= EXT2_FLAG_NODUMP; /* EXT2_NODUMP_FL */
return put_user(flags, (int *)arg);
case HFSPLUS_IOC_EXT2_SETFLAGS: {
- if (IS_RDONLY(inode))
+ if (IS_RDONLY(inode, filp->f_vfsmnt))
return -EROFS;
if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/inode.c linux-2.6.4-20040314_2308-bme0.04.1/fs/inode.c
--- linux-2.6.4-20040314_2308/fs/inode.c 2004-03-15 05:41:49.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/inode.c 2004-03-15 06:32:33.000000000 +0100
@@ -1173,14 +1175,14 @@ EXPORT_SYMBOL(update_atime);
* When ctime_too is specified update the ctime too.
*/
-void inode_update_time(struct inode *inode, int ctime_too)
+void inode_update_time(struct inode *inode, int ctime_too, struct vfsmount *mount)
{
struct timespec now;
int sync_it = 0;
if (IS_NOCMTIME(inode))
return;
- if (IS_RDONLY(inode))
+ if (IS_RDONLY(inode, mount))
return;
now = current_kernel_time();
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/nfs/dir.c linux-2.6.4-20040314_2308-bme0.04.1/fs/nfs/dir.c
--- linux-2.6.4-20040314_2308/fs/nfs/dir.c 2004-03-15 05:41:49.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/nfs/dir.c 2004-03-15 06:24:31.000000000 +0100
@@ -778,7 +778,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, nd->mnt) &&
+ (nd->intent.open.flags & (O_CREAT|O_TRUNC|FMODE_WRITE)))
return 0;
return 1;
}
@@ -1514,7 +1515,7 @@ nfs_permission(struct inode *inode, int
* Nobody gets write access to a read-only fs.
*
*/
- if (IS_RDONLY(inode) &&
+ if (IS_RDONLY(inode, nd->mnt) &&
(S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
return -EROFS;
@@ -1565,7 +1566,7 @@ out:
return res;
out_notsup:
nfs_revalidate_inode(NFS_SERVER(inode), inode);
- res = vfs_permission(inode, mask);
+ res = vfs_permission(inode, mask, nd);
unlock_kernel();
return res;
add_cache:
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/proc/base.c linux-2.6.4-20040314_2308-bme0.04.1/fs/proc/base.c
--- linux-2.6.4-20040314_2308/fs/proc/base.c 2004-03-11 03:55:34.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/proc/base.c 2004-03-15 06:24:42.000000000 +0100
@@ -449,7 +449,7 @@ out:
static int proc_permission(struct inode *inode, int mask, struct nameidata *nd)
{
- if (vfs_permission(inode, mask) != 0)
+ if (vfs_permission(inode, mask, nd) != 0)
return -EACCES;
return proc_check_root(inode);
}
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/reiserfs/ioctl.c linux-2.6.4-20040314_2308-bme0.04.1/fs/reiserfs/ioctl.c
--- linux-2.6.4-20040314_2308/fs/reiserfs/ioctl.c 2004-03-11 03:55:26.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/reiserfs/ioctl.c 2004-03-15 05:58:51.000000000 +0100
@@ -38,7 +39,7 @@ int reiserfs_ioctl (struct inode * inode
i_attrs_to_sd_attrs( inode, ( __u16 * ) &flags );
return put_user(flags, (int *) arg);
case REISERFS_IOC_SETFLAGS: {
- if (IS_RDONLY(inode))
+ if (IS_RDONLY(inode, filp->f_vfsmnt))
return -EROFS;
if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
@@ -70,7 +71,7 @@ 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->f_vfsmnt))
return -EROFS;
if (get_user(inode->i_generation, (int *) arg))
return -EFAULT;
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/namei.c linux-2.6.4-20040314_2308-bme0.04.1/fs/namei.c
--- linux-2.6.4-20040314_2308/fs/namei.c 2004-03-11 03:55:25.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/namei.c 2004-03-15 07:29:50.000000000 +0100
@@ -156,15 +156,15 @@ char * getname(const char __user * filen
* for filesystem access without changing the "normal" uids which
* are used for other things..
*/
-int vfs_permission(struct inode * inode, int mask)
+int vfs_permission(struct inode * inode, int mask, struct nameidata *nd)
{
- umode_t mode = inode->i_mode;
+ umode_t mode = inode->i_mode;
if (mask & MAY_WRITE) {
/*
* Nobody gets write access to a read-only fs.
*/
- if (IS_RDONLY(inode) &&
+ if (IS_RDONLY(inode, nd ? nd->mnt : NULL) &&
(S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
return -EROFS;
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/ext2/acl.c linux-2.6.4-20040314_2308-bme0.04.1/fs/ext2/acl.c
--- linux-2.6.4-20040314_2308/fs/ext2/acl.c 2004-03-15 05:41:49.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/ext2/acl.c 2004-03-15 07:44:41.000000000 +0100
@@ -291,7 +292,8 @@ ext2_permission(struct inode *inode, int
int mode = inode->i_mode;
/* Nobody gets write access to a read-only fs */
- if ((mask & MAY_WRITE) && IS_RDONLY(inode) &&
+ if ((mask & MAY_WRITE) &&
+ (IS_RDONLY(inode, nd ? nd->mnt : NULL)) &&
(S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
return -EROFS;
/* Nobody gets write access to an immutable file */
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/ext3/acl.c linux-2.6.4-20040314_2308-bme0.04.1/fs/ext3/acl.c
--- linux-2.6.4-20040314_2308/fs/ext3/acl.c 2004-03-15 05:41:49.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/ext3/acl.c 2004-03-15 07:38:42.000000000 +0100
@@ -296,7 +296,8 @@ ext3_permission(struct inode *inode, int
int mode = inode->i_mode;
/* Nobody gets write access to a read-only fs */
- if ((mask & MAY_WRITE) && IS_RDONLY(inode) &&
+ if ((mask & MAY_WRITE) &&
+ (IS_RDONLY(inode, nd ? nd->mnt : NULL)) &&
(S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
return -EROFS;
/* Nobody gets write access to an immutable file */
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/jfs/acl.c linux-2.6.4-20040314_2308-bme0.04.1/fs/jfs/acl.c
--- linux-2.6.4-20040314_2308/fs/jfs/acl.c 2004-03-11 03:55:21.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/jfs/acl.c 2004-03-15 07:37:45.000000000 +0100
@@ -136,7 +136,7 @@ int jfs_permission(struct inode * inode,
/*
* Nobody gets write access to a read-only fs.
*/
- if (IS_RDONLY(inode) &&
+ if (IS_RDONLY(inode, nd ? nd->mnt : NULL) &&
(S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
return -EROFS;
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/xfs/xfs_inode.c linux-2.6.4-20040314_2308-bme0.04.1/fs/xfs/xfs_inode.c
--- linux-2.6.4-20040314_2308/fs/xfs/xfs_inode.c 2004-03-11 03:55:50.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/xfs/xfs_inode.c 2004-03-15 06:17:57.000000000 +0100
@@ -3677,7 +3677,7 @@ xfs_iaccess(
if (mode & S_IWUSR) {
umode_t imode = inode->i_mode;
- if (IS_RDONLY(inode) &&
+ if (IS_RDONLY_INODE(inode) &&
(S_ISREG(imode) || S_ISDIR(imode) || S_ISLNK(imode)))
return XFS_ERROR(EROFS);
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/nfsd/vfs.c linux-2.6.4-20040314_2308-bme0.04.1/fs/nfsd/vfs.c
--- linux-2.6.4-20040314_2308/fs/nfsd/vfs.c 2004-03-11 03:55:26.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/nfsd/vfs.c 2004-03-15 06:19:48.000000000 +0100
@@ -1539,7 +1539,7 @@ nfsd_permission(struct svc_export *exp,
inode->i_mode,
IS_IMMUTABLE(inode)? " immut" : "",
IS_APPEND(inode)? " append" : "",
- IS_RDONLY(inode)? " ro" : "");
+ IS_RDONLY_INODE(inode)? " ro" : "");
dprintk(" owner %d/%d user %d/%d\n",
inode->i_uid, inode->i_gid, current->fsuid, current->fsgid);
#endif
@@ -1550,7 +1550,7 @@ 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(inode))
return nfserr_rofs;
if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode))
return nfserr_perm;
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/ntfs/inode.c linux-2.6.4-20040314_2308-bme0.04.1/fs/ntfs/inode.c
--- linux-2.6.4-20040314_2308/fs/ntfs/inode.c 2004-03-11 03:55:44.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/ntfs/inode.c 2004-03-15 06:18:51.000000000 +0100
@@ -885,7 +885,7 @@ skip_large_dir_stuff:
/* Everyone gets read and scan permissions. */
vi->i_mode |= S_IRUGO | S_IXUGO;
/* If not read-only, set write permissions. */
- if (!IS_RDONLY(vi))
+ if (!IS_RDONLY_INODE(vi))
vi->i_mode |= S_IWUGO;
/*
* Apply the directory permissions mask set in the mount
@@ -1026,7 +1026,7 @@ no_data_attr_special_case:
/* Everyone gets all permissions. */
vi->i_mode |= S_IRWXUGO;
/* If read-only, noone gets write permissions. */
- if (IS_RDONLY(vi))
+ if (IS_RDONLY_INODE(vi))
vi->i_mode &= ~S_IWUGO;
/* Apply the file permissions mask set in the mount options. */
vi->i_mode &= ~vol->fmask;
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/fat/file.c linux-2.6.4-20040314_2308-bme0.04.1/fs/fat/file.c
--- linux-2.6.4-20040314_2308/fs/fat/file.c 2004-03-11 03:55:24.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/fat/file.c 2004-03-15 06:28:31.000000000 +0100
@@ -90,7 +90,7 @@ void fat_truncate(struct inode *inode)
int nr_clusters;
/* Why no return value? Surely the disk could fail... */
- if (IS_RDONLY (inode))
+ if (IS_RDONLY_INODE(inode))
return /* -EPERM */;
if (IS_IMMUTABLE(inode))
return /* -EPERM */;
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/jfs/xattr.c linux-2.6.4-20040314_2308-bme0.04.1/fs/jfs/xattr.c
--- linux-2.6.4-20040314_2308/fs/jfs/xattr.c 2004-03-11 03:55:25.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/jfs/xattr.c 2004-03-15 06:40:42.000000000 +0100
@@ -717,7 +717,7 @@ static int can_set_system_xattr(struct i
static int can_set_xattr(struct inode *inode, const char *name,
const void *value, size_t value_len)
{
- if (IS_RDONLY(inode))
+ if (IS_RDONLY_INODE(inode))
return -EROFS;
if (IS_IMMUTABLE(inode) || IS_APPEND(inode) || S_ISLNK(inode->i_mode))
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/ext3/inode.c linux-2.6.4-20040314_2308-bme0.04.1/fs/ext3/inode.c
--- linux-2.6.4-20040314_2308/fs/ext3/inode.c 2004-03-11 03:55:35.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/ext3/inode.c 2004-03-15 06:27:47.000000000 +0100
@@ -3018,7 +3018,7 @@ int ext3_change_inode_journal_flag(struc
*/
journal = EXT3_JOURNAL(inode);
- if (is_journal_aborted(journal) || IS_RDONLY(inode))
+ if (is_journal_aborted(journal) || IS_RDONLY_INODE(inode))
return -EROFS;
journal_lock_updates(journal);
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/ncpfs/file.c linux-2.6.4-20040314_2308-bme0.04.1/fs/ncpfs/file.c
--- linux-2.6.4-20040314_2308/fs/ncpfs/file.c 2004-03-11 03:55:21.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/ncpfs/file.c 2004-03-15 06:21:31.000000000 +0100
@@ -175,7 +175,7 @@ ncp_file_read(struct file *file, char *b
*ppos = pos;
- if (!IS_RDONLY(inode)) {
+ if (!IS_RDONLY_INODE(inode)) {
inode->i_atime = CURRENT_TIME;
}
diff -NurpP --minimal linux-2.6.4-20040314_2308/fs/ncpfs/mmap.c linux-2.6.4-20040314_2308-bme0.04.1/fs/ncpfs/mmap.c
--- linux-2.6.4-20040314_2308/fs/ncpfs/mmap.c 2004-03-11 03:55:36.000000000 +0100
+++ linux-2.6.4-20040314_2308-bme0.04.1/fs/ncpfs/mmap.c 2004-03-15 06:21:00.000000000 +0100
@@ -123,7 +123,7 @@ int ncp_mmap(struct file *file, struct v
if (((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff
> (1U << (32 - PAGE_SHIFT)))
return -EFBIG;
- if (!IS_RDONLY(inode)) {
+ if (!IS_RDONLY_INODE(inode)) {
inode->i_atime = CURRENT_TIME;
}
On Monday 15 March 2004 05:14, Andrew Morton wrote:
Hi Herbert, Andrew,
> Herbert Poetzl <[email protected]> wrote:
> > ; this patch adds some functionality to the --bind
> > ; type of vfs mounts.
> This won't apply any more. We very recently changed a large number of
> filesystems to not call update_atime() from within their readdir functions.
> That operation was hoisted up to vfs_readdir().
right. Anyway, I like to see this merged into -mm for wider testing after
Herbert has fixed up some things like update_atime removal etc.
I personally use it for a long time now and I really like it.
ciao, Marc
> I personally use it for a long time now and I really like it.
Same here, I hope this functionality gets merged sooner rather then later.
--
Dariush Pietrzak,
Key fingerprint = 40D0 9FFB 9939 7320 8294 05E0 BCC7 02C4 75CC 50D9
Herbert Poetzl <[email protected]> wrote:
>
> --- linux-2.6.4-20040314_2308/fs/ext2/xattr.c 2004-03-11 03:55:34.000000000 +0100
> +++ linux-2.6.4-20040314_2308-bme0.04.1/fs/ext2/xattr.c 2004-03-15 06:27:13.000000000 +0100
> @@ -496,7 +496,7 @@ ext2_xattr_set(struct inode *inode, int
> ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
> name_index, name, value, (long)value_len);
>
> - if (IS_RDONLY(inode))
> + if (IS_RDONLY_INODE(inode))
I do think that if we're going to do this thing it should have 100%
coverage, and not have little exceptions because the volume of changes got
too high.
The number of places where you need IS_RDONLY_INODE() are encouragingly
small. It appears that all we need to do to get rid of it is to propagate
the file* down through the ext2 and ext3 xattr code. A NULL value will
need to be permitted because ext2_new_inode doesn't have a file*, and we've
already performed the check.
Sure, it's a largeish patch but it is very safe: if it compiles, it works.
Could you please work that with Andreas?
IS_RDONLY_INODE() is also used in intermezzo, but that doesn't compile any
more anyway.
On Mon, Mar 15, 2004 at 02:10:04PM -0800, Andrew Morton wrote:
> Herbert Poetzl <[email protected]> wrote:
> >
> > --- linux-2.6.4-20040314_2308/fs/ext2/xattr.c 2004-03-11 03:55:34.000000000 +0100
> > +++ linux-2.6.4-20040314_2308-bme0.04.1/fs/ext2/xattr.c 2004-03-15 06:27:13.000000000 +0100
> > @@ -496,7 +496,7 @@ ext2_xattr_set(struct inode *inode, int
> > ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
> > name_index, name, value, (long)value_len);
> >
> > - if (IS_RDONLY(inode))
> > + if (IS_RDONLY_INODE(inode))
>
> I do think that if we're going to do this thing it should have 100%
> coverage, and not have little exceptions because the volume of changes got
> too high.
>
> The number of places where you need IS_RDONLY_INODE() are encouragingly
> small. It appears that all we need to do to get rid of it is to propagate
> the file* down through the ext2 and ext3 xattr code. A NULL value will
> need to be permitted because ext2_new_inode doesn't have a file*, and we've
> already performed the check.
I'm not sure we actually want to do this, but I'll
try ... seems to go up all the way to the syscall entry.
> Sure, it's a largeish patch but it is very safe: if it compiles, it works.
agreed.
> Could you please work that with Andreas?
sure, Andreas who?
> IS_RDONLY_INODE() is also used in intermezzo, but that doesn't compile any
> more anyway.
so I do not bother with that, but what about the nfs(d)
stuff?
TIA,
Herbert
Herbert Poetzl <[email protected]> wrote:
>
> > Could you please work that with Andreas?
>
> sure, Andreas who?
Andreas Gruenbacher <[email protected]>
> > IS_RDONLY_INODE() is also used in intermezzo, but that doesn't compile any
> > more anyway.
>
> so I do not bother with that, but what about the nfs(d)
> stuff?
er, what nfs stuff? Your patches only have IS_RDONLY_INODE() being used in
the ext2/3 xattr code and in intermezzo.
On Mon, Mar 15, 2004 at 03:31:53PM -0800, Andrew Morton wrote:
> Herbert Poetzl <[email protected]> wrote:
> >
> > > Could you please work that with Andreas?
> >
> > sure, Andreas who?
>
> Andreas Gruenbacher <[email protected]>
okay, will contact him ...
> > > IS_RDONLY_INODE() is also used in intermezzo, but that doesn't compile any
> > > more anyway.
> >
> > so I do not bother with that, but what about the nfs(d)
> > stuff?
> er, what nfs stuff? Your patches only have IS_RDONLY_INODE() being used in
> the ext2/3 xattr code and in intermezzo.
hmm, I guess nfsd_permission() can be considered nfs stuff,
but I'll look into that anyway, maybe Trond can help here ...
(patch-2.6.4-20040314_2308-bme0.04.1-ro3.diff 5/5)
best,
Herbert
On Mon, Mar 15, 2004 at 08:57:23AM +0100, Herbert Poetzl wrote:
> -void update_atime(struct inode *inode)
> +void update_atime(struct inode *inode, struct vfsmount *mnt)
_Hell_, no. Proper solution is to move the callers upstream instead
of propagating vfsmounts downstream. That, BTW, was the main reason
for readdir() patch.
BTW, update_atime() is exported. And it's 2.6 now...
On Mon, Mar 15, 2004 at 08:58:14AM +0100, Herbert Poetzl wrote:
> -extern int vfs_permission(struct inode *, int);
> +extern int vfs_permission(struct inode *, int, struct nameidata *);
Vetoed, along with IS_RDONLY() prototype change.
Note that you are doing exactly the opposite of the changes we'll need
to deal with remount races.
What we need is to push readonly checks _up_ - into callers of fs methods.
vfs_permission() is default ->permission() - no more, no less. Neither
it nor other instances have any business touching "this vfsmount is readonly"
logics - it's not something where fs can override stuff; it's "admin said
no r/w access here".
IOW, the check for r/w access to file/directory/symlink on a r/o mount should
be moved into the callers (very few of them) of ->permission() and away from
the methods themselves.
On Thu, Mar 18, 2004 at 12:16:50PM +0000, [email protected] wrote:
> On Mon, Mar 15, 2004 at 08:57:23AM +0100, Herbert Poetzl wrote:
> > -void update_atime(struct inode *inode)
> > +void update_atime(struct inode *inode, struct vfsmount *mnt)
Hi Alexander!
> _Hell_, no.
thanks for looking at the code ;)
> Proper solution is to move the callers upstream instead of
> propagating vfsmounts downstream. That, BTW, was the main reason
> for readdir() patch.
it that what you have in mind?
-? update_atime()
?-? __generic_file_aio_read() [done]
?
?-? autofs4_update_usage() [removed]
? ?-? autofs4_revalidate() [done]
? ?-? autofs4_root_revalidate() [done]
? ?-? try_to_fill_dentry() [done,NULL]
? '-? try_to_fill_dentry() [done,NULL]
?
?-? coda_readdir() [done]
?-? do_follow_link() [done]
?-? do_generic_mapping_read() [done]
?-? do_shmem_file_read() [done]
?
?-? generic_file_mmap() [done]
?-? hugetlbfs_file_mmap() [done]
?
?-? nfsd_readlink() [done]
?-? open_namei() [done]
?-? pipe_readv() [done]
?-? random_read() [done]
?-? shmem_mmap() [done]
?-? sys_readlink() [done]
?
?-? unix_find_other() [done,NULL]
?
'-? vfs_readdir() [done]
> BTW, update_atime() is exported. And it's 2.6 now...
patch is also available at:
http://www.13thfloor.at/patches/patch-2.6.5-rc1-bk3-bme0.04.2-atime.diff
best,
Herbert
diff -NurpP --minimal linux-2.6.5-rc1-bk3/drivers/char/random.c linux-2.6.5-rc1-bk3-bme0.04.2-atime/drivers/char/random.c
--- linux-2.6.5-rc1-bk3/drivers/char/random.c 2004-03-11 03:55:22.000000000 +0100
+++ linux-2.6.5-rc1-bk3-bme0.04.2-atime/drivers/char/random.c 2004-03-19 01:43:33.000000000 +0100
@@ -1640,9 +1640,9 @@ random_read(struct file * file, char * b
/*
* If we gave the user some bytes, update the access time.
*/
- if (count != 0) {
+ if ((count != 0) &&
+ may_update_atime(file->f_dentry->d_inode, file->f_vfsmnt))
update_atime(file->f_dentry->d_inode);
- }
return (count ? count : retval);
}
diff -NurpP --minimal linux-2.6.5-rc1-bk3/fs/autofs/root.c linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/autofs/root.c
--- linux-2.6.5-rc1-bk3/fs/autofs/root.c 2004-03-11 03:55:27.000000000 +0100
+++ linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/autofs/root.c 2004-03-19 01:17:58.000000000 +0100
@@ -129,8 +129,10 @@ static int try_to_fill_dentry(struct den
/* We don't update the usages for the autofs daemon itself, this
is necessary for recursive autofs mounts */
- if ( !autofs_oz_mode(sbi) ) {
+ if (!autofs_oz_mode(sbi)) {
autofs_update_usage(&sbi->dirhash,ent);
+ if (may_update_atime(dentry->d_inode, NULL))
+ update_atime(dentry->d_inode);
}
dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
diff -NurpP --minimal linux-2.6.5-rc1-bk3/fs/autofs4/root.c linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/autofs4/root.c
--- linux-2.6.5-rc1-bk3/fs/autofs4/root.c 2004-03-11 03:55:21.000000000 +0100
+++ linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/autofs4/root.c 2004-03-19 02:22:01.000000000 +0100
@@ -15,6 +15,8 @@
#include <linux/stat.h>
#include <linux/param.h>
#include <linux/time.h>
+#include <linux/fs.h>
+#include <linux/namei.h>
#include <linux/smp_lock.h>
#include "autofs_i.h"
@@ -60,10 +62,8 @@ static void autofs4_update_usage(struct
for(; dentry != top; dentry = dentry->d_parent) {
struct autofs_info *ino = autofs4_dentry_ino(dentry);
- if (ino) {
- update_atime(dentry->d_inode);
+ if (ino)
ino->last_used = jiffies;
- }
}
}
@@ -129,8 +129,11 @@ static int try_to_fill_dentry(struct den
/* We don't update the usages for the autofs daemon itself, this
is necessary for recursive autofs mounts */
- if (!autofs4_oz_mode(sbi))
+ if (!autofs4_oz_mode(sbi)) {
autofs4_update_usage(dentry);
+ if (may_update_atime(dentry->d_inode, NULL))
+ update_atime(dentry->d_inode);
+ }
dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
return 1;
@@ -177,9 +180,11 @@ static int autofs4_root_revalidate(struc
spin_unlock(&dcache_lock);
/* Update the usage list */
- if (!oz_mode)
+ if (!oz_mode) {
autofs4_update_usage(dentry);
-
+ if (may_update_atime(dentry->d_inode, nd->mnt))
+ update_atime(dentry->d_inode);
+ }
return 1;
}
@@ -187,9 +192,11 @@ static int autofs4_revalidate(struct den
{
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
- if (!autofs4_oz_mode(sbi))
+ if (!autofs4_oz_mode(sbi)) {
autofs4_update_usage(dentry);
-
+ if (may_update_atime(dentry->d_inode, nd->mnt))
+ update_atime(dentry->d_inode);
+ }
return 1;
}
diff -NurpP --minimal linux-2.6.5-rc1-bk3/fs/coda/dir.c linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/coda/dir.c
--- linux-2.6.5-rc1-bk3/fs/coda/dir.c 2004-03-16 10:21:19.000000000 +0100
+++ linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/coda/dir.c 2004-03-19 01:27:56.000000000 +0100
@@ -512,7 +512,8 @@ int coda_readdir(struct file *coda_file,
ret = -ENOENT;
if (!IS_DEADDIR(host_inode)) {
ret = host_file->f_op->readdir(host_file, filldir, dirent);
- update_atime(host_inode);
+ if (may_update_atime(host_inode, host_file->f_vfsmnt))
+ update_atime(host_inode);
}
}
out:
diff -NurpP --minimal linux-2.6.5-rc1-bk3/fs/hugetlbfs/inode.c linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/hugetlbfs/inode.c
--- linux-2.6.5-rc1-bk3/fs/hugetlbfs/inode.c 2004-03-18 22:49:57.000000000 +0100
+++ linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/hugetlbfs/inode.c 2004-03-19 01:34:21.000000000 +0100
@@ -62,7 +62,8 @@ static int hugetlbfs_file_mmap(struct fi
vma_len = (loff_t)(vma->vm_end - vma->vm_start);
down(&inode->i_sem);
- update_atime(inode);
+ if (may_update_atime(inode, file->f_vfsmnt))
+ update_atime(inode);
vma->vm_flags |= VM_HUGETLB | VM_RESERVED;
vma->vm_ops = &hugetlb_vm_ops;
ret = hugetlb_prefault(mapping, vma);
diff -NurpP --minimal linux-2.6.5-rc1-bk3/fs/inode.c linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/inode.c
--- linux-2.6.5-rc1-bk3/fs/inode.c 2004-03-16 10:21:19.000000000 +0100
+++ linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/inode.c 2004-03-19 02:31:59.000000000 +0100
@@ -1145,13 +1145,6 @@ void update_atime(struct inode *inode)
{
struct timespec now;
- if (IS_NOATIME(inode))
- return;
- if (IS_NODIRATIME(inode) && S_ISDIR(inode->i_mode))
- return;
- if (IS_RDONLY(inode))
- return;
-
now = current_kernel_time();
if (inode_times_differ(inode, &inode->i_atime, &now)) {
inode->i_atime = now;
diff -NurpP --minimal linux-2.6.5-rc1-bk3/fs/namei.c linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/namei.c
--- linux-2.6.5-rc1-bk3/fs/namei.c 2004-03-11 03:55:25.000000000 +0100
+++ linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/namei.c 2004-03-19 01:40:53.000000000 +0100
@@ -412,7 +412,8 @@ static inline int do_follow_link(struct
goto loop;
current->link_count++;
current->total_link_count++;
- update_atime(dentry->d_inode);
+ if (may_update_atime(dentry->d_inode, nd->mnt))
+ update_atime(dentry->d_inode);
err = dentry->d_inode->i_op->follow_link(dentry, nd);
current->link_count--;
return err;
@@ -1368,7 +1369,8 @@ do_link:
error = security_inode_follow_link(dentry, nd);
if (error)
goto exit_dput;
- update_atime(dentry->d_inode);
+ if (may_update_atime(dentry->d_inode, nd->mnt))
+ update_atime(dentry->d_inode);
error = dentry->d_inode->i_op->follow_link(dentry, nd);
dput(dentry);
if (error)
diff -NurpP --minimal linux-2.6.5-rc1-bk3/fs/namespace.c linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/namespace.c
--- linux-2.6.5-rc1-bk3/fs/namespace.c 2004-03-11 03:55:35.000000000 +0100
+++ linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/namespace.c 2004-03-19 02:48:01.000000000 +0100
@@ -206,37 +206,39 @@ 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" },
- { 0, NULL }
- };
- static struct proc_fs_info mnt_info[] = {
- { MNT_NOSUID, ",nosuid" },
- { MNT_NODEV, ",nodev" },
- { MNT_NOEXEC, ",noexec" },
- { 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);
+ 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);
@@ -522,11 +524,13 @@ out_unlock:
/*
* do loopback mount.
*/
-static int do_loopback(struct nameidata *nd, char *old_name, int recurse)
+static int do_loopback(struct nameidata *nd, char *old_name, unsigned long flags, int mnt_flags)
{
struct nameidata old_nd;
struct vfsmount *mnt = NULL;
+ int recurse = flags & MS_REC;
int err = mount_is_safe(nd);
+
if (err)
return err;
if (!old_name || !*old_name)
@@ -553,6 +557,7 @@ static int do_loopback(struct nameidata
spin_unlock(&vfsmount_lock);
} else
mntput(mnt);
+ mnt->mnt_flags = mnt_flags;
}
up_write(¤t->namespace->sem);
@@ -759,12 +764,18 @@ long do_mount(char * dev_name, char * di
((char *)data_page)[PAGE_SIZE - 1] = 0;
/* Separate the per-mountpoint flags */
+ if (flags & MS_RDONLY)
+ mnt_flags |= MNT_RDONLY;
if (flags & MS_NOSUID)
mnt_flags |= MNT_NOSUID;
if (flags & MS_NODEV)
mnt_flags |= MNT_NODEV;
if (flags & MS_NOEXEC)
mnt_flags |= MNT_NOEXEC;
+ if (flags & MS_NOATIME)
+ mnt_flags |= MNT_NOATIME;
+ if (flags & MS_NODIRATIME)
+ mnt_flags |= MNT_NODIRATIME;
flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV);
/* ... and get the mountpoint */
@@ -780,7 +791,7 @@ long do_mount(char * dev_name, char * di
retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
data_page);
else if (flags & MS_BIND)
- retval = do_loopback(&nd, dev_name, flags & MS_REC);
+ retval = do_loopback(&nd, dev_name, flags, mnt_flags);
else if (flags & MS_MOVE)
retval = do_move_mount(&nd, dev_name);
else
diff -NurpP --minimal linux-2.6.5-rc1-bk3/fs/nfsd/vfs.c linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/nfsd/vfs.c
--- linux-2.6.5-rc1-bk3/fs/nfsd/vfs.c 2004-03-11 03:55:26.000000000 +0100
+++ linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/nfsd/vfs.c 2004-03-19 02:27:08.000000000 +0100
@@ -1143,7 +1143,8 @@ nfsd_readlink(struct svc_rqst *rqstp, st
if (!inode->i_op || !inode->i_op->readlink)
goto out;
- update_atime(inode);
+ if (may_update_atime(inode, fhp->fh_export->ex_mnt))
+ update_atime(inode);
/* N.B. Why does this call need a get_fs()??
* Remove the set_fs and watch the fireworks:-) --okir
*/
diff -NurpP --minimal linux-2.6.5-rc1-bk3/fs/pipe.c linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/pipe.c
--- linux-2.6.5-rc1-bk3/fs/pipe.c 2004-03-11 03:55:28.000000000 +0100
+++ linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/pipe.c 2004-03-19 01:42:17.000000000 +0100
@@ -164,7 +164,8 @@ pipe_readv(struct file *filp, const stru
wake_up_interruptible(PIPE_WAIT(*inode));
kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
}
- if (ret > 0)
+ if ((ret > 0) &&
+ may_update_atime(inode, filp->f_vfsmnt))
update_atime(inode);
return ret;
}
diff -NurpP --minimal linux-2.6.5-rc1-bk3/fs/readdir.c linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/readdir.c
--- linux-2.6.5-rc1-bk3/fs/readdir.c 2004-03-16 10:21:20.000000000 +0100
+++ linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/readdir.c 2004-03-19 01:48:32.000000000 +0100
@@ -32,7 +32,8 @@ int vfs_readdir(struct file *file, filld
res = -ENOENT;
if (!IS_DEADDIR(inode)) {
res = file->f_op->readdir(file, buf, filler);
- update_atime(inode);
+ if (may_update_atime(inode, file->f_vfsmnt))
+ update_atime(inode);
}
up(&inode->i_sem);
out:
diff -NurpP --minimal linux-2.6.5-rc1-bk3/fs/stat.c linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/stat.c
--- linux-2.6.5-rc1-bk3/fs/stat.c 2004-03-11 03:55:23.000000000 +0100
+++ linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/stat.c 2004-03-19 01:45:44.000000000 +0100
@@ -272,7 +272,8 @@ asmlinkage long sys_readlink(const char
if (inode->i_op && inode->i_op->readlink) {
error = security_inode_readlink(nd.dentry);
if (!error) {
- update_atime(inode);
+ if (may_update_atime(inode, nd.mnt))
+ update_atime(inode);
error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
}
}
diff -NurpP --minimal linux-2.6.5-rc1-bk3/include/linux/fs.h linux-2.6.5-rc1-bk3-bme0.04.2-atime/include/linux/fs.h
--- linux-2.6.5-rc1-bk3/include/linux/fs.h 2004-03-16 10:21:20.000000000 +0100
+++ linux-2.6.5-rc1-bk3-bme0.04.2-atime/include/linux/fs.h 2004-03-19 02:33:01.000000000 +0100
@@ -19,6 +19,7 @@
#include <linux/cache.h>
#include <linux/radix-tree.h>
#include <linux/kobject.h>
+#include <linux/mount.h>
#include <asm/atomic.h>
struct iovec;
@@ -751,6 +753,22 @@ extern int vfs_rmdir(struct inode *, str
extern int vfs_unlink(struct inode *, struct dentry *);
extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
+static inline int may_update_atime(struct inode *inode, struct vfsmount *mnt)
+{
+ if (IS_RDONLY(inode) ||
+ (mnt && MNT_IS_RDONLY(mnt)))
+ return 0;
+ if (IS_NOATIME(inode) ||
+ (mnt && MNT_IS_NOATIME(mnt)))
+ return 0;
+ if (S_ISDIR(inode->i_mode) &&
+ (IS_NODIRATIME(inode) ||
+ (mnt && MNT_IS_NODIRATIME(mnt))))
+ return 0;
+ return 1;
+}
+
+
/*
* File types
*
diff -NurpP --minimal linux-2.6.5-rc1-bk3/include/linux/mount.h linux-2.6.5-rc1-bk3-bme0.04.2-atime/include/linux/mount.h
--- linux-2.6.5-rc1-bk3/include/linux/mount.h 2004-03-11 03:55:22.000000000 +0100
+++ linux-2.6.5-rc1-bk3-bme0.04.2-atime/include/linux/mount.h 2004-03-19 00:36:56.000000000 +0100
@@ -14,9 +14,12 @@
#include <linux/list.h>
-#define MNT_NOSUID 1
-#define MNT_NODEV 2
-#define MNT_NOEXEC 4
+#define MNT_RDONLY 1
+#define MNT_NOSUID 2
+#define MNT_NODEV 4
+#define MNT_NOEXEC 8
+#define MNT_NOATIME 1024
+#define MNT_NODIRATIME 2048
struct vfsmount
{
@@ -33,6 +36,10 @@ struct vfsmount
struct list_head mnt_list;
};
+#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 -NurpP --minimal linux-2.6.5-rc1-bk3/mm/filemap.c linux-2.6.5-rc1-bk3-bme0.04.2-atime/mm/filemap.c
--- linux-2.6.5-rc1-bk3/mm/filemap.c 2004-03-18 22:49:57.000000000 +0100
+++ linux-2.6.5-rc1-bk3-bme0.04.2-atime/mm/filemap.c 2004-03-19 02:11:00.000000000 +0100
@@ -21,6 +21,7 @@
#include <linux/mman.h>
#include <linux/pagemap.h>
#include <linux/file.h>
+#include <linux/mount.h>
#include <linux/uio.h>
#include <linux/hash.h>
#include <linux/writeback.h>
@@ -725,7 +726,8 @@ no_cached_page:
*ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
if (cached_page)
page_cache_release(cached_page);
- update_atime(inode);
+ if (may_update_atime(inode, filp->f_vfsmnt))
+ update_atime(inode);
}
EXPORT_SYMBOL(do_generic_mapping_read);
@@ -820,7 +822,8 @@ __generic_file_aio_read(struct kiocb *io
if (retval > 0)
*ppos = pos + retval;
}
- update_atime(filp->f_dentry->d_inode);
+ if (may_update_atime(filp->f_dentry->d_inode, filp->f_vfsmnt))
+ update_atime(filp->f_dentry->d_inode);
goto out;
}
@@ -1357,7 +1360,8 @@ int generic_file_mmap(struct file * file
if (!mapping->a_ops->readpage)
return -ENOEXEC;
- update_atime(inode);
+ if (may_update_atime(inode, file->f_vfsmnt))
+ update_atime(inode);
vma->vm_ops = &generic_file_vm_ops;
return 0;
}
diff -NurpP --minimal linux-2.6.5-rc1-bk3/mm/shmem.c linux-2.6.5-rc1-bk3-bme0.04.2-atime/mm/shmem.c
--- linux-2.6.5-rc1-bk3/mm/shmem.c 2004-03-11 03:55:26.000000000 +0100
+++ linux-2.6.5-rc1-bk3-bme0.04.2-atime/mm/shmem.c 2004-03-19 02:12:34.000000000 +0100
@@ -1067,7 +1067,8 @@ static int shmem_mmap(struct file *file,
ops = &shmem_vm_ops;
if (!S_ISREG(inode->i_mode))
return -EACCES;
- update_atime(inode);
+ if (may_update_atime(inode, file->f_vfsmnt))
+ update_atime(inode);
vma->vm_ops = ops;
return 0;
}
@@ -1363,7 +1364,8 @@ static void do_shmem_file_read(struct fi
}
*ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
- update_atime(inode);
+ if (may_update_atime(inode, filp->f_vfsmnt))
+ update_atime(inode);
}
static ssize_t shmem_file_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
diff -NurpP --minimal linux-2.6.5-rc1-bk3/net/unix/af_unix.c linux-2.6.5-rc1-bk3-bme0.04.2-atime/net/unix/af_unix.c
--- linux-2.6.5-rc1-bk3/net/unix/af_unix.c 2004-03-11 03:55:35.000000000 +0100
+++ linux-2.6.5-rc1-bk3-bme0.04.2-atime/net/unix/af_unix.c 2004-03-19 01:47:43.000000000 +0100
@@ -706,7 +706,7 @@ static struct sock *unix_find_other(stru
if (u) {
struct dentry *dentry;
dentry = unix_sk(u)->dentry;
- if (dentry)
+ if (dentry && may_update_atime(dentry->d_inode, NULL))
update_atime(dentry->d_inode);
} else
goto fail;
On Thu, Mar 18, 2004 at 12:26:45PM +0000, [email protected] wrote:
> On Mon, Mar 15, 2004 at 08:58:14AM +0100, Herbert Poetzl wrote:
> > -extern int vfs_permission(struct inode *, int);
> > +extern int vfs_permission(struct inode *, int, struct nameidata *);
>
> Vetoed, along with IS_RDONLY() prototype change.
hmm, that is what I expected ...
> Note that you are doing exactly the opposite of the changes we'll need
> to deal with remount races.
>
> What we need is to push readonly checks _up_ - into callers of fs methods.
> vfs_permission() is default ->permission() - no more, no less. Neither
> it nor other instances have any business touching "this vfsmount is readonly"
> logics - it's not something where fs can override stuff; it's "admin said
> no r/w access here".
>
> IOW, the check for r/w access to file/directory/symlink on a r/o mount should
> be moved into the callers (very few of them) of ->permission() and away from
> the methods themselves.
maybe like this ...
patch can be downloaded at:
http://www.13thfloor.at/patches/patch-2.6.5-rc1-bk3-bme0.04.2-permission.diff
best,
Herbert
diff -NurpP --minimal linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/ext2/acl.c linux-2.6.5-rc1-bk3-bme0.04.2-permission/fs/ext2/acl.c
--- linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/ext2/acl.c 2004-03-16 10:21:19.000000000 +0100
+++ linux-2.6.5-rc1-bk3-bme0.04.2-permission/fs/ext2/acl.c 2004-03-19 03:17:17.000000000 +0100
@@ -290,13 +290,6 @@ ext2_permission(struct inode *inode, int
{
int mode = inode->i_mode;
- /* Nobody gets write access to a read-only fs */
- if ((mask & MAY_WRITE) && IS_RDONLY(inode) &&
- (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
- return -EROFS;
- /* Nobody gets write access to an immutable file */
- if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode))
- return -EACCES;
if (current->fsuid == inode->i_uid) {
mode >>= 6;
} else if (test_opt(inode->i_sb, POSIX_ACL)) {
diff -NurpP --minimal linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/ext3/acl.c linux-2.6.5-rc1-bk3-bme0.04.2-permission/fs/ext3/acl.c
--- linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/ext3/acl.c 2004-03-16 10:21:19.000000000 +0100
+++ linux-2.6.5-rc1-bk3-bme0.04.2-permission/fs/ext3/acl.c 2004-03-19 03:17:28.000000000 +0100
@@ -295,13 +295,6 @@ ext3_permission(struct inode *inode, int
{
int mode = inode->i_mode;
- /* Nobody gets write access to a read-only fs */
- if ((mask & MAY_WRITE) && IS_RDONLY(inode) &&
- (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
- return -EROFS;
- /* Nobody gets write access to an immutable file */
- if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode))
- return -EACCES;
if (current->fsuid == inode->i_uid) {
mode >>= 6;
} else if (test_opt(inode->i_sb, POSIX_ACL)) {
diff -NurpP --minimal linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/intermezzo/dir.c linux-2.6.5-rc1-bk3-bme0.04.2-permission/fs/intermezzo/dir.c
--- linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/intermezzo/dir.c 2004-03-18 22:49:57.000000000 +0100
+++ linux-2.6.5-rc1-bk3-bme0.04.2-permission/fs/intermezzo/dir.c 2004-03-19 03:46:49.000000000 +0100
@@ -846,6 +846,16 @@ int presto_permission(struct inode *inod
cache = presto_get_cache(inode);
+ /* Nobody gets write access to a read-only fs */
+ if ((mask & MAY_WRITE) &&
+ (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) &&
+ (IS_RDONLY(inode) || (nd && MNT_IS_RDONLY(nd->mnt))))
+ return -EROFS;
+
+ /* Nobody gets write access to an immutable file */
+ if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode))
+ return -EACCES;
+
if ( cache ) {
/* we only override the file/dir permission operations */
struct inode_operations *fiops = filter_c2cfiops(cache->cache_filter);
diff -NurpP --minimal linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/jfs/acl.c linux-2.6.5-rc1-bk3-bme0.04.2-permission/fs/jfs/acl.c
--- linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/jfs/acl.c 2004-03-11 03:55:21.000000000 +0100
+++ linux-2.6.5-rc1-bk3-bme0.04.2-permission/fs/jfs/acl.c 2004-03-19 03:18:12.000000000 +0100
@@ -132,21 +132,6 @@ int jfs_permission(struct inode * inode,
umode_t mode = inode->i_mode;
struct jfs_inode_info *ji = JFS_IP(inode);
- if (mask & MAY_WRITE) {
- /*
- * Nobody gets write access to a read-only fs.
- */
- if (IS_RDONLY(inode) &&
- (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
- return -EROFS;
-
- /*
- * Nobody gets write access to an immutable file.
- */
- if (IS_IMMUTABLE(inode))
- return -EACCES;
- }
-
if (current->fsuid == inode->i_uid) {
mode >>= 6;
goto check_mode;
diff -NurpP --minimal linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/namei.c linux-2.6.5-rc1-bk3-bme0.04.2-permission/fs/namei.c
--- linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/namei.c 2004-03-19 01:40:53.000000000 +0100
+++ linux-2.6.5-rc1-bk3-bme0.04.2-permission/fs/namei.c 2004-03-19 03:43:38.000000000 +0100
@@ -160,21 +160,6 @@ int vfs_permission(struct inode * inode,
{
umode_t mode = inode->i_mode;
- if (mask & MAY_WRITE) {
- /*
- * Nobody gets write access to a read-only fs.
- */
- if (IS_RDONLY(inode) &&
- (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
- return -EROFS;
-
- /*
- * Nobody gets write access to an immutable file.
- */
- if (IS_IMMUTABLE(inode))
- return -EACCES;
- }
-
if (current->fsuid == inode->i_uid)
mode >>= 6;
else if (in_group_p(inode->i_gid))
@@ -207,9 +192,20 @@ int vfs_permission(struct inode * inode,
int permission(struct inode * inode,int mask, struct nameidata *nd)
{
+ int mode = inode->i_mode;
int retval;
int submask;
+ /* Nobody gets write access to a read-only fs */
+ if ((mask & MAY_WRITE) &&
+ (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) &&
+ (IS_RDONLY(inode) || (nd && MNT_IS_RDONLY(nd->mnt))))
+ return -EROFS;
+
+ /* Nobody gets write access to an immutable file */
+ if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode))
+ return -EACCES;
+
/* Ordinary permission routines do not understand MAY_APPEND. */
submask = mask & ~MAY_APPEND;
diff -NurpP --minimal linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/nfs/dir.c linux-2.6.5-rc1-bk3-bme0.04.2-permission/fs/nfs/dir.c
--- linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/nfs/dir.c 2004-03-16 10:21:20.000000000 +0100
+++ linux-2.6.5-rc1-bk3-bme0.04.2-permission/fs/nfs/dir.c 2004-03-19 03:36:11.000000000 +0100
@@ -1503,29 +1503,11 @@ nfs_permission(struct inode *inode, int
{
struct nfs_access_cache *cache = &NFS_I(inode)->cache_access;
struct rpc_cred *cred;
- int mode = inode->i_mode;
int res;
if (mask == 0)
return 0;
- if (mask & MAY_WRITE) {
- /*
- *
- * Nobody gets write access to a read-only fs.
- *
- */
- if (IS_RDONLY(inode) &&
- (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
- return -EROFS;
- /*
- *
- * Nobody gets write access to an immutable file.
- *
- */
- if (IS_IMMUTABLE(inode))
- return -EACCES;
- }
/* Are we checking permissions on anything other than lookup/execute? */
if ((mask & MAY_EXEC) == 0) {
/* We only need to check permissions on file open() and access() */
On Fri, Mar 19, 2004 at 03:52:36AM +0100, Herbert Poetzl wrote:
> @@ -846,6 +846,16 @@ int presto_permission(struct inode *inod
>
> cache = presto_get_cache(inode);
>
> + /* Nobody gets write access to a read-only fs */
> + if ((mask & MAY_WRITE) &&
> + (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) &&
> + (IS_RDONLY(inode) || (nd && MNT_IS_RDONLY(nd->mnt))))
> + return -EROFS;
> +
> + /* Nobody gets write access to an immutable file */
> + if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode))
> + return -EACCES;
> +
That is gratitious, since the only way presto_setattr() is ever called is
as ->permission().
> --- linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/jfs/acl.c 2004-03-11 03:55:21.000000000 +0100
> +++ linux-2.6.5-rc1-bk3-bme0.04.2-permission/fs/jfs/acl.c 2004-03-19 03:18:12.000000000 +0100
> @@ -132,21 +132,6 @@ int jfs_permission(struct inode * inode,
> umode_t mode = inode->i_mode;
> struct jfs_inode_info *ji = JFS_IP(inode);
>
> - if (mask & MAY_WRITE) {
> - /*
... and that is broken, since jfs_permission() can be called directly.
FWIW, I would start with
1) split out simple_permission() - vfs_permission() sans the
r/o checks; vfs_permission() would call it and all in-tree calls of
vfs_permission() would get expanded.
2) prove that all instances of ->permission() honour r/o checks.
Fix the broken ones (and yes, we do have them - e.g. hfs_permission()
or bogus return values in proc_permission()), after we'd shown that
it's safe. Note that it's not obvious - e.g. anything around ACLs or
<barf> XFS ioctls is not just fscking ugly - it's brittle as hell and
will require very careful treatment.
3) once that is done, put r/o checks into the beginning of
permission(9)
4) for all instances of ->permission(), move r/o checks in
the places that call that instance directly. Remove them from method
itself.
And yes, #2 will hurt. Badly.
BTW, IS_RDONLY() part of that stuff will really hit the fan when you start
touching the FPOS in fs/ext2/xattr.c and around it. Have fun...
Note that it's not enough to bring relevant vfsmount to every caller of
IS_RDONLY() - if we are calling it to make sure that fs is not r/o,
we _really_ want to make sure that it doesn't get remounted r/o just as
IS_RDONLY() returns. And yes, there are real bugs in that area.
On Fri, Mar 19, 2004 at 11:11:17AM +0000, [email protected] wrote:
> On Fri, Mar 19, 2004 at 03:52:36AM +0100, Herbert Poetzl wrote:
> > @@ -846,6 +846,16 @@ int presto_permission(struct inode *inod
> >
> > cache = presto_get_cache(inode);
> >
> > + /* Nobody gets write access to a read-only fs */
> > + if ((mask & MAY_WRITE) &&
> > + (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) &&
> > + (IS_RDONLY(inode) || (nd && MNT_IS_RDONLY(nd->mnt))))
> > + return -EROFS;
> > +
> > + /* Nobody gets write access to an immutable file */
> > + if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode))
> > + return -EACCES;
> > +
>
> That is gratitious, since the only way presto_setattr()
> is ever called is as ->permission().
you mean presto_permission(), and yes, so that can be removed
> > --- linux-2.6.5-rc1-bk3-bme0.04.2-atime/fs/jfs/acl.c 2004-03-11 03:55:21.000000000 +0100
> > +++ linux-2.6.5-rc1-bk3-bme0.04.2-permission/fs/jfs/acl.c 2004-03-19 03:18:12.000000000 +0100
> > @@ -132,21 +132,6 @@ int jfs_permission(struct inode * inode,
> > umode_t mode = inode->i_mode;
> > struct jfs_inode_info *ji = JFS_IP(inode);
> >
> > - if (mask & MAY_WRITE) {
> > - /*
>
> ... and that is broken, since jfs_permission() can be called directly.
incomplete, not broken ...
-? jfs_permission()
?-? can_get_xattr()
? '-? __jfs_getxattr()
? ?-? jfs_get_acl()
? ? ?-? jfs_acl_chmod()
? ? ? '-? jfs_setattr()
? ? ?
? ? ?-? jfs_init_acl()
? ? ? ?-? jfs_create()
? ? ? ?-? jfs_mkdir()
? ? ? ?-? jfs_mknod()
? ? ? '-? jfs_symlink()
? ? ?
? ? '-= jfs_permission()
? ?
? '-? jfs_getxattr()
?
'-? can_set_xattr()
'-? __jfs_setxattr()
?-? jfs_removexattr()
?-? jfs_set_acl()
? ?-= jfs_acl_chmod()
? '-= jfs_init_acl()
?
'-? jfs_setxattr()
the xattr struff needs attention anyway, and many
of the functions calling jfs_permission() directly or
indirectly will have the check at a higher layer ...
> FWIW, I would start with
> 1) split out simple_permission() - vfs_permission() sans the
> r/o checks; vfs_permission() would call it and all in-tree calls of
> vfs_permission() would get expanded.
-? vfs_permission()
?-? hfs_permission()
?-? hfsplus_permission()
?-? nfs_permission()
?-* permission()
?-? presto_permission()
'-? proc_permission()
please elaborate ...
> 2) prove that all instances of ->permission() honour r/o checks.
> Fix the broken ones (and yes, we do have them - e.g. hfs_permission()
> or bogus return values in proc_permission()), after we'd shown that
> it's safe. Note that it's not obvious - e.g. anything around ACLs or
> <barf> XFS ioctls is not just fscking ugly - it's brittle as hell and
> will require very careful treatment.
okay, but why not do it in permission(), and make
the few callers of vfs_permission use that one instead?
except for jfs_permission() and nfsd_permission()
(which is hell enough) there are no direct calls
of *_permission() ...
> 3) once that is done, put r/o checks into the beginning of
> permission(9)
hmm, obviously you didn't read the patch at all, as that
is exactly what I did, so please have a look at it ...
> 4) for all instances of ->permission(), move r/o checks in
> the places that call that instance directly. Remove them from method
> itself.
>
> And yes, #2 will hurt. Badly.
I don't see why, please enlighten me ...
> BTW, IS_RDONLY() part of that stuff will really hit the fan when you start
> touching the FPOS in fs/ext2/xattr.c and around it. Have fun...
>
> Note that it's not enough to bring relevant vfsmount to every caller of
> IS_RDONLY() - if we are calling it to make sure that fs is not r/o,
> we _really_ want to make sure that it doesn't get remounted r/o just as
> IS_RDONLY() returns. And yes, there are real bugs in that area.
hmm, well but how would moving the ro checks around
or adding them for the vfs mounts influence that?
I agree that this _is_ an issue but why should this _not_
happen with mount -o remount,ro /xy ?
best,
Herbert
On Fri, Mar 19, 2004 at 02:40:28PM +0100, Herbert Poetzl wrote:
> > FWIW, I would start with
> > 1) split out simple_permission() - vfs_permission() sans the
> > r/o checks; vfs_permission() would call it and all in-tree calls of
> > vfs_permission() would get expanded.
>
> -? vfs_permission()
> ?-? hfs_permission()
> ?-? hfsplus_permission()
> ?-? nfs_permission()
> ?-* permission()
> ?-? presto_permission()
> '-? proc_permission()
>
> please elaborate ...
First chunk: replace calls of vfs_permission() with r/o checks +
simple_permission(), _leaving_ vfs_permission() _itself_ _as-is_.
> > 2) prove that all instances of ->permission() honour r/o checks.
> > Fix the broken ones (and yes, we do have them - e.g. hfs_permission()
> > or bogus return values in proc_permission()), after we'd shown that
> > it's safe. Note that it's not obvious - e.g. anything around ACLs or
> > <barf> XFS ioctls is not just fscking ugly - it's brittle as hell and
> > will require very careful treatment.
>
> okay, but why not do it in permission(), and make
> the few callers of vfs_permission use that one instead?
Filesystem code might be calling permission(9) and expecting (broken)
behaviour from its own ->permission(). Switch to uniform behaviour
would break such places, forcing us to compensate there. And analysis
won't be fun.
> except for jfs_permission() and nfsd_permission()
> (which is hell enough) there are no direct calls
> of *_permission() ...
fs code calling permission() is basically equivalent to direct call.
> > 3) once that is done, put r/o checks into the beginning of
> > permission(9)
>
> hmm, obviously you didn't read the patch at all, as that
> is exactly what I did, so please have a look at it ...
Yes, I have read it. Try to read the reply - what I'm saying is that it
should be a separate chunk in the series _and_ it will need some preparations
before it can go in.
> > 4) for all instances of ->permission(), move r/o checks in
> > the places that call that instance directly. Remove them from method
> > itself.
> >
> > And yes, #2 will hurt. Badly.
>
> I don't see why, please enlighten me ...
See above.
> > BTW, IS_RDONLY() part of that stuff will really hit the fan when you start
> > touching the FPOS in fs/ext2/xattr.c and around it. Have fun...
> >
> > Note that it's not enough to bring relevant vfsmount to every caller of
> > IS_RDONLY() - if we are calling it to make sure that fs is not r/o,
> > we _really_ want to make sure that it doesn't get remounted r/o just as
> > IS_RDONLY() returns. And yes, there are real bugs in that area.
>
> hmm, well but how would moving the ro checks around
> or adding them for the vfs mounts influence that?
>
> I agree that this _is_ an issue but why should this _not_
> happen with mount -o remount,ro /xy ?
Once the checks are moved up, we split them into pairs (want_write_access(),
drop_write_access()) where the former can fail. Then the second call gets
moved past the call of fs method. IOW, we go from
start fs activity
deep in the bowels of fs code check for r/o and possibly fail
do the rest
to
check for r/o and possibly fail
do fs work
_and_ to
request write access and possibly fail
do fs work
drop write access
Transition between (2) and (3) is simple and relatively easy to verify
_IF_ the checks are lifted up. And result will give sane protection
for remount - switch to r/o would have to be atomic wrt requesting
write access and would fail if we had writers.
Note that per-mountpoint r/o will take pretty much the same amount of work -
propagating vfsmounts down to the IS_RDONLY checks only to have that reverted
when we lift the checks up would mean doing more or less the same twice.
It can be done and it can be merged gradually in small and simple chunks,
so that they could be (a) well-understood and (b) well-tested.
The way we split the series *does* matter - composition of these patches
will be large and will touch quite a few places (there's extra fun with
delayed writes - e.g. removal of last link in foo_unlink() will mean
extra request for write access, dropped when inode is finally deleted,
possibly hours after unlink(2) had returned). Doing that in one or even
3-4 patches would be insane even in 2.7; in 2.6 it's so out of question
that it's not even funny.
> I personally use it for a long time now and I really like it.
> Same here, I hope this functionality gets merged sooner rather then later.
yes, i think, that vanilla kernel realy miss such an thing. personaly i don't even would call it extension,
because it's just missing part of the kernel, which should be here from the begining of `bind` option. now behaving
of mount one_dir into_another -o bind,ro is a least missleading, because it just _silently_ ignores the read-only option mounting read write.
nobody would even assume, that it is mounted read write. bind mounting should just work like any other.
Albeiro
On Thu, Mar 18, 2004 at 12:16:50PM +0000, [email protected] wrote:
> On Mon, Mar 15, 2004 at 08:57:23AM +0100, Herbert Poetzl wrote:
> > -void update_atime(struct inode *inode)
> > +void update_atime(struct inode *inode, struct vfsmount *mnt)
>
> _Hell_, no. Proper solution is to move the callers upstream instead
> of propagating vfsmounts downstream. That, BTW, was the main reason
> for readdir() patch.
# 04/03/18 [email protected] 1.1795.6.4
# [PATCH] add touch_atime() helper
#
# Preparation for per-mountpoint noatime, nodiratime and later -
# per-mountpoint r/o. Depends on file_accessed() patch, should go after
# it.
#
# New helper - touch_atime(mnt, dentry). It's a wrapper for
# update_atime() and that's where all future per-mountpoint checks will
# go.
static inline void touch_atime(struct vfsmount *mnt, struct dentry *dentry)
{
/* per-mountpoint checks will go here */
update_atime(dentry->d_inode);
}
Hum, so that is what you call 'moving the callers upstream'
instead of 'propagating vfsmounts downstream' ...
best,
Herbert
> BTW, update_atime() is exported. And it's 2.6 now...
> -
> 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/