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