]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libxfs/init.c
libxfs: remove libxfs_physmem
[thirdparty/xfsprogs-dev.git] / libxfs / init.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0
2bd0ea18 2/*
da23017d
NS
3 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
2bd0ea18
NS
5 */
6
2bd0ea18 7#include <sys/stat.h>
9440d84d 8#include "init.h"
29e62271 9
9c799827 10#include "libxfs_priv.h"
b626fb59
DC
11#include "xfs_fs.h"
12#include "xfs_shared.h"
13#include "xfs_format.h"
14#include "xfs_log_format.h"
15#include "xfs_trans_resv.h"
16#include "xfs_mount.h"
794a5604 17#include "xfs_defer.h"
b626fb59
DC
18#include "xfs_inode_buf.h"
19#include "xfs_inode_fork.h"
20#include "xfs_inode.h"
21#include "xfs_trans.h"
b3a96b46 22#include "xfs_rmap_btree.h"
e7be6330 23#include "xfs_refcount_btree.h"
b626fb59 24
6b803e5a 25#include "libxfs.h" /* for now */
b626fb59 26
2bd0ea18
NS
27char *progname = "libxfs"; /* default, changed by each tool */
28
f1b058f9 29struct cache *libxfs_bcache; /* global buffer cache */
9f38f08d 30int libxfs_bhash_size; /* #buckets in bcache */
f1b058f9 31
d0572de5
BN
32int use_xfs_buf_lock; /* global flag: use xfs_buf_t locks for MT */
33
2bd0ea18
NS
34/*
35 * dev_map - map open devices to fd.
36 */
37#define MAX_DEVS 10 /* arbitary maximum */
00ff2b10 38static int nextfakedev = -1; /* device number to give to next fake device */
2bd0ea18 39static struct dev_to_fd {
9440d84d
NS
40 dev_t dev;
41 int fd;
2bd0ea18
NS
42} dev_map[MAX_DEVS]={{0}};
43
2bd0ea18
NS
44/*
45 * Checks whether a given device has a mounted, writable
46 * filesystem, returns 1 if it does & fatal (just warns
47 * if not fatal, but allows us to proceed).
5000d01d 48 *
2bd0ea18
NS
49 * Useful to tools which will produce uncertain results
50 * if the filesystem is active - repair, check, logprint.
51 */
52static int
53check_isactive(char *name, char *block, int fatal)
54{
f594a0d1 55 struct stat st;
2bd0ea18 56
f594a0d1 57 if (stat(block, &st) < 0)
9440d84d 58 return 0;
fc8202ba 59 if ((st.st_mode & S_IFMT) != S_IFBLK)
9440d84d 60 return 0;
93d9f139 61 if (platform_check_ismounted(name, block, &st, 0) == 0)
9440d84d 62 return 0;
7f510afb
ES
63 if (platform_check_iswritable(name, block, &st))
64 return fatal ? 1 : 0;
65 return 0;
2bd0ea18
NS
66}
67
5000d01d 68/* libxfs_device_to_fd:
2bd0ea18
NS
69 * lookup a device number in the device map
70 * return the associated fd
71 */
72int
73libxfs_device_to_fd(dev_t device)
74{
9440d84d 75 int d;
5000d01d 76
9440d84d 77 for (d = 0; d < MAX_DEVS; d++)
5000d01d 78 if (dev_map[d].dev == device)
2bd0ea18 79 return dev_map[d].fd;
5000d01d 80
9440d84d
NS
81 fprintf(stderr, _("%s: %s: device %lld is not open\n"),
82 progname, __FUNCTION__, (long long)device);
2bd0ea18 83 exit(1);
25d246df 84 /* NOTREACHED */
2bd0ea18
NS
85}
86
87/* libxfs_device_open:
88 * open a device and return its device number
89 */
90dev_t
7eb6693f 91libxfs_device_open(char *path, int creat, int xflags, int setblksize)
2bd0ea18 92{
2bd0ea18 93 dev_t dev;
7eb6693f 94 int fd, d, flags;
b74a1f6a 95 int readonly, dio, excl;
f594a0d1 96 struct stat statb;
7eb6693f
NS
97
98 readonly = (xflags & LIBXFS_ISREADONLY);
99 excl = (xflags & LIBXFS_EXCLUSIVELY) && !creat;
b74a1f6a 100 dio = (xflags & LIBXFS_DIRECT) && !creat && platform_direct_blockdev();
2bd0ea18 101
b74a1f6a 102retry:
7eb6693f
NS
103 flags = (readonly ? O_RDONLY : O_RDWR) | \
104 (creat ? (O_CREAT|O_TRUNC) : 0) | \
b74a1f6a 105 (dio ? O_DIRECT : 0) | \
7eb6693f 106 (excl ? O_EXCL : 0);
b74a1f6a 107
7eb6693f 108 if ((fd = open(path, flags, 0666)) < 0) {
b74a1f6a
NS
109 if (errno == EINVAL && --dio == 0)
110 goto retry;
9440d84d 111 fprintf(stderr, _("%s: cannot open %s: %s\n"),
2bd0ea18
NS
112 progname, path, strerror(errno));
113 exit(1);
114 }
115
f594a0d1 116 if (fstat(fd, &statb) < 0) {
9440d84d 117 fprintf(stderr, _("%s: cannot stat %s: %s\n"),
2bd0ea18
NS
118 progname, path, strerror(errno));
119 exit(1);
120 }
a33a9e62 121
edd45774
TS
122 if (!readonly && setblksize && (statb.st_mode & S_IFMT) == S_IFBLK) {
123 if (setblksize == 1)
124 /* use the default blocksize */
125 (void)platform_set_blocksize(fd, path, statb.st_rdev, XFS_MIN_SECTORSIZE, 0);
126 else {
127 /* given an explicit blocksize to use */
128 if (platform_set_blocksize(fd, path, statb.st_rdev, setblksize, 1))
129 exit(1);
130 }
131 }
2bd0ea18 132
a33a9e62
NS
133 /*
134 * Get the device number from the stat buf - unless
2bd0ea18 135 * we're not opening a real device, in which case
a33a9e62 136 * choose a new fake device number.
2bd0ea18 137 */
32181a02 138 dev = (statb.st_rdev) ? (statb.st_rdev) : (nextfakedev--);
2bd0ea18 139
32181a02 140 for (d = 0; d < MAX_DEVS; d++)
2bd0ea18 141 if (dev_map[d].dev == dev) {
9440d84d 142 fprintf(stderr, _("%s: device %lld is already open\n"),
5b64e00a 143 progname, (long long)dev);
2bd0ea18
NS
144 exit(1);
145 }
146
32181a02 147 for (d = 0; d < MAX_DEVS; d++)
2bd0ea18 148 if (!dev_map[d].dev) {
32181a02
NS
149 dev_map[d].dev = dev;
150 dev_map[d].fd = fd;
5000d01d 151
2bd0ea18
NS
152 return dev;
153 }
154
9440d84d
NS
155 fprintf(stderr, _("%s: %s: too many open devices\n"),
156 progname, __FUNCTION__);
2bd0ea18 157 exit(1);
25d246df 158 /* NOTREACHED */
2bd0ea18
NS
159}
160
161void
162libxfs_device_close(dev_t dev)
163{
5000d01d 164 int d;
2bd0ea18 165
32181a02 166 for (d = 0; d < MAX_DEVS; d++)
2bd0ea18 167 if (dev_map[d].dev == dev) {
32181a02 168 int fd;
5000d01d 169
32181a02
NS
170 fd = dev_map[d].fd;
171 dev_map[d].dev = dev_map[d].fd = 0;
5000d01d 172
2bd0ea18 173 fsync(fd);
ac419944 174 platform_flush_device(fd, dev);
2bd0ea18 175 close(fd);
5000d01d 176
2bd0ea18
NS
177 return;
178 }
179
9440d84d
NS
180 fprintf(stderr, _("%s: %s: device %lld is not open\n"),
181 progname, __FUNCTION__, (long long)dev);
2bd0ea18
NS
182 exit(1);
183}
184
74668075
NS
185static int
186check_open(char *path, int flags, char **rawfile, char **blockfile)
187{
c781939c
RC
188 int readonly = (flags & LIBXFS_ISREADONLY);
189 int inactive = (flags & LIBXFS_ISINACTIVE);
190 int dangerously = (flags & LIBXFS_DANGEROUSLY);
f594a0d1 191 struct stat stbuf;
c781939c 192
f594a0d1 193 if (stat(path, &stbuf) < 0) {
c781939c
RC
194 perror(path);
195 return 0;
196 }
b74a1f6a 197 if (!(*rawfile = platform_findrawpath(path))) {
c781939c
RC
198 fprintf(stderr, _("%s: "
199 "can't find a character device matching %s\n"),
200 progname, path);
201 return 0;
202 }
b74a1f6a 203 if (!(*blockfile = platform_findblockpath(path))) {
c781939c
RC
204 fprintf(stderr, _("%s: "
205 "can't find a block device matching %s\n"),
206 progname, path);
207 return 0;
208 }
209 if (!readonly && !inactive && platform_check_ismounted(path, *blockfile, NULL, 1))
210 return 0;
e08f5594 211
c781939c
RC
212 if (inactive && check_isactive(path, *blockfile, ((readonly|dangerously)?1:0)))
213 return 0;
214
215 return 1;
216}
217
7a326ce0
ES
218/*
219 * Initialize/destroy all of the zone allocators we use.
220 */
221static void
222init_zones(void)
223{
224 /* initialise zone allocation */
225 xfs_buf_zone = kmem_zone_init(sizeof(struct xfs_buf), "xfs_buffer");
226 xfs_inode_zone = kmem_zone_init(sizeof(struct xfs_inode), "xfs_inode");
227 xfs_ifork_zone = kmem_zone_init(sizeof(struct xfs_ifork), "xfs_ifork");
228 xfs_ili_zone = kmem_zone_init(
229 sizeof(struct xfs_inode_log_item),"xfs_inode_log_item");
230 xfs_buf_item_zone = kmem_zone_init(
231 sizeof(struct xfs_buf_log_item), "xfs_buf_log_item");
232 xfs_da_state_zone = kmem_zone_init(
233 sizeof(struct xfs_da_state), "xfs_da_state");
234 xfs_btree_cur_zone = kmem_zone_init(
235 sizeof(struct xfs_btree_cur), "xfs_btree_cur");
236 xfs_bmap_free_item_zone = kmem_zone_init(
237 sizeof(struct xfs_extent_free_item),
238 "xfs_bmap_free_item");
239 xfs_trans_zone = kmem_zone_init(
240 sizeof(struct xfs_trans), "xfs_trans");
241}
242
243static int
244destroy_zones(void)
245{
246 int leaked = 0;
247
248 leaked += kmem_zone_destroy(xfs_buf_zone);
249 leaked += kmem_zone_destroy(xfs_ili_zone);
250 leaked += kmem_zone_destroy(xfs_inode_zone);
251 leaked += kmem_zone_destroy(xfs_ifork_zone);
252 leaked += kmem_zone_destroy(xfs_buf_item_zone);
253 leaked += kmem_zone_destroy(xfs_da_state_zone);
254 leaked += kmem_zone_destroy(xfs_btree_cur_zone);
255 leaked += kmem_zone_destroy(xfs_bmap_free_item_zone);
256 leaked += kmem_zone_destroy(xfs_trans_zone);
257
258 return leaked;
259}
260
2bd0ea18
NS
261/*
262 * libxfs initialization.
263 * Caller gets a 0 on failure (and we print a message), 1 on success.
264 */
265int
266libxfs_init(libxfs_init_t *a)
267{
268 char *blockfile;
2bd0ea18
NS
269 char *dname;
270 char dpath[25];
271 int fd;
272 char *logname;
273 char logpath[25];
2bd0ea18
NS
274 char *rawfile;
275 char *rtname;
276 char rtpath[25];
277 int rval = 0;
c781939c 278 int flags;
2bd0ea18
NS
279
280 dpath[0] = logpath[0] = rtpath[0] = '\0';
281 dname = a->dname;
282 logname = a->logname;
283 rtname = a->rtname;
2bd0ea18 284 a->dfd = a->logfd = a->rtfd = -1;
74668075 285 a->ddev = a->logdev = a->rtdev = 0;
06ac92fd
DC
286 a->dsize = a->lbsize = a->rtbsize = 0;
287 a->dbsize = a->logBBsize = a->logBBstart = a->rtsize = 0;
2bd0ea18 288
2bd0ea18 289 fd = -1;
b74a1f6a 290 flags = (a->isreadonly | a->isdirect);
c781939c 291
bacd44a5
AE
292 radix_tree_init();
293
2bd0ea18 294 if (a->volname) {
c781939c 295 if(!check_open(a->volname,flags,&rawfile,&blockfile))
2bd0ea18 296 goto done;
2bd0ea18 297 fd = open(rawfile, O_RDONLY);
eb37fca5
NS
298 dname = a->dname = a->volname;
299 a->volname = NULL;
2bd0ea18 300 }
2bd0ea18 301 if (dname) {
2bd0ea18 302 if (a->disfile) {
7eb6693f 303 a->ddev= libxfs_device_open(dname, a->dcreat, flags,
c5907b96 304 a->setblksize);
2bd0ea18 305 a->dfd = libxfs_device_to_fd(a->ddev);
06ac92fd
DC
306 platform_findsizes(dname, a->dfd, &a->dsize,
307 &a->dbsize);
2bd0ea18 308 } else {
f02037ce 309 if (!check_open(dname, flags, &rawfile, &blockfile))
2bd0ea18
NS
310 goto done;
311 a->ddev = libxfs_device_open(rawfile,
7eb6693f 312 a->dcreat, flags, a->setblksize);
2bd0ea18 313 a->dfd = libxfs_device_to_fd(a->ddev);
f02037ce 314 platform_findsizes(rawfile, a->dfd,
06ac92fd 315 &a->dsize, &a->dbsize);
2bd0ea18 316 }
2bd0ea18
NS
317 } else
318 a->dsize = 0;
319 if (logname) {
2bd0ea18
NS
320 if (a->lisfile) {
321 a->logdev = libxfs_device_open(logname,
7eb6693f 322 a->lcreat, flags, a->setblksize);
2bd0ea18 323 a->logfd = libxfs_device_to_fd(a->logdev);
06ac92fd
DC
324 platform_findsizes(dname, a->logfd, &a->logBBsize,
325 &a->lbsize);
2bd0ea18 326 } else {
f02037ce 327 if (!check_open(logname, flags, &rawfile, &blockfile))
2bd0ea18
NS
328 goto done;
329 a->logdev = libxfs_device_open(rawfile,
7eb6693f 330 a->lcreat, flags, a->setblksize);
2bd0ea18 331 a->logfd = libxfs_device_to_fd(a->logdev);
f02037ce 332 platform_findsizes(rawfile, a->logfd,
06ac92fd 333 &a->logBBsize, &a->lbsize);
2bd0ea18 334 }
2bd0ea18
NS
335 } else
336 a->logBBsize = 0;
337 if (rtname) {
2bd0ea18
NS
338 if (a->risfile) {
339 a->rtdev = libxfs_device_open(rtname,
7eb6693f 340 a->rcreat, flags, a->setblksize);
2bd0ea18 341 a->rtfd = libxfs_device_to_fd(a->rtdev);
06ac92fd
DC
342 platform_findsizes(dname, a->rtfd, &a->rtsize,
343 &a->rtbsize);
2bd0ea18 344 } else {
f02037ce 345 if (!check_open(rtname, flags, &rawfile, &blockfile))
2bd0ea18
NS
346 goto done;
347 a->rtdev = libxfs_device_open(rawfile,
7eb6693f 348 a->rcreat, flags, a->setblksize);
2bd0ea18 349 a->rtfd = libxfs_device_to_fd(a->rtdev);
f02037ce 350 platform_findsizes(rawfile, a->rtfd,
06ac92fd 351 &a->rtsize, &a->rtbsize);
2bd0ea18 352 }
2bd0ea18
NS
353 } else
354 a->rtsize = 0;
355 if (a->dsize < 0) {
9440d84d 356 fprintf(stderr, _("%s: can't get size for data subvolume\n"),
2bd0ea18
NS
357 progname);
358 goto done;
359 }
360 if (a->logBBsize < 0) {
9440d84d 361 fprintf(stderr, _("%s: can't get size for log subvolume\n"),
2bd0ea18
NS
362 progname);
363 goto done;
364 }
365 if (a->rtsize < 0) {
9440d84d 366 fprintf(stderr, _("%s: can't get size for realtime subvolume\n"),
2bd0ea18
NS
367 progname);
368 goto done;
369 }
9f38f08d
MV
370 if (!libxfs_bhash_size)
371 libxfs_bhash_size = LIBXFS_BHASHSIZE(sbp);
ba9ecd40
DC
372 libxfs_bcache = cache_init(a->bcache_flags, libxfs_bhash_size,
373 &libxfs_bcache_operations);
d0572de5 374 use_xfs_buf_lock = a->usebuflock;
7a326ce0
ES
375 xfs_dir_startup();
376 init_zones();
2bd0ea18
NS
377 rval = 1;
378done:
379 if (dpath[0])
380 unlink(dpath);
381 if (logpath[0])
382 unlink(logpath);
383 if (rtpath[0])
384 unlink(rtpath);
385 if (fd >= 0)
386 close(fd);
387 if (!rval && a->ddev)
388 libxfs_device_close(a->ddev);
389 if (!rval && a->logdev)
390 libxfs_device_close(a->logdev);
391 if (!rval && a->rtdev)
392 libxfs_device_close(a->rtdev);
393 return rval;
394}
395
396
b391b7cd
NS
397/*
398 * Initialize realtime fields in the mount structure.
399 */
400static int
401rtmount_init(
39798eb5
NS
402 xfs_mount_t *mp, /* file system mount structure */
403 int flags)
b391b7cd
NS
404{
405 xfs_buf_t *bp; /* buffer for last block of subvolume */
406 xfs_daddr_t d; /* address of last block of subvolume */
407 xfs_sb_t *sbp; /* filesystem superblock copy in mount */
408
409 sbp = &mp->m_sb;
410 if (sbp->sb_rblocks == 0)
411 return 0;
75c8b434 412 if (mp->m_rtdev_targp->dev == 0 && !(flags & LIBXFS_MOUNT_DEBUGGER)) {
9440d84d 413 fprintf(stderr, _("%s: filesystem has a realtime subvolume\n"),
b391b7cd
NS
414 progname);
415 return -1;
416 }
417 mp->m_rsumlevels = sbp->sb_rextslog + 1;
418 mp->m_rsumsize =
419 (uint)sizeof(xfs_suminfo_t) * mp->m_rsumlevels *
420 sbp->sb_rbmblocks;
421 mp->m_rsumsize = roundup(mp->m_rsumsize, sbp->sb_blocksize);
422 mp->m_rbmip = mp->m_rsumip = NULL;
39798eb5
NS
423
424 /*
425 * Allow debugger to be run without the realtime device present.
426 */
427 if (flags & LIBXFS_MOUNT_DEBUGGER)
428 return 0;
429
b391b7cd
NS
430 /*
431 * Check that the realtime section is an ok size.
432 */
433 d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
434 if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_rblocks) {
9440d84d
NS
435 fprintf(stderr, _("%s: realtime init - %llu != %llu\n"),
436 progname, (unsigned long long) XFS_BB_TO_FSB(mp, d),
b391b7cd
NS
437 (unsigned long long) mp->m_sb.sb_rblocks);
438 return -1;
439 }
9440d84d 440 bp = libxfs_readbuf(mp->m_rtdev,
75c8b434 441 d - XFS_FSB_TO_BB(mp, 1), XFS_FSB_TO_BB(mp, 1), 0, NULL);
b391b7cd 442 if (bp == NULL) {
9440d84d
NS
443 fprintf(stderr, _("%s: realtime size check failed\n"),
444 progname);
b391b7cd
NS
445 return -1;
446 }
447 libxfs_putbuf(bp);
448 return 0;
449}
450
56b2de80
DC
451static int
452libxfs_initialize_perag(
453 xfs_mount_t *mp,
454 xfs_agnumber_t agcount,
455 xfs_agnumber_t *maxagi)
456{
457 xfs_agnumber_t index, max_metadata;
458 xfs_agnumber_t first_initialised = 0;
459 xfs_perag_t *pag;
460 xfs_agino_t agino;
461 xfs_ino_t ino;
462 xfs_sb_t *sbp = &mp->m_sb;
463 int error = -ENOMEM;
464
465 /*
466 * Walk the current per-ag tree so we don't try to initialise AGs
467 * that already exist (growfs case). Allocate and insert all the
468 * AGs we don't find ready for initialisation.
469 */
470 for (index = 0; index < agcount; index++) {
471 pag = xfs_perag_get(mp, index);
472 if (pag) {
473 xfs_perag_put(pag);
474 continue;
475 }
476 if (!first_initialised)
477 first_initialised = index;
478
479 pag = kmem_zalloc(sizeof(*pag), KM_MAYFAIL);
480 if (!pag)
481 goto out_unwind;
482 pag->pag_agno = index;
483 pag->pag_mount = mp;
484
485 if (radix_tree_insert(&mp->m_perag_tree, index, pag)) {
486 error = -EEXIST;
487 goto out_unwind;
488 }
489 }
490
491 /*
492 * If we mount with the inode64 option, or no inode overflows
493 * the legacy 32-bit address space clear the inode32 option.
494 */
7516da71 495 agino = XFS_AGB_TO_AGINO(mp, sbp->sb_agblocks - 1);
56b2de80
DC
496 ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino);
497
498 if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > XFS_MAXINUMBER_32)
499 mp->m_flags |= XFS_MOUNT_32BITINODES;
500 else
501 mp->m_flags &= ~XFS_MOUNT_32BITINODES;
502
503 if (mp->m_flags & XFS_MOUNT_32BITINODES) {
504 /*
505 * Calculate how much should be reserved for inodes to meet
506 * the max inode percentage.
507 */
e7fd2b6f 508 if (M_IGEO(mp)->maxicount) {
14f8b681 509 uint64_t icount;
56b2de80
DC
510
511 icount = sbp->sb_dblocks * sbp->sb_imax_pct;
512 do_div(icount, 100);
513 icount += sbp->sb_agblocks - 1;
514 do_div(icount, sbp->sb_agblocks);
515 max_metadata = icount;
516 } else {
517 max_metadata = agcount;
518 }
519
520 for (index = 0; index < agcount; index++) {
521 ino = XFS_AGINO_TO_INO(mp, index, agino);
522 if (ino > XFS_MAXINUMBER_32) {
523 index++;
524 break;
525 }
526
527 pag = xfs_perag_get(mp, index);
528 pag->pagi_inodeok = 1;
529 if (index < max_metadata)
530 pag->pagf_metadata = 1;
531 xfs_perag_put(pag);
532 }
533 } else {
534 for (index = 0; index < agcount; index++) {
535 pag = xfs_perag_get(mp, index);
536 pag->pagi_inodeok = 1;
537 xfs_perag_put(pag);
538 }
539 }
540
541 if (maxagi)
542 *maxagi = index;
ef5340cd
DW
543
544 mp->m_ag_prealloc_blocks = xfs_prealloc_blocks(mp);
56b2de80
DC
545 return 0;
546
547out_unwind:
548 kmem_free(pag);
549 for (; index > first_initialised; index--) {
550 pag = radix_tree_delete(&mp->m_perag_tree, index);
551 kmem_free(pag);
552 }
553 return error;
554}
555
75c8b434
DC
556static struct xfs_buftarg *
557libxfs_buftarg_alloc(
558 struct xfs_mount *mp,
559 dev_t dev)
560{
561 struct xfs_buftarg *btp;
562
563 btp = malloc(sizeof(*btp));
564 if (!btp) {
565 fprintf(stderr, _("%s: buftarg init failed\n"),
566 progname);
567 exit(1);
568 }
569 btp->bt_mount = mp;
570 btp->dev = dev;
571 return btp;
572}
573
574void
575libxfs_buftarg_init(
576 struct xfs_mount *mp,
577 dev_t dev,
578 dev_t logdev,
579 dev_t rtdev)
580{
581 if (mp->m_ddev_targp) {
582 /* should already have all buftargs initialised */
583 if (mp->m_ddev_targp->dev != dev ||
584 mp->m_ddev_targp->bt_mount != mp) {
585 fprintf(stderr,
586 _("%s: bad buftarg reinit, ddev\n"),
587 progname);
588 exit(1);
589 }
590 if (!logdev || logdev == dev) {
591 if (mp->m_logdev_targp != mp->m_ddev_targp) {
592 fprintf(stderr,
593 _("%s: bad buftarg reinit, ldev mismatch\n"),
594 progname);
595 exit(1);
596 }
597 } else if (mp->m_logdev_targp->dev != logdev ||
598 mp->m_logdev_targp->bt_mount != mp) {
599 fprintf(stderr,
600 _("%s: bad buftarg reinit, logdev\n"),
601 progname);
602 exit(1);
603 }
604 if (rtdev && (mp->m_rtdev_targp->dev != rtdev ||
605 mp->m_rtdev_targp->bt_mount != mp)) {
606 fprintf(stderr,
607 _("%s: bad buftarg reinit, rtdev\n"),
608 progname);
609 exit(1);
610 }
611 return;
612 }
613
614 mp->m_ddev_targp = libxfs_buftarg_alloc(mp, dev);
615 if (!logdev || logdev == dev)
616 mp->m_logdev_targp = mp->m_ddev_targp;
617 else
618 mp->m_logdev_targp = libxfs_buftarg_alloc(mp, logdev);
619 mp->m_rtdev_targp = libxfs_buftarg_alloc(mp, rtdev);
620}
621
2bd0ea18
NS
622/*
623 * Mount structure initialization, provides a filled-in xfs_mount_t
624 * such that the numerous XFS_* macros can be used. If dev is zero,
625 * no IO will be performed (no size checks, read root inodes).
626 */
627xfs_mount_t *
628libxfs_mount(
629 xfs_mount_t *mp,
630 xfs_sb_t *sb,
631 dev_t dev,
632 dev_t logdev,
633 dev_t rtdev,
4ca431fc 634 int flags)
2bd0ea18
NS
635{
636 xfs_daddr_t d;
637 xfs_buf_t *bp;
638 xfs_sb_t *sbp;
2bd0ea18
NS
639 int error;
640
75c8b434
DC
641 libxfs_buftarg_init(mp, dev, logdev, rtdev);
642
f747f7dd 643 mp->m_finobt_nores = true;
6239071d 644 mp->m_flags = (LIBXFS_MOUNT_32BITINODES|LIBXFS_MOUNT_32BITINOOPT);
2bd0ea18 645 mp->m_sb = *sb;
56b2de80 646 INIT_RADIX_TREE(&mp->m_perag_tree, GFP_KERNEL);
2bd0ea18 647 sbp = &(mp->m_sb);
2bd0ea18 648
4896e6c8 649 xfs_sb_mount_common(mp, sb);
2bd0ea18 650
949c0f10
NS
651 /*
652 * Set whether we're using stripe alignment.
653 */
5e656dbb 654 if (xfs_sb_version_hasdalign(&mp->m_sb)) {
949c0f10
NS
655 mp->m_dalign = sbp->sb_unit;
656 mp->m_swidth = sbp->sb_width;
657 }
658
3a05ab22
DW
659 xfs_alloc_compute_maxlevels(mp);
660 xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK);
661 xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK);
662 xfs_ialloc_setup_geometry(mp);
663 xfs_rmapbt_compute_maxlevels(mp);
664 xfs_refcountbt_compute_maxlevels(mp);
2bd0ea18
NS
665
666 /*
667 * Check that the data (and log if separate) are an ok size.
668 */
9440d84d 669 d = (xfs_daddr_t) XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
2bd0ea18 670 if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) {
9440d84d 671 fprintf(stderr, _("%s: size check failed\n"), progname);
4ca431fc
NS
672 if (!(flags & LIBXFS_MOUNT_DEBUGGER))
673 return NULL;
2bd0ea18
NS
674 }
675
ff105f75
DC
676 /*
677 * We automatically convert v1 inodes to v2 inodes now, so if
678 * the NLINK bit is not set we can't operate on the filesystem.
679 */
680 if (!(sbp->sb_versionnum & XFS_SB_VERSION_NLINKBIT)) {
681
682 fprintf(stderr, _(
683 "%s: V1 inodes unsupported. Please try an older xfsprogs.\n"),
684 progname);
685 exit(1);
686 }
687
688 /* Check for supported directory formats */
689 if (!(sbp->sb_versionnum & XFS_SB_VERSION_DIRV2BIT)) {
9a048535
DC
690
691 fprintf(stderr, _(
692 "%s: V1 directories unsupported. Please try an older xfsprogs.\n"),
693 progname);
694 exit(1);
5e656dbb 695 }
2bd0ea18 696
ff105f75
DC
697 /* check for unsupported other features */
698 if (!xfs_sb_good_version(sbp)) {
699 fprintf(stderr, _(
700 "%s: Unsupported features detected. Please try a newer xfsprogs.\n"),
701 progname);
702 exit(1);
703 }
704
705 xfs_da_mount(mp);
706
5e656dbb
BN
707 if (xfs_sb_version_hasattr2(&mp->m_sb))
708 mp->m_flags |= LIBXFS_MOUNT_ATTR2;
57c9fccb 709
2bd0ea18 710 /* Initialize the precomputed transaction reservations values */
5e656dbb 711 xfs_trans_init(mp);
2bd0ea18
NS
712
713 if (dev == 0) /* maxtrres, we have no device so leave now */
714 return mp;
715
9440d84d 716 bp = libxfs_readbuf(mp->m_dev,
4ca431fc 717 d - XFS_FSS_TO_BB(mp, 1), XFS_FSS_TO_BB(mp, 1),
75c8b434 718 !(flags & LIBXFS_MOUNT_DEBUGGER), NULL);
9440d84d
NS
719 if (!bp) {
720 fprintf(stderr, _("%s: data size check failed\n"), progname);
4ca431fc
NS
721 if (!(flags & LIBXFS_MOUNT_DEBUGGER))
722 return NULL;
32244196
BN
723 } else
724 libxfs_putbuf(bp);
2bd0ea18 725
75c8b434
DC
726 if (mp->m_logdev_targp->dev &&
727 mp->m_logdev_targp->dev != mp->m_ddev_targp->dev) {
9440d84d 728 d = (xfs_daddr_t) XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
2bd0ea18 729 if ( (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) ||
75c8b434 730 (!(bp = libxfs_readbuf(mp->m_logdev_targp,
9440d84d 731 d - XFS_FSB_TO_BB(mp, 1),
4ca431fc 732 XFS_FSB_TO_BB(mp, 1),
75c8b434 733 !(flags & LIBXFS_MOUNT_DEBUGGER), NULL))) ) {
9440d84d 734 fprintf(stderr, _("%s: log size checks failed\n"),
2bd0ea18 735 progname);
4ca431fc
NS
736 if (!(flags & LIBXFS_MOUNT_DEBUGGER))
737 return NULL;
2bd0ea18 738 }
32244196
BN
739 if (bp)
740 libxfs_putbuf(bp);
2bd0ea18
NS
741 }
742
743 /* Initialize realtime fields in the mount structure */
39798eb5 744 if (rtmount_init(mp, flags)) {
9440d84d
NS
745 fprintf(stderr, _("%s: realtime device init failed\n"),
746 progname);
4ca431fc 747 return NULL;
2bd0ea18
NS
748 }
749
a547152d
ES
750 /*
751 * libxfs_initialize_perag will allocate a perag structure for each ag.
752 * If agcount is corrupted and insanely high, this will OOM the box.
753 * If the agount seems (arbitrarily) high, try to read what would be
754 * the last AG, and if that fails for a relatively high agcount, just
755 * read the first one and let the user know to check the geometry.
756 */
757 if (sbp->sb_agcount > 1000000) {
758 bp = libxfs_readbuf(mp->m_dev,
759 XFS_AG_DADDR(mp, sbp->sb_agcount - 1, 0), 1,
760 !(flags & LIBXFS_MOUNT_DEBUGGER), NULL);
761 if (bp->b_error) {
762 fprintf(stderr, _("%s: read of AG %u failed\n"),
763 progname, sbp->sb_agcount);
764 if (!(flags & LIBXFS_MOUNT_DEBUGGER))
765 return NULL;
766 fprintf(stderr, _("%s: limiting reads to AG 0\n"),
767 progname);
768 sbp->sb_agcount = 1;
769 }
770 libxfs_putbuf(bp);
771 }
772
56b2de80
DC
773 error = libxfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi);
774 if (error) {
775 fprintf(stderr, _("%s: perag init failed\n"),
776 progname);
2bd0ea18
NS
777 exit(1);
778 }
779
2bd0ea18
NS
780 return mp;
781}
782
f1b058f9
NS
783void
784libxfs_rtmount_destroy(xfs_mount_t *mp)
785{
786 if (mp->m_rsumip)
31845e4c 787 libxfs_irele(mp->m_rsumip);
f1b058f9 788 if (mp->m_rbmip)
31845e4c 789 libxfs_irele(mp->m_rbmip);
f1b058f9
NS
790 mp->m_rsumip = mp->m_rbmip = NULL;
791}
792
2bd0ea18 793/*
9440d84d 794 * Release any resource obtained during a mount.
2bd0ea18
NS
795 */
796void
797libxfs_umount(xfs_mount_t *mp)
798{
56b2de80
DC
799 struct xfs_perag *pag;
800 int agno;
801
f1b058f9 802 libxfs_rtmount_destroy(mp);
f1b058f9
NS
803 libxfs_bcache_purge();
804
56b2de80
DC
805 for (agno = 0; agno < mp->m_maxagi; agno++) {
806 pag = radix_tree_delete(&mp->m_perag_tree, agno);
807 kmem_free(pag);
fceb0d99 808 }
4334e2e8
ES
809
810 kmem_free(mp->m_attr_geo);
811 kmem_free(mp->m_dir_geo);
812
813 kmem_free(mp->m_rtdev_targp);
814 if (mp->m_logdev_targp != mp->m_ddev_targp)
815 kmem_free(mp->m_logdev_targp);
816 kmem_free(mp->m_ddev_targp);
f8149110 817
2bd0ea18 818}
f1b058f9
NS
819
820/*
821 * Release any global resources used by libxfs.
822 */
823void
824libxfs_destroy(void)
825{
44488491
ES
826 int leaked;
827
864028ed
ES
828 /* Free everything from the buffer cache before freeing buffer zone */
829 libxfs_bcache_purge();
830 libxfs_bcache_free();
f1b058f9 831 cache_destroy(libxfs_bcache);
7a326ce0 832 leaked = destroy_zones();
44488491
ES
833 if (getenv("LIBXFS_LEAK_CHECK") && leaked)
834 exit(1);
f1b058f9 835}
9f38f08d 836
b74a1f6a
NS
837int
838libxfs_device_alignment(void)
839{
840 return platform_align_blockdev();
841}
842
9f38f08d 843void
b6281496 844libxfs_report(FILE *fp)
9f38f08d 845{
cb5b3ef4
MV
846 time_t t;
847 char *c;
848
b6281496 849 cache_report(fp, "libxfs_bcache", libxfs_bcache);
cb5b3ef4
MV
850
851 t = time(NULL);
852 c = asctime(localtime(&t));
853 fprintf(fp, "%s", c);
854}