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