aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jfs
diff options
context:
space:
mode:
authorDave Kleikamp <shaggy@austin.ibm.com>2005-09-01 10:02:43 -0400
committerDave Kleikamp <shaggy@austin.ibm.com>2005-09-01 10:02:43 -0400
commit4f4b401bfaa97edbea41a1fcab794148e7ac0421 (patch)
treed58dcf9d90e15364398a3a4584f2892439295b64 /fs/jfs
parentb1b5d7f9b7ac6a8e3452ac43a53eebf69fdf5a77 (diff)
JFS: allow extended attributes to be set within a existing transaction
Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
Diffstat (limited to 'fs/jfs')
-rw-r--r--fs/jfs/acl.c24
-rw-r--r--fs/jfs/jfs_acl.h12
-rw-r--r--fs/jfs/jfs_xattr.h4
-rw-r--r--fs/jfs/namei.c63
-rw-r--r--fs/jfs/xattr.c58
5 files changed, 112 insertions, 49 deletions
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c
index e892dab40c26..461e4934ca7c 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -23,6 +23,7 @@
23#include <linux/quotaops.h> 23#include <linux/quotaops.h>
24#include <linux/posix_acl_xattr.h> 24#include <linux/posix_acl_xattr.h>
25#include "jfs_incore.h" 25#include "jfs_incore.h"
26#include "jfs_txnmgr.h"
26#include "jfs_xattr.h" 27#include "jfs_xattr.h"
27#include "jfs_acl.h" 28#include "jfs_acl.h"
28 29
@@ -75,7 +76,8 @@ static struct posix_acl *jfs_get_acl(struct inode *inode, int type)
75 return acl; 76 return acl;
76} 77}
77 78
78static int jfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) 79static int jfs_set_acl(tid_t tid, struct inode *inode, int type,
80 struct posix_acl *acl)
79{ 81{
80 char *ea_name; 82 char *ea_name;
81 struct jfs_inode_info *ji = JFS_IP(inode); 83 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)
110 if (rc < 0) 112 if (rc < 0)
111 goto out; 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);
114out: 116out:
115 kfree(value); 117 kfree(value);
116 118
@@ -143,7 +145,7 @@ int jfs_permission(struct inode *inode, int mask, struct nameidata *nd)
143 return generic_permission(inode, mask, jfs_check_acl); 145 return generic_permission(inode, mask, jfs_check_acl);
144} 146}
145 147
146int jfs_init_acl(struct inode *inode, struct inode *dir) 148int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
147{ 149{
148 struct posix_acl *acl = NULL; 150 struct posix_acl *acl = NULL;
149 struct posix_acl *clone; 151 struct posix_acl *clone;
@@ -159,7 +161,7 @@ int jfs_init_acl(struct inode *inode, struct inode *dir)
159 161
160 if (acl) { 162 if (acl) {
161 if (S_ISDIR(inode->i_mode)) { 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 if (rc) 165 if (rc)
164 goto cleanup; 166 goto cleanup;
165 } 167 }
@@ -173,7 +175,8 @@ int jfs_init_acl(struct inode *inode, struct inode *dir)
173 if (rc >= 0) { 175 if (rc >= 0) {
174 inode->i_mode = mode; 176 inode->i_mode = mode;
175 if (rc > 0) 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 posix_acl_release(clone); 181 posix_acl_release(clone);
179cleanup: 182cleanup:
@@ -202,8 +205,15 @@ static int jfs_acl_chmod(struct inode *inode)
202 return -ENOMEM; 205 return -ENOMEM;
203 206
204 rc = posix_acl_chmod_masq(clone, inode->i_mode); 207 rc = posix_acl_chmod_masq(clone, inode->i_mode);
205 if (!rc) 208 if (!rc) {
206 rc = jfs_set_acl(inode, ACL_TYPE_ACCESS, clone); 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 posix_acl_release(clone); 218 posix_acl_release(clone);
209 return rc; 219 return rc;
diff --git a/fs/jfs/jfs_acl.h b/fs/jfs/jfs_acl.h
index a3acd3eec059..a76293767c73 100644
--- a/fs/jfs/jfs_acl.h
+++ b/fs/jfs/jfs_acl.h
@@ -21,8 +21,16 @@
21#ifdef CONFIG_JFS_POSIX_ACL 21#ifdef CONFIG_JFS_POSIX_ACL
22 22
23int jfs_permission(struct inode *, int, struct nameidata *); 23int jfs_permission(struct inode *, int, struct nameidata *);
24int jfs_init_acl(struct inode *, struct inode *); 24int jfs_init_acl(tid_t, struct inode *, struct inode *);
25int jfs_setattr(struct dentry *, struct iattr *); 25int jfs_setattr(struct dentry *, struct iattr *);
26 26
27#endif /* CONFIG_JFS_POSIX_ACL */ 27#else
28
29static inline int jfs_init_acl(tid_t tid, struct inode *inode,
30 struct inode *dir)
31{
32 return 0;
33}
34
35#endif
28#endif /* _H_JFS_ACL */ 36#endif /* _H_JFS_ACL */
diff --git a/fs/jfs/jfs_xattr.h b/fs/jfs/jfs_xattr.h
index a1052f3f0bee..116a73ce3076 100644
--- a/fs/jfs/jfs_xattr.h
+++ b/fs/jfs/jfs_xattr.h
@@ -52,8 +52,8 @@ struct jfs_ea_list {
52#define END_EALIST(ealist) \ 52#define END_EALIST(ealist) \
53 ((struct jfs_ea *) (((char *) (ealist)) + EALIST_SIZE(ealist))) 53 ((struct jfs_ea *) (((char *) (ealist)) + EALIST_SIZE(ealist)))
54 54
55extern int __jfs_setxattr(struct inode *, const char *, const void *, size_t, 55extern int __jfs_setxattr(tid_t, struct inode *, const char *, const void *,
56 int); 56 size_t, int);
57extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t, 57extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t,
58 int); 58 int);
59extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t); 59extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t);
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 49ccde3937f9..f23f9c2aa525 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -39,6 +39,24 @@ struct dentry_operations jfs_ci_dentry_operations;
39static s64 commitZeroLink(tid_t, struct inode *); 39static 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 */
47static 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 * NAME: jfs_create(dip, dentry, mode) 60 * NAME: jfs_create(dip, dentry, mode)
43 * 61 *
44 * FUNCTION: create a regular file in the parent directory <dip> 62 * 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,
89 down(&JFS_IP(dip)->commit_sem); 107 down(&JFS_IP(dip)->commit_sem);
90 down(&JFS_IP(ip)->commit_sem); 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 if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) { 114 if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) {
93 jfs_err("jfs_create: dtSearch returned %d", rc); 115 jfs_err("jfs_create: dtSearch returned %d", rc);
116 txAbort(tid, 0);
94 goto out3; 117 goto out3;
95 } 118 }
96 119
@@ -139,6 +162,7 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
139 up(&JFS_IP(dip)->commit_sem); 162 up(&JFS_IP(dip)->commit_sem);
140 up(&JFS_IP(ip)->commit_sem); 163 up(&JFS_IP(ip)->commit_sem);
141 if (rc) { 164 if (rc) {
165 free_ea_wmap(ip);
142 ip->i_nlink = 0; 166 ip->i_nlink = 0;
143 iput(ip); 167 iput(ip);
144 } else 168 } else
@@ -147,11 +171,6 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
147 out2: 171 out2:
148 free_UCSname(&dname); 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 out1: 174 out1:
156 175
157 jfs_info("jfs_create: rc:%d", rc); 176 jfs_info("jfs_create: rc:%d", rc);
@@ -216,8 +235,13 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
216 down(&JFS_IP(dip)->commit_sem); 235 down(&JFS_IP(dip)->commit_sem);
217 down(&JFS_IP(ip)->commit_sem); 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 if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) { 242 if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) {
220 jfs_err("jfs_mkdir: dtSearch returned %d", rc); 243 jfs_err("jfs_mkdir: dtSearch returned %d", rc);
244 txAbort(tid, 0);
221 goto out3; 245 goto out3;
222 } 246 }
223 247
@@ -267,6 +291,7 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
267 up(&JFS_IP(dip)->commit_sem); 291 up(&JFS_IP(dip)->commit_sem);
268 up(&JFS_IP(ip)->commit_sem); 292 up(&JFS_IP(ip)->commit_sem);
269 if (rc) { 293 if (rc) {
294 free_ea_wmap(ip);
270 ip->i_nlink = 0; 295 ip->i_nlink = 0;
271 iput(ip); 296 iput(ip);
272 } else 297 } else
@@ -275,10 +300,6 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
275 out2: 300 out2:
276 free_UCSname(&dname); 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 out1: 304 out1:
284 305
@@ -1000,6 +1021,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
1000 up(&JFS_IP(dip)->commit_sem); 1021 up(&JFS_IP(dip)->commit_sem);
1001 up(&JFS_IP(ip)->commit_sem); 1022 up(&JFS_IP(ip)->commit_sem);
1002 if (rc) { 1023 if (rc) {
1024 free_ea_wmap(ip);
1003 ip->i_nlink = 0; 1025 ip->i_nlink = 0;
1004 iput(ip); 1026 iput(ip);
1005 } else 1027 } else
@@ -1008,11 +1030,6 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
1008 out2: 1030 out2:
1009 free_UCSname(&dname); 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 out1: 1033 out1:
1017 jfs_info("jfs_symlink: rc:%d", rc); 1034 jfs_info("jfs_symlink: rc:%d", rc);
1018 return rc; 1035 return rc;
@@ -1328,17 +1345,25 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
1328 down(&JFS_IP(dir)->commit_sem); 1345 down(&JFS_IP(dir)->commit_sem);
1329 down(&JFS_IP(ip)->commit_sem); 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 goto out3; 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 tblk = tid_to_tblock(tid); 1357 tblk = tid_to_tblock(tid);
1335 tblk->xflag |= COMMIT_CREATE; 1358 tblk->xflag |= COMMIT_CREATE;
1336 tblk->ino = ip->i_ino; 1359 tblk->ino = ip->i_ino;
1337 tblk->u.ixpxd = JFS_IP(ip)->ixpxd; 1360 tblk->u.ixpxd = JFS_IP(ip)->ixpxd;
1338 1361
1339 ino = ip->i_ino; 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 goto out3; 1365 goto out3;
1366 }
1342 1367
1343 ip->i_op = &jfs_file_inode_operations; 1368 ip->i_op = &jfs_file_inode_operations;
1344 jfs_ip->dev = new_encode_dev(rdev); 1369 jfs_ip->dev = new_encode_dev(rdev);
@@ -1360,6 +1385,7 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
1360 up(&JFS_IP(ip)->commit_sem); 1385 up(&JFS_IP(ip)->commit_sem);
1361 up(&JFS_IP(dir)->commit_sem); 1386 up(&JFS_IP(dir)->commit_sem);
1362 if (rc) { 1387 if (rc) {
1388 free_ea_wmap(ip);
1363 ip->i_nlink = 0; 1389 ip->i_nlink = 0;
1364 iput(ip); 1390 iput(ip);
1365 } else 1391 } else
@@ -1368,11 +1394,6 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
1368 out1: 1394 out1:
1369 free_UCSname(&dname); 1395 free_UCSname(&dname);
1370 1396
1371#ifdef CONFIG_JFS_POSIX_ACL
1372 if (rc == 0)
1373 jfs_init_acl(ip, dir);
1374#endif
1375
1376 out: 1397 out:
1377 jfs_info("jfs_mknod: returning %d", rc); 1398 jfs_info("jfs_mknod: returning %d", rc);
1378 return rc; 1399 return rc;
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index 554ec739e49b..35674b2a0e6c 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)
633 } 633 }
634} 634}
635 635
636static int ea_put(struct inode *inode, struct ea_buffer *ea_buf, int new_size) 636static int ea_put(tid_t tid, struct inode *inode, struct ea_buffer *ea_buf,
637 int new_size)
637{ 638{
638 struct jfs_inode_info *ji = JFS_IP(inode); 639 struct jfs_inode_info *ji = JFS_IP(inode);
639 unsigned long old_blocks, new_blocks; 640 unsigned long old_blocks, new_blocks;
640 int rc = 0; 641 int rc = 0;
641 tid_t tid;
642 642
643 if (new_size == 0) { 643 if (new_size == 0) {
644 ea_release(inode, ea_buf); 644 ea_release(inode, ea_buf);
@@ -664,9 +664,6 @@ static int ea_put(struct inode *inode, struct ea_buffer *ea_buf, int new_size)
664 if (rc) 664 if (rc)
665 return rc; 665 return rc;
666 666
667 tid = txBegin(inode->i_sb, 0);
668 down(&ji->commit_sem);
669
670 old_blocks = new_blocks = 0; 667 old_blocks = new_blocks = 0;
671 668
672 if (ji->ea.flag & DXD_EXTENT) { 669 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)
695 DQUOT_FREE_BLOCK(inode, old_blocks); 692 DQUOT_FREE_BLOCK(inode, old_blocks);
696 693
697 inode->i_ctime = CURRENT_TIME; 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 @@ static int can_set_xattr(struct inode *inode, const char *name,
810 return permission(inode, MAY_WRITE, NULL); 804 return permission(inode, MAY_WRITE, NULL);
811} 805}
812 806
813int __jfs_setxattr(struct inode *inode, const char *name, const void *value, 807int __jfs_setxattr(tid_t tid, struct inode *inode, const char *name,
814 size_t value_len, int flags) 808 const void *value, size_t value_len, int flags)
815{ 809{
816 struct jfs_ea_list *ealist; 810 struct jfs_ea_list *ealist;
817 struct jfs_ea *ea, *old_ea = NULL, *next_ea = NULL; 811 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,
825 int rc; 819 int rc;
826 int length; 820 int length;
827 821
828 if ((rc = can_set_xattr(inode, name, value, value_len)))
829 return rc;
830
831 if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { 822 if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
832 os2name = kmalloc(namelen - XATTR_OS2_PREFIX_LEN + 1, 823 os2name = kmalloc(namelen - XATTR_OS2_PREFIX_LEN + 1,
833 GFP_KERNEL); 824 GFP_KERNEL);
@@ -939,7 +930,7 @@ int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
939 930
940 ealist->size = cpu_to_le32(new_size); 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 goto out; 935 goto out;
945 release: 936 release:
@@ -955,12 +946,29 @@ int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
955int jfs_setxattr(struct dentry *dentry, const char *name, const void *value, 946int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
956 size_t value_len, int flags) 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 if (value == NULL) { /* empty EA, do not remove */ 957 if (value == NULL) { /* empty EA, do not remove */
959 value = ""; 958 value = "";
960 value_len = 0; 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
966static int can_get_xattr(struct inode *inode, const char *name) 974static 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)
1122 1130
1123int jfs_removexattr(struct dentry *dentry, const char *name) 1131int 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}