JFS: allow extended attributes to be set within a existing transaction

Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>

+112 -49
+17 -7
fs/jfs/acl.c
··· 23 23 #include <linux/quotaops.h> 24 24 #include <linux/posix_acl_xattr.h> 25 25 #include "jfs_incore.h" 26 + #include "jfs_txnmgr.h" 26 27 #include "jfs_xattr.h" 27 28 #include "jfs_acl.h" 28 29 ··· 76 75 return acl; 77 76 } 78 77 79 - static int jfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) 78 + static int jfs_set_acl(tid_t tid, struct inode *inode, int type, 79 + struct posix_acl *acl) 80 80 { 81 81 char *ea_name; 82 82 struct jfs_inode_info *ji = JFS_IP(inode); ··· 112 110 if (rc < 0) 113 111 goto out; 114 112 } 115 - rc = __jfs_setxattr(inode, ea_name, value, size, 0); 113 + rc = __jfs_setxattr(tid, inode, ea_name, value, size, 0); 116 114 out: 117 115 kfree(value); 118 116 ··· 145 143 return generic_permission(inode, mask, jfs_check_acl); 146 144 } 147 145 148 - int jfs_init_acl(struct inode *inode, struct inode *dir) 146 + int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir) 149 147 { 150 148 struct posix_acl *acl = NULL; 151 149 struct posix_acl *clone; ··· 161 159 162 160 if (acl) { 163 161 if (S_ISDIR(inode->i_mode)) { 164 - rc = jfs_set_acl(inode, ACL_TYPE_DEFAULT, acl); 162 + rc = jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, acl); 165 163 if (rc) 166 164 goto cleanup; 167 165 } ··· 175 173 if (rc >= 0) { 176 174 inode->i_mode = mode; 177 175 if (rc > 0) 178 - rc = jfs_set_acl(inode, ACL_TYPE_ACCESS, clone); 176 + rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, 177 + clone); 179 178 } 180 179 posix_acl_release(clone); 181 180 cleanup: ··· 205 202 return -ENOMEM; 206 203 207 204 rc = posix_acl_chmod_masq(clone, inode->i_mode); 208 - if (!rc) 209 - rc = jfs_set_acl(inode, ACL_TYPE_ACCESS, clone); 205 + if (!rc) { 206 + tid_t tid = txBegin(inode->i_sb, 0); 207 + down(&JFS_IP(inode)->commit_sem); 208 + rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, clone); 209 + if (!rc) 210 + rc = txCommit(tid, 1, &inode, 0); 211 + txEnd(tid); 212 + up(&JFS_IP(inode)->commit_sem); 213 + } 210 214 211 215 posix_acl_release(clone); 212 216 return rc;
+10 -2
fs/jfs/jfs_acl.h
··· 21 21 #ifdef CONFIG_JFS_POSIX_ACL 22 22 23 23 int jfs_permission(struct inode *, int, struct nameidata *); 24 - int jfs_init_acl(struct inode *, struct inode *); 24 + int jfs_init_acl(tid_t, struct inode *, struct inode *); 25 25 int jfs_setattr(struct dentry *, struct iattr *); 26 26 27 - #endif /* CONFIG_JFS_POSIX_ACL */ 27 + #else 28 + 29 + static inline int jfs_init_acl(tid_t tid, struct inode *inode, 30 + struct inode *dir) 31 + { 32 + return 0; 33 + } 34 + 35 + #endif 28 36 #endif /* _H_JFS_ACL */
+2 -2
fs/jfs/jfs_xattr.h
··· 52 52 #define END_EALIST(ealist) \ 53 53 ((struct jfs_ea *) (((char *) (ealist)) + EALIST_SIZE(ealist))) 54 54 55 - extern int __jfs_setxattr(struct inode *, const char *, const void *, size_t, 56 - int); 55 + extern int __jfs_setxattr(tid_t, struct inode *, const char *, const void *, 56 + size_t, int); 57 57 extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t, 58 58 int); 59 59 extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t);
+42 -21
fs/jfs/namei.c
··· 39 39 static s64 commitZeroLink(tid_t, struct inode *); 40 40 41 41 /* 42 + * NAME: free_ea_wmap(inode) 43 + * 44 + * FUNCTION: free uncommitted extended attributes from working map 45 + * 46 + */ 47 + static inline void free_ea_wmap(struct inode *inode) 48 + { 49 + dxd_t *ea = &JFS_IP(inode)->ea; 50 + 51 + if (ea->flag & DXD_EXTENT) { 52 + /* free EA pages from cache */ 53 + invalidate_dxd_metapages(inode, *ea); 54 + dbFree(inode, addressDXD(ea), lengthDXD(ea)); 55 + } 56 + ea->flag = 0; 57 + } 58 + 59 + /* 42 60 * NAME: jfs_create(dip, dentry, mode) 43 61 * 44 62 * FUNCTION: create a regular file in the parent directory <dip> ··· 107 89 down(&JFS_IP(dip)->commit_sem); 108 90 down(&JFS_IP(ip)->commit_sem); 109 91 92 + rc = jfs_init_acl(tid, ip, dip); 93 + if (rc) 94 + goto out3; 95 + 110 96 if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) { 111 97 jfs_err("jfs_create: dtSearch returned %d", rc); 98 + txAbort(tid, 0); 112 99 goto out3; 113 100 } 114 101 ··· 162 139 up(&JFS_IP(dip)->commit_sem); 163 140 up(&JFS_IP(ip)->commit_sem); 164 141 if (rc) { 142 + free_ea_wmap(ip); 165 143 ip->i_nlink = 0; 166 144 iput(ip); 167 145 } else ··· 170 146 171 147 out2: 172 148 free_UCSname(&dname); 173 - 174 - #ifdef CONFIG_JFS_POSIX_ACL 175 - if (rc == 0) 176 - jfs_init_acl(ip, dip); 177 - #endif 178 149 179 150 out1: 180 151 ··· 235 216 down(&JFS_IP(dip)->commit_sem); 236 217 down(&JFS_IP(ip)->commit_sem); 237 218 219 + rc = jfs_init_acl(tid, ip, dip); 220 + if (rc) 221 + goto out3; 222 + 238 223 if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) { 239 224 jfs_err("jfs_mkdir: dtSearch returned %d", rc); 225 + txAbort(tid, 0); 240 226 goto out3; 241 227 } 242 228 ··· 291 267 up(&JFS_IP(dip)->commit_sem); 292 268 up(&JFS_IP(ip)->commit_sem); 293 269 if (rc) { 270 + free_ea_wmap(ip); 294 271 ip->i_nlink = 0; 295 272 iput(ip); 296 273 } else ··· 300 275 out2: 301 276 free_UCSname(&dname); 302 277 303 - #ifdef CONFIG_JFS_POSIX_ACL 304 - if (rc == 0) 305 - jfs_init_acl(ip, dip); 306 - #endif 307 278 308 279 out1: 309 280 ··· 1021 1000 up(&JFS_IP(dip)->commit_sem); 1022 1001 up(&JFS_IP(ip)->commit_sem); 1023 1002 if (rc) { 1003 + free_ea_wmap(ip); 1024 1004 ip->i_nlink = 0; 1025 1005 iput(ip); 1026 1006 } else ··· 1029 1007 1030 1008 out2: 1031 1009 free_UCSname(&dname); 1032 - 1033 - #ifdef CONFIG_JFS_POSIX_ACL 1034 - if (rc == 0) 1035 - jfs_init_acl(ip, dip); 1036 - #endif 1037 1010 1038 1011 out1: 1039 1012 jfs_info("jfs_symlink: rc:%d", rc); ··· 1345 1328 down(&JFS_IP(dir)->commit_sem); 1346 1329 down(&JFS_IP(ip)->commit_sem); 1347 1330 1348 - if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE))) 1331 + rc = jfs_init_acl(tid, ip, dir); 1332 + if (rc) 1349 1333 goto out3; 1334 + 1335 + if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE))) { 1336 + txAbort(tid, 0); 1337 + goto out3; 1338 + } 1350 1339 1351 1340 tblk = tid_to_tblock(tid); 1352 1341 tblk->xflag |= COMMIT_CREATE; ··· 1360 1337 tblk->u.ixpxd = JFS_IP(ip)->ixpxd; 1361 1338 1362 1339 ino = ip->i_ino; 1363 - if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack))) 1340 + if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack))) { 1341 + txAbort(tid, 0); 1364 1342 goto out3; 1343 + } 1365 1344 1366 1345 ip->i_op = &jfs_file_inode_operations; 1367 1346 jfs_ip->dev = new_encode_dev(rdev); ··· 1385 1360 up(&JFS_IP(ip)->commit_sem); 1386 1361 up(&JFS_IP(dir)->commit_sem); 1387 1362 if (rc) { 1363 + free_ea_wmap(ip); 1388 1364 ip->i_nlink = 0; 1389 1365 iput(ip); 1390 1366 } else ··· 1393 1367 1394 1368 out1: 1395 1369 free_UCSname(&dname); 1396 - 1397 - #ifdef CONFIG_JFS_POSIX_ACL 1398 - if (rc == 0) 1399 - jfs_init_acl(ip, dir); 1400 - #endif 1401 1370 1402 1371 out: 1403 1372 jfs_info("jfs_mknod: returning %d", rc);
+41 -17
fs/jfs/xattr.c
··· 633 633 } 634 634 } 635 635 636 - static int ea_put(struct inode *inode, struct ea_buffer *ea_buf, int new_size) 636 + static int ea_put(tid_t tid, struct inode *inode, struct ea_buffer *ea_buf, 637 + int new_size) 637 638 { 638 639 struct jfs_inode_info *ji = JFS_IP(inode); 639 640 unsigned long old_blocks, new_blocks; 640 641 int rc = 0; 641 - tid_t tid; 642 642 643 643 if (new_size == 0) { 644 644 ea_release(inode, ea_buf); ··· 663 663 } 664 664 if (rc) 665 665 return rc; 666 - 667 - tid = txBegin(inode->i_sb, 0); 668 - down(&ji->commit_sem); 669 666 670 667 old_blocks = new_blocks = 0; 671 668 ··· 692 695 DQUOT_FREE_BLOCK(inode, old_blocks); 693 696 694 697 inode->i_ctime = CURRENT_TIME; 695 - rc = txCommit(tid, 1, &inode, 0); 696 - txEnd(tid); 697 - up(&ji->commit_sem); 698 698 699 - return rc; 699 + return 0; 700 700 } 701 701 702 702 /* ··· 804 810 return permission(inode, MAY_WRITE, NULL); 805 811 } 806 812 807 - int __jfs_setxattr(struct inode *inode, const char *name, const void *value, 808 - size_t value_len, int flags) 813 + int __jfs_setxattr(tid_t tid, struct inode *inode, const char *name, 814 + const void *value, size_t value_len, int flags) 809 815 { 810 816 struct jfs_ea_list *ealist; 811 817 struct jfs_ea *ea, *old_ea = NULL, *next_ea = NULL; ··· 818 824 int found = 0; 819 825 int rc; 820 826 int length; 821 - 822 - if ((rc = can_set_xattr(inode, name, value, value_len))) 823 - return rc; 824 827 825 828 if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { 826 829 os2name = kmalloc(namelen - XATTR_OS2_PREFIX_LEN + 1, ··· 930 939 931 940 ealist->size = cpu_to_le32(new_size); 932 941 933 - rc = ea_put(inode, &ea_buf, new_size); 942 + rc = ea_put(tid, inode, &ea_buf, new_size); 934 943 935 944 goto out; 936 945 release: ··· 946 955 int jfs_setxattr(struct dentry *dentry, const char *name, const void *value, 947 956 size_t value_len, int flags) 948 957 { 958 + struct inode *inode = dentry->d_inode; 959 + struct jfs_inode_info *ji = JFS_IP(inode); 960 + int rc; 961 + tid_t tid; 962 + 963 + if ((rc = can_set_xattr(inode, name, value, value_len))) 964 + return rc; 965 + 949 966 if (value == NULL) { /* empty EA, do not remove */ 950 967 value = ""; 951 968 value_len = 0; 952 969 } 953 970 954 - return __jfs_setxattr(dentry->d_inode, name, value, value_len, flags); 971 + tid = txBegin(inode->i_sb, 0); 972 + down(&ji->commit_sem); 973 + rc = __jfs_setxattr(tid, dentry->d_inode, name, value, value_len, 974 + flags); 975 + if (!rc) 976 + rc = txCommit(tid, 1, &inode, 0); 977 + txEnd(tid); 978 + up(&ji->commit_sem); 979 + 980 + return rc; 955 981 } 956 982 957 983 static int can_get_xattr(struct inode *inode, const char *name) ··· 1130 1122 1131 1123 int jfs_removexattr(struct dentry *dentry, const char *name) 1132 1124 { 1133 - return __jfs_setxattr(dentry->d_inode, name, NULL, 0, XATTR_REPLACE); 1125 + struct inode *inode = dentry->d_inode; 1126 + struct jfs_inode_info *ji = JFS_IP(inode); 1127 + int rc; 1128 + tid_t tid; 1129 + 1130 + if ((rc = can_set_xattr(inode, name, NULL, 0))) 1131 + return rc; 1132 + 1133 + tid = txBegin(inode->i_sb, 0); 1134 + down(&ji->commit_sem); 1135 + rc = __jfs_setxattr(tid, dentry->d_inode, name, NULL, 0, XATTR_REPLACE); 1136 + if (!rc) 1137 + rc = txCommit(tid, 1, &inode, 0); 1138 + txEnd(tid); 1139 + up(&ji->commit_sem); 1140 + 1141 + return rc; 1134 1142 }