]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libxfs/topology.c
configure: require libblkid
[thirdparty/xfsprogs-dev.git] / libxfs / topology.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0
82c3a179
BD
2/*
3 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
82c3a179
BD
5 */
6
6bc3531c 7#include "libxfs_priv.h"
82c3a179 8#include "libxcmd.h"
bd07eede 9#include <blkid/blkid.h>
82c3a179 10#include "xfs_multidisk.h"
6bc3531c 11#include "libfrog/platform.h"
82c3a179 12
14f8b681
DW
13#define TERABYTES(count, blog) ((uint64_t)(count) << (40 - (blog)))
14#define GIGABYTES(count, blog) ((uint64_t)(count) << (30 - (blog)))
15#define MEGABYTES(count, blog) ((uint64_t)(count) << (20 - (blog)))
82c3a179
BD
16
17void
18calc_default_ag_geometry(
19 int blocklog,
14f8b681 20 uint64_t dblocks,
82c3a179 21 int multidisk,
14f8b681
DW
22 uint64_t *agsize,
23 uint64_t *agcount)
82c3a179 24{
14f8b681 25 uint64_t blocks = 0;
82c3a179
BD
26 int shift = 0;
27
28 /*
29 * First handle the high extreme - the point at which we will
30 * always use the maximum AG size.
31 *
32 * This applies regardless of storage configuration.
33 */
34 if (dblocks >= TERABYTES(32, blocklog)) {
35 blocks = XFS_AG_MAX_BLOCKS(blocklog);
36 goto done;
37 }
38
39 /*
40 * For a single underlying storage device over 4TB in size
41 * use the maximum AG size. Between 128MB and 4TB, just use
42 * 4 AGs and scale up smoothly between min/max AG sizes.
43 */
44 if (!multidisk) {
45 if (dblocks >= TERABYTES(4, blocklog)) {
46 blocks = XFS_AG_MAX_BLOCKS(blocklog);
47 goto done;
48 } else if (dblocks >= MEGABYTES(128, blocklog)) {
49 shift = XFS_NOMULTIDISK_AGLOG;
50 goto calc_blocks;
51 }
52 }
53
54 /*
55 * For the multidisk configs we choose an AG count based on the number
56 * of data blocks available, trying to keep the number of AGs higher
57 * than the single disk configurations. This makes the assumption that
58 * larger filesystems have more parallelism available to them.
59 */
60 shift = XFS_MULTIDISK_AGLOG;
61 if (dblocks <= GIGABYTES(512, blocklog))
62 shift--;
63 if (dblocks <= GIGABYTES(8, blocklog))
64 shift--;
65 if (dblocks < MEGABYTES(128, blocklog))
66 shift--;
67 if (dblocks < MEGABYTES(64, blocklog))
68 shift--;
69 if (dblocks < MEGABYTES(32, blocklog))
70 shift--;
71
72 /*
73 * If dblocks is not evenly divisible by the number of
74 * desired AGs, round "blocks" up so we don't lose the
75 * last bit of the filesystem. The same principle applies
76 * to the AG count, so we don't lose the last AG!
77 */
78calc_blocks:
79 ASSERT(shift >= 0 && shift <= XFS_MULTIDISK_AGLOG);
80 blocks = dblocks >> shift;
81 if (dblocks & xfs_mask32lo(shift)) {
82 if (blocks < XFS_AG_MAX_BLOCKS(blocklog))
83 blocks++;
84 }
85done:
86 *agsize = blocks;
87 *agcount = dblocks / blocks + (dblocks % blocks != 0);
88}
89
90/*
91 * Check for existing filesystem or partition table on device.
92 * Returns:
93 * 1 for existing fs or partition
94 * 0 for nothing found
95 * -1 for internal error
96 */
82c3a179
BD
97int
98check_overwrite(
99 const char *device)
100{
101 const char *type;
102 blkid_probe pr = NULL;
103 int ret;
104 int fd;
105 long long size;
106 int bsz;
107
108 if (!device || !*device)
109 return 0;
110
111 ret = -1; /* will reset on success of all setup calls */
112
113 fd = open(device, O_RDONLY);
114 if (fd < 0)
115 goto out;
116 platform_findsizes((char *)device, fd, &size, &bsz);
117 close(fd);
118
119 /* nothing to overwrite on a 0-length device */
120 if (size == 0) {
121 ret = 0;
122 goto out;
123 }
124
125 pr = blkid_new_probe_from_filename(device);
126 if (!pr)
127 goto out;
128
129 ret = blkid_probe_enable_partitions(pr, 1);
130 if (ret < 0)
131 goto out;
132
133 ret = blkid_do_fullprobe(pr);
134 if (ret < 0)
135 goto out;
136
137 /*
138 * Blkid returns 1 for nothing found and 0 when it finds a signature,
139 * but we want the exact opposite, so reverse the return value here.
140 *
141 * In addition print some useful diagnostics about what actually is
142 * on the device.
143 */
144 if (ret) {
145 ret = 0;
146 goto out;
147 }
148
149 if (!blkid_probe_lookup_value(pr, "TYPE", &type, NULL)) {
150 fprintf(stderr,
151 _("%s: %s appears to contain an existing "
152 "filesystem (%s).\n"), progname, device, type);
153 } else if (!blkid_probe_lookup_value(pr, "PTTYPE", &type, NULL)) {
154 fprintf(stderr,
155 _("%s: %s appears to contain a partition "
156 "table (%s).\n"), progname, device, type);
157 } else {
158 fprintf(stderr,
159 _("%s: %s appears to contain something weird "
160 "according to blkid\n"), progname, device);
161 }
162 ret = 1;
163out:
164 if (pr)
165 blkid_free_probe(pr);
166 if (ret == -1)
167 fprintf(stderr,
168 _("%s: probe of %s failed, cannot detect "
169 "existing filesystem.\n"), progname, device);
170 return ret;
171}
172
173static void blkid_get_topology(
174 const char *device,
175 int *sunit,
176 int *swidth,
177 int *lsectorsize,
178 int *psectorsize,
179 int force_overwrite)
180{
181
182 blkid_topology tp;
183 blkid_probe pr;
184 unsigned long val;
185 struct stat statbuf;
186
187 /* can't get topology info from a file */
188 if (!stat(device, &statbuf) && S_ISREG(statbuf.st_mode)) {
189 fprintf(stderr,
190 _("%s: Warning: trying to probe topology of a file %s!\n"),
191 progname, device);
192 return;
193 }
194
195 pr = blkid_new_probe_from_filename(device);
196 if (!pr)
197 return;
198
199 tp = blkid_probe_get_topology(pr);
200 if (!tp)
201 goto out_free_probe;
202
203 val = blkid_topology_get_logical_sector_size(tp);
204 *lsectorsize = val;
205 val = blkid_topology_get_physical_sector_size(tp);
206 *psectorsize = val;
207 val = blkid_topology_get_minimum_io_size(tp);
208 *sunit = val;
209 val = blkid_topology_get_optimal_io_size(tp);
210 *swidth = val;
211
212 /*
213 * If the reported values are the same as the physical sector size
214 * do not bother to report anything. It will only cause warnings
215 * if people specify larger stripe units or widths manually.
216 */
217 if (*sunit == *psectorsize || *swidth == *psectorsize) {
218 *sunit = 0;
219 *swidth = 0;
220 }
221
222 /*
223 * Blkid reports the information in terms of bytes, but we want it in
224 * terms of 512 bytes blocks (only to convert it to bytes later..)
225 */
226 *sunit = *sunit >> 9;
227 *swidth = *swidth >> 9;
228
229 if (blkid_topology_get_alignment_offset(tp) != 0) {
230 fprintf(stderr,
231 _("warning: device is not properly aligned %s\n"),
232 device);
233
234 if (!force_overwrite) {
235 fprintf(stderr,
236 _("Use -f to force usage of a misaligned device\n"));
237
238 exit(EXIT_FAILURE);
239 }
240 /* Do not use physical sector size if the device is misaligned */
241 *psectorsize = *lsectorsize;
242 }
243
244 blkid_free_probe(pr);
245 return;
246
247out_free_probe:
248 blkid_free_probe(pr);
249 fprintf(stderr,
250 _("warning: unable to probe device topology for device %s\n"),
251 device);
252}
82c3a179 253
01dcfd9e
CH
254void
255get_topology(
256 struct libxfs_init *xi,
82c3a179
BD
257 struct fs_topology *ft,
258 int force_overwrite)
259{
260 struct stat statbuf;
82c3a179
BD
261
262 /*
263 * If our target is a regular file, use platform_findsizes
264 * to try to obtain the underlying filesystem's requirements
265 * for direct IO; we'll set our sector size to that if possible.
266 */
fc83c757
CH
267 if (xi->data.isfile ||
268 (!stat(xi->data.name, &statbuf) && S_ISREG(statbuf.st_mode))) {
82c3a179
BD
269 int fd;
270 int flags = O_RDONLY;
271 long long dummy;
272
273 /* with xi->disfile we may not have the file yet! */
fc83c757 274 if (xi->data.isfile)
82c3a179
BD
275 flags |= O_CREAT;
276
fc83c757 277 fd = open(xi->data.name, flags, 0666);
82c3a179 278 if (fd >= 0) {
fc83c757 279 platform_findsizes(xi->data.name, fd, &dummy,
732f5b90 280 &ft->lsectorsize);
82c3a179
BD
281 close(fd);
282 ft->psectorsize = ft->lsectorsize;
283 } else
284 ft->psectorsize = ft->lsectorsize = BBSIZE;
285 } else {
fc83c757 286 blkid_get_topology(xi->data.name, &ft->dsunit, &ft->dswidth,
82c3a179
BD
287 &ft->lsectorsize, &ft->psectorsize,
288 force_overwrite);
289 }
290
fc83c757 291 if (xi->rt.name && !xi->rt.isfile) {
82c3a179
BD
292 int sunit, lsectorsize, psectorsize;
293
fc83c757 294 blkid_get_topology(xi->rt.name, &sunit, &ft->rtswidth,
82c3a179
BD
295 &lsectorsize, &psectorsize, force_overwrite);
296 }
297}