+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
* 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
/* 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);
}
/*
- * 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 {
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) {
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;