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: [PATCH] pass struct path * to do_add_mount() [PATCH] switch mtd and dm-table to lookup_bdev() [patch 3/4] vfs: remove unused nameidata argument of may_create() [PATCH] devpts: switch to IDA [PATCH 2/2] proc: switch inode number allocation to IDA [PATCH 1/2] proc: fix inode number bogorithmetic [PATCH] fix bdev leak in block_dev.c do_open() [PATCH] fix races and leaks in vfs_quota_on() users [PATCH] clean dup2() up a bit [PATCH] merge locate_fd() and get_unused_fd() [PATCH] ipv4_static_sysctl_init() should be under CONFIG_SYSCTL Re: BUG at security/selinux/avc.c:883 (was: Re: linux-next: Tree
This commit is contained in:
commit
d65f5c5803
@ -316,29 +316,12 @@ static inline int check_space(struct dm_table *t)
|
|||||||
*/
|
*/
|
||||||
static int lookup_device(const char *path, dev_t *dev)
|
static int lookup_device(const char *path, dev_t *dev)
|
||||||
{
|
{
|
||||||
int r;
|
struct block_device *bdev = lookup_bdev(path);
|
||||||
struct nameidata nd;
|
if (IS_ERR(bdev))
|
||||||
struct inode *inode;
|
return PTR_ERR(bdev);
|
||||||
|
*dev = bdev->bd_dev;
|
||||||
if ((r = path_lookup(path, LOOKUP_FOLLOW, &nd)))
|
bdput(bdev);
|
||||||
return r;
|
return 0;
|
||||||
|
|
||||||
inode = nd.path.dentry->d_inode;
|
|
||||||
if (!inode) {
|
|
||||||
r = -ENOENT;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!S_ISBLK(inode->i_mode)) {
|
|
||||||
r = -ENOTBLK;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
*dev = inode->i_rdev;
|
|
||||||
|
|
||||||
out:
|
|
||||||
path_put(&nd.path);
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -125,7 +125,7 @@ int get_sb_mtd(struct file_system_type *fs_type, int flags,
|
|||||||
int (*fill_super)(struct super_block *, void *, int),
|
int (*fill_super)(struct super_block *, void *, int),
|
||||||
struct vfsmount *mnt)
|
struct vfsmount *mnt)
|
||||||
{
|
{
|
||||||
struct nameidata nd;
|
struct block_device *bdev;
|
||||||
int mtdnr, ret;
|
int mtdnr, ret;
|
||||||
|
|
||||||
if (!dev_name)
|
if (!dev_name)
|
||||||
@ -181,29 +181,20 @@ int get_sb_mtd(struct file_system_type *fs_type, int flags,
|
|||||||
/* try the old way - the hack where we allowed users to mount
|
/* try the old way - the hack where we allowed users to mount
|
||||||
* /dev/mtdblock$(n) but didn't actually _use_ the blockdev
|
* /dev/mtdblock$(n) but didn't actually _use_ the blockdev
|
||||||
*/
|
*/
|
||||||
ret = path_lookup(dev_name, LOOKUP_FOLLOW, &nd);
|
bdev = lookup_bdev(dev_name);
|
||||||
|
if (IS_ERR(bdev)) {
|
||||||
DEBUG(1, "MTDSB: path_lookup() returned %d, inode %p\n",
|
ret = PTR_ERR(bdev);
|
||||||
ret, nd.path.dentry ? nd.path.dentry->d_inode : NULL);
|
DEBUG(1, "MTDSB: lookup_bdev() returned %d\n", ret);
|
||||||
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
DEBUG(1, "MTDSB: lookup_bdev() returned 0\n");
|
||||||
|
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
if (MAJOR(bdev->bd_dev) != MTD_BLOCK_MAJOR)
|
||||||
if (!S_ISBLK(nd.path.dentry->d_inode->i_mode))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (nd.path.mnt->mnt_flags & MNT_NODEV) {
|
|
||||||
ret = -EACCES;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (imajor(nd.path.dentry->d_inode) != MTD_BLOCK_MAJOR)
|
|
||||||
goto not_an_MTD_device;
|
goto not_an_MTD_device;
|
||||||
|
|
||||||
mtdnr = iminor(nd.path.dentry->d_inode);
|
mtdnr = MINOR(bdev->bd_dev);
|
||||||
path_put(&nd.path);
|
bdput(bdev);
|
||||||
|
|
||||||
return get_sb_mtd_nr(fs_type, flags, dev_name, data, mtdnr, fill_super,
|
return get_sb_mtd_nr(fs_type, flags, dev_name, data, mtdnr, fill_super,
|
||||||
mnt);
|
mnt);
|
||||||
@ -213,10 +204,8 @@ int get_sb_mtd(struct file_system_type *fs_type, int flags,
|
|||||||
printk(KERN_NOTICE
|
printk(KERN_NOTICE
|
||||||
"MTD: Attempt to mount non-MTD device \"%s\"\n",
|
"MTD: Attempt to mount non-MTD device \"%s\"\n",
|
||||||
dev_name);
|
dev_name);
|
||||||
out:
|
bdput(bdev);
|
||||||
path_put(&nd.path);
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL_GPL(get_sb_mtd);
|
EXPORT_SYMBOL_GPL(get_sb_mtd);
|
||||||
|
@ -232,7 +232,7 @@ static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
mntget(newmnt);
|
mntget(newmnt);
|
||||||
err = do_add_mount(newmnt, nd, MNT_SHRINKABLE, &afs_vfsmounts);
|
err = do_add_mount(newmnt, &nd->path, MNT_SHRINKABLE, &afs_vfsmounts);
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case 0:
|
case 0:
|
||||||
path_put(&nd->path);
|
path_put(&nd->path);
|
||||||
|
@ -941,8 +941,10 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part)
|
|||||||
* hooks: /n/, see "layering violations".
|
* hooks: /n/, see "layering violations".
|
||||||
*/
|
*/
|
||||||
ret = devcgroup_inode_permission(bdev->bd_inode, perm);
|
ret = devcgroup_inode_permission(bdev->bd_inode, perm);
|
||||||
if (ret != 0)
|
if (ret != 0) {
|
||||||
|
bdput(bdev);
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
ret = -ENXIO;
|
ret = -ENXIO;
|
||||||
file->f_mapping = bdev->bd_inode->i_mapping;
|
file->f_mapping = bdev->bd_inode->i_mapping;
|
||||||
@ -1234,6 +1236,7 @@ struct block_device *lookup_bdev(const char *path)
|
|||||||
bdev = ERR_PTR(error);
|
bdev = ERR_PTR(error);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(lookup_bdev);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* open_bdev_excl - open a block device by name and set it up for use
|
* open_bdev_excl - open a block device by name and set it up for use
|
||||||
|
@ -226,7 +226,7 @@ static int add_mount_helper(struct vfsmount *newmnt, struct nameidata *nd,
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
mntget(newmnt);
|
mntget(newmnt);
|
||||||
err = do_add_mount(newmnt, nd, nd->path.mnt->mnt_flags, mntlist);
|
err = do_add_mount(newmnt, &nd->path, nd->path.mnt->mnt_flags, mntlist);
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case 0:
|
case 0:
|
||||||
path_put(&nd->path);
|
path_put(&nd->path);
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#define DEVPTS_DEFAULT_MODE 0600
|
#define DEVPTS_DEFAULT_MODE 0600
|
||||||
|
|
||||||
extern int pty_limit; /* Config limit on Unix98 ptys */
|
extern int pty_limit; /* Config limit on Unix98 ptys */
|
||||||
static DEFINE_IDR(allocated_ptys);
|
static DEFINE_IDA(allocated_ptys);
|
||||||
static DEFINE_MUTEX(allocated_ptys_lock);
|
static DEFINE_MUTEX(allocated_ptys_lock);
|
||||||
|
|
||||||
static struct vfsmount *devpts_mnt;
|
static struct vfsmount *devpts_mnt;
|
||||||
@ -180,24 +180,24 @@ static struct dentry *get_node(int num)
|
|||||||
int devpts_new_index(void)
|
int devpts_new_index(void)
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
int idr_ret;
|
int ida_ret;
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) {
|
if (!ida_pre_get(&allocated_ptys, GFP_KERNEL)) {
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&allocated_ptys_lock);
|
mutex_lock(&allocated_ptys_lock);
|
||||||
idr_ret = idr_get_new(&allocated_ptys, NULL, &index);
|
ida_ret = ida_get_new(&allocated_ptys, &index);
|
||||||
if (idr_ret < 0) {
|
if (ida_ret < 0) {
|
||||||
mutex_unlock(&allocated_ptys_lock);
|
mutex_unlock(&allocated_ptys_lock);
|
||||||
if (idr_ret == -EAGAIN)
|
if (ida_ret == -EAGAIN)
|
||||||
goto retry;
|
goto retry;
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index >= pty_limit) {
|
if (index >= pty_limit) {
|
||||||
idr_remove(&allocated_ptys, index);
|
ida_remove(&allocated_ptys, index);
|
||||||
mutex_unlock(&allocated_ptys_lock);
|
mutex_unlock(&allocated_ptys_lock);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
@ -208,7 +208,7 @@ int devpts_new_index(void)
|
|||||||
void devpts_kill_index(int idx)
|
void devpts_kill_index(int idx)
|
||||||
{
|
{
|
||||||
mutex_lock(&allocated_ptys_lock);
|
mutex_lock(&allocated_ptys_lock);
|
||||||
idr_remove(&allocated_ptys, idx);
|
ida_remove(&allocated_ptys, idx);
|
||||||
mutex_unlock(&allocated_ptys_lock);
|
mutex_unlock(&allocated_ptys_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
33
fs/dquot.c
33
fs/dquot.c
@ -1793,6 +1793,21 @@ static int vfs_quota_on_remount(struct super_block *sb, int type)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int vfs_quota_on_path(struct super_block *sb, int type, int format_id,
|
||||||
|
struct path *path)
|
||||||
|
{
|
||||||
|
int error = security_quota_on(path->dentry);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
/* Quota file not on the same filesystem? */
|
||||||
|
if (path->mnt->mnt_sb != sb)
|
||||||
|
error = -EXDEV;
|
||||||
|
else
|
||||||
|
error = vfs_quota_on_inode(path->dentry->d_inode, type,
|
||||||
|
format_id);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
/* Actual function called from quotactl() */
|
/* Actual function called from quotactl() */
|
||||||
int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path,
|
int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path,
|
||||||
int remount)
|
int remount)
|
||||||
@ -1804,19 +1819,10 @@ int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path,
|
|||||||
return vfs_quota_on_remount(sb, type);
|
return vfs_quota_on_remount(sb, type);
|
||||||
|
|
||||||
error = path_lookup(path, LOOKUP_FOLLOW, &nd);
|
error = path_lookup(path, LOOKUP_FOLLOW, &nd);
|
||||||
if (error < 0)
|
if (!error) {
|
||||||
return error;
|
error = vfs_quota_on_path(sb, type, format_id, &nd.path);
|
||||||
error = security_quota_on(nd.path.dentry);
|
path_put(&nd.path);
|
||||||
if (error)
|
}
|
||||||
goto out_path;
|
|
||||||
/* Quota file not on the same filesystem? */
|
|
||||||
if (nd.path.mnt->mnt_sb != sb)
|
|
||||||
error = -EXDEV;
|
|
||||||
else
|
|
||||||
error = vfs_quota_on_inode(nd.path.dentry->d_inode, type,
|
|
||||||
format_id);
|
|
||||||
out_path:
|
|
||||||
path_put(&nd.path);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2185,6 +2191,7 @@ EXPORT_SYMBOL(unregister_quota_format);
|
|||||||
EXPORT_SYMBOL(dqstats);
|
EXPORT_SYMBOL(dqstats);
|
||||||
EXPORT_SYMBOL(dq_data_lock);
|
EXPORT_SYMBOL(dq_data_lock);
|
||||||
EXPORT_SYMBOL(vfs_quota_on);
|
EXPORT_SYMBOL(vfs_quota_on);
|
||||||
|
EXPORT_SYMBOL(vfs_quota_on_path);
|
||||||
EXPORT_SYMBOL(vfs_quota_on_mount);
|
EXPORT_SYMBOL(vfs_quota_on_mount);
|
||||||
EXPORT_SYMBOL(vfs_quota_off);
|
EXPORT_SYMBOL(vfs_quota_off);
|
||||||
EXPORT_SYMBOL(vfs_quota_sync);
|
EXPORT_SYMBOL(vfs_quota_sync);
|
||||||
|
@ -2810,8 +2810,9 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id,
|
|||||||
journal_unlock_updates(EXT3_SB(sb)->s_journal);
|
journal_unlock_updates(EXT3_SB(sb)->s_journal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = vfs_quota_on_path(sb, type, format_id, &nd.path);
|
||||||
path_put(&nd.path);
|
path_put(&nd.path);
|
||||||
return vfs_quota_on(sb, type, format_id, path, remount);
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read data from quotafile - avoid pagecache and such because we cannot afford
|
/* Read data from quotafile - avoid pagecache and such because we cannot afford
|
||||||
|
@ -3352,8 +3352,9 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
|
|||||||
jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
|
jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = vfs_quota_on_path(sb, type, format_id, &nd.path);
|
||||||
path_put(&nd.path);
|
path_put(&nd.path);
|
||||||
return vfs_quota_on(sb, type, format_id, path, remount);
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read data from quotafile - avoid pagecache and such because we cannot afford
|
/* Read data from quotafile - avoid pagecache and such because we cannot afford
|
||||||
|
138
fs/fcntl.c
138
fs/fcntl.c
@ -49,73 +49,6 @@ static int get_close_on_exec(unsigned int fd)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* locate_fd finds a free file descriptor in the open_fds fdset,
|
|
||||||
* expanding the fd arrays if necessary. Must be called with the
|
|
||||||
* file_lock held for write.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int locate_fd(unsigned int orig_start, int cloexec)
|
|
||||||
{
|
|
||||||
struct files_struct *files = current->files;
|
|
||||||
unsigned int newfd;
|
|
||||||
unsigned int start;
|
|
||||||
int error;
|
|
||||||
struct fdtable *fdt;
|
|
||||||
|
|
||||||
spin_lock(&files->file_lock);
|
|
||||||
repeat:
|
|
||||||
fdt = files_fdtable(files);
|
|
||||||
/*
|
|
||||||
* Someone might have closed fd's in the range
|
|
||||||
* orig_start..fdt->next_fd
|
|
||||||
*/
|
|
||||||
start = orig_start;
|
|
||||||
if (start < files->next_fd)
|
|
||||||
start = files->next_fd;
|
|
||||||
|
|
||||||
newfd = start;
|
|
||||||
if (start < fdt->max_fds)
|
|
||||||
newfd = find_next_zero_bit(fdt->open_fds->fds_bits,
|
|
||||||
fdt->max_fds, start);
|
|
||||||
|
|
||||||
error = expand_files(files, newfd);
|
|
||||||
if (error < 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we needed to expand the fs array we
|
|
||||||
* might have blocked - try again.
|
|
||||||
*/
|
|
||||||
if (error)
|
|
||||||
goto repeat;
|
|
||||||
|
|
||||||
if (start <= files->next_fd)
|
|
||||||
files->next_fd = newfd + 1;
|
|
||||||
|
|
||||||
FD_SET(newfd, fdt->open_fds);
|
|
||||||
if (cloexec)
|
|
||||||
FD_SET(newfd, fdt->close_on_exec);
|
|
||||||
else
|
|
||||||
FD_CLR(newfd, fdt->close_on_exec);
|
|
||||||
error = newfd;
|
|
||||||
|
|
||||||
out:
|
|
||||||
spin_unlock(&files->file_lock);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int dupfd(struct file *file, unsigned int start, int cloexec)
|
|
||||||
{
|
|
||||||
int fd = locate_fd(start, cloexec);
|
|
||||||
if (fd >= 0)
|
|
||||||
fd_install(fd, file);
|
|
||||||
else
|
|
||||||
fput(file);
|
|
||||||
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags)
|
asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags)
|
||||||
{
|
{
|
||||||
int err = -EBADF;
|
int err = -EBADF;
|
||||||
@ -130,31 +63,35 @@ asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
spin_lock(&files->file_lock);
|
spin_lock(&files->file_lock);
|
||||||
if (!(file = fcheck(oldfd)))
|
|
||||||
goto out_unlock;
|
|
||||||
get_file(file); /* We are now finished with oldfd */
|
|
||||||
|
|
||||||
err = expand_files(files, newfd);
|
err = expand_files(files, newfd);
|
||||||
|
file = fcheck(oldfd);
|
||||||
|
if (unlikely(!file))
|
||||||
|
goto Ebadf;
|
||||||
if (unlikely(err < 0)) {
|
if (unlikely(err < 0)) {
|
||||||
if (err == -EMFILE)
|
if (err == -EMFILE)
|
||||||
err = -EBADF;
|
goto Ebadf;
|
||||||
goto out_fput;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
/* To avoid races with open() and dup(), we will mark the fd as
|
* We need to detect attempts to do dup2() over allocated but still
|
||||||
* in-use in the open-file bitmap throughout the entire dup2()
|
* not finished descriptor. NB: OpenBSD avoids that at the price of
|
||||||
* process. This is quite safe: do_close() uses the fd array
|
* extra work in their equivalent of fget() - they insert struct
|
||||||
* entry, not the bitmap, to decide what work needs to be
|
* file immediately after grabbing descriptor, mark it larval if
|
||||||
* done. --sct */
|
* more work (e.g. actual opening) is needed and make sure that
|
||||||
/* Doesn't work. open() might be there first. --AV */
|
* fget() treats larval files as absent. Potentially interesting,
|
||||||
|
* but while extra work in fget() is trivial, locking implications
|
||||||
/* Yes. It's a race. In user space. Nothing sane to do */
|
* and amount of surgery on open()-related paths in VFS are not.
|
||||||
|
* FreeBSD fails with -EBADF in the same situation, NetBSD "solution"
|
||||||
|
* deadlocks in rather amusing ways, AFAICS. All of that is out of
|
||||||
|
* scope of POSIX or SUS, since neither considers shared descriptor
|
||||||
|
* tables and this condition does not arise without those.
|
||||||
|
*/
|
||||||
err = -EBUSY;
|
err = -EBUSY;
|
||||||
fdt = files_fdtable(files);
|
fdt = files_fdtable(files);
|
||||||
tofree = fdt->fd[newfd];
|
tofree = fdt->fd[newfd];
|
||||||
if (!tofree && FD_ISSET(newfd, fdt->open_fds))
|
if (!tofree && FD_ISSET(newfd, fdt->open_fds))
|
||||||
goto out_fput;
|
goto out_unlock;
|
||||||
|
get_file(file);
|
||||||
rcu_assign_pointer(fdt->fd[newfd], file);
|
rcu_assign_pointer(fdt->fd[newfd], file);
|
||||||
FD_SET(newfd, fdt->open_fds);
|
FD_SET(newfd, fdt->open_fds);
|
||||||
if (flags & O_CLOEXEC)
|
if (flags & O_CLOEXEC)
|
||||||
@ -165,17 +102,14 @@ asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags)
|
|||||||
|
|
||||||
if (tofree)
|
if (tofree)
|
||||||
filp_close(tofree, files);
|
filp_close(tofree, files);
|
||||||
err = newfd;
|
|
||||||
out:
|
return newfd;
|
||||||
return err;
|
|
||||||
|
Ebadf:
|
||||||
|
err = -EBADF;
|
||||||
out_unlock:
|
out_unlock:
|
||||||
spin_unlock(&files->file_lock);
|
spin_unlock(&files->file_lock);
|
||||||
goto out;
|
return err;
|
||||||
|
|
||||||
out_fput:
|
|
||||||
spin_unlock(&files->file_lock);
|
|
||||||
fput(file);
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
|
asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
|
||||||
@ -194,10 +128,15 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
|
|||||||
asmlinkage long sys_dup(unsigned int fildes)
|
asmlinkage long sys_dup(unsigned int fildes)
|
||||||
{
|
{
|
||||||
int ret = -EBADF;
|
int ret = -EBADF;
|
||||||
struct file * file = fget(fildes);
|
struct file *file = fget(fildes);
|
||||||
|
|
||||||
if (file)
|
if (file) {
|
||||||
ret = dupfd(file, 0, 0);
|
ret = get_unused_fd();
|
||||||
|
if (ret >= 0)
|
||||||
|
fd_install(ret, file);
|
||||||
|
else
|
||||||
|
fput(file);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -322,8 +261,11 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
|
|||||||
case F_DUPFD_CLOEXEC:
|
case F_DUPFD_CLOEXEC:
|
||||||
if (arg >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
|
if (arg >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
|
||||||
break;
|
break;
|
||||||
get_file(filp);
|
err = alloc_fd(arg, cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0);
|
||||||
err = dupfd(filp, arg, cmd == F_DUPFD_CLOEXEC);
|
if (err >= 0) {
|
||||||
|
get_file(filp);
|
||||||
|
fd_install(err, filp);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case F_GETFD:
|
case F_GETFD:
|
||||||
err = get_close_on_exec(fd) ? FD_CLOEXEC : 0;
|
err = get_close_on_exec(fd) ? FD_CLOEXEC : 0;
|
||||||
|
61
fs/file.c
61
fs/file.c
@ -6,6 +6,7 @@
|
|||||||
* Manage the dynamic fd arrays in the process files_struct.
|
* Manage the dynamic fd arrays in the process files_struct.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/time.h>
|
#include <linux/time.h>
|
||||||
@ -432,3 +433,63 @@ struct files_struct init_files = {
|
|||||||
},
|
},
|
||||||
.file_lock = __SPIN_LOCK_UNLOCKED(init_task.file_lock),
|
.file_lock = __SPIN_LOCK_UNLOCKED(init_task.file_lock),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* allocate a file descriptor, mark it busy.
|
||||||
|
*/
|
||||||
|
int alloc_fd(unsigned start, unsigned flags)
|
||||||
|
{
|
||||||
|
struct files_struct *files = current->files;
|
||||||
|
unsigned int fd;
|
||||||
|
int error;
|
||||||
|
struct fdtable *fdt;
|
||||||
|
|
||||||
|
spin_lock(&files->file_lock);
|
||||||
|
repeat:
|
||||||
|
fdt = files_fdtable(files);
|
||||||
|
fd = start;
|
||||||
|
if (fd < files->next_fd)
|
||||||
|
fd = files->next_fd;
|
||||||
|
|
||||||
|
if (fd < fdt->max_fds)
|
||||||
|
fd = find_next_zero_bit(fdt->open_fds->fds_bits,
|
||||||
|
fdt->max_fds, fd);
|
||||||
|
|
||||||
|
error = expand_files(files, fd);
|
||||||
|
if (error < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we needed to expand the fs array we
|
||||||
|
* might have blocked - try again.
|
||||||
|
*/
|
||||||
|
if (error)
|
||||||
|
goto repeat;
|
||||||
|
|
||||||
|
if (start <= files->next_fd)
|
||||||
|
files->next_fd = fd + 1;
|
||||||
|
|
||||||
|
FD_SET(fd, fdt->open_fds);
|
||||||
|
if (flags & O_CLOEXEC)
|
||||||
|
FD_SET(fd, fdt->close_on_exec);
|
||||||
|
else
|
||||||
|
FD_CLR(fd, fdt->close_on_exec);
|
||||||
|
error = fd;
|
||||||
|
#if 1
|
||||||
|
/* Sanity check */
|
||||||
|
if (rcu_dereference(fdt->fd[fd]) != NULL) {
|
||||||
|
printk(KERN_WARNING "alloc_fd: slot %d not NULL!\n", fd);
|
||||||
|
rcu_assign_pointer(fdt->fd[fd], NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
out:
|
||||||
|
spin_unlock(&files->file_lock);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_unused_fd(void)
|
||||||
|
{
|
||||||
|
return alloc_fd(0, 0);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(get_unused_fd);
|
||||||
|
17
fs/namei.c
17
fs/namei.c
@ -274,7 +274,7 @@ int inode_permission(struct inode *inode, int mask)
|
|||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
return security_inode_permission(inode,
|
return security_inode_permission(inode,
|
||||||
mask & (MAY_READ|MAY_WRITE|MAY_EXEC));
|
mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1431,8 +1431,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
|
|||||||
* 3. We should have write and exec permissions on dir
|
* 3. We should have write and exec permissions on dir
|
||||||
* 4. We can't do it if dir is immutable (done in permission())
|
* 4. We can't do it if dir is immutable (done in permission())
|
||||||
*/
|
*/
|
||||||
static inline int may_create(struct inode *dir, struct dentry *child,
|
static inline int may_create(struct inode *dir, struct dentry *child)
|
||||||
struct nameidata *nd)
|
|
||||||
{
|
{
|
||||||
if (child->d_inode)
|
if (child->d_inode)
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
@ -1504,7 +1503,7 @@ void unlock_rename(struct dentry *p1, struct dentry *p2)
|
|||||||
int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
|
int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
|
||||||
struct nameidata *nd)
|
struct nameidata *nd)
|
||||||
{
|
{
|
||||||
int error = may_create(dir, dentry, nd);
|
int error = may_create(dir, dentry);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
@ -1948,7 +1947,7 @@ EXPORT_SYMBOL_GPL(lookup_create);
|
|||||||
|
|
||||||
int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
|
int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
|
||||||
{
|
{
|
||||||
int error = may_create(dir, dentry, NULL);
|
int error = may_create(dir, dentry);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
@ -2049,7 +2048,7 @@ asmlinkage long sys_mknod(const char __user *filename, int mode, unsigned dev)
|
|||||||
|
|
||||||
int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
|
int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
|
||||||
{
|
{
|
||||||
int error = may_create(dir, dentry, NULL);
|
int error = may_create(dir, dentry);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
@ -2316,7 +2315,7 @@ asmlinkage long sys_unlink(const char __user *pathname)
|
|||||||
|
|
||||||
int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
|
int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
|
||||||
{
|
{
|
||||||
int error = may_create(dir, dentry, NULL);
|
int error = may_create(dir, dentry);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
@ -2386,7 +2385,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
|
|||||||
if (!inode)
|
if (!inode)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
error = may_create(dir, new_dentry, NULL);
|
error = may_create(dir, new_dentry);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
@ -2595,7 +2594,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||||||
return error;
|
return error;
|
||||||
|
|
||||||
if (!new_dentry->d_inode)
|
if (!new_dentry->d_inode)
|
||||||
error = may_create(new_dir, new_dentry, NULL);
|
error = may_create(new_dir, new_dentry);
|
||||||
else
|
else
|
||||||
error = may_delete(new_dir, new_dentry, is_dir);
|
error = may_delete(new_dir, new_dentry, is_dir);
|
||||||
if (error)
|
if (error)
|
||||||
|
@ -1667,31 +1667,31 @@ static noinline int do_new_mount(struct nameidata *nd, char *type, int flags,
|
|||||||
if (IS_ERR(mnt))
|
if (IS_ERR(mnt))
|
||||||
return PTR_ERR(mnt);
|
return PTR_ERR(mnt);
|
||||||
|
|
||||||
return do_add_mount(mnt, nd, mnt_flags, NULL);
|
return do_add_mount(mnt, &nd->path, mnt_flags, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* add a mount into a namespace's mount tree
|
* add a mount into a namespace's mount tree
|
||||||
* - provide the option of adding the new mount to an expiration list
|
* - provide the option of adding the new mount to an expiration list
|
||||||
*/
|
*/
|
||||||
int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd,
|
int do_add_mount(struct vfsmount *newmnt, struct path *path,
|
||||||
int mnt_flags, struct list_head *fslist)
|
int mnt_flags, struct list_head *fslist)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
down_write(&namespace_sem);
|
down_write(&namespace_sem);
|
||||||
/* Something was mounted here while we slept */
|
/* Something was mounted here while we slept */
|
||||||
while (d_mountpoint(nd->path.dentry) &&
|
while (d_mountpoint(path->dentry) &&
|
||||||
follow_down(&nd->path.mnt, &nd->path.dentry))
|
follow_down(&path->mnt, &path->dentry))
|
||||||
;
|
;
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
if (!check_mnt(nd->path.mnt))
|
if (!check_mnt(path->mnt))
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
/* Refuse the same filesystem on the same mount point */
|
/* Refuse the same filesystem on the same mount point */
|
||||||
err = -EBUSY;
|
err = -EBUSY;
|
||||||
if (nd->path.mnt->mnt_sb == newmnt->mnt_sb &&
|
if (path->mnt->mnt_sb == newmnt->mnt_sb &&
|
||||||
nd->path.mnt->mnt_root == nd->path.dentry)
|
path->mnt->mnt_root == path->dentry)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
@ -1699,7 +1699,7 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd,
|
|||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
newmnt->mnt_flags = mnt_flags;
|
newmnt->mnt_flags = mnt_flags;
|
||||||
if ((err = graft_tree(newmnt, &nd->path)))
|
if ((err = graft_tree(newmnt, path)))
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
if (fslist) /* add to the specified expiration list */
|
if (fslist) /* add to the specified expiration list */
|
||||||
|
@ -129,7 +129,7 @@ static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
|
|||||||
goto out_err;
|
goto out_err;
|
||||||
|
|
||||||
mntget(mnt);
|
mntget(mnt);
|
||||||
err = do_add_mount(mnt, nd, nd->path.mnt->mnt_flags|MNT_SHRINKABLE,
|
err = do_add_mount(mnt, &nd->path, nd->path.mnt->mnt_flags|MNT_SHRINKABLE,
|
||||||
&nfs_automount_list);
|
&nfs_automount_list);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
mntput(mnt);
|
mntput(mnt);
|
||||||
|
56
fs/open.c
56
fs/open.c
@ -963,62 +963,6 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(dentry_open);
|
EXPORT_SYMBOL(dentry_open);
|
||||||
|
|
||||||
/*
|
|
||||||
* Find an empty file descriptor entry, and mark it busy.
|
|
||||||
*/
|
|
||||||
int get_unused_fd_flags(int flags)
|
|
||||||
{
|
|
||||||
struct files_struct * files = current->files;
|
|
||||||
int fd, error;
|
|
||||||
struct fdtable *fdt;
|
|
||||||
|
|
||||||
spin_lock(&files->file_lock);
|
|
||||||
|
|
||||||
repeat:
|
|
||||||
fdt = files_fdtable(files);
|
|
||||||
fd = find_next_zero_bit(fdt->open_fds->fds_bits, fdt->max_fds,
|
|
||||||
files->next_fd);
|
|
||||||
|
|
||||||
/* Do we need to expand the fd array or fd set? */
|
|
||||||
error = expand_files(files, fd);
|
|
||||||
if (error < 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
/*
|
|
||||||
* If we needed to expand the fs array we
|
|
||||||
* might have blocked - try again.
|
|
||||||
*/
|
|
||||||
goto repeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
FD_SET(fd, fdt->open_fds);
|
|
||||||
if (flags & O_CLOEXEC)
|
|
||||||
FD_SET(fd, fdt->close_on_exec);
|
|
||||||
else
|
|
||||||
FD_CLR(fd, fdt->close_on_exec);
|
|
||||||
files->next_fd = fd + 1;
|
|
||||||
#if 1
|
|
||||||
/* Sanity check */
|
|
||||||
if (fdt->fd[fd] != NULL) {
|
|
||||||
printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd);
|
|
||||||
fdt->fd[fd] = NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
error = fd;
|
|
||||||
|
|
||||||
out:
|
|
||||||
spin_unlock(&files->file_lock);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_unused_fd(void)
|
|
||||||
{
|
|
||||||
return get_unused_fd_flags(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_SYMBOL(get_unused_fd);
|
|
||||||
|
|
||||||
static void __put_unused_fd(struct files_struct *files, unsigned int fd)
|
static void __put_unused_fd(struct files_struct *files, unsigned int fd)
|
||||||
{
|
{
|
||||||
struct fdtable *fdt = files_fdtable(files);
|
struct fdtable *fdt = files_fdtable(files);
|
||||||
|
@ -300,10 +300,10 @@ static int xlate_proc_name(const char *name,
|
|||||||
return rtn;
|
return rtn;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEFINE_IDR(proc_inum_idr);
|
static DEFINE_IDA(proc_inum_ida);
|
||||||
static DEFINE_SPINLOCK(proc_inum_lock); /* protects the above */
|
static DEFINE_SPINLOCK(proc_inum_lock); /* protects the above */
|
||||||
|
|
||||||
#define PROC_DYNAMIC_FIRST 0xF0000000UL
|
#define PROC_DYNAMIC_FIRST 0xF0000000U
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return an inode number between PROC_DYNAMIC_FIRST and
|
* Return an inode number between PROC_DYNAMIC_FIRST and
|
||||||
@ -311,36 +311,33 @@ static DEFINE_SPINLOCK(proc_inum_lock); /* protects the above */
|
|||||||
*/
|
*/
|
||||||
static unsigned int get_inode_number(void)
|
static unsigned int get_inode_number(void)
|
||||||
{
|
{
|
||||||
int i, inum = 0;
|
unsigned int i;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
if (idr_pre_get(&proc_inum_idr, GFP_KERNEL) == 0)
|
if (ida_pre_get(&proc_inum_ida, GFP_KERNEL) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
spin_lock(&proc_inum_lock);
|
spin_lock(&proc_inum_lock);
|
||||||
error = idr_get_new(&proc_inum_idr, NULL, &i);
|
error = ida_get_new(&proc_inum_ida, &i);
|
||||||
spin_unlock(&proc_inum_lock);
|
spin_unlock(&proc_inum_lock);
|
||||||
if (error == -EAGAIN)
|
if (error == -EAGAIN)
|
||||||
goto retry;
|
goto retry;
|
||||||
else if (error)
|
else if (error)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
inum = (i & MAX_ID_MASK) + PROC_DYNAMIC_FIRST;
|
if (i > UINT_MAX - PROC_DYNAMIC_FIRST) {
|
||||||
|
spin_lock(&proc_inum_lock);
|
||||||
/* inum will never be more than 0xf0ffffff, so no check
|
ida_remove(&proc_inum_ida, i);
|
||||||
* for overflow.
|
spin_unlock(&proc_inum_lock);
|
||||||
*/
|
}
|
||||||
|
return PROC_DYNAMIC_FIRST + i;
|
||||||
return inum;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void release_inode_number(unsigned int inum)
|
static void release_inode_number(unsigned int inum)
|
||||||
{
|
{
|
||||||
int id = (inum - PROC_DYNAMIC_FIRST) | ~MAX_ID_MASK;
|
|
||||||
|
|
||||||
spin_lock(&proc_inum_lock);
|
spin_lock(&proc_inum_lock);
|
||||||
idr_remove(&proc_inum_idr, id);
|
ida_remove(&proc_inum_ida, inum - PROC_DYNAMIC_FIRST);
|
||||||
spin_unlock(&proc_inum_lock);
|
spin_unlock(&proc_inum_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2076,8 +2076,8 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
|
|||||||
return err;
|
return err;
|
||||||
/* Quotafile not on the same filesystem? */
|
/* Quotafile not on the same filesystem? */
|
||||||
if (nd.path.mnt->mnt_sb != sb) {
|
if (nd.path.mnt->mnt_sb != sb) {
|
||||||
path_put(&nd.path);
|
err = -EXDEV;
|
||||||
return -EXDEV;
|
goto out;
|
||||||
}
|
}
|
||||||
inode = nd.path.dentry->d_inode;
|
inode = nd.path.dentry->d_inode;
|
||||||
/* We must not pack tails for quota files on reiserfs for quota IO to work */
|
/* We must not pack tails for quota files on reiserfs for quota IO to work */
|
||||||
@ -2087,8 +2087,8 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
|
|||||||
reiserfs_warning(sb,
|
reiserfs_warning(sb,
|
||||||
"reiserfs: Unpacking tail of quota file failed"
|
"reiserfs: Unpacking tail of quota file failed"
|
||||||
" (%d). Cannot turn on quotas.", err);
|
" (%d). Cannot turn on quotas.", err);
|
||||||
path_put(&nd.path);
|
err = -EINVAL;
|
||||||
return -EINVAL;
|
goto out;
|
||||||
}
|
}
|
||||||
mark_inode_dirty(inode);
|
mark_inode_dirty(inode);
|
||||||
}
|
}
|
||||||
@ -2109,13 +2109,15 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
|
|||||||
/* Just start temporary transaction and finish it */
|
/* Just start temporary transaction and finish it */
|
||||||
err = journal_begin(&th, sb, 1);
|
err = journal_begin(&th, sb, 1);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
goto out;
|
||||||
err = journal_end_sync(&th, sb, 1);
|
err = journal_end_sync(&th, sb, 1);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
goto out;
|
||||||
}
|
}
|
||||||
|
err = vfs_quota_on_path(sb, type, format_id, &nd.path);
|
||||||
|
out:
|
||||||
path_put(&nd.path);
|
path_put(&nd.path);
|
||||||
return vfs_quota_on(sb, type, format_id, path, 0);
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read data from quotafile - avoid pagecache and such because we cannot afford
|
/* Read data from quotafile - avoid pagecache and such because we cannot afford
|
||||||
|
@ -34,8 +34,9 @@ extern struct file *fget(unsigned int fd);
|
|||||||
extern struct file *fget_light(unsigned int fd, int *fput_needed);
|
extern struct file *fget_light(unsigned int fd, int *fput_needed);
|
||||||
extern void set_close_on_exec(unsigned int fd, int flag);
|
extern void set_close_on_exec(unsigned int fd, int flag);
|
||||||
extern void put_filp(struct file *);
|
extern void put_filp(struct file *);
|
||||||
|
extern int alloc_fd(unsigned start, unsigned flags);
|
||||||
extern int get_unused_fd(void);
|
extern int get_unused_fd(void);
|
||||||
extern int get_unused_fd_flags(int flags);
|
#define get_unused_fd_flags(flags) alloc_fd(0, (flags))
|
||||||
extern void put_unused_fd(unsigned int fd);
|
extern void put_unused_fd(unsigned int fd);
|
||||||
|
|
||||||
extern void fd_install(unsigned int fd, struct file *file);
|
extern void fd_install(unsigned int fd, struct file *file);
|
||||||
|
@ -105,7 +105,8 @@ extern struct vfsmount *vfs_kern_mount(struct file_system_type *type,
|
|||||||
|
|
||||||
struct nameidata;
|
struct nameidata;
|
||||||
|
|
||||||
extern int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd,
|
struct path;
|
||||||
|
extern int do_add_mount(struct vfsmount *newmnt, struct path *path,
|
||||||
int mnt_flags, struct list_head *fslist);
|
int mnt_flags, struct list_head *fslist);
|
||||||
|
|
||||||
extern void mark_mounts_for_expiry(struct list_head *mounts);
|
extern void mark_mounts_for_expiry(struct list_head *mounts);
|
||||||
|
@ -43,6 +43,8 @@ int dquot_mark_dquot_dirty(struct dquot *dquot);
|
|||||||
|
|
||||||
int vfs_quota_on(struct super_block *sb, int type, int format_id,
|
int vfs_quota_on(struct super_block *sb, int type, int format_id,
|
||||||
char *path, int remount);
|
char *path, int remount);
|
||||||
|
int vfs_quota_on_path(struct super_block *sb, int type, int format_id,
|
||||||
|
struct path *path);
|
||||||
int vfs_quota_on_mount(struct super_block *sb, char *qf_name,
|
int vfs_quota_on_mount(struct super_block *sb, char *qf_name,
|
||||||
int format_id, int type);
|
int format_id, int type);
|
||||||
int vfs_quota_off(struct super_block *sb, int type, int remount);
|
int vfs_quota_off(struct super_block *sb, int type, int remount);
|
||||||
|
@ -3216,6 +3216,7 @@ int __init ip_rt_init(void)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SYSCTL
|
||||||
/*
|
/*
|
||||||
* We really need to sanitize the damn ipv4 init order, then all
|
* We really need to sanitize the damn ipv4 init order, then all
|
||||||
* this nonsense will go away.
|
* this nonsense will go away.
|
||||||
@ -3224,6 +3225,7 @@ void __init ip_static_sysctl_init(void)
|
|||||||
{
|
{
|
||||||
register_sysctl_paths(ipv4_route_path, ipv4_route_table);
|
register_sysctl_paths(ipv4_route_path, ipv4_route_table);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
EXPORT_SYMBOL(__ip_select_ident);
|
EXPORT_SYMBOL(__ip_select_ident);
|
||||||
EXPORT_SYMBOL(ip_route_input);
|
EXPORT_SYMBOL(ip_route_input);
|
||||||
|
Loading…
Reference in New Issue
Block a user