aboutsummaryrefslogtreecommitdiffstats
path: root/fs/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/super.c')
-rw-r--r--fs/super.c35
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
566static void mark_files_ro(struct super_block *sb) 567static void mark_files_ro(struct super_block *sb)
567{ 568{
568 struct file *f; 569 struct file *f;
569 570
571retry:
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}
968EXPORT_SYMBOL_GPL(do_kern_mount);
948 969
949struct vfsmount *kern_mount_data(struct file_system_type *type, void *data) 970struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
950{ 971{