diff options
-rw-r--r-- | fs/reiserfs/Makefile | 4 | ||||
-rw-r--r-- | fs/reiserfs/xattr.c | 689 | ||||
-rw-r--r-- | include/linux/reiserfs_fs_sb.h | 2 | ||||
-rw-r--r-- | include/linux/reiserfs_xattr.h | 29 |
4 files changed, 367 insertions, 357 deletions
diff --git a/fs/reiserfs/Makefile b/fs/reiserfs/Makefile index 0eb7ac080484..7c5ab6330dd6 100644 --- a/fs/reiserfs/Makefile +++ b/fs/reiserfs/Makefile | |||
@@ -7,10 +7,10 @@ obj-$(CONFIG_REISERFS_FS) += reiserfs.o | |||
7 | reiserfs-objs := bitmap.o do_balan.o namei.o inode.o file.o dir.o fix_node.o \ | 7 | reiserfs-objs := bitmap.o do_balan.o namei.o inode.o file.o dir.o fix_node.o \ |
8 | super.o prints.o objectid.o lbalance.o ibalance.o stree.o \ | 8 | super.o prints.o objectid.o lbalance.o ibalance.o stree.o \ |
9 | hashes.o tail_conversion.o journal.o resize.o \ | 9 | hashes.o tail_conversion.o journal.o resize.o \ |
10 | item_ops.o ioctl.o procfs.o | 10 | item_ops.o ioctl.o procfs.o xattr.o |
11 | 11 | ||
12 | ifeq ($(CONFIG_REISERFS_FS_XATTR),y) | 12 | ifeq ($(CONFIG_REISERFS_FS_XATTR),y) |
13 | reiserfs-objs += xattr.o xattr_user.o xattr_trusted.o | 13 | reiserfs-objs += xattr_user.o xattr_trusted.o |
14 | endif | 14 | endif |
15 | 15 | ||
16 | ifeq ($(CONFIG_REISERFS_FS_SECURITY),y) | 16 | ifeq ($(CONFIG_REISERFS_FS_SECURITY),y) |
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index c5fc207e529c..f9bcdd5750f7 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
@@ -50,9 +50,6 @@ | |||
50 | #define PRIVROOT_NAME ".reiserfs_priv" | 50 | #define PRIVROOT_NAME ".reiserfs_priv" |
51 | #define XAROOT_NAME "xattrs" | 51 | #define XAROOT_NAME "xattrs" |
52 | 52 | ||
53 | static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char | ||
54 | *prefix); | ||
55 | |||
56 | /* Returns the dentry referring to the root of the extended attribute | 53 | /* Returns the dentry referring to the root of the extended attribute |
57 | * directory tree. If it has already been retrieved, it is used. If it | 54 | * directory tree. If it has already been retrieved, it is used. If it |
58 | * hasn't been created and the flags indicate creation is allowed, we | 55 | * hasn't been created and the flags indicate creation is allowed, we |
@@ -143,60 +140,6 @@ static struct dentry *open_xa_dir(const struct inode *inode, int flags) | |||
143 | return xadir; | 140 | return xadir; |
144 | } | 141 | } |
145 | 142 | ||
146 | /* Returns a dentry corresponding to a specific extended attribute file | ||
147 | * for the inode. If flags allow, the file is created. Otherwise, a | ||
148 | * valid or negative dentry, or an error is returned. */ | ||
149 | static struct dentry *get_xa_file_dentry(const struct inode *inode, | ||
150 | const char *name, int flags) | ||
151 | { | ||
152 | struct dentry *xadir, *xafile; | ||
153 | int err = 0; | ||
154 | |||
155 | xadir = open_xa_dir(inode, flags); | ||
156 | if (IS_ERR(xadir)) { | ||
157 | return ERR_CAST(xadir); | ||
158 | } else if (!xadir->d_inode) { | ||
159 | dput(xadir); | ||
160 | return ERR_PTR(-ENODATA); | ||
161 | } | ||
162 | |||
163 | xafile = lookup_one_len(name, xadir, strlen(name)); | ||
164 | if (IS_ERR(xafile)) { | ||
165 | dput(xadir); | ||
166 | return ERR_CAST(xafile); | ||
167 | } | ||
168 | |||
169 | if (xafile->d_inode) { /* file exists */ | ||
170 | if (flags & XATTR_CREATE) { | ||
171 | err = -EEXIST; | ||
172 | dput(xafile); | ||
173 | goto out; | ||
174 | } | ||
175 | } else if (flags & XATTR_REPLACE || flags & FL_READONLY) { | ||
176 | goto out; | ||
177 | } else { | ||
178 | /* inode->i_mutex is down, so nothing else can try to create | ||
179 | * the same xattr */ | ||
180 | err = xadir->d_inode->i_op->create(xadir->d_inode, xafile, | ||
181 | 0700 | S_IFREG, NULL); | ||
182 | |||
183 | if (err) { | ||
184 | dput(xafile); | ||
185 | goto out; | ||
186 | } | ||
187 | } | ||
188 | |||
189 | out: | ||
190 | dput(xadir); | ||
191 | if (err) | ||
192 | xafile = ERR_PTR(err); | ||
193 | else if (!xafile->d_inode) { | ||
194 | dput(xafile); | ||
195 | xafile = ERR_PTR(-ENODATA); | ||
196 | } | ||
197 | return xafile; | ||
198 | } | ||
199 | |||
200 | /* | 143 | /* |
201 | * this is very similar to fs/reiserfs/dir.c:reiserfs_readdir, but | 144 | * this is very similar to fs/reiserfs/dir.c:reiserfs_readdir, but |
202 | * we need to drop the path before calling the filldir struct. That | 145 | * we need to drop the path before calling the filldir struct. That |
@@ -369,6 +312,251 @@ int xattr_readdir(struct inode *inode, filldir_t filler, void *buf) | |||
369 | return res; | 312 | return res; |
370 | } | 313 | } |
371 | 314 | ||
315 | static int | ||
316 | __reiserfs_xattr_del(struct dentry *xadir, const char *name, int namelen) | ||
317 | { | ||
318 | struct dentry *dentry; | ||
319 | struct inode *dir = xadir->d_inode; | ||
320 | int err = 0; | ||
321 | |||
322 | dentry = lookup_one_len(name, xadir, namelen); | ||
323 | if (IS_ERR(dentry)) { | ||
324 | err = PTR_ERR(dentry); | ||
325 | goto out; | ||
326 | } else if (!dentry->d_inode) { | ||
327 | err = -ENODATA; | ||
328 | goto out_file; | ||
329 | } | ||
330 | |||
331 | /* Skip directories.. */ | ||
332 | if (S_ISDIR(dentry->d_inode->i_mode)) | ||
333 | goto out_file; | ||
334 | |||
335 | if (!IS_PRIVATE(dentry->d_inode)) { | ||
336 | reiserfs_error(dir->i_sb, "jdm-20003", | ||
337 | "OID %08x [%.*s/%.*s] doesn't have " | ||
338 | "priv flag set [parent is %sset].", | ||
339 | le32_to_cpu(INODE_PKEY(dentry->d_inode)-> | ||
340 | k_objectid), xadir->d_name.len, | ||
341 | xadir->d_name.name, namelen, name, | ||
342 | IS_PRIVATE(xadir->d_inode) ? "" : | ||
343 | "not "); | ||
344 | dput(dentry); | ||
345 | return -EIO; | ||
346 | } | ||
347 | |||
348 | err = dir->i_op->unlink(dir, dentry); | ||
349 | if (!err) | ||
350 | d_delete(dentry); | ||
351 | |||
352 | out_file: | ||
353 | dput(dentry); | ||
354 | |||
355 | out: | ||
356 | return err; | ||
357 | } | ||
358 | |||
359 | /* The following are side effects of other operations that aren't explicitly | ||
360 | * modifying extended attributes. This includes operations such as permissions | ||
361 | * or ownership changes, object deletions, etc. */ | ||
362 | |||
363 | static int | ||
364 | reiserfs_delete_xattrs_filler(void *buf, const char *name, int namelen, | ||
365 | loff_t offset, u64 ino, unsigned int d_type) | ||
366 | { | ||
367 | struct dentry *xadir = (struct dentry *)buf; | ||
368 | |||
369 | return __reiserfs_xattr_del(xadir, name, namelen); | ||
370 | |||
371 | } | ||
372 | |||
373 | /* This is called w/ inode->i_mutex downed */ | ||
374 | int reiserfs_delete_xattrs(struct inode *inode) | ||
375 | { | ||
376 | struct dentry *dir, *root; | ||
377 | int err = 0; | ||
378 | |||
379 | /* Skip out, an xattr has no xattrs associated with it */ | ||
380 | if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1) | ||
381 | return 0; | ||
382 | |||
383 | reiserfs_read_lock_xattrs(inode->i_sb); | ||
384 | dir = open_xa_dir(inode, FL_READONLY); | ||
385 | reiserfs_read_unlock_xattrs(inode->i_sb); | ||
386 | if (IS_ERR(dir)) { | ||
387 | err = PTR_ERR(dir); | ||
388 | goto out; | ||
389 | } else if (!dir->d_inode) { | ||
390 | dput(dir); | ||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | lock_kernel(); | ||
395 | err = xattr_readdir(dir->d_inode, reiserfs_delete_xattrs_filler, dir); | ||
396 | if (err) { | ||
397 | unlock_kernel(); | ||
398 | goto out_dir; | ||
399 | } | ||
400 | |||
401 | /* Leftovers besides . and .. -- that's not good. */ | ||
402 | if (dir->d_inode->i_nlink <= 2) { | ||
403 | root = get_xa_root(inode->i_sb, XATTR_REPLACE); | ||
404 | reiserfs_write_lock_xattrs(inode->i_sb); | ||
405 | err = vfs_rmdir(root->d_inode, dir); | ||
406 | reiserfs_write_unlock_xattrs(inode->i_sb); | ||
407 | dput(root); | ||
408 | } else { | ||
409 | reiserfs_warning(inode->i_sb, "jdm-20006", | ||
410 | "Couldn't remove all entries in directory"); | ||
411 | } | ||
412 | unlock_kernel(); | ||
413 | |||
414 | out_dir: | ||
415 | dput(dir); | ||
416 | |||
417 | out: | ||
418 | if (!err) | ||
419 | REISERFS_I(inode)->i_flags = | ||
420 | REISERFS_I(inode)->i_flags & ~i_has_xattr_dir; | ||
421 | return err; | ||
422 | } | ||
423 | |||
424 | struct reiserfs_chown_buf { | ||
425 | struct inode *inode; | ||
426 | struct dentry *xadir; | ||
427 | struct iattr *attrs; | ||
428 | }; | ||
429 | |||
430 | /* XXX: If there is a better way to do this, I'd love to hear about it */ | ||
431 | static int | ||
432 | reiserfs_chown_xattrs_filler(void *buf, const char *name, int namelen, | ||
433 | loff_t offset, u64 ino, unsigned int d_type) | ||
434 | { | ||
435 | struct reiserfs_chown_buf *chown_buf = (struct reiserfs_chown_buf *)buf; | ||
436 | struct dentry *xafile, *xadir = chown_buf->xadir; | ||
437 | struct iattr *attrs = chown_buf->attrs; | ||
438 | int err = 0; | ||
439 | |||
440 | xafile = lookup_one_len(name, xadir, namelen); | ||
441 | if (IS_ERR(xafile)) | ||
442 | return PTR_ERR(xafile); | ||
443 | else if (!xafile->d_inode) { | ||
444 | dput(xafile); | ||
445 | return -ENODATA; | ||
446 | } | ||
447 | |||
448 | if (!S_ISDIR(xafile->d_inode->i_mode)) | ||
449 | err = notify_change(xafile, attrs); | ||
450 | dput(xafile); | ||
451 | |||
452 | return err; | ||
453 | } | ||
454 | |||
455 | int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs) | ||
456 | { | ||
457 | struct dentry *dir; | ||
458 | int err = 0; | ||
459 | struct reiserfs_chown_buf buf; | ||
460 | unsigned int ia_valid = attrs->ia_valid; | ||
461 | |||
462 | /* Skip out, an xattr has no xattrs associated with it */ | ||
463 | if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1) | ||
464 | return 0; | ||
465 | |||
466 | reiserfs_read_lock_xattrs(inode->i_sb); | ||
467 | dir = open_xa_dir(inode, FL_READONLY); | ||
468 | reiserfs_read_unlock_xattrs(inode->i_sb); | ||
469 | if (IS_ERR(dir)) { | ||
470 | if (PTR_ERR(dir) != -ENODATA) | ||
471 | err = PTR_ERR(dir); | ||
472 | goto out; | ||
473 | } else if (!dir->d_inode) { | ||
474 | dput(dir); | ||
475 | goto out; | ||
476 | } | ||
477 | |||
478 | lock_kernel(); | ||
479 | |||
480 | attrs->ia_valid &= (ATTR_UID | ATTR_GID | ATTR_CTIME); | ||
481 | buf.xadir = dir; | ||
482 | buf.attrs = attrs; | ||
483 | buf.inode = inode; | ||
484 | |||
485 | err = xattr_readdir(dir->d_inode, reiserfs_chown_xattrs_filler, &buf); | ||
486 | if (err) { | ||
487 | unlock_kernel(); | ||
488 | goto out_dir; | ||
489 | } | ||
490 | |||
491 | err = notify_change(dir, attrs); | ||
492 | unlock_kernel(); | ||
493 | |||
494 | out_dir: | ||
495 | dput(dir); | ||
496 | |||
497 | out: | ||
498 | attrs->ia_valid = ia_valid; | ||
499 | return err; | ||
500 | } | ||
501 | |||
502 | #ifdef CONFIG_REISERFS_FS_XATTR | ||
503 | static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char | ||
504 | *prefix); | ||
505 | |||
506 | /* Returns a dentry corresponding to a specific extended attribute file | ||
507 | * for the inode. If flags allow, the file is created. Otherwise, a | ||
508 | * valid or negative dentry, or an error is returned. */ | ||
509 | static struct dentry *get_xa_file_dentry(const struct inode *inode, | ||
510 | const char *name, int flags) | ||
511 | { | ||
512 | struct dentry *xadir, *xafile; | ||
513 | int err = 0; | ||
514 | |||
515 | xadir = open_xa_dir(inode, flags); | ||
516 | if (IS_ERR(xadir)) { | ||
517 | return ERR_CAST(xadir); | ||
518 | } else if (xadir && !xadir->d_inode) { | ||
519 | dput(xadir); | ||
520 | return ERR_PTR(-ENODATA); | ||
521 | } | ||
522 | |||
523 | xafile = lookup_one_len(name, xadir, strlen(name)); | ||
524 | if (IS_ERR(xafile)) { | ||
525 | dput(xadir); | ||
526 | return ERR_CAST(xafile); | ||
527 | } | ||
528 | |||
529 | if (xafile->d_inode) { /* file exists */ | ||
530 | if (flags & XATTR_CREATE) { | ||
531 | err = -EEXIST; | ||
532 | dput(xafile); | ||
533 | goto out; | ||
534 | } | ||
535 | } else if (flags & XATTR_REPLACE || flags & FL_READONLY) { | ||
536 | goto out; | ||
537 | } else { | ||
538 | /* inode->i_mutex is down, so nothing else can try to create | ||
539 | * the same xattr */ | ||
540 | err = xadir->d_inode->i_op->create(xadir->d_inode, xafile, | ||
541 | 0700 | S_IFREG, NULL); | ||
542 | |||
543 | if (err) { | ||
544 | dput(xafile); | ||
545 | goto out; | ||
546 | } | ||
547 | } | ||
548 | |||
549 | out: | ||
550 | dput(xadir); | ||
551 | if (err) | ||
552 | xafile = ERR_PTR(err); | ||
553 | else if (!xafile->d_inode) { | ||
554 | dput(xafile); | ||
555 | xafile = ERR_PTR(-ENODATA); | ||
556 | } | ||
557 | return xafile; | ||
558 | } | ||
559 | |||
372 | /* Internal operations on file data */ | 560 | /* Internal operations on file data */ |
373 | static inline void reiserfs_put_page(struct page *page) | 561 | static inline void reiserfs_put_page(struct page *page) |
374 | { | 562 | { |
@@ -606,54 +794,10 @@ reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer, | |||
606 | err = -EIO; | 794 | err = -EIO; |
607 | } | 795 | } |
608 | 796 | ||
609 | out_dput: | 797 | out_dput: |
610 | dput(dentry); | 798 | dput(dentry); |
611 | 799 | ||
612 | out: | 800 | out: |
613 | return err; | ||
614 | } | ||
615 | |||
616 | static int | ||
617 | __reiserfs_xattr_del(struct dentry *xadir, const char *name, int namelen) | ||
618 | { | ||
619 | struct dentry *dentry; | ||
620 | struct inode *dir = xadir->d_inode; | ||
621 | int err = 0; | ||
622 | |||
623 | dentry = lookup_one_len(name, xadir, namelen); | ||
624 | if (IS_ERR(dentry)) { | ||
625 | err = PTR_ERR(dentry); | ||
626 | goto out; | ||
627 | } else if (!dentry->d_inode) { | ||
628 | err = -ENODATA; | ||
629 | goto out_file; | ||
630 | } | ||
631 | |||
632 | /* Skip directories.. */ | ||
633 | if (S_ISDIR(dentry->d_inode->i_mode)) | ||
634 | goto out_file; | ||
635 | |||
636 | if (!IS_PRIVATE(dentry->d_inode)) { | ||
637 | reiserfs_error(dir->i_sb, "jdm-20003", | ||
638 | "OID %08x [%.*s/%.*s] doesn't have " | ||
639 | "priv flag set [parent is %sset].", | ||
640 | le32_to_cpu(INODE_PKEY(dentry->d_inode)-> | ||
641 | k_objectid), xadir->d_name.len, | ||
642 | xadir->d_name.name, namelen, name, | ||
643 | IS_PRIVATE(xadir->d_inode) ? "" : | ||
644 | "not "); | ||
645 | dput(dentry); | ||
646 | return -EIO; | ||
647 | } | ||
648 | |||
649 | err = dir->i_op->unlink(dir, dentry); | ||
650 | if (!err) | ||
651 | d_delete(dentry); | ||
652 | |||
653 | out_file: | ||
654 | dput(dentry); | ||
655 | |||
656 | out: | ||
657 | return err; | 801 | return err; |
658 | } | 802 | } |
659 | 803 | ||
@@ -680,151 +824,6 @@ int reiserfs_xattr_del(struct inode *inode, const char *name) | |||
680 | return err; | 824 | return err; |
681 | } | 825 | } |
682 | 826 | ||
683 | /* The following are side effects of other operations that aren't explicitly | ||
684 | * modifying extended attributes. This includes operations such as permissions | ||
685 | * or ownership changes, object deletions, etc. */ | ||
686 | |||
687 | static int | ||
688 | reiserfs_delete_xattrs_filler(void *buf, const char *name, int namelen, | ||
689 | loff_t offset, u64 ino, unsigned int d_type) | ||
690 | { | ||
691 | struct dentry *xadir = (struct dentry *)buf; | ||
692 | |||
693 | return __reiserfs_xattr_del(xadir, name, namelen); | ||
694 | |||
695 | } | ||
696 | |||
697 | /* This is called w/ inode->i_mutex downed */ | ||
698 | int reiserfs_delete_xattrs(struct inode *inode) | ||
699 | { | ||
700 | struct dentry *dir, *root; | ||
701 | int err = 0; | ||
702 | |||
703 | /* Skip out, an xattr has no xattrs associated with it */ | ||
704 | if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1 || | ||
705 | !reiserfs_xattrs(inode->i_sb)) { | ||
706 | return 0; | ||
707 | } | ||
708 | reiserfs_read_lock_xattrs(inode->i_sb); | ||
709 | dir = open_xa_dir(inode, FL_READONLY); | ||
710 | reiserfs_read_unlock_xattrs(inode->i_sb); | ||
711 | if (IS_ERR(dir)) { | ||
712 | err = PTR_ERR(dir); | ||
713 | goto out; | ||
714 | } else if (!dir->d_inode) { | ||
715 | dput(dir); | ||
716 | return 0; | ||
717 | } | ||
718 | |||
719 | lock_kernel(); | ||
720 | err = xattr_readdir(dir->d_inode, reiserfs_delete_xattrs_filler, dir); | ||
721 | if (err) { | ||
722 | unlock_kernel(); | ||
723 | goto out_dir; | ||
724 | } | ||
725 | |||
726 | /* Leftovers besides . and .. -- that's not good. */ | ||
727 | if (dir->d_inode->i_nlink <= 2) { | ||
728 | root = get_xa_root(inode->i_sb, XATTR_REPLACE); | ||
729 | reiserfs_write_lock_xattrs(inode->i_sb); | ||
730 | err = vfs_rmdir(root->d_inode, dir); | ||
731 | reiserfs_write_unlock_xattrs(inode->i_sb); | ||
732 | dput(root); | ||
733 | } else { | ||
734 | reiserfs_warning(inode->i_sb, "jdm-20006", | ||
735 | "Couldn't remove all entries in directory"); | ||
736 | } | ||
737 | unlock_kernel(); | ||
738 | |||
739 | out_dir: | ||
740 | dput(dir); | ||
741 | |||
742 | out: | ||
743 | if (!err) | ||
744 | REISERFS_I(inode)->i_flags = | ||
745 | REISERFS_I(inode)->i_flags & ~i_has_xattr_dir; | ||
746 | return err; | ||
747 | } | ||
748 | |||
749 | struct reiserfs_chown_buf { | ||
750 | struct inode *inode; | ||
751 | struct dentry *xadir; | ||
752 | struct iattr *attrs; | ||
753 | }; | ||
754 | |||
755 | /* XXX: If there is a better way to do this, I'd love to hear about it */ | ||
756 | static int | ||
757 | reiserfs_chown_xattrs_filler(void *buf, const char *name, int namelen, | ||
758 | loff_t offset, u64 ino, unsigned int d_type) | ||
759 | { | ||
760 | struct reiserfs_chown_buf *chown_buf = (struct reiserfs_chown_buf *)buf; | ||
761 | struct dentry *xafile, *xadir = chown_buf->xadir; | ||
762 | struct iattr *attrs = chown_buf->attrs; | ||
763 | int err = 0; | ||
764 | |||
765 | xafile = lookup_one_len(name, xadir, namelen); | ||
766 | if (IS_ERR(xafile)) | ||
767 | return PTR_ERR(xafile); | ||
768 | else if (!xafile->d_inode) { | ||
769 | dput(xafile); | ||
770 | return -ENODATA; | ||
771 | } | ||
772 | |||
773 | if (!S_ISDIR(xafile->d_inode->i_mode)) | ||
774 | err = notify_change(xafile, attrs); | ||
775 | dput(xafile); | ||
776 | |||
777 | return err; | ||
778 | } | ||
779 | |||
780 | int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs) | ||
781 | { | ||
782 | struct dentry *dir; | ||
783 | int err = 0; | ||
784 | struct reiserfs_chown_buf buf; | ||
785 | unsigned int ia_valid = attrs->ia_valid; | ||
786 | |||
787 | /* Skip out, an xattr has no xattrs associated with it */ | ||
788 | if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1 || | ||
789 | !reiserfs_xattrs(inode->i_sb)) { | ||
790 | return 0; | ||
791 | } | ||
792 | reiserfs_read_lock_xattrs(inode->i_sb); | ||
793 | dir = open_xa_dir(inode, FL_READONLY); | ||
794 | reiserfs_read_unlock_xattrs(inode->i_sb); | ||
795 | if (IS_ERR(dir)) { | ||
796 | if (PTR_ERR(dir) != -ENODATA) | ||
797 | err = PTR_ERR(dir); | ||
798 | goto out; | ||
799 | } else if (!dir->d_inode) { | ||
800 | dput(dir); | ||
801 | goto out; | ||
802 | } | ||
803 | |||
804 | lock_kernel(); | ||
805 | |||
806 | attrs->ia_valid &= (ATTR_UID | ATTR_GID | ATTR_CTIME); | ||
807 | buf.xadir = dir; | ||
808 | buf.attrs = attrs; | ||
809 | buf.inode = inode; | ||
810 | |||
811 | err = xattr_readdir(dir->d_inode, reiserfs_chown_xattrs_filler, &buf); | ||
812 | if (err) { | ||
813 | unlock_kernel(); | ||
814 | goto out_dir; | ||
815 | } | ||
816 | |||
817 | err = notify_change(dir, attrs); | ||
818 | unlock_kernel(); | ||
819 | |||
820 | out_dir: | ||
821 | dput(dir); | ||
822 | |||
823 | out: | ||
824 | attrs->ia_valid = ia_valid; | ||
825 | return err; | ||
826 | } | ||
827 | |||
828 | /* Actual operations that are exported to VFS-land */ | 827 | /* Actual operations that are exported to VFS-land */ |
829 | 828 | ||
830 | /* | 829 | /* |
@@ -1101,6 +1100,94 @@ void reiserfs_xattr_unregister_handlers(void) | |||
1101 | write_unlock(&handler_lock); | 1100 | write_unlock(&handler_lock); |
1102 | } | 1101 | } |
1103 | 1102 | ||
1103 | static int reiserfs_check_acl(struct inode *inode, int mask) | ||
1104 | { | ||
1105 | struct posix_acl *acl; | ||
1106 | int error = -EAGAIN; /* do regular unix permission checks by default */ | ||
1107 | |||
1108 | reiserfs_read_lock_xattr_i(inode); | ||
1109 | reiserfs_read_lock_xattrs(inode->i_sb); | ||
1110 | |||
1111 | acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); | ||
1112 | |||
1113 | reiserfs_read_unlock_xattrs(inode->i_sb); | ||
1114 | reiserfs_read_unlock_xattr_i(inode); | ||
1115 | |||
1116 | if (acl) { | ||
1117 | if (!IS_ERR(acl)) { | ||
1118 | error = posix_acl_permission(inode, acl, mask); | ||
1119 | posix_acl_release(acl); | ||
1120 | } else if (PTR_ERR(acl) != -ENODATA) | ||
1121 | error = PTR_ERR(acl); | ||
1122 | } | ||
1123 | |||
1124 | return error; | ||
1125 | } | ||
1126 | |||
1127 | int reiserfs_permission(struct inode *inode, int mask) | ||
1128 | { | ||
1129 | /* | ||
1130 | * We don't do permission checks on the internal objects. | ||
1131 | * Permissions are determined by the "owning" object. | ||
1132 | */ | ||
1133 | if (IS_PRIVATE(inode)) | ||
1134 | return 0; | ||
1135 | /* | ||
1136 | * Stat data v1 doesn't support ACLs. | ||
1137 | */ | ||
1138 | if (get_inode_sd_version(inode) == STAT_DATA_V1) | ||
1139 | return generic_permission(inode, mask, NULL); | ||
1140 | else | ||
1141 | return generic_permission(inode, mask, reiserfs_check_acl); | ||
1142 | } | ||
1143 | |||
1144 | static int create_privroot(struct dentry *dentry) | ||
1145 | { | ||
1146 | int err; | ||
1147 | struct inode *inode = dentry->d_parent->d_inode; | ||
1148 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_XATTR); | ||
1149 | err = inode->i_op->mkdir(inode, dentry, 0700); | ||
1150 | mutex_unlock(&inode->i_mutex); | ||
1151 | if (err) { | ||
1152 | dput(dentry); | ||
1153 | dentry = NULL; | ||
1154 | } | ||
1155 | |||
1156 | if (dentry && dentry->d_inode) | ||
1157 | reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr " | ||
1158 | "storage.\n", PRIVROOT_NAME); | ||
1159 | |||
1160 | return err; | ||
1161 | } | ||
1162 | |||
1163 | static int xattr_mount_check(struct super_block *s) | ||
1164 | { | ||
1165 | /* We need generation numbers to ensure that the oid mapping is correct | ||
1166 | * v3.5 filesystems don't have them. */ | ||
1167 | if (!old_format_only(s)) { | ||
1168 | set_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt)); | ||
1169 | } else if (reiserfs_xattrs_optional(s)) { | ||
1170 | /* Old format filesystem, but optional xattrs have been enabled | ||
1171 | * at mount time. Error out. */ | ||
1172 | reiserfs_warning(s, "jdm-20005", | ||
1173 | "xattrs/ACLs not supported on pre v3.6 " | ||
1174 | "format filesystem. Failing mount."); | ||
1175 | return -EOPNOTSUPP; | ||
1176 | } else { | ||
1177 | /* Old format filesystem, but no optional xattrs have | ||
1178 | * been enabled. This means we silently disable xattrs | ||
1179 | * on the filesystem. */ | ||
1180 | clear_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt)); | ||
1181 | } | ||
1182 | |||
1183 | return 0; | ||
1184 | } | ||
1185 | |||
1186 | #else | ||
1187 | int __init reiserfs_xattr_register_handlers(void) { return 0; } | ||
1188 | void reiserfs_xattr_unregister_handlers(void) {} | ||
1189 | #endif | ||
1190 | |||
1104 | /* This will catch lookups from the fs root to .reiserfs_priv */ | 1191 | /* This will catch lookups from the fs root to .reiserfs_priv */ |
1105 | static int | 1192 | static int |
1106 | xattr_lookup_poison(struct dentry *dentry, struct qstr *q1, struct qstr *name) | 1193 | xattr_lookup_poison(struct dentry *dentry, struct qstr *q1, struct qstr *name) |
@@ -1127,47 +1214,23 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags) | |||
1127 | { | 1214 | { |
1128 | int err = 0; | 1215 | int err = 0; |
1129 | 1216 | ||
1130 | /* We need generation numbers to ensure that the oid mapping is correct | 1217 | #ifdef CONFIG_REISERFS_FS_XATTR |
1131 | * v3.5 filesystems don't have them. */ | 1218 | err = xattr_mount_check(s); |
1132 | if (!old_format_only(s)) { | 1219 | if (err) |
1133 | set_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt)); | ||
1134 | } else if (reiserfs_xattrs_optional(s)) { | ||
1135 | /* Old format filesystem, but optional xattrs have been enabled | ||
1136 | * at mount time. Error out. */ | ||
1137 | reiserfs_warning(s, "jdm-20005", | ||
1138 | "xattrs/ACLs not supported on pre v3.6 " | ||
1139 | "format filesystem. Failing mount."); | ||
1140 | err = -EOPNOTSUPP; | ||
1141 | goto error; | 1220 | goto error; |
1142 | } else { | 1221 | #endif |
1143 | /* Old format filesystem, but no optional xattrs have been enabled. This | ||
1144 | * means we silently disable xattrs on the filesystem. */ | ||
1145 | clear_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt)); | ||
1146 | } | ||
1147 | 1222 | ||
1148 | /* If we don't have the privroot located yet - go find it */ | 1223 | /* If we don't have the privroot located yet - go find it */ |
1149 | if (reiserfs_xattrs(s) && !REISERFS_SB(s)->priv_root) { | 1224 | if (!REISERFS_SB(s)->priv_root) { |
1150 | struct dentry *dentry; | 1225 | struct dentry *dentry; |
1151 | dentry = lookup_one_len(PRIVROOT_NAME, s->s_root, | 1226 | dentry = lookup_one_len(PRIVROOT_NAME, s->s_root, |
1152 | strlen(PRIVROOT_NAME)); | 1227 | strlen(PRIVROOT_NAME)); |
1153 | if (!IS_ERR(dentry)) { | 1228 | if (!IS_ERR(dentry)) { |
1154 | if (!(mount_flags & MS_RDONLY) && !dentry->d_inode) { | 1229 | #ifdef CONFIG_REISERFS_FS_XATTR |
1155 | struct inode *inode = dentry->d_parent->d_inode; | 1230 | if (!(mount_flags & MS_RDONLY) && !dentry->d_inode) |
1156 | mutex_lock_nested(&inode->i_mutex, | 1231 | err = create_privroot(dentry); |
1157 | I_MUTEX_XATTR); | 1232 | #endif |
1158 | err = inode->i_op->mkdir(inode, dentry, 0700); | 1233 | if (!dentry->d_inode) { |
1159 | mutex_unlock(&inode->i_mutex); | ||
1160 | if (err) { | ||
1161 | dput(dentry); | ||
1162 | dentry = NULL; | ||
1163 | } | ||
1164 | |||
1165 | if (dentry && dentry->d_inode) | ||
1166 | reiserfs_info(s, "Created %s - " | ||
1167 | "reserved for xattr " | ||
1168 | "storage.\n", | ||
1169 | PRIVROOT_NAME); | ||
1170 | } else if (!dentry->d_inode) { | ||
1171 | dput(dentry); | 1234 | dput(dentry); |
1172 | dentry = NULL; | 1235 | dentry = NULL; |
1173 | } | 1236 | } |
@@ -1178,73 +1241,37 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags) | |||
1178 | s->s_root->d_op = &xattr_lookup_poison_ops; | 1241 | s->s_root->d_op = &xattr_lookup_poison_ops; |
1179 | dentry->d_inode->i_flags |= S_PRIVATE; | 1242 | dentry->d_inode->i_flags |= S_PRIVATE; |
1180 | REISERFS_SB(s)->priv_root = dentry; | 1243 | REISERFS_SB(s)->priv_root = dentry; |
1181 | } else if (!(mount_flags & MS_RDONLY)) { /* xattrs are unavailable */ | 1244 | #ifdef CONFIG_REISERFS_FS_XATTR |
1182 | /* If we're read-only it just means that the dir hasn't been | 1245 | /* xattrs are unavailable */ |
1183 | * created. Not an error -- just no xattrs on the fs. We'll | 1246 | } else if (!(mount_flags & MS_RDONLY)) { |
1184 | * check again if we go read-write */ | 1247 | /* If we're read-only it just means that the dir |
1248 | * hasn't been created. Not an error -- just no | ||
1249 | * xattrs on the fs. We'll check again if we | ||
1250 | * go read-write */ | ||
1185 | reiserfs_warning(s, "jdm-20006", | 1251 | reiserfs_warning(s, "jdm-20006", |
1186 | "xattrs/ACLs enabled and couldn't " | 1252 | "xattrs/ACLs enabled and couldn't " |
1187 | "find/create .reiserfs_priv. " | 1253 | "find/create .reiserfs_priv. " |
1188 | "Failing mount."); | 1254 | "Failing mount."); |
1189 | err = -EOPNOTSUPP; | 1255 | err = -EOPNOTSUPP; |
1256 | #endif | ||
1190 | } | 1257 | } |
1191 | } | 1258 | } |
1192 | 1259 | ||
1193 | error: | 1260 | #ifdef CONFIG_REISERFS_FS_XATTR |
1194 | /* This is only nonzero if there was an error initializing the xattr | 1261 | error: |
1195 | * directory or if there is a condition where we don't support them. */ | ||
1196 | if (err) { | 1262 | if (err) { |
1197 | clear_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt)); | 1263 | clear_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt)); |
1198 | clear_bit(REISERFS_XATTRS_USER, &(REISERFS_SB(s)->s_mount_opt)); | 1264 | clear_bit(REISERFS_XATTRS_USER, &(REISERFS_SB(s)->s_mount_opt)); |
1199 | clear_bit(REISERFS_POSIXACL, &(REISERFS_SB(s)->s_mount_opt)); | 1265 | clear_bit(REISERFS_POSIXACL, &(REISERFS_SB(s)->s_mount_opt)); |
1200 | } | 1266 | } |
1267 | #endif | ||
1201 | 1268 | ||
1202 | /* The super_block MS_POSIXACL must mirror the (no)acl mount option. */ | 1269 | /* The super_block MS_POSIXACL must mirror the (no)acl mount option. */ |
1203 | s->s_flags = s->s_flags & ~MS_POSIXACL; | 1270 | s->s_flags = s->s_flags & ~MS_POSIXACL; |
1271 | #ifdef CONFIG_REISERFS_FS_POSIX_ACL | ||
1204 | if (reiserfs_posixacl(s)) | 1272 | if (reiserfs_posixacl(s)) |
1205 | s->s_flags |= MS_POSIXACL; | 1273 | s->s_flags |= MS_POSIXACL; |
1274 | #endif | ||
1206 | 1275 | ||
1207 | return err; | 1276 | return err; |
1208 | } | 1277 | } |
1209 | |||
1210 | static int reiserfs_check_acl(struct inode *inode, int mask) | ||
1211 | { | ||
1212 | struct posix_acl *acl; | ||
1213 | int error = -EAGAIN; /* do regular unix permission checks by default */ | ||
1214 | |||
1215 | reiserfs_read_lock_xattr_i(inode); | ||
1216 | reiserfs_read_lock_xattrs(inode->i_sb); | ||
1217 | |||
1218 | acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); | ||
1219 | |||
1220 | reiserfs_read_unlock_xattrs(inode->i_sb); | ||
1221 | reiserfs_read_unlock_xattr_i(inode); | ||
1222 | |||
1223 | if (acl) { | ||
1224 | if (!IS_ERR(acl)) { | ||
1225 | error = posix_acl_permission(inode, acl, mask); | ||
1226 | posix_acl_release(acl); | ||
1227 | } else if (PTR_ERR(acl) != -ENODATA) | ||
1228 | error = PTR_ERR(acl); | ||
1229 | } | ||
1230 | |||
1231 | return error; | ||
1232 | } | ||
1233 | |||
1234 | int reiserfs_permission(struct inode *inode, int mask) | ||
1235 | { | ||
1236 | /* | ||
1237 | * We don't do permission checks on the internal objects. | ||
1238 | * Permissions are determined by the "owning" object. | ||
1239 | */ | ||
1240 | if (IS_PRIVATE(inode)) | ||
1241 | return 0; | ||
1242 | |||
1243 | /* | ||
1244 | * Stat data v1 doesn't support ACLs. | ||
1245 | */ | ||
1246 | if (get_inode_sd_version(inode) == STAT_DATA_V1) | ||
1247 | return generic_permission(inode, mask, NULL); | ||
1248 | else | ||
1249 | return generic_permission(inode, mask, reiserfs_check_acl); | ||
1250 | } | ||
diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h index 12fc2a0d13be..cbb8868e844e 100644 --- a/include/linux/reiserfs_fs_sb.h +++ b/include/linux/reiserfs_fs_sb.h | |||
@@ -402,8 +402,8 @@ struct reiserfs_sb_info { | |||
402 | int reserved_blocks; /* amount of blocks reserved for further allocations */ | 402 | int reserved_blocks; /* amount of blocks reserved for further allocations */ |
403 | spinlock_t bitmap_lock; /* this lock on now only used to protect reserved_blocks variable */ | 403 | spinlock_t bitmap_lock; /* this lock on now only used to protect reserved_blocks variable */ |
404 | struct dentry *priv_root; /* root of /.reiserfs_priv */ | 404 | struct dentry *priv_root; /* root of /.reiserfs_priv */ |
405 | #ifdef CONFIG_REISERFS_FS_XATTR | ||
406 | struct dentry *xattr_root; /* root of /.reiserfs_priv/.xa */ | 405 | struct dentry *xattr_root; /* root of /.reiserfs_priv/.xa */ |
406 | #ifdef CONFIG_REISERFS_FS_XATTR | ||
407 | struct rw_semaphore xattr_dir_sem; | 407 | struct rw_semaphore xattr_dir_sem; |
408 | #endif | 408 | #endif |
409 | int j_errno; | 409 | int j_errno; |
diff --git a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h index 58f32ba7f5a0..13cdd5e1cb60 100644 --- a/include/linux/reiserfs_xattr.h +++ b/include/linux/reiserfs_xattr.h | |||
@@ -43,6 +43,12 @@ struct reiserfs_xattr_handler { | |||
43 | struct list_head handlers; | 43 | struct list_head handlers; |
44 | }; | 44 | }; |
45 | 45 | ||
46 | int reiserfs_xattr_register_handlers(void) __init; | ||
47 | void reiserfs_xattr_unregister_handlers(void); | ||
48 | int reiserfs_xattr_init(struct super_block *sb, int mount_flags); | ||
49 | int reiserfs_delete_xattrs(struct inode *inode); | ||
50 | int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs); | ||
51 | |||
46 | #ifdef CONFIG_REISERFS_FS_XATTR | 52 | #ifdef CONFIG_REISERFS_FS_XATTR |
47 | #define has_xattr_dir(inode) (REISERFS_I(inode)->i_flags & i_has_xattr_dir) | 53 | #define has_xattr_dir(inode) (REISERFS_I(inode)->i_flags & i_has_xattr_dir) |
48 | ssize_t reiserfs_getxattr(struct dentry *dentry, const char *name, | 54 | ssize_t reiserfs_getxattr(struct dentry *dentry, const char *name, |
@@ -51,9 +57,6 @@ int reiserfs_setxattr(struct dentry *dentry, const char *name, | |||
51 | const void *value, size_t size, int flags); | 57 | const void *value, size_t size, int flags); |
52 | ssize_t reiserfs_listxattr(struct dentry *dentry, char *buffer, size_t size); | 58 | ssize_t reiserfs_listxattr(struct dentry *dentry, char *buffer, size_t size); |
53 | int reiserfs_removexattr(struct dentry *dentry, const char *name); | 59 | int reiserfs_removexattr(struct dentry *dentry, const char *name); |
54 | int reiserfs_delete_xattrs(struct inode *inode); | ||
55 | int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs); | ||
56 | int reiserfs_xattr_init(struct super_block *sb, int mount_flags); | ||
57 | int reiserfs_permission(struct inode *inode, int mask); | 60 | int reiserfs_permission(struct inode *inode, int mask); |
58 | 61 | ||
59 | int reiserfs_xattr_del(struct inode *, const char *); | 62 | int reiserfs_xattr_del(struct inode *, const char *); |
@@ -64,9 +67,6 @@ extern struct reiserfs_xattr_handler user_handler; | |||
64 | extern struct reiserfs_xattr_handler trusted_handler; | 67 | extern struct reiserfs_xattr_handler trusted_handler; |
65 | extern struct reiserfs_xattr_handler security_handler; | 68 | extern struct reiserfs_xattr_handler security_handler; |
66 | 69 | ||
67 | int reiserfs_xattr_register_handlers(void) __init; | ||
68 | void reiserfs_xattr_unregister_handlers(void); | ||
69 | |||
70 | static inline void reiserfs_write_lock_xattrs(struct super_block *sb) | 70 | static inline void reiserfs_write_lock_xattrs(struct super_block *sb) |
71 | { | 71 | { |
72 | down_write(&REISERFS_XATTR_DIR_SEM(sb)); | 72 | down_write(&REISERFS_XATTR_DIR_SEM(sb)); |
@@ -121,23 +121,6 @@ static inline void reiserfs_init_xattr_rwsem(struct inode *inode) | |||
121 | 121 | ||
122 | #define reiserfs_permission NULL | 122 | #define reiserfs_permission NULL |
123 | 123 | ||
124 | #define reiserfs_xattr_register_handlers() 0 | ||
125 | #define reiserfs_xattr_unregister_handlers() | ||
126 | |||
127 | static inline int reiserfs_delete_xattrs(struct inode *inode) | ||
128 | { | ||
129 | return 0; | ||
130 | }; | ||
131 | static inline int reiserfs_chown_xattrs(struct inode *inode, | ||
132 | struct iattr *attrs) | ||
133 | { | ||
134 | return 0; | ||
135 | }; | ||
136 | static inline int reiserfs_xattr_init(struct super_block *sb, int mount_flags) | ||
137 | { | ||
138 | sb->s_flags = (sb->s_flags & ~MS_POSIXACL); /* to be sure */ | ||
139 | return 0; | ||
140 | }; | ||
141 | static inline void reiserfs_init_xattr_rwsem(struct inode *inode) | 124 | static inline void reiserfs_init_xattr_rwsem(struct inode *inode) |
142 | { | 125 | { |
143 | } | 126 | } |