aboutsummaryrefslogtreecommitdiffstats
path: root/fs/reiserfs/xattr_acl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/reiserfs/xattr_acl.c')
-rw-r--r--fs/reiserfs/xattr_acl.c105
1 files changed, 81 insertions, 24 deletions
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index bfecf7553002..d423416d93d1 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -10,15 +10,17 @@
10#include <linux/reiserfs_acl.h> 10#include <linux/reiserfs_acl.h>
11#include <asm/uaccess.h> 11#include <asm/uaccess.h>
12 12
13static int reiserfs_set_acl(struct inode *inode, int type, 13static int reiserfs_set_acl(struct reiserfs_transaction_handle *th,
14 struct inode *inode, int type,
14 struct posix_acl *acl); 15 struct posix_acl *acl);
15 16
16static int 17static int
17xattr_set_acl(struct inode *inode, int type, const void *value, size_t size) 18xattr_set_acl(struct inode *inode, int type, const void *value, size_t size)
18{ 19{
19 struct posix_acl *acl; 20 struct posix_acl *acl;
20 int error; 21 int error, error2;
21 22 struct reiserfs_transaction_handle th;
23 size_t jcreate_blocks;
22 if (!reiserfs_posixacl(inode->i_sb)) 24 if (!reiserfs_posixacl(inode->i_sb))
23 return -EOPNOTSUPP; 25 return -EOPNOTSUPP;
24 if (!is_owner_or_cap(inode)) 26 if (!is_owner_or_cap(inode))
@@ -36,7 +38,21 @@ xattr_set_acl(struct inode *inode, int type, const void *value, size_t size)
36 } else 38 } else
37 acl = NULL; 39 acl = NULL;
38 40
39 error = reiserfs_set_acl(inode, type, acl); 41 /* Pessimism: We can't assume that anything from the xattr root up
42 * has been created. */
43
44 jcreate_blocks = reiserfs_xattr_jcreate_nblocks(inode) +
45 reiserfs_xattr_nblocks(inode, size) * 2;
46
47 reiserfs_write_lock(inode->i_sb);
48 error = journal_begin(&th, inode->i_sb, jcreate_blocks);
49 if (error == 0) {
50 error = reiserfs_set_acl(&th, inode, type, acl);
51 error2 = journal_end(&th, inode->i_sb, jcreate_blocks);
52 if (error2)
53 error = error2;
54 }
55 reiserfs_write_unlock(inode->i_sb);
40 56
41 release_and_out: 57 release_and_out:
42 posix_acl_release(acl); 58 posix_acl_release(acl);
@@ -266,7 +282,8 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type)
266 * BKL held [before 2.5.x] 282 * BKL held [before 2.5.x]
267 */ 283 */
268static int 284static int
269reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) 285reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
286 int type, struct posix_acl *acl)
270{ 287{
271 char *name; 288 char *name;
272 void *value = NULL; 289 void *value = NULL;
@@ -310,7 +327,7 @@ reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
310 return (int)PTR_ERR(value); 327 return (int)PTR_ERR(value);
311 } 328 }
312 329
313 error = __reiserfs_xattr_set(inode, name, value, size, 0); 330 error = reiserfs_xattr_set_handle(th, inode, name, value, size, 0);
314 331
315 /* 332 /*
316 * Ensure that the inode gets dirtied if we're only using 333 * Ensure that the inode gets dirtied if we're only using
@@ -337,7 +354,8 @@ reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
337/* dir->i_mutex: locked, 354/* dir->i_mutex: locked,
338 * inode is new and not released into the wild yet */ 355 * inode is new and not released into the wild yet */
339int 356int
340reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry, 357reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
358 struct inode *dir, struct dentry *dentry,
341 struct inode *inode) 359 struct inode *inode)
342{ 360{
343 struct posix_acl *acl; 361 struct posix_acl *acl;
@@ -374,7 +392,8 @@ reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry,
374 392
375 /* Copy the default ACL to the default ACL of a new directory */ 393 /* Copy the default ACL to the default ACL of a new directory */
376 if (S_ISDIR(inode->i_mode)) { 394 if (S_ISDIR(inode->i_mode)) {
377 err = reiserfs_set_acl(inode, ACL_TYPE_DEFAULT, acl); 395 err = reiserfs_set_acl(th, inode, ACL_TYPE_DEFAULT,
396 acl);
378 if (err) 397 if (err)
379 goto cleanup; 398 goto cleanup;
380 } 399 }
@@ -395,9 +414,9 @@ reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry,
395 414
396 /* If we need an ACL.. */ 415 /* If we need an ACL.. */
397 if (need_acl > 0) { 416 if (need_acl > 0) {
398 err = 417 err = reiserfs_set_acl(th, inode,
399 reiserfs_set_acl(inode, ACL_TYPE_ACCESS, 418 ACL_TYPE_ACCESS,
400 acl_copy); 419 acl_copy);
401 if (err) 420 if (err)
402 goto cleanup_copy; 421 goto cleanup_copy;
403 } 422 }
@@ -415,21 +434,45 @@ reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry,
415 return err; 434 return err;
416} 435}
417 436
418/* Looks up and caches the result of the default ACL. 437/* This is used to cache the default acl before a new object is created.
419 * We do this so that we don't need to carry the xattr_sem into 438 * The biggest reason for this is to get an idea of how many blocks will
420 * reiserfs_new_inode if we don't need to */ 439 * actually be required for the create operation if we must inherit an ACL.
440 * An ACL write can add up to 3 object creations and an additional file write
441 * so we'd prefer not to reserve that many blocks in the journal if we can.
442 * It also has the advantage of not loading the ACL with a transaction open,
443 * this may seem silly, but if the owner of the directory is doing the
444 * creation, the ACL may not be loaded since the permissions wouldn't require
445 * it.
446 * We return the number of blocks required for the transaction.
447 */
421int reiserfs_cache_default_acl(struct inode *inode) 448int reiserfs_cache_default_acl(struct inode *inode)
422{ 449{
423 int ret = 0; 450 struct posix_acl *acl;
424 if (reiserfs_posixacl(inode->i_sb) && !IS_PRIVATE(inode)) { 451 int nblocks = 0;
425 struct posix_acl *acl; 452
426 acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT); 453 if (IS_PRIVATE(inode))
427 ret = (acl && !IS_ERR(acl)); 454 return 0;
428 if (ret) 455
429 posix_acl_release(acl); 456 acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT);
457
458 if (acl && !IS_ERR(acl)) {
459 int size = reiserfs_acl_size(acl->a_count);
460
461 /* Other xattrs can be created during inode creation. We don't
462 * want to claim too many blocks, so we check to see if we
463 * we need to create the tree to the xattrs, and then we
464 * just want two files. */
465 nblocks = reiserfs_xattr_jcreate_nblocks(inode);
466 nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
467
468 REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
469
470 /* We need to account for writes + bitmaps for two files */
471 nblocks += reiserfs_xattr_nblocks(inode, size) * 4;
472 posix_acl_release(acl);
430 } 473 }
431 474
432 return ret; 475 return nblocks;
433} 476}
434 477
435int reiserfs_acl_chmod(struct inode *inode) 478int reiserfs_acl_chmod(struct inode *inode)
@@ -455,8 +498,22 @@ int reiserfs_acl_chmod(struct inode *inode)
455 if (!clone) 498 if (!clone)
456 return -ENOMEM; 499 return -ENOMEM;
457 error = posix_acl_chmod_masq(clone, inode->i_mode); 500 error = posix_acl_chmod_masq(clone, inode->i_mode);
458 if (!error) 501 if (!error) {
459 error = reiserfs_set_acl(inode, ACL_TYPE_ACCESS, clone); 502 struct reiserfs_transaction_handle th;
503 size_t size = reiserfs_xattr_nblocks(inode,
504 reiserfs_acl_size(clone->a_count));
505 reiserfs_write_lock(inode->i_sb);
506 error = journal_begin(&th, inode->i_sb, size * 2);
507 if (!error) {
508 int error2;
509 error = reiserfs_set_acl(&th, inode, ACL_TYPE_ACCESS,
510 clone);
511 error2 = journal_end(&th, inode->i_sb, size * 2);
512 if (error2)
513 error = error2;
514 }
515 reiserfs_write_unlock(inode->i_sb);
516 }
460 posix_acl_release(clone); 517 posix_acl_release(clone);
461 return error; 518 return error;
462} 519}