From 466341bae2c891e86c0e2d4c64a890e51b158c1c Mon Sep 17 00:00:00 2001 From: Alexander Viro <viro@www.linux.org.uk> Date: Fri, 16 Apr 2004 00:26:34 -0700 Subject: [PATCH] [PATCH] remount: fs/sysv fixes - several variants of sysv fs are supported only r/o. Driver does force r/o on mount, but doesn't do anything on remount. As the result, one can remount them r/w and results are Not Pretty(tm). Missing checks added, code cleaned up. - we had double-brelse() in v7fs - if sanity checks on root inode will succeed, but allocation of root dentry fails, we brelse() the same buffer_head twice. Fixed. --- fs/sysv/inode.c | 11 +++++++++++ fs/sysv/super.c | 8 +++++--- fs/sysv/sysv.h | 1 + 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index 09c131fbb36f..379d42408f53 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -57,6 +57,16 @@ static void sysv_write_super(struct super_block *sb) unlock_kernel(); } +static int sysv_remount(struct super_block *sb, int *flags, char *data) +{ + struct sysv_sb_info *sbi = SYSV_SB(sb); + if (sbi->s_forced_ro) + *flags |= MS_RDONLY; + if (!(*flags & MS_RDONLY)) + sb->s_dirt = 1; + return 0; +} + static void sysv_put_super(struct super_block *sb) { struct sysv_sb_info *sbi = SYSV_SB(sb); @@ -321,6 +331,7 @@ struct super_operations sysv_sops = { .delete_inode = sysv_delete_inode, .put_super = sysv_put_super, .write_super = sysv_write_super, + .remount_fs = sysv_remount, .statfs = sysv_statfs, }; diff --git a/fs/sysv/super.c b/fs/sysv/super.c index baf3157204b3..f0e99fc617cc 100644 --- a/fs/sysv/super.c +++ b/fs/sysv/super.c @@ -206,11 +206,11 @@ static int detect_sysv(struct sysv_sb_info *sbi, struct buffer_head *bh) if (fs16_to_cpu(sbi, sbd->s_nfree) == 0xffff) { sbi->s_type = FSTYPE_AFS; + sbi->s_forced_ro = 1; if (!(sb->s_flags & MS_RDONLY)) { printk("SysV FS: SCO EAFS on %s detected, " "forcing read-only mode.\n", sb->s_id); - sb->s_flags |= MS_RDONLY; } return sbd->s_type; } @@ -234,7 +234,7 @@ static int detect_sysv(struct sysv_sb_info *sbi, struct buffer_head *bh) if (sbd->s_type >= 0x10) { printk("SysV FS: can't handle long file names on %s, " "forcing read-only mode.\n", sb->s_id); - sb->s_flags |= MS_RDONLY; + sbi->s_forced_ro = 1; } sbi->s_type = FSTYPE_SYSV4; @@ -335,9 +335,10 @@ static int complete_read_super(struct super_block *sb, int silent, int size) printk("SysV FS: get root dentry failed\n"); return 0; } + if (sbi->s_forced_ro) + sb->s_flags |= MS_RDONLY; if (sbi->s_truncate) sb->s_root->d_op = &sysv_dentry_operations; - sb->s_flags |= MS_RDONLY; sb->s_dirt = 1; return 1; } @@ -481,6 +482,7 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent) (fs32_to_cpu(sbi, v7i->i_size) & 017) != 0) goto failed; brelse(bh2); + bh2 = NULL; sbi->s_bh1 = bh; sbi->s_bh2 = bh; diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h index f759717bd018..493b0a6a4f0e 100644 --- a/fs/sysv/sysv.h +++ b/fs/sysv/sysv.h @@ -54,6 +54,7 @@ struct sysv_sb_info { u32 s_ndatazones; /* total number of data zones */ u32 s_nzones; /* same as s_sbd->s_fsize */ u16 s_namelen; /* max length of dir entry */ + int s_forced_ro; }; /* -- 2.30.9