Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP5:Update
xfsprogs.21270
xfsprogs-mkfs-don-t-treat-files-as-though-they-...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File xfsprogs-mkfs-don-t-treat-files-as-though-they-are-block-devi.patch of Package xfsprogs.21270
From 06ac92fdf8571ea10a3df64c7456eace03cf14c3 Mon Sep 17 00:00:00 2001 From: Dave Chinner <dchinner@redhat.com> Date: Tue, 10 May 2016 17:16:07 +1000 Subject: [PATCH] mkfs: don't treat files as though they are block devices Git-commit: 06ac92fdf8571ea10a3df64c7456eace03cf14c3 Patch-mainline: v4.7.0-rc1 References: bsc#1186054 If the device is actually a file, and "-d file" is not specified, mkfs will try to treat it as a block device and get stuff wrong. Image files don't necessarily have the same sector sizes as the block device or filesystem underlying the image file, nor should we be issuing discard ioctls on image files. To fix this sanely, only require "-d file" if the device name is invalid to trigger creation of the file. Otherwise, use stat() to determine if the device is a file or block device and deal with that appropriately by setting the "isfile" variables and turning off direct IO. Then ensure that we check the "isfile" options before doing things that are specific to block devices. Other file/blockdev issues fixed: - use getstr to detect specifying the data device name twice. - check file/size/name parameters before anything else. - overwrite checks need to be done before the image file is opened and potentially truncated. - blkid_get_topology() should not be called for image files, so warn when it is called that way. - zero_old_xfs_structures() emits a spurious error: "existing superblock read failed: Success" when it is run on a truncated image file. Don't warn if we see this problem on an image file. - Don't issue discards on image files. - Use fsync() for image files, not BLKFLSBUF in platform_flush_device() for Linux. [ Eric Sandeen <sandeen@redhat.com>: move check for no mkfs target, other minor fixes. ] Signed-off-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Jan Tulak <jtulak@redhat.com> Reviewed-by: Eric Sandeen <sandeen@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com> Acked-by: Anthony Iliopoulos <ailiop@suse.com> --- libxfs/init.c | 16 +++-- libxfs/linux.c | 11 ++- mkfs/xfs_mkfs.c | 183 +++++++++++++++++++++++++++++++++--------------- 3 files changed, 149 insertions(+), 61 deletions(-) diff --git a/libxfs/init.c b/libxfs/init.c index c7f9dc8bd9e6..79944b6a8972 100644 --- a/libxfs/init.c +++ b/libxfs/init.c @@ -253,8 +253,8 @@ libxfs_init(libxfs_init_t *a) rtname = a->rtname; a->dfd = a->logfd = a->rtfd = -1; a->ddev = a->logdev = a->rtdev = 0; - a->dbsize = a->lbsize = a->rtbsize = 0; - a->dsize = a->logBBsize = a->logBBstart = a->rtsize = 0; + a->dsize = a->lbsize = a->rtbsize = 0; + a->dbsize = a->logBBsize = a->logBBstart = a->rtsize = 0; (void)getcwd(curdir,MAXPATHLEN); needcd = 0; @@ -278,6 +278,8 @@ libxfs_init(libxfs_init_t *a) a->ddev= libxfs_device_open(dname, a->dcreat, flags, a->setblksize); a->dfd = libxfs_device_to_fd(a->ddev); + platform_findsizes(dname, a->dfd, &a->dsize, + &a->dbsize); } else { if (!check_open(dname, flags, &rawfile, &blockfile)) goto done; @@ -285,7 +287,7 @@ libxfs_init(libxfs_init_t *a) a->dcreat, flags, a->setblksize); a->dfd = libxfs_device_to_fd(a->ddev); platform_findsizes(rawfile, a->dfd, - &a->dsize, &a->dbsize); + &a->dsize, &a->dbsize); } needcd = 1; } else @@ -297,6 +299,8 @@ libxfs_init(libxfs_init_t *a) a->logdev = libxfs_device_open(logname, a->lcreat, flags, a->setblksize); a->logfd = libxfs_device_to_fd(a->logdev); + platform_findsizes(dname, a->logfd, &a->logBBsize, + &a->lbsize); } else { if (!check_open(logname, flags, &rawfile, &blockfile)) goto done; @@ -304,7 +308,7 @@ libxfs_init(libxfs_init_t *a) a->lcreat, flags, a->setblksize); a->logfd = libxfs_device_to_fd(a->logdev); platform_findsizes(rawfile, a->logfd, - &a->logBBsize, &a->lbsize); + &a->logBBsize, &a->lbsize); } needcd = 1; } else @@ -316,6 +320,8 @@ libxfs_init(libxfs_init_t *a) a->rtdev = libxfs_device_open(rtname, a->rcreat, flags, a->setblksize); a->rtfd = libxfs_device_to_fd(a->rtdev); + platform_findsizes(dname, a->rtfd, &a->rtsize, + &a->rtbsize); } else { if (!check_open(rtname, flags, &rawfile, &blockfile)) goto done; @@ -323,7 +329,7 @@ libxfs_init(libxfs_init_t *a) a->rcreat, flags, a->setblksize); a->rtfd = libxfs_device_to_fd(a->rtdev); platform_findsizes(rawfile, a->rtfd, - &a->rtsize, &a->rtbsize); + &a->rtsize, &a->rtbsize); } needcd = 1; } else diff --git a/libxfs/linux.c b/libxfs/linux.c index 885016a01673..49d430c73242 100644 --- a/libxfs/linux.c +++ b/libxfs/linux.c @@ -125,7 +125,16 @@ platform_set_blocksize(int fd, char *path, dev_t device, int blocksize, int fata void platform_flush_device(int fd, dev_t device) { - if (major(device) != RAMDISK_MAJOR) + struct stat64 st; + if (major(device) == RAMDISK_MAJOR) + return; + + if (fstat64(fd, &st) < 0) + return; + + if (S_ISREG(st.st_mode)) + fsync(fd); + else ioctl(fd, BLKFLSBUF, 0); } diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 7cba41a69dcb..8030472759ec 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -305,7 +305,7 @@ calc_stripe_factors( #ifdef ENABLE_BLKID static int check_overwrite( - char *device) + const char *device) { const char *type; blkid_probe pr = NULL; @@ -322,7 +322,7 @@ check_overwrite( fd = open(device, O_RDONLY); if (fd < 0) goto out; - platform_findsizes(device, fd, &size, &bsz); + platform_findsizes((char *)device, fd, &size, &bsz); close(fd); /* nothing to overwrite on a 0-length device */ @@ -369,7 +369,6 @@ check_overwrite( "according to blkid\n"), progname, device); } ret = 1; - out: if (pr) blkid_free_probe(pr); @@ -395,8 +394,12 @@ static void blkid_get_topology( struct stat statbuf; /* can't get topology info from a file */ - if (!stat(device, &statbuf) && S_ISREG(statbuf.st_mode)) + if (!stat(device, &statbuf) && S_ISREG(statbuf.st_mode)) { + fprintf(stderr, + _("%s: Warning: trying to probe topology of a file %s!\n"), + progname, device); return; + } pr = blkid_new_probe_from_filename(device); if (!pr) @@ -466,7 +469,7 @@ out_free_probe: access are not working! static int check_overwrite( - char *device) + const char *device) { return 1; } @@ -533,6 +536,80 @@ static void get_topology( } } +static void +check_device_type( + const char *name, + int *isfile, + bool no_size, + bool no_name, + int *create, + bool force_overwrite, + const char *optname) +{ + struct stat64 statbuf; + + if (*isfile && (no_size || no_name)) { + fprintf(stderr, + _("if -%s file then -%s name and -%s size are required\n"), + optname, optname, optname); + usage(); + } + + if (!name) { + fprintf(stderr, _("No device name specified\n")); + usage(); + } + + if (stat64(name, &statbuf)) { + if (errno == ENOENT && *isfile) { + if (create) + *create = 1; + return; + } + + fprintf(stderr, + _("Error accessing specified device %s: %s\n"), + name, strerror(errno)); + usage(); + return; + } + + if (!force_overwrite && check_overwrite(name)) { + fprintf(stderr, + _("%s: Use the -f option to force overwrite.\n"), + progname); + exit(1); + } + + /* + * We only want to completely truncate and recreate an existing file if + * we were specifically told it was a file. Set the create flag only in + * this case to trigger that behaviour. + */ + if (S_ISREG(statbuf.st_mode)) { + if (!*isfile) + *isfile = 1; + else if (create) + *create = 1; + return; + } + + if (S_ISBLK(statbuf.st_mode)) { + if (*isfile) { + fprintf(stderr, + _("specified \"-%s file\" on a block device %s\n"), + optname, name); + usage(); + } + return; + } + + fprintf(stderr, + _("specified device %s not a file or block device\n"), + name); + usage(); +} + static void fixup_log_stripe_unit( int lsflag, @@ -795,7 +872,6 @@ zero_old_xfs_structures( __uint32_t bsize; int i; xfs_off_t off; - int tmp; /* * We open regular files with O_TRUNC|O_CREAT. Nothing to do here... @@ -815,15 +891,18 @@ zero_old_xfs_structures( } memset(buf, 0, new_sb->sb_sectsize); - tmp = pread(xi->dfd, buf, new_sb->sb_sectsize, 0); - if (tmp < 0) { - fprintf(stderr, _("existing superblock read failed: %s\n"), - strerror(errno)); - goto done; - } - if (tmp != new_sb->sb_sectsize) { - fprintf(stderr, - _("warning: could not read existing superblock, skip zeroing\n")); + /* + * If we are creating an image file, it might be of zero length at this + * point in time. Hence reading the existing superblock is going to + * return zero bytes. It's not a failure we need to warn about in this + * case. + */ + off = pread(xi->dfd, buf, new_sb->sb_sectsize, 0); + if (off != new_sb->sb_sectsize) { + if (!xi->disfile) + fprintf(stderr, + _("error reading existing superblock: %s\n"), + strerror(errno)); goto done; } libxfs_sb_from_disk(&sb, buf); @@ -1107,8 +1186,6 @@ main( xi.disfile = atoi(value); if (xi.disfile < 0 || xi.disfile > 1) illegal(value, "d file"); - if (xi.disfile && !Nflag) - xi.dcreat = 1; break; case D_NAME: if (!value || *value == '\0') @@ -1380,8 +1457,6 @@ main( xi.lisfile = atoi(value); if (xi.lisfile < 0 || xi.lisfile > 1) illegal(value, "l file"); - if (xi.lisfile) - xi.lcreat = 1; break; case L_INTERNAL: if (!value || *value == '\0') @@ -1635,8 +1710,6 @@ main( xi.risfile = atoi(value); if (xi.risfile < 0 || xi.risfile > 1) illegal(value, "r file"); - if (xi.risfile) - xi.rcreat = 1; break; case R_NAME: case R_DEV: @@ -1754,6 +1827,26 @@ _("Minimum block size for CRC enabled filesystems is %d bytes.\n"), usage(); } + /* + * Before anything else, verify that we are correctly operating on + * files or block devices and set the control parameters correctly. + * Explicitly disable direct IO for image files so we don't error out on + * sector size mismatches between the new filesystem and the underlying + * host filesystem. + */ + check_device_type(dfile, &xi.disfile, !dsize, !dfile, + Nflag ? NULL : &xi.dcreat, force_overwrite, "d"); + if (!loginternal) + check_device_type(xi.logname, &xi.lisfile, !logsize, !xi.logname, + Nflag ? NULL : &xi.lcreat, + force_overwrite, "l"); + if (xi.rtname) + check_device_type(xi.rtname, &xi.risfile, !rtsize, !xi.rtname, + Nflag ? NULL : &xi.rcreat, + force_overwrite, "r"); + if (xi.disfile || xi.lisfile || xi.risfile) + xi.isdirect = 0; + memset(&ft, 0, sizeof(ft)); get_topology(&xi, &ft, force_overwrite); @@ -1909,11 +2002,6 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n")); usage(); } - if (xi.disfile && (!dsize || !xi.dname)) { - fprintf(stderr, - _("if -d file then -d name and -d size are required\n")); - usage(); - } if (dsize) { __uint64_t dbytes; @@ -1946,11 +2034,6 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n")); usage(); } - if (xi.lisfile && (!logsize || !xi.logname)) { - fprintf(stderr, - _("if -l file then -l name and -l size are required\n")); - usage(); - } if (logsize) { __uint64_t logbytes; @@ -1968,11 +2051,6 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n")); (long long)logbytes, blocksize, (long long)(logblocks << blocklog)); } - if (xi.risfile && (!rtsize || !xi.rtname)) { - fprintf(stderr, - _("if -r file then -r name and -r size are required\n")); - usage(); - } if (rtsize) { __uint64_t rtbytes; @@ -2106,22 +2184,14 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n")); xi.rtsize &= sector_mask; xi.logBBsize &= (__uint64_t)-1 << (MAX(lsectorlog, 10) - BBSHIFT); - if (!force_overwrite) { - if (check_overwrite(dfile) || - check_overwrite(logfile) || - check_overwrite(xi.rtname)) { - fprintf(stderr, - _("%s: Use the -f option to force overwrite.\n"), - progname); - exit(1); - } - } + /* don't do discards on print-only runs or on files */ if (discard && !Nflag) { - discard_blocks(xi.ddev, xi.dsize); - if (xi.rtdev) + if (!xi.disfile) + discard_blocks(xi.ddev, xi.dsize); + if (xi.rtdev && !xi.risfile) discard_blocks(xi.rtdev, xi.rtsize); - if (xi.logdev && xi.logdev != xi.ddev) + if (xi.logdev && xi.logdev != xi.ddev && !xi.lisfile) discard_blocks(xi.logdev, xi.logBBsize); } @@ -2684,13 +2754,16 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), /* * If the data area is a file, then grow it out to its final size - * so that the reads for the end of the device in the mount code - * will succeed. + * if needed so that the reads for the end of the device in the mount + * code will succeed. */ - if (xi.disfile && ftruncate64(xi.dfd, dblocks * blocksize) < 0) { - fprintf(stderr, _("%s: Growing the data section failed\n"), - progname); - exit(1); + if (xi.disfile && xi.dsize * xi.dbsize < dblocks * blocksize) { + if (ftruncate64(xi.dfd, dblocks * blocksize) < 0) { + fprintf(stderr, + _("%s: Growing the data section failed\n"), + progname); + exit(1); + } } /* -- 2.33.0
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor