Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (22 commits) Fix the race between capifs remount and node creation Fix races around the access to ->s_options switch ufs directories to ufs_sync_file() Switch open_exec() and sys_uselib() to do_open_filp() Make open_exec() and sys_uselib() use may_open(), instead of duplicating its parts Reduce path_lookup() abuses Make checkpatch.pl shut up on fs/inode.c NULL noise in fs/super.c:kill_bdev_super() romfs: cleanup romfs_fs.h ROMFS: romfs_dev_read() error ignored fs: dcache fix LRU ordering ocfs2: Use nd_set_link(). Fix deadlock in ipathfs ->get_sb() Fix a leak in failure exit in 9p ->get_sb() Convert obvious places to deactivate_locked_super() New helper: deactivate_locked_super() reiserfs: remove privroot hiding in lookup reiserfs: dont associate security.* with xattr files reiserfs: fixup xattr_root caching Always lookup priv_root on reiserfs mount and keep it ...
This commit is contained in:
Коммит
93b49d45eb
|
@ -347,7 +347,7 @@ static int ipathfs_fill_super(struct super_block *sb, void *data,
|
||||||
spin_unlock_irqrestore(&ipath_devs_lock, flags);
|
spin_unlock_irqrestore(&ipath_devs_lock, flags);
|
||||||
ret = create_device_files(sb, dd);
|
ret = create_device_files(sb, dd);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
deactivate_super(sb);
|
deactivate_locked_super(sb);
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
spin_lock_irqsave(&ipath_devs_lock, flags);
|
spin_lock_irqsave(&ipath_devs_lock, flags);
|
||||||
|
|
|
@ -75,15 +75,17 @@ static int capifs_remount(struct super_block *s, int *flags, char *data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(s->s_options);
|
mutex_lock(&s->s_root->d_inode->i_mutex);
|
||||||
s->s_options = new_opt;
|
|
||||||
|
|
||||||
|
replace_mount_options(s, new_opt);
|
||||||
config.setuid = setuid;
|
config.setuid = setuid;
|
||||||
config.setgid = setgid;
|
config.setgid = setgid;
|
||||||
config.uid = uid;
|
config.uid = uid;
|
||||||
config.gid = gid;
|
config.gid = gid;
|
||||||
config.mode = mode;
|
config.mode = mode;
|
||||||
|
|
||||||
|
mutex_unlock(&s->s_root->d_inode->i_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,13 +156,16 @@ void capifs_new_ncci(unsigned int number, dev_t device)
|
||||||
if (!inode)
|
if (!inode)
|
||||||
return;
|
return;
|
||||||
inode->i_ino = number+2;
|
inode->i_ino = number+2;
|
||||||
|
|
||||||
|
dentry = get_node(number);
|
||||||
|
|
||||||
|
/* config contents is protected by root's i_mutex */
|
||||||
inode->i_uid = config.setuid ? config.uid : current_fsuid();
|
inode->i_uid = config.setuid ? config.uid : current_fsuid();
|
||||||
inode->i_gid = config.setgid ? config.gid : current_fsgid();
|
inode->i_gid = config.setgid ? config.gid : current_fsgid();
|
||||||
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
|
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
|
||||||
init_special_inode(inode, S_IFCHR|config.mode, device);
|
init_special_inode(inode, S_IFCHR|config.mode, device);
|
||||||
//inode->i_op = &capifs_file_inode_operations;
|
//inode->i_op = &capifs_file_inode_operations;
|
||||||
|
|
||||||
dentry = get_node(number);
|
|
||||||
if (!IS_ERR(dentry) && !dentry->d_inode)
|
if (!IS_ERR(dentry) && !dentry->d_inode)
|
||||||
d_instantiate(dentry, inode);
|
d_instantiate(dentry, inode);
|
||||||
mutex_unlock(&capifs_root->d_inode->i_mutex);
|
mutex_unlock(&capifs_root->d_inode->i_mutex);
|
||||||
|
|
|
@ -74,8 +74,7 @@ static int get_sb_mtd_aux(struct file_system_type *fs_type, int flags,
|
||||||
|
|
||||||
ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
|
ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
up_write(&sb->s_umount);
|
deactivate_locked_super(sb);
|
||||||
deactivate_super(sb);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -173,26 +173,26 @@ static const struct file_operations osd_fops = {
|
||||||
.unlocked_ioctl = osd_uld_ioctl,
|
.unlocked_ioctl = osd_uld_ioctl,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct osd_dev *osduld_path_lookup(const char *path)
|
struct osd_dev *osduld_path_lookup(const char *name)
|
||||||
{
|
{
|
||||||
struct nameidata nd;
|
struct path path;
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
struct cdev *cdev;
|
struct cdev *cdev;
|
||||||
struct osd_uld_device *uninitialized_var(oud);
|
struct osd_uld_device *uninitialized_var(oud);
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (!path || !*path) {
|
if (!name || !*name) {
|
||||||
OSD_ERR("Mount with !path || !*path\n");
|
OSD_ERR("Mount with !path || !*path\n");
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
error = path_lookup(path, LOOKUP_FOLLOW, &nd);
|
error = kern_path(name, LOOKUP_FOLLOW, &path);
|
||||||
if (error) {
|
if (error) {
|
||||||
OSD_ERR("path_lookup of %s faild=>%d\n", path, error);
|
OSD_ERR("path_lookup of %s failed=>%d\n", name, error);
|
||||||
return ERR_PTR(error);
|
return ERR_PTR(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
inode = nd.path.dentry->d_inode;
|
inode = path.dentry->d_inode;
|
||||||
error = -EINVAL; /* Not the right device e.g osd_uld_device */
|
error = -EINVAL; /* Not the right device e.g osd_uld_device */
|
||||||
if (!S_ISCHR(inode->i_mode)) {
|
if (!S_ISCHR(inode->i_mode)) {
|
||||||
OSD_DEBUG("!S_ISCHR()\n");
|
OSD_DEBUG("!S_ISCHR()\n");
|
||||||
|
@ -202,15 +202,15 @@ struct osd_dev *osduld_path_lookup(const char *path)
|
||||||
cdev = inode->i_cdev;
|
cdev = inode->i_cdev;
|
||||||
if (!cdev) {
|
if (!cdev) {
|
||||||
OSD_ERR("Before mounting an OSD Based filesystem\n");
|
OSD_ERR("Before mounting an OSD Based filesystem\n");
|
||||||
OSD_ERR(" user-mode must open+close the %s device\n", path);
|
OSD_ERR(" user-mode must open+close the %s device\n", name);
|
||||||
OSD_ERR(" Example: bash: echo < %s\n", path);
|
OSD_ERR(" Example: bash: echo < %s\n", name);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The Magic wand. Is it our char-dev */
|
/* The Magic wand. Is it our char-dev */
|
||||||
/* TODO: Support sg devices */
|
/* TODO: Support sg devices */
|
||||||
if (cdev->owner != THIS_MODULE) {
|
if (cdev->owner != THIS_MODULE) {
|
||||||
OSD_ERR("Error mounting %s - is not an OSD device\n", path);
|
OSD_ERR("Error mounting %s - is not an OSD device\n", name);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ struct osd_dev *osduld_path_lookup(const char *path)
|
||||||
error = 0;
|
error = 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
path_put(&nd.path);
|
path_put(&path);
|
||||||
return error ? ERR_PTR(error) : &oud->od;
|
return error ? ERR_PTR(error) : &oud->od;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(osduld_path_lookup);
|
EXPORT_SYMBOL(osduld_path_lookup);
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include <linux/mount.h>
|
#include <linux/mount.h>
|
||||||
#include <linux/idr.h>
|
#include <linux/idr.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
#include <linux/smp_lock.h>
|
||||||
#include <net/9p/9p.h>
|
#include <net/9p/9p.h>
|
||||||
#include <net/9p/client.h>
|
#include <net/9p/client.h>
|
||||||
|
|
||||||
|
@ -155,6 +156,7 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
|
||||||
|
|
||||||
root = d_alloc_root(inode);
|
root = d_alloc_root(inode);
|
||||||
if (!root) {
|
if (!root) {
|
||||||
|
iput(inode);
|
||||||
retval = -ENOMEM;
|
retval = -ENOMEM;
|
||||||
goto release_sb;
|
goto release_sb;
|
||||||
}
|
}
|
||||||
|
@ -173,10 +175,7 @@ P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
release_sb:
|
release_sb:
|
||||||
if (sb) {
|
deactivate_locked_super(sb);
|
||||||
up_write(&sb->s_umount);
|
|
||||||
deactivate_super(sb);
|
|
||||||
}
|
|
||||||
|
|
||||||
free_stat:
|
free_stat:
|
||||||
kfree(st);
|
kfree(st);
|
||||||
|
@ -230,9 +229,12 @@ static int v9fs_show_options(struct seq_file *m, struct vfsmount *mnt)
|
||||||
static void
|
static void
|
||||||
v9fs_umount_begin(struct super_block *sb)
|
v9fs_umount_begin(struct super_block *sb)
|
||||||
{
|
{
|
||||||
struct v9fs_session_info *v9ses = sb->s_fs_info;
|
struct v9fs_session_info *v9ses;
|
||||||
|
|
||||||
|
lock_kernel();
|
||||||
|
v9ses = sb->s_fs_info;
|
||||||
v9fs_session_cancel(v9ses);
|
v9fs_session_cancel(v9ses);
|
||||||
|
unlock_kernel();
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct super_operations v9fs_super_ops = {
|
static const struct super_operations v9fs_super_ops = {
|
||||||
|
|
|
@ -507,8 +507,7 @@ affs_remount(struct super_block *sb, int *flags, char *data)
|
||||||
kfree(new_opts);
|
kfree(new_opts);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
kfree(sb->s_options);
|
replace_mount_options(sb, new_opts);
|
||||||
sb->s_options = new_opts;
|
|
||||||
|
|
||||||
sbi->s_flags = mount_flags;
|
sbi->s_flags = mount_flags;
|
||||||
sbi->s_mode = mode;
|
sbi->s_mode = mode;
|
||||||
|
|
|
@ -405,21 +405,20 @@ static int afs_get_sb(struct file_system_type *fs_type,
|
||||||
sb->s_flags = flags;
|
sb->s_flags = flags;
|
||||||
ret = afs_fill_super(sb, ¶ms);
|
ret = afs_fill_super(sb, ¶ms);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
up_write(&sb->s_umount);
|
deactivate_locked_super(sb);
|
||||||
deactivate_super(sb);
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
sb->s_options = new_opts;
|
save_mount_options(sb, new_opts);
|
||||||
sb->s_flags |= MS_ACTIVE;
|
sb->s_flags |= MS_ACTIVE;
|
||||||
} else {
|
} else {
|
||||||
_debug("reuse");
|
_debug("reuse");
|
||||||
kfree(new_opts);
|
|
||||||
ASSERTCMP(sb->s_flags, &, MS_ACTIVE);
|
ASSERTCMP(sb->s_flags, &, MS_ACTIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
simple_set_mnt(mnt, sb);
|
simple_set_mnt(mnt, sb);
|
||||||
afs_put_volume(params.volume);
|
afs_put_volume(params.volume);
|
||||||
afs_put_cell(params.cell);
|
afs_put_cell(params.cell);
|
||||||
|
kfree(new_opts);
|
||||||
_leave(" = 0 [%p]", sb);
|
_leave(" = 0 [%p]", sb);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -502,8 +502,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags,
|
||||||
|
|
||||||
if (s->s_root) {
|
if (s->s_root) {
|
||||||
if ((flags ^ s->s_flags) & MS_RDONLY) {
|
if ((flags ^ s->s_flags) & MS_RDONLY) {
|
||||||
up_write(&s->s_umount);
|
deactivate_locked_super(s);
|
||||||
deactivate_super(s);
|
|
||||||
error = -EBUSY;
|
error = -EBUSY;
|
||||||
goto error_close_devices;
|
goto error_close_devices;
|
||||||
}
|
}
|
||||||
|
@ -517,8 +516,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags,
|
||||||
error = btrfs_fill_super(s, fs_devices, data,
|
error = btrfs_fill_super(s, fs_devices, data,
|
||||||
flags & MS_SILENT ? 1 : 0);
|
flags & MS_SILENT ? 1 : 0);
|
||||||
if (error) {
|
if (error) {
|
||||||
up_write(&s->s_umount);
|
deactivate_locked_super(s);
|
||||||
deactivate_super(s);
|
|
||||||
goto error_free_subvol_name;
|
goto error_free_subvol_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -535,15 +533,13 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags,
|
||||||
mutex_unlock(&s->s_root->d_inode->i_mutex);
|
mutex_unlock(&s->s_root->d_inode->i_mutex);
|
||||||
|
|
||||||
if (IS_ERR(root)) {
|
if (IS_ERR(root)) {
|
||||||
up_write(&s->s_umount);
|
deactivate_locked_super(s);
|
||||||
deactivate_super(s);
|
|
||||||
error = PTR_ERR(root);
|
error = PTR_ERR(root);
|
||||||
goto error_free_subvol_name;
|
goto error_free_subvol_name;
|
||||||
}
|
}
|
||||||
if (!root->d_inode) {
|
if (!root->d_inode) {
|
||||||
dput(root);
|
dput(root);
|
||||||
up_write(&s->s_umount);
|
deactivate_locked_super(s);
|
||||||
deactivate_super(s);
|
|
||||||
error = -ENXIO;
|
error = -ENXIO;
|
||||||
goto error_free_subvol_name;
|
goto error_free_subvol_name;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/kthread.h>
|
#include <linux/kthread.h>
|
||||||
#include <linux/freezer.h>
|
#include <linux/freezer.h>
|
||||||
|
#include <linux/smp_lock.h>
|
||||||
#include "cifsfs.h"
|
#include "cifsfs.h"
|
||||||
#include "cifspdu.h"
|
#include "cifspdu.h"
|
||||||
#define DECLARE_GLOBALS_HERE
|
#define DECLARE_GLOBALS_HERE
|
||||||
|
@ -530,6 +531,7 @@ static void cifs_umount_begin(struct super_block *sb)
|
||||||
if (tcon == NULL)
|
if (tcon == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
lock_kernel();
|
||||||
read_lock(&cifs_tcp_ses_lock);
|
read_lock(&cifs_tcp_ses_lock);
|
||||||
if (tcon->tc_count == 1)
|
if (tcon->tc_count == 1)
|
||||||
tcon->tidStatus = CifsExiting;
|
tcon->tidStatus = CifsExiting;
|
||||||
|
@ -548,6 +550,7 @@ static void cifs_umount_begin(struct super_block *sb)
|
||||||
}
|
}
|
||||||
/* BB FIXME - finish add checks for tidStatus BB */
|
/* BB FIXME - finish add checks for tidStatus BB */
|
||||||
|
|
||||||
|
unlock_kernel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,8 +602,7 @@ cifs_get_sb(struct file_system_type *fs_type,
|
||||||
|
|
||||||
rc = cifs_read_super(sb, data, dev_name, flags & MS_SILENT ? 1 : 0);
|
rc = cifs_read_super(sb, data, dev_name, flags & MS_SILENT ? 1 : 0);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
up_write(&sb->s_umount);
|
deactivate_locked_super(sb);
|
||||||
deactivate_super(sb);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
sb->s_flags |= MS_ACTIVE;
|
sb->s_flags |= MS_ACTIVE;
|
||||||
|
|
|
@ -481,7 +481,7 @@ restart:
|
||||||
if ((flags & DCACHE_REFERENCED)
|
if ((flags & DCACHE_REFERENCED)
|
||||||
&& (dentry->d_flags & DCACHE_REFERENCED)) {
|
&& (dentry->d_flags & DCACHE_REFERENCED)) {
|
||||||
dentry->d_flags &= ~DCACHE_REFERENCED;
|
dentry->d_flags &= ~DCACHE_REFERENCED;
|
||||||
list_move_tail(&dentry->d_lru, &referenced);
|
list_move(&dentry->d_lru, &referenced);
|
||||||
spin_unlock(&dentry->d_lock);
|
spin_unlock(&dentry->d_lock);
|
||||||
} else {
|
} else {
|
||||||
list_move_tail(&dentry->d_lru, &tmp);
|
list_move_tail(&dentry->d_lru, &tmp);
|
||||||
|
|
|
@ -389,11 +389,10 @@ static int devpts_get_sb(struct file_system_type *fs_type,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_dput:
|
out_dput:
|
||||||
dput(s->s_root);
|
dput(s->s_root); /* undo dget() in simple_set_mnt() */
|
||||||
|
|
||||||
out_undo_sget:
|
out_undo_sget:
|
||||||
up_write(&s->s_umount);
|
deactivate_locked_super(s);
|
||||||
deactivate_super(s);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -614,9 +614,8 @@ static int ecryptfs_get_sb(struct file_system_type *fs_type, int flags,
|
||||||
}
|
}
|
||||||
goto out;
|
goto out;
|
||||||
out_abort:
|
out_abort:
|
||||||
dput(sb->s_root);
|
dput(sb->s_root); /* aka mnt->mnt_root, as set by get_sb_nodev() */
|
||||||
up_write(&sb->s_umount);
|
deactivate_locked_super(sb);
|
||||||
deactivate_super(sb);
|
|
||||||
out:
|
out:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
83
fs/exec.c
83
fs/exec.c
|
@ -105,40 +105,28 @@ static inline void put_binfmt(struct linux_binfmt * fmt)
|
||||||
SYSCALL_DEFINE1(uselib, const char __user *, library)
|
SYSCALL_DEFINE1(uselib, const char __user *, library)
|
||||||
{
|
{
|
||||||
struct file *file;
|
struct file *file;
|
||||||
struct nameidata nd;
|
|
||||||
char *tmp = getname(library);
|
char *tmp = getname(library);
|
||||||
int error = PTR_ERR(tmp);
|
int error = PTR_ERR(tmp);
|
||||||
|
|
||||||
if (!IS_ERR(tmp)) {
|
if (IS_ERR(tmp))
|
||||||
error = path_lookup_open(AT_FDCWD, tmp,
|
|
||||||
LOOKUP_FOLLOW, &nd,
|
|
||||||
FMODE_READ|FMODE_EXEC);
|
|
||||||
putname(tmp);
|
|
||||||
}
|
|
||||||
if (error)
|
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
error = -EINVAL;
|
file = do_filp_open(AT_FDCWD, tmp,
|
||||||
if (!S_ISREG(nd.path.dentry->d_inode->i_mode))
|
O_LARGEFILE | O_RDONLY | FMODE_EXEC, 0,
|
||||||
goto exit;
|
MAY_READ | MAY_EXEC | MAY_OPEN);
|
||||||
|
putname(tmp);
|
||||||
error = -EACCES;
|
|
||||||
if (nd.path.mnt->mnt_flags & MNT_NOEXEC)
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
error = inode_permission(nd.path.dentry->d_inode,
|
|
||||||
MAY_READ | MAY_EXEC | MAY_OPEN);
|
|
||||||
if (error)
|
|
||||||
goto exit;
|
|
||||||
error = ima_path_check(&nd.path, MAY_READ | MAY_EXEC | MAY_OPEN);
|
|
||||||
if (error)
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE);
|
|
||||||
error = PTR_ERR(file);
|
error = PTR_ERR(file);
|
||||||
if (IS_ERR(file))
|
if (IS_ERR(file))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
error = -EINVAL;
|
||||||
|
if (!S_ISREG(file->f_path.dentry->d_inode->i_mode))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
error = -EACCES;
|
||||||
|
if (file->f_path.mnt->mnt_flags & MNT_NOEXEC)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
fsnotify_open(file->f_path.dentry);
|
fsnotify_open(file->f_path.dentry);
|
||||||
|
|
||||||
error = -ENOEXEC;
|
error = -ENOEXEC;
|
||||||
|
@ -160,13 +148,10 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
|
||||||
}
|
}
|
||||||
read_unlock(&binfmt_lock);
|
read_unlock(&binfmt_lock);
|
||||||
}
|
}
|
||||||
|
exit:
|
||||||
fput(file);
|
fput(file);
|
||||||
out:
|
out:
|
||||||
return error;
|
return error;
|
||||||
exit:
|
|
||||||
release_open_intent(&nd);
|
|
||||||
path_put(&nd.path);
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_MMU
|
#ifdef CONFIG_MMU
|
||||||
|
@ -661,47 +646,33 @@ EXPORT_SYMBOL(setup_arg_pages);
|
||||||
|
|
||||||
struct file *open_exec(const char *name)
|
struct file *open_exec(const char *name)
|
||||||
{
|
{
|
||||||
struct nameidata nd;
|
|
||||||
struct file *file;
|
struct file *file;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd,
|
file = do_filp_open(AT_FDCWD, name,
|
||||||
FMODE_READ|FMODE_EXEC);
|
O_LARGEFILE | O_RDONLY | FMODE_EXEC, 0,
|
||||||
if (err)
|
MAY_EXEC | MAY_OPEN);
|
||||||
|
if (IS_ERR(file))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
err = -EACCES;
|
err = -EACCES;
|
||||||
if (!S_ISREG(nd.path.dentry->d_inode->i_mode))
|
if (!S_ISREG(file->f_path.dentry->d_inode->i_mode))
|
||||||
goto out_path_put;
|
goto exit;
|
||||||
|
|
||||||
if (nd.path.mnt->mnt_flags & MNT_NOEXEC)
|
if (file->f_path.mnt->mnt_flags & MNT_NOEXEC)
|
||||||
goto out_path_put;
|
goto exit;
|
||||||
|
|
||||||
err = inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_OPEN);
|
|
||||||
if (err)
|
|
||||||
goto out_path_put;
|
|
||||||
err = ima_path_check(&nd.path, MAY_EXEC | MAY_OPEN);
|
|
||||||
if (err)
|
|
||||||
goto out_path_put;
|
|
||||||
|
|
||||||
file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE);
|
|
||||||
if (IS_ERR(file))
|
|
||||||
return file;
|
|
||||||
|
|
||||||
fsnotify_open(file->f_path.dentry);
|
fsnotify_open(file->f_path.dentry);
|
||||||
|
|
||||||
err = deny_write_access(file);
|
err = deny_write_access(file);
|
||||||
if (err) {
|
if (err)
|
||||||
fput(file);
|
goto exit;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
out:
|
||||||
return file;
|
return file;
|
||||||
|
|
||||||
out_path_put:
|
exit:
|
||||||
release_open_intent(&nd);
|
fput(file);
|
||||||
path_put(&nd.path);
|
|
||||||
out:
|
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(open_exec);
|
EXPORT_SYMBOL(open_exec);
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/exportfs.h>
|
#include <linux/exportfs.h>
|
||||||
|
#include <linux/smp_lock.h>
|
||||||
|
|
||||||
MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
|
MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
|
||||||
MODULE_DESCRIPTION("Filesystem in Userspace");
|
MODULE_DESCRIPTION("Filesystem in Userspace");
|
||||||
|
@ -259,7 +260,9 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
|
||||||
|
|
||||||
static void fuse_umount_begin(struct super_block *sb)
|
static void fuse_umount_begin(struct super_block *sb)
|
||||||
{
|
{
|
||||||
|
lock_kernel();
|
||||||
fuse_abort_conn(get_fuse_conn_super(sb));
|
fuse_abort_conn(get_fuse_conn_super(sb));
|
||||||
|
unlock_kernel();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fuse_send_destroy(struct fuse_conn *fc)
|
static void fuse_send_destroy(struct fuse_conn *fc)
|
||||||
|
|
|
@ -1282,21 +1282,21 @@ static int gfs2_get_sb(struct file_system_type *fs_type, int flags,
|
||||||
static struct super_block *get_gfs2_sb(const char *dev_name)
|
static struct super_block *get_gfs2_sb(const char *dev_name)
|
||||||
{
|
{
|
||||||
struct super_block *sb;
|
struct super_block *sb;
|
||||||
struct nameidata nd;
|
struct path path;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
error = path_lookup(dev_name, LOOKUP_FOLLOW, &nd);
|
error = kern_path(dev_name, LOOKUP_FOLLOW, &path);
|
||||||
if (error) {
|
if (error) {
|
||||||
printk(KERN_WARNING "GFS2: path_lookup on %s returned error %d\n",
|
printk(KERN_WARNING "GFS2: path_lookup on %s returned error %d\n",
|
||||||
dev_name, error);
|
dev_name, error);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
sb = nd.path.dentry->d_inode->i_sb;
|
sb = path.dentry->d_inode->i_sb;
|
||||||
if (sb && (sb->s_type == &gfs2_fs_type))
|
if (sb && (sb->s_type == &gfs2_fs_type))
|
||||||
atomic_inc(&sb->s_active);
|
atomic_inc(&sb->s_active);
|
||||||
else
|
else
|
||||||
sb = NULL;
|
sb = NULL;
|
||||||
path_put(&nd.path);
|
path_put(&path);
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -423,8 +423,7 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
|
||||||
|
|
||||||
if (!(*flags & MS_RDONLY)) mark_dirty(s);
|
if (!(*flags & MS_RDONLY)) mark_dirty(s);
|
||||||
|
|
||||||
kfree(s->s_options);
|
replace_mount_options(s, new_opts);
|
||||||
s->s_options = new_opts;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
81
fs/inode.c
81
fs/inode.c
|
@ -99,7 +99,7 @@ static DEFINE_MUTEX(iprune_mutex);
|
||||||
*/
|
*/
|
||||||
struct inodes_stat_t inodes_stat;
|
struct inodes_stat_t inodes_stat;
|
||||||
|
|
||||||
static struct kmem_cache * inode_cachep __read_mostly;
|
static struct kmem_cache *inode_cachep __read_mostly;
|
||||||
|
|
||||||
static void wake_up_inode(struct inode *inode)
|
static void wake_up_inode(struct inode *inode)
|
||||||
{
|
{
|
||||||
|
@ -124,7 +124,7 @@ struct inode *inode_init_always(struct super_block *sb, struct inode *inode)
|
||||||
static struct inode_operations empty_iops;
|
static struct inode_operations empty_iops;
|
||||||
static const struct file_operations empty_fops;
|
static const struct file_operations empty_fops;
|
||||||
|
|
||||||
struct address_space * const mapping = &inode->i_data;
|
struct address_space *const mapping = &inode->i_data;
|
||||||
|
|
||||||
inode->i_sb = sb;
|
inode->i_sb = sb;
|
||||||
inode->i_blkbits = sb->s_blocksize_bits;
|
inode->i_blkbits = sb->s_blocksize_bits;
|
||||||
|
@ -216,7 +216,7 @@ static struct inode *alloc_inode(struct super_block *sb)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy_inode(struct inode *inode)
|
void destroy_inode(struct inode *inode)
|
||||||
{
|
{
|
||||||
BUG_ON(inode_has_buffers(inode));
|
BUG_ON(inode_has_buffers(inode));
|
||||||
security_inode_free(inode);
|
security_inode_free(inode);
|
||||||
|
@ -252,12 +252,11 @@ void inode_init_once(struct inode *inode)
|
||||||
mutex_init(&inode->inotify_mutex);
|
mutex_init(&inode->inotify_mutex);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(inode_init_once);
|
EXPORT_SYMBOL(inode_init_once);
|
||||||
|
|
||||||
static void init_once(void *foo)
|
static void init_once(void *foo)
|
||||||
{
|
{
|
||||||
struct inode * inode = (struct inode *) foo;
|
struct inode *inode = (struct inode *) foo;
|
||||||
|
|
||||||
inode_init_once(inode);
|
inode_init_once(inode);
|
||||||
}
|
}
|
||||||
|
@ -265,7 +264,7 @@ static void init_once(void *foo)
|
||||||
/*
|
/*
|
||||||
* inode_lock must be held
|
* inode_lock must be held
|
||||||
*/
|
*/
|
||||||
void __iget(struct inode * inode)
|
void __iget(struct inode *inode)
|
||||||
{
|
{
|
||||||
if (atomic_read(&inode->i_count)) {
|
if (atomic_read(&inode->i_count)) {
|
||||||
atomic_inc(&inode->i_count);
|
atomic_inc(&inode->i_count);
|
||||||
|
@ -289,7 +288,7 @@ void clear_inode(struct inode *inode)
|
||||||
{
|
{
|
||||||
might_sleep();
|
might_sleep();
|
||||||
invalidate_inode_buffers(inode);
|
invalidate_inode_buffers(inode);
|
||||||
|
|
||||||
BUG_ON(inode->i_data.nrpages);
|
BUG_ON(inode->i_data.nrpages);
|
||||||
BUG_ON(!(inode->i_state & I_FREEING));
|
BUG_ON(!(inode->i_state & I_FREEING));
|
||||||
BUG_ON(inode->i_state & I_CLEAR);
|
BUG_ON(inode->i_state & I_CLEAR);
|
||||||
|
@ -303,7 +302,6 @@ void clear_inode(struct inode *inode)
|
||||||
cd_forget(inode);
|
cd_forget(inode);
|
||||||
inode->i_state = I_CLEAR;
|
inode->i_state = I_CLEAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(clear_inode);
|
EXPORT_SYMBOL(clear_inode);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -351,8 +349,8 @@ static int invalidate_list(struct list_head *head, struct list_head *dispose)
|
||||||
|
|
||||||
next = head->next;
|
next = head->next;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
struct list_head * tmp = next;
|
struct list_head *tmp = next;
|
||||||
struct inode * inode;
|
struct inode *inode;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We can reschedule here without worrying about the list's
|
* We can reschedule here without worrying about the list's
|
||||||
|
@ -391,7 +389,7 @@ static int invalidate_list(struct list_head *head, struct list_head *dispose)
|
||||||
* fails because there are busy inodes then a non zero value is returned.
|
* fails because there are busy inodes then a non zero value is returned.
|
||||||
* If the discard is successful all the inodes have been discarded.
|
* If the discard is successful all the inodes have been discarded.
|
||||||
*/
|
*/
|
||||||
int invalidate_inodes(struct super_block * sb)
|
int invalidate_inodes(struct super_block *sb)
|
||||||
{
|
{
|
||||||
int busy;
|
int busy;
|
||||||
LIST_HEAD(throw_away);
|
LIST_HEAD(throw_away);
|
||||||
|
@ -407,7 +405,6 @@ int invalidate_inodes(struct super_block * sb)
|
||||||
|
|
||||||
return busy;
|
return busy;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(invalidate_inodes);
|
EXPORT_SYMBOL(invalidate_inodes);
|
||||||
|
|
||||||
static int can_unuse(struct inode *inode)
|
static int can_unuse(struct inode *inode)
|
||||||
|
@ -504,7 +501,7 @@ static int shrink_icache_memory(int nr, gfp_t gfp_mask)
|
||||||
* Nasty deadlock avoidance. We may hold various FS locks,
|
* Nasty deadlock avoidance. We may hold various FS locks,
|
||||||
* and we don't want to recurse into the FS that called us
|
* and we don't want to recurse into the FS that called us
|
||||||
* in clear_inode() and friends..
|
* in clear_inode() and friends..
|
||||||
*/
|
*/
|
||||||
if (!(gfp_mask & __GFP_FS))
|
if (!(gfp_mask & __GFP_FS))
|
||||||
return -1;
|
return -1;
|
||||||
prune_icache(nr);
|
prune_icache(nr);
|
||||||
|
@ -524,10 +521,13 @@ static void __wait_on_freeing_inode(struct inode *inode);
|
||||||
* by hand after calling find_inode now! This simplifies iunique and won't
|
* by hand after calling find_inode now! This simplifies iunique and won't
|
||||||
* add any additional branch in the common code.
|
* add any additional branch in the common code.
|
||||||
*/
|
*/
|
||||||
static struct inode * find_inode(struct super_block * sb, struct hlist_head *head, int (*test)(struct inode *, void *), void *data)
|
static struct inode *find_inode(struct super_block *sb,
|
||||||
|
struct hlist_head *head,
|
||||||
|
int (*test)(struct inode *, void *),
|
||||||
|
void *data)
|
||||||
{
|
{
|
||||||
struct hlist_node *node;
|
struct hlist_node *node;
|
||||||
struct inode * inode = NULL;
|
struct inode *inode = NULL;
|
||||||
|
|
||||||
repeat:
|
repeat:
|
||||||
hlist_for_each_entry(inode, node, head, i_hash) {
|
hlist_for_each_entry(inode, node, head, i_hash) {
|
||||||
|
@ -548,10 +548,11 @@ repeat:
|
||||||
* find_inode_fast is the fast path version of find_inode, see the comment at
|
* find_inode_fast is the fast path version of find_inode, see the comment at
|
||||||
* iget_locked for details.
|
* iget_locked for details.
|
||||||
*/
|
*/
|
||||||
static struct inode * find_inode_fast(struct super_block * sb, struct hlist_head *head, unsigned long ino)
|
static struct inode *find_inode_fast(struct super_block *sb,
|
||||||
|
struct hlist_head *head, unsigned long ino)
|
||||||
{
|
{
|
||||||
struct hlist_node *node;
|
struct hlist_node *node;
|
||||||
struct inode * inode = NULL;
|
struct inode *inode = NULL;
|
||||||
|
|
||||||
repeat:
|
repeat:
|
||||||
hlist_for_each_entry(inode, node, head, i_hash) {
|
hlist_for_each_entry(inode, node, head, i_hash) {
|
||||||
|
@ -631,10 +632,10 @@ struct inode *new_inode(struct super_block *sb)
|
||||||
* here to attempt to avoid that.
|
* here to attempt to avoid that.
|
||||||
*/
|
*/
|
||||||
static unsigned int last_ino;
|
static unsigned int last_ino;
|
||||||
struct inode * inode;
|
struct inode *inode;
|
||||||
|
|
||||||
spin_lock_prefetch(&inode_lock);
|
spin_lock_prefetch(&inode_lock);
|
||||||
|
|
||||||
inode = alloc_inode(sb);
|
inode = alloc_inode(sb);
|
||||||
if (inode) {
|
if (inode) {
|
||||||
spin_lock(&inode_lock);
|
spin_lock(&inode_lock);
|
||||||
|
@ -645,7 +646,6 @@ struct inode *new_inode(struct super_block *sb)
|
||||||
}
|
}
|
||||||
return inode;
|
return inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(new_inode);
|
EXPORT_SYMBOL(new_inode);
|
||||||
|
|
||||||
void unlock_new_inode(struct inode *inode)
|
void unlock_new_inode(struct inode *inode)
|
||||||
|
@ -674,7 +674,6 @@ void unlock_new_inode(struct inode *inode)
|
||||||
inode->i_state &= ~(I_LOCK|I_NEW);
|
inode->i_state &= ~(I_LOCK|I_NEW);
|
||||||
wake_up_inode(inode);
|
wake_up_inode(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(unlock_new_inode);
|
EXPORT_SYMBOL(unlock_new_inode);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -683,13 +682,17 @@ EXPORT_SYMBOL(unlock_new_inode);
|
||||||
* We no longer cache the sb_flags in i_flags - see fs.h
|
* We no longer cache the sb_flags in i_flags - see fs.h
|
||||||
* -- rmk@arm.uk.linux.org
|
* -- rmk@arm.uk.linux.org
|
||||||
*/
|
*/
|
||||||
static struct inode * get_new_inode(struct super_block *sb, struct hlist_head *head, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data)
|
static struct inode *get_new_inode(struct super_block *sb,
|
||||||
|
struct hlist_head *head,
|
||||||
|
int (*test)(struct inode *, void *),
|
||||||
|
int (*set)(struct inode *, void *),
|
||||||
|
void *data)
|
||||||
{
|
{
|
||||||
struct inode * inode;
|
struct inode *inode;
|
||||||
|
|
||||||
inode = alloc_inode(sb);
|
inode = alloc_inode(sb);
|
||||||
if (inode) {
|
if (inode) {
|
||||||
struct inode * old;
|
struct inode *old;
|
||||||
|
|
||||||
spin_lock(&inode_lock);
|
spin_lock(&inode_lock);
|
||||||
/* We released the lock, so.. */
|
/* We released the lock, so.. */
|
||||||
|
@ -731,13 +734,14 @@ set_failed:
|
||||||
* get_new_inode_fast is the fast path version of get_new_inode, see the
|
* get_new_inode_fast is the fast path version of get_new_inode, see the
|
||||||
* comment at iget_locked for details.
|
* comment at iget_locked for details.
|
||||||
*/
|
*/
|
||||||
static struct inode * get_new_inode_fast(struct super_block *sb, struct hlist_head *head, unsigned long ino)
|
static struct inode *get_new_inode_fast(struct super_block *sb,
|
||||||
|
struct hlist_head *head, unsigned long ino)
|
||||||
{
|
{
|
||||||
struct inode * inode;
|
struct inode *inode;
|
||||||
|
|
||||||
inode = alloc_inode(sb);
|
inode = alloc_inode(sb);
|
||||||
if (inode) {
|
if (inode) {
|
||||||
struct inode * old;
|
struct inode *old;
|
||||||
|
|
||||||
spin_lock(&inode_lock);
|
spin_lock(&inode_lock);
|
||||||
/* We released the lock, so.. */
|
/* We released the lock, so.. */
|
||||||
|
@ -823,7 +827,6 @@ struct inode *igrab(struct inode *inode)
|
||||||
spin_unlock(&inode_lock);
|
spin_unlock(&inode_lock);
|
||||||
return inode;
|
return inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(igrab);
|
EXPORT_SYMBOL(igrab);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -924,7 +927,6 @@ struct inode *ilookup5_nowait(struct super_block *sb, unsigned long hashval,
|
||||||
|
|
||||||
return ifind(sb, head, test, data, 0);
|
return ifind(sb, head, test, data, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(ilookup5_nowait);
|
EXPORT_SYMBOL(ilookup5_nowait);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -953,7 +955,6 @@ struct inode *ilookup5(struct super_block *sb, unsigned long hashval,
|
||||||
|
|
||||||
return ifind(sb, head, test, data, 1);
|
return ifind(sb, head, test, data, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(ilookup5);
|
EXPORT_SYMBOL(ilookup5);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -976,7 +977,6 @@ struct inode *ilookup(struct super_block *sb, unsigned long ino)
|
||||||
|
|
||||||
return ifind_fast(sb, head, ino);
|
return ifind_fast(sb, head, ino);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(ilookup);
|
EXPORT_SYMBOL(ilookup);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1015,7 +1015,6 @@ struct inode *iget5_locked(struct super_block *sb, unsigned long hashval,
|
||||||
*/
|
*/
|
||||||
return get_new_inode(sb, head, test, set, data);
|
return get_new_inode(sb, head, test, set, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(iget5_locked);
|
EXPORT_SYMBOL(iget5_locked);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1047,7 +1046,6 @@ struct inode *iget_locked(struct super_block *sb, unsigned long ino)
|
||||||
*/
|
*/
|
||||||
return get_new_inode_fast(sb, head, ino);
|
return get_new_inode_fast(sb, head, ino);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(iget_locked);
|
EXPORT_SYMBOL(iget_locked);
|
||||||
|
|
||||||
int insert_inode_locked(struct inode *inode)
|
int insert_inode_locked(struct inode *inode)
|
||||||
|
@ -1076,7 +1074,6 @@ int insert_inode_locked(struct inode *inode)
|
||||||
iput(old);
|
iput(old);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(insert_inode_locked);
|
EXPORT_SYMBOL(insert_inode_locked);
|
||||||
|
|
||||||
int insert_inode_locked4(struct inode *inode, unsigned long hashval,
|
int insert_inode_locked4(struct inode *inode, unsigned long hashval,
|
||||||
|
@ -1106,7 +1103,6 @@ int insert_inode_locked4(struct inode *inode, unsigned long hashval,
|
||||||
iput(old);
|
iput(old);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(insert_inode_locked4);
|
EXPORT_SYMBOL(insert_inode_locked4);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1124,7 +1120,6 @@ void __insert_inode_hash(struct inode *inode, unsigned long hashval)
|
||||||
hlist_add_head(&inode->i_hash, head);
|
hlist_add_head(&inode->i_hash, head);
|
||||||
spin_unlock(&inode_lock);
|
spin_unlock(&inode_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(__insert_inode_hash);
|
EXPORT_SYMBOL(__insert_inode_hash);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1139,7 +1134,6 @@ void remove_inode_hash(struct inode *inode)
|
||||||
hlist_del_init(&inode->i_hash);
|
hlist_del_init(&inode->i_hash);
|
||||||
spin_unlock(&inode_lock);
|
spin_unlock(&inode_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(remove_inode_hash);
|
EXPORT_SYMBOL(remove_inode_hash);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1187,7 +1181,6 @@ void generic_delete_inode(struct inode *inode)
|
||||||
BUG_ON(inode->i_state != I_CLEAR);
|
BUG_ON(inode->i_state != I_CLEAR);
|
||||||
destroy_inode(inode);
|
destroy_inode(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(generic_delete_inode);
|
EXPORT_SYMBOL(generic_delete_inode);
|
||||||
|
|
||||||
static void generic_forget_inode(struct inode *inode)
|
static void generic_forget_inode(struct inode *inode)
|
||||||
|
@ -1237,12 +1230,11 @@ void generic_drop_inode(struct inode *inode)
|
||||||
else
|
else
|
||||||
generic_forget_inode(inode);
|
generic_forget_inode(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL_GPL(generic_drop_inode);
|
EXPORT_SYMBOL_GPL(generic_drop_inode);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called when we're dropping the last reference
|
* Called when we're dropping the last reference
|
||||||
* to an inode.
|
* to an inode.
|
||||||
*
|
*
|
||||||
* Call the FS "drop()" function, defaulting to
|
* Call the FS "drop()" function, defaulting to
|
||||||
* the legacy UNIX filesystem behaviour..
|
* the legacy UNIX filesystem behaviour..
|
||||||
|
@ -1262,7 +1254,7 @@ static inline void iput_final(struct inode *inode)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* iput - put an inode
|
* iput - put an inode
|
||||||
* @inode: inode to put
|
* @inode: inode to put
|
||||||
*
|
*
|
||||||
* Puts an inode, dropping its usage count. If the inode use count hits
|
* Puts an inode, dropping its usage count. If the inode use count hits
|
||||||
|
@ -1279,7 +1271,6 @@ void iput(struct inode *inode)
|
||||||
iput_final(inode);
|
iput_final(inode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(iput);
|
EXPORT_SYMBOL(iput);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1290,10 +1281,10 @@ EXPORT_SYMBOL(iput);
|
||||||
* Returns the block number on the device holding the inode that
|
* Returns the block number on the device holding the inode that
|
||||||
* is the disk block number for the block of the file requested.
|
* is the disk block number for the block of the file requested.
|
||||||
* That is, asked for block 4 of inode 1 the function will return the
|
* That is, asked for block 4 of inode 1 the function will return the
|
||||||
* disk block relative to the disk start that holds that block of the
|
* disk block relative to the disk start that holds that block of the
|
||||||
* file.
|
* file.
|
||||||
*/
|
*/
|
||||||
sector_t bmap(struct inode * inode, sector_t block)
|
sector_t bmap(struct inode *inode, sector_t block)
|
||||||
{
|
{
|
||||||
sector_t res = 0;
|
sector_t res = 0;
|
||||||
if (inode->i_mapping->a_ops->bmap)
|
if (inode->i_mapping->a_ops->bmap)
|
||||||
|
@ -1425,7 +1416,6 @@ void file_update_time(struct file *file)
|
||||||
mark_inode_dirty_sync(inode);
|
mark_inode_dirty_sync(inode);
|
||||||
mnt_drop_write(file->f_path.mnt);
|
mnt_drop_write(file->f_path.mnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(file_update_time);
|
EXPORT_SYMBOL(file_update_time);
|
||||||
|
|
||||||
int inode_needs_sync(struct inode *inode)
|
int inode_needs_sync(struct inode *inode)
|
||||||
|
@ -1436,7 +1426,6 @@ int inode_needs_sync(struct inode *inode)
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(inode_needs_sync);
|
EXPORT_SYMBOL(inode_needs_sync);
|
||||||
|
|
||||||
int inode_wait(void *word)
|
int inode_wait(void *word)
|
||||||
|
|
|
@ -246,8 +246,7 @@ int get_sb_pseudo(struct file_system_type *fs_type, char *name,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
Enomem:
|
Enomem:
|
||||||
up_write(&s->s_umount);
|
deactivate_locked_super(s);
|
||||||
deactivate_super(s);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
13
fs/namei.c
13
fs/namei.c
|
@ -1130,8 +1130,8 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
|
||||||
* @nd: pointer to nameidata
|
* @nd: pointer to nameidata
|
||||||
* @open_flags: open intent flags
|
* @open_flags: open intent flags
|
||||||
*/
|
*/
|
||||||
int path_lookup_open(int dfd, const char *name, unsigned int lookup_flags,
|
static int path_lookup_open(int dfd, const char *name,
|
||||||
struct nameidata *nd, int open_flags)
|
unsigned int lookup_flags, struct nameidata *nd, int open_flags)
|
||||||
{
|
{
|
||||||
struct file *filp = get_empty_filp();
|
struct file *filp = get_empty_filp();
|
||||||
int err;
|
int err;
|
||||||
|
@ -1637,18 +1637,19 @@ static int open_will_write_to_fs(int flag, struct inode *inode)
|
||||||
* open_to_namei_flags() for more details.
|
* open_to_namei_flags() for more details.
|
||||||
*/
|
*/
|
||||||
struct file *do_filp_open(int dfd, const char *pathname,
|
struct file *do_filp_open(int dfd, const char *pathname,
|
||||||
int open_flag, int mode)
|
int open_flag, int mode, int acc_mode)
|
||||||
{
|
{
|
||||||
struct file *filp;
|
struct file *filp;
|
||||||
struct nameidata nd;
|
struct nameidata nd;
|
||||||
int acc_mode, error;
|
int error;
|
||||||
struct path path;
|
struct path path;
|
||||||
struct dentry *dir;
|
struct dentry *dir;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int will_write;
|
int will_write;
|
||||||
int flag = open_to_namei_flags(open_flag);
|
int flag = open_to_namei_flags(open_flag);
|
||||||
|
|
||||||
acc_mode = MAY_OPEN | ACC_MODE(flag);
|
if (!acc_mode)
|
||||||
|
acc_mode = MAY_OPEN | ACC_MODE(flag);
|
||||||
|
|
||||||
/* O_TRUNC implies we need access checks for write permissions */
|
/* O_TRUNC implies we need access checks for write permissions */
|
||||||
if (flag & O_TRUNC)
|
if (flag & O_TRUNC)
|
||||||
|
@ -1869,7 +1870,7 @@ do_link:
|
||||||
*/
|
*/
|
||||||
struct file *filp_open(const char *filename, int flags, int mode)
|
struct file *filp_open(const char *filename, int flags, int mode)
|
||||||
{
|
{
|
||||||
return do_filp_open(AT_FDCWD, filename, flags, mode);
|
return do_filp_open(AT_FDCWD, filename, flags, mode, 0);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(filp_open);
|
EXPORT_SYMBOL(filp_open);
|
||||||
|
|
||||||
|
|
|
@ -695,12 +695,16 @@ static inline void mangle(struct seq_file *m, const char *s)
|
||||||
*/
|
*/
|
||||||
int generic_show_options(struct seq_file *m, struct vfsmount *mnt)
|
int generic_show_options(struct seq_file *m, struct vfsmount *mnt)
|
||||||
{
|
{
|
||||||
const char *options = mnt->mnt_sb->s_options;
|
const char *options;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
options = rcu_dereference(mnt->mnt_sb->s_options);
|
||||||
|
|
||||||
if (options != NULL && options[0]) {
|
if (options != NULL && options[0]) {
|
||||||
seq_putc(m, ',');
|
seq_putc(m, ',');
|
||||||
mangle(m, options);
|
mangle(m, options);
|
||||||
}
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -721,11 +725,22 @@ EXPORT_SYMBOL(generic_show_options);
|
||||||
*/
|
*/
|
||||||
void save_mount_options(struct super_block *sb, char *options)
|
void save_mount_options(struct super_block *sb, char *options)
|
||||||
{
|
{
|
||||||
kfree(sb->s_options);
|
BUG_ON(sb->s_options);
|
||||||
sb->s_options = kstrdup(options, GFP_KERNEL);
|
rcu_assign_pointer(sb->s_options, kstrdup(options, GFP_KERNEL));
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(save_mount_options);
|
EXPORT_SYMBOL(save_mount_options);
|
||||||
|
|
||||||
|
void replace_mount_options(struct super_block *sb, char *options)
|
||||||
|
{
|
||||||
|
char *old = sb->s_options;
|
||||||
|
rcu_assign_pointer(sb->s_options, options);
|
||||||
|
if (old) {
|
||||||
|
synchronize_rcu();
|
||||||
|
kfree(old);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(replace_mount_options);
|
||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
/* iterator */
|
/* iterator */
|
||||||
static void *m_start(struct seq_file *m, loff_t *pos)
|
static void *m_start(struct seq_file *m, loff_t *pos)
|
||||||
|
@ -1073,9 +1088,7 @@ static int do_umount(struct vfsmount *mnt, int flags)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (flags & MNT_FORCE && sb->s_op->umount_begin) {
|
if (flags & MNT_FORCE && sb->s_op->umount_begin) {
|
||||||
lock_kernel();
|
|
||||||
sb->s_op->umount_begin(sb);
|
sb->s_op->umount_begin(sb);
|
||||||
unlock_kernel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -683,9 +683,12 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
|
||||||
*/
|
*/
|
||||||
static void nfs_umount_begin(struct super_block *sb)
|
static void nfs_umount_begin(struct super_block *sb)
|
||||||
{
|
{
|
||||||
struct nfs_server *server = NFS_SB(sb);
|
struct nfs_server *server;
|
||||||
struct rpc_clnt *rpc;
|
struct rpc_clnt *rpc;
|
||||||
|
|
||||||
|
lock_kernel();
|
||||||
|
|
||||||
|
server = NFS_SB(sb);
|
||||||
/* -EIO all pending I/O */
|
/* -EIO all pending I/O */
|
||||||
rpc = server->client_acl;
|
rpc = server->client_acl;
|
||||||
if (!IS_ERR(rpc))
|
if (!IS_ERR(rpc))
|
||||||
|
@ -693,6 +696,8 @@ static void nfs_umount_begin(struct super_block *sb)
|
||||||
rpc = server->client;
|
rpc = server->client;
|
||||||
if (!IS_ERR(rpc))
|
if (!IS_ERR(rpc))
|
||||||
rpc_killall_tasks(rpc);
|
rpc_killall_tasks(rpc);
|
||||||
|
|
||||||
|
unlock_kernel();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2106,8 +2111,7 @@ out_err_nosb:
|
||||||
error_splat_root:
|
error_splat_root:
|
||||||
dput(mntroot);
|
dput(mntroot);
|
||||||
error_splat_super:
|
error_splat_super:
|
||||||
up_write(&s->s_umount);
|
deactivate_locked_super(s);
|
||||||
deactivate_super(s);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2203,8 +2207,7 @@ out_err_noserver:
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
error_splat_super:
|
error_splat_super:
|
||||||
up_write(&s->s_umount);
|
deactivate_locked_super(s);
|
||||||
deactivate_super(s);
|
|
||||||
dprintk("<-- nfs_xdev_get_sb() = %d [splat]\n", error);
|
dprintk("<-- nfs_xdev_get_sb() = %d [splat]\n", error);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -2464,8 +2467,7 @@ out_free:
|
||||||
error_splat_root:
|
error_splat_root:
|
||||||
dput(mntroot);
|
dput(mntroot);
|
||||||
error_splat_super:
|
error_splat_super:
|
||||||
up_write(&s->s_umount);
|
deactivate_locked_super(s);
|
||||||
deactivate_super(s);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2559,8 +2561,7 @@ out_err_noserver:
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
error_splat_super:
|
error_splat_super:
|
||||||
up_write(&s->s_umount);
|
deactivate_locked_super(s);
|
||||||
deactivate_super(s);
|
|
||||||
dprintk("<-- nfs4_xdev_get_sb() = %d [splat]\n", error);
|
dprintk("<-- nfs4_xdev_get_sb() = %d [splat]\n", error);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -2644,8 +2645,7 @@ out_err_noserver:
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
error_splat_super:
|
error_splat_super:
|
||||||
up_write(&s->s_umount);
|
deactivate_locked_super(s);
|
||||||
deactivate_super(s);
|
|
||||||
dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error);
|
dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/pagemap.h>
|
#include <linux/pagemap.h>
|
||||||
#include <linux/utsname.h>
|
#include <linux/utsname.h>
|
||||||
|
#include <linux/namei.h>
|
||||||
|
|
||||||
#define MLOG_MASK_PREFIX ML_NAMEI
|
#define MLOG_MASK_PREFIX ML_NAMEI
|
||||||
#include <cluster/masklog.h>
|
#include <cluster/masklog.h>
|
||||||
|
@ -54,26 +55,6 @@
|
||||||
|
|
||||||
#include "buffer_head_io.h"
|
#include "buffer_head_io.h"
|
||||||
|
|
||||||
static char *ocfs2_page_getlink(struct dentry * dentry,
|
|
||||||
struct page **ppage);
|
|
||||||
static char *ocfs2_fast_symlink_getlink(struct inode *inode,
|
|
||||||
struct buffer_head **bh);
|
|
||||||
|
|
||||||
/* get the link contents into pagecache */
|
|
||||||
static char *ocfs2_page_getlink(struct dentry * dentry,
|
|
||||||
struct page **ppage)
|
|
||||||
{
|
|
||||||
struct page * page;
|
|
||||||
struct address_space *mapping = dentry->d_inode->i_mapping;
|
|
||||||
page = read_mapping_page(mapping, 0, NULL);
|
|
||||||
if (IS_ERR(page))
|
|
||||||
goto sync_fail;
|
|
||||||
*ppage = page;
|
|
||||||
return kmap(page);
|
|
||||||
|
|
||||||
sync_fail:
|
|
||||||
return (char*)page;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *ocfs2_fast_symlink_getlink(struct inode *inode,
|
static char *ocfs2_fast_symlink_getlink(struct inode *inode,
|
||||||
struct buffer_head **bh)
|
struct buffer_head **bh)
|
||||||
|
@ -128,40 +109,55 @@ out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *ocfs2_follow_link(struct dentry *dentry,
|
static void *ocfs2_fast_follow_link(struct dentry *dentry,
|
||||||
struct nameidata *nd)
|
struct nameidata *nd)
|
||||||
{
|
{
|
||||||
int status;
|
int status = 0;
|
||||||
char *link;
|
int len;
|
||||||
|
char *target, *link = ERR_PTR(-ENOMEM);
|
||||||
struct inode *inode = dentry->d_inode;
|
struct inode *inode = dentry->d_inode;
|
||||||
struct page *page = NULL;
|
|
||||||
struct buffer_head *bh = NULL;
|
struct buffer_head *bh = NULL;
|
||||||
|
|
||||||
if (ocfs2_inode_is_fast_symlink(inode))
|
mlog_entry_void();
|
||||||
link = ocfs2_fast_symlink_getlink(inode, &bh);
|
|
||||||
else
|
BUG_ON(!ocfs2_inode_is_fast_symlink(inode));
|
||||||
link = ocfs2_page_getlink(dentry, &page);
|
target = ocfs2_fast_symlink_getlink(inode, &bh);
|
||||||
if (IS_ERR(link)) {
|
if (IS_ERR(target)) {
|
||||||
status = PTR_ERR(link);
|
status = PTR_ERR(target);
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = vfs_follow_link(nd, link);
|
/* Fast symlinks can't be large */
|
||||||
|
len = strlen(target);
|
||||||
|
link = kzalloc(len + 1, GFP_NOFS);
|
||||||
|
if (!link) {
|
||||||
|
status = -ENOMEM;
|
||||||
|
mlog_errno(status);
|
||||||
|
goto bail;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(link, target, len);
|
||||||
|
nd_set_link(nd, link);
|
||||||
|
|
||||||
bail:
|
bail:
|
||||||
if (page) {
|
|
||||||
kunmap(page);
|
|
||||||
page_cache_release(page);
|
|
||||||
}
|
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
|
|
||||||
return ERR_PTR(status);
|
mlog_exit(status);
|
||||||
|
return status ? ERR_PTR(status) : link;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ocfs2_fast_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
|
||||||
|
{
|
||||||
|
char *link = cookie;
|
||||||
|
|
||||||
|
kfree(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct inode_operations ocfs2_symlink_inode_operations = {
|
const struct inode_operations ocfs2_symlink_inode_operations = {
|
||||||
.readlink = page_readlink,
|
.readlink = page_readlink,
|
||||||
.follow_link = ocfs2_follow_link,
|
.follow_link = page_follow_link_light,
|
||||||
|
.put_link = page_put_link,
|
||||||
.getattr = ocfs2_getattr,
|
.getattr = ocfs2_getattr,
|
||||||
.setattr = ocfs2_setattr,
|
.setattr = ocfs2_setattr,
|
||||||
.setxattr = generic_setxattr,
|
.setxattr = generic_setxattr,
|
||||||
|
@ -171,7 +167,8 @@ const struct inode_operations ocfs2_symlink_inode_operations = {
|
||||||
};
|
};
|
||||||
const struct inode_operations ocfs2_fast_symlink_inode_operations = {
|
const struct inode_operations ocfs2_fast_symlink_inode_operations = {
|
||||||
.readlink = ocfs2_readlink,
|
.readlink = ocfs2_readlink,
|
||||||
.follow_link = ocfs2_follow_link,
|
.follow_link = ocfs2_fast_follow_link,
|
||||||
|
.put_link = ocfs2_fast_put_link,
|
||||||
.getattr = ocfs2_getattr,
|
.getattr = ocfs2_getattr,
|
||||||
.setattr = ocfs2_setattr,
|
.setattr = ocfs2_setattr,
|
||||||
.setxattr = generic_setxattr,
|
.setxattr = generic_setxattr,
|
||||||
|
|
|
@ -1033,7 +1033,7 @@ long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
|
||||||
if (!IS_ERR(tmp)) {
|
if (!IS_ERR(tmp)) {
|
||||||
fd = get_unused_fd_flags(flags);
|
fd = get_unused_fd_flags(flags);
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
struct file *f = do_filp_open(dfd, tmp, flags, mode);
|
struct file *f = do_filp_open(dfd, tmp, flags, mode, 0);
|
||||||
if (IS_ERR(f)) {
|
if (IS_ERR(f)) {
|
||||||
put_unused_fd(fd);
|
put_unused_fd(fd);
|
||||||
fd = PTR_ERR(f);
|
fd = PTR_ERR(f);
|
||||||
|
|
|
@ -67,8 +67,7 @@ static int proc_get_sb(struct file_system_type *fs_type,
|
||||||
sb->s_flags = flags;
|
sb->s_flags = flags;
|
||||||
err = proc_fill_super(sb);
|
err = proc_fill_super(sb);
|
||||||
if (err) {
|
if (err) {
|
||||||
up_write(&sb->s_umount);
|
deactivate_locked_super(sb);
|
||||||
deactivate_super(sb);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,18 @@ static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry,
|
||||||
|
|
||||||
#define store_ih(where,what) copy_item_head (where, what)
|
#define store_ih(where,what) copy_item_head (where, what)
|
||||||
|
|
||||||
|
static inline bool is_privroot_deh(struct dentry *dir,
|
||||||
|
struct reiserfs_de_head *deh)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
#ifdef CONFIG_REISERFS_FS_XATTR
|
||||||
|
struct dentry *privroot = REISERFS_SB(dir->d_sb)->priv_root;
|
||||||
|
ret = (dir == dir->d_parent && privroot->d_inode &&
|
||||||
|
deh->deh_objectid == INODE_PKEY(privroot->d_inode)->k_objectid);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent,
|
int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent,
|
||||||
filldir_t filldir, loff_t *pos)
|
filldir_t filldir, loff_t *pos)
|
||||||
{
|
{
|
||||||
|
@ -138,18 +150,8 @@ int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ignore the .reiserfs_priv entry */
|
/* Ignore the .reiserfs_priv entry */
|
||||||
if (reiserfs_xattrs(inode->i_sb) &&
|
if (is_privroot_deh(dentry, deh))
|
||||||
!old_format_only(inode->i_sb) &&
|
|
||||||
dentry == inode->i_sb->s_root &&
|
|
||||||
REISERFS_SB(inode->i_sb)->priv_root &&
|
|
||||||
REISERFS_SB(inode->i_sb)->priv_root->d_inode
|
|
||||||
&& deh_objectid(deh) ==
|
|
||||||
le32_to_cpu(INODE_PKEY
|
|
||||||
(REISERFS_SB(inode->i_sb)->
|
|
||||||
priv_root->d_inode)->
|
|
||||||
k_objectid)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
d_off = deh_offset(deh);
|
d_off = deh_offset(deh);
|
||||||
*pos = d_off;
|
*pos = d_off;
|
||||||
|
|
|
@ -338,21 +338,8 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
|
||||||
&path_to_entry, &de);
|
&path_to_entry, &de);
|
||||||
pathrelse(&path_to_entry);
|
pathrelse(&path_to_entry);
|
||||||
if (retval == NAME_FOUND) {
|
if (retval == NAME_FOUND) {
|
||||||
/* Hide the .reiserfs_priv directory */
|
inode = reiserfs_iget(dir->i_sb,
|
||||||
if (reiserfs_xattrs(dir->i_sb) &&
|
(struct cpu_key *)&(de.de_dir_id));
|
||||||
!old_format_only(dir->i_sb) &&
|
|
||||||
REISERFS_SB(dir->i_sb)->priv_root &&
|
|
||||||
REISERFS_SB(dir->i_sb)->priv_root->d_inode &&
|
|
||||||
de.de_objectid ==
|
|
||||||
le32_to_cpu(INODE_PKEY
|
|
||||||
(REISERFS_SB(dir->i_sb)->priv_root->d_inode)->
|
|
||||||
k_objectid)) {
|
|
||||||
reiserfs_write_unlock(dir->i_sb);
|
|
||||||
return ERR_PTR(-EACCES);
|
|
||||||
}
|
|
||||||
|
|
||||||
inode =
|
|
||||||
reiserfs_iget(dir->i_sb, (struct cpu_key *)&(de.de_dir_id));
|
|
||||||
if (!inode || IS_ERR(inode)) {
|
if (!inode || IS_ERR(inode)) {
|
||||||
reiserfs_write_unlock(dir->i_sb);
|
reiserfs_write_unlock(dir->i_sb);
|
||||||
return ERR_PTR(-EACCES);
|
return ERR_PTR(-EACCES);
|
||||||
|
|
|
@ -1316,8 +1316,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
out_ok:
|
out_ok:
|
||||||
kfree(s->s_options);
|
replace_mount_options(s, new_opts);
|
||||||
s->s_options = new_opts;
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_err:
|
out_err:
|
||||||
|
@ -1842,7 +1841,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((errval = reiserfs_xattr_init(s, s->s_flags))) {
|
if ((errval = reiserfs_lookup_privroot(s)) ||
|
||||||
|
(errval = reiserfs_xattr_init(s, s->s_flags))) {
|
||||||
dput(s->s_root);
|
dput(s->s_root);
|
||||||
s->s_root = NULL;
|
s->s_root = NULL;
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -1855,7 +1855,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
|
||||||
reiserfs_info(s, "using 3.5.x disk format\n");
|
reiserfs_info(s, "using 3.5.x disk format\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((errval = reiserfs_xattr_init(s, s->s_flags))) {
|
if ((errval = reiserfs_lookup_privroot(s)) ||
|
||||||
|
(errval = reiserfs_xattr_init(s, s->s_flags))) {
|
||||||
dput(s->s_root);
|
dput(s->s_root);
|
||||||
s->s_root = NULL;
|
s->s_root = NULL;
|
||||||
goto error;
|
goto error;
|
||||||
|
|
|
@ -113,41 +113,28 @@ static int xattr_rmdir(struct inode *dir, struct dentry *dentry)
|
||||||
|
|
||||||
#define xattr_may_create(flags) (!flags || flags & XATTR_CREATE)
|
#define xattr_may_create(flags) (!flags || flags & XATTR_CREATE)
|
||||||
|
|
||||||
/* Returns and possibly creates the xattr dir. */
|
|
||||||
static struct dentry *lookup_or_create_dir(struct dentry *parent,
|
|
||||||
const char *name, int flags)
|
|
||||||
{
|
|
||||||
struct dentry *dentry;
|
|
||||||
BUG_ON(!parent);
|
|
||||||
|
|
||||||
dentry = lookup_one_len(name, parent, strlen(name));
|
|
||||||
if (IS_ERR(dentry))
|
|
||||||
return dentry;
|
|
||||||
else if (!dentry->d_inode) {
|
|
||||||
int err = -ENODATA;
|
|
||||||
|
|
||||||
if (xattr_may_create(flags)) {
|
|
||||||
mutex_lock_nested(&parent->d_inode->i_mutex,
|
|
||||||
I_MUTEX_XATTR);
|
|
||||||
err = xattr_mkdir(parent->d_inode, dentry, 0700);
|
|
||||||
mutex_unlock(&parent->d_inode->i_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err) {
|
|
||||||
dput(dentry);
|
|
||||||
dentry = ERR_PTR(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return dentry;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct dentry *open_xa_root(struct super_block *sb, int flags)
|
static struct dentry *open_xa_root(struct super_block *sb, int flags)
|
||||||
{
|
{
|
||||||
struct dentry *privroot = REISERFS_SB(sb)->priv_root;
|
struct dentry *privroot = REISERFS_SB(sb)->priv_root;
|
||||||
if (!privroot)
|
struct dentry *xaroot;
|
||||||
|
if (!privroot->d_inode)
|
||||||
return ERR_PTR(-ENODATA);
|
return ERR_PTR(-ENODATA);
|
||||||
return lookup_or_create_dir(privroot, XAROOT_NAME, flags);
|
|
||||||
|
mutex_lock_nested(&privroot->d_inode->i_mutex, I_MUTEX_XATTR);
|
||||||
|
|
||||||
|
xaroot = dget(REISERFS_SB(sb)->xattr_root);
|
||||||
|
if (!xaroot->d_inode) {
|
||||||
|
int err = -ENODATA;
|
||||||
|
if (xattr_may_create(flags))
|
||||||
|
err = xattr_mkdir(privroot->d_inode, xaroot, 0700);
|
||||||
|
if (err) {
|
||||||
|
dput(xaroot);
|
||||||
|
xaroot = ERR_PTR(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&privroot->d_inode->i_mutex);
|
||||||
|
return xaroot;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dentry *open_xa_dir(const struct inode *inode, int flags)
|
static struct dentry *open_xa_dir(const struct inode *inode, int flags)
|
||||||
|
@ -163,10 +150,22 @@ static struct dentry *open_xa_dir(const struct inode *inode, int flags)
|
||||||
le32_to_cpu(INODE_PKEY(inode)->k_objectid),
|
le32_to_cpu(INODE_PKEY(inode)->k_objectid),
|
||||||
inode->i_generation);
|
inode->i_generation);
|
||||||
|
|
||||||
xadir = lookup_or_create_dir(xaroot, namebuf, flags);
|
mutex_lock_nested(&xaroot->d_inode->i_mutex, I_MUTEX_XATTR);
|
||||||
|
|
||||||
|
xadir = lookup_one_len(namebuf, xaroot, strlen(namebuf));
|
||||||
|
if (!IS_ERR(xadir) && !xadir->d_inode) {
|
||||||
|
int err = -ENODATA;
|
||||||
|
if (xattr_may_create(flags))
|
||||||
|
err = xattr_mkdir(xaroot->d_inode, xadir, 0700);
|
||||||
|
if (err) {
|
||||||
|
dput(xadir);
|
||||||
|
xadir = ERR_PTR(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&xaroot->d_inode->i_mutex);
|
||||||
dput(xaroot);
|
dput(xaroot);
|
||||||
return xadir;
|
return xadir;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The following are side effects of other operations that aren't explicitly
|
/* The following are side effects of other operations that aren't explicitly
|
||||||
|
@ -184,6 +183,7 @@ fill_with_dentries(void *buf, const char *name, int namelen, loff_t offset,
|
||||||
{
|
{
|
||||||
struct reiserfs_dentry_buf *dbuf = buf;
|
struct reiserfs_dentry_buf *dbuf = buf;
|
||||||
struct dentry *dentry;
|
struct dentry *dentry;
|
||||||
|
WARN_ON_ONCE(!mutex_is_locked(&dbuf->xadir->d_inode->i_mutex));
|
||||||
|
|
||||||
if (dbuf->count == ARRAY_SIZE(dbuf->dentries))
|
if (dbuf->count == ARRAY_SIZE(dbuf->dentries))
|
||||||
return -ENOSPC;
|
return -ENOSPC;
|
||||||
|
@ -349,6 +349,7 @@ static struct dentry *xattr_lookup(struct inode *inode, const char *name,
|
||||||
if (IS_ERR(xadir))
|
if (IS_ERR(xadir))
|
||||||
return ERR_CAST(xadir);
|
return ERR_CAST(xadir);
|
||||||
|
|
||||||
|
mutex_lock_nested(&xadir->d_inode->i_mutex, I_MUTEX_XATTR);
|
||||||
xafile = lookup_one_len(name, xadir, strlen(name));
|
xafile = lookup_one_len(name, xadir, strlen(name));
|
||||||
if (IS_ERR(xafile)) {
|
if (IS_ERR(xafile)) {
|
||||||
err = PTR_ERR(xafile);
|
err = PTR_ERR(xafile);
|
||||||
|
@ -360,18 +361,15 @@ static struct dentry *xattr_lookup(struct inode *inode, const char *name,
|
||||||
|
|
||||||
if (!xafile->d_inode) {
|
if (!xafile->d_inode) {
|
||||||
err = -ENODATA;
|
err = -ENODATA;
|
||||||
if (xattr_may_create(flags)) {
|
if (xattr_may_create(flags))
|
||||||
mutex_lock_nested(&xadir->d_inode->i_mutex,
|
|
||||||
I_MUTEX_XATTR);
|
|
||||||
err = xattr_create(xadir->d_inode, xafile,
|
err = xattr_create(xadir->d_inode, xafile,
|
||||||
0700|S_IFREG);
|
0700|S_IFREG);
|
||||||
mutex_unlock(&xadir->d_inode->i_mutex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
dput(xafile);
|
dput(xafile);
|
||||||
out:
|
out:
|
||||||
|
mutex_unlock(&xadir->d_inode->i_mutex);
|
||||||
dput(xadir);
|
dput(xadir);
|
||||||
if (err)
|
if (err)
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
|
@ -435,6 +433,7 @@ static int lookup_and_delete_xattr(struct inode *inode, const char *name)
|
||||||
if (IS_ERR(xadir))
|
if (IS_ERR(xadir))
|
||||||
return PTR_ERR(xadir);
|
return PTR_ERR(xadir);
|
||||||
|
|
||||||
|
mutex_lock_nested(&xadir->d_inode->i_mutex, I_MUTEX_XATTR);
|
||||||
dentry = lookup_one_len(name, xadir, strlen(name));
|
dentry = lookup_one_len(name, xadir, strlen(name));
|
||||||
if (IS_ERR(dentry)) {
|
if (IS_ERR(dentry)) {
|
||||||
err = PTR_ERR(dentry);
|
err = PTR_ERR(dentry);
|
||||||
|
@ -442,14 +441,13 @@ static int lookup_and_delete_xattr(struct inode *inode, const char *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dentry->d_inode) {
|
if (dentry->d_inode) {
|
||||||
mutex_lock_nested(&xadir->d_inode->i_mutex, I_MUTEX_XATTR);
|
|
||||||
err = xattr_unlink(xadir->d_inode, dentry);
|
err = xattr_unlink(xadir->d_inode, dentry);
|
||||||
mutex_unlock(&xadir->d_inode->i_mutex);
|
|
||||||
update_ctime(inode);
|
update_ctime(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
out_dput:
|
out_dput:
|
||||||
|
mutex_unlock(&xadir->d_inode->i_mutex);
|
||||||
dput(xadir);
|
dput(xadir);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -843,7 +841,7 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size)
|
||||||
if (!dentry->d_inode)
|
if (!dentry->d_inode)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!reiserfs_xattrs(dentry->d_sb) ||
|
if (!dentry->d_sb->s_xattr ||
|
||||||
get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
|
get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
@ -906,19 +904,22 @@ static int create_privroot(struct dentry *dentry)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
struct inode *inode = dentry->d_parent->d_inode;
|
struct inode *inode = dentry->d_parent->d_inode;
|
||||||
mutex_lock_nested(&inode->i_mutex, I_MUTEX_XATTR);
|
WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex));
|
||||||
|
|
||||||
err = xattr_mkdir(inode, dentry, 0700);
|
err = xattr_mkdir(inode, dentry, 0700);
|
||||||
mutex_unlock(&inode->i_mutex);
|
if (err || !dentry->d_inode) {
|
||||||
if (err) {
|
reiserfs_warning(dentry->d_sb, "jdm-20006",
|
||||||
dput(dentry);
|
"xattrs/ACLs enabled and couldn't "
|
||||||
dentry = NULL;
|
"find/create .reiserfs_priv. "
|
||||||
|
"Failing mount.");
|
||||||
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dentry && dentry->d_inode)
|
dentry->d_inode->i_flags |= S_PRIVATE;
|
||||||
reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr "
|
reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr "
|
||||||
"storage.\n", PRIVROOT_NAME);
|
"storage.\n", PRIVROOT_NAME);
|
||||||
|
|
||||||
return err;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xattr_mount_check(struct super_block *s)
|
static int xattr_mount_check(struct super_block *s)
|
||||||
|
@ -950,11 +951,9 @@ static int
|
||||||
xattr_lookup_poison(struct dentry *dentry, struct qstr *q1, struct qstr *name)
|
xattr_lookup_poison(struct dentry *dentry, struct qstr *q1, struct qstr *name)
|
||||||
{
|
{
|
||||||
struct dentry *priv_root = REISERFS_SB(dentry->d_sb)->priv_root;
|
struct dentry *priv_root = REISERFS_SB(dentry->d_sb)->priv_root;
|
||||||
if (name->len == priv_root->d_name.len &&
|
if (container_of(q1, struct dentry, d_name) == priv_root)
|
||||||
name->hash == priv_root->d_name.hash &&
|
|
||||||
!memcmp(name->name, priv_root->d_name.name, name->len)) {
|
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
} else if (q1->len == name->len &&
|
if (q1->len == name->len &&
|
||||||
!memcmp(q1->name, name->name, name->len))
|
!memcmp(q1->name, name->name, name->len))
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -964,59 +963,60 @@ static const struct dentry_operations xattr_lookup_poison_ops = {
|
||||||
.d_compare = xattr_lookup_poison,
|
.d_compare = xattr_lookup_poison,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int reiserfs_lookup_privroot(struct super_block *s)
|
||||||
|
{
|
||||||
|
struct dentry *dentry;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
/* If we don't have the privroot located yet - go find it */
|
||||||
|
mutex_lock(&s->s_root->d_inode->i_mutex);
|
||||||
|
dentry = lookup_one_len(PRIVROOT_NAME, s->s_root,
|
||||||
|
strlen(PRIVROOT_NAME));
|
||||||
|
if (!IS_ERR(dentry)) {
|
||||||
|
REISERFS_SB(s)->priv_root = dentry;
|
||||||
|
s->s_root->d_op = &xattr_lookup_poison_ops;
|
||||||
|
if (dentry->d_inode)
|
||||||
|
dentry->d_inode->i_flags |= S_PRIVATE;
|
||||||
|
} else
|
||||||
|
err = PTR_ERR(dentry);
|
||||||
|
mutex_unlock(&s->s_root->d_inode->i_mutex);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/* We need to take a copy of the mount flags since things like
|
/* We need to take a copy of the mount flags since things like
|
||||||
* MS_RDONLY don't get set until *after* we're called.
|
* MS_RDONLY don't get set until *after* we're called.
|
||||||
* mount_flags != mount_options */
|
* mount_flags != mount_options */
|
||||||
int reiserfs_xattr_init(struct super_block *s, int mount_flags)
|
int reiserfs_xattr_init(struct super_block *s, int mount_flags)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
struct dentry *privroot = REISERFS_SB(s)->priv_root;
|
||||||
|
|
||||||
#ifdef CONFIG_REISERFS_FS_XATTR
|
#ifdef CONFIG_REISERFS_FS_XATTR
|
||||||
err = xattr_mount_check(s);
|
err = xattr_mount_check(s);
|
||||||
if (err)
|
if (err)
|
||||||
goto error;
|
goto error;
|
||||||
#endif
|
|
||||||
|
|
||||||
/* If we don't have the privroot located yet - go find it */
|
if (!privroot->d_inode && !(mount_flags & MS_RDONLY)) {
|
||||||
if (!REISERFS_SB(s)->priv_root) {
|
mutex_lock(&s->s_root->d_inode->i_mutex);
|
||||||
struct dentry *dentry;
|
err = create_privroot(REISERFS_SB(s)->priv_root);
|
||||||
dentry = lookup_one_len(PRIVROOT_NAME, s->s_root,
|
mutex_unlock(&s->s_root->d_inode->i_mutex);
|
||||||
strlen(PRIVROOT_NAME));
|
|
||||||
if (!IS_ERR(dentry)) {
|
|
||||||
#ifdef CONFIG_REISERFS_FS_XATTR
|
|
||||||
if (!(mount_flags & MS_RDONLY) && !dentry->d_inode)
|
|
||||||
err = create_privroot(dentry);
|
|
||||||
#endif
|
|
||||||
if (!dentry->d_inode) {
|
|
||||||
dput(dentry);
|
|
||||||
dentry = NULL;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
err = PTR_ERR(dentry);
|
|
||||||
|
|
||||||
if (!err && dentry) {
|
|
||||||
s->s_root->d_op = &xattr_lookup_poison_ops;
|
|
||||||
dentry->d_inode->i_flags |= S_PRIVATE;
|
|
||||||
REISERFS_SB(s)->priv_root = dentry;
|
|
||||||
#ifdef CONFIG_REISERFS_FS_XATTR
|
|
||||||
/* xattrs are unavailable */
|
|
||||||
} else if (!(mount_flags & MS_RDONLY)) {
|
|
||||||
/* If we're read-only it just means that the dir
|
|
||||||
* hasn't been created. Not an error -- just no
|
|
||||||
* xattrs on the fs. We'll check again if we
|
|
||||||
* go read-write */
|
|
||||||
reiserfs_warning(s, "jdm-20006",
|
|
||||||
"xattrs/ACLs enabled and couldn't "
|
|
||||||
"find/create .reiserfs_priv. "
|
|
||||||
"Failing mount.");
|
|
||||||
err = -EOPNOTSUPP;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_REISERFS_FS_XATTR
|
if (privroot->d_inode) {
|
||||||
if (!err)
|
|
||||||
s->s_xattr = reiserfs_xattr_handlers;
|
s->s_xattr = reiserfs_xattr_handlers;
|
||||||
|
mutex_lock(&privroot->d_inode->i_mutex);
|
||||||
|
if (!REISERFS_SB(s)->xattr_root) {
|
||||||
|
struct dentry *dentry;
|
||||||
|
dentry = lookup_one_len(XAROOT_NAME, privroot,
|
||||||
|
strlen(XAROOT_NAME));
|
||||||
|
if (!IS_ERR(dentry))
|
||||||
|
REISERFS_SB(s)->xattr_root = dentry;
|
||||||
|
else
|
||||||
|
err = PTR_ERR(dentry);
|
||||||
|
}
|
||||||
|
mutex_unlock(&privroot->d_inode->i_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -1026,11 +1026,12 @@ error:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The super_block MS_POSIXACL must mirror the (no)acl mount option. */
|
/* The super_block MS_POSIXACL must mirror the (no)acl mount option. */
|
||||||
s->s_flags = s->s_flags & ~MS_POSIXACL;
|
|
||||||
#ifdef CONFIG_REISERFS_FS_POSIX_ACL
|
#ifdef CONFIG_REISERFS_FS_POSIX_ACL
|
||||||
if (reiserfs_posixacl(s))
|
if (reiserfs_posixacl(s))
|
||||||
s->s_flags |= MS_POSIXACL;
|
s->s_flags |= MS_POSIXACL;
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
|
s->s_flags &= ~MS_POSIXACL;
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,8 +55,16 @@ int reiserfs_security_init(struct inode *dir, struct inode *inode,
|
||||||
struct reiserfs_security_handle *sec)
|
struct reiserfs_security_handle *sec)
|
||||||
{
|
{
|
||||||
int blocks = 0;
|
int blocks = 0;
|
||||||
int error = security_inode_init_security(inode, dir, &sec->name,
|
int error;
|
||||||
&sec->value, &sec->length);
|
|
||||||
|
sec->name = NULL;
|
||||||
|
|
||||||
|
/* Don't add selinux attributes on xattrs - they'll never get used */
|
||||||
|
if (IS_PRIVATE(dir))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error = security_inode_init_security(inode, dir, &sec->name,
|
||||||
|
&sec->value, &sec->length);
|
||||||
if (error) {
|
if (error) {
|
||||||
if (error == -EOPNOTSUPP)
|
if (error == -EOPNOTSUPP)
|
||||||
error = 0;
|
error = 0;
|
||||||
|
|
|
@ -298,7 +298,8 @@ static struct inode *romfs_iget(struct super_block *sb, unsigned long pos)
|
||||||
struct romfs_inode ri;
|
struct romfs_inode ri;
|
||||||
struct inode *i;
|
struct inode *i;
|
||||||
unsigned long nlen;
|
unsigned long nlen;
|
||||||
unsigned nextfh, ret;
|
unsigned nextfh;
|
||||||
|
int ret;
|
||||||
umode_t mode;
|
umode_t mode;
|
||||||
|
|
||||||
/* we might have to traverse a chain of "hard link" file entries to get
|
/* we might have to traverse a chain of "hard link" file entries to get
|
||||||
|
|
48
fs/super.c
48
fs/super.c
|
@ -207,6 +207,34 @@ void deactivate_super(struct super_block *s)
|
||||||
|
|
||||||
EXPORT_SYMBOL(deactivate_super);
|
EXPORT_SYMBOL(deactivate_super);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* deactivate_locked_super - drop an active reference to superblock
|
||||||
|
* @s: superblock to deactivate
|
||||||
|
*
|
||||||
|
* Equivalent of up_write(&s->s_umount); deactivate_super(s);, except that
|
||||||
|
* it does not unlock it until it's all over. As the result, it's safe to
|
||||||
|
* use to dispose of new superblock on ->get_sb() failure exits - nobody
|
||||||
|
* will see the sucker until it's all over. Equivalent using up_write +
|
||||||
|
* deactivate_super is safe for that purpose only if superblock is either
|
||||||
|
* safe to use or has NULL ->s_root when we unlock.
|
||||||
|
*/
|
||||||
|
void deactivate_locked_super(struct super_block *s)
|
||||||
|
{
|
||||||
|
struct file_system_type *fs = s->s_type;
|
||||||
|
if (atomic_dec_and_lock(&s->s_active, &sb_lock)) {
|
||||||
|
s->s_count -= S_BIAS-1;
|
||||||
|
spin_unlock(&sb_lock);
|
||||||
|
vfs_dq_off(s, 0);
|
||||||
|
fs->kill_sb(s);
|
||||||
|
put_filesystem(fs);
|
||||||
|
put_super(s);
|
||||||
|
} else {
|
||||||
|
up_write(&s->s_umount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(deactivate_locked_super);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* grab_super - acquire an active reference
|
* grab_super - acquire an active reference
|
||||||
* @s: reference we are trying to make active
|
* @s: reference we are trying to make active
|
||||||
|
@ -797,8 +825,7 @@ int get_sb_ns(struct file_system_type *fs_type, int flags, void *data,
|
||||||
sb->s_flags = flags;
|
sb->s_flags = flags;
|
||||||
err = fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
|
err = fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
|
||||||
if (err) {
|
if (err) {
|
||||||
up_write(&sb->s_umount);
|
deactivate_locked_super(sb);
|
||||||
deactivate_super(sb);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -854,8 +881,7 @@ int get_sb_bdev(struct file_system_type *fs_type,
|
||||||
|
|
||||||
if (s->s_root) {
|
if (s->s_root) {
|
||||||
if ((flags ^ s->s_flags) & MS_RDONLY) {
|
if ((flags ^ s->s_flags) & MS_RDONLY) {
|
||||||
up_write(&s->s_umount);
|
deactivate_locked_super(s);
|
||||||
deactivate_super(s);
|
|
||||||
error = -EBUSY;
|
error = -EBUSY;
|
||||||
goto error_bdev;
|
goto error_bdev;
|
||||||
}
|
}
|
||||||
|
@ -870,8 +896,7 @@ int get_sb_bdev(struct file_system_type *fs_type,
|
||||||
sb_set_blocksize(s, block_size(bdev));
|
sb_set_blocksize(s, block_size(bdev));
|
||||||
error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
|
error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
|
||||||
if (error) {
|
if (error) {
|
||||||
up_write(&s->s_umount);
|
deactivate_locked_super(s);
|
||||||
deactivate_super(s);
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -897,7 +922,7 @@ void kill_block_super(struct super_block *sb)
|
||||||
struct block_device *bdev = sb->s_bdev;
|
struct block_device *bdev = sb->s_bdev;
|
||||||
fmode_t mode = sb->s_mode;
|
fmode_t mode = sb->s_mode;
|
||||||
|
|
||||||
bdev->bd_super = 0;
|
bdev->bd_super = NULL;
|
||||||
generic_shutdown_super(sb);
|
generic_shutdown_super(sb);
|
||||||
sync_blockdev(bdev);
|
sync_blockdev(bdev);
|
||||||
close_bdev_exclusive(bdev, mode);
|
close_bdev_exclusive(bdev, mode);
|
||||||
|
@ -921,8 +946,7 @@ int get_sb_nodev(struct file_system_type *fs_type,
|
||||||
|
|
||||||
error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
|
error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
|
||||||
if (error) {
|
if (error) {
|
||||||
up_write(&s->s_umount);
|
deactivate_locked_super(s);
|
||||||
deactivate_super(s);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
s->s_flags |= MS_ACTIVE;
|
s->s_flags |= MS_ACTIVE;
|
||||||
|
@ -952,8 +976,7 @@ int get_sb_single(struct file_system_type *fs_type,
|
||||||
s->s_flags = flags;
|
s->s_flags = flags;
|
||||||
error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
|
error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
|
||||||
if (error) {
|
if (error) {
|
||||||
up_write(&s->s_umount);
|
deactivate_locked_super(s);
|
||||||
deactivate_super(s);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
s->s_flags |= MS_ACTIVE;
|
s->s_flags |= MS_ACTIVE;
|
||||||
|
@ -1006,8 +1029,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
|
||||||
return mnt;
|
return mnt;
|
||||||
out_sb:
|
out_sb:
|
||||||
dput(mnt->mnt_root);
|
dput(mnt->mnt_root);
|
||||||
up_write(&mnt->mnt_sb->s_umount);
|
deactivate_locked_super(mnt->mnt_sb);
|
||||||
deactivate_super(mnt->mnt_sb);
|
|
||||||
out_free_secdata:
|
out_free_secdata:
|
||||||
free_secdata(secdata);
|
free_secdata(secdata);
|
||||||
out_mnt:
|
out_mnt:
|
||||||
|
|
|
@ -2055,8 +2055,7 @@ static int ubifs_get_sb(struct file_system_type *fs_type, int flags,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_deact:
|
out_deact:
|
||||||
up_write(&sb->s_umount);
|
deactivate_locked_super(sb);
|
||||||
deactivate_super(sb);
|
|
||||||
out_close:
|
out_close:
|
||||||
ubi_close_volume(ubi);
|
ubi_close_volume(ubi);
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -666,6 +666,6 @@ not_empty:
|
||||||
const struct file_operations ufs_dir_operations = {
|
const struct file_operations ufs_dir_operations = {
|
||||||
.read = generic_read_dir,
|
.read = generic_read_dir,
|
||||||
.readdir = ufs_readdir,
|
.readdir = ufs_readdir,
|
||||||
.fsync = file_fsync,
|
.fsync = ufs_sync_file,
|
||||||
.llseek = generic_file_llseek,
|
.llseek = generic_file_llseek,
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#include "ufs.h"
|
#include "ufs.h"
|
||||||
|
|
||||||
|
|
||||||
static int ufs_sync_file(struct file *file, struct dentry *dentry, int datasync)
|
int ufs_sync_file(struct file *file, struct dentry *dentry, int datasync)
|
||||||
{
|
{
|
||||||
struct inode *inode = dentry->d_inode;
|
struct inode *inode = dentry->d_inode;
|
||||||
int err;
|
int err;
|
||||||
|
|
|
@ -98,8 +98,8 @@ extern void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
|
||||||
/* file.c */
|
/* file.c */
|
||||||
extern const struct inode_operations ufs_file_inode_operations;
|
extern const struct inode_operations ufs_file_inode_operations;
|
||||||
extern const struct file_operations ufs_file_operations;
|
extern const struct file_operations ufs_file_operations;
|
||||||
|
|
||||||
extern const struct address_space_operations ufs_aops;
|
extern const struct address_space_operations ufs_aops;
|
||||||
|
extern int ufs_sync_file(struct file *, struct dentry *, int);
|
||||||
|
|
||||||
/* ialloc.c */
|
/* ialloc.c */
|
||||||
extern void ufs_free_inode (struct inode *inode);
|
extern void ufs_free_inode (struct inode *inode);
|
||||||
|
|
|
@ -138,6 +138,7 @@ header-y += qnxtypes.h
|
||||||
header-y += radeonfb.h
|
header-y += radeonfb.h
|
||||||
header-y += raw.h
|
header-y += raw.h
|
||||||
header-y += resource.h
|
header-y += resource.h
|
||||||
|
header-y += romfs_fs.h
|
||||||
header-y += rose.h
|
header-y += rose.h
|
||||||
header-y += serial_reg.h
|
header-y += serial_reg.h
|
||||||
header-y += smbno.h
|
header-y += smbno.h
|
||||||
|
@ -314,7 +315,6 @@ unifdef-y += irqnr.h
|
||||||
unifdef-y += reboot.h
|
unifdef-y += reboot.h
|
||||||
unifdef-y += reiserfs_fs.h
|
unifdef-y += reiserfs_fs.h
|
||||||
unifdef-y += reiserfs_xattr.h
|
unifdef-y += reiserfs_xattr.h
|
||||||
unifdef-y += romfs_fs.h
|
|
||||||
unifdef-y += route.h
|
unifdef-y += route.h
|
||||||
unifdef-y += rtc.h
|
unifdef-y += rtc.h
|
||||||
unifdef-y += rtnetlink.h
|
unifdef-y += rtnetlink.h
|
||||||
|
|
|
@ -1775,6 +1775,7 @@ void kill_block_super(struct super_block *sb);
|
||||||
void kill_anon_super(struct super_block *sb);
|
void kill_anon_super(struct super_block *sb);
|
||||||
void kill_litter_super(struct super_block *sb);
|
void kill_litter_super(struct super_block *sb);
|
||||||
void deactivate_super(struct super_block *sb);
|
void deactivate_super(struct super_block *sb);
|
||||||
|
void deactivate_locked_super(struct super_block *sb);
|
||||||
int set_anon_super(struct super_block *s, void *data);
|
int set_anon_super(struct super_block *s, void *data);
|
||||||
struct super_block *sget(struct file_system_type *type,
|
struct super_block *sget(struct file_system_type *type,
|
||||||
int (*test)(struct super_block *,void *),
|
int (*test)(struct super_block *,void *),
|
||||||
|
@ -2117,7 +2118,7 @@ extern struct file *create_write_pipe(int flags);
|
||||||
extern void free_write_pipe(struct file *);
|
extern void free_write_pipe(struct file *);
|
||||||
|
|
||||||
extern struct file *do_filp_open(int dfd, const char *pathname,
|
extern struct file *do_filp_open(int dfd, const char *pathname,
|
||||||
int open_flag, int mode);
|
int open_flag, int mode, int acc_mode);
|
||||||
extern int may_open(struct path *, int, int);
|
extern int may_open(struct path *, int, int);
|
||||||
|
|
||||||
extern int kernel_read(struct file *, unsigned long, char *, unsigned long);
|
extern int kernel_read(struct file *, unsigned long, char *, unsigned long);
|
||||||
|
@ -2367,6 +2368,7 @@ extern void file_update_time(struct file *file);
|
||||||
|
|
||||||
extern int generic_show_options(struct seq_file *m, struct vfsmount *mnt);
|
extern int generic_show_options(struct seq_file *m, struct vfsmount *mnt);
|
||||||
extern void save_mount_options(struct super_block *sb, char *options);
|
extern void save_mount_options(struct super_block *sb, char *options);
|
||||||
|
extern void replace_mount_options(struct super_block *sb, char *options);
|
||||||
|
|
||||||
static inline ino_t parent_ino(struct dentry *dentry)
|
static inline ino_t parent_ino(struct dentry *dentry)
|
||||||
{
|
{
|
||||||
|
|
|
@ -69,7 +69,6 @@ extern int path_lookup(const char *, unsigned, struct nameidata *);
|
||||||
extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
|
extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
|
||||||
const char *, unsigned int, struct nameidata *);
|
const char *, unsigned int, struct nameidata *);
|
||||||
|
|
||||||
extern int path_lookup_open(int dfd, const char *name, unsigned lookup_flags, struct nameidata *, int open_flags);
|
|
||||||
extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
|
extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
|
||||||
int (*open)(struct inode *, struct file *));
|
int (*open)(struct inode *, struct file *));
|
||||||
extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
|
extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
|
||||||
|
|
|
@ -402,7 +402,7 @@ struct reiserfs_sb_info {
|
||||||
int reserved_blocks; /* amount of blocks reserved for further allocations */
|
int reserved_blocks; /* amount of blocks reserved for further allocations */
|
||||||
spinlock_t bitmap_lock; /* this lock on now only used to protect reserved_blocks variable */
|
spinlock_t bitmap_lock; /* this lock on now only used to protect reserved_blocks variable */
|
||||||
struct dentry *priv_root; /* root of /.reiserfs_priv */
|
struct dentry *priv_root; /* root of /.reiserfs_priv */
|
||||||
struct dentry *xattr_root; /* root of /.reiserfs_priv/.xa */
|
struct dentry *xattr_root; /* root of /.reiserfs_priv/xattrs */
|
||||||
int j_errno;
|
int j_errno;
|
||||||
#ifdef CONFIG_QUOTA
|
#ifdef CONFIG_QUOTA
|
||||||
char *s_qf_names[MAXQUOTAS];
|
char *s_qf_names[MAXQUOTAS];
|
||||||
|
@ -488,7 +488,6 @@ enum reiserfs_mount_options {
|
||||||
#define reiserfs_data_log(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_LOG))
|
#define reiserfs_data_log(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_LOG))
|
||||||
#define reiserfs_data_ordered(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_ORDERED))
|
#define reiserfs_data_ordered(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_ORDERED))
|
||||||
#define reiserfs_data_writeback(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_WRITEBACK))
|
#define reiserfs_data_writeback(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_WRITEBACK))
|
||||||
#define reiserfs_xattrs(s) ((s)->s_xattr != NULL)
|
|
||||||
#define reiserfs_xattrs_user(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_XATTRS_USER))
|
#define reiserfs_xattrs_user(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_XATTRS_USER))
|
||||||
#define reiserfs_posixacl(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_POSIXACL))
|
#define reiserfs_posixacl(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_POSIXACL))
|
||||||
#define reiserfs_xattrs_optional(s) (reiserfs_xattrs_user(s) || reiserfs_posixacl(s))
|
#define reiserfs_xattrs_optional(s) (reiserfs_xattrs_user(s) || reiserfs_posixacl(s))
|
||||||
|
|
|
@ -38,6 +38,7 @@ struct nameidata;
|
||||||
int reiserfs_xattr_register_handlers(void) __init;
|
int reiserfs_xattr_register_handlers(void) __init;
|
||||||
void reiserfs_xattr_unregister_handlers(void);
|
void reiserfs_xattr_unregister_handlers(void);
|
||||||
int reiserfs_xattr_init(struct super_block *sb, int mount_flags);
|
int reiserfs_xattr_init(struct super_block *sb, int mount_flags);
|
||||||
|
int reiserfs_lookup_privroot(struct super_block *sb);
|
||||||
int reiserfs_delete_xattrs(struct inode *inode);
|
int reiserfs_delete_xattrs(struct inode *inode);
|
||||||
int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs);
|
int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs);
|
||||||
|
|
||||||
|
@ -97,7 +98,7 @@ static inline size_t reiserfs_xattr_jcreate_nblocks(struct inode *inode)
|
||||||
|
|
||||||
if ((REISERFS_I(inode)->i_flags & i_has_xattr_dir) == 0) {
|
if ((REISERFS_I(inode)->i_flags & i_has_xattr_dir) == 0) {
|
||||||
nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
|
nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
|
||||||
if (REISERFS_SB(inode->i_sb)->xattr_root == NULL)
|
if (!REISERFS_SB(inode->i_sb)->xattr_root->d_inode)
|
||||||
nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
|
nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,9 +53,4 @@ struct romfs_inode {
|
||||||
#define ROMFH_PAD (ROMFH_SIZE-1)
|
#define ROMFH_PAD (ROMFH_SIZE-1)
|
||||||
#define ROMFH_MASK (~ROMFH_PAD)
|
#define ROMFH_MASK (~ROMFH_PAD)
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
|
||||||
|
|
||||||
/* Not much now */
|
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1133,8 +1133,7 @@ static int cgroup_get_sb(struct file_system_type *fs_type,
|
||||||
free_cg_links:
|
free_cg_links:
|
||||||
free_cg_links(&tmp_cg_links);
|
free_cg_links(&tmp_cg_links);
|
||||||
drop_new_super:
|
drop_new_super:
|
||||||
up_write(&sb->s_umount);
|
deactivate_locked_super(sb);
|
||||||
deactivate_super(sb);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1720,14 +1720,14 @@ static bool tomoyo_policy_loader_exists(void)
|
||||||
* policies are not loaded yet.
|
* policies are not loaded yet.
|
||||||
* Thus, let do_execve() call this function everytime.
|
* Thus, let do_execve() call this function everytime.
|
||||||
*/
|
*/
|
||||||
struct nameidata nd;
|
struct path path;
|
||||||
|
|
||||||
if (path_lookup(tomoyo_loader, LOOKUP_FOLLOW, &nd)) {
|
if (kern_path(tomoyo_loader, LOOKUP_FOLLOW, &path)) {
|
||||||
printk(KERN_INFO "Not activating Mandatory Access Control now "
|
printk(KERN_INFO "Not activating Mandatory Access Control now "
|
||||||
"since %s doesn't exist.\n", tomoyo_loader);
|
"since %s doesn't exist.\n", tomoyo_loader);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
path_put(&nd.path);
|
path_put(&path);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -165,11 +165,11 @@ char *tomoyo_realpath_from_path(struct path *path)
|
||||||
*/
|
*/
|
||||||
char *tomoyo_realpath(const char *pathname)
|
char *tomoyo_realpath(const char *pathname)
|
||||||
{
|
{
|
||||||
struct nameidata nd;
|
struct path path;
|
||||||
|
|
||||||
if (pathname && path_lookup(pathname, LOOKUP_FOLLOW, &nd) == 0) {
|
if (pathname && kern_path(pathname, LOOKUP_FOLLOW, &path) == 0) {
|
||||||
char *buf = tomoyo_realpath_from_path(&nd.path);
|
char *buf = tomoyo_realpath_from_path(&path);
|
||||||
path_put(&nd.path);
|
path_put(&path);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -184,11 +184,11 @@ char *tomoyo_realpath(const char *pathname)
|
||||||
*/
|
*/
|
||||||
char *tomoyo_realpath_nofollow(const char *pathname)
|
char *tomoyo_realpath_nofollow(const char *pathname)
|
||||||
{
|
{
|
||||||
struct nameidata nd;
|
struct path path;
|
||||||
|
|
||||||
if (pathname && path_lookup(pathname, 0, &nd) == 0) {
|
if (pathname && kern_path(pathname, 0, &path) == 0) {
|
||||||
char *buf = tomoyo_realpath_from_path(&nd.path);
|
char *buf = tomoyo_realpath_from_path(&path);
|
||||||
path_put(&nd.path);
|
path_put(&path);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче