You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
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: truncate: use new helpers truncate: new helpers fs: fix overflow in sys_mount() for in-kernel calls fs: Make unload_nls() NULL pointer safe freeze_bdev: grab active reference to frozen superblocks freeze_bdev: kill bd_mount_sem exofs: remove BKL from super operations fs/romfs: correct error-handling code vfs: seq_file: add helpers for data filling vfs: remove redundant position check in do_sendfile vfs: change sb->s_maxbytes to a loff_t vfs: explicitly cast s_maxbytes in fiemap_check_ranges libfs: return error code on failed attr set seq_file: return a negative error code when seq_path_root() fails. vfs: optimize touch_time() too vfs: optimization for touch_atime() vfs: split generic_forget_inode() so that hugetlbfs does not have to copy it fs/inode.c: add dev-id and inode number for debugging in init_special_inode() libfs: make simple_read_from_buffer conventional
This commit is contained in:
@@ -80,7 +80,7 @@ Note: PTL can also be used to guarantee that no new clones using the
|
||||
mm start up ... this is a loose form of stability on mm_users. For
|
||||
example, it is used in copy_mm to protect against a racing tlb_gather_mmu
|
||||
single address space optimization, so that the zap_page_range (from
|
||||
vmtruncate) does not lose sending ipi's to cloned threads that might
|
||||
truncate) does not lose sending ipi's to cloned threads that might
|
||||
be spawned underneath it and go to user mode to drag in pte's into tlbs.
|
||||
|
||||
swap_lock
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
/* Taken over from the old code... */
|
||||
|
||||
/* POSIX UID/GID verification for setting inode attributes. */
|
||||
int inode_change_ok(struct inode *inode, struct iattr *attr)
|
||||
int inode_change_ok(const struct inode *inode, struct iattr *attr)
|
||||
{
|
||||
int retval = -EPERM;
|
||||
unsigned int ia_valid = attr->ia_valid;
|
||||
@@ -60,9 +60,51 @@ fine:
|
||||
error:
|
||||
return retval;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(inode_change_ok);
|
||||
|
||||
/**
|
||||
* inode_newsize_ok - may this inode be truncated to a given size
|
||||
* @inode: the inode to be truncated
|
||||
* @offset: the new size to assign to the inode
|
||||
* @Returns: 0 on success, -ve errno on failure
|
||||
*
|
||||
* inode_newsize_ok will check filesystem limits and ulimits to check that the
|
||||
* new inode size is within limits. inode_newsize_ok will also send SIGXFSZ
|
||||
* when necessary. Caller must not proceed with inode size change if failure is
|
||||
* returned. @inode must be a file (not directory), with appropriate
|
||||
* permissions to allow truncate (inode_newsize_ok does NOT check these
|
||||
* conditions).
|
||||
*
|
||||
* inode_newsize_ok must be called with i_mutex held.
|
||||
*/
|
||||
int inode_newsize_ok(const struct inode *inode, loff_t offset)
|
||||
{
|
||||
if (inode->i_size < offset) {
|
||||
unsigned long limit;
|
||||
|
||||
limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
|
||||
if (limit != RLIM_INFINITY && offset > limit)
|
||||
goto out_sig;
|
||||
if (offset > inode->i_sb->s_maxbytes)
|
||||
goto out_big;
|
||||
} else {
|
||||
/*
|
||||
* truncation of in-use swapfiles is disallowed - it would
|
||||
* cause subsequent swapout to scribble on the now-freed
|
||||
* blocks.
|
||||
*/
|
||||
if (IS_SWAPFILE(inode))
|
||||
return -ETXTBSY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
out_sig:
|
||||
send_sig(SIGXFSZ, current, 0);
|
||||
out_big:
|
||||
return -EFBIG;
|
||||
}
|
||||
EXPORT_SYMBOL(inode_newsize_ok);
|
||||
|
||||
int inode_setattr(struct inode * inode, struct iattr * attr)
|
||||
{
|
||||
unsigned int ia_valid = attr->ia_valid;
|
||||
|
||||
@@ -737,12 +737,7 @@ befs_put_super(struct super_block *sb)
|
||||
{
|
||||
kfree(BEFS_SB(sb)->mount_opts.iocharset);
|
||||
BEFS_SB(sb)->mount_opts.iocharset = NULL;
|
||||
|
||||
if (BEFS_SB(sb)->nls) {
|
||||
unload_nls(BEFS_SB(sb)->nls);
|
||||
BEFS_SB(sb)->nls = NULL;
|
||||
}
|
||||
|
||||
kfree(sb->s_fs_info);
|
||||
sb->s_fs_info = NULL;
|
||||
}
|
||||
|
||||
+38
-32
@@ -216,8 +216,6 @@ EXPORT_SYMBOL(fsync_bdev);
|
||||
* freeze_bdev -- lock a filesystem and force it into a consistent state
|
||||
* @bdev: blockdevice to lock
|
||||
*
|
||||
* This takes the block device bd_mount_sem to make sure no new mounts
|
||||
* happen on bdev until thaw_bdev() is called.
|
||||
* If a superblock is found on this device, we take the s_umount semaphore
|
||||
* on it to make sure nobody unmounts until the snapshot creation is done.
|
||||
* The reference counter (bd_fsfreeze_count) guarantees that only the last
|
||||
@@ -232,17 +230,27 @@ struct super_block *freeze_bdev(struct block_device *bdev)
|
||||
int error = 0;
|
||||
|
||||
mutex_lock(&bdev->bd_fsfreeze_mutex);
|
||||
if (bdev->bd_fsfreeze_count > 0) {
|
||||
bdev->bd_fsfreeze_count++;
|
||||
if (++bdev->bd_fsfreeze_count > 1) {
|
||||
/*
|
||||
* We don't even need to grab a reference - the first call
|
||||
* to freeze_bdev grab an active reference and only the last
|
||||
* thaw_bdev drops it.
|
||||
*/
|
||||
sb = get_super(bdev);
|
||||
drop_super(sb);
|
||||
mutex_unlock(&bdev->bd_fsfreeze_mutex);
|
||||
return sb;
|
||||
}
|
||||
|
||||
sb = get_active_super(bdev);
|
||||
if (!sb)
|
||||
goto out;
|
||||
if (sb->s_flags & MS_RDONLY) {
|
||||
deactivate_locked_super(sb);
|
||||
mutex_unlock(&bdev->bd_fsfreeze_mutex);
|
||||
return sb;
|
||||
}
|
||||
bdev->bd_fsfreeze_count++;
|
||||
|
||||
down(&bdev->bd_mount_sem);
|
||||
sb = get_super(bdev);
|
||||
if (sb && !(sb->s_flags & MS_RDONLY)) {
|
||||
sb->s_frozen = SB_FREEZE_WRITE;
|
||||
smp_wmb();
|
||||
|
||||
@@ -259,19 +267,18 @@ struct super_block *freeze_bdev(struct block_device *bdev)
|
||||
printk(KERN_ERR
|
||||
"VFS:Filesystem freeze failed\n");
|
||||
sb->s_frozen = SB_UNFROZEN;
|
||||
drop_super(sb);
|
||||
up(&bdev->bd_mount_sem);
|
||||
deactivate_locked_super(sb);
|
||||
bdev->bd_fsfreeze_count--;
|
||||
mutex_unlock(&bdev->bd_fsfreeze_mutex);
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
up_write(&sb->s_umount);
|
||||
|
||||
out:
|
||||
sync_blockdev(bdev);
|
||||
mutex_unlock(&bdev->bd_fsfreeze_mutex);
|
||||
|
||||
return sb; /* thaw_bdev releases s->s_umount and bd_mount_sem */
|
||||
return sb; /* thaw_bdev releases s->s_umount */
|
||||
}
|
||||
EXPORT_SYMBOL(freeze_bdev);
|
||||
|
||||
@@ -284,25 +291,24 @@ EXPORT_SYMBOL(freeze_bdev);
|
||||
*/
|
||||
int thaw_bdev(struct block_device *bdev, struct super_block *sb)
|
||||
{
|
||||
int error = 0;
|
||||
int error = -EINVAL;
|
||||
|
||||
mutex_lock(&bdev->bd_fsfreeze_mutex);
|
||||
if (!bdev->bd_fsfreeze_count) {
|
||||
mutex_unlock(&bdev->bd_fsfreeze_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!bdev->bd_fsfreeze_count)
|
||||
goto out_unlock;
|
||||
|
||||
bdev->bd_fsfreeze_count--;
|
||||
if (bdev->bd_fsfreeze_count > 0) {
|
||||
if (sb)
|
||||
drop_super(sb);
|
||||
mutex_unlock(&bdev->bd_fsfreeze_mutex);
|
||||
return 0;
|
||||
}
|
||||
error = 0;
|
||||
if (--bdev->bd_fsfreeze_count > 0)
|
||||
goto out_unlock;
|
||||
|
||||
if (!sb)
|
||||
goto out_unlock;
|
||||
|
||||
if (sb) {
|
||||
BUG_ON(sb->s_bdev != bdev);
|
||||
if (!(sb->s_flags & MS_RDONLY)) {
|
||||
down_write(&sb->s_umount);
|
||||
if (sb->s_flags & MS_RDONLY)
|
||||
goto out_deactivate;
|
||||
|
||||
if (sb->s_op->unfreeze_fs) {
|
||||
error = sb->s_op->unfreeze_fs(sb);
|
||||
if (error) {
|
||||
@@ -314,14 +320,15 @@ int thaw_bdev(struct block_device *bdev, struct super_block *sb)
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
sb->s_frozen = SB_UNFROZEN;
|
||||
smp_wmb();
|
||||
wake_up(&sb->s_wait_unfrozen);
|
||||
}
|
||||
drop_super(sb);
|
||||
}
|
||||
|
||||
up(&bdev->bd_mount_sem);
|
||||
out_deactivate:
|
||||
if (sb)
|
||||
deactivate_locked_super(sb);
|
||||
out_unlock:
|
||||
mutex_unlock(&bdev->bd_fsfreeze_mutex);
|
||||
return 0;
|
||||
}
|
||||
@@ -430,7 +437,6 @@ static void init_once(void *foo)
|
||||
|
||||
memset(bdev, 0, sizeof(*bdev));
|
||||
mutex_init(&bdev->bd_mutex);
|
||||
sema_init(&bdev->bd_mount_sem, 1);
|
||||
INIT_LIST_HEAD(&bdev->bd_inodes);
|
||||
INIT_LIST_HEAD(&bdev->bd_list);
|
||||
#ifdef CONFIG_SYSFS
|
||||
|
||||
+2
-8
@@ -2239,16 +2239,10 @@ int generic_cont_expand_simple(struct inode *inode, loff_t size)
|
||||
struct address_space *mapping = inode->i_mapping;
|
||||
struct page *page;
|
||||
void *fsdata;
|
||||
unsigned long limit;
|
||||
int err;
|
||||
|
||||
err = -EFBIG;
|
||||
limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
|
||||
if (limit != RLIM_INFINITY && size > (loff_t)limit) {
|
||||
send_sig(SIGXFSZ, current, 0);
|
||||
goto out;
|
||||
}
|
||||
if (size > inode->i_sb->s_maxbytes)
|
||||
err = inode_newsize_ok(inode, size);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = pagecache_write_begin(NULL, mapping, size, 0,
|
||||
|
||||
@@ -185,7 +185,6 @@ out_mount_failed:
|
||||
cifs_sb->mountdata = NULL;
|
||||
}
|
||||
#endif
|
||||
if (cifs_sb->local_nls)
|
||||
unload_nls(cifs_sb->local_nls);
|
||||
kfree(cifs_sb);
|
||||
}
|
||||
|
||||
+9
-42
@@ -1557,57 +1557,24 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from)
|
||||
|
||||
static int cifs_vmtruncate(struct inode *inode, loff_t offset)
|
||||
{
|
||||
struct address_space *mapping = inode->i_mapping;
|
||||
unsigned long limit;
|
||||
loff_t oldsize;
|
||||
int err;
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
if (inode->i_size < offset)
|
||||
goto do_expand;
|
||||
/*
|
||||
* truncation of in-use swapfiles is disallowed - it would cause
|
||||
* subsequent swapout to scribble on the now-freed blocks.
|
||||
*/
|
||||
if (IS_SWAPFILE(inode)) {
|
||||
err = inode_newsize_ok(inode, offset);
|
||||
if (err) {
|
||||
spin_unlock(&inode->i_lock);
|
||||
goto out_busy;
|
||||
goto out;
|
||||
}
|
||||
i_size_write(inode, offset);
|
||||
spin_unlock(&inode->i_lock);
|
||||
/*
|
||||
* unmap_mapping_range is called twice, first simply for efficiency
|
||||
* so that truncate_inode_pages does fewer single-page unmaps. However
|
||||
* after this first call, and before truncate_inode_pages finishes,
|
||||
* it is possible for private pages to be COWed, which remain after
|
||||
* truncate_inode_pages finishes, hence the second unmap_mapping_range
|
||||
* call must be made for correctness.
|
||||
*/
|
||||
unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
|
||||
truncate_inode_pages(mapping, offset);
|
||||
unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
|
||||
goto out_truncate;
|
||||
|
||||
do_expand:
|
||||
limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
|
||||
if (limit != RLIM_INFINITY && offset > limit) {
|
||||
spin_unlock(&inode->i_lock);
|
||||
goto out_sig;
|
||||
}
|
||||
if (offset > inode->i_sb->s_maxbytes) {
|
||||
spin_unlock(&inode->i_lock);
|
||||
goto out_big;
|
||||
}
|
||||
oldsize = inode->i_size;
|
||||
i_size_write(inode, offset);
|
||||
spin_unlock(&inode->i_lock);
|
||||
out_truncate:
|
||||
truncate_pagecache(inode, oldsize, offset);
|
||||
if (inode->i_op->truncate)
|
||||
inode->i_op->truncate(inode);
|
||||
return 0;
|
||||
out_sig:
|
||||
send_sig(SIGXFSZ, current, 0);
|
||||
out_big:
|
||||
return -EFBIG;
|
||||
out_busy:
|
||||
return -ETXTBSY;
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
+12
-12
@@ -768,13 +768,13 @@ asmlinkage long compat_sys_mount(char __user * dev_name, char __user * dir_name,
|
||||
char __user * type, unsigned long flags,
|
||||
void __user * data)
|
||||
{
|
||||
unsigned long type_page;
|
||||
char *kernel_type;
|
||||
unsigned long data_page;
|
||||
unsigned long dev_page;
|
||||
char *kernel_dev;
|
||||
char *dir_page;
|
||||
int retval;
|
||||
|
||||
retval = copy_mount_options (type, &type_page);
|
||||
retval = copy_mount_string(type, &kernel_type);
|
||||
if (retval < 0)
|
||||
goto out;
|
||||
|
||||
@@ -783,38 +783,38 @@ asmlinkage long compat_sys_mount(char __user * dev_name, char __user * dir_name,
|
||||
if (IS_ERR(dir_page))
|
||||
goto out1;
|
||||
|
||||
retval = copy_mount_options (dev_name, &dev_page);
|
||||
retval = copy_mount_string(dev_name, &kernel_dev);
|
||||
if (retval < 0)
|
||||
goto out2;
|
||||
|
||||
retval = copy_mount_options (data, &data_page);
|
||||
retval = copy_mount_options(data, &data_page);
|
||||
if (retval < 0)
|
||||
goto out3;
|
||||
|
||||
retval = -EINVAL;
|
||||
|
||||
if (type_page && data_page) {
|
||||
if (!strcmp((char *)type_page, SMBFS_NAME)) {
|
||||
if (kernel_type && data_page) {
|
||||
if (!strcmp(kernel_type, SMBFS_NAME)) {
|
||||
do_smb_super_data_conv((void *)data_page);
|
||||
} else if (!strcmp((char *)type_page, NCPFS_NAME)) {
|
||||
} else if (!strcmp(kernel_type, NCPFS_NAME)) {
|
||||
do_ncp_super_data_conv((void *)data_page);
|
||||
} else if (!strcmp((char *)type_page, NFS4_NAME)) {
|
||||
} else if (!strcmp(kernel_type, NFS4_NAME)) {
|
||||
if (do_nfs4_super_data_conv((void *) data_page))
|
||||
goto out4;
|
||||
}
|
||||
}
|
||||
|
||||
retval = do_mount((char*)dev_page, dir_page, (char*)type_page,
|
||||
retval = do_mount(kernel_dev, dir_page, kernel_type,
|
||||
flags, (void*)data_page);
|
||||
|
||||
out4:
|
||||
free_page(data_page);
|
||||
out3:
|
||||
free_page(dev_page);
|
||||
kfree(kernel_dev);
|
||||
out2:
|
||||
putname(dir_page);
|
||||
out1:
|
||||
free_page(type_page);
|
||||
kfree(kernel_type);
|
||||
out:
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -214,7 +214,6 @@ int exofs_sync_fs(struct super_block *sb, int wait)
|
||||
}
|
||||
|
||||
lock_super(sb);
|
||||
lock_kernel();
|
||||
sbi = sb->s_fs_info;
|
||||
fscb->s_nextid = cpu_to_le64(sbi->s_nextid);
|
||||
fscb->s_numfiles = cpu_to_le32(sbi->s_numfiles);
|
||||
@@ -245,7 +244,6 @@ int exofs_sync_fs(struct super_block *sb, int wait)
|
||||
out:
|
||||
if (or)
|
||||
osd_end_request(or);
|
||||
unlock_kernel();
|
||||
unlock_super(sb);
|
||||
kfree(fscb);
|
||||
return ret;
|
||||
@@ -268,8 +266,6 @@ static void exofs_put_super(struct super_block *sb)
|
||||
int num_pend;
|
||||
struct exofs_sb_info *sbi = sb->s_fs_info;
|
||||
|
||||
lock_kernel();
|
||||
|
||||
if (sb->s_dirt)
|
||||
exofs_write_super(sb);
|
||||
|
||||
@@ -286,8 +282,6 @@ static void exofs_put_super(struct super_block *sb)
|
||||
osduld_put_device(sbi->s_dev);
|
||||
kfree(sb->s_fs_info);
|
||||
sb->s_fs_info = NULL;
|
||||
|
||||
unlock_kernel();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+2
-10
@@ -470,19 +470,11 @@ static void fat_put_super(struct super_block *sb)
|
||||
|
||||
iput(sbi->fat_inode);
|
||||
|
||||
if (sbi->nls_disk) {
|
||||
unload_nls(sbi->nls_disk);
|
||||
sbi->nls_disk = NULL;
|
||||
sbi->options.codepage = fat_default_codepage;
|
||||
}
|
||||
if (sbi->nls_io) {
|
||||
unload_nls(sbi->nls_io);
|
||||
sbi->nls_io = NULL;
|
||||
}
|
||||
if (sbi->options.iocharset != fat_default_iocharset) {
|
||||
|
||||
if (sbi->options.iocharset != fat_default_iocharset)
|
||||
kfree(sbi->options.iocharset);
|
||||
sbi->options.iocharset = fat_default_iocharset;
|
||||
}
|
||||
|
||||
sb->s_fs_info = NULL;
|
||||
kfree(sbi);
|
||||
|
||||
+4
-10
@@ -1276,14 +1276,9 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
|
||||
return 0;
|
||||
|
||||
if (attr->ia_valid & ATTR_SIZE) {
|
||||
unsigned long limit;
|
||||
if (IS_SWAPFILE(inode))
|
||||
return -ETXTBSY;
|
||||
limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
|
||||
if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) {
|
||||
send_sig(SIGXFSZ, current, 0);
|
||||
return -EFBIG;
|
||||
}
|
||||
err = inode_newsize_ok(inode, attr->ia_size);
|
||||
if (err)
|
||||
return err;
|
||||
is_truncate = true;
|
||||
}
|
||||
|
||||
@@ -1350,8 +1345,7 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
|
||||
* FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
|
||||
*/
|
||||
if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
|
||||
if (outarg.attr.size < oldsize)
|
||||
fuse_truncate(inode->i_mapping, outarg.attr.size);
|
||||
truncate_pagecache(inode, oldsize, outarg.attr.size);
|
||||
invalidate_inode_pages2(inode->i_mapping);
|
||||
}
|
||||
|
||||
|
||||
@@ -606,8 +606,6 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
|
||||
void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
|
||||
u64 attr_valid);
|
||||
|
||||
void fuse_truncate(struct address_space *mapping, loff_t offset);
|
||||
|
||||
/**
|
||||
* Initialize the client device
|
||||
*/
|
||||
|
||||
+1
-10
@@ -140,14 +140,6 @@ static int fuse_remount_fs(struct super_block *sb, int *flags, char *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fuse_truncate(struct address_space *mapping, loff_t offset)
|
||||
{
|
||||
/* See vmtruncate() */
|
||||
unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
|
||||
truncate_inode_pages(mapping, offset);
|
||||
unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
|
||||
}
|
||||
|
||||
void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
|
||||
u64 attr_valid)
|
||||
{
|
||||
@@ -205,8 +197,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
|
||||
spin_unlock(&fc->lock);
|
||||
|
||||
if (S_ISREG(inode->i_mode) && oldsize != attr->size) {
|
||||
if (attr->size < oldsize)
|
||||
fuse_truncate(inode->i_mapping, attr->size);
|
||||
truncate_pagecache(inode, oldsize, attr->size);
|
||||
invalidate_inode_pages2(inode->i_mapping);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,9 +344,7 @@ void hfs_mdb_put(struct super_block *sb)
|
||||
brelse(HFS_SB(sb)->mdb_bh);
|
||||
brelse(HFS_SB(sb)->alt_mdb_bh);
|
||||
|
||||
if (HFS_SB(sb)->nls_io)
|
||||
unload_nls(HFS_SB(sb)->nls_io);
|
||||
if (HFS_SB(sb)->nls_disk)
|
||||
unload_nls(HFS_SB(sb)->nls_disk);
|
||||
|
||||
free_pages((unsigned long)HFS_SB(sb)->bitmap, PAGE_SIZE < 8192 ? 1 : 0);
|
||||
|
||||
@@ -229,7 +229,6 @@ static void hfsplus_put_super(struct super_block *sb)
|
||||
iput(HFSPLUS_SB(sb).alloc_file);
|
||||
iput(HFSPLUS_SB(sb).hidden_dir);
|
||||
brelse(HFSPLUS_SB(sb).s_vhbh);
|
||||
if (HFSPLUS_SB(sb).nls)
|
||||
unload_nls(HFSPLUS_SB(sb).nls);
|
||||
kfree(sb->s_fs_info);
|
||||
sb->s_fs_info = NULL;
|
||||
@@ -464,7 +463,6 @@ out:
|
||||
|
||||
cleanup:
|
||||
hfsplus_put_super(sb);
|
||||
if (nls)
|
||||
unload_nls(nls);
|
||||
return err;
|
||||
}
|
||||
|
||||
+2
-27
@@ -380,36 +380,11 @@ static void hugetlbfs_delete_inode(struct inode *inode)
|
||||
|
||||
static void hugetlbfs_forget_inode(struct inode *inode) __releases(inode_lock)
|
||||
{
|
||||
struct super_block *sb = inode->i_sb;
|
||||
|
||||
if (!hlist_unhashed(&inode->i_hash)) {
|
||||
if (!(inode->i_state & (I_DIRTY|I_SYNC)))
|
||||
list_move(&inode->i_list, &inode_unused);
|
||||
inodes_stat.nr_unused++;
|
||||
if (!sb || (sb->s_flags & MS_ACTIVE)) {
|
||||
spin_unlock(&inode_lock);
|
||||
return;
|
||||
}
|
||||
inode->i_state |= I_WILL_FREE;
|
||||
spin_unlock(&inode_lock);
|
||||
/*
|
||||
* write_inode_now is a noop as we set BDI_CAP_NO_WRITEBACK
|
||||
* in our backing_dev_info.
|
||||
*/
|
||||
write_inode_now(inode, 1);
|
||||
spin_lock(&inode_lock);
|
||||
inode->i_state &= ~I_WILL_FREE;
|
||||
inodes_stat.nr_unused--;
|
||||
hlist_del_init(&inode->i_hash);
|
||||
}
|
||||
list_del_init(&inode->i_list);
|
||||
list_del_init(&inode->i_sb_list);
|
||||
inode->i_state |= I_FREEING;
|
||||
inodes_stat.nr_inodes--;
|
||||
spin_unlock(&inode_lock);
|
||||
if (generic_detach_inode(inode)) {
|
||||
truncate_hugepages(inode, 0);
|
||||
clear_inode(inode);
|
||||
destroy_inode(inode);
|
||||
}
|
||||
}
|
||||
|
||||
static void hugetlbfs_drop_inode(struct inode *inode)
|
||||
|
||||
+54
-33
@@ -1241,7 +1241,16 @@ void generic_delete_inode(struct inode *inode)
|
||||
}
|
||||
EXPORT_SYMBOL(generic_delete_inode);
|
||||
|
||||
static void generic_forget_inode(struct inode *inode)
|
||||
/**
|
||||
* generic_detach_inode - remove inode from inode lists
|
||||
* @inode: inode to remove
|
||||
*
|
||||
* Remove inode from inode lists, write it if it's dirty. This is just an
|
||||
* internal VFS helper exported for hugetlbfs. Do not use!
|
||||
*
|
||||
* Returns 1 if inode should be completely destroyed.
|
||||
*/
|
||||
int generic_detach_inode(struct inode *inode)
|
||||
{
|
||||
struct super_block *sb = inode->i_sb;
|
||||
|
||||
@@ -1251,7 +1260,7 @@ static void generic_forget_inode(struct inode *inode)
|
||||
inodes_stat.nr_unused++;
|
||||
if (sb->s_flags & MS_ACTIVE) {
|
||||
spin_unlock(&inode_lock);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
WARN_ON(inode->i_state & I_NEW);
|
||||
inode->i_state |= I_WILL_FREE;
|
||||
@@ -1269,6 +1278,14 @@ static void generic_forget_inode(struct inode *inode)
|
||||
inode->i_state |= I_FREEING;
|
||||
inodes_stat.nr_inodes--;
|
||||
spin_unlock(&inode_lock);
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(generic_detach_inode);
|
||||
|
||||
static void generic_forget_inode(struct inode *inode)
|
||||
{
|
||||
if (!generic_detach_inode(inode))
|
||||
return;
|
||||
if (inode->i_data.nrpages)
|
||||
truncate_inode_pages(&inode->i_data, 0);
|
||||
clear_inode(inode);
|
||||
@@ -1399,31 +1416,31 @@ void touch_atime(struct vfsmount *mnt, struct dentry *dentry)
|
||||
struct inode *inode = dentry->d_inode;
|
||||
struct timespec now;
|
||||
|
||||
if (mnt_want_write(mnt))
|
||||
return;
|
||||
if (inode->i_flags & S_NOATIME)
|
||||
goto out;
|
||||
return;
|
||||
if (IS_NOATIME(inode))
|
||||
goto out;
|
||||
return;
|
||||
if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode))
|
||||
goto out;
|
||||
return;
|
||||
|
||||
if (mnt->mnt_flags & MNT_NOATIME)
|
||||
goto out;
|
||||
return;
|
||||
if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))
|
||||
goto out;
|
||||
return;
|
||||
|
||||
now = current_fs_time(inode->i_sb);
|
||||
|
||||
if (!relatime_need_update(mnt, inode, now))
|
||||
goto out;
|
||||
return;
|
||||
|
||||
if (timespec_equal(&inode->i_atime, &now))
|
||||
goto out;
|
||||
return;
|
||||
|
||||
if (mnt_want_write(mnt))
|
||||
return;
|
||||
|
||||
inode->i_atime = now;
|
||||
mark_inode_dirty_sync(inode);
|
||||
out:
|
||||
mnt_drop_write(mnt);
|
||||
}
|
||||
EXPORT_SYMBOL(touch_atime);
|
||||
@@ -1444,33 +1461,36 @@ void file_update_time(struct file *file)
|
||||
{
|
||||
struct inode *inode = file->f_path.dentry->d_inode;
|
||||
struct timespec now;
|
||||
int sync_it = 0;
|
||||
int err;
|
||||
enum { S_MTIME = 1, S_CTIME = 2, S_VERSION = 4 } sync_it = 0;
|
||||
|
||||
/* First try to exhaust all avenues to not sync */
|
||||
if (IS_NOCMTIME(inode))
|
||||
return;
|
||||
|
||||
err = mnt_want_write_file(file);
|
||||
if (err)
|
||||
now = current_fs_time(inode->i_sb);
|
||||
if (!timespec_equal(&inode->i_mtime, &now))
|
||||
sync_it = S_MTIME;
|
||||
|
||||
if (!timespec_equal(&inode->i_ctime, &now))
|
||||
sync_it |= S_CTIME;
|
||||
|
||||
if (IS_I_VERSION(inode))
|
||||
sync_it |= S_VERSION;
|
||||
|
||||
if (!sync_it)
|
||||
return;
|
||||
|
||||
now = current_fs_time(inode->i_sb);
|
||||
if (!timespec_equal(&inode->i_mtime, &now)) {
|
||||
inode->i_mtime = now;
|
||||
sync_it = 1;
|
||||
}
|
||||
/* Finally allowed to write? Takes lock. */
|
||||
if (mnt_want_write_file(file))
|
||||
return;
|
||||
|
||||
if (!timespec_equal(&inode->i_ctime, &now)) {
|
||||
inode->i_ctime = now;
|
||||
sync_it = 1;
|
||||
}
|
||||
|
||||
if (IS_I_VERSION(inode)) {
|
||||
/* Only change inode inside the lock region */
|
||||
if (sync_it & S_VERSION)
|
||||
inode_inc_iversion(inode);
|
||||
sync_it = 1;
|
||||
}
|
||||
|
||||
if (sync_it)
|
||||
if (sync_it & S_CTIME)
|
||||
inode->i_ctime = now;
|
||||
if (sync_it & S_MTIME)
|
||||
inode->i_mtime = now;
|
||||
mark_inode_dirty_sync(inode);
|
||||
mnt_drop_write(file->f_path.mnt);
|
||||
}
|
||||
@@ -1599,7 +1619,8 @@ void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev)
|
||||
else if (S_ISSOCK(mode))
|
||||
inode->i_fop = &bad_sock_fops;
|
||||
else
|
||||
printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o)\n",
|
||||
mode);
|
||||
printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o) for"
|
||||
" inode %s:%lu\n", mode, inode->i_sb->s_id,
|
||||
inode->i_ino);
|
||||
}
|
||||
EXPORT_SYMBOL(init_special_inode);
|
||||
|
||||
@@ -57,6 +57,7 @@ extern int check_unsafe_exec(struct linux_binprm *);
|
||||
* namespace.c
|
||||
*/
|
||||
extern int copy_mount_options(const void __user *, unsigned long *);
|
||||
extern int copy_mount_string(const void __user *, char **);
|
||||
|
||||
extern void free_vfsmnt(struct vfsmount *);
|
||||
extern struct vfsmount *alloc_vfsmnt(const char *);
|
||||
|
||||
+5
-4
@@ -162,20 +162,21 @@ EXPORT_SYMBOL(fiemap_check_flags);
|
||||
static int fiemap_check_ranges(struct super_block *sb,
|
||||
u64 start, u64 len, u64 *new_len)
|
||||
{
|
||||
u64 maxbytes = (u64) sb->s_maxbytes;
|
||||
|
||||
*new_len = len;
|
||||
|
||||
if (len == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (start > sb->s_maxbytes)
|
||||
if (start > maxbytes)
|
||||
return -EFBIG;
|
||||
|
||||
/*
|
||||
* Shrink request scope to what the fs can actually handle.
|
||||
*/
|
||||
if ((len > sb->s_maxbytes) ||
|
||||
(sb->s_maxbytes - len) < start)
|
||||
*new_len = sb->s_maxbytes - start;
|
||||
if (len > maxbytes || (maxbytes - len) < start)
|
||||
*new_len = maxbytes - start;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -46,10 +46,7 @@ static void isofs_put_super(struct super_block *sb)
|
||||
#ifdef CONFIG_JOLIET
|
||||
lock_kernel();
|
||||
|
||||
if (sbi->s_nls_iocharset) {
|
||||
unload_nls(sbi->s_nls_iocharset);
|
||||
sbi->s_nls_iocharset = NULL;
|
||||
}
|
||||
|
||||
unlock_kernel();
|
||||
#endif
|
||||
@@ -912,7 +909,6 @@ out_no_root:
|
||||
printk(KERN_WARNING "%s: get root inode failed\n", __func__);
|
||||
out_no_inode:
|
||||
#ifdef CONFIG_JOLIET
|
||||
if (sbi->s_nls_iocharset)
|
||||
unload_nls(sbi->s_nls_iocharset);
|
||||
#endif
|
||||
goto out_freesbi;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user