aboutsummaryrefslogtreecommitdiffstats
path: root/fs/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/super.c')
-rw-r--r--fs/super.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/fs/super.c b/fs/super.c
index 09008dbd264e..4798350b2bc9 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -37,7 +37,9 @@
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>
42#include "internal.h"
41 43
42 44
43LIST_HEAD(super_blocks); 45LIST_HEAD(super_blocks);
@@ -567,10 +569,29 @@ static void mark_files_ro(struct super_block *sb)
567{ 569{
568 struct file *f; 570 struct file *f;
569 571
572retry:
570 file_list_lock(); 573 file_list_lock();
571 list_for_each_entry(f, &sb->s_files, f_u.fu_list) { 574 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)) 575 struct vfsmount *mnt;
573 f->f_mode &= ~FMODE_WRITE; 576 if (!S_ISREG(f->f_path.dentry->d_inode->i_mode))
577 continue;
578 if (!file_count(f))
579 continue;
580 if (!(f->f_mode & FMODE_WRITE))
581 continue;
582 f->f_mode &= ~FMODE_WRITE;
583 if (file_check_writeable(f) != 0)
584 continue;
585 file_release_write(f);
586 mnt = mntget(f->f_path.mnt);
587 file_list_unlock();
588 /*
589 * This can sleep, so we can't hold
590 * the file_list_lock() spinlock.
591 */
592 mnt_drop_write(mnt);
593 mntput(mnt);
594 goto retry;
574 } 595 }
575 file_list_unlock(); 596 file_list_unlock();
576} 597}