1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
7 #ifdef OVERRIDE_SYSTEM_STATX
8 #define statx sys_statx
13 #include "libxfs_priv.h"
15 #include <blkid/blkid.h>
16 #include "xfs_multidisk.h"
17 #include "libfrog/platform.h"
18 #include "libfrog/statx.h"
20 #define TERABYTES(count, blog) ((uint64_t)(count) << (40 - (blog)))
21 #define GIGABYTES(count, blog) ((uint64_t)(count) << (30 - (blog)))
22 #define MEGABYTES(count, blog) ((uint64_t)(count) << (20 - (blog)))
25 calc_default_ag_geometry(
36 * First handle the high extreme - the point at which we will
37 * always use the maximum AG size.
39 * This applies regardless of storage configuration.
41 if (dblocks
>= TERABYTES(32, blocklog
)) {
42 blocks
= XFS_AG_MAX_BLOCKS(blocklog
);
47 * For a single underlying storage device over 4TB in size
48 * use the maximum AG size. Between 128MB and 4TB, just use
49 * 4 AGs and scale up smoothly between min/max AG sizes.
52 if (dblocks
>= TERABYTES(4, blocklog
)) {
53 blocks
= XFS_AG_MAX_BLOCKS(blocklog
);
55 } else if (dblocks
>= MEGABYTES(128, blocklog
)) {
56 shift
= XFS_NOMULTIDISK_AGLOG
;
62 * For the multidisk configs we choose an AG count based on the number
63 * of data blocks available, trying to keep the number of AGs higher
64 * than the single disk configurations. This makes the assumption that
65 * larger filesystems have more parallelism available to them.
67 shift
= XFS_MULTIDISK_AGLOG
;
68 if (dblocks
<= GIGABYTES(512, blocklog
))
70 if (dblocks
<= GIGABYTES(8, blocklog
))
72 if (dblocks
< MEGABYTES(128, blocklog
))
74 if (dblocks
< MEGABYTES(64, blocklog
))
76 if (dblocks
< MEGABYTES(32, blocklog
))
80 * If dblocks is not evenly divisible by the number of
81 * desired AGs, round "blocks" up so we don't lose the
82 * last bit of the filesystem. The same principle applies
83 * to the AG count, so we don't lose the last AG!
86 ASSERT(shift
>= 0 && shift
<= XFS_MULTIDISK_AGLOG
);
87 blocks
= dblocks
>> shift
;
88 if (dblocks
& xfs_mask32lo(shift
)) {
89 if (blocks
< XFS_AG_MAX_BLOCKS(blocklog
))
94 *agcount
= dblocks
/ blocks
+ (dblocks
% blocks
!= 0);
98 calc_default_rtgroup_geometry(
108 * For a single underlying storage device over 4TB in size use the
109 * maximum rtgroup size. Between 128MB and 4TB, just use 4 rtgroups
110 * and scale up smoothly between min/max rtgroup sizes.
112 if (rblocks
>= TERABYTES(4, blocklog
)) {
113 blocks
= XFS_MAX_RGBLOCKS
;
116 if (rblocks
>= MEGABYTES(128, blocklog
)) {
117 shift
= XFS_NOMULTIDISK_AGLOG
;
122 * If rblocks is not evenly divisible by the number of desired rt
123 * groups, round "blocks" up so we don't lose the last bit of the
124 * filesystem. The same principle applies to the rt group count, so we
125 * don't lose the last rt group!
128 ASSERT(shift
>= 0 && shift
<= XFS_MULTIDISK_AGLOG
);
129 blocks
= rblocks
>> shift
;
130 if (rblocks
& xfs_mask32lo(shift
)) {
131 if (blocks
< XFS_MAX_RGBLOCKS
)
136 *rgcount
= rblocks
/ blocks
+ (rblocks
% blocks
!= 0);
140 * Check for existing filesystem or partition table on device.
142 * 1 for existing fs or partition
143 * 0 for nothing found
144 * -1 for internal error
151 blkid_probe pr
= NULL
;
157 if (!device
|| !*device
)
160 ret
= -1; /* will reset on success of all setup calls */
162 fd
= open(device
, O_RDONLY
);
165 platform_findsizes((char *)device
, fd
, &size
, &bsz
);
168 /* nothing to overwrite on a 0-length device */
174 pr
= blkid_new_probe_from_filename(device
);
178 ret
= blkid_probe_enable_partitions(pr
, 1);
182 ret
= blkid_do_fullprobe(pr
);
187 * Blkid returns 1 for nothing found and 0 when it finds a signature,
188 * but we want the exact opposite, so reverse the return value here.
190 * In addition print some useful diagnostics about what actually is
198 if (!blkid_probe_lookup_value(pr
, "TYPE", &type
, NULL
)) {
200 _("%s: %s appears to contain an existing "
201 "filesystem (%s).\n"), progname
, device
, type
);
202 } else if (!blkid_probe_lookup_value(pr
, "PTTYPE", &type
, NULL
)) {
204 _("%s: %s appears to contain a partition "
205 "table (%s).\n"), progname
, device
, type
);
208 _("%s: %s appears to contain something weird "
209 "according to blkid\n"), progname
, device
);
214 blkid_free_probe(pr
);
215 /* libblkid 2.38.1 lies and can return -EIO */
218 _("%s: probe of %s failed, cannot detect "
219 "existing filesystem.\n"), progname
, device
);
226 struct device_topology
*dt
,
232 pr
= blkid_new_probe_from_filename(device
);
236 tp
= blkid_probe_get_topology(pr
);
240 dt
->logical_sector_size
= blkid_topology_get_logical_sector_size(tp
);
241 dt
->physical_sector_size
= blkid_topology_get_physical_sector_size(tp
);
242 dt
->sunit
= blkid_topology_get_minimum_io_size(tp
);
243 dt
->swidth
= blkid_topology_get_optimal_io_size(tp
);
246 * If the reported values are the same as the physical sector size
247 * do not bother to report anything. It will only cause warnings
248 * if people specify larger stripe units or widths manually.
250 if (dt
->sunit
== dt
->physical_sector_size
||
251 dt
->swidth
== dt
->physical_sector_size
) {
257 * Blkid reports the information in terms of bytes, but we want it in
258 * terms of 512 bytes blocks (only to convert it to bytes later..)
263 if (blkid_topology_get_alignment_offset(tp
) != 0) {
265 _("warning: device is not properly aligned %s\n"),
268 if (!force_overwrite
) {
270 _("Use -f to force usage of a misaligned device\n"));
274 /* Do not use physical sector size if the device is misaligned */
275 dt
->physical_sector_size
= dt
->logical_sector_size
;
278 blkid_free_probe(pr
);
282 blkid_free_probe(pr
);
284 _("warning: unable to probe device topology for device %s\n"),
289 get_hw_atomic_writes_topology(
290 struct libxfs_dev
*dev
,
291 struct device_topology
*dt
)
297 fd
= open(dev
->name
, O_RDONLY
);
301 ret
= statx(fd
, "", AT_EMPTY_PATH
, STATX_WRITE_ATOMIC
, &sx
);
305 if (!(sx
.stx_mask
& STATX_WRITE_ATOMIC
))
308 dt
->awu_min
= sx
.stx_atomic_write_unit_min
>> 9;
309 dt
->awu_max
= max(sx
.stx_atomic_write_unit_max_opt
,
310 sx
.stx_atomic_write_unit_max
) >> 9;
318 struct libxfs_dev
*dev
,
319 struct device_topology
*dt
,
325 * Nothing to do if this particular subvolume doesn't exist.
331 * If our target is a regular file, use platform_findsizes
332 * to try to obtain the underlying filesystem's requirements
333 * for direct IO; we'll set our sector size to that if possible.
335 if (dev
->isfile
|| (!stat(dev
->name
, &st
) && S_ISREG(st
.st_mode
))) {
336 int flags
= O_RDONLY
;
340 /* with xi->disfile we may not have the file yet! */
344 fd
= open(dev
->name
, flags
, 0666);
346 platform_findsizes(dev
->name
, fd
, &dummy
,
347 &dt
->logical_sector_size
);
350 dt
->logical_sector_size
= BBSIZE
;
353 blkid_get_topology(dev
->name
, dt
, force_overwrite
);
354 get_hw_atomic_writes_topology(dev
, dt
);
357 ASSERT(dt
->logical_sector_size
);
360 * Older kernels may not have physical/logical distinction.
362 if (!dt
->physical_sector_size
)
363 dt
->physical_sector_size
= dt
->logical_sector_size
;
368 struct libxfs_init
*xi
,
369 struct fs_topology
*ft
,
372 get_device_topology(&xi
->data
, &ft
->data
, force_overwrite
);
373 get_device_topology(&xi
->rt
, &ft
->rt
, force_overwrite
);
374 get_device_topology(&xi
->log
, &ft
->log
, force_overwrite
);