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.c257
1 files changed, 142 insertions, 115 deletions
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index b7e4fa4539de..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);
@@ -172,6 +188,29 @@ static void *posix_acl_to_disk(const struct posix_acl *acl, size_t * size)
172 return ERR_PTR(-EINVAL); 188 return ERR_PTR(-EINVAL);
173} 189}
174 190
191static inline void iset_acl(struct inode *inode, struct posix_acl **i_acl,
192 struct posix_acl *acl)
193{
194 spin_lock(&inode->i_lock);
195 if (*i_acl != ERR_PTR(-ENODATA))
196 posix_acl_release(*i_acl);
197 *i_acl = posix_acl_dup(acl);
198 spin_unlock(&inode->i_lock);
199}
200
201static inline struct posix_acl *iget_acl(struct inode *inode,
202 struct posix_acl **i_acl)
203{
204 struct posix_acl *acl = ERR_PTR(-ENODATA);
205
206 spin_lock(&inode->i_lock);
207 if (*i_acl != ERR_PTR(-ENODATA))
208 acl = posix_acl_dup(*i_acl);
209 spin_unlock(&inode->i_lock);
210
211 return acl;
212}
213
175/* 214/*
176 * Inode operation get_posix_acl(). 215 * Inode operation get_posix_acl().
177 * 216 *
@@ -199,11 +238,11 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type)
199 return ERR_PTR(-EINVAL); 238 return ERR_PTR(-EINVAL);
200 } 239 }
201 240
202 if (IS_ERR(*p_acl)) { 241 acl = iget_acl(inode, p_acl);
203 if (PTR_ERR(*p_acl) == -ENODATA) 242 if (acl && !IS_ERR(acl))
204 return NULL; 243 return acl;
205 } else if (*p_acl != NULL) 244 else if (PTR_ERR(acl) == -ENODATA)
206 return posix_acl_dup(*p_acl); 245 return NULL;
207 246
208 size = reiserfs_xattr_get(inode, name, NULL, 0); 247 size = reiserfs_xattr_get(inode, name, NULL, 0);
209 if (size < 0) { 248 if (size < 0) {
@@ -229,7 +268,7 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type)
229 } else { 268 } else {
230 acl = posix_acl_from_disk(value, retval); 269 acl = posix_acl_from_disk(value, retval);
231 if (!IS_ERR(acl)) 270 if (!IS_ERR(acl))
232 *p_acl = posix_acl_dup(acl); 271 iset_acl(inode, p_acl, acl);
233 } 272 }
234 273
235 kfree(value); 274 kfree(value);
@@ -243,12 +282,13 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type)
243 * BKL held [before 2.5.x] 282 * BKL held [before 2.5.x]
244 */ 283 */
245static int 284static int
246reiserfs_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)
247{ 287{
248 char *name; 288 char *name;
249 void *value = NULL; 289 void *value = NULL;
250 struct posix_acl **p_acl; 290 struct posix_acl **p_acl;
251 size_t size; 291 size_t size = 0;
252 int error; 292 int error;
253 struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode); 293 struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode);
254 294
@@ -285,31 +325,28 @@ reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
285 value = posix_acl_to_disk(acl, &size); 325 value = posix_acl_to_disk(acl, &size);
286 if (IS_ERR(value)) 326 if (IS_ERR(value))
287 return (int)PTR_ERR(value); 327 return (int)PTR_ERR(value);
288 error = reiserfs_xattr_set(inode, name, value, size, 0); 328 }
289 } else { 329
290 error = reiserfs_xattr_del(inode, name); 330 error = reiserfs_xattr_set_handle(th, inode, name, value, size, 0);
291 if (error == -ENODATA) { 331
292 /* This may seem odd here, but it means that the ACL was set 332 /*
293 * with a value representable with mode bits. If there was 333 * Ensure that the inode gets dirtied if we're only using
294 * an ACL before, reiserfs_xattr_del already dirtied the inode. 334 * the mode bits and an old ACL didn't exist. We don't need
295 */ 335 * to check if the inode is hashed here since we won't get
336 * called by reiserfs_inherit_default_acl().
337 */
338 if (error == -ENODATA) {
339 error = 0;
340 if (type == ACL_TYPE_ACCESS) {
341 inode->i_ctime = CURRENT_TIME_SEC;
296 mark_inode_dirty(inode); 342 mark_inode_dirty(inode);
297 error = 0;
298 } 343 }
299 } 344 }
300 345
301 kfree(value); 346 kfree(value);
302 347
303 if (!error) { 348 if (!error)
304 /* Release the old one */ 349 iset_acl(inode, p_acl, acl);
305 if (!IS_ERR(*p_acl) && *p_acl)
306 posix_acl_release(*p_acl);
307
308 if (acl == NULL)
309 *p_acl = ERR_PTR(-ENODATA);
310 else
311 *p_acl = posix_acl_dup(acl);
312 }
313 350
314 return error; 351 return error;
315} 352}
@@ -317,7 +354,8 @@ reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
317/* dir->i_mutex: locked, 354/* dir->i_mutex: locked,
318 * inode is new and not released into the wild yet */ 355 * inode is new and not released into the wild yet */
319int 356int
320reiserfs_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,
321 struct inode *inode) 359 struct inode *inode)
322{ 360{
323 struct posix_acl *acl; 361 struct posix_acl *acl;
@@ -335,8 +373,8 @@ reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry,
335 /* Don't apply ACLs to objects in the .reiserfs_priv tree.. This 373 /* Don't apply ACLs to objects in the .reiserfs_priv tree.. This
336 * would be useless since permissions are ignored, and a pain because 374 * would be useless since permissions are ignored, and a pain because
337 * it introduces locking cycles */ 375 * it introduces locking cycles */
338 if (is_reiserfs_priv_object(dir)) { 376 if (IS_PRIVATE(dir)) {
339 reiserfs_mark_inode_private(inode); 377 inode->i_flags |= S_PRIVATE;
340 goto apply_umask; 378 goto apply_umask;
341 } 379 }
342 380
@@ -354,7 +392,8 @@ reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry,
354 392
355 /* 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 */
356 if (S_ISDIR(inode->i_mode)) { 394 if (S_ISDIR(inode->i_mode)) {
357 err = reiserfs_set_acl(inode, ACL_TYPE_DEFAULT, acl); 395 err = reiserfs_set_acl(th, inode, ACL_TYPE_DEFAULT,
396 acl);
358 if (err) 397 if (err)
359 goto cleanup; 398 goto cleanup;
360 } 399 }
@@ -375,9 +414,9 @@ reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry,
375 414
376 /* If we need an ACL.. */ 415 /* If we need an ACL.. */
377 if (need_acl > 0) { 416 if (need_acl > 0) {
378 err = 417 err = reiserfs_set_acl(th, inode,
379 reiserfs_set_acl(inode, ACL_TYPE_ACCESS, 418 ACL_TYPE_ACCESS,
380 acl_copy); 419 acl_copy);
381 if (err) 420 if (err)
382 goto cleanup_copy; 421 goto cleanup_copy;
383 } 422 }
@@ -395,25 +434,45 @@ reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry,
395 return err; 434 return err;
396} 435}
397 436
398/* 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.
399 * 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
400 * 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 */
401int reiserfs_cache_default_acl(struct inode *inode) 448int reiserfs_cache_default_acl(struct inode *inode)
402{ 449{
403 int ret = 0; 450 struct posix_acl *acl;
404 if (reiserfs_posixacl(inode->i_sb) && !is_reiserfs_priv_object(inode)) { 451 int nblocks = 0;
405 struct posix_acl *acl; 452
406 reiserfs_read_lock_xattr_i(inode); 453 if (IS_PRIVATE(inode))
407 reiserfs_read_lock_xattrs(inode->i_sb); 454 return 0;
408 acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT); 455
409 reiserfs_read_unlock_xattrs(inode->i_sb); 456 acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT);
410 reiserfs_read_unlock_xattr_i(inode); 457
411 ret = (acl && !IS_ERR(acl)); 458 if (acl && !IS_ERR(acl)) {
412 if (ret) 459 int size = reiserfs_acl_size(acl->a_count);
413 posix_acl_release(acl); 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);
414 } 473 }
415 474
416 return ret; 475 return nblocks;
417} 476}
418 477
419int reiserfs_acl_chmod(struct inode *inode) 478int reiserfs_acl_chmod(struct inode *inode)
@@ -429,9 +488,7 @@ int reiserfs_acl_chmod(struct inode *inode)
429 return 0; 488 return 0;
430 } 489 }
431 490
432 reiserfs_read_lock_xattrs(inode->i_sb);
433 acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); 491 acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
434 reiserfs_read_unlock_xattrs(inode->i_sb);
435 if (!acl) 492 if (!acl)
436 return 0; 493 return 0;
437 if (IS_ERR(acl)) 494 if (IS_ERR(acl))
@@ -442,18 +499,20 @@ int reiserfs_acl_chmod(struct inode *inode)
442 return -ENOMEM; 499 return -ENOMEM;
443 error = posix_acl_chmod_masq(clone, inode->i_mode); 500 error = posix_acl_chmod_masq(clone, inode->i_mode);
444 if (!error) { 501 if (!error) {
445 int lock = !has_xattr_dir(inode); 502 struct reiserfs_transaction_handle th;
446 reiserfs_write_lock_xattr_i(inode); 503 size_t size = reiserfs_xattr_nblocks(inode,
447 if (lock) 504 reiserfs_acl_size(clone->a_count));
448 reiserfs_write_lock_xattrs(inode->i_sb); 505 reiserfs_write_lock(inode->i_sb);
449 else 506 error = journal_begin(&th, inode->i_sb, size * 2);
450 reiserfs_read_lock_xattrs(inode->i_sb); 507 if (!error) {
451 error = reiserfs_set_acl(inode, ACL_TYPE_ACCESS, clone); 508 int error2;
452 if (lock) 509 error = reiserfs_set_acl(&th, inode, ACL_TYPE_ACCESS,
453 reiserfs_write_unlock_xattrs(inode->i_sb); 510 clone);
454 else 511 error2 = journal_end(&th, inode->i_sb, size * 2);
455 reiserfs_read_unlock_xattrs(inode->i_sb); 512 if (error2)
456 reiserfs_write_unlock_xattr_i(inode); 513 error = error2;
514 }
515 reiserfs_write_unlock(inode->i_sb);
457 } 516 }
458 posix_acl_release(clone); 517 posix_acl_release(clone);
459 return error; 518 return error;
@@ -477,38 +536,22 @@ posix_acl_access_set(struct inode *inode, const char *name,
477 return xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size); 536 return xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
478} 537}
479 538
480static int posix_acl_access_del(struct inode *inode, const char *name) 539static size_t posix_acl_access_list(struct inode *inode, char *list,
540 size_t list_size, const char *name,
541 size_t name_len)
481{ 542{
482 struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode); 543 const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
483 struct posix_acl **acl = &reiserfs_i->i_acl_access;
484 if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS) - 1)
485 return -EINVAL;
486 if (!IS_ERR(*acl) && *acl) {
487 posix_acl_release(*acl);
488 *acl = ERR_PTR(-ENODATA);
489 }
490
491 return 0;
492}
493
494static int
495posix_acl_access_list(struct inode *inode, const char *name, int namelen,
496 char *out)
497{
498 int len = namelen;
499 if (!reiserfs_posixacl(inode->i_sb)) 544 if (!reiserfs_posixacl(inode->i_sb))
500 return 0; 545 return 0;
501 if (out) 546 if (list && size <= list_size)
502 memcpy(out, name, len); 547 memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
503 548 return size;
504 return len;
505} 549}
506 550
507struct reiserfs_xattr_handler posix_acl_access_handler = { 551struct xattr_handler reiserfs_posix_acl_access_handler = {
508 .prefix = POSIX_ACL_XATTR_ACCESS, 552 .prefix = POSIX_ACL_XATTR_ACCESS,
509 .get = posix_acl_access_get, 553 .get = posix_acl_access_get,
510 .set = posix_acl_access_set, 554 .set = posix_acl_access_set,
511 .del = posix_acl_access_del,
512 .list = posix_acl_access_list, 555 .list = posix_acl_access_list,
513}; 556};
514 557
@@ -530,37 +573,21 @@ posix_acl_default_set(struct inode *inode, const char *name,
530 return xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size); 573 return xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
531} 574}
532 575
533static int posix_acl_default_del(struct inode *inode, const char *name) 576static size_t posix_acl_default_list(struct inode *inode, char *list,
577 size_t list_size, const char *name,
578 size_t name_len)
534{ 579{
535 struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode); 580 const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
536 struct posix_acl **acl = &reiserfs_i->i_acl_default;
537 if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT) - 1)
538 return -EINVAL;
539 if (!IS_ERR(*acl) && *acl) {
540 posix_acl_release(*acl);
541 *acl = ERR_PTR(-ENODATA);
542 }
543
544 return 0;
545}
546
547static int
548posix_acl_default_list(struct inode *inode, const char *name, int namelen,
549 char *out)
550{
551 int len = namelen;
552 if (!reiserfs_posixacl(inode->i_sb)) 581 if (!reiserfs_posixacl(inode->i_sb))
553 return 0; 582 return 0;
554 if (out) 583 if (list && size <= list_size)
555 memcpy(out, name, len); 584 memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
556 585 return size;
557 return len;
558} 586}
559 587
560struct reiserfs_xattr_handler posix_acl_default_handler = { 588struct xattr_handler reiserfs_posix_acl_default_handler = {
561 .prefix = POSIX_ACL_XATTR_DEFAULT, 589 .prefix = POSIX_ACL_XATTR_DEFAULT,
562 .get = posix_acl_default_get, 590 .get = posix_acl_default_get,
563 .set = posix_acl_default_set, 591 .set = posix_acl_default_set,
564 .del = posix_acl_default_del,
565 .list = posix_acl_default_list, 592 .list = posix_acl_default_list,
566}; 593};