diff options
author | Jeff Mahoney <jeffm@suse.com> | 2009-03-30 14:02:33 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-03-30 15:16:37 -0400 |
commit | a72bdb1cd244725ff47b3a29662e2cb820d8c60f (patch) | |
tree | 68f9022b303ca5183bd64eddbff41f0624e84188 /fs | |
parent | 6dfede696391133eadd7ce90b61c9573ee6e5a90 (diff) |
reiserfs: Clean up xattrs when REISERFS_FS_XATTR is unset
The current reiserfs xattr implementation will not clean up old xattr
files if files are deleted when REISERFS_FS_XATTR is unset. This
results in inaccessible lost files, wasting space.
This patch compiles in basic xattr knowledge, such as how to delete them
and change ownership for quota tracking. If the file system has never
used xattrs, then the operation is quite fast: it returns immediately
when it sees there is no .reiserfs_priv directory.
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/reiserfs/Makefile | 4 | ||||
-rw-r--r-- | fs/reiserfs/xattr.c | 689 |
2 files changed, 360 insertions, 333 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 | } | ||