Merge branch 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull misc vfs updates from Al Viro: "Assorted stuff pile - no common topic here" * 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: whack-a-mole: don't open-code iminor/imajor 9p: fix misuse of sscanf() in v9fs_stat2inode() audit_alloc_mark(): don't open-code ERR_CAST() fs/inode.c: make inode_init_always() initialize i_ino to 0 vfs: don't unnecessarily clone write access for writable fds
This commit is contained in:
Коммит
5ceabb6078
|
@ -883,3 +883,10 @@ For bvec based itererators bio_iov_iter_get_pages() now doesn't copy bvecs but
|
||||||
uses the one provided. Anyone issuing kiocb-I/O should ensure that the bvec and
|
uses the one provided. Anyone issuing kiocb-I/O should ensure that the bvec and
|
||||||
page references stay until I/O has completed, i.e. until ->ki_complete() has
|
page references stay until I/O has completed, i.e. until ->ki_complete() has
|
||||||
been called or returned with non -EIOCBQUEUED code.
|
been called or returned with non -EIOCBQUEUED code.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**mandatory**
|
||||||
|
|
||||||
|
mnt_want_write_file() can now only be paired with mnt_drop_write_file(),
|
||||||
|
whereas previously it could be paired with mnt_drop_write() as well.
|
||||||
|
|
|
@ -27,11 +27,10 @@ static int openCnt;
|
||||||
|
|
||||||
static int gio_open(struct inode *inode, struct file *filp)
|
static int gio_open(struct inode *inode, struct file *filp)
|
||||||
{
|
{
|
||||||
int minor;
|
int minor = iminor(inode);
|
||||||
int ret = -ENOENT;
|
int ret = -ENOENT;
|
||||||
|
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
minor = MINOR(inode->i_rdev);
|
|
||||||
if (minor < DEVCOUNT) {
|
if (minor < DEVCOUNT) {
|
||||||
if (openCnt > 0) {
|
if (openCnt > 0) {
|
||||||
ret = -EALREADY;
|
ret = -EALREADY;
|
||||||
|
@ -46,9 +45,8 @@ static int gio_open(struct inode *inode, struct file *filp)
|
||||||
|
|
||||||
static int gio_close(struct inode *inode, struct file *filp)
|
static int gio_close(struct inode *inode, struct file *filp)
|
||||||
{
|
{
|
||||||
int minor;
|
int minor = iminor(inode);
|
||||||
|
|
||||||
minor = MINOR(inode->i_rdev);
|
|
||||||
if (minor < DEVCOUNT) {
|
if (minor < DEVCOUNT) {
|
||||||
openCnt--;
|
openCnt--;
|
||||||
}
|
}
|
||||||
|
|
|
@ -663,7 +663,7 @@ static inline int is_loop_device(struct file *file)
|
||||||
{
|
{
|
||||||
struct inode *i = file->f_mapping->host;
|
struct inode *i = file->f_mapping->host;
|
||||||
|
|
||||||
return i && S_ISBLK(i->i_mode) && MAJOR(i->i_rdev) == LOOP_MAJOR;
|
return i && S_ISBLK(i->i_mode) && imajor(i) == LOOP_MAJOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int loop_validate_file(struct file *file, struct block_device *bdev)
|
static int loop_validate_file(struct file *file, struct block_device *bdev)
|
||||||
|
|
|
@ -480,7 +480,7 @@ static void dax_free_inode(struct inode *inode)
|
||||||
kfree(dax_dev->host);
|
kfree(dax_dev->host);
|
||||||
dax_dev->host = NULL;
|
dax_dev->host = NULL;
|
||||||
if (inode->i_rdev)
|
if (inode->i_rdev)
|
||||||
ida_simple_remove(&dax_minor_ida, MINOR(inode->i_rdev));
|
ida_simple_remove(&dax_minor_ida, iminor(inode));
|
||||||
kmem_cache_free(dax_cache, dax_dev);
|
kmem_cache_free(dax_cache, dax_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -785,7 +785,7 @@ static long wdt_unlocked_ioctl(struct file *file, unsigned int cmd,
|
||||||
*/
|
*/
|
||||||
static int wdt_open(struct inode *inode, struct file *file)
|
static int wdt_open(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
|
if (iminor(inode) == WATCHDOG_MINOR) {
|
||||||
mutex_lock(&m41t80_rtc_mutex);
|
mutex_lock(&m41t80_rtc_mutex);
|
||||||
if (test_and_set_bit(0, &wdt_is_open)) {
|
if (test_and_set_bit(0, &wdt_is_open)) {
|
||||||
mutex_unlock(&m41t80_rtc_mutex);
|
mutex_unlock(&m41t80_rtc_mutex);
|
||||||
|
@ -809,7 +809,7 @@ static int wdt_open(struct inode *inode, struct file *file)
|
||||||
*/
|
*/
|
||||||
static int wdt_release(struct inode *inode, struct file *file)
|
static int wdt_release(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
if (MINOR(inode->i_rdev) == WATCHDOG_MINOR)
|
if (iminor(inode) == WATCHDOG_MINOR)
|
||||||
clear_bit(0, &wdt_is_open);
|
clear_bit(0, &wdt_is_open);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -681,7 +681,7 @@ static int ur_open(struct inode *inode, struct file *file)
|
||||||
* We treat the minor number as the devno of the ur device
|
* We treat the minor number as the devno of the ur device
|
||||||
* to find in the driver tree.
|
* to find in the driver tree.
|
||||||
*/
|
*/
|
||||||
devno = MINOR(file_inode(file)->i_rdev);
|
devno = iminor(file_inode(file));
|
||||||
|
|
||||||
urd = urdev_get_from_devno(devno);
|
urd = urdev_get_from_devno(devno);
|
||||||
if (!urd) {
|
if (!urd) {
|
||||||
|
|
|
@ -175,7 +175,7 @@ static ssize_t buffer_from_user(unsigned int minor, const char __user *buf,
|
||||||
static ssize_t vme_user_read(struct file *file, char __user *buf, size_t count,
|
static ssize_t vme_user_read(struct file *file, char __user *buf, size_t count,
|
||||||
loff_t *ppos)
|
loff_t *ppos)
|
||||||
{
|
{
|
||||||
unsigned int minor = MINOR(file_inode(file)->i_rdev);
|
unsigned int minor = iminor(file_inode(file));
|
||||||
ssize_t retval;
|
ssize_t retval;
|
||||||
size_t image_size;
|
size_t image_size;
|
||||||
|
|
||||||
|
@ -218,7 +218,7 @@ static ssize_t vme_user_read(struct file *file, char __user *buf, size_t count,
|
||||||
static ssize_t vme_user_write(struct file *file, const char __user *buf,
|
static ssize_t vme_user_write(struct file *file, const char __user *buf,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
unsigned int minor = MINOR(file_inode(file)->i_rdev);
|
unsigned int minor = iminor(file_inode(file));
|
||||||
ssize_t retval;
|
ssize_t retval;
|
||||||
size_t image_size;
|
size_t image_size;
|
||||||
|
|
||||||
|
@ -260,7 +260,7 @@ static ssize_t vme_user_write(struct file *file, const char __user *buf,
|
||||||
|
|
||||||
static loff_t vme_user_llseek(struct file *file, loff_t off, int whence)
|
static loff_t vme_user_llseek(struct file *file, loff_t off, int whence)
|
||||||
{
|
{
|
||||||
unsigned int minor = MINOR(file_inode(file)->i_rdev);
|
unsigned int minor = iminor(file_inode(file));
|
||||||
size_t image_size;
|
size_t image_size;
|
||||||
loff_t res;
|
loff_t res;
|
||||||
|
|
||||||
|
@ -294,7 +294,7 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,
|
||||||
struct vme_slave slave;
|
struct vme_slave slave;
|
||||||
struct vme_irq_id irq_req;
|
struct vme_irq_id irq_req;
|
||||||
unsigned long copied;
|
unsigned long copied;
|
||||||
unsigned int minor = MINOR(inode->i_rdev);
|
unsigned int minor = iminor(inode);
|
||||||
int retval;
|
int retval;
|
||||||
dma_addr_t pci_addr;
|
dma_addr_t pci_addr;
|
||||||
void __user *argp = (void __user *)arg;
|
void __user *argp = (void __user *)arg;
|
||||||
|
@ -412,7 +412,7 @@ vme_user_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct inode *inode = file_inode(file);
|
struct inode *inode = file_inode(file);
|
||||||
unsigned int minor = MINOR(inode->i_rdev);
|
unsigned int minor = iminor(inode);
|
||||||
|
|
||||||
mutex_lock(&image[minor].mutex);
|
mutex_lock(&image[minor].mutex);
|
||||||
ret = vme_user_ioctl(inode, file, cmd, arg);
|
ret = vme_user_ioctl(inode, file, cmd, arg);
|
||||||
|
@ -481,7 +481,7 @@ static int vme_user_master_mmap(unsigned int minor, struct vm_area_struct *vma)
|
||||||
|
|
||||||
static int vme_user_mmap(struct file *file, struct vm_area_struct *vma)
|
static int vme_user_mmap(struct file *file, struct vm_area_struct *vma)
|
||||||
{
|
{
|
||||||
unsigned int minor = MINOR(file_inode(file)->i_rdev);
|
unsigned int minor = iminor(file_inode(file));
|
||||||
|
|
||||||
if (type[minor] == MASTER_MINOR)
|
if (type[minor] == MASTER_MINOR)
|
||||||
return vme_user_master_mmap(minor, vma);
|
return vme_user_master_mmap(minor, vma);
|
||||||
|
|
|
@ -1139,9 +1139,6 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
|
||||||
struct super_block *sb, unsigned int flags)
|
struct super_block *sb, unsigned int flags)
|
||||||
{
|
{
|
||||||
umode_t mode;
|
umode_t mode;
|
||||||
char ext[32];
|
|
||||||
char tag_name[14];
|
|
||||||
unsigned int i_nlink;
|
|
||||||
struct v9fs_session_info *v9ses = sb->s_fs_info;
|
struct v9fs_session_info *v9ses = sb->s_fs_info;
|
||||||
struct v9fs_inode *v9inode = V9FS_I(inode);
|
struct v9fs_inode *v9inode = V9FS_I(inode);
|
||||||
|
|
||||||
|
@ -1159,18 +1156,18 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
|
||||||
inode->i_gid = stat->n_gid;
|
inode->i_gid = stat->n_gid;
|
||||||
}
|
}
|
||||||
if ((S_ISREG(inode->i_mode)) || (S_ISDIR(inode->i_mode))) {
|
if ((S_ISREG(inode->i_mode)) || (S_ISDIR(inode->i_mode))) {
|
||||||
if (v9fs_proto_dotu(v9ses) && (stat->extension[0] != '\0')) {
|
if (v9fs_proto_dotu(v9ses)) {
|
||||||
|
unsigned int i_nlink;
|
||||||
/*
|
/*
|
||||||
* Hadlink support got added later to
|
* Hadlink support got added later to the .u extension.
|
||||||
* to the .u extension. So there can be
|
* So there can be a server out there that doesn't
|
||||||
* server out there that doesn't support
|
* support this even with .u extension. That would
|
||||||
* this even with .u extension. So check
|
* just leave us with stat->extension being an empty
|
||||||
* for non NULL stat->extension
|
* string, though.
|
||||||
*/
|
*/
|
||||||
strlcpy(ext, stat->extension, sizeof(ext));
|
|
||||||
/* HARDLINKCOUNT %u */
|
/* HARDLINKCOUNT %u */
|
||||||
sscanf(ext, "%13s %u", tag_name, &i_nlink);
|
if (sscanf(stat->extension,
|
||||||
if (!strncmp(tag_name, "HARDLINKCOUNT", 13))
|
" HARDLINKCOUNT %u", &i_nlink) == 1)
|
||||||
set_nlink(inode, i_nlink);
|
set_nlink(inode, i_nlink);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -491,8 +491,8 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_inode *ip,
|
||||||
di = (struct gfs2_dinode *)dibh->b_data;
|
di = (struct gfs2_dinode *)dibh->b_data;
|
||||||
gfs2_dinode_out(ip, di);
|
gfs2_dinode_out(ip, di);
|
||||||
|
|
||||||
di->di_major = cpu_to_be32(MAJOR(ip->i_inode.i_rdev));
|
di->di_major = cpu_to_be32(imajor(&ip->i_inode));
|
||||||
di->di_minor = cpu_to_be32(MINOR(ip->i_inode.i_rdev));
|
di->di_minor = cpu_to_be32(iminor(&ip->i_inode));
|
||||||
di->__pad1 = 0;
|
di->__pad1 = 0;
|
||||||
di->__pad2 = 0;
|
di->__pad2 = 0;
|
||||||
di->__pad3 = 0;
|
di->__pad3 = 0;
|
||||||
|
|
|
@ -142,6 +142,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
|
||||||
atomic_set(&inode->i_count, 1);
|
atomic_set(&inode->i_count, 1);
|
||||||
inode->i_op = &empty_iops;
|
inode->i_op = &empty_iops;
|
||||||
inode->i_fop = &no_open_fops;
|
inode->i_fop = &no_open_fops;
|
||||||
|
inode->i_ino = 0;
|
||||||
inode->__i_nlink = 1;
|
inode->__i_nlink = 1;
|
||||||
inode->i_opflags = 0;
|
inode->i_opflags = 0;
|
||||||
if (sb->s_xattr)
|
if (sb->s_xattr)
|
||||||
|
|
|
@ -551,7 +551,6 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto out_unload;
|
goto out_unload;
|
||||||
}
|
}
|
||||||
inode->i_ino = 0;
|
|
||||||
inode->i_size = i_size_read(sb->s_bdev->bd_inode);
|
inode->i_size = i_size_read(sb->s_bdev->bd_inode);
|
||||||
inode->i_mapping->a_ops = &jfs_metapage_aops;
|
inode->i_mapping->a_ops = &jfs_metapage_aops;
|
||||||
inode_fake_hash(inode);
|
inode_fake_hash(inode);
|
||||||
|
|
|
@ -380,51 +380,37 @@ int mnt_want_write(struct vfsmount *m)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(mnt_want_write);
|
EXPORT_SYMBOL_GPL(mnt_want_write);
|
||||||
|
|
||||||
/**
|
|
||||||
* mnt_clone_write - get write access to a mount
|
|
||||||
* @mnt: the mount on which to take a write
|
|
||||||
*
|
|
||||||
* This is effectively like mnt_want_write, except
|
|
||||||
* it must only be used to take an extra write reference
|
|
||||||
* on a mountpoint that we already know has a write reference
|
|
||||||
* on it. This allows some optimisation.
|
|
||||||
*
|
|
||||||
* After finished, mnt_drop_write must be called as usual to
|
|
||||||
* drop the reference.
|
|
||||||
*/
|
|
||||||
int mnt_clone_write(struct vfsmount *mnt)
|
|
||||||
{
|
|
||||||
/* superblock may be r/o */
|
|
||||||
if (__mnt_is_readonly(mnt))
|
|
||||||
return -EROFS;
|
|
||||||
preempt_disable();
|
|
||||||
mnt_inc_writers(real_mount(mnt));
|
|
||||||
preempt_enable();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(mnt_clone_write);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __mnt_want_write_file - get write access to a file's mount
|
* __mnt_want_write_file - get write access to a file's mount
|
||||||
* @file: the file who's mount on which to take a write
|
* @file: the file who's mount on which to take a write
|
||||||
*
|
*
|
||||||
* This is like __mnt_want_write, but it takes a file and can
|
* This is like __mnt_want_write, but if the file is already open for writing it
|
||||||
* do some optimisations if the file is open for write already
|
* skips incrementing mnt_writers (since the open file already has a reference)
|
||||||
|
* and instead only does the check for emergency r/o remounts. This must be
|
||||||
|
* paired with __mnt_drop_write_file.
|
||||||
*/
|
*/
|
||||||
int __mnt_want_write_file(struct file *file)
|
int __mnt_want_write_file(struct file *file)
|
||||||
{
|
{
|
||||||
if (!(file->f_mode & FMODE_WRITER))
|
if (file->f_mode & FMODE_WRITER) {
|
||||||
|
/*
|
||||||
|
* Superblock may have become readonly while there are still
|
||||||
|
* writable fd's, e.g. due to a fs error with errors=remount-ro
|
||||||
|
*/
|
||||||
|
if (__mnt_is_readonly(file->f_path.mnt))
|
||||||
|
return -EROFS;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return __mnt_want_write(file->f_path.mnt);
|
return __mnt_want_write(file->f_path.mnt);
|
||||||
else
|
|
||||||
return mnt_clone_write(file->f_path.mnt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mnt_want_write_file - get write access to a file's mount
|
* mnt_want_write_file - get write access to a file's mount
|
||||||
* @file: the file who's mount on which to take a write
|
* @file: the file who's mount on which to take a write
|
||||||
*
|
*
|
||||||
* This is like mnt_want_write, but it takes a file and can
|
* This is like mnt_want_write, but if the file is already open for writing it
|
||||||
* do some optimisations if the file is open for write already
|
* skips incrementing mnt_writers (since the open file already has a reference)
|
||||||
|
* and instead only does the freeze protection and the check for emergency r/o
|
||||||
|
* remounts. This must be paired with mnt_drop_write_file.
|
||||||
*/
|
*/
|
||||||
int mnt_want_write_file(struct file *file)
|
int mnt_want_write_file(struct file *file)
|
||||||
{
|
{
|
||||||
|
@ -470,6 +456,7 @@ EXPORT_SYMBOL_GPL(mnt_drop_write);
|
||||||
|
|
||||||
void __mnt_drop_write_file(struct file *file)
|
void __mnt_drop_write_file(struct file *file)
|
||||||
{
|
{
|
||||||
|
if (!(file->f_mode & FMODE_WRITER))
|
||||||
__mnt_drop_write(file->f_path.mnt);
|
__mnt_drop_write(file->f_path.mnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,6 @@ struct path;
|
||||||
|
|
||||||
extern int mnt_want_write(struct vfsmount *mnt);
|
extern int mnt_want_write(struct vfsmount *mnt);
|
||||||
extern int mnt_want_write_file(struct file *file);
|
extern int mnt_want_write_file(struct file *file);
|
||||||
extern int mnt_clone_write(struct vfsmount *mnt);
|
|
||||||
extern void mnt_drop_write(struct vfsmount *mnt);
|
extern void mnt_drop_write(struct vfsmount *mnt);
|
||||||
extern void mnt_drop_write_file(struct file *file);
|
extern void mnt_drop_write_file(struct file *file);
|
||||||
extern void mntput(struct vfsmount *mnt);
|
extern void mntput(struct vfsmount *mnt);
|
||||||
|
|
|
@ -84,7 +84,7 @@ struct audit_fsnotify_mark *audit_alloc_mark(struct audit_krule *krule, char *pa
|
||||||
|
|
||||||
dentry = kern_path_locked(pathname, &path);
|
dentry = kern_path_locked(pathname, &path);
|
||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
return (void *)dentry; /* returning an error */
|
return ERR_CAST(dentry); /* returning an error */
|
||||||
inode = path.dentry->d_inode;
|
inode = path.dentry->d_inode;
|
||||||
inode_unlock(inode);
|
inode_unlock(inode);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче