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