diff options
author | Theodore Ts'o <tytso@mit.edu> | 2007-06-04 01:14:52 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2007-06-04 01:14:52 -0400 |
commit | d2af1bdd0526603b762c875630e82e0dd9eff059 (patch) | |
tree | 4aee4eaa6f78a591705d5d4a4b3e2ba6166fd1bb | |
parent | a2b2ff61c88ac7583f288a1723d8195a0b7f2f83 (diff) | |
download | e2fsprogs-d2af1bdd0526603b762c875630e82e0dd9eff059.tar.gz |
Fix e2fsck's get_size logic so it will work with the Linux floppy driver
The Linux floppy driver is a bit different from the other block device
drivers, in that if the device has been opened with O_EXCL, it disallows
another open(), even if the second open() does not have the O_EXCL flag.
So this patch moves the call to ext2fs_get_device_size() so that if it
returns EBUSY, e2fsck can close the filesystem, retry the device size,
and then reopen it. This rather complicated approach is required since
we need to know the blocksize of the filesystem before we can call
ext2fs_get_device_size().
Addresses Debian Bug: #410569
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-rw-r--r-- | e2fsck/ChangeLog | 10 | ||||
-rw-r--r-- | e2fsck/e2fsck.h | 2 | ||||
-rw-r--r-- | e2fsck/super.c | 31 | ||||
-rw-r--r-- | e2fsck/unix.c | 36 |
4 files changed, 52 insertions, 27 deletions
diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog index a6df3618..fa40d282 100644 --- a/e2fsck/ChangeLog +++ b/e2fsck/ChangeLog @@ -1,3 +1,13 @@ +2007-06-04 Theodore Tso <tytso@mit.edu> + + * super.c (check_super_block, e2fsck_get_device_size), + unix.c (main): Move device size logic into the main(), to + support the Linux floppy driver, which disallows another + (non-O_EXCL) open() if it has been opened with O_EXCL. + (Addresses Debian Bug: #410569) + + * e2fsck.h (E2F_FLAG_GOT_DEVSIZE): New flag used in get_device logic + 2007-05-31 Theodore Tso <tytso@mit.edu> * util.c (get_backup_sb): Do basic sanity checking to make sure diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h index ae337907..96b83dab 100644 --- a/e2fsck/e2fsck.h +++ b/e2fsck/e2fsck.h @@ -170,6 +170,7 @@ struct resource_track { * specified by the user */ #define E2F_FLAG_RESTARTED 0x0200 /* E2fsck has been restarted */ #define E2F_FLAG_RESIZE_INODE 0x0400 /* Request to recreate resize inode */ +#define E2F_FLAG_GOT_DEVSIZE 0x0800 /* Device size has been fetched */ /* * Defines for indicating the e2fsck pass number @@ -452,7 +453,6 @@ void e2fsck_rehash_directories(e2fsck_t ctx); /* super.c */ void check_super_block(e2fsck_t ctx); -errcode_t e2fsck_get_device_size(e2fsck_t ctx); /* swapfs.c */ void swap_filesys(e2fsck_t ctx); diff --git a/e2fsck/super.c b/e2fsck/super.c index 8d4f0694..00a131ce 100644 --- a/e2fsck/super.c +++ b/e2fsck/super.c @@ -39,19 +39,6 @@ static void check_super_value(e2fsck_t ctx, const char *descr, } /* - * This routine may get stubbed out in special compilations of the - * e2fsck code.. - */ -#ifndef EXT2_SPECIAL_DEVICE_SIZE -errcode_t e2fsck_get_device_size(e2fsck_t ctx) -{ - return (ext2fs_get_device_size(ctx->filesystem_name, - EXT2_BLOCK_SIZE(ctx->fs->super), - &ctx->num_blocks)); -} -#endif - -/* * helper function to release an inode */ struct process_block_struct { @@ -536,22 +523,14 @@ void check_super_block(e2fsck_t ctx) return; } - if (!ctx->num_blocks) { - pctx.errcode = e2fsck_get_device_size(ctx); - if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) { - fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx); + if ((ctx->flags & E2F_FLAG_GOT_DEVSIZE) && + (ctx->num_blocks < sb->s_blocks_count)) { + pctx.blk = sb->s_blocks_count; + pctx.blk2 = ctx->num_blocks; + if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) { ctx->flags |= E2F_FLAG_ABORT; return; } - if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) && - (ctx->num_blocks < sb->s_blocks_count)) { - pctx.blk = sb->s_blocks_count; - pctx.blk2 = ctx->num_blocks; - if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) { - ctx->flags |= E2F_FLAG_ABORT; - return; - } - } } if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) { diff --git a/e2fsck/unix.c b/e2fsck/unix.c index 7631c147..79578944 100644 --- a/e2fsck/unix.c +++ b/e2fsck/unix.c @@ -981,6 +981,42 @@ restart: fix_problem(ctx, PR_0_SB_CORRUPT, &pctx); fatal_error(ctx, 0); } + + if (!(ctx->flags & E2F_FLAG_GOT_DEVSIZE)) { + __u32 blocksize = EXT2_BLOCK_SIZE(fs->super); + int need_restart = 0; + + pctx.errcode = ext2fs_get_device_size(ctx->filesystem_name, + blocksize, + &ctx->num_blocks); + /* + * The floppy driver refuses to allow anyone else to + * open the device if has been opened with O_EXCL; + * this is unlike other block device drivers in Linux. + * To handle this, we close the filesystem and then + * reopen the filesystem after we get the device size. + */ + if (pctx.errcode == EBUSY) { + ext2fs_close(fs); + need_restart++; + pctx.errcode = + ext2fs_get_device_size(ctx->filesystem_name, + blocksize, + &ctx->num_blocks); + } + if (pctx.errcode == EXT2_ET_UNIMPLEMENTED) + ctx->num_blocks = 0; + else if (pctx.errcode) { + fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + fatal_error(ctx, 0); + return; + } + ctx->flags |= E2F_FLAG_GOT_DEVSIZE; + if (need_restart) + goto restart; + } + ctx->fs = fs; fs->priv_data = ctx; fs->now = ctx->now; |