aboutsummaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/acl.c44
-rw-r--r--fs/btrfs/btrfs_inode.h4
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/inode.c18
-rw-r--r--fs/compat_ioctl.c48
-rw-r--r--fs/devpts/inode.c10
-rw-r--r--fs/ext2/acl.c81
-rw-r--r--fs/ext2/acl.h4
-rw-r--r--fs/ext2/ext2.h4
-rw-r--r--fs/ext2/inode.c4
-rw-r--r--fs/ext2/super.c16
-rw-r--r--fs/ext3/acl.c85
-rw-r--r--fs/ext3/acl.h4
-rw-r--r--fs/ext3/inode.c4
-rw-r--r--fs/ext3/super.c16
-rw-r--r--fs/ext4/acl.c67
-rw-r--r--fs/ext4/acl.h4
-rw-r--r--fs/ext4/ext4.h4
-rw-r--r--fs/ext4/inode.c4
-rw-r--r--fs/ext4/super.c16
-rw-r--r--fs/fs-writeback.c100
-rw-r--r--fs/inode.c27
-rw-r--r--fs/ioctl.c35
-rw-r--r--fs/jffs2/acl.c87
-rw-r--r--fs/jffs2/acl.h4
-rw-r--r--fs/jffs2/jffs2_fs_i.h4
-rw-r--r--fs/jffs2/os-linux.h4
-rw-r--r--fs/jffs2/readinode.c1
-rw-r--r--fs/jfs/acl.c47
-rw-r--r--fs/jfs/jfs_incore.h6
-rw-r--r--fs/jfs/super.c16
-rw-r--r--fs/jfs/xattr.c10
-rw-r--r--fs/namei.c11
-rw-r--r--fs/namespace.c37
-rw-r--r--fs/nilfs2/inode.c8
-rw-r--r--fs/nilfs2/nilfs.h4
-rw-r--r--fs/nilfs2/super.c10
-rw-r--r--fs/ocfs2/dlmglue.c123
-rw-r--r--fs/ocfs2/dlmglue.h24
-rw-r--r--fs/ocfs2/file.c6
-rw-r--r--fs/ocfs2/inode.c11
-rw-r--r--fs/ocfs2/journal.c43
-rw-r--r--fs/ocfs2/journal.h2
-rw-r--r--fs/ocfs2/namei.c15
-rw-r--r--fs/ocfs2/ocfs2.h10
-rw-r--r--fs/ocfs2/stack_o2cb.c11
-rw-r--r--fs/ocfs2/stack_user.c8
-rw-r--r--fs/ocfs2/stackglue.c13
-rw-r--r--fs/ocfs2/stackglue.h6
-rw-r--r--fs/ocfs2/suballoc.c28
-rw-r--r--fs/ocfs2/super.c69
-rw-r--r--fs/ocfs2/sysfile.c19
-rw-r--r--fs/open.c58
-rw-r--r--fs/reiserfs/inode.c4
-rw-r--r--fs/reiserfs/resize.c1
-rw-r--r--fs/reiserfs/super.c24
-rw-r--r--fs/reiserfs/xattr_acl.c58
-rw-r--r--fs/super.c9
-rw-r--r--fs/ubifs/xattr.c2
-rw-r--r--fs/udf/balloc.c9
-rw-r--r--fs/udf/lowlevel.c7
-rw-r--r--fs/xfs/linux-2.6/xfs_acl.c73
-rw-r--r--fs/xfs/xfs_acl.h4
-rw-r--r--fs/xfs/xfs_iget.c2
-rw-r--r--fs/xfs/xfs_inode.h5
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 */