]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - libxcmd/topology.c
2 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 # include <blkid/blkid.h>
23 #endif /* ENABLE_BLKID */
24 #include "xfs_multidisk.h"
26 #define TERABYTES(count, blog) ((__uint64_t)(count) << (40 - (blog)))
27 #define GIGABYTES(count, blog) ((__uint64_t)(count) << (30 - (blog)))
28 #define MEGABYTES(count, blog) ((__uint64_t)(count) << (20 - (blog)))
31 calc_default_ag_geometry(
38 __uint64_t blocks
= 0;
42 * First handle the high extreme - the point at which we will
43 * always use the maximum AG size.
45 * This applies regardless of storage configuration.
47 if (dblocks
>= TERABYTES(32, blocklog
)) {
48 blocks
= XFS_AG_MAX_BLOCKS(blocklog
);
53 * For a single underlying storage device over 4TB in size
54 * use the maximum AG size. Between 128MB and 4TB, just use
55 * 4 AGs and scale up smoothly between min/max AG sizes.
58 if (dblocks
>= TERABYTES(4, blocklog
)) {
59 blocks
= XFS_AG_MAX_BLOCKS(blocklog
);
61 } else if (dblocks
>= MEGABYTES(128, blocklog
)) {
62 shift
= XFS_NOMULTIDISK_AGLOG
;
68 * For the multidisk configs we choose an AG count based on the number
69 * of data blocks available, trying to keep the number of AGs higher
70 * than the single disk configurations. This makes the assumption that
71 * larger filesystems have more parallelism available to them.
73 shift
= XFS_MULTIDISK_AGLOG
;
74 if (dblocks
<= GIGABYTES(512, blocklog
))
76 if (dblocks
<= GIGABYTES(8, blocklog
))
78 if (dblocks
< MEGABYTES(128, blocklog
))
80 if (dblocks
< MEGABYTES(64, blocklog
))
82 if (dblocks
< MEGABYTES(32, blocklog
))
86 * If dblocks is not evenly divisible by the number of
87 * desired AGs, round "blocks" up so we don't lose the
88 * last bit of the filesystem. The same principle applies
89 * to the AG count, so we don't lose the last AG!
92 ASSERT(shift
>= 0 && shift
<= XFS_MULTIDISK_AGLOG
);
93 blocks
= dblocks
>> shift
;
94 if (dblocks
& xfs_mask32lo(shift
)) {
95 if (blocks
< XFS_AG_MAX_BLOCKS(blocklog
))
100 *agcount
= dblocks
/ blocks
+ (dblocks
% blocks
!= 0);
104 * Check for existing filesystem or partition table on device.
106 * 1 for existing fs or partition
107 * 0 for nothing found
108 * -1 for internal error
116 blkid_probe pr
= NULL
;
122 if (!device
|| !*device
)
125 ret
= -1; /* will reset on success of all setup calls */
127 fd
= open(device
, O_RDONLY
);
130 platform_findsizes((char *)device
, fd
, &size
, &bsz
);
133 /* nothing to overwrite on a 0-length device */
139 pr
= blkid_new_probe_from_filename(device
);
143 ret
= blkid_probe_enable_partitions(pr
, 1);
147 ret
= blkid_do_fullprobe(pr
);
152 * Blkid returns 1 for nothing found and 0 when it finds a signature,
153 * but we want the exact opposite, so reverse the return value here.
155 * In addition print some useful diagnostics about what actually is
163 if (!blkid_probe_lookup_value(pr
, "TYPE", &type
, NULL
)) {
165 _("%s: %s appears to contain an existing "
166 "filesystem (%s).\n"), progname
, device
, type
);
167 } else if (!blkid_probe_lookup_value(pr
, "PTTYPE", &type
, NULL
)) {
169 _("%s: %s appears to contain a partition "
170 "table (%s).\n"), progname
, device
, type
);
173 _("%s: %s appears to contain something weird "
174 "according to blkid\n"), progname
, device
);
179 blkid_free_probe(pr
);
182 _("%s: probe of %s failed, cannot detect "
183 "existing filesystem.\n"), progname
, device
);
187 static void blkid_get_topology(
201 /* can't get topology info from a file */
202 if (!stat(device
, &statbuf
) && S_ISREG(statbuf
.st_mode
)) {
204 _("%s: Warning: trying to probe topology of a file %s!\n"),
209 pr
= blkid_new_probe_from_filename(device
);
213 tp
= blkid_probe_get_topology(pr
);
217 val
= blkid_topology_get_logical_sector_size(tp
);
219 val
= blkid_topology_get_physical_sector_size(tp
);
221 val
= blkid_topology_get_minimum_io_size(tp
);
223 val
= blkid_topology_get_optimal_io_size(tp
);
227 * If the reported values are the same as the physical sector size
228 * do not bother to report anything. It will only cause warnings
229 * if people specify larger stripe units or widths manually.
231 if (*sunit
== *psectorsize
|| *swidth
== *psectorsize
) {
237 * Blkid reports the information in terms of bytes, but we want it in
238 * terms of 512 bytes blocks (only to convert it to bytes later..)
240 *sunit
= *sunit
>> 9;
241 *swidth
= *swidth
>> 9;
243 if (blkid_topology_get_alignment_offset(tp
) != 0) {
245 _("warning: device is not properly aligned %s\n"),
248 if (!force_overwrite
) {
250 _("Use -f to force usage of a misaligned device\n"));
254 /* Do not use physical sector size if the device is misaligned */
255 *psectorsize
= *lsectorsize
;
258 blkid_free_probe(pr
);
262 blkid_free_probe(pr
);
264 _("warning: unable to probe device topology for device %s\n"),
267 #else /* ifdef ENABLE_BLKID */
269 * Without blkid, we can't do a good check for signatures.
270 * So instead of some messy attempts, just disable any checks
271 * and always return 'nothing found'.
273 # warning BLKID is disabled, so signature detection and block device\
274 access are not working!
282 static void blkid_get_topology(
291 * Shouldn't make any difference (no blkid = no block device access),
292 * but make sure this dummy replacement returns with at least some
295 *lsectorsize
= *psectorsize
= 512;
298 #endif /* ENABLE_BLKID */
302 struct fs_topology
*ft
,
306 char *dfile
= xi
->volname
? xi
->volname
: xi
->dname
;
309 * If our target is a regular file, use platform_findsizes
310 * to try to obtain the underlying filesystem's requirements
311 * for direct IO; we'll set our sector size to that if possible.
314 (!stat(dfile
, &statbuf
) && S_ISREG(statbuf
.st_mode
))) {
316 int flags
= O_RDONLY
;
319 /* with xi->disfile we may not have the file yet! */
323 fd
= open(dfile
, flags
, 0666);
325 platform_findsizes(dfile
, fd
, &dummy
, &ft
->lsectorsize
);
327 ft
->psectorsize
= ft
->lsectorsize
;
329 ft
->psectorsize
= ft
->lsectorsize
= BBSIZE
;
331 blkid_get_topology(dfile
, &ft
->dsunit
, &ft
->dswidth
,
332 &ft
->lsectorsize
, &ft
->psectorsize
,
336 if (xi
->rtname
&& !xi
->risfile
) {
337 int sunit
, lsectorsize
, psectorsize
;
339 blkid_get_topology(xi
->rtname
, &sunit
, &ft
->rtswidth
,
340 &lsectorsize
, &psectorsize
, force_overwrite
);