Commit f51dc7a2 authored by Geert Uytterhoeven's avatar Geert Uytterhoeven Committed by Linus Torvalds

[PATCH] affs remount fixes

AFFS: Fix oops on write after remount (from Roman Zippel):
  - Allocate/free bitmap as necessary
  - Remove last uses of SF_READONLY
Signed-off-by: default avatarGeert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 74325fde
......@@ -458,7 +458,6 @@ affs_error(struct super_block *sb, const char *function, const char *fmt, ...)
if (!(sb->s_flags & MS_RDONLY))
printk(KERN_WARNING "AFFS: Remounting filesystem read-only\n");
sb->s_flags |= MS_RDONLY;
AFFS_SB(sb)->s_flags |= SF_READONLY; /* Don't allow to remount rw */
}
void
......
......@@ -272,8 +272,7 @@ affs_alloc_block(struct inode *inode, u32 goal)
return 0;
}
int
affs_init_bitmap(struct super_block *sb)
int affs_init_bitmap(struct super_block *sb, int *flags)
{
struct affs_bm_info *bm;
struct buffer_head *bmap_bh = NULL, *bh = NULL;
......@@ -282,13 +281,13 @@ affs_init_bitmap(struct super_block *sb)
int i, res = 0;
struct affs_sb_info *sbi = AFFS_SB(sb);
if (sb->s_flags & MS_RDONLY)
if (*flags & MS_RDONLY)
return 0;
if (!AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->bm_flag) {
printk(KERN_NOTICE "AFFS: Bitmap invalid - mounting %s read only\n",
sb->s_id);
sb->s_flags |= MS_RDONLY;
*flags |= MS_RDONLY;
return 0;
}
......@@ -301,7 +300,7 @@ affs_init_bitmap(struct super_block *sb)
bm = sbi->s_bitmap = kmalloc(size, GFP_KERNEL);
if (!sbi->s_bitmap) {
printk(KERN_ERR "AFFS: Bitmap allocation failed\n");
return 1;
return -ENOMEM;
}
memset(sbi->s_bitmap, 0, size);
......@@ -316,13 +315,13 @@ affs_init_bitmap(struct super_block *sb)
bh = affs_bread(sb, bm->bm_key);
if (!bh) {
printk(KERN_ERR "AFFS: Cannot read bitmap\n");
res = 1;
res = -EIO;
goto out;
}
if (affs_checksum_block(sb, bh)) {
printk(KERN_WARNING "AFFS: Bitmap %u invalid - mounting %s read only.\n",
bm->bm_key, sb->s_id);
sb->s_flags |= MS_RDONLY;
*flags |= MS_RDONLY;
goto out;
}
pr_debug("AFFS: read bitmap block %d: %d\n", blk, bm->bm_key);
......@@ -338,7 +337,7 @@ affs_init_bitmap(struct super_block *sb)
bmap_bh = affs_bread(sb, be32_to_cpu(bmap_blk[blk]));
if (!bmap_bh) {
printk(KERN_ERR "AFFS: Cannot read bitmap extension\n");
res = 1;
res = -EIO;
goto out;
}
bmap_blk = (u32 *)bmap_bh->b_data;
......@@ -383,3 +382,17 @@ affs_init_bitmap(struct super_block *sb)
affs_brelse(bmap_bh);
return res;
}
void affs_free_bitmap(struct super_block *sb)
{
struct affs_sb_info *sbi = AFFS_SB(sb);
if (!sbi->s_bitmap)
return;
affs_brelse(sbi->s_bmap_bh);
sbi->s_bmap_bh = NULL;
sbi->s_last_bmap = ~0;
kfree(sbi->s_bitmap);
sbi->s_bitmap = NULL;
}
......@@ -51,10 +51,9 @@ affs_put_super(struct super_block *sb)
mark_buffer_dirty(sbi->s_root_bh);
}
affs_brelse(sbi->s_bmap_bh);
if (sbi->s_prefix)
kfree(sbi->s_prefix);
kfree(sbi->s_bitmap);
affs_free_bitmap(sb);
affs_brelse(sbi->s_root_bh);
kfree(sbi);
sb->s_fs_info = NULL;
......@@ -288,6 +287,7 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
gid_t gid;
int reserved;
unsigned long mount_flags;
int tmp_flags; /* fix remount prototype... */
pr_debug("AFFS: read_super(%s)\n",data ? (const char *)data : "no options");
......@@ -399,7 +399,6 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
printk(KERN_NOTICE "AFFS: Dircache FS - mounting %s read only\n",
sb->s_id);
sb->s_flags |= MS_RDONLY;
sbi->s_flags |= SF_READONLY;
}
switch (chksum) {
case MUFS_FS:
......@@ -455,8 +454,10 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
sbi->s_root_bh = root_bh;
/* N.B. after this point s_root_bh must be released */
if (affs_init_bitmap(sb))
tmp_flags = sb->s_flags;
if (affs_init_bitmap(sb, &tmp_flags))
goto out_error;
sb->s_flags = tmp_flags;
/* set up enough so that it can read an inode */
......@@ -498,7 +499,7 @@ affs_remount(struct super_block *sb, int *flags, char *data)
int reserved;
int root_block;
unsigned long mount_flags;
unsigned long read_only = sbi->s_flags & SF_READONLY;
int res = 0;
pr_debug("AFFS: remount(flags=0x%x,opts=\"%s\")\n",*flags,data);
......@@ -507,7 +508,7 @@ affs_remount(struct super_block *sb, int *flags, char *data)
if (!parse_options(data,&uid,&gid,&mode,&reserved,&root_block,
&blocksize,&sbi->s_prefix,sbi->s_volume,&mount_flags))
return -EINVAL;
sbi->s_flags = mount_flags | read_only;
sbi->s_flags = mount_flags;
sbi->s_mode = mode;
sbi->s_uid = uid;
sbi->s_gid = gid;
......@@ -518,14 +519,11 @@ affs_remount(struct super_block *sb, int *flags, char *data)
sb->s_dirt = 1;
while (sb->s_dirt)
affs_write_super(sb);
sb->s_flags |= MS_RDONLY;
} else if (!(sbi->s_flags & SF_READONLY)) {
sb->s_flags &= ~MS_RDONLY;
} else {
affs_warning(sb,"remount","Cannot remount fs read/write because of errors");
return -EINVAL;
}
return 0;
affs_free_bitmap(sb);
} else
res = affs_init_bitmap(sb, flags);
return res;
}
static int
......
......@@ -36,7 +36,8 @@ extern u32 affs_count_free_bits(u32 blocksize, const void *data);
extern u32 affs_count_free_blocks(struct super_block *s);
extern void affs_free_block(struct super_block *sb, u32 block);
extern u32 affs_alloc_block(struct inode *inode, u32 goal);
extern int affs_init_bitmap(struct super_block *sb);
extern int affs_init_bitmap(struct super_block *sb, int *flags);
extern void affs_free_bitmap(struct super_block *sb);
/* namei.c */
......
......@@ -47,7 +47,6 @@ struct affs_sb_info {
#define SF_OFS 0x0200 /* Old filesystem */
#define SF_PREFIX 0x0400 /* Buffer for prefix is allocated */
#define SF_VERBOSE 0x0800 /* Talk about fs when mounting */
#define SF_READONLY 0x1000 /* Don't allow to remount rw */
/* short cut to get to the affs specific sb data */
static inline struct affs_sb_info *AFFS_SB(struct super_block *sb)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment