Move general topology functions from xfs_mkfs to new topology collection in libxcmd. Signed-off-by: Bill O'Donnell <billodo@xxxxxxxxxx> --- include/Makefile | 1 + include/libxcmd.h | 55 +++++++++ libxcmd/Makefile | 2 +- libxcmd/topology.c | 348 +++++++++++++++++++++++++++++++++++++++++++++++++++++ mkfs/Makefile | 2 +- mkfs/xfs_mkfs.c | 321 +----------------------------------------------- 6 files changed, 407 insertions(+), 322 deletions(-) create mode 100644 include/libxcmd.h create mode 100644 libxcmd/topology.c diff --git a/include/Makefile b/include/Makefile index 6148756..2671f07 100644 --- a/include/Makefile +++ b/include/Makefile @@ -20,6 +20,7 @@ include $(TOPDIR)/include/builddefs LIBHFILES = libxfs.h \ libxlog.h \ + libxcmd.h \ atomic.h \ bitops.h \ cache.h \ diff --git a/include/libxcmd.h b/include/libxcmd.h new file mode 100644 index 0000000..df7046e --- /dev/null +++ b/include/libxcmd.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2000-2005 Silicon Graphics, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __LIBXCMD_H__ +#define __LIBXCMD_H__ + +#include "libxfs.h" +#include <sys/time.h> + +/* + * Device topology information. + */ +typedef struct fs_topology { + int dsunit; /* stripe unit - data subvolume */ + int dswidth; /* stripe width - data subvolume */ + int rtswidth; /* stripe width - rt subvolume */ + int lsectorsize; /* logical sector size &*/ + int psectorsize; /* physical sector size */ +} fs_topology_t; + +extern void get_topology( + libxfs_init_t *xi, + struct fs_topology *ft, + int force_overwrite); + +extern void +calc_default_ag_geometry( + int blocklog, + __uint64_t dblocks, + int multidisk, + __uint64_t *agsize, + __uint64_t *agcount); + +extern int +check_overwrite( + char *device); + + + +#endif /* __LIBXCMD_H__ */ diff --git a/libxcmd/Makefile b/libxcmd/Makefile index 7701ed9..aab8d6d 100644 --- a/libxcmd/Makefile +++ b/libxcmd/Makefile @@ -10,7 +10,7 @@ LT_CURRENT = 0 LT_REVISION = 0 LT_AGE = 0 -CFILES = command.c input.c paths.c projects.c help.c quit.c +CFILES = command.c input.c paths.c projects.c help.c quit.c topology.c ifeq ($(HAVE_GETMNTENT),yes) LCFLAGS += -DHAVE_GETMNTENT diff --git a/libxcmd/topology.c b/libxcmd/topology.c new file mode 100644 index 0000000..0eeea28 --- /dev/null +++ b/libxcmd/topology.c @@ -0,0 +1,348 @@ +/* + * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libxfs.h" +#ifdef ENABLE_BLKID +# include <blkid/blkid.h> +#endif /* ENABLE_BLKID */ +#include "../mkfs/xfs_mkfs.h" + +#define TERABYTES(count, blog) ((__uint64_t)(count) << (40 - (blog))) +#define GIGABYTES(count, blog) ((__uint64_t)(count) << (30 - (blog))) +#define MEGABYTES(count, blog) ((__uint64_t)(count) << (20 - (blog))) + +void +calc_default_ag_geometry( + int blocklog, + __uint64_t dblocks, + int multidisk, + __uint64_t *agsize, + __uint64_t *agcount) +{ + __uint64_t blocks = 0; + int shift = 0; + + /* + * First handle the high extreme - the point at which we will + * always use the maximum AG size. + * + * This applies regardless of storage configuration. + */ + if (dblocks >= TERABYTES(32, blocklog)) { + blocks = XFS_AG_MAX_BLOCKS(blocklog); + goto done; + } + + /* + * For the remainder we choose an AG size based on the + * number of data blocks available, trying to keep the + * number of AGs relatively small (especially compared + * to the original algorithm). AG count is calculated + * based on the preferred AG size, not vice-versa - the + * count can be increased by growfs, so prefer to use + * smaller counts at mkfs time. + * + * For a single underlying storage device between 128MB + * and 4TB in size, just use 4 AGs, otherwise scale up + * smoothly between min/max AG sizes. + */ + + if (!multidisk && dblocks >= MEGABYTES(128, blocklog)) { + if (dblocks >= TERABYTES(4, blocklog)) { + blocks = XFS_AG_MAX_BLOCKS(blocklog); + goto done; + } + shift = 2; + } else if (dblocks > GIGABYTES(512, blocklog)) + shift = 5; + else if (dblocks > GIGABYTES(8, blocklog)) + shift = 4; + else if (dblocks >= MEGABYTES(128, blocklog)) + shift = 3; + else if (dblocks >= MEGABYTES(64, blocklog)) + shift = 2; + else if (dblocks >= MEGABYTES(32, blocklog)) + shift = 1; + else + shift = 0; + /* + * If dblocks is not evenly divisible by the number of + * desired AGs, round "blocks" up so we don't lose the + * last bit of the filesystem. The same principle applies + * to the AG count, so we don't lose the last AG! + */ + blocks = dblocks >> shift; + if (dblocks & xfs_mask32lo(shift)) { + if (blocks < XFS_AG_MAX_BLOCKS(blocklog)) + blocks++; + } +done: + *agsize = blocks; + *agcount = dblocks / blocks + (dblocks % blocks != 0); +} + +/* + * Device topology information. + */ +struct fs_topology { + int dsunit; /* stripe unit - data subvolume */ + int dswidth; /* stripe width - data subvolume */ + int rtswidth; /* stripe width - rt subvolume */ + int lsectorsize; /* logical sector size &*/ + int psectorsize; /* physical sector size */ +}; + +/* + * Check for existing filesystem or partition table on device. + * Returns: + * 1 for existing fs or partition + * 0 for nothing found + * -1 for internal error + */ +#ifdef ENABLE_BLKID +int +check_overwrite( + char *device) +{ + const char *type; + blkid_probe pr = NULL; + int ret; + int fd; + long long size; + int bsz; + + if (!device || !*device) + return 0; + + ret = -1; /* will reset on success of all setup calls */ + + fd = open(device, O_RDONLY); + if (fd < 0) + goto out; + platform_findsizes(device, fd, &size, &bsz); + close(fd); + + /* nothing to overwrite on a 0-length device */ + if (size == 0) { + ret = 0; + goto out; + } + + pr = blkid_new_probe_from_filename(device); + if (!pr) + goto out; + + ret = blkid_probe_enable_partitions(pr, 1); + if (ret < 0) + goto out; + + ret = blkid_do_fullprobe(pr); + if (ret < 0) + goto out; + + /* + * Blkid returns 1 for nothing found and 0 when it finds a signature, + * but we want the exact opposite, so reverse the return value here. + * + * In addition print some useful diagnostics about what actually is + * on the device. + */ + if (ret) { + ret = 0; + goto out; + } + + if (!blkid_probe_lookup_value(pr, "TYPE", &type, NULL)) { + fprintf(stderr, + _("%s: %s appears to contain an existing " + "filesystem (%s).\n"), progname, device, type); + } else if (!blkid_probe_lookup_value(pr, "PTTYPE", &type, NULL)) { + fprintf(stderr, + _("%s: %s appears to contain a partition " + "table (%s).\n"), progname, device, type); + } else { + fprintf(stderr, + _("%s: %s appears to contain something weird " + "according to blkid\n"), progname, device); + } + ret = 1; + +out: + if (pr) + blkid_free_probe(pr); + if (ret == -1) + fprintf(stderr, + _("%s: probe of %s failed, cannot detect " + "existing filesystem.\n"), progname, device); + return ret; +} + +static void blkid_get_topology( + const char *device, + int *sunit, + int *swidth, + int *lsectorsize, + int *psectorsize, + int force_overwrite) +{ + + blkid_topology tp; + blkid_probe pr; + unsigned long val; + struct stat statbuf; + + /* can't get topology info from a file */ + if (!stat(device, &statbuf) && S_ISREG(statbuf.st_mode)) + return; + + pr = blkid_new_probe_from_filename(device); + if (!pr) + return; + + tp = blkid_probe_get_topology(pr); + if (!tp) + goto out_free_probe; + + val = blkid_topology_get_logical_sector_size(tp); + *lsectorsize = val; + val = blkid_topology_get_physical_sector_size(tp); + *psectorsize = val; + val = blkid_topology_get_minimum_io_size(tp); + *sunit = val; + val = blkid_topology_get_optimal_io_size(tp); + *swidth = val; + + /* + * If the reported values are the same as the physical sector size + * do not bother to report anything. It will only cause warnings + * if people specify larger stripe units or widths manually. + */ + if (*sunit == *psectorsize || *swidth == *psectorsize) { + *sunit = 0; + *swidth = 0; + } + + /* + * Blkid reports the information in terms of bytes, but we want it in + * terms of 512 bytes blocks (only to convert it to bytes later..) + */ + *sunit = *sunit >> 9; + *swidth = *swidth >> 9; + + if (blkid_topology_get_alignment_offset(tp) != 0) { + fprintf(stderr, + _("warning: device is not properly aligned %s\n"), + device); + + if (!force_overwrite) { + fprintf(stderr, + _("Use -f to force usage of a misaligned device\n")); + + exit(EXIT_FAILURE); + } + /* Do not use physical sector size if the device is misaligned */ + *psectorsize = *lsectorsize; + } + + blkid_free_probe(pr); + return; + +out_free_probe: + blkid_free_probe(pr); + fprintf(stderr, + _("warning: unable to probe device topology for device %s\n"), + device); +} +#else /* ifdef ENABLE_BLKID */ +/* + * Without blkid, we can't do a good check for signatures. + * So instead of some messy attempts, just disable any checks + * and always return 'nothing found'. + */ +# warning BLKID is disabled, so signature detection and block device\ + access are not working! + +int +check_overwrite( + char *device) +{ + return 1; +} + +static void blkid_get_topology( + const char *device, + int *sunit, + int *swidth, + int *lsectorsize, + int *psectorsize, + int force_overwrite) +{ + /* + * Shouldn't make any difference (no blkid = no block device access), + * but make sure this dummy replacement returns with at least some + * sanity. + */ + *lsectorsize = *psectorsize = 512; +} + +#endif /* ENABLE_BLKID */ + + +void get_topology( + libxfs_init_t *xi, + struct fs_topology *ft, + int force_overwrite) +{ + struct stat statbuf; + char *dfile = xi->volname ? xi->volname : xi->dname; + + /* + * If our target is a regular file, use platform_findsizes + * to try to obtain the underlying filesystem's requirements + * for direct IO; we'll set our sector size to that if possible. + */ + if (xi->disfile || + (!stat(dfile, &statbuf) && S_ISREG(statbuf.st_mode))) { + int fd; + int flags = O_RDONLY; + long long dummy; + + /* with xi->disfile we may not have the file yet! */ + if (xi->disfile) + flags |= O_CREAT; + + fd = open(dfile, flags, 0666); + if (fd >= 0) { + platform_findsizes(dfile, fd, &dummy, &ft->lsectorsize); + close(fd); + ft->psectorsize = ft->lsectorsize; + } else + ft->psectorsize = ft->lsectorsize = BBSIZE; + } else { + blkid_get_topology(dfile, &ft->dsunit, &ft->dswidth, + &ft->lsectorsize, &ft->psectorsize, + force_overwrite); + } + + if (xi->rtname && !xi->risfile) { + int sunit, lsectorsize, psectorsize; + + blkid_get_topology(xi->rtname, &sunit, &ft->rtswidth, + &lsectorsize, &psectorsize, force_overwrite); + } +} diff --git a/mkfs/Makefile b/mkfs/Makefile index 570ab07..2997398 100644 --- a/mkfs/Makefile +++ b/mkfs/Makefile @@ -10,7 +10,7 @@ LTCOMMAND = mkfs.xfs HFILES = xfs_mkfs.h CFILES = maxtrres.c proto.c xfs_mkfs.c -LLDLIBS += $(LIBBLKID) $(LIBXFS) $(LIBUUID) $(LIBRT) $(LIBPTHREAD) +LLDLIBS += $(LIBBLKID) $(LIBXFS) $(LIBUUID) $(LIBRT) $(LIBPTHREAD) $(LIBXCMD) LTDEPENDENCIES += $(LIBXFS) LLDFLAGS = -static-libtool-libs diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 700d12c..2ca7e5c 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -22,17 +22,7 @@ # include <blkid/blkid.h> #endif /* ENABLE_BLKID */ #include "xfs_mkfs.h" - -/* - * Device topology information. - */ -struct fs_topology { - int dsunit; /* stripe unit - data subvolume */ - int dswidth; /* stripe width - data subvolume */ - int rtswidth; /* stripe width - rt subvolume */ - int lsectorsize; /* logical sector size &*/ - int psectorsize; /* physical sector size */ -}; +#include "libxcmd.h" /* * Prototypes for internal functions. @@ -295,244 +285,6 @@ calc_stripe_factors( } } -/* - * Check for existing filesystem or partition table on device. - * Returns: - * 1 for existing fs or partition - * 0 for nothing found - * -1 for internal error - */ -#ifdef ENABLE_BLKID -static int -check_overwrite( - char *device) -{ - const char *type; - blkid_probe pr = NULL; - int ret; - int fd; - long long size; - int bsz; - - if (!device || !*device) - return 0; - - ret = -1; /* will reset on success of all setup calls */ - - fd = open(device, O_RDONLY); - if (fd < 0) - goto out; - platform_findsizes(device, fd, &size, &bsz); - close(fd); - - /* nothing to overwrite on a 0-length device */ - if (size == 0) { - ret = 0; - goto out; - } - - pr = blkid_new_probe_from_filename(device); - if (!pr) - goto out; - - ret = blkid_probe_enable_partitions(pr, 1); - if (ret < 0) - goto out; - - ret = blkid_do_fullprobe(pr); - if (ret < 0) - goto out; - - /* - * Blkid returns 1 for nothing found and 0 when it finds a signature, - * but we want the exact opposite, so reverse the return value here. - * - * In addition print some useful diagnostics about what actually is - * on the device. - */ - if (ret) { - ret = 0; - goto out; - } - - if (!blkid_probe_lookup_value(pr, "TYPE", &type, NULL)) { - fprintf(stderr, - _("%s: %s appears to contain an existing " - "filesystem (%s).\n"), progname, device, type); - } else if (!blkid_probe_lookup_value(pr, "PTTYPE", &type, NULL)) { - fprintf(stderr, - _("%s: %s appears to contain a partition " - "table (%s).\n"), progname, device, type); - } else { - fprintf(stderr, - _("%s: %s appears to contain something weird " - "according to blkid\n"), progname, device); - } - ret = 1; - -out: - if (pr) - blkid_free_probe(pr); - if (ret == -1) - fprintf(stderr, - _("%s: probe of %s failed, cannot detect " - "existing filesystem.\n"), progname, device); - return ret; -} - -static void blkid_get_topology( - const char *device, - int *sunit, - int *swidth, - int *lsectorsize, - int *psectorsize, - int force_overwrite) -{ - - blkid_topology tp; - blkid_probe pr; - unsigned long val; - struct stat statbuf; - - /* can't get topology info from a file */ - if (!stat(device, &statbuf) && S_ISREG(statbuf.st_mode)) - return; - - pr = blkid_new_probe_from_filename(device); - if (!pr) - return; - - tp = blkid_probe_get_topology(pr); - if (!tp) - goto out_free_probe; - - val = blkid_topology_get_logical_sector_size(tp); - *lsectorsize = val; - val = blkid_topology_get_physical_sector_size(tp); - *psectorsize = val; - val = blkid_topology_get_minimum_io_size(tp); - *sunit = val; - val = blkid_topology_get_optimal_io_size(tp); - *swidth = val; - - /* - * If the reported values are the same as the physical sector size - * do not bother to report anything. It will only cause warnings - * if people specify larger stripe units or widths manually. - */ - if (*sunit == *psectorsize || *swidth == *psectorsize) { - *sunit = 0; - *swidth = 0; - } - - /* - * Blkid reports the information in terms of bytes, but we want it in - * terms of 512 bytes blocks (only to convert it to bytes later..) - */ - *sunit = *sunit >> 9; - *swidth = *swidth >> 9; - - if (blkid_topology_get_alignment_offset(tp) != 0) { - fprintf(stderr, - _("warning: device is not properly aligned %s\n"), - device); - - if (!force_overwrite) { - fprintf(stderr, - _("Use -f to force usage of a misaligned device\n")); - - exit(EXIT_FAILURE); - } - /* Do not use physical sector size if the device is misaligned */ - *psectorsize = *lsectorsize; - } - - blkid_free_probe(pr); - return; - -out_free_probe: - blkid_free_probe(pr); - fprintf(stderr, - _("warning: unable to probe device topology for device %s\n"), - device); -} -#else /* ifdef ENABLE_BLKID */ -/* - * Without blkid, we can't do a good check for signatures. - * So instead of some messy attempts, just disable any checks - * and always return 'nothing found'. - */ -# warning BLKID is disabled, so signature detection and block device\ - access are not working! -static int -check_overwrite( - char *device) -{ - return 1; -} - -static void blkid_get_topology( - const char *device, - int *sunit, - int *swidth, - int *lsectorsize, - int *psectorsize, - int force_overwrite) -{ - /* - * Shouldn't make any difference (no blkid = no block device access), - * but make sure this dummy replacement returns with at least some - * sanity. - */ - *lsectorsize = *psectorsize = 512; -} - -#endif /* ENABLE_BLKID */ - -static void get_topology( - libxfs_init_t *xi, - struct fs_topology *ft, - int force_overwrite) -{ - struct stat statbuf; - char *dfile = xi->volname ? xi->volname : xi->dname; - - /* - * If our target is a regular file, use platform_findsizes - * to try to obtain the underlying filesystem's requirements - * for direct IO; we'll set our sector size to that if possible. - */ - if (xi->disfile || - (!stat(dfile, &statbuf) && S_ISREG(statbuf.st_mode))) { - int fd; - int flags = O_RDONLY; - long long dummy; - - /* with xi->disfile we may not have the file yet! */ - if (xi->disfile) - flags |= O_CREAT; - - fd = open(dfile, flags, 0666); - if (fd >= 0) { - platform_findsizes(dfile, fd, &dummy, &ft->lsectorsize); - close(fd); - ft->psectorsize = ft->lsectorsize; - } else - ft->psectorsize = ft->lsectorsize = BBSIZE; - } else { - blkid_get_topology(dfile, &ft->dsunit, &ft->dswidth, - &ft->lsectorsize, &ft->psectorsize, - force_overwrite); - } - - if (xi->rtname && !xi->risfile) { - int sunit, lsectorsize, psectorsize; - - blkid_get_topology(xi->rtname, &sunit, &ft->rtswidth, - &lsectorsize, &psectorsize, force_overwrite); - } -} - static void fixup_log_stripe_unit( int lsflag, @@ -640,77 +392,6 @@ calc_default_imaxpct( return 1; } - -void -calc_default_ag_geometry( - int blocklog, - __uint64_t dblocks, - int multidisk, - __uint64_t *agsize, - __uint64_t *agcount) -{ - __uint64_t blocks = 0; - int shift = 0; - - /* - * First handle the high extreme - the point at which we will - * always use the maximum AG size. - * - * This applies regardless of storage configuration. - */ - if (dblocks >= TERABYTES(32, blocklog)) { - blocks = XFS_AG_MAX_BLOCKS(blocklog); - goto done; - } - - /* - * For the remainder we choose an AG size based on the - * number of data blocks available, trying to keep the - * number of AGs relatively small (especially compared - * to the original algorithm). AG count is calculated - * based on the preferred AG size, not vice-versa - the - * count can be increased by growfs, so prefer to use - * smaller counts at mkfs time. - * - * For a single underlying storage device between 128MB - * and 4TB in size, just use 4 AGs, otherwise scale up - * smoothly between min/max AG sizes. - */ - - if (!multidisk && dblocks >= MEGABYTES(128, blocklog)) { - if (dblocks >= TERABYTES(4, blocklog)) { - blocks = XFS_AG_MAX_BLOCKS(blocklog); - goto done; - } - shift = 2; - } else if (dblocks > GIGABYTES(512, blocklog)) - shift = 5; - else if (dblocks > GIGABYTES(8, blocklog)) - shift = 4; - else if (dblocks >= MEGABYTES(128, blocklog)) - shift = 3; - else if (dblocks >= MEGABYTES(64, blocklog)) - shift = 2; - else if (dblocks >= MEGABYTES(32, blocklog)) - shift = 1; - else - shift = 0; - /* - * If dblocks is not evenly divisible by the number of - * desired AGs, round "blocks" up so we don't lose the - * last bit of the filesystem. The same principle applies - * to the AG count, so we don't lose the last AG! - */ - blocks = dblocks >> shift; - if (dblocks & xfs_mask32lo(shift)) { - if (blocks < XFS_AG_MAX_BLOCKS(blocklog)) - blocks++; - } -done: - *agsize = blocks; - *agcount = dblocks / blocks + (dblocks % blocks != 0); -} - static void validate_ag_geometry( int blocklog, -- 2.5.0 _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs