diff options
Diffstat (limited to 'fs/super.c')
-rw-r--r-- | fs/super.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/fs/super.c b/fs/super.c index 88811f60c8de..1f8f05ede437 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/idr.h> | 37 | #include <linux/idr.h> |
38 | #include <linux/kobject.h> | 38 | #include <linux/kobject.h> |
39 | #include <linux/mutex.h> | 39 | #include <linux/mutex.h> |
40 | #include <linux/file.h> | ||
40 | #include <asm/uaccess.h> | 41 | #include <asm/uaccess.h> |
41 | 42 | ||
42 | 43 | ||
@@ -556,21 +557,40 @@ out: | |||
556 | } | 557 | } |
557 | 558 | ||
558 | /** | 559 | /** |
559 | * mark_files_ro | 560 | * mark_files_ro - mark all files read-only |
560 | * @sb: superblock in question | 561 | * @sb: superblock in question |
561 | * | 562 | * |
562 | * All files are marked read/only. We don't care about pending | 563 | * All files are marked read-only. We don't care about pending |
563 | * delete files so this should be used in 'force' mode only | 564 | * delete files so this should be used in 'force' mode only. |
564 | */ | 565 | */ |
565 | 566 | ||
566 | static void mark_files_ro(struct super_block *sb) | 567 | static void mark_files_ro(struct super_block *sb) |
567 | { | 568 | { |
568 | struct file *f; | 569 | struct file *f; |
569 | 570 | ||
571 | retry: | ||
570 | file_list_lock(); | 572 | file_list_lock(); |
571 | list_for_each_entry(f, &sb->s_files, f_u.fu_list) { | 573 | list_for_each_entry(f, &sb->s_files, f_u.fu_list) { |
572 | if (S_ISREG(f->f_path.dentry->d_inode->i_mode) && file_count(f)) | 574 | struct vfsmount *mnt; |
573 | f->f_mode &= ~FMODE_WRITE; | 575 | if (!S_ISREG(f->f_path.dentry->d_inode->i_mode)) |
576 | continue; | ||
577 | if (!file_count(f)) | ||
578 | continue; | ||
579 | if (!(f->f_mode & FMODE_WRITE)) | ||
580 | continue; | ||
581 | f->f_mode &= ~FMODE_WRITE; | ||
582 | if (file_check_writeable(f) != 0) | ||
583 | continue; | ||
584 | file_release_write(f); | ||
585 | mnt = mntget(f->f_path.mnt); | ||
586 | file_list_unlock(); | ||
587 | /* | ||
588 | * This can sleep, so we can't hold | ||
589 | * the file_list_lock() spinlock. | ||
590 | */ | ||
591 | mnt_drop_write(mnt); | ||
592 | mntput(mnt); | ||
593 | goto retry; | ||
574 | } | 594 | } |
575 | file_list_unlock(); | 595 | file_list_unlock(); |
576 | } | 596 | } |
@@ -870,12 +890,12 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void | |||
870 | if (!mnt) | 890 | if (!mnt) |
871 | goto out; | 891 | goto out; |
872 | 892 | ||
873 | if (data) { | 893 | if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) { |
874 | secdata = alloc_secdata(); | 894 | secdata = alloc_secdata(); |
875 | if (!secdata) | 895 | if (!secdata) |
876 | goto out_mnt; | 896 | goto out_mnt; |
877 | 897 | ||
878 | error = security_sb_copy_data(type, data, secdata); | 898 | error = security_sb_copy_data(data, secdata); |
879 | if (error) | 899 | if (error) |
880 | goto out_free_secdata; | 900 | goto out_free_secdata; |
881 | } | 901 | } |
@@ -945,6 +965,7 @@ do_kern_mount(const char *fstype, int flags, const char *name, void *data) | |||
945 | put_filesystem(type); | 965 | put_filesystem(type); |
946 | return mnt; | 966 | return mnt; |
947 | } | 967 | } |
968 | EXPORT_SYMBOL_GPL(do_kern_mount); | ||
948 | 969 | ||
949 | struct vfsmount *kern_mount_data(struct file_system_type *type, void *data) | 970 | struct vfsmount *kern_mount_data(struct file_system_type *type, void *data) |
950 | { | 971 | { |