diff options
author | Dave Kleikamp <shaggy@austin.ibm.com> | 2005-09-01 09:02:43 -0500 |
---|---|---|
committer | Dave Kleikamp <shaggy@austin.ibm.com> | 2005-09-01 09:02:43 -0500 |
commit | 4f4b401bfaa97edbea41a1fcab794148e7ac0421 (patch) | |
tree | d58dcf9d90e15364398a3a4584f2892439295b64 | |
parent | b1b5d7f9b7ac6a8e3452ac43a53eebf69fdf5a77 (diff) | |
download | op-kernel-dev-4f4b401bfaa97edbea41a1fcab794148e7ac0421.zip op-kernel-dev-4f4b401bfaa97edbea41a1fcab794148e7ac0421.tar.gz |
JFS: allow extended attributes to be set within a existing transaction
Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
-rw-r--r-- | fs/jfs/acl.c | 24 | ||||
-rw-r--r-- | fs/jfs/jfs_acl.h | 12 | ||||
-rw-r--r-- | fs/jfs/jfs_xattr.h | 4 | ||||
-rw-r--r-- | fs/jfs/namei.c | 63 | ||||
-rw-r--r-- | fs/jfs/xattr.c | 58 |
5 files changed, 112 insertions, 49 deletions
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c index e892dab..461e493 100644 --- a/fs/jfs/acl.c +++ b/fs/jfs/acl.c @@ -23,6 +23,7 @@ #include <linux/quotaops.h> #include <linux/posix_acl_xattr.h> #include "jfs_incore.h" +#include "jfs_txnmgr.h" #include "jfs_xattr.h" #include "jfs_acl.h" @@ -75,7 +76,8 @@ static struct posix_acl *jfs_get_acl(struct inode *inode, int type) return acl; } -static int jfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) +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); @@ -110,7 +112,7 @@ static int jfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) if (rc < 0) goto out; } - rc = __jfs_setxattr(inode, ea_name, value, size, 0); + rc = __jfs_setxattr(tid, inode, ea_name, value, size, 0); out: kfree(value); @@ -143,7 +145,7 @@ int jfs_permission(struct inode *inode, int mask, struct nameidata *nd) return generic_permission(inode, mask, jfs_check_acl); } -int jfs_init_acl(struct inode *inode, struct inode *dir) +int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir) { struct posix_acl *acl = NULL; struct posix_acl *clone; @@ -159,7 +161,7 @@ int jfs_init_acl(struct inode *inode, struct inode *dir) if (acl) { if (S_ISDIR(inode->i_mode)) { - rc = jfs_set_acl(inode, ACL_TYPE_DEFAULT, acl); + rc = jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, acl); if (rc) goto cleanup; } @@ -173,7 +175,8 @@ int jfs_init_acl(struct inode *inode, struct inode *dir) if (rc >= 0) { inode->i_mode = mode; if (rc > 0) - rc = jfs_set_acl(inode, ACL_TYPE_ACCESS, clone); + rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, + clone); } posix_acl_release(clone); cleanup: @@ -202,8 +205,15 @@ static int jfs_acl_chmod(struct inode *inode) return -ENOMEM; rc = posix_acl_chmod_masq(clone, inode->i_mode); - if (!rc) - rc = jfs_set_acl(inode, ACL_TYPE_ACCESS, clone); + if (!rc) { + tid_t tid = txBegin(inode->i_sb, 0); + down(&JFS_IP(inode)->commit_sem); + rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, clone); + if (!rc) + rc = txCommit(tid, 1, &inode, 0); + txEnd(tid); + up(&JFS_IP(inode)->commit_sem); + } posix_acl_release(clone); return rc; diff --git a/fs/jfs/jfs_acl.h b/fs/jfs/jfs_acl.h index a3acd3e..a7629376 100644 --- a/fs/jfs/jfs_acl.h +++ b/fs/jfs/jfs_acl.h @@ -21,8 +21,16 @@ #ifdef CONFIG_JFS_POSIX_ACL int jfs_permission(struct inode *, int, struct nameidata *); -int jfs_init_acl(struct inode *, struct inode *); +int jfs_init_acl(tid_t, struct inode *, struct inode *); int jfs_setattr(struct dentry *, struct iattr *); -#endif /* CONFIG_JFS_POSIX_ACL */ +#else + +static inline int jfs_init_acl(tid_t tid, struct inode *inode, + struct inode *dir) +{ + return 0; +} + +#endif #endif /* _H_JFS_ACL */ diff --git a/fs/jfs/jfs_xattr.h b/fs/jfs/jfs_xattr.h index a1052f3f0..116a73c 100644 --- a/fs/jfs/jfs_xattr.h +++ b/fs/jfs/jfs_xattr.h @@ -52,8 +52,8 @@ struct jfs_ea_list { #define END_EALIST(ealist) \ ((struct jfs_ea *) (((char *) (ealist)) + EALIST_SIZE(ealist))) -extern int __jfs_setxattr(struct inode *, const char *, const void *, size_t, - int); +extern int __jfs_setxattr(tid_t, struct inode *, const char *, const void *, + size_t, int); extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t, int); extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t); diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 49ccde3..f23f9c2 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -39,6 +39,24 @@ struct dentry_operations jfs_ci_dentry_operations; static s64 commitZeroLink(tid_t, struct inode *); /* + * NAME: free_ea_wmap(inode) + * + * FUNCTION: free uncommitted extended attributes from working map + * + */ +static inline void free_ea_wmap(struct inode *inode) +{ + dxd_t *ea = &JFS_IP(inode)->ea; + + if (ea->flag & DXD_EXTENT) { + /* free EA pages from cache */ + invalidate_dxd_metapages(inode, *ea); + dbFree(inode, addressDXD(ea), lengthDXD(ea)); + } + ea->flag = 0; +} + +/* * NAME: jfs_create(dip, dentry, mode) * * FUNCTION: create a regular file in the parent directory <dip> @@ -89,8 +107,13 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode, down(&JFS_IP(dip)->commit_sem); down(&JFS_IP(ip)->commit_sem); + rc = jfs_init_acl(tid, ip, dip); + if (rc) + goto out3; + if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) { jfs_err("jfs_create: dtSearch returned %d", rc); + txAbort(tid, 0); goto out3; } @@ -139,6 +162,7 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode, up(&JFS_IP(dip)->commit_sem); up(&JFS_IP(ip)->commit_sem); if (rc) { + free_ea_wmap(ip); ip->i_nlink = 0; iput(ip); } else @@ -147,11 +171,6 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode, out2: free_UCSname(&dname); -#ifdef CONFIG_JFS_POSIX_ACL - if (rc == 0) - jfs_init_acl(ip, dip); -#endif - out1: jfs_info("jfs_create: rc:%d", rc); @@ -216,8 +235,13 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode) down(&JFS_IP(dip)->commit_sem); down(&JFS_IP(ip)->commit_sem); + rc = jfs_init_acl(tid, ip, dip); + if (rc) + goto out3; + if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) { jfs_err("jfs_mkdir: dtSearch returned %d", rc); + txAbort(tid, 0); goto out3; } @@ -267,6 +291,7 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode) up(&JFS_IP(dip)->commit_sem); up(&JFS_IP(ip)->commit_sem); if (rc) { + free_ea_wmap(ip); ip->i_nlink = 0; iput(ip); } else @@ -275,10 +300,6 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode) out2: free_UCSname(&dname); -#ifdef CONFIG_JFS_POSIX_ACL - if (rc == 0) - jfs_init_acl(ip, dip); -#endif out1: @@ -1000,6 +1021,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, up(&JFS_IP(dip)->commit_sem); up(&JFS_IP(ip)->commit_sem); if (rc) { + free_ea_wmap(ip); ip->i_nlink = 0; iput(ip); } else @@ -1008,11 +1030,6 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, out2: free_UCSname(&dname); -#ifdef CONFIG_JFS_POSIX_ACL - if (rc == 0) - jfs_init_acl(ip, dip); -#endif - out1: jfs_info("jfs_symlink: rc:%d", rc); return rc; @@ -1328,17 +1345,25 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry, down(&JFS_IP(dir)->commit_sem); down(&JFS_IP(ip)->commit_sem); - if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE))) + rc = jfs_init_acl(tid, ip, dir); + if (rc) goto out3; + if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE))) { + txAbort(tid, 0); + goto out3; + } + tblk = tid_to_tblock(tid); tblk->xflag |= COMMIT_CREATE; tblk->ino = ip->i_ino; tblk->u.ixpxd = JFS_IP(ip)->ixpxd; ino = ip->i_ino; - if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack))) + if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack))) { + txAbort(tid, 0); goto out3; + } ip->i_op = &jfs_file_inode_operations; jfs_ip->dev = new_encode_dev(rdev); @@ -1360,6 +1385,7 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry, up(&JFS_IP(ip)->commit_sem); up(&JFS_IP(dir)->commit_sem); if (rc) { + free_ea_wmap(ip); ip->i_nlink = 0; iput(ip); } else @@ -1368,11 +1394,6 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry, out1: free_UCSname(&dname); -#ifdef CONFIG_JFS_POSIX_ACL - if (rc == 0) - jfs_init_acl(ip, dir); -#endif - out: jfs_info("jfs_mknod: returning %d", rc); return rc; diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index 554ec73..35674b2 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c @@ -633,12 +633,12 @@ static void ea_release(struct inode *inode, struct ea_buffer *ea_buf) } } -static int ea_put(struct inode *inode, struct ea_buffer *ea_buf, int new_size) +static int ea_put(tid_t tid, struct inode *inode, struct ea_buffer *ea_buf, + int new_size) { struct jfs_inode_info *ji = JFS_IP(inode); unsigned long old_blocks, new_blocks; int rc = 0; - tid_t tid; if (new_size == 0) { ea_release(inode, ea_buf); @@ -664,9 +664,6 @@ static int ea_put(struct inode *inode, struct ea_buffer *ea_buf, int new_size) if (rc) return rc; - tid = txBegin(inode->i_sb, 0); - down(&ji->commit_sem); - old_blocks = new_blocks = 0; if (ji->ea.flag & DXD_EXTENT) { @@ -695,11 +692,8 @@ static int ea_put(struct inode *inode, struct ea_buffer *ea_buf, int new_size) DQUOT_FREE_BLOCK(inode, old_blocks); inode->i_ctime = CURRENT_TIME; - rc = txCommit(tid, 1, &inode, 0); - txEnd(tid); - up(&ji->commit_sem); - return rc; + return 0; } /* @@ -810,8 +804,8 @@ static int can_set_xattr(struct inode *inode, const char *name, return permission(inode, MAY_WRITE, NULL); } -int __jfs_setxattr(struct inode *inode, const char *name, const void *value, - size_t value_len, int flags) +int __jfs_setxattr(tid_t tid, struct inode *inode, const char *name, + const void *value, size_t value_len, int flags) { struct jfs_ea_list *ealist; struct jfs_ea *ea, *old_ea = NULL, *next_ea = NULL; @@ -825,9 +819,6 @@ int __jfs_setxattr(struct inode *inode, const char *name, const void *value, int rc; int length; - if ((rc = can_set_xattr(inode, name, value, value_len))) - return rc; - if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { os2name = kmalloc(namelen - XATTR_OS2_PREFIX_LEN + 1, GFP_KERNEL); @@ -939,7 +930,7 @@ int __jfs_setxattr(struct inode *inode, const char *name, const void *value, ealist->size = cpu_to_le32(new_size); - rc = ea_put(inode, &ea_buf, new_size); + rc = ea_put(tid, inode, &ea_buf, new_size); goto out; release: @@ -955,12 +946,29 @@ int __jfs_setxattr(struct inode *inode, const char *name, const void *value, int jfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t value_len, int flags) { + struct inode *inode = dentry->d_inode; + struct jfs_inode_info *ji = JFS_IP(inode); + int rc; + tid_t tid; + + if ((rc = can_set_xattr(inode, name, value, value_len))) + return rc; + if (value == NULL) { /* empty EA, do not remove */ value = ""; value_len = 0; } - return __jfs_setxattr(dentry->d_inode, name, value, value_len, flags); + tid = txBegin(inode->i_sb, 0); + down(&ji->commit_sem); + rc = __jfs_setxattr(tid, dentry->d_inode, name, value, value_len, + flags); + if (!rc) + rc = txCommit(tid, 1, &inode, 0); + txEnd(tid); + up(&ji->commit_sem); + + return rc; } static int can_get_xattr(struct inode *inode, const char *name) @@ -1122,5 +1130,21 @@ ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size) int jfs_removexattr(struct dentry *dentry, const char *name) { - return __jfs_setxattr(dentry->d_inode, name, NULL, 0, XATTR_REPLACE); + struct inode *inode = dentry->d_inode; + struct jfs_inode_info *ji = JFS_IP(inode); + int rc; + tid_t tid; + + if ((rc = can_set_xattr(inode, name, NULL, 0))) + return rc; + + tid = txBegin(inode->i_sb, 0); + down(&ji->commit_sem); + rc = __jfs_setxattr(tid, dentry->d_inode, name, NULL, 0, XATTR_REPLACE); + if (!rc) + rc = txCommit(tid, 1, &inode, 0); + txEnd(tid); + up(&ji->commit_sem); + + return rc; } |