Commit 4f4b401bfaa97edbea41a1fcab794148e7ac0421
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
fs/jfs/acl.c
... | ... | @@ -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; |
fs/jfs/jfs_acl.h
... | ... | @@ -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 */ |
fs/jfs/jfs_xattr.h
... | ... | @@ -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); |
fs/jfs/namei.c
... | ... | @@ -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); |
fs/jfs/xattr.c
... | ... | @@ -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 | } |