diff options
Diffstat (limited to 'fs')
65 files changed, 632 insertions, 862 deletions
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index 603972576f0..f128427b995 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c @@ -29,51 +29,28 @@ #ifdef CONFIG_FS_POSIX_ACL -static void btrfs_update_cached_acl(struct inode *inode, - struct posix_acl **p_acl, - struct posix_acl *acl) -{ - spin_lock(&inode->i_lock); - if (*p_acl && *p_acl != BTRFS_ACL_NOT_CACHED) - posix_acl_release(*p_acl); - *p_acl = posix_acl_dup(acl); - spin_unlock(&inode->i_lock); -} - static struct posix_acl *btrfs_get_acl(struct inode *inode, int type) { int size; const char *name; char *value = NULL; - struct posix_acl *acl = NULL, **p_acl; + struct posix_acl *acl; + + acl = get_cached_acl(inode, type); + if (acl != ACL_NOT_CACHED) + return acl; switch (type) { case ACL_TYPE_ACCESS: name = POSIX_ACL_XATTR_ACCESS; - p_acl = &BTRFS_I(inode)->i_acl; break; case ACL_TYPE_DEFAULT: name = POSIX_ACL_XATTR_DEFAULT; - p_acl = &BTRFS_I(inode)->i_default_acl; break; default: - return ERR_PTR(-EINVAL); + BUG(); } - /* Handle the cached NULL acl case without locking */ - acl = ACCESS_ONCE(*p_acl); - if (!acl) - return acl; - - spin_lock(&inode->i_lock); - acl = *p_acl; - if (acl != BTRFS_ACL_NOT_CACHED) - acl = posix_acl_dup(acl); - spin_unlock(&inode->i_lock); - - if (acl != BTRFS_ACL_NOT_CACHED) - return acl; - size = __btrfs_getxattr(inode, name, "", 0); if (size > 0) { value = kzalloc(size, GFP_NOFS); @@ -82,13 +59,13 @@ static struct posix_acl *btrfs_get_acl(struct inode *inode, int type) size = __btrfs_getxattr(inode, name, value, size); if (size > 0) { acl = posix_acl_from_xattr(value, size); - btrfs_update_cached_acl(inode, p_acl, acl); + set_cached_acl(inode, type, acl); } kfree(value); } else if (size == -ENOENT || size == -ENODATA || size == 0) { /* FIXME, who returns -ENOENT? I think nobody */ acl = NULL; - btrfs_update_cached_acl(inode, p_acl, acl); + set_cached_acl(inode, type, acl); } else { acl = ERR_PTR(-EIO); } @@ -121,7 +98,6 @@ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) { int ret, size = 0; const char *name; - struct posix_acl **p_acl; char *value = NULL; mode_t mode; @@ -141,13 +117,11 @@ static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) ret = 0; inode->i_mode = mode; name = POSIX_ACL_XATTR_ACCESS; - p_acl = &BTRFS_I(inode)->i_acl; break; case ACL_TYPE_DEFAULT: if (!S_ISDIR(inode->i_mode)) return acl ? -EINVAL : 0; name = POSIX_ACL_XATTR_DEFAULT; - p_acl = &BTRFS_I(inode)->i_default_acl; break; default: return -EINVAL; @@ -172,7 +146,7 @@ out: kfree(value); if (!ret) - btrfs_update_cached_acl(inode, p_acl, acl); + set_cached_acl(inode, type, acl); return ret; } diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index acb4f351758..ea1ea0af8c0 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h @@ -53,10 +53,6 @@ struct btrfs_inode { /* used to order data wrt metadata */ struct btrfs_ordered_inode_tree ordered_tree; - /* standard acl pointers */ - struct posix_acl *i_acl; - struct posix_acl *i_default_acl; - /* for keeping track of orphaned inodes */ struct list_head i_orphan; diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 03441a99ea3..2779c2f5360 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -41,8 +41,6 @@ struct btrfs_ordered_sum; #define BTRFS_MAGIC "_BHRfS_M" -#define BTRFS_ACL_NOT_CACHED ((void *)-1) - #define BTRFS_MAX_LEVEL 8 #define BTRFS_COMPAT_EXTENT_TREE_V0 diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 8612b3a0981..dbe1aabf96c 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -2122,10 +2122,8 @@ static void btrfs_read_locked_inode(struct inode *inode) * any xattrs or acls */ maybe_acls = acls_after_inode_item(leaf, path->slots[0], inode->i_ino); - if (!maybe_acls) { - BTRFS_I(inode)->i_acl = NULL; - BTRFS_I(inode)->i_default_acl = NULL; - } + if (!maybe_acls) + cache_no_acl(inode); BTRFS_I(inode)->block_group = btrfs_find_block_group(root, 0, alloc_group_block, 0); @@ -3141,9 +3139,6 @@ static noinline void init_btrfs_i(struct inode *inode) { struct btrfs_inode *bi = BTRFS_I(inode); - bi->i_acl = BTRFS_ACL_NOT_CACHED; - bi->i_default_acl = BTRFS_ACL_NOT_CACHED; - bi->generation = 0; bi->sequence = 0; bi->last_trans = 0; @@ -4640,8 +4635,6 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) ei->last_trans = 0; ei->logged_trans = 0; btrfs_ordered_inode_tree_init(&ei->ordered_tree); - ei->i_acl = BTRFS_ACL_NOT_CACHED; - ei->i_default_acl = BTRFS_ACL_NOT_CACHED; INIT_LIST_HEAD(&ei->i_orphan); INIT_LIST_HEAD(&ei->ordered_operations); return &ei->vfs_inode; @@ -4655,13 +4648,6 @@ void btrfs_destroy_inode(struct inode *inode) WARN_ON(!list_empty(&inode->i_dentry)); WARN_ON(inode->i_data.nrpages); - if (BTRFS_I(inode)->i_acl && - BTRFS_I(inode)->i_acl != BTRFS_ACL_NOT_CACHED) - posix_acl_release(BTRFS_I(inode)->i_acl); - if (BTRFS_I(inode)->i_default_acl && - BTRFS_I(inode)->i_default_acl != BTRFS_ACL_NOT_CACHED) - posix_acl_release(BTRFS_I(inode)->i_default_acl); - /* * Make sure we're properly removed from the ordered operation * lists. diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index c135202c38b..626c7483b4d 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -31,6 +31,7 @@ #include <linux/skbuff.h> #include <linux/netlink.h> #include <linux/vt.h> +#include <linux/falloc.h> #include <linux/fs.h> #include <linux/file.h> #include <linux/ppp_defs.h> @@ -1779,6 +1780,41 @@ lp_timeout_trans(unsigned int fd, unsigned int cmd, unsigned long arg) return sys_ioctl(fd, cmd, (unsigned long)tn); } +/* on ia32 l_start is on a 32-bit boundary */ +#if defined(CONFIG_IA64) || defined(CONFIG_X86_64) +struct space_resv_32 { + __s16 l_type; + __s16 l_whence; + __s64 l_start __attribute__((packed)); + /* len == 0 means until end of file */ + __s64 l_len __attribute__((packed)); + __s32 l_sysid; + __u32 l_pid; + __s32 l_pad[4]; /* reserve area */ +}; + +#define FS_IOC_RESVSP_32 _IOW ('X', 40, struct space_resv_32) +#define FS_IOC_RESVSP64_32 _IOW ('X', 42, struct space_resv_32) + +/* just account for different alignment */ +static int compat_ioctl_preallocate(struct file *file, unsigned long arg) +{ + struct space_resv_32 __user *p32 = (void __user *)arg; + struct space_resv __user *p = compat_alloc_user_space(sizeof(*p)); + + if (copy_in_user(&p->l_type, &p32->l_type, sizeof(s16)) || + copy_in_user(&p->l_whence, &p32->l_whence, sizeof(s16)) || + copy_in_user(&p->l_start, &p32->l_start, sizeof(s64)) || + copy_in_user(&p->l_len, &p32->l_len, sizeof(s64)) || + copy_in_user(&p->l_sysid, &p32->l_sysid, sizeof(s32)) || + copy_in_user(&p->l_pid, &p32->l_pid, sizeof(u32)) || + copy_in_user(&p->l_pad, &p32->l_pad, 4*sizeof(u32))) + return -EFAULT; + + return ioctl_preallocate(file, p); +} +#endif + typedef int (*ioctl_trans_handler_t)(unsigned int, unsigned int, unsigned long, struct file *); @@ -2756,6 +2792,18 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, case FIOQSIZE: break; +#if defined(CONFIG_IA64) || defined(CONFIG_X86_64) + case FS_IOC_RESVSP_32: + case FS_IOC_RESVSP64_32: + error = compat_ioctl_preallocate(filp, arg); + goto out_fput; +#else + case FS_IOC_RESVSP: + case FS_IOC_RESVSP64: + error = ioctl_preallocate(filp, (void __user *)arg); + goto out_fput; +#endif + case FIBMAP: case FIGETBSZ: case FIONREAD: diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 9b1d285f9fe..75efb028974 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -423,7 +423,6 @@ static void devpts_kill_sb(struct super_block *sb) } static struct file_system_type devpts_fs_type = { - .owner = THIS_MODULE, .name = "devpts", .get_sb = devpts_get_sb, .kill_sb = devpts_kill_sb, @@ -564,13 +563,4 @@ static int __init init_devpts_fs(void) } return err; } - -static void __exit exit_devpts_fs(void) -{ - unregister_filesystem(&devpts_fs_type); - mntput(devpts_mnt); -} - module_init(init_devpts_fs) -module_exit(exit_devpts_fs) -MODULE_LICENSE("GPL"); diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c index d46e38cb85c..d636e1297ca 100644 --- a/fs/ext2/acl.c +++ b/fs/ext2/acl.c @@ -125,37 +125,12 @@ fail: return ERR_PTR(-EINVAL); } -static inline struct posix_acl * -ext2_iget_acl(struct inode *inode, struct posix_acl **i_acl) -{ - struct posix_acl *acl = EXT2_ACL_NOT_CACHED; - - spin_lock(&inode->i_lock); - if (*i_acl != EXT2_ACL_NOT_CACHED) - acl = posix_acl_dup(*i_acl); - spin_unlock(&inode->i_lock); - - return acl; -} - -static inline void -ext2_iset_acl(struct inode *inode, struct posix_acl **i_acl, - struct posix_acl *acl) -{ - spin_lock(&inode->i_lock); - if (*i_acl != EXT2_ACL_NOT_CACHED) - posix_acl_release(*i_acl); - *i_acl = posix_acl_dup(acl); - spin_unlock(&inode->i_lock); -} - /* * inode->i_mutex: don't care */ static struct posix_acl * ext2_get_acl(struct inode *inode, int type) { - struct ext2_inode_info *ei = EXT2_I(inode); int name_index; char *value = NULL; struct posix_acl *acl; @@ -164,23 +139,19 @@ ext2_get_acl(struct inode *inode, int type) if (!test_opt(inode->i_sb, POSIX_ACL)) return NULL; - switch(type) { - case ACL_TYPE_ACCESS: - acl = ext2_iget_acl(inode, &ei->i_acl); - if (acl != EXT2_ACL_NOT_CACHED) - return acl; - name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS; - break; - - case ACL_TYPE_DEFAULT: - acl = ext2_iget_acl(inode, &ei->i_default_acl); - if (acl != EXT2_ACL_NOT_CACHED) - return acl; - name_index = EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT; - break; - - default: - return ERR_PTR(-EINVAL); + acl = get_cached_acl(inode, type); + if (acl != ACL_NOT_CACHED) + return acl; + + switch (type) { + case ACL_TYPE_ACCESS: + name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS; + break; + case ACL_TYPE_DEFAULT: + name_index = EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT; + break; + default: + BUG(); } retval = ext2_xattr_get(inode, name_index, "", NULL, 0); if (retval > 0) { @@ -197,17 +168,9 @@ ext2_get_acl(struct inode *inode, int type) acl = ERR_PTR(retval); kfree(value); - if (!IS_ERR(acl)) { - switch(type) { - case ACL_TYPE_ACCESS: - ext2_iset_acl(inode, &ei->i_acl, acl); - break; + if (!IS_ERR(acl)) + set_cached_acl(inode, type, acl); - case ACL_TYPE_DEFAULT: - ext2_iset_acl(inode, &ei->i_default_acl, acl); - break; - } - } return acl; } @@ -217,7 +180,6 @@ ext2_get_acl(struct inode *inode, int type) static int ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl) { - struct ext2_inode_info *ei = EXT2_I(inode); int name_index; void *value = NULL; size_t size = 0; @@ -263,17 +225,8 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl) error = ext2_xattr_set(inode, name_index, "", value, size, 0); kfree(value); - if (!error) { - switch(type) { - case ACL_TYPE_ACCESS: - ext2_iset_acl(inode, &ei->i_acl, acl); - break; - - case ACL_TYPE_DEFAULT: - ext2_iset_acl(inode, &ei->i_default_acl, acl); - break; - } - } + if (!error) + set_cached_acl(inode, type, acl); return error; } diff --git a/fs/ext2/acl.h b/fs/ext2/acl.h index b42cf578554..ecefe478898 100644 --- a/fs/ext2/acl.h +++ b/fs/ext2/acl.h @@ -53,10 +53,6 @@ static inline int ext2_acl_count(size_t size) #ifdef CONFIG_EXT2_FS_POSIX_ACL -/* Value for inode->u.ext2_i.i_acl and inode->u.ext2_i.i_default_acl - if the ACL has not been cached */ -#define EXT2_ACL_NOT_CACHED ((void *)-1) - /* acl.c */ extern int ext2_permission (struct inode *, int); extern int ext2_acl_chmod (struct inode *); diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index d988a718aed..9a8a8e27a06 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h @@ -47,10 +47,6 @@ struct ext2_inode_info { */ struct rw_semaphore xattr_sem; #endif -#ifdef CONFIG_EXT2_FS_POSIX_ACL - struct posix_acl *i_acl; - struct posix_acl *i_default_acl; -#endif rwlock_t i_meta_lock; /* diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 29ed682061f..e27130341d4 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -1224,10 +1224,6 @@ struct inode *ext2_iget (struct super_block *sb, unsigned long ino) return inode; ei = EXT2_I(inode); -#ifdef CONFIG_EXT2_FS_POSIX_ACL - ei->i_acl = EXT2_ACL_NOT_CACHED; - ei->i_default_acl = EXT2_ACL_NOT_CACHED; -#endif ei->i_block_alloc_info = NULL; raw_inode = ext2_get_inode(inode->i_sb, ino, &bh); diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 458999638c3..1a9ffee47d5 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -152,10 +152,6 @@ static struct inode *ext2_alloc_inode(struct super_block *sb) ei = (struct ext2_inode_info *)kmem_cache_alloc(ext2_inode_cachep, GFP_KERNEL); if (!ei) return NULL; -#ifdef CONFIG_EXT2_FS_POSIX_ACL - ei->i_acl = EXT2_ACL_NOT_CACHED; - ei->i_default_acl = EXT2_ACL_NOT_CACHED; -#endif ei->i_block_alloc_info = NULL; ei->vfs_inode.i_version = 1; return &ei->vfs_inode; @@ -198,18 +194,6 @@ static void destroy_inodecache(void) static void ext2_clear_inode(struct inode *inode) { struct ext2_block_alloc_info *rsv = EXT2_I(inode)->i_block_alloc_info; -#ifdef CONFIG_EXT2_FS_POSIX_ACL - struct ext2_inode_info *ei = EXT2_I(inode); - - if (ei->i_acl && ei->i_acl != EXT2_ACL_NOT_CACHED) { - posix_acl_release(ei->i_acl); - ei->i_acl = EXT2_ACL_NOT_CACHED; - } - if (ei->i_default_acl && ei->i_default_acl != EXT2_ACL_NOT_CACHED) { - posix_acl_release(ei->i_default_acl); - ei->i_default_acl = EXT2_ACL_NOT_CACHED; - } -#endif ext2_discard_reservation(inode); EXT2_I(inode)->i_block_alloc_info = NULL; if (unlikely(rsv)) diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c index e0c74545171..e167bae37ef 100644 --- a/fs/ext3/acl.c +++ b/fs/ext3/acl.c @@ -126,33 +126,6 @@ fail: return ERR_PTR(-EINVAL); } -static inline struct posix_acl * -ext3_iget_acl(struct inode *inode, struct posix_acl **i_acl) -{ - struct posix_acl *acl = ACCESS_ONCE(*i_acl); - - if (acl) { - spin_lock(&inode->i_lock); - acl = *i_acl; - if (acl != EXT3_ACL_NOT_CACHED) - acl = posix_acl_dup(acl); - spin_unlock(&inode->i_lock); - } - - return acl; -} - -static inline void -ext3_iset_acl(struct inode *inode, struct posix_acl **i_acl, - struct posix_acl *acl) -{ - spin_lock(&inode->i_lock); - if (*i_acl != EXT3_ACL_NOT_CACHED) - posix_acl_release(*i_acl); - *i_acl = posix_acl_dup(acl); - spin_unlock(&inode->i_lock); -} - /* * Inode operation get_posix_acl(). * @@ -161,7 +134,6 @@ ext3_iset_acl(struct inode *inode, struct posix_acl **i_acl, static struct posix_acl * ext3_get_acl(struct inode *inode, int type) { - struct ext3_inode_info *ei = EXT3_I(inode); int name_index; char *value = NULL; struct posix_acl *acl; @@ -170,24 +142,21 @@ ext3_get_acl(struct inode *inode, int type) if (!test_opt(inode->i_sb, POSIX_ACL)) return NULL; - switch(type) { - case ACL_TYPE_ACCESS: - acl = ext3_iget_acl(inode, &ei->i_acl); - if (acl != EXT3_ACL_NOT_CACHED) - return acl; - name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS; - break; - - case ACL_TYPE_DEFAULT: - acl = ext3_iget_acl(inode, &ei->i_default_acl); - if (acl != EXT3_ACL_NOT_CACHED) - return acl; - name_index = EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT; - break; - - default: - return ERR_PTR(-EINVAL); + acl = get_cached_acl(inode, type); + if (acl != ACL_NOT_CACHED) + return acl; + + switch (type) { + case ACL_TYPE_ACCESS: + name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS; + break; + case ACL_TYPE_DEFAULT: + name_index = EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT; + break; + default: + BUG(); } + retval = ext3_xattr_get(inode, name_index, "", NULL, 0); if (retval > 0) { value = kmalloc(retval, GFP_NOFS); @@ -203,17 +172,9 @@ ext3_get_acl(struct inode *inode, int type) acl = ERR_PTR(retval); kfree(value); - if (!IS_ERR(acl)) { - switch(type) { - case ACL_TYPE_ACCESS: - ext3_iset_acl(inode, &ei->i_acl, acl); - break; + if (!IS_ERR(acl)) + set_cached_acl(inode, type, acl); - case ACL_TYPE_DEFAULT: - ext3_iset_acl(inode, &ei->i_default_acl, acl); - break; - } - } return acl; } @@ -226,7 +187,6 @@ static int ext3_set_acl(handle_t *handle, struct inode *inode, int type, struct posix_acl *acl) { - struct ext3_inode_info *ei = EXT3_I(inode); int name_index; void *value = NULL; size_t size = 0; @@ -271,17 +231,10 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type, value, size, 0); kfree(value); - if (!error) { - switch(type) { - case ACL_TYPE_ACCESS: - ext3_iset_acl(inode, &ei->i_acl, acl); - break; - case ACL_TYPE_DEFAULT: - ext3_iset_acl(inode, &ei->i_default_acl, acl); - break; - } - } + if (!error) + set_cached_acl(inode, type, acl); + return error; } diff --git a/fs/ext3/acl.h b/fs/ext3/acl.h index 42da16b8cac..07d15a3a596 100644 --- a/fs/ext3/acl.h +++ b/fs/ext3/acl.h @@ -53,10 +53,6 @@ static inline int ext3_acl_count(size_t size) #ifdef CONFIG_EXT3_FS_POSIX_ACL -/* Value for inode->u.ext3_i.i_acl and inode->u.ext3_i.i_default_acl - if the ACL has not been cached */ -#define EXT3_ACL_NOT_CACHED ((void *)-1) - /* acl.c */ extern int ext3_permission (struct inode *, int); extern int ext3_acl_chmod (struct inode *); diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 05dea8132fc..5f51fed5c75 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -2752,10 +2752,6 @@ struct inode *ext3_iget(struct super_block *sb, unsigned long ino) return inode; ei = EXT3_I(inode); -#ifdef CONFIG_EXT3_FS_POSIX_ACL - ei->i_acl = EXT3_ACL_NOT_CACHED; - ei->i_default_acl = EXT3_ACL_NOT_CACHED; -#endif ei->i_block_alloc_info = NULL; ret = __ext3_get_inode_loc(inode, &iloc, 0); diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 601e881e610..524b349c629 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -464,10 +464,6 @@ static struct inode *ext3_alloc_inode(struct super_block *sb) ei = kmem_cache_alloc(ext3_inode_cachep, GFP_NOFS); if (!ei) return NULL; -#ifdef CONFIG_EXT3_FS_POSIX_ACL - ei->i_acl = EXT3_ACL_NOT_CACHED; - ei->i_default_acl = EXT3_ACL_NOT_CACHED; -#endif ei->i_block_alloc_info = NULL; ei->vfs_inode.i_version = 1; return &ei->vfs_inode; @@ -518,18 +514,6 @@ static void destroy_inodecache(void) static void ext3_clear_inode(struct inode *inode) { struct ext3_block_alloc_info *rsv = EXT3_I(inode)->i_block_alloc_info; -#ifdef CONFIG_EXT3_FS_POSIX_ACL - if (EXT3_I(inode)->i_acl && - EXT3_I(inode)->i_acl != EXT3_ACL_NOT_CACHED) { - posix_acl_release(EXT3_I(inode)->i_acl); - EXT3_I(inode)->i_acl = EXT3_ACL_NOT_CACHED; - } - if (EXT3_I(inode)->i_default_acl && - EXT3_I(inode)->i_default_acl != EXT3_ACL_NOT_CACHED) { - posix_acl_release(EXT3_I(inode)->i_default_acl); - EXT3_I(inode)->i_default_acl = EXT3_ACL_NOT_CACHED; - } -#endif ext3_discard_reservation(inode); EXT3_I(inode)->i_block_alloc_info = NULL; if (unlikely(rsv)) diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c index 605aeed96d6..f6d8967149c 100644 --- a/fs/ext4/acl.c +++ b/fs/ext4/acl.c @@ -126,33 +126,6 @@ fail: return ERR_PTR(-EINVAL); } -static inline struct posix_acl * -ext4_iget_acl(struct inode *inode, struct posix_acl **i_acl) -{ - struct posix_acl *acl = ACCESS_ONCE(*i_acl); - - if (acl) { - spin_lock(&inode->i_lock); - acl = *i_acl; - if (acl != EXT4_ACL_NOT_CACHED) - acl = posix_acl_dup(acl); - spin_unlock(&inode->i_lock); - } - - return acl; -} - -static inline void -ext4_iset_acl(struct inode *inode, struct posix_acl **i_acl, - struct posix_acl *acl) -{ - spin_lock(&inode->i_lock); - if (*i_acl != EXT4_ACL_NOT_CACHED) - posix_acl_release(*i_acl); - *i_acl = posix_acl_dup(acl); - spin_unlock(&inode->i_lock); -} - /* * Inode operation get_posix_acl(). * @@ -161,7 +134,6 @@ ext4_iset_acl(struct inode *inode, struct posix_acl **i_acl, static struct posix_acl * ext4_get_acl(struct inode *inode, int type) { - struct ext4_inode_info *ei = EXT4_I(inode); int name_index; char *value = NULL; struct posix_acl *acl; @@ -170,23 +142,19 @@ ext4_get_acl(struct inode *inode, int type) if (!test_opt(inode->i_sb, POSIX_ACL)) return NULL; + acl = get_cached_acl(inode, type); + if (acl != ACL_NOT_CACHED) + return acl; + switch (type) { case ACL_TYPE_ACCESS: - acl = ext4_iget_acl(inode, &ei->i_acl); - if (acl != EXT4_ACL_NOT_CACHED) - return acl; name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS; break; - case ACL_TYPE_DEFAULT: - acl = ext4_iget_acl(inode, &ei->i_default_acl); - if (acl != EXT4_ACL_NOT_CACHED) - return acl; name_index = EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT; break; - default: - return ERR_PTR(-EINVAL); + BUG(); } retval = ext4_xattr_get(inode, name_index, "", NULL, 0); if (retval > 0) { @@ -203,17 +171,9 @@ ext4_get_acl(struct inode *inode, int type) acl = ERR_PTR(retval); kfree(value); - if (!IS_ERR(acl)) { - switch (type) { - case ACL_TYPE_ACCESS: - ext4_iset_acl(inode, &ei->i_acl, acl); - break; + if (!IS_ERR(acl)) + set_cached_acl(inode, type, acl); - case ACL_TYPE_DEFAULT: - ext4_iset_acl(inode, &ei->i_default_acl, acl); - break; - } - } return acl; } @@ -226,7 +186,6 @@ static int ext4_set_acl(handle_t *handle, struct inode *inode, int type, struct posix_acl *acl) { - struct ext4_inode_info *ei = EXT4_I(inode); int name_index; void *value = NULL; size_t size = 0; @@ -271,17 +230,9 @@ ext4_set_acl(handle_t *handle, struct inode *inode, int type, value, size, 0); kfree(value); - if (!error) { - switch (type) { - case ACL_TYPE_ACCESS: - ext4_iset_acl(inode, &ei->i_acl, acl); - break; + if (!error) + set_cached_acl(inode, type, acl); - case ACL_TYPE_DEFAULT: - ext4_iset_acl(inode, &ei->i_default_acl, acl); - break; - } - } return error; } diff --git a/fs/ext4/acl.h b/fs/ext4/acl.h index cb45257a246..949789d2bba 100644 --- a/fs/ext4/acl.h +++ b/fs/ext4/acl.h @@ -53,10 +53,6 @@ static inline int ext4_acl_count(size_t size) #ifdef CONFIG_EXT4_FS_POSIX_ACL -/* Value for inode->u.ext4_i.i_acl and inode->u.ext4_i.i_default_acl - if the ACL has not been cached */ -#define EXT4_ACL_NOT_CACHED ((void *)-1) - /* acl.c */ extern int ext4_permission(struct inode *, int); extern int ext4_acl_chmod(struct inode *); diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 17b9998680e..0ddf7e55abe 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -595,10 +595,6 @@ struct ext4_inode_info { */ struct rw_semaphore xattr_sem; #endif -#ifdef CONFIG_EXT4_FS_POSIX_ACL - struct posix_acl *i_acl; - struct posix_acl *i_default_acl; -#endif struct list_head i_orphan; /* unlinked but open inodes */ diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 7c17ae275af..60a26f3a6f8 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4453,10 +4453,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) return inode; ei = EXT4_I(inode); -#ifdef CONFIG_EXT4_FS_POSIX_ACL - ei->i_acl = EXT4_ACL_NOT_CACHED; - ei->i_default_acl = EXT4_ACL_NOT_CACHED; -#endif ret = __ext4_get_inode_loc(inode, &iloc, 0); if (ret < 0) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 8bb9e2d3e4b..8f4f079e6b9 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -666,10 +666,6 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) if (!ei) return NULL; -#ifdef CONFIG_EXT4_FS_POSIX_ACL - ei->i_acl = EXT4_ACL_NOT_CACHED; - ei->i_default_acl = EXT4_ACL_NOT_CACHED; -#endif ei->vfs_inode.i_version = 1; ei->vfs_inode.i_data.writeback_index = 0; memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache)); @@ -735,18 +731,6 @@ static void destroy_inodecache(void) static void ext4_clear_inode(struct inode *inode) { -#ifdef CONFIG_EXT4_FS_POSIX_ACL - if (EXT4_I(inode)->i_acl && - EXT4_I(inode)->i_acl != EXT4_ACL_NOT_CACHED) { - posix_acl_release(EXT4_I(inode)->i_acl); - EXT4_I(inode)->i_acl = EXT4_ACL_NOT_CACHED; - } - if (EXT4_I(inode)->i_default_acl && - EXT4_I(inode)->i_default_acl != EXT4_ACL_NOT_CACHED) { - posix_acl_release(EXT4_I(inode)->i_default_acl); - EXT4_I(inode)->i_default_acl = EXT4_ACL_NOT_CACHED; - } -#endif ext4_discard_preallocations(inode); if (EXT4_JOURNAL(inode)) jbd2_journal_release_jbd_inode(EXT4_SB(inode->i_sb)->s_journal, diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index caf049146ca..c54226be529 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -278,7 +278,26 @@ int sb_has_dirty_inodes(struct super_block *sb) EXPORT_SYMBOL(sb_has_dirty_inodes); /* - * Write a single inode's dirty pages and inode data out to disk. + * Wait for writeback on an inode to complete. + */ +static void inode_wait_for_writeback(struct inode *inode) +{ + DEFINE_WAIT_BIT(wq, &inode->i_state, __I_SYNC); + wait_queue_head_t *wqh; + + wqh = bit_waitqueue(&inode->i_state, __I_SYNC); + do { + spin_unlock(&inode_lock); + __wait_on_bit(wqh, &wq, inode_wait, TASK_UNINTERRUPTIBLE); + spin_lock(&inode_lock); + } while (inode->i_state & I_SYNC); +} + +/* + * Write out an inode's dirty pages. Called under inode_lock. Either the + * caller has ref on the inode (either via __iget or via syscall against an fd) + * or the inode has I_WILL_FREE set (via generic_forget_inode) + * * If `wait' is set, wait on the writeout. * * The whole writeout design is quite complex and fragile. We want to avoid @@ -288,13 +307,38 @@ EXPORT_SYMBOL(sb_has_dirty_inodes); * Called under inode_lock. */ static int -__sync_single_inode(struct inode *inode, struct writeback_control *wbc) +writeback_single_inode(struct inode *inode, struct writeback_control *wbc) { - unsigned dirty; struct address_space *mapping = inode->i_mapping; int wait = wbc->sync_mode == WB_SYNC_ALL; + unsigned dirty; int ret; + if (!atomic_read(&inode->i_count)) + WARN_ON(!(inode->i_state & (I_WILL_FREE|I_FREEING))); + else + WARN_ON(inode->i_state & I_WILL_FREE); + + if (inode->i_state & I_SYNC) { + /* + * If this inode is locked for writeback and we are not doing + * writeback-for-data-integrity, move it to s_more_io so that + * writeback can proceed with the other inodes on s_io. + * + * We'll have another go at writing back this inode when we + * completed a full scan of s_io. + */ + if (!wait) { + requeue_io(inode); + return 0; + } + + /* + * It's a data-integrity sync. We must wait. + */ + inode_wait_for_writeback(inode); + } + BUG_ON(inode->i_state & I_SYNC); /* Set I_SYNC, reset I_DIRTY */ @@ -390,50 +434,6 @@ __sync_single_inode(struct inode *inode, struct writeback_control *wbc) } /* - * Write out an inode's dirty pages. Called under inode_lock. Either the - * caller has ref on the inode (either via __iget or via syscall against an fd) - * or the inode has I_WILL_FREE set (via generic_forget_inode) - */ -static int -__writeback_single_inode(struct inode *inode, struct writeback_control *wbc) -{ - wait_queue_head_t *wqh; - - if (!atomic_read(&inode->i_count)) - WARN_ON(!(inode->i_state & (I_WILL_FREE|I_FREEING))); - else - WARN_ON(inode->i_state & I_WILL_FREE); - - if ((wbc->sync_mode != WB_SYNC_ALL) && (inode->i_state & I_SYNC)) { - /* - * We're skipping this inode because it's locked, and we're not - * doing writeback-for-data-integrity. Move it to s_more_io so - * that writeback can proceed with the other inodes on s_io. - * We'll have another go at writing back this inode when we - * completed a full scan of s_io. - */ - requeue_io(inode); - return 0; - } - - /* - * It's a data-integrity sync. We must wait. - */ - if (inode->i_state & I_SYNC) { - DEFINE_WAIT_BIT(wq, &inode->i_state, __I_SYNC); - - wqh = bit_waitqueue(&inode->i_state, __I_SYNC); - do { - spin_unlock(&inode_lock); - __wait_on_bit(wqh, &wq, inode_wait, - TASK_UNINTERRUPTIBLE); - spin_lock(&inode_lock); - } while (inode->i_state & I_SYNC); - } - return __sync_single_inode(inode, wbc); -} - -/* * Write out a superblock's list of dirty inodes. A wait will be performed * upon no inodes, all inodes or the final one, depending upon sync_mode. * @@ -526,7 +526,7 @@ void generic_sync_sb_inodes(struct super_block *sb, BUG_ON(inode->i_state & (I_FREEING | I_CLEAR)); __iget(inode); pages_skipped = wbc->pages_skipped; - __writeback_single_inode(inode, wbc); + writeback_single_inode(inode, wbc); if (current_is_pdflush()) writeback_release(bdi); if (wbc->pages_skipped != pages_skipped) { @@ -708,7 +708,7 @@ int write_inode_now(struct inode *inode, int sync) might_sleep(); spin_lock(&inode_lock); - ret = __writeback_single_inode(inode, &wbc); + ret = writeback_single_inode(inode, &wbc); spin_unlock(&inode_lock); if (sync) inode_sync_wait(inode); @@ -732,7 +732,7 @@ int sync_inode(struct inode *inode, struct writeback_control *wbc) int ret; spin_lock(&inode_lock); - ret = __writeback_single_inode(inode, wbc); + ret = writeback_single_inode(inode, wbc); spin_unlock(&inode_lock); return ret; } diff --git a/fs/inode.c b/fs/inode.c index f643be565df..901bad1e5f1 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -25,6 +25,7 @@ #include <linux/fsnotify.h> #include <linux/mount.h> #include <linux/async.h> +#include <linux/posix_acl.h> /* * This is needed for the following functions: @@ -189,6 +190,9 @@ struct inode *inode_init_always(struct super_block *sb, struct inode *inode) } inode->i_private = NULL; inode->i_mapping = mapping; +#ifdef CONFIG_FS_POSIX_ACL + inode->i_acl = inode->i_default_acl = ACL_NOT_CACHED; +#endif #ifdef CONFIG_FSNOTIFY inode->i_fsnotify_mask = 0; @@ -227,6 +231,12 @@ void destroy_inode(struct inode *inode) ima_inode_free(inode); security_inode_free(inode); fsnotify_inode_delete(inode); +#ifdef CONFIG_FS_POSIX_ACL + if (inode->i_acl && inode->i_acl != ACL_NOT_CACHED) + posix_acl_release(inode->i_acl); + if (inode->i_default_acl && inode->i_default_acl != ACL_NOT_CACHED) + posix_acl_release(inode->i_default_acl); +#endif if (inode->i_sb->s_op->destroy_inode) inode->i_sb->s_op->destroy_inode(inode); else @@ -665,12 +675,17 @@ void unlock_new_inode(struct inode *inode) if (inode->i_mode & S_IFDIR) { struct file_system_type *type = inode->i_sb->s_type; - /* - * ensure nobody is actually holding i_mutex - */ - mutex_destroy(&inode->i_mutex); - mutex_init(&inode->i_mutex); - lockdep_set_class(&inode->i_mutex, &type->i_mutex_dir_key); + /* Set new key only if filesystem hasn't already changed it */ + if (!lockdep_match_class(&inode->i_mutex, + &type->i_mutex_key)) { + /* + * ensure nobody is actually holding i_mutex + */ + mutex_destroy(&inode->i_mutex); + mutex_init(&inode->i_mutex); + lockdep_set_class(&inode->i_mutex, + &type->i_mutex_dir_key); + } } #endif /* diff --git a/fs/ioctl.c b/fs/ioctl.c index 001f8d3118f..5612880fcbe 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -15,6 +15,7 @@ #include <linux/uaccess.h> #include <linux/writeback.h> #include <linux/buffer_head.h> +#include <linux/falloc.h> #include <asm/ioctls.h> @@ -403,6 +404,37 @@ EXPORT_SYMBOL(generic_block_fiemap); #endif /* CONFIG_BLOCK */ +/* + * This provides compatibility with legacy XFS pre-allocation ioctls + * which predate the fallocate syscall. + * + * Only the l_start, l_len and l_whence fields of the 'struct space_resv' + * are used here, rest are ignored. + */ +int ioctl_preallocate(struct file *filp, void __user *argp) +{ + struct inode *inode = filp->f_path.dentry->d_inode; + struct space_resv sr; + + if (copy_from_user(&sr, argp, sizeof(sr))) + return -EFAULT; + + switch (sr.l_whence) { + case SEEK_SET: + break; + case SEEK_CUR: + sr.l_start += filp->f_pos; + break; + case SEEK_END: + sr.l_start += i_size_read(inode); + break; + default: + return -EINVAL; + } + + return do_fallocate(filp, FALLOC_FL_KEEP_SIZE, sr.l_start, sr.l_len); +} + static int file_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { @@ -414,6 +446,9 @@ static int file_ioctl(struct file *filp, unsigned int cmd, return ioctl_fibmap(filp, p); case FIONREAD: return put_user(i_size_read(inode) - filp->f_pos, p); + case FS_IOC_RESVSP: + case FS_IOC_RESVSP64: + return ioctl_preallocate(filp, p); } return vfs_ioctl(filp, cmd, arg); diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c index 043740dde20..8fcb6239218 100644 --- a/fs/jffs2/acl.c +++ b/fs/jffs2/acl.c @@ -156,48 +156,25 @@ static void *jffs2_acl_to_medium(const struct posix_acl *acl, size_t *size) return ERR_PTR(-EINVAL); } -static struct posix_acl *jffs2_iget_acl(struct inode *inode, struct posix_acl **i_acl) -{ - struct posix_acl *acl = JFFS2_ACL_NOT_CACHED; - - spin_lock(&inode->i_lock); - if (*i_acl != JFFS2_ACL_NOT_CACHED) - acl = posix_acl_dup(*i_acl); - spin_unlock(&inode->i_lock); - return acl; -} - -static void jffs2_iset_acl(struct inode *inode, struct posix_acl **i_acl, struct posix_acl *acl) -{ - spin_lock(&inode->i_lock); - if (*i_acl != JFFS2_ACL_NOT_CACHED) - posix_acl_release(*i_acl); - *i_acl = posix_acl_dup(acl); - spin_unlock(&inode->i_lock); -} - static struct posix_acl *jffs2_get_acl(struct inode *inode, int type) { - struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); struct posix_acl *acl; char *value = NULL; int rc, xprefix; + acl = get_cached_acl(inode, type); + if (acl != ACL_NOT_CACHED) + return acl; + switch (type) { case ACL_TYPE_ACCESS: - acl = jffs2_iget_acl(inode, &f->i_acl_access); - if (acl != JFFS2_ACL_NOT_CACHED) - return acl; xprefix = JFFS2_XPREFIX_ACL_ACCESS; break; case ACL_TYPE_DEFAULT: - acl = jffs2_iget_acl(inode, &f->i_acl_default); - if (acl != JFFS2_ACL_NOT_CACHED) - return acl; xprefix = JFFS2_XPREFIX_ACL_DEFAULT; break; default: - return ERR_PTR(-EINVAL); + BUG(); } rc = do_jffs2_getxattr(inode, xprefix, "", NULL, 0); if (rc > 0) { @@ -215,16 +192,8 @@ static struct posix_acl *jffs2_get_acl(struct inode *inode, int type) } if (value) kfree(value); - if (!IS_ERR(acl)) { - switch (type) { - case ACL_TYPE_ACCESS: - jffs2_iset_acl(inode, &f->i_acl_access, acl); - break; - case ACL_TYPE_DEFAULT: - jffs2_iset_acl(inode, &f->i_acl_default, acl); - break; - } - } + if (!IS_ERR(acl)) + set_cached_acl(inode, type, acl); return acl; } @@ -249,7 +218,6 @@ static int __jffs2_set_acl(struct inode *inode, int xprefix, struct posix_acl *a static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl) { - struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); int rc, xprefix; if (S_ISLNK(inode->i_mode)) @@ -285,16 +253,8 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl) return -EINVAL; } rc = __jffs2_set_acl(inode, xprefix, acl); - if (!rc) { - switch(type) { - case ACL_TYPE_ACCESS: - jffs2_iset_acl(inode, &f->i_acl_access, acl); - break; - case ACL_TYPE_DEFAULT: - jffs2_iset_acl(inode, &f->i_acl_default, acl); - break; - } - } + if (!rc) + set_cached_acl(inode, type, acl); return rc; } @@ -321,12 +281,10 @@ int jffs2_permission(struct inode *inode, int mask) int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, int *i_mode) { - struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); struct posix_acl *acl, *clone; int rc; - f->i_acl_default = NULL; - f->i_acl_access = NULL; + cache_no_acl(inode); if (S_ISLNK(*i_mode)) return 0; /* Symlink always has no-ACL */ @@ -339,7 +297,7 @@ int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, int *i_mode) *i_mode &= ~current_umask(); } else { if (S_ISDIR(*i_mode)) - jffs2_iset_acl(inode, &f->i_acl_default, acl); + set_cached_acl(inode, ACL_TYPE_DEFAULT, acl); clone = posix_acl_clone(acl, GFP_KERNEL); if (!clone) @@ -350,7 +308,7 @@ int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, int *i_mode) return rc; } if (rc > 0) - jffs2_iset_acl(inode, &f->i_acl_access, clone); + set_cached_acl(inode, ACL_TYPE_ACCESS, clone); posix_acl_release(clone); } @@ -359,17 +317,16 @@ int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, int *i_mode) int jffs2_init_acl_post(struct inode *inode) { - struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); int rc; - if (f->i_acl_default) { - rc = __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_DEFAULT, f->i_acl_default); + if (inode->i_default_acl) { + rc = __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_DEFAULT, inode->i_default_acl); if (rc) return rc; } - if (f->i_acl_access) { - rc = __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_ACCESS, f->i_acl_access); + if (inode->i_acl) { + rc = __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_ACCESS, inode->i_acl); if (rc) return rc; } @@ -377,18 +334,6 @@ int jffs2_init_acl_post(struct inode *inode) return 0; } -void jffs2_clear_acl(struct jffs2_inode_info *f) -{ - if (f->i_acl_access && f->i_acl_access != JFFS2_ACL_NOT_CACHED) { - posix_acl_release(f->i_acl_access); - f->i_acl_access = JFFS2_ACL_NOT_CACHED; - } - if (f->i_acl_default && f->i_acl_default != JFFS2_ACL_NOT_CACHED) { - posix_acl_release(f->i_acl_default); - f->i_acl_default = JFFS2_ACL_NOT_CACHED; - } -} - int jffs2_acl_chmod(struct inode *inode) { struct posix_acl *acl, *clone; diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h index 8ca058aed38..fc929f2a14f 100644 --- a/fs/jffs2/acl.h +++ b/fs/jffs2/acl.h @@ -26,13 +26,10 @@ struct jffs2_acl_header { #ifdef CONFIG_JFFS2_FS_POSIX_ACL -#define JFFS2_ACL_NOT_CACHED ((void *)-1) - extern int jffs2_permission(struct inode *, int); extern int jffs2_acl_chmod(struct inode *); extern int jffs2_init_acl_pre(struct inode *, struct inode *, int *); extern int jffs2_init_acl_post(struct inode *); -extern void jffs2_clear_acl(struct jffs2_inode_info *); extern struct xattr_handler jffs2_acl_access_xattr_handler; extern struct xattr_handler jffs2_acl_default_xattr_handler; @@ -43,6 +40,5 @@ extern struct xattr_handler jffs2_acl_default_xattr_handler; #define jffs2_acl_chmod(inode) (0) #define jffs2_init_acl_pre(dir_i,inode,mode) (0) #define jffs2_init_acl_post(inode) (0) -#define jffs2_clear_acl(f) #endif /* CONFIG_JFFS2_FS_POSIX_ACL */ diff --git a/fs/jffs2/jffs2_fs_i.h b/fs/jffs2/jffs2_fs_i.h index 4c41db91eaa..c6923da9826 100644 --- a/fs/jffs2/jffs2_fs_i.h +++ b/fs/jffs2/jffs2_fs_i.h @@ -50,10 +50,6 @@ struct jffs2_inode_info { uint16_t flags; uint8_t usercompr; struct inode vfs_inode; -#ifdef CONFIG_JFFS2_FS_POSIX_ACL - struct posix_acl *i_acl_access; - struct posix_acl *i_acl_default; -#endif }; #endif /* _JFFS2_FS_I */ diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index 2228380c47b..a7f03b7ebcb 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -56,10 +56,6 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) f->target = NULL; f->flags = 0; f->usercompr = 0; -#ifdef CONFIG_JFFS2_FS_POSIX_ACL - f->i_acl_access = JFFS2_ACL_NOT_CACHED; - f->i_acl_default = JFFS2_ACL_NOT_CACHED; -#endif } diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 1fc1e92356e..1a80301004b 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -1424,7 +1424,6 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) struct jffs2_full_dirent *fd, *fds; int deleted; - jffs2_clear_acl(f); jffs2_xattr_delete_inode(c, f->inocache); mutex_lock(&f->sem); deleted = f->inocache && !f->inocache->pino_nlink; diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c index 06ca1b8d205..91fa3ad6e8c 100644 --- a/fs/jfs/acl.c +++ b/fs/jfs/acl.c @@ -31,27 +31,24 @@ static struct posix_acl *jfs_get_acl(struct inode *inode, int type) { struct posix_acl *acl; char *ea_name; - struct jfs_inode_info *ji = JFS_IP(inode); - struct posix_acl **p_acl; int size; char *value = NULL; + acl = get_cached_acl(inode, type); + if (acl != ACL_NOT_CACHED) + return acl; + switch(type) { case ACL_TYPE_ACCESS: ea_name = POSIX_ACL_XATTR_ACCESS; - p_acl = &ji->i_acl; break; case ACL_TYPE_DEFAULT: ea_name = POSIX_ACL_XATTR_DEFAULT; - p_acl = &ji->i_default_acl; break; default: return ERR_PTR(-EINVAL); } - if (*p_acl != JFS_ACL_NOT_CACHED) - return posix_acl_dup(*p_acl); - size = __jfs_getxattr(inode, ea_name, NULL, 0); if (size > 0) { @@ -62,17 +59,18 @@ static struct posix_acl *jfs_get_acl(struct inode *inode, int type) } if (size < 0) { - if (size == -ENODATA) { - *p_acl = NULL; + if (size == -ENODATA) acl = NULL; - } else + else acl = ERR_PTR(size); } else { acl = posix_acl_from_xattr(value, size); - if (!IS_ERR(acl)) - *p_acl = posix_acl_dup(acl); } kfree(value); + if (!IS_ERR(acl)) { + set_cached_acl(inode, type, acl); + posix_acl_release(acl); + } return acl; } @@ -80,8 +78,6 @@ static int jfs_set_acl(tid_t tid, struct inode *inode, int type, struct posix_acl *acl) { char *ea_name; - struct jfs_inode_info *ji = JFS_IP(inode); - struct posix_acl **p_acl; int rc; int size = 0; char *value = NULL; @@ -92,11 +88,9 @@ static int jfs_set_acl(tid_t tid, struct inode *inode, int type, switch(type) { case ACL_TYPE_ACCESS: ea_name = POSIX_ACL_XATTR_ACCESS; - p_acl = &ji->i_acl; break; case ACL_TYPE_DEFAULT: ea_name = POSIX_ACL_XATTR_DEFAULT; - p_acl = &ji->i_default_acl; if (!S_ISDIR(inode->i_mode)) return acl ? -EACCES : 0; break; @@ -116,27 +110,24 @@ static int jfs_set_acl(tid_t tid, struct inode *inode, int type, out: kfree(value); - if (!rc) { - if (*p_acl && (*p_acl != JFS_ACL_NOT_CACHED)) - posix_acl_release(*p_acl); - *p_acl = posix_acl_dup(acl); - } + if (!rc) + set_cached_acl(inode, type, acl); + return rc; } static int jfs_check_acl(struct inode *inode, int mask) { - struct jfs_inode_info *ji = JFS_IP(inode); + struct posix_acl *acl = jfs_get_acl(inode, ACL_TYPE_ACCESS); - if (ji->i_acl == JFS_ACL_NOT_CACHED) { - struct posix_acl *acl = jfs_get_acl(inode, ACL_TYPE_ACCESS); - if (IS_ERR(acl)) - return PTR_ERR(acl); + if (IS_ERR(acl)) + return PTR_ERR(acl); + if (acl) { + int error = posix_acl_permission(inode, acl, mask); posix_acl_release(acl); + return error; } - if (ji->i_acl) - return posix_acl_permission(inode, ji->i_acl, mask); return -EAGAIN; } diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h index 439901d205f..1439f119ec8 100644 --- a/fs/jfs/jfs_incore.h +++ b/fs/jfs/jfs_incore.h @@ -74,10 +74,6 @@ struct jfs_inode_info { /* xattr_sem allows us to access the xattrs without taking i_mutex */ struct rw_semaphore xattr_sem; lid_t xtlid; /* lid of xtree lock on directory */ -#ifdef CONFIG_JFS_POSIX_ACL - struct posix_acl *i_acl; - struct posix_acl *i_default_acl; -#endif union { struct { xtpage_t _xtroot; /* 288: xtree root */ @@ -107,8 +103,6 @@ struct jfs_inode_info { #define i_inline u.link._inline #define i_inline_ea u.link._inline_ea -#define JFS_ACL_NOT_CACHED ((void *)-1) - #define IREAD_LOCK(ip, subclass) \ down_read_nested(&JFS_IP(ip)->rdwrlock, subclass) #define IREAD_UNLOCK(ip) up_read(&JFS_IP(ip)->rdwrlock) diff --git a/fs/jfs/super.c b/fs/jfs/super.c index 09b1b6ee218..37e6dcda8fc 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -128,18 +128,6 @@ static void jfs_destroy_inode(struct inode *inode) ji->active_ag = -1; } spin_unlock_irq(&ji->ag_lock); - -#ifdef CONFIG_JFS_POSIX_ACL - if (ji->i_acl != JFS_ACL_NOT_CACHED) { - posix_acl_release(ji->i_acl); - ji->i_acl = JFS_ACL_NOT_CACHED; - } - if (ji->i_default_acl != JFS_ACL_NOT_CACHED) { - posix_acl_release(ji->i_default_acl); - ji->i_default_acl = JFS_ACL_NOT_CACHED; - } -#endif - kmem_cache_free(jfs_inode_cachep, ji); } @@ -798,10 +786,6 @@ static void init_once(void *foo) init_rwsem(&jfs_ip->xattr_sem); spin_lock_init(&jfs_ip->ag_lock); jfs_ip->active_ag = -1; -#ifdef CONFIG_JFS_POSIX_ACL - jfs_ip->i_acl = JFS_ACL_NOT_CACHED; - jfs_ip->i_default_acl = JFS_ACL_NOT_CACHED; -#endif inode_init_once(&jfs_ip->vfs_inode); } diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index 61dfa8173eb..fad364548bc 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c @@ -727,10 +727,7 @@ static int can_set_system_xattr(struct inode *inode, const char *name, /* * We're changing the ACL. Get rid of the cached one */ - acl =JFS_IP(inode)->i_acl; - if (acl != JFS_ACL_NOT_CACHED) - posix_acl_release(acl); - JFS_IP(inode)->i_acl = JFS_ACL_NOT_CACHED; + forget_cached_acl(inode, ACL_TYPE_ACCESS); return 0; } else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0) { @@ -746,10 +743,7 @@ static int can_set_system_xattr(struct inode *inode, const char *name, /* * We're changing the default ACL. Get rid of the cached one */ - acl =JFS_IP(inode)->i_default_acl; - if (acl && (acl != JFS_ACL_NOT_CACHED)) - posix_acl_release(acl); - JFS_IP(inode)->i_default_acl = JFS_ACL_NOT_CACHED; + forget_cached_acl(inode, ACL_TYPE_DEFAULT); return 0; } diff --git a/fs/namei.c b/fs/namei.c index 527119afb6a..5b961eb71cb 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1698,8 +1698,11 @@ struct file *do_filp_open(int dfd, const char *pathname, if (error) return ERR_PTR(error); error = path_walk(pathname, &nd); - if (error) + if (error) { + if (nd.root.mnt) + path_put(&nd.root); return ERR_PTR(error); + } if (unlikely(!audit_dummy_context())) audit_inode(pathname, nd.path.dentry); @@ -1759,6 +1762,8 @@ do_last: } filp = nameidata_to_filp(&nd, open_flag); mnt_drop_write(nd.path.mnt); + if (nd.root.mnt) + path_put(&nd.root); return filp; } @@ -1819,6 +1824,8 @@ ok: */ if (will_write) mnt_drop_write(nd.path.mnt); + if (nd.root.mnt) + path_put(&nd.root); return filp; exit_mutex_unlock: @@ -1859,6 +1866,8 @@ do_link: * with "intent.open". */ release_open_intent(&nd); + if (nd.root.mnt) + path_put(&nd.root); return ERR_PTR(error); } nd.flags &= ~LOOKUP_PARENT; diff --git a/fs/namespace.c b/fs/namespace.c index a7bea8c8bd4..3dc283fd471 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -42,6 +42,8 @@ __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock); static int event; static DEFINE_IDA(mnt_id_ida); static DEFINE_IDA(mnt_group_ida); +static int mnt_id_start = 0; +static int mnt_group_start = 1; static struct list_head *mount_hashtable __read_mostly; static struct kmem_cache *mnt_cache __read_mostly; @@ -69,7 +71,9 @@ static int mnt_alloc_id(struct vfsmount *mnt) retry: ida_pre_get(&mnt_id_ida, GFP_KERNEL); spin_lock(&vfsmount_lock); - res = ida_get_new(&mnt_id_ida, &mnt->mnt_id); + res = ida_get_new_above(&mnt_id_ida, mnt_id_start, &mnt->mnt_id); + if (!res) + mnt_id_start = mnt->mnt_id + 1; spin_unlock(&vfsmount_lock); if (res == -EAGAIN) goto retry; @@ -79,8 +83,11 @@ retry: static void mnt_free_id(struct vfsmount *mnt) { + int id = mnt->mnt_id; spin_lock(&vfsmount_lock); - ida_remove(&mnt_id_ida, mnt->mnt_id); + ida_remove(&mnt_id_ida, id); + if (mnt_id_start > id) + mnt_id_start = id; spin_unlock(&vfsmount_lock); } @@ -91,10 +98,18 @@ static void mnt_free_id(struct vfsmount *mnt) */ static int mnt_alloc_group_id(struct vfsmount *mnt) { + int res; + if (!ida_pre_get(&mnt_group_ida, GFP_KERNEL)) return -ENOMEM; - return ida_get_new_above(&mnt_group_ida, 1, &mnt->mnt_group_id); + res = ida_get_new_above(&mnt_group_ida, + mnt_group_start, + &mnt->mnt_group_id); + if (!res) + mnt_group_start = mnt->mnt_group_id + 1; + + return res; } /* @@ -102,7 +117,10 @@ static int mnt_alloc_group_id(struct vfsmount *mnt) */ void mnt_release_group_id(struct vfsmount *mnt) { - ida_remove(&mnt_group_ida, mnt->mnt_group_id); + int id = mnt->mnt_group_id; + ida_remove(&mnt_group_ida, id); + if (mnt_group_start > id) + mnt_group_start = id; mnt->mnt_group_id = 0; } @@ -2222,16 +2240,9 @@ static void __init init_mount_tree(void) mnt = do_kern_mount("rootfs", 0, "rootfs", NULL); if (IS_ERR(mnt)) panic("Can't create rootfs"); - ns = kmalloc(sizeof(*ns), GFP_KERNEL); - if (!ns) + ns = create_mnt_ns(mnt); + if (IS_ERR(ns)) panic("Can't allocate initial namespace"); - atomic_set(&ns->count, 1); - INIT_LIST_HEAD(&ns->list); - init_waitqueue_head(&ns->poll); - ns->event = 0; - list_add(&mnt->mnt_list, &ns->list); - ns->root = mnt; - mnt->mnt_ns = ns; init_task.nsproxy->mnt_ns = ns; get_mnt_ns(ns); diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 2696d6b513b..fe9d8f2a13f 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -309,10 +309,6 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode) /* ii->i_file_acl = 0; */ /* ii->i_dir_acl = 0; */ ii->i_dir_start_lookup = 0; -#ifdef CONFIG_NILFS_FS_POSIX_ACL - ii->i_acl = NULL; - ii->i_default_acl = NULL; -#endif ii->i_cno = 0; nilfs_set_inode_flags(inode); spin_lock(&sbi->s_next_gen_lock); @@ -434,10 +430,6 @@ static int __nilfs_read_inode(struct super_block *sb, unsigned long ino, raw_inode = nilfs_ifile_map_inode(sbi->s_ifile, ino, bh); -#ifdef CONFIG_NILFS_FS_POSIX_ACL - ii->i_acl = NILFS_ACL_NOT_CACHED; - ii->i_default_acl = NILFS_ACL_NOT_CACHED; -#endif if (nilfs_read_inode_common(inode, raw_inode)) goto failed_unmap; diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index edf6a59d9f2..724c63766e8 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h @@ -58,10 +58,6 @@ struct nilfs_inode_info { */ struct rw_semaphore xattr_sem; #endif -#ifdef CONFIG_NILFS_POSIX_ACL - struct posix_acl *i_acl; - struct posix_acl *i_default_acl; -#endif struct buffer_head *i_bh; /* i_bh contains a new or dirty disk inode */ struct inode vfs_inode; diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index ab785f85aa5..8e2ec43b18f 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -189,16 +189,6 @@ static void nilfs_clear_inode(struct inode *inode) { struct nilfs_inode_info *ii = NILFS_I(inode); -#ifdef CONFIG_NILFS_POSIX_ACL - if (ii->i_acl && ii->i_acl != NILFS_ACL_NOT_CACHED) { - posix_acl_release(ii->i_acl); - ii->i_acl = NILFS_ACL_NOT_CACHED; - } - if (ii->i_default_acl && ii->i_default_acl != NILFS_ACL_NOT_CACHED) { - posix_acl_release(ii->i_default_acl); - ii->i_default_acl = NILFS_ACL_NOT_CACHED; - } -#endif /* * Free resources allocated in nilfs_read_inode(), here. */ diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 6cdeaa76f27..110bb57c46a 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -92,6 +92,9 @@ struct ocfs2_unblock_ctl { enum ocfs2_unblock_action unblock_action; }; +/* Lockdep class keys */ +struct lock_class_key lockdep_keys[OCFS2_NUM_LOCK_TYPES]; + static int ocfs2_check_meta_downconvert(struct ocfs2_lock_res *lockres, int new_level); static void ocfs2_set_meta_lvb(struct ocfs2_lock_res *lockres); @@ -317,9 +320,16 @@ static int ocfs2_lock_create(struct ocfs2_super *osb, u32 dlm_flags); static inline int ocfs2_may_continue_on_blocked_lock(struct ocfs2_lock_res *lockres, int wanted); -static void ocfs2_cluster_unlock(struct ocfs2_super *osb, - struct ocfs2_lock_res *lockres, - int level); +static void __ocfs2_cluster_unlock(struct ocfs2_super *osb, + struct ocfs2_lock_res *lockres, + int level, unsigned long caller_ip); +static inline void ocfs2_cluster_unlock(struct ocfs2_super *osb, + struct ocfs2_lock_res *lockres, + int level) +{ + __ocfs2_cluster_unlock(osb, lockres, level, _RET_IP_); +} + static inline void ocfs2_generic_handle_downconvert_action(struct ocfs2_lock_res *lockres); static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lockres); static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *lockres); @@ -489,6 +499,13 @@ static void ocfs2_lock_res_init_common(struct ocfs2_super *osb, ocfs2_add_lockres_tracking(res, osb->osb_dlm_debug); ocfs2_init_lock_stats(res); +#ifdef CONFIG_DEBUG_LOCK_ALLOC + if (type != OCFS2_LOCK_TYPE_OPEN) + lockdep_init_map(&res->l_lockdep_map, ocfs2_lock_type_strings[type], + &lockdep_keys[type], 0); + else + res->l_lockdep_map.key = NULL; +#endif } void ocfs2_lock_res_init_once(struct ocfs2_lock_res *res) @@ -644,14 +661,10 @@ static void ocfs2_nfs_sync_lock_res_init(struct ocfs2_lock_res *res, static void ocfs2_orphan_scan_lock_res_init(struct ocfs2_lock_res *res, struct ocfs2_super *osb) { - struct ocfs2_orphan_scan_lvb *lvb; - ocfs2_lock_res_init_once(res); ocfs2_build_lock_name(OCFS2_LOCK_TYPE_ORPHAN_SCAN, 0, 0, res->l_name); ocfs2_lock_res_init_common(osb, res, OCFS2_LOCK_TYPE_ORPHAN_SCAN, &ocfs2_orphan_scan_lops, osb); - lvb = ocfs2_dlm_lvb(&res->l_lksb); - lvb->lvb_version = OCFS2_ORPHAN_LVB_VERSION; } void ocfs2_file_lock_res_init(struct ocfs2_lock_res *lockres, @@ -1256,11 +1269,13 @@ static int ocfs2_wait_for_mask_interruptible(struct ocfs2_mask_waiter *mw, return ret; } -static int ocfs2_cluster_lock(struct ocfs2_super *osb, - struct ocfs2_lock_res *lockres, - int level, - u32 lkm_flags, - int arg_flags) +static int __ocfs2_cluster_lock(struct ocfs2_super *osb, + struct ocfs2_lock_res *lockres, + int level, + u32 lkm_flags, + int arg_flags, + int l_subclass, + unsigned long caller_ip) { struct ocfs2_mask_waiter mw; int wait, catch_signals = !(osb->s_mount_opt & OCFS2_MOUNT_NOINTR); @@ -1403,13 +1418,37 @@ out: } ocfs2_update_lock_stats(lockres, level, &mw, ret); +#ifdef CONFIG_DEBUG_LOCK_ALLOC + if (!ret && lockres->l_lockdep_map.key != NULL) { + if (level == DLM_LOCK_PR) + rwsem_acquire_read(&lockres->l_lockdep_map, l_subclass, + !!(arg_flags & OCFS2_META_LOCK_NOQUEUE), + caller_ip); + else + rwsem_acquire(&lockres->l_lockdep_map, l_subclass, + !!(arg_flags & OCFS2_META_LOCK_NOQUEUE), + caller_ip); + } +#endif mlog_exit(ret); return ret; } -static void ocfs2_cluster_unlock(struct ocfs2_super *osb, - struct ocfs2_lock_res *lockres, - int level) +static inline int ocfs2_cluster_lock(struct ocfs2_super *osb, + struct ocfs2_lock_res *lockres, + int level, + u32 lkm_flags, + int arg_flags) +{ + return __ocfs2_cluster_lock(osb, lockres, level, lkm_flags, arg_flags, + 0, _RET_IP_); +} + + +static void __ocfs2_cluster_unlock(struct ocfs2_super *osb, + struct ocfs2_lock_res *lockres, + int level, + unsigned long caller_ip) { unsigned long flags; @@ -1418,6 +1457,10 @@ static void ocfs2_cluster_unlock(struct ocfs2_super *osb, ocfs2_dec_holders(lockres, level); ocfs2_downconvert_on_unlock(osb, lockres); spin_unlock_irqrestore(&lockres->l_lock, flags); +#ifdef CONFIG_DEBUG_LOCK_ALLOC + if (lockres->l_lockdep_map.key != NULL) + rwsem_release(&lockres->l_lockdep_map, 1, caller_ip); +#endif mlog_exit_void(); } @@ -1989,7 +2032,8 @@ static inline int ocfs2_meta_lvb_is_trustable(struct inode *inode, { struct ocfs2_meta_lvb *lvb = ocfs2_dlm_lvb(&lockres->l_lksb); - if (lvb->lvb_version == OCFS2_LVB_VERSION + if (ocfs2_dlm_lvb_valid(&lockres->l_lksb) + && lvb->lvb_version == OCFS2_LVB_VERSION && be32_to_cpu(lvb->lvb_igeneration) == inode->i_generation) return 1; return 0; @@ -2162,10 +2206,11 @@ static int ocfs2_assign_bh(struct inode *inode, * returns < 0 error if the callback will never be called, otherwise * the result of the lock will be communicated via the callback. */ -int ocfs2_inode_lock_full(struct inode *inode, - struct buffer_head **ret_bh, - int ex, - int arg_flags) +int ocfs2_inode_lock_full_nested(struct inode *inode, + struct buffer_head **ret_bh, + int ex, + int arg_flags, + int subclass) { int status, level, acquired; u32 dlm_flags; @@ -2203,7 +2248,8 @@ int ocfs2_inode_lock_full(struct inode *inode, if (arg_flags & OCFS2_META_LOCK_NOQUEUE) dlm_flags |= DLM_LKF_NOQUEUE; - status = ocfs2_cluster_lock(osb, lockres, level, dlm_flags, arg_flags); + status = __ocfs2_cluster_lock(osb, lockres, level, dlm_flags, + arg_flags, subclass, _RET_IP_); if (status < 0) { if (status != -EAGAIN && status != -EIOCBRETRY) mlog_errno(status); @@ -2369,35 +2415,45 @@ void ocfs2_inode_unlock(struct inode *inode, mlog_exit_void(); } -int ocfs2_orphan_scan_lock(struct ocfs2_super *osb, u32 *seqno, int ex) +int ocfs2_orphan_scan_lock(struct ocfs2_super *osb, u32 *seqno) { struct ocfs2_lock_res *lockres; struct ocfs2_orphan_scan_lvb *lvb; - int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR; int status = 0; + if (ocfs2_is_hard_readonly(osb)) + return -EROFS; + + if (ocfs2_mount_local(osb)) + return 0; + lockres = &osb->osb_orphan_scan.os_lockres; - status = ocfs2_cluster_lock(osb, lockres, level, 0, 0); + status = ocfs2_cluster_lock(osb, lockres, DLM_LOCK_EX, 0, 0); if (status < 0) return status; lvb = ocfs2_dlm_lvb(&lockres->l_lksb); - if (lvb->lvb_version == OCFS2_ORPHAN_LVB_VERSION) + if (ocfs2_dlm_lvb_valid(&lockres->l_lksb) && + lvb->lvb_version == OCFS2_ORPHAN_LVB_VERSION) *seqno = be32_to_cpu(lvb->lvb_os_seqno); + else + *seqno = osb->osb_orphan_scan.os_seqno + 1; + return status; } -void ocfs2_orphan_scan_unlock(struct ocfs2_super *osb, u32 seqno, int ex) +void ocfs2_orphan_scan_unlock(struct ocfs2_super *osb, u32 seqno) { struct ocfs2_lock_res *lockres; struct ocfs2_orphan_scan_lvb *lvb; - int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR; - lockres = &osb->osb_orphan_scan.os_lockres; - lvb = ocfs2_dlm_lvb(&lockres->l_lksb); - lvb->lvb_version = OCFS2_ORPHAN_LVB_VERSION; - lvb->lvb_os_seqno = cpu_to_be32(seqno); - ocfs2_cluster_unlock(osb, lockres, level); + if (!ocfs2_is_hard_readonly(osb) && !ocfs2_mount_local(osb)) { + lockres = &osb->osb_orphan_scan.os_lockres; + lvb = ocfs2_dlm_lvb(&lockres->l_lksb); + lvb->lvb_version = OCFS2_ORPHAN_LVB_VERSION; + lvb->lvb_os_seqno = cpu_to_be32(seqno); + ocfs2_cluster_unlock(osb, lockres, DLM_LOCK_EX); + } } int ocfs2_super_lock(struct ocfs2_super *osb, @@ -3627,7 +3683,8 @@ static int ocfs2_refresh_qinfo(struct ocfs2_mem_dqinfo *oinfo) struct ocfs2_global_disk_dqinfo *gdinfo; int status = 0; - if (lvb->lvb_version == OCFS2_QINFO_LVB_VERSION) { + if (ocfs2_dlm_lvb_valid(&lockres->l_lksb) && + lvb->lvb_version == OCFS2_QINFO_LVB_VERSION) { info->dqi_bgrace = be32_to_cpu(lvb->lvb_bgrace); info->dqi_igrace = be32_to_cpu(lvb->lvb_igrace); oinfo->dqi_syncms = be32_to_cpu(lvb->lvb_syncms); diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h index 31b90d7b8f5..7553836931d 100644 --- a/fs/ocfs2/dlmglue.h +++ b/fs/ocfs2/dlmglue.h @@ -78,6 +78,14 @@ struct ocfs2_orphan_scan_lvb { /* don't block waiting for the downconvert thread, instead return -EAGAIN */ #define OCFS2_LOCK_NONBLOCK (0x04) +/* Locking subclasses of inode cluster lock */ +enum { + OI_LS_NORMAL = 0, + OI_LS_PARENT, + OI_LS_RENAME1, + OI_LS_RENAME2, +}; + int ocfs2_dlm_init(struct ocfs2_super *osb); void ocfs2_dlm_shutdown(struct ocfs2_super *osb, int hangup_pending); void ocfs2_lock_res_init_once(struct ocfs2_lock_res *res); @@ -104,25 +112,31 @@ void ocfs2_open_unlock(struct inode *inode); int ocfs2_inode_lock_atime(struct inode *inode, struct vfsmount *vfsmnt, int *level); -int ocfs2_inode_lock_full(struct inode *inode, +int ocfs2_inode_lock_full_nested(struct inode *inode, struct buffer_head **ret_bh, int ex, - int arg_flags); + int arg_flags, + int subclass); int ocfs2_inode_lock_with_page(struct inode *inode, struct buffer_head **ret_bh, int ex, struct page *page); +/* Variants without special locking class or flags */ +#define ocfs2_inode_lock_full(i, r, e, f)\ + ocfs2_inode_lock_full_nested(i, r, e, f, OI_LS_NORMAL) +#define ocfs2_inode_lock_nested(i, b, e, s)\ + ocfs2_inode_lock_full_nested(i, b, e, 0, s) /* 99% of the time we don't want to supply any additional flags -- * those are for very specific cases only. */ -#define ocfs2_inode_lock(i, b, e) ocfs2_inode_lock_full(i, b, e, 0) +#define ocfs2_inode_lock(i, b, e) ocfs2_inode_lock_full_nested(i, b, e, 0, OI_LS_NORMAL) void ocfs2_inode_unlock(struct inode *inode, int ex); int ocfs2_super_lock(struct ocfs2_super *osb, int ex); void ocfs2_super_unlock(struct ocfs2_super *osb, int ex); -int ocfs2_orphan_scan_lock(struct ocfs2_super *osb, u32 *seqno, int ex); -void ocfs2_orphan_scan_unlock(struct ocfs2_super *osb, u32 seqno, int ex); +int ocfs2_orphan_scan_lock(struct ocfs2_super *osb, u32 *seqno); +void ocfs2_orphan_scan_unlock(struct ocfs2_super *osb, u32 seqno); int ocfs2_rename_lock(struct ocfs2_super *osb); void ocfs2_rename_unlock(struct ocfs2_super *osb); diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 07267e0da90..62442e413a0 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -2026,7 +2026,7 @@ static ssize_t ocfs2_file_splice_read(struct file *in, size_t len, unsigned int flags) { - int ret = 0; + int ret = 0, lock_level = 0; struct inode *inode = in->f_path.dentry->d_inode; mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", in, pipe, @@ -2037,12 +2037,12 @@ static ssize_t ocfs2_file_splice_read(struct file *in, /* * See the comment in ocfs2_file_aio_read() */ - ret = ocfs2_inode_lock(inode, NULL, 0); + ret = ocfs2_inode_lock_atime(inode, in->f_vfsmnt, &lock_level); if (ret < 0) { mlog_errno(ret); goto bail; } - ocfs2_inode_unlock(inode, 0); + ocfs2_inode_unlock(inode, lock_level); ret = generic_file_splice_read(in, ppos, pipe, len, flags); diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 10e1fa87396..4dc8890ba31 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -215,6 +215,8 @@ bail: static int ocfs2_init_locked_inode(struct inode *inode, void *opaque) { struct ocfs2_find_inode_args *args = opaque; + static struct lock_class_key ocfs2_quota_ip_alloc_sem_key, + ocfs2_file_ip_alloc_sem_key; mlog_entry("inode = %p, opaque = %p\n", inode, opaque); @@ -223,6 +225,15 @@ static int ocfs2_init_locked_inode(struct inode *inode, void *opaque) if (args->fi_sysfile_type != 0) lockdep_set_class(&inode->i_mutex, &ocfs2_sysfile_lock_key[args->fi_sysfile_type]); + if (args->fi_sysfile_type == USER_QUOTA_SYSTEM_INODE || + args->fi_sysfile_type == GROUP_QUOTA_SYSTEM_INODE || + args->fi_sysfile_type == LOCAL_USER_QUOTA_SYSTEM_INODE || + args->fi_sysfile_type == LOCAL_GROUP_QUOTA_SYSTEM_INODE) + lockdep_set_class(&OCFS2_I(inode)->ip_alloc_sem, + &ocfs2_quota_ip_alloc_sem_key); + else + lockdep_set_class(&OCFS2_I(inode)->ip_alloc_sem, + &ocfs2_file_ip_alloc_sem_key); mlog_exit(0); return 0; diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 4a3b9e6b31a..f033760ecbe 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -1880,13 +1880,20 @@ void ocfs2_queue_orphan_scan(struct ocfs2_super *osb) os = &osb->osb_orphan_scan; - status = ocfs2_orphan_scan_lock(osb, &seqno, DLM_LOCK_EX); + if (atomic_read(&os->os_state) == ORPHAN_SCAN_INACTIVE) + goto out; + + status = ocfs2_orphan_scan_lock(osb, &seqno); if (status < 0) { if (status != -EAGAIN) mlog_errno(status); goto out; } + /* Do no queue the tasks if the volume is being umounted */ + if (atomic_read(&os->os_state) == ORPHAN_SCAN_INACTIVE) + goto unlock; + if (os->os_seqno != seqno) { os->os_seqno = seqno; goto unlock; @@ -1903,7 +1910,7 @@ void ocfs2_queue_orphan_scan(struct ocfs2_super *osb) os->os_count++; os->os_scantime = CURRENT_TIME; unlock: - ocfs2_orphan_scan_unlock(osb, seqno, DLM_LOCK_EX); + ocfs2_orphan_scan_unlock(osb, seqno); out: return; } @@ -1920,8 +1927,9 @@ void ocfs2_orphan_scan_work(struct work_struct *work) mutex_lock(&os->os_lock); ocfs2_queue_orphan_scan(osb); - schedule_delayed_work(&os->os_orphan_scan_work, - ocfs2_orphan_scan_timeout()); + if (atomic_read(&os->os_state) == ORPHAN_SCAN_ACTIVE) + schedule_delayed_work(&os->os_orphan_scan_work, + ocfs2_orphan_scan_timeout()); mutex_unlock(&os->os_lock); } @@ -1930,26 +1938,33 @@ void ocfs2_orphan_scan_stop(struct ocfs2_super *osb) struct ocfs2_orphan_scan *os; os = &osb->osb_orphan_scan; - mutex_lock(&os->os_lock); - cancel_delayed_work(&os->os_orphan_scan_work); - mutex_unlock(&os->os_lock); + if (atomic_read(&os->os_state) == ORPHAN_SCAN_ACTIVE) { + atomic_set(&os->os_state, ORPHAN_SCAN_INACTIVE); + mutex_lock(&os->os_lock); + cancel_delayed_work(&os->os_orphan_scan_work); + mutex_unlock(&os->os_lock); + } } -int ocfs2_orphan_scan_init(struct ocfs2_super *osb) +void ocfs2_orphan_scan_init(struct ocfs2_super *osb) { struct ocfs2_orphan_scan *os; os = &osb->osb_orphan_scan; os->os_osb = osb; os->os_count = 0; + os->os_seqno = 0; os->os_scantime = CURRENT_TIME; mutex_init(&os->os_lock); - - INIT_DELAYED_WORK(&os->os_orphan_scan_work, - ocfs2_orphan_scan_work); - schedule_delayed_work(&os->os_orphan_scan_work, - ocfs2_orphan_scan_timeout()); - return 0; + INIT_DELAYED_WORK(&os->os_orphan_scan_work, ocfs2_orphan_scan_work); + + if (ocfs2_is_hard_readonly(osb) || ocfs2_mount_local(osb)) + atomic_set(&os->os_state, ORPHAN_SCAN_INACTIVE); + else { + atomic_set(&os->os_state, ORPHAN_SCAN_ACTIVE); + schedule_delayed_work(&os->os_orphan_scan_work, + ocfs2_orphan_scan_timeout()); + } } struct ocfs2_orphan_filldir_priv { diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index 61045eeb3f6..5432c7f79cc 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h @@ -144,7 +144,7 @@ static inline void ocfs2_inode_set_new(struct ocfs2_super *osb, } /* Exported only for the journal struct init code in super.c. Do not call. */ -int ocfs2_orphan_scan_init(struct ocfs2_super *osb); +void ocfs2_orphan_scan_init(struct ocfs2_super *osb); void ocfs2_orphan_scan_stop(struct ocfs2_super *osb); void ocfs2_orphan_scan_exit(struct ocfs2_super *osb); diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 33464c6b60a..8601f934010 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -118,7 +118,7 @@ static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry, mlog(0, "find name %.*s in directory %llu\n", dentry->d_name.len, dentry->d_name.name, (unsigned long long)OCFS2_I(dir)->ip_blkno); - status = ocfs2_inode_lock(dir, NULL, 0); + status = ocfs2_inode_lock_nested(dir, NULL, 0, OI_LS_PARENT); if (status < 0) { if (status != -ENOENT) mlog_errno(status); @@ -636,7 +636,7 @@ static int ocfs2_link(struct dentry *old_dentry, if (S_ISDIR(inode->i_mode)) return -EPERM; - err = ocfs2_inode_lock(dir, &parent_fe_bh, 1); + err = ocfs2_inode_lock_nested(dir, &parent_fe_bh, 1, OI_LS_PARENT); if (err < 0) { if (err != -ENOENT) mlog_errno(err); @@ -800,7 +800,8 @@ static int ocfs2_unlink(struct inode *dir, return -EPERM; } - status = ocfs2_inode_lock(dir, &parent_node_bh, 1); + status = ocfs2_inode_lock_nested(dir, &parent_node_bh, 1, + OI_LS_PARENT); if (status < 0) { if (status != -ENOENT) mlog_errno(status); @@ -978,7 +979,8 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, inode1 = tmpinode; } /* lock id2 */ - status = ocfs2_inode_lock(inode2, bh2, 1); + status = ocfs2_inode_lock_nested(inode2, bh2, 1, + OI_LS_RENAME1); if (status < 0) { if (status != -ENOENT) mlog_errno(status); @@ -987,7 +989,7 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, } /* lock id1 */ - status = ocfs2_inode_lock(inode1, bh1, 1); + status = ocfs2_inode_lock_nested(inode1, bh1, 1, OI_LS_RENAME2); if (status < 0) { /* * An error return must mean that no cluster locks @@ -1103,7 +1105,8 @@ static int ocfs2_rename(struct inode *old_dir, * won't have to concurrently downconvert the inode and the * dentry locks. */ - status = ocfs2_inode_lock(old_inode, &old_inode_bh, 1); + status = ocfs2_inode_lock_nested(old_inode, &old_inode_bh, 1, + OI_LS_PARENT); if (status < 0) { if (status != -ENOENT) mlog_errno(status); diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 18c1d9ec1c9..c9345ebb849 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h @@ -34,6 +34,7 @@ #include <linux/workqueue.h> #include <linux/kref.h> #include <linux/mutex.h> +#include <linux/lockdep.h> #ifndef CONFIG_OCFS2_COMPAT_JBD # include <linux/jbd2.h> #else @@ -152,6 +153,14 @@ struct ocfs2_lock_res { unsigned int l_lock_max_exmode; /* Max wait for EX */ unsigned int l_lock_refresh; /* Disk refreshes */ #endif +#ifdef CONFIG_DEBUG_LOCK_ALLOC + struct lockdep_map l_lockdep_map; +#endif +}; + +enum ocfs2_orphan_scan_state { + ORPHAN_SCAN_ACTIVE, + ORPHAN_SCAN_INACTIVE }; struct ocfs2_orphan_scan { @@ -162,6 +171,7 @@ struct ocfs2_orphan_scan { struct timespec os_scantime; /* time this node ran the scan */ u32 os_count; /* tracks node specific scans */ u32 os_seqno; /* tracks cluster wide scans */ + atomic_t os_state; /* ACTIVE or INACTIVE */ }; struct ocfs2_dlm_debug { diff --git a/fs/ocfs2/stack_o2cb.c b/fs/ocfs2/stack_o2cb.c index fcd120f1493..3f661376a2d 100644 --- a/fs/ocfs2/stack_o2cb.c +++ b/fs/ocfs2/stack_o2cb.c @@ -236,6 +236,16 @@ static int o2cb_dlm_lock_status(union ocfs2_dlm_lksb *lksb) return dlm_status_to_errno(lksb->lksb_o2dlm.status); } +/* + * o2dlm aways has a "valid" LVB. If the dlm loses track of the LVB + * contents, it will zero out the LVB. Thus the caller can always trust + * the contents. + */ +static int o2cb_dlm_lvb_valid(union ocfs2_dlm_lksb *lksb) +{ + return 1; +} + static void *o2cb_dlm_lvb(union ocfs2_dlm_lksb *lksb) { return (void *)(lksb->lksb_o2dlm.lvb); @@ -354,6 +364,7 @@ static struct ocfs2_stack_operations o2cb_stack_ops = { .dlm_lock = o2cb_dlm_lock, .dlm_unlock = o2cb_dlm_unlock, .lock_status = o2cb_dlm_lock_status, + .lvb_valid = o2cb_dlm_lvb_valid, .lock_lvb = o2cb_dlm_lvb, .dump_lksb = o2cb_dump_lksb, }; diff --git a/fs/ocfs2/stack_user.c b/fs/ocfs2/stack_user.c index 9b76d41a8ac..ff4c798a563 100644 --- a/fs/ocfs2/stack_user.c +++ b/fs/ocfs2/stack_user.c @@ -738,6 +738,13 @@ static int user_dlm_lock_status(union ocfs2_dlm_lksb *lksb) return lksb->lksb_fsdlm.sb_status; } +static int user_dlm_lvb_valid(union ocfs2_dlm_lksb *lksb) +{ + int invalid = lksb->lksb_fsdlm.sb_flags & DLM_SBF_VALNOTVALID; + + return !invalid; +} + static void *user_dlm_lvb(union ocfs2_dlm_lksb *lksb) { if (!lksb->lksb_fsdlm.sb_lvbptr) @@ -873,6 +880,7 @@ static struct ocfs2_stack_operations ocfs2_user_plugin_ops = { .dlm_lock = user_dlm_lock, .dlm_unlock = user_dlm_unlock, .lock_status = user_dlm_lock_status, + .lvb_valid = user_dlm_lvb_valid, .lock_lvb = user_dlm_lvb, .plock = user_plock, .dump_lksb = user_dlm_dump_lksb, diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c index 68b668b0e60..3f2f1c45b7b 100644 --- a/fs/ocfs2/stackglue.c +++ b/fs/ocfs2/stackglue.c @@ -6,7 +6,7 @@ * Code which implements an OCFS2 specific interface to underlying * cluster stacks. * - * Copyright (C) 2007 Oracle. All rights reserved. + * Copyright (C) 2007, 2009 Oracle. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public @@ -271,11 +271,12 @@ int ocfs2_dlm_lock_status(union ocfs2_dlm_lksb *lksb) } EXPORT_SYMBOL_GPL(ocfs2_dlm_lock_status); -/* - * Why don't we cast to ocfs2_meta_lvb? The "clean" answer is that we - * don't cast at the glue level. The real answer is that the header - * ordering is nigh impossible. - */ +int ocfs2_dlm_lvb_valid(union ocfs2_dlm_lksb *lksb) +{ + return active_stack->sp_ops->lvb_valid(lksb); +} +EXPORT_SYMBOL_GPL(ocfs2_dlm_lvb_valid); + void *ocfs2_dlm_lvb(union ocfs2_dlm_lksb *lksb) { return active_stack->sp_ops->lock_lvb(lksb); diff --git a/fs/ocfs2/stackglue.h b/fs/ocfs2/stackglue.h index c571af375ef..03a44d60eac 100644 --- a/fs/ocfs2/stackglue.h +++ b/fs/ocfs2/stackglue.h @@ -186,6 +186,11 @@ struct ocfs2_stack_operations { int (*lock_status)(union ocfs2_dlm_lksb *lksb); /* + * Return non-zero if the LVB is valid. + */ + int (*lvb_valid)(union ocfs2_dlm_lksb *lksb); + + /* * Pull the lvb pointer off of the stack-specific lksb. */ void *(*lock_lvb)(union ocfs2_dlm_lksb *lksb); @@ -252,6 +257,7 @@ int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn, struct ocfs2_lock_res *astarg); int ocfs2_dlm_lock_status(union ocfs2_dlm_lksb *lksb); +int ocfs2_dlm_lvb_valid(union ocfs2_dlm_lksb *lksb); void *ocfs2_dlm_lvb(union ocfs2_dlm_lksb *lksb); void ocfs2_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb); diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 8439f6b324b..73a16d4666d 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -923,14 +923,23 @@ static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh, int nr) { struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data; + int ret; if (ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap)) return 0; - if (!buffer_jbd(bg_bh) || !bh2jh(bg_bh)->b_committed_data) + + if (!buffer_jbd(bg_bh)) return 1; + jbd_lock_bh_state(bg_bh); bg = (struct ocfs2_group_desc *) bh2jh(bg_bh)->b_committed_data; - return !ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap); + if (bg) + ret = !ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap); + else + ret = 1; + jbd_unlock_bh_state(bg_bh); + + return ret; } static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb, @@ -1885,6 +1894,7 @@ static inline int ocfs2_block_group_clear_bits(handle_t *handle, unsigned int tmp; int journal_type = OCFS2_JOURNAL_ACCESS_WRITE; struct ocfs2_group_desc *undo_bg = NULL; + int cluster_bitmap = 0; mlog_entry_void(); @@ -1905,18 +1915,28 @@ static inline int ocfs2_block_group_clear_bits(handle_t *handle, } if (ocfs2_is_cluster_bitmap(alloc_inode)) - undo_bg = (struct ocfs2_group_desc *) bh2jh(group_bh)->b_committed_data; + cluster_bitmap = 1; + + if (cluster_bitmap) { + jbd_lock_bh_state(group_bh); + undo_bg = (struct ocfs2_group_desc *) + bh2jh(group_bh)->b_committed_data; + BUG_ON(!undo_bg); + } tmp = num_bits; while(tmp--) { ocfs2_clear_bit((bit_off + tmp), (unsigned long *) bg->bg_bitmap); - if (ocfs2_is_cluster_bitmap(alloc_inode)) + if (cluster_bitmap) ocfs2_set_bit(bit_off + tmp, (unsigned long *) undo_bg->bg_bitmap); } le16_add_cpu(&bg->bg_free_bits_count, num_bits); + if (cluster_bitmap) + jbd_unlock_bh_state(group_bh); + status = ocfs2_journal_dirty(handle, group_bh); if (status < 0) mlog_errno(status); diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 0d3ed7407a0..7efb349fb9b 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -205,11 +205,10 @@ static const match_table_t tokens = { #ifdef CONFIG_DEBUG_FS static int ocfs2_osb_dump(struct ocfs2_super *osb, char *buf, int len) { - int out = 0; - int i; struct ocfs2_cluster_connection *cconn = osb->cconn; struct ocfs2_recovery_map *rm = osb->recovery_map; - struct ocfs2_orphan_scan *os; + struct ocfs2_orphan_scan *os = &osb->osb_orphan_scan; + int i, out = 0; out += snprintf(buf + out, len - out, "%10s => Id: %-s Uuid: %-s Gen: 0x%X Label: %-s\n", @@ -234,20 +233,24 @@ static int ocfs2_osb_dump(struct ocfs2_super *osb, char *buf, int len) "%10s => Opts: 0x%lX AtimeQuanta: %u\n", "Mount", osb->s_mount_opt, osb->s_atime_quantum); - out += snprintf(buf + out, len - out, - "%10s => Stack: %s Name: %*s Version: %d.%d\n", - "Cluster", - (*osb->osb_cluster_stack == '\0' ? - "o2cb" : osb->osb_cluster_stack), - cconn->cc_namelen, cconn->cc_name, - cconn->cc_version.pv_major, cconn->cc_version.pv_minor); + if (cconn) { + out += snprintf(buf + out, len - out, + "%10s => Stack: %s Name: %*s " + "Version: %d.%d\n", "Cluster", + (*osb->osb_cluster_stack == '\0' ? + "o2cb" : osb->osb_cluster_stack), + cconn->cc_namelen, cconn->cc_name, + cconn->cc_version.pv_major, + cconn->cc_version.pv_minor); + } spin_lock(&osb->dc_task_lock); out += snprintf(buf + out, len - out, "%10s => Pid: %d Count: %lu WakeSeq: %lu " "WorkSeq: %lu\n", "DownCnvt", - task_pid_nr(osb->dc_task), osb->blocked_lock_count, - osb->dc_wake_sequence, osb->dc_work_sequence); + (osb->dc_task ? task_pid_nr(osb->dc_task) : -1), + osb->blocked_lock_count, osb->dc_wake_sequence, + osb->dc_work_sequence); spin_unlock(&osb->dc_task_lock); spin_lock(&osb->osb_lock); @@ -267,14 +270,15 @@ static int ocfs2_osb_dump(struct ocfs2_super *osb, char *buf, int len) out += snprintf(buf + out, len - out, "%10s => Pid: %d Interval: %lu Needs: %d\n", "Commit", - task_pid_nr(osb->commit_task), osb->osb_commit_interval, + (osb->commit_task ? task_pid_nr(osb->commit_task) : -1), + osb->osb_commit_interval, atomic_read(&osb->needs_checkpoint)); out += snprintf(buf + out, len - out, - "%10s => State: %d NumTxns: %d TxnId: %lu\n", + "%10s => State: %d TxnId: %lu NumTxns: %d\n", "Journal", osb->journal->j_state, - atomic_read(&osb->journal->j_num_trans), - osb->journal->j_trans_id); + osb->journal->j_trans_id, + atomic_read(&osb->journal->j_num_trans)); out += snprintf(buf + out, len - out, "%10s => GlobalAllocs: %d LocalAllocs: %d " @@ -300,9 +304,18 @@ static int ocfs2_osb_dump(struct ocfs2_super *osb, char *buf, int len) atomic_read(&osb->s_num_inodes_stolen)); spin_unlock(&osb->osb_lock); + out += snprintf(buf + out, len - out, "OrphanScan => "); + out += snprintf(buf + out, len - out, "Local: %u Global: %u ", + os->os_count, os->os_seqno); + out += snprintf(buf + out, len - out, " Last Scan: "); + if (atomic_read(&os->os_state) == ORPHAN_SCAN_INACTIVE) + out += snprintf(buf + out, len - out, "Disabled\n"); + else + out += snprintf(buf + out, len - out, "%lu seconds ago\n", + (get_seconds() - os->os_scantime.tv_sec)); + out += snprintf(buf + out, len - out, "%10s => %3s %10s\n", "Slots", "Num", "RecoGen"); - for (i = 0; i < osb->max_slots; ++i) { out += snprintf(buf + out, len - out, "%10s %c %3d %10d\n", @@ -311,13 +324,6 @@ static int ocfs2_osb_dump(struct ocfs2_super *osb, char *buf, int len) i, osb->slot_recovery_generations[i]); } - os = &osb->osb_orphan_scan; - out += snprintf(buf + out, len - out, "Orphan Scan=> "); - out += snprintf(buf + out, len - out, "Local: %u Global: %u ", - os->os_count, os->os_seqno); - out += snprintf(buf + out, len - out, " Last Scan: %lu seconds ago\n", - (get_seconds() - os->os_scantime.tv_sec)); - return out; } @@ -1175,6 +1181,9 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) atomic_set(&osb->vol_state, VOLUME_MOUNTED_QUOTAS); wake_up(&osb->osb_mount_event); + /* Start this when the mount is almost sure of being successful */ + ocfs2_orphan_scan_init(osb); + mlog_exit(status); return status; @@ -1810,14 +1819,15 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err) debugfs_remove(osb->osb_ctxt); + /* Orphan scan should be stopped as early as possible */ + ocfs2_orphan_scan_stop(osb); + ocfs2_disable_quotas(osb); ocfs2_shutdown_local_alloc(osb); ocfs2_truncate_log_shutdown(osb); - ocfs2_orphan_scan_stop(osb); - /* This will disable recovery and flush any recovery work. */ ocfs2_recovery_exit(osb); @@ -1978,13 +1988,6 @@ static int ocfs2_initialize_super(struct super_block *sb, goto bail; } - status = ocfs2_orphan_scan_init(osb); - if (status) { - mlog(ML_ERROR, "Unable to initialize delayed orphan scan\n"); - mlog_errno(status); - goto bail; - } - init_waitqueue_head(&osb->checkpoint_event); atomic_set(&osb->needs_checkpoint, 0); diff --git a/fs/ocfs2/sysfile.c b/fs/ocfs2/sysfile.c index ab713ebdd54..40e53702948 100644 --- a/fs/ocfs2/sysfile.c +++ b/fs/ocfs2/sysfile.c @@ -50,6 +50,10 @@ static inline int is_in_system_inode_array(struct ocfs2_super *osb, int type, u32 slot); +#ifdef CONFIG_DEBUG_LOCK_ALLOC +static struct lock_class_key ocfs2_sysfile_cluster_lock_key[NUM_SYSTEM_INODES]; +#endif + static inline int is_global_system_inode(int type) { return type >= OCFS2_FIRST_ONLINE_SYSTEM_INODE && @@ -118,6 +122,21 @@ static struct inode * _ocfs2_get_system_file_inode(struct ocfs2_super *osb, inode = NULL; goto bail; } +#ifdef CONFIG_DEBUG_LOCK_ALLOC + if (type == LOCAL_USER_QUOTA_SYSTEM_INODE || + type == LOCAL_GROUP_QUOTA_SYSTEM_INODE || + type == JOURNAL_SYSTEM_INODE) { + /* Ignore inode lock on these inodes as the lock does not + * really belong to any process and lockdep cannot handle + * that */ + OCFS2_I(inode)->ip_inode_lockres.l_lockdep_map.key = NULL; + } else { + lockdep_init_map(&OCFS2_I(inode)->ip_inode_lockres. + l_lockdep_map, + ocfs2_system_inodes[type].si_name, + &ocfs2_sysfile_cluster_lock_key[type], 0); + } +#endif bail: return inode; diff --git a/fs/open.c b/fs/open.c index 7200e23d925..dd98e807602 100644 --- a/fs/open.c +++ b/fs/open.c @@ -378,63 +378,63 @@ SYSCALL_ALIAS(sys_ftruncate64, SyS_ftruncate64); #endif #endif /* BITS_PER_LONG == 32 */ -SYSCALL_DEFINE(fallocate)(int fd, int mode, loff_t offset, loff_t len) + +int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len) { - struct file *file; - struct inode *inode; - long ret = -EINVAL; + struct inode *inode = file->f_path.dentry->d_inode; + long ret; if (offset < 0 || len <= 0) - goto out; + return -EINVAL; /* Return error if mode is not supported */ - ret = -EOPNOTSUPP; if (mode && !(mode & FALLOC_FL_KEEP_SIZE)) - goto out; + return -EOPNOTSUPP; - ret = -EBADF; - file = fget(fd); - if (!file) - goto out; if (!(file->f_mode & FMODE_WRITE)) - goto out_fput; + return -EBADF; /* * Revalidate the write permissions, in case security policy has * changed since the files were opened. */ ret = security_file_permission(file, MAY_WRITE); if (ret) - goto out_fput; + return ret; - inode = file->f_path.dentry->d_inode; - - ret = -ESPIPE; if (S_ISFIFO(inode->i_mode)) - goto out_fput; + return -ESPIPE; - ret = -ENODEV; /* * Let individual file system decide if it supports preallocation * for directories or not. */ if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) - goto out_fput; + return -ENODEV; - ret = -EFBIG; /* Check for wrap through zero too */ if (((offset + len) > inode->i_sb->s_maxbytes) || ((offset + len) < 0)) - goto out_fput; + return -EFBIG; - if (inode->i_op->fallocate) - ret = inode->i_op->fallocate(inode, mode, offset, len); - else - ret = -EOPNOTSUPP; + if (!inode->i_op->fallocate) + return -EOPNOTSUPP; -out_fput: - fput(file); -out: - return ret; + return inode->i_op->fallocate(inode, mode, offset, len); } + +SYSCALL_DEFINE(fallocate)(int fd, int mode, loff_t offset, loff_t len) +{ + struct file *file; + int error = -EBADF; + + file = fget(fd); + if (file) { + error = do_fallocate(file, mode, offset, len); + fput(file); + } + + return error; +} + #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS asmlinkage long SyS_fallocate(long fd, long mode, loff_t offset, loff_t len) { diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 6fd0f47e45d..a14d6cd9eed 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1131,8 +1131,6 @@ static void init_inode(struct inode *inode, struct treepath *path) REISERFS_I(inode)->i_trans_id = 0; REISERFS_I(inode)->i_jl = NULL; mutex_init(&(REISERFS_I(inode)->i_mmap)); - reiserfs_init_acl_access(inode); - reiserfs_init_acl_default(inode); reiserfs_init_xattr_rwsem(inode); if (stat_data_v1(ih)) { @@ -1834,8 +1832,6 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK; sd_attrs_to_i_attrs(REISERFS_I(inode)->i_attrs, inode); mutex_init(&(REISERFS_I(inode)->i_mmap)); - reiserfs_init_acl_access(inode); - reiserfs_init_acl_default(inode); reiserfs_init_xattr_rwsem(inode); /* key to search for correct place for new stat data */ diff --git a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c index 238e9d9b31e..18b315d3d10 100644 --- a/fs/reiserfs/resize.c +++ b/fs/reiserfs/resize.c @@ -82,7 +82,6 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) if (reiserfs_allocate_list_bitmaps(s, jbitmap, bmap_nr_new) < 0) { printk ("reiserfs_resize: unable to allocate memory for journal bitmaps\n"); - unlock_super(s); return -ENOMEM; } /* the new journal bitmaps are zero filled, now we copy in the bitmap diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 2969773cfc2..d3aeb061612 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -529,10 +529,6 @@ static void init_once(void *foo) INIT_LIST_HEAD(&ei->i_prealloc_list); inode_init_once(&ei->vfs_inode); -#ifdef CONFIG_REISERFS_FS_POSIX_ACL - ei->i_acl_access = NULL; - ei->i_acl_default = NULL; -#endif } static int init_inodecache(void) @@ -580,25 +576,6 @@ static void reiserfs_dirty_inode(struct inode *inode) reiserfs_write_unlock(inode->i_sb); } -#ifdef CONFIG_REISERFS_FS_POSIX_ACL -static void reiserfs_clear_inode(struct inode *inode) -{ - struct posix_acl *acl; - - acl = REISERFS_I(inode)->i_acl_access; - if (acl && !IS_ERR(acl)) - posix_acl_release(acl); - REISERFS_I(inode)->i_acl_access = NULL; - - acl = REISERFS_I(inode)->i_acl_default; - if (acl && !IS_ERR(acl)) - posix_acl_release(acl); - REISERFS_I(inode)->i_acl_default = NULL; -} -#else -#define reiserfs_clear_inode NULL -#endif - #ifdef CONFIG_QUOTA static ssize_t reiserfs_quota_write(struct super_block *, int, const char *, size_t, loff_t); @@ -612,7 +589,6 @@ static const struct super_operations reiserfs_sops = { .write_inode = reiserfs_write_inode, .dirty_inode = reiserfs_dirty_inode, .delete_inode = reiserfs_delete_inode, - .clear_inode = reiserfs_clear_inode, .put_super = reiserfs_put_super, .write_super = reiserfs_write_super, .sync_fs = reiserfs_sync_fs, diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index c303c426fe2..35d6e672a27 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c @@ -188,29 +188,6 @@ static void *posix_acl_to_disk(const struct posix_acl *acl, size_t * size) return ERR_PTR(-EINVAL); } -static inline void iset_acl(struct inode *inode, struct posix_acl **i_acl, - struct posix_acl *acl) -{ - spin_lock(&inode->i_lock); - if (*i_acl != ERR_PTR(-ENODATA)) - posix_acl_release(*i_acl); - *i_acl = posix_acl_dup(acl); - spin_unlock(&inode->i_lock); -} - -static inline struct posix_acl *iget_acl(struct inode *inode, - struct posix_acl **i_acl) -{ - struct posix_acl *acl = ERR_PTR(-ENODATA); - - spin_lock(&inode->i_lock); - if (*i_acl != ERR_PTR(-ENODATA)) - acl = posix_acl_dup(*i_acl); - spin_unlock(&inode->i_lock); - - return acl; -} - /* * Inode operation get_posix_acl(). * @@ -220,34 +197,29 @@ static inline struct posix_acl *iget_acl(struct inode *inode, struct posix_acl *reiserfs_get_acl(struct inode *inode, int type) { char *name, *value; - struct posix_acl *acl, **p_acl; + struct posix_acl *acl; int size; int retval; - struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode); + + acl = get_cached_acl(inode, type); + if (acl != ACL_NOT_CACHED) + return acl; switch (type) { case ACL_TYPE_ACCESS: name = POSIX_ACL_XATTR_ACCESS; - p_acl = &reiserfs_i->i_acl_access; break; case ACL_TYPE_DEFAULT: name = POSIX_ACL_XATTR_DEFAULT; - p_acl = &reiserfs_i->i_acl_default; break; default: - return ERR_PTR(-EINVAL); + BUG(); } - acl = iget_acl(inode, p_acl); - if (acl && !IS_ERR(acl)) - return acl; - else if (PTR_ERR(acl) == -ENODATA) - return NULL; - size = reiserfs_xattr_get(inode, name, NULL, 0); if (size < 0) { if (size == -ENODATA || size == -ENOSYS) { - *p_acl = ERR_PTR(-ENODATA); + set_cached_acl(inode, type, NULL); return NULL; } return ERR_PTR(size); @@ -262,14 +234,13 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type) /* This shouldn't actually happen as it should have been caught above.. but just in case */ acl = NULL; - *p_acl = ERR_PTR(-ENODATA); } else if (retval < 0) { acl = ERR_PTR(retval); } else { acl = posix_acl_from_disk(value, retval); - if (!IS_ERR(acl)) - iset_acl(inode, p_acl, acl); } + if (!IS_ERR(acl)) + set_cached_acl(inode, type, acl); kfree(value); return acl; @@ -287,10 +258,8 @@ reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode, { char *name; void *value = NULL; - struct posix_acl **p_acl; size_t size = 0; int error; - struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode); if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; @@ -298,7 +267,6 @@ reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode, switch (type) { case ACL_TYPE_ACCESS: name = POSIX_ACL_XATTR_ACCESS; - p_acl = &reiserfs_i->i_acl_access; if (acl) { mode_t mode = inode->i_mode; error = posix_acl_equiv_mode(acl, &mode); @@ -313,7 +281,6 @@ reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode, break; case ACL_TYPE_DEFAULT: name = POSIX_ACL_XATTR_DEFAULT; - p_acl = &reiserfs_i->i_acl_default; if (!S_ISDIR(inode->i_mode)) return acl ? -EACCES : 0; break; @@ -346,7 +313,7 @@ reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode, kfree(value); if (!error) - iset_acl(inode, p_acl, acl); + set_cached_acl(inode, type, acl); return error; } @@ -379,11 +346,8 @@ reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th, } acl = reiserfs_get_acl(dir, ACL_TYPE_DEFAULT); - if (IS_ERR(acl)) { - if (PTR_ERR(acl) == -ENODATA) - goto apply_umask; + if (IS_ERR(acl)) return PTR_ERR(acl); - } if (acl) { struct posix_acl *acl_copy; diff --git a/fs/super.c b/fs/super.c index d40d53a22fb..2761d3e22ed 100644 --- a/fs/super.c +++ b/fs/super.c @@ -608,6 +608,7 @@ void emergency_remount(void) static DEFINE_IDA(unnamed_dev_ida); static DEFINE_SPINLOCK(unnamed_dev_lock);/* protects the above */ +static int unnamed_dev_start = 0; /* don't bother trying below it */ int set_anon_super(struct super_block *s, void *data) { @@ -618,7 +619,9 @@ int set_anon_super(struct super_block *s, void *data) if (ida_pre_get(&unnamed_dev_ida, GFP_ATOMIC) == 0) return -ENOMEM; spin_lock(&unnamed_dev_lock); - error = ida_get_new(&unnamed_dev_ida, &dev); + error = ida_get_new_above(&unnamed_dev_ida, unnamed_dev_start, &dev); + if (!error) + unnamed_dev_start = dev + 1; spin_unlock(&unnamed_dev_lock); if (error == -EAGAIN) /* We raced and lost with another CPU. */ @@ -629,6 +632,8 @@ int set_anon_super(struct super_block *s, void *data) if ((dev & MAX_ID_MASK) == (1 << MINORBITS)) { spin_lock(&unnamed_dev_lock); ida_remove(&unnamed_dev_ida, dev); + if (unnamed_dev_start > dev) + unnamed_dev_start = dev; spin_unlock(&unnamed_dev_lock); return -EMFILE; } @@ -645,6 +650,8 @@ void kill_anon_super(struct super_block *sb) generic_shutdown_super(sb); spin_lock(&unnamed_dev_lock); ida_remove(&unnamed_dev_ida, slot); + if (slot < unnamed_dev_start) + unnamed_dev_start = slot; spin_unlock(&unnamed_dev_lock); } diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c index cfd31e229c8..adafcf55653 100644 --- a/fs/ubifs/xattr.c +++ b/fs/ubifs/xattr.c @@ -55,9 +55,9 @@ * ACL support is not implemented. */ +#include "ubifs.h" #include <linux/xattr.h> #include <linux/posix_acl_xattr.h> -#include "ubifs.h" /* * Limit the number of extended attributes per inode so that the total size diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c index e48e9a3af76..1e068535b58 100644 --- a/fs/udf/balloc.c +++ b/fs/udf/balloc.c @@ -238,7 +238,7 @@ static int udf_bitmap_prealloc_blocks(struct super_block *sb, mutex_lock(&sbi->s_alloc_mutex); part_len = sbi->s_partmaps[partition].s_partition_len; - if (first_block < 0 || first_block >= part_len) + if (first_block >= part_len) goto out; if (first_block + block_count > part_len) @@ -297,7 +297,7 @@ static int udf_bitmap_new_block(struct super_block *sb, mutex_lock(&sbi->s_alloc_mutex); repeat: - if (goal < 0 || goal >= sbi->s_partmaps[partition].s_partition_len) + if (goal >= sbi->s_partmaps[partition].s_partition_len) goal = 0; nr_groups = bitmap->s_nr_groups; @@ -666,8 +666,7 @@ static int udf_table_prealloc_blocks(struct super_block *sb, int8_t etype = -1; struct udf_inode_info *iinfo; - if (first_block < 0 || - first_block >= sbi->s_partmaps[partition].s_partition_len) + if (first_block >= sbi->s_partmaps[partition].s_partition_len) return 0; iinfo = UDF_I(table); @@ -743,7 +742,7 @@ static int udf_table_new_block(struct super_block *sb, return newblock; mutex_lock(&sbi->s_alloc_mutex); - if (goal < 0 || goal >= sbi->s_partmaps[partition].s_partition_len) + if (goal >= sbi->s_partmaps[partition].s_partition_len) goal = 0; /* We search for the closest matching block to goal. If we find diff --git a/fs/udf/lowlevel.c b/fs/udf/lowlevel.c index 703843f30ff..1b88fd5df05 100644 --- a/fs/udf/lowlevel.c +++ b/fs/udf/lowlevel.c @@ -56,7 +56,12 @@ unsigned long udf_get_last_block(struct super_block *sb) struct block_device *bdev = sb->s_bdev; unsigned long lblock = 0; - if (ioctl_by_bdev(bdev, CDROM_LAST_WRITTEN, (unsigned long) &lblock)) + /* + * ioctl failed or returned obviously bogus value? + * Try using the device size... + */ + if (ioctl_by_bdev(bdev, CDROM_LAST_WRITTEN, (unsigned long) &lblock) || + lblock == 0) lblock = bdev->bd_inode->i_size >> sb->s_blocksize_bits; if (lblock) diff --git a/fs/xfs/linux-2.6/xfs_acl.c b/fs/xfs/linux-2.6/xfs_acl.c index 1e9d1246eeb..b23a5450644 100644 --- a/fs/xfs/linux-2.6/xfs_acl.c +++ b/fs/xfs/linux-2.6/xfs_acl.c @@ -25,14 +25,10 @@ #include <linux/posix_acl_xattr.h> -#define XFS_ACL_NOT_CACHED ((void *)-1) - /* * Locking scheme: * - all ACL updates are protected by inode->i_mutex, which is taken before * calling into this file. - * - access and updates to the ip->i_acl and ip->i_default_acl pointers are - * protected by inode->i_lock. */ STATIC struct posix_acl * @@ -102,59 +98,35 @@ xfs_acl_to_disk(struct xfs_acl *aclp, const struct posix_acl *acl) } } -/* - * Update the cached ACL pointer in the inode. - * - * Because we don't hold any locks while reading/writing the attribute - * from/to disk another thread could have raced and updated the cached - * ACL value before us. In that case we release the previous cached value - * and update it with our new value. - */ -STATIC void -xfs_update_cached_acl(struct inode *inode, struct posix_acl **p_acl, - struct posix_acl *acl) -{ - spin_lock(&inode->i_lock); - if (*p_acl && *p_acl != XFS_ACL_NOT_CACHED) - posix_acl_release(*p_acl); - *p_acl = posix_acl_dup(acl); - spin_unlock(&inode->i_lock); -} - struct posix_acl * xfs_get_acl(struct inode *inode, int type) { struct xfs_inode *ip = XFS_I(inode); - struct posix_acl *acl = NULL, **p_acl; + struct posix_acl *acl; struct xfs_acl *xfs_acl; int len = sizeof(struct xfs_acl); char *ea_name; int error; + acl = get_cached_acl(inode, type); + if (acl != ACL_NOT_CACHED) + return acl; + switch (type) { case ACL_TYPE_ACCESS: ea_name = SGI_ACL_FILE; - p_acl = &ip->i_acl; break; case ACL_TYPE_DEFAULT: ea_name = SGI_ACL_DEFAULT; - p_acl = &ip->i_default_acl; break; default: - return ERR_PTR(-EINVAL); + BUG(); } - spin_lock(&inode->i_lock); - if (*p_acl != XFS_ACL_NOT_CACHED) - acl = posix_acl_dup(*p_acl); - spin_unlock(&inode->i_lock); - /* * If we have a cached ACLs value just return it, not need to * go out to the disk. */ - if (acl) - return acl; xfs_acl = kzalloc(sizeof(struct xfs_acl), GFP_KERNEL); if (!xfs_acl) @@ -165,7 +137,7 @@ xfs_get_acl(struct inode *inode, int type) /* * If the attribute doesn't exist make sure we have a negative * cache entry, for any other error assume it is transient and - * leave the cache entry as XFS_ACL_NOT_CACHED. + * leave the cache entry as ACL_NOT_CACHED. */ if (error == -ENOATTR) { acl = NULL; @@ -179,7 +151,7 @@ xfs_get_acl(struct inode *inode, int type) goto out; out_update_cache: - xfs_update_cached_acl(inode, p_acl, acl); + set_cached_acl(inode, type, acl); out: kfree(xfs_acl); return acl; @@ -189,7 +161,6 @@ STATIC int xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) { struct xfs_inode *ip = XFS_I(inode); - struct posix_acl **p_acl; char *ea_name; int error; @@ -199,13 +170,11 @@ xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) switch (type) { case ACL_TYPE_ACCESS: ea_name = SGI_ACL_FILE; - p_acl = &ip->i_acl; break; case ACL_TYPE_DEFAULT: if (!S_ISDIR(inode->i_mode)) return acl ? -EACCES : 0; ea_name = SGI_ACL_DEFAULT; - p_acl = &ip->i_default_acl; break; default: return -EINVAL; @@ -242,7 +211,7 @@ xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) } if (!error) - xfs_update_cached_acl(inode, p_acl, acl); + set_cached_acl(inode, type, acl); return error; } @@ -384,30 +353,6 @@ xfs_acl_chmod(struct inode *inode) return error; } -void -xfs_inode_init_acls(struct xfs_inode *ip) -{ - /* - * No need for locking, inode is not live yet. - */ - ip->i_acl = XFS_ACL_NOT_CACHED; - ip->i_default_acl = XFS_ACL_NOT_CACHED; -} - -void -xfs_inode_clear_acls(struct xfs_inode *ip) -{ - /* - * No need for locking here, the inode is not live anymore - * and just about to be freed. - */ - if (ip->i_acl != XFS_ACL_NOT_CACHED) - posix_acl_release(ip->i_acl); - if (ip->i_default_acl != XFS_ACL_NOT_CACHED) - posix_acl_release(ip->i_default_acl); -} - - /* * System xattr handlers. * diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h index 63dc1f2efad..947b150df8e 100644 --- a/fs/xfs/xfs_acl.h +++ b/fs/xfs/xfs_acl.h @@ -46,8 +46,6 @@ extern int xfs_check_acl(struct inode *inode, int mask); extern struct posix_acl *xfs_get_acl(struct inode *inode, int type); extern int xfs_inherit_acl(struct inode *inode, struct posix_acl *default_acl); extern int xfs_acl_chmod(struct inode *inode); -extern void xfs_inode_init_acls(struct xfs_inode *ip); -extern void xfs_inode_clear_acls(struct xfs_inode *ip); extern int posix_acl_access_exists(struct inode *inode); extern int posix_acl_default_exists(struct inode *inode); @@ -57,8 +55,6 @@ extern struct xattr_handler xfs_xattr_system_handler; # define xfs_get_acl(inode, type) NULL # define xfs_inherit_acl(inode, default_acl) 0 # define xfs_acl_chmod(inode) 0 -# define xfs_inode_init_acls(ip) -# define xfs_inode_clear_acls(ip) # define posix_acl_access_exists(inode) 0 # define posix_acl_default_exists(inode) 0 #endif /* CONFIG_XFS_POSIX_ACL */ diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 76c540f719e..5fcec6f020a 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -83,7 +83,6 @@ xfs_inode_alloc( memset(&ip->i_d, 0, sizeof(xfs_icdinode_t)); ip->i_size = 0; ip->i_new_size = 0; - xfs_inode_init_acls(ip); /* * Initialize inode's trace buffers. @@ -560,7 +559,6 @@ xfs_ireclaim( ASSERT(atomic_read(&ip->i_pincount) == 0); ASSERT(!spin_is_locked(&ip->i_flags_lock)); ASSERT(completion_done(&ip->i_flush)); - xfs_inode_clear_acls(ip); kmem_zone_free(xfs_inode_zone, ip); } diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 77016702938..1804f866a71 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -273,11 +273,6 @@ typedef struct xfs_inode { /* VFS inode */ struct inode i_vnode; /* embedded VFS inode */ -#ifdef CONFIG_XFS_POSIX_ACL - struct posix_acl *i_acl; - struct posix_acl *i_default_acl; -#endif - /* Trace buffers per inode. */ #ifdef XFS_INODE_TRACE struct ktrace *i_trace; /* general inode trace */ |