]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
mkfs: handle 4k sector devices more cleanly
authorEric Sandeen <sandeen@sandeen.net>
Tue, 12 Jan 2010 16:22:43 +0000 (10:22 -0600)
committerEric Sandeen <sandeen@sandeen.net>
Tue, 12 Jan 2010 16:22:43 +0000 (10:22 -0600)
Trying to mkfs a 4k sector device today fails w/o manually specifying
sector size:

# modprobe scsi_debug sector_size=4096 dev_size_mb=32
# mkfs.xfs -f /dev/sdc
mkfs.xfs: warning - cannot set blocksize on block device /dev/sdc: Invalid argument
Warning: the data subvolume sector size 512 is less than the sector size
reported by the device (4096).
... <fail>

add sectorsize to the device topology info, and use that if present.

Also check that explicitly requested sector sizes are not smaller
than the hardware size.  This already fails today, but with the more
cryptic "cannot set blocksize" ioctl error above.

With a few more suggested comments & cleanups from Christoph.

Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
include/libxfs.h
libxfs/init.h
libxfs/linux.c
mkfs/xfs_mkfs.c

index ab37a60401e266dc1bb314af6e40531abba34ee8..e7199c7b66bb3f1725ce96e24d35e13019b47368 100644 (file)
@@ -115,6 +115,7 @@ extern void libxfs_device_zero (dev_t, xfs_daddr_t, uint);
 extern void    libxfs_device_close (dev_t);
 extern int     libxfs_device_alignment (void);
 extern void    libxfs_report(FILE *);
+extern void    platform_findsizes(char *path, int fd, long long *sz, int *bsz);
 
 /* check or write log footer: specify device, log size in blocks & uuid */
 typedef xfs_caddr_t (libxfs_get_block_t)(xfs_caddr_t, int, void *);
index 1f27af67bad4bc67d4d34b0e9944d62f9c0cff4c..f0b8cb6788398f5f743b13b32b679f6e846c1deb 100644 (file)
@@ -24,7 +24,6 @@ extern int platform_check_ismounted (char *path, char *block,
                                        struct stat64 *sptr, int verbose);
 extern int platform_check_iswritable (char *path, char *block,
                                        struct stat64 *sptr, int fatal);
-extern void platform_findsizes (char *path, int fd, long long *sz, int *bsz);
 extern int platform_set_blocksize (int fd, char *path, dev_t device, int bsz, int fatal);
 extern void platform_flush_device (int fd, dev_t device);
 extern char *platform_findrawpath(char *path);
index bc4990323d805c0f8c9e1739181a6bf86c28327a..2e07d544d9ba8682e3670f796f224dabf2db2080 100644 (file)
@@ -112,9 +112,9 @@ platform_set_blocksize(int fd, char *path, dev_t device, int blocksize, int fata
        if (major(device) != RAMDISK_MAJOR) {
                if ((error = ioctl(fd, BLKBSZSET, &blocksize)) < 0) {
                        fprintf(stderr, _("%s: %s - cannot set blocksize "
-                                       "on block device %s: %s\n"),
+                                       "%d on block device %s: %s\n"),
                                progname, fatal ? "error": "warning",
-                               path, strerror(errno));
+                               blocksize, path, strerror(errno));
                }
        }
        return error;
index d3ed00ae4232fa22b404711bc99678c8f0e8a1d5..9a8eff3487fc4c7d5392a1a0e6f37a0c33e4883e 100644 (file)
@@ -33,6 +33,7 @@ struct fs_topology {
        int     dsunit;         /* stripe unit - data subvolume */
        int     dswidth;        /* stripe width - data subvolume */
        int     rtswidth;       /* stripe width - rt subvolume */
+       int     sectorsize;
        int     sectoralign;
 };
 
@@ -320,7 +321,7 @@ out_free_probe:
        return ret;
 }
 
-static void blkid_get_topology(const char *device, int *sunit, int *swidth)
+static void blkid_get_topology(const char *device, int *sunit, int *swidth, int *sectorsize)
 {
        blkid_topology tp;
        blkid_probe pr;
@@ -348,6 +349,8 @@ static void blkid_get_topology(const char *device, int *sunit, int *swidth)
        val = blkid_topology_get_optimal_io_size(tp) >> 9;
        if (val > 1)
                *swidth = val;
+       val = blkid_probe_get_sectorsize(pr);
+       *sectorsize = val;
 
        if (blkid_topology_get_alignment_offset(tp) != 0) {
                fprintf(stderr,
@@ -370,13 +373,14 @@ static void get_topology(libxfs_init_t *xi, struct fs_topology *ft)
        if (!xi->disfile) {
                const char *dfile = xi->volname ? xi->volname : xi->dname;
 
-               blkid_get_topology(dfile, &ft->dsunit, &ft->dswidth);
+               blkid_get_topology(dfile, &ft->dsunit, &ft->dswidth,
+                                  &ft->sectorsize);
        }
 
        if (xi->rtname && !xi->risfile) {
                int dummy;
 
-               blkid_get_topology(xi->rtname, &dummy, &ft->rtswidth);
+               blkid_get_topology(xi->rtname, &dummy, &ft->rtswidth, &dummy);
        }
 }
 #else /* ENABLE_BLKID */
@@ -406,12 +410,24 @@ check_overwrite(
 static void get_topology(libxfs_init_t *xi, struct fs_topology *ft)
 {
        char *dfile = xi->volname ? xi->volname : xi->dname;
+       int bsz = BBSIZE;
 
        if (!xi->disfile) {
+               int fd;
+               long long dummy;
+
                get_subvol_stripe_wrapper(dfile, SVTYPE_DATA,
                                &ft->dsunit, &ft->dswidth, &ft->sectoralign);
+               fd = open(dfile, O_RDONLY);
+               /* If this fails we just fall back to BBSIZE */
+               if (fd) {
+                       platform_findsizes(dfile, fd, &dummy, &bsz);
+                       close(fd);
+               }
        }
 
+       ft->sectorsize = bsz;
+
        if (xi->rtname && !xi->risfile) {
                int dummy1;
 
@@ -1544,18 +1560,41 @@ main(
        get_topology(&xi, &ft);
 
        if (ft.sectoralign) {
+               /*
+                * Older Linux software RAID versions want the sector size
+                * to match the block size to avoid switching I/O sizes.
+                * For the legacy libdisk case we thus set the sector size to
+                * match the block size.  For systems using libblkid we assume
+                * that the kernel is recent enough to not require this and
+                * ft.sectoralign will never be set.
+                */
                sectorsize = blocksize;
+       } else if (!ssflag) {
+               /*
+                * Unless specified manually on the command line use the
+                * advertised sector size of the device.
+                */
+               sectorsize = ft.sectorsize;
+       }
+
+       if (ft.sectoralign || !ssflag) {
                sectorlog = libxfs_highbit32(sectorsize);
                if (loginternal) {
                        lsectorsize = sectorsize;
                        lsectorlog = sectorlog;
                }
        }
+
        if (sectorsize < XFS_MIN_SECTORSIZE ||
            sectorsize > XFS_MAX_SECTORSIZE || sectorsize > blocksize) {
                fprintf(stderr, _("illegal sector size %d\n"), sectorsize);
                usage();
        }
+       if (sectorsize < ft.sectorsize) {
+               fprintf(stderr, _("illegal sector size %d; hw sector is %d\n"),
+                       sectorsize, ft.sectorsize);
+               usage();
+       }
        if (lsectorsize < XFS_MIN_SECTORSIZE ||
            lsectorsize > XFS_MAX_SECTORSIZE || lsectorsize > blocksize) {
                fprintf(stderr, _("illegal log sector size %d\n"), lsectorsize);
@@ -1749,10 +1788,7 @@ main(
        calc_stripe_factors(dsu, dsw, sectorsize, lsu, lsectorsize,
                                &dsunit, &dswidth, &lsunit);
 
-       if (slflag || ssflag)
-               xi.setblksize = sectorsize;
-       else
-               xi.setblksize = 1;
+       xi.setblksize = sectorsize;
 
        /*
         * Initialize.  This will open the log and rt devices as well.