X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=fs%2Fsuper.c;h=4798350b2bc9dc6c294fe47e91a9ed27c52b7dd3;hb=cdf8803768db6f652d498628fe1421a23c025253;hp=dc02af0302fe68609d2de842c2394a677af7a642;hpb=8a4e98d9d758d0eb751916e906fae40bda151b11;p=safe%2Fjmp%2Flinux-2.6 diff --git a/fs/super.c b/fs/super.c index dc02af0..4798350 100644 --- a/fs/super.c +++ b/fs/super.c @@ -37,7 +37,9 @@ #include #include #include +#include #include +#include "internal.h" LIST_HEAD(super_blocks); @@ -556,21 +558,40 @@ out: } /** - * mark_files_ro + * mark_files_ro - mark all files read-only * @sb: superblock in question * - * All files are marked read/only. We don't care about pending - * delete files so this should be used in 'force' mode only + * All files are marked read-only. We don't care about pending + * delete files so this should be used in 'force' mode only. */ static void mark_files_ro(struct super_block *sb) { struct file *f; +retry: file_list_lock(); list_for_each_entry(f, &sb->s_files, f_u.fu_list) { - if (S_ISREG(f->f_path.dentry->d_inode->i_mode) && file_count(f)) - f->f_mode &= ~FMODE_WRITE; + struct vfsmount *mnt; + if (!S_ISREG(f->f_path.dentry->d_inode->i_mode)) + continue; + if (!file_count(f)) + continue; + if (!(f->f_mode & FMODE_WRITE)) + continue; + f->f_mode &= ~FMODE_WRITE; + if (file_check_writeable(f) != 0) + continue; + file_release_write(f); + mnt = mntget(f->f_path.mnt); + file_list_unlock(); + /* + * This can sleep, so we can't hold + * the file_list_lock() spinlock. + */ + mnt_drop_write(mnt); + mntput(mnt); + goto retry; } file_list_unlock(); }