Commit 4f4b401bfaa97edbea41a1fcab794148e7ac0421

Authored by Dave Kleikamp
1 parent b1b5d7f9b7

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

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

Showing 5 changed files with 112 additions and 49 deletions Side-by-side Diff

... ... @@ -23,6 +23,7 @@
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  
... ... @@ -75,7 +76,8 @@
75 76 return acl;
76 77 }
77 78  
78   -static int jfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
  79 +static int jfs_set_acl(tid_t tid, struct inode *inode, int type,
  80 + struct posix_acl *acl)
79 81 {
80 82 char *ea_name;
81 83 struct jfs_inode_info *ji = JFS_IP(inode);
... ... @@ -110,7 +112,7 @@
110 112 if (rc < 0)
111 113 goto out;
112 114 }
113   - rc = __jfs_setxattr(inode, ea_name, value, size, 0);
  115 + rc = __jfs_setxattr(tid, inode, ea_name, value, size, 0);
114 116 out:
115 117 kfree(value);
116 118  
... ... @@ -143,7 +145,7 @@
143 145 return generic_permission(inode, mask, jfs_check_acl);
144 146 }
145 147  
146   -int jfs_init_acl(struct inode *inode, struct inode *dir)
  148 +int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
147 149 {
148 150 struct posix_acl *acl = NULL;
149 151 struct posix_acl *clone;
... ... @@ -159,7 +161,7 @@
159 161  
160 162 if (acl) {
161 163 if (S_ISDIR(inode->i_mode)) {
162   - rc = jfs_set_acl(inode, ACL_TYPE_DEFAULT, acl);
  164 + rc = jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, acl);
163 165 if (rc)
164 166 goto cleanup;
165 167 }
... ... @@ -173,7 +175,8 @@
173 175 if (rc >= 0) {
174 176 inode->i_mode = mode;
175 177 if (rc > 0)
176   - rc = jfs_set_acl(inode, ACL_TYPE_ACCESS, clone);
  178 + rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS,
  179 + clone);
177 180 }
178 181 posix_acl_release(clone);
179 182 cleanup:
... ... @@ -202,8 +205,15 @@
202 205 return -ENOMEM;
203 206  
204 207 rc = posix_acl_chmod_masq(clone, inode->i_mode);
205   - if (!rc)
206   - rc = jfs_set_acl(inode, ACL_TYPE_ACCESS, clone);
  208 + if (!rc) {
  209 + tid_t tid = txBegin(inode->i_sb, 0);
  210 + down(&JFS_IP(inode)->commit_sem);
  211 + rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, clone);
  212 + if (!rc)
  213 + rc = txCommit(tid, 1, &inode, 0);
  214 + txEnd(tid);
  215 + up(&JFS_IP(inode)->commit_sem);
  216 + }
207 217  
208 218 posix_acl_release(clone);
209 219 return rc;
... ... @@ -21,9 +21,17 @@
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 */
... ... @@ -52,8 +52,8 @@
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);
... ... @@ -39,6 +39,24 @@
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>
45 63  
... ... @@ -89,8 +107,13 @@
89 107 down(&JFS_IP(dip)->commit_sem);
90 108 down(&JFS_IP(ip)->commit_sem);
91 109  
  110 + rc = jfs_init_acl(tid, ip, dip);
  111 + if (rc)
  112 + goto out3;
  113 +
92 114 if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) {
93 115 jfs_err("jfs_create: dtSearch returned %d", rc);
  116 + txAbort(tid, 0);
94 117 goto out3;
95 118 }
96 119  
... ... @@ -139,6 +162,7 @@
139 162 up(&JFS_IP(dip)->commit_sem);
140 163 up(&JFS_IP(ip)->commit_sem);
141 164 if (rc) {
  165 + free_ea_wmap(ip);
142 166 ip->i_nlink = 0;
143 167 iput(ip);
144 168 } else
... ... @@ -147,11 +171,6 @@
147 171 out2:
148 172 free_UCSname(&dname);
149 173  
150   -#ifdef CONFIG_JFS_POSIX_ACL
151   - if (rc == 0)
152   - jfs_init_acl(ip, dip);
153   -#endif
154   -
155 174 out1:
156 175  
157 176 jfs_info("jfs_create: rc:%d", rc);
158 177  
... ... @@ -216,8 +235,13 @@
216 235 down(&JFS_IP(dip)->commit_sem);
217 236 down(&JFS_IP(ip)->commit_sem);
218 237  
  238 + rc = jfs_init_acl(tid, ip, dip);
  239 + if (rc)
  240 + goto out3;
  241 +
219 242 if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) {
220 243 jfs_err("jfs_mkdir: dtSearch returned %d", rc);
  244 + txAbort(tid, 0);
221 245 goto out3;
222 246 }
223 247  
... ... @@ -267,6 +291,7 @@
267 291 up(&JFS_IP(dip)->commit_sem);
268 292 up(&JFS_IP(ip)->commit_sem);
269 293 if (rc) {
  294 + free_ea_wmap(ip);
270 295 ip->i_nlink = 0;
271 296 iput(ip);
272 297 } else
... ... @@ -275,10 +300,6 @@
275 300 out2:
276 301 free_UCSname(&dname);
277 302  
278   -#ifdef CONFIG_JFS_POSIX_ACL
279   - if (rc == 0)
280   - jfs_init_acl(ip, dip);
281   -#endif
282 303  
283 304 out1:
284 305  
... ... @@ -1000,6 +1021,7 @@
1000 1021 up(&JFS_IP(dip)->commit_sem);
1001 1022 up(&JFS_IP(ip)->commit_sem);
1002 1023 if (rc) {
  1024 + free_ea_wmap(ip);
1003 1025 ip->i_nlink = 0;
1004 1026 iput(ip);
1005 1027 } else
... ... @@ -1008,11 +1030,6 @@
1008 1030 out2:
1009 1031 free_UCSname(&dname);
1010 1032  
1011   -#ifdef CONFIG_JFS_POSIX_ACL
1012   - if (rc == 0)
1013   - jfs_init_acl(ip, dip);
1014   -#endif
1015   -
1016 1033 out1:
1017 1034 jfs_info("jfs_symlink: rc:%d", rc);
1018 1035 return rc;
1019 1036  
1020 1037  
1021 1038  
... ... @@ -1328,17 +1345,25 @@
1328 1345 down(&JFS_IP(dir)->commit_sem);
1329 1346 down(&JFS_IP(ip)->commit_sem);
1330 1347  
1331   - if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE)))
  1348 + rc = jfs_init_acl(tid, ip, dir);
  1349 + if (rc)
1332 1350 goto out3;
1333 1351  
  1352 + if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE))) {
  1353 + txAbort(tid, 0);
  1354 + goto out3;
  1355 + }
  1356 +
1334 1357 tblk = tid_to_tblock(tid);
1335 1358 tblk->xflag |= COMMIT_CREATE;
1336 1359 tblk->ino = ip->i_ino;
1337 1360 tblk->u.ixpxd = JFS_IP(ip)->ixpxd;
1338 1361  
1339 1362 ino = ip->i_ino;
1340   - if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack)))
  1363 + if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack))) {
  1364 + txAbort(tid, 0);
1341 1365 goto out3;
  1366 + }
1342 1367  
1343 1368 ip->i_op = &jfs_file_inode_operations;
1344 1369 jfs_ip->dev = new_encode_dev(rdev);
... ... @@ -1360,6 +1385,7 @@
1360 1385 up(&JFS_IP(ip)->commit_sem);
1361 1386 up(&JFS_IP(dir)->commit_sem);
1362 1387 if (rc) {
  1388 + free_ea_wmap(ip);
1363 1389 ip->i_nlink = 0;
1364 1390 iput(ip);
1365 1391 } else
... ... @@ -1367,11 +1393,6 @@
1367 1393  
1368 1394 out1:
1369 1395 free_UCSname(&dname);
1370   -
1371   -#ifdef CONFIG_JFS_POSIX_ACL
1372   - if (rc == 0)
1373   - jfs_init_acl(ip, dir);
1374   -#endif
1375 1396  
1376 1397 out:
1377 1398 jfs_info("jfs_mknod: returning %d", rc);
... ... @@ -633,12 +633,12 @@
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);
... ... @@ -664,9 +664,6 @@
664 664 if (rc)
665 665 return rc;
666 666  
667   - tid = txBegin(inode->i_sb, 0);
668   - down(&ji->commit_sem);
669   -
670 667 old_blocks = new_blocks = 0;
671 668  
672 669 if (ji->ea.flag & DXD_EXTENT) {
673 670  
... ... @@ -695,11 +692,8 @@
695 692 DQUOT_FREE_BLOCK(inode, old_blocks);
696 693  
697 694 inode->i_ctime = CURRENT_TIME;
698   - rc = txCommit(tid, 1, &inode, 0);
699   - txEnd(tid);
700   - up(&ji->commit_sem);
701 695  
702   - return rc;
  696 + return 0;
703 697 }
704 698  
705 699 /*
... ... @@ -810,8 +804,8 @@
810 804 return permission(inode, MAY_WRITE, NULL);
811 805 }
812 806  
813   -int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
814   - size_t value_len, int flags)
  807 +int __jfs_setxattr(tid_t tid, struct inode *inode, const char *name,
  808 + const void *value, size_t value_len, int flags)
815 809 {
816 810 struct jfs_ea_list *ealist;
817 811 struct jfs_ea *ea, *old_ea = NULL, *next_ea = NULL;
... ... @@ -825,9 +819,6 @@
825 819 int rc;
826 820 int length;
827 821  
828   - if ((rc = can_set_xattr(inode, name, value, value_len)))
829   - return rc;
830   -
831 822 if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
832 823 os2name = kmalloc(namelen - XATTR_OS2_PREFIX_LEN + 1,
833 824 GFP_KERNEL);
... ... @@ -939,7 +930,7 @@
939 930  
940 931 ealist->size = cpu_to_le32(new_size);
941 932  
942   - rc = ea_put(inode, &ea_buf, new_size);
  933 + rc = ea_put(tid, inode, &ea_buf, new_size);
943 934  
944 935 goto out;
945 936 release:
946 937  
... ... @@ -955,12 +946,29 @@
955 946 int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
956 947 size_t value_len, int flags)
957 948 {
  949 + struct inode *inode = dentry->d_inode;
  950 + struct jfs_inode_info *ji = JFS_IP(inode);
  951 + int rc;
  952 + tid_t tid;
  953 +
  954 + if ((rc = can_set_xattr(inode, name, value, value_len)))
  955 + return rc;
  956 +
958 957 if (value == NULL) { /* empty EA, do not remove */
959 958 value = "";
960 959 value_len = 0;
961 960 }
962 961  
963   - return __jfs_setxattr(dentry->d_inode, name, value, value_len, flags);
  962 + tid = txBegin(inode->i_sb, 0);
  963 + down(&ji->commit_sem);
  964 + rc = __jfs_setxattr(tid, dentry->d_inode, name, value, value_len,
  965 + flags);
  966 + if (!rc)
  967 + rc = txCommit(tid, 1, &inode, 0);
  968 + txEnd(tid);
  969 + up(&ji->commit_sem);
  970 +
  971 + return rc;
964 972 }
965 973  
966 974 static int can_get_xattr(struct inode *inode, const char *name)
... ... @@ -1122,6 +1130,22 @@
1122 1130  
1123 1131 int jfs_removexattr(struct dentry *dentry, const char *name)
1124 1132 {
1125   - return __jfs_setxattr(dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
  1133 + struct inode *inode = dentry->d_inode;
  1134 + struct jfs_inode_info *ji = JFS_IP(inode);
  1135 + int rc;
  1136 + tid_t tid;
  1137 +
  1138 + if ((rc = can_set_xattr(inode, name, NULL, 0)))
  1139 + return rc;
  1140 +
  1141 + tid = txBegin(inode->i_sb, 0);
  1142 + down(&ji->commit_sem);
  1143 + rc = __jfs_setxattr(tid, dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
  1144 + if (!rc)
  1145 + rc = txCommit(tid, 1, &inode, 0);
  1146 + txEnd(tid);
  1147 + up(&ji->commit_sem);
  1148 +
  1149 + return rc;
1126 1150 }