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