OSDN Git Service

mke2fs: account for physical as well as logical sector size
authorTheodore Ts'o <tytso@mit.edu>
Tue, 18 May 2010 02:31:45 +0000 (22:31 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 18 May 2010 03:04:40 +0000 (23:04 -0400)
Some devices, notably 4k sector drives, may have a 512 logical
sector size, mapped onto a 4k physical sector size.

When mke2fs is ratcheting down the blocksize for small filesystems,
or when a blocksize is specified on the commandline, we should not
willingly go below the physical sector size of the device.

When a blocksize is specified, we -must- not go below
the logical sector size of the device.

Add a new library function, ext2fs_get_device_phys_sectsize()
to get the physical sector size if possible, and adjust the
logic in mke2fs to enforce the above rules.

Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
debian/e2fslibs.symbols
lib/ext2fs/ext2fs.h
lib/ext2fs/getsectsize.c
lib/ext2fs/tst_getsectsize.c
misc/mke2fs.c

index c203f02..c5a6a0b 100644 (file)
@@ -163,6 +163,7 @@ libext2fs.so.2 e2fslibs #MINVER#
  ext2fs_get_blocks@Base 1.37
  ext2fs_get_data_io@Base 1.37
  ext2fs_get_device_sectsize@Base 1.37
+ ext2fs_get_device_phys_sectsize@Base 1.41.12
  ext2fs_get_device_size2@Base 1.41.4
  ext2fs_get_device_size@Base 1.37
  ext2fs_get_free_blocks@Base 1.37
index a3d3cd3..2674941 100644 (file)
@@ -942,6 +942,7 @@ extern errcode_t ext2fs_get_device_size2(const char *file, int blocksize,
 
 /* getsectsize.c */
 errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize);
+errcode_t ext2fs_get_device_phys_sectsize(const char *file, int *sectsize);
 
 /* i_block.c */
 errcode_t ext2fs_iblk_add_blocks(ext2_filsys fs, struct ext2_inode *inode,
index 09fb45c..64f42a6 100644 (file)
 #include <linux/fd.h>
 #endif
 
-#if defined(__linux__) && defined(_IO) && !defined(BLKSSZGET)
+#if defined(__linux__) && defined(_IO)
+#if !defined(BLKSSZGET)
 #define BLKSSZGET  _IO(0x12,104)/* get block device sector size */
 #endif
+#if !defined(BLKPBSZGET)
+#define BLKPBSZGET _IO(0x12,123)/* get block physical sector size */
+#endif
+#endif
 
 #include "ext2_fs.h"
 #include "ext2fs.h"
 
 /*
- * Returns the number of blocks in a partition
+ * Returns the logical sector size of a device
  */
 errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize)
 {
@@ -58,3 +63,29 @@ errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize)
        close(fd);
        return 0;
 }
+
+/*
+ * Returns the physical sector size of a device
+ */
+errcode_t ext2fs_get_device_phys_sectsize(const char *file, int *sectsize)
+{
+       int     fd;
+
+#ifdef HAVE_OPEN64
+       fd = open64(file, O_RDONLY);
+#else
+       fd = open(file, O_RDONLY);
+#endif
+       if (fd < 0)
+               return errno;
+
+#ifdef BLKPBSZGET
+       if (ioctl(fd, BLKPBSZGET, sectsize) >= 0) {
+               close(fd);
+               return 0;
+       }
+#endif
+       *sectsize = 0;
+       close(fd);
+       return 0;
+}
index 863cf64..5591b5d 100644 (file)
@@ -27,7 +27,7 @@
 
 int main(int argc, char **argv)
 {
-       int     sectsize;
+       int     lsectsize, psectsize;
        int     retval;
 
        if (argc < 2) {
@@ -35,13 +35,19 @@ int main(int argc, char **argv)
                exit(1);
        }
 
-       retval = ext2fs_get_device_sectsize(argv[1], &sectsize);
+       retval = ext2fs_get_device_sectsize(argv[1], &lsectsize);
        if (retval) {
                com_err(argv[0], retval,
                        "while calling ext2fs_get_device_sectsize");
                exit(1);
        }
-       printf("Device %s has a hardware sector size of %d.\n",
-              argv[1], sectsize);
+       retval = ext2fs_get_device_phys_sectsize(argv[1], &psectsize);
+       if (retval) {
+               com_err(argv[0], retval,
+                       "while calling ext2fs_get_device_phys_sectsize");
+               exit(1);
+       }
+       printf("Device %s has logical/physical sector size of %d/%d.\n",
+              argv[1], lsectsize, psectsize);
        exit(0);
 }
index 5843ed4..ac87b8e 100644 (file)
@@ -1130,7 +1130,7 @@ static void PRS(int argc, char *argv[])
        int             inode_size = 0;
        unsigned long   flex_bg_size = 0;
        double          reserved_ratio = 5.0;
-       int             sector_size = 0;
+       int             lsector_size = 0, psector_size = 0;
        int             show_version_only = 0;
        unsigned long long num_inodes = 0; /* unsigned long long to catch too-large input */
        errcode_t       retval;
@@ -1645,16 +1645,25 @@ got_size:
            ((tmp = getenv("MKE2FS_FIRST_META_BG"))))
                fs_param.s_first_meta_bg = atoi(tmp);
 
-       /* Get the hardware sector size, if available */
-       retval = ext2fs_get_device_sectsize(device_name, &sector_size);
+       /* Get the hardware sector sizes, if available */
+       retval = ext2fs_get_device_sectsize(device_name, &lsector_size);
        if (retval) {
                com_err(program_name, retval,
                        _("while trying to determine hardware sector size"));
                exit(1);
        }
+       retval = ext2fs_get_device_phys_sectsize(device_name, &psector_size);
+       if (retval) {
+               com_err(program_name, retval,
+                       _("while trying to determine physical sector size"));
+               exit(1);
+       }
+       /* Older kernels may not have physical/logical distinction */
+       if (!psector_size)
+               psector_size = lsector_size;
 
        if ((tmp = getenv("MKE2FS_DEVICE_SECTSIZE")) != NULL)
-               sector_size = atoi(tmp);
+               psector_size = atoi(tmp);
 
        if (blocksize <= 0) {
                use_bsize = get_int_from_profile(fs_types, "blocksize", 4096);
@@ -1665,12 +1674,25 @@ got_size:
                            (use_bsize > 4096))
                                use_bsize = 4096;
                }
-               if (sector_size && use_bsize < sector_size)
-                       use_bsize = sector_size;
+               if (psector_size && use_bsize < psector_size)
+                       use_bsize = psector_size;
                if ((blocksize < 0) && (use_bsize < (-blocksize)))
                        use_bsize = -blocksize;
                blocksize = use_bsize;
                fs_param.s_blocks_count /= blocksize / 1024;
+       } else {
+               if (blocksize < lsector_size ||                 /* Impossible */
+                   (!force && (blocksize < psector_size))) {   /* Suboptimal */
+                       com_err(program_name, EINVAL,
+                               _("while setting blocksize; too small "
+                                 "for device\n"));
+                       exit(1);
+               } else if (blocksize < psector_size) {
+                       fprintf(stderr, _("Warning: specified blocksize %d is "
+                               "less than device physical sectorsize %d, "
+                               "forced to continue\n"), blocksize,
+                               psector_size);
+               }
        }
 
        if (inode_ratio == 0) {