2 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
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
7 * published by the Free Software Foundation.
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.
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
22 #include "libxfs_priv.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_defer.h"
30 #include "xfs_inode_buf.h"
31 #include "xfs_inode_fork.h"
32 #include "xfs_inode.h"
33 #include "xfs_trans.h"
34 #include "xfs_rmap_btree.h"
35 #include "xfs_refcount_btree.h"
37 #include "libxfs.h" /* for now */
39 char *progname
= "libxfs"; /* default, changed by each tool */
41 struct cache
*libxfs_bcache
; /* global buffer cache */
42 int libxfs_bhash_size
; /* #buckets in bcache */
44 int use_xfs_buf_lock
; /* global flag: use xfs_buf_t locks for MT */
46 static void manage_zones(int); /* setup global zones */
48 kmem_zone_t
*xfs_inode_zone
;
51 * dev_map - map open devices to fd.
53 #define MAX_DEVS 10 /* arbitary maximum */
54 int nextfakedev
= -1; /* device number to give to next fake device */
55 static struct dev_to_fd
{
58 } dev_map
[MAX_DEVS
]={{0}};
61 * Checks whether a given device has a mounted, writable
62 * filesystem, returns 1 if it does & fatal (just warns
63 * if not fatal, but allows us to proceed).
65 * Useful to tools which will produce uncertain results
66 * if the filesystem is active - repair, check, logprint.
69 check_isactive(char *name
, char *block
, int fatal
)
73 if (stat(block
, &st
) < 0)
75 if ((st
.st_mode
& S_IFMT
) != S_IFBLK
)
77 if (platform_check_ismounted(name
, block
, &st
, 0) == 0)
79 if (platform_check_iswritable(name
, block
, &st
))
84 /* libxfs_device_to_fd:
85 * lookup a device number in the device map
86 * return the associated fd
89 libxfs_device_to_fd(dev_t device
)
93 for (d
= 0; d
< MAX_DEVS
; d
++)
94 if (dev_map
[d
].dev
== device
)
97 fprintf(stderr
, _("%s: %s: device %lld is not open\n"),
98 progname
, __FUNCTION__
, (long long)device
);
103 /* libxfs_device_open:
104 * open a device and return its device number
107 libxfs_device_open(char *path
, int creat
, int xflags
, int setblksize
)
111 int readonly
, dio
, excl
;
114 readonly
= (xflags
& LIBXFS_ISREADONLY
);
115 excl
= (xflags
& LIBXFS_EXCLUSIVELY
) && !creat
;
116 dio
= (xflags
& LIBXFS_DIRECT
) && !creat
&& platform_direct_blockdev();
119 flags
= (readonly
? O_RDONLY
: O_RDWR
) | \
120 (creat
? (O_CREAT
|O_TRUNC
) : 0) | \
121 (dio
? O_DIRECT
: 0) | \
124 if ((fd
= open(path
, flags
, 0666)) < 0) {
125 if (errno
== EINVAL
&& --dio
== 0)
127 fprintf(stderr
, _("%s: cannot open %s: %s\n"),
128 progname
, path
, strerror(errno
));
132 if (fstat(fd
, &statb
) < 0) {
133 fprintf(stderr
, _("%s: cannot stat %s: %s\n"),
134 progname
, path
, strerror(errno
));
138 if (!readonly
&& setblksize
&& (statb
.st_mode
& S_IFMT
) == S_IFBLK
) {
140 /* use the default blocksize */
141 (void)platform_set_blocksize(fd
, path
, statb
.st_rdev
, XFS_MIN_SECTORSIZE
, 0);
143 /* given an explicit blocksize to use */
144 if (platform_set_blocksize(fd
, path
, statb
.st_rdev
, setblksize
, 1))
150 * Get the device number from the stat buf - unless
151 * we're not opening a real device, in which case
152 * choose a new fake device number.
154 dev
= (statb
.st_rdev
) ? (statb
.st_rdev
) : (nextfakedev
--);
156 for (d
= 0; d
< MAX_DEVS
; d
++)
157 if (dev_map
[d
].dev
== dev
) {
158 fprintf(stderr
, _("%s: device %lld is already open\n"),
159 progname
, (long long)dev
);
163 for (d
= 0; d
< MAX_DEVS
; d
++)
164 if (!dev_map
[d
].dev
) {
165 dev_map
[d
].dev
= dev
;
171 fprintf(stderr
, _("%s: %s: too many open devices\n"),
172 progname
, __FUNCTION__
);
178 libxfs_device_close(dev_t dev
)
182 for (d
= 0; d
< MAX_DEVS
; d
++)
183 if (dev_map
[d
].dev
== dev
) {
187 dev_map
[d
].dev
= dev_map
[d
].fd
= 0;
190 platform_flush_device(fd
, dev
);
196 fprintf(stderr
, _("%s: %s: device %lld is not open\n"),
197 progname
, __FUNCTION__
, (long long)dev
);
202 check_open(char *path
, int flags
, char **rawfile
, char **blockfile
)
204 int readonly
= (flags
& LIBXFS_ISREADONLY
);
205 int inactive
= (flags
& LIBXFS_ISINACTIVE
);
206 int dangerously
= (flags
& LIBXFS_DANGEROUSLY
);
209 if (stat(path
, &stbuf
) < 0) {
213 if (!(*rawfile
= platform_findrawpath(path
))) {
214 fprintf(stderr
, _("%s: "
215 "can't find a character device matching %s\n"),
219 if (!(*blockfile
= platform_findblockpath(path
))) {
220 fprintf(stderr
, _("%s: "
221 "can't find a block device matching %s\n"),
225 if (!readonly
&& !inactive
&& platform_check_ismounted(path
, *blockfile
, NULL
, 1))
228 if (inactive
&& check_isactive(path
, *blockfile
, ((readonly
|dangerously
)?1:0)))
235 * libxfs initialization.
236 * Caller gets a 0 on failure (and we print a message), 1 on success.
239 libxfs_init(libxfs_init_t
*a
)
242 char curdir
[MAXPATHLEN
];
255 dpath
[0] = logpath
[0] = rtpath
[0] = '\0';
257 logname
= a
->logname
;
259 a
->dfd
= a
->logfd
= a
->rtfd
= -1;
260 a
->ddev
= a
->logdev
= a
->rtdev
= 0;
261 a
->dsize
= a
->lbsize
= a
->rtbsize
= 0;
262 a
->dbsize
= a
->logBBsize
= a
->logBBstart
= a
->rtsize
= 0;
264 (void)getcwd(curdir
,MAXPATHLEN
);
267 flags
= (a
->isreadonly
| a
->isdirect
);
269 xfs_extent_free_init_defer_op();
270 xfs_rmap_update_init_defer_op();
271 xfs_refcount_update_init_defer_op();
272 xfs_bmap_update_init_defer_op();
277 if(!check_open(a
->volname
,flags
,&rawfile
,&blockfile
))
280 fd
= open(rawfile
, O_RDONLY
);
281 dname
= a
->dname
= a
->volname
;
285 if (dname
[0] != '/' && needcd
)
288 a
->ddev
= libxfs_device_open(dname
, a
->dcreat
, flags
,
290 a
->dfd
= libxfs_device_to_fd(a
->ddev
);
291 platform_findsizes(dname
, a
->dfd
, &a
->dsize
,
294 if (!check_open(dname
, flags
, &rawfile
, &blockfile
))
296 a
->ddev
= libxfs_device_open(rawfile
,
297 a
->dcreat
, flags
, a
->setblksize
);
298 a
->dfd
= libxfs_device_to_fd(a
->ddev
);
299 platform_findsizes(rawfile
, a
->dfd
,
300 &a
->dsize
, &a
->dbsize
);
306 if (logname
[0] != '/' && needcd
)
309 a
->logdev
= libxfs_device_open(logname
,
310 a
->lcreat
, flags
, a
->setblksize
);
311 a
->logfd
= libxfs_device_to_fd(a
->logdev
);
312 platform_findsizes(dname
, a
->logfd
, &a
->logBBsize
,
315 if (!check_open(logname
, flags
, &rawfile
, &blockfile
))
317 a
->logdev
= libxfs_device_open(rawfile
,
318 a
->lcreat
, flags
, a
->setblksize
);
319 a
->logfd
= libxfs_device_to_fd(a
->logdev
);
320 platform_findsizes(rawfile
, a
->logfd
,
321 &a
->logBBsize
, &a
->lbsize
);
327 if (rtname
[0] != '/' && needcd
)
330 a
->rtdev
= libxfs_device_open(rtname
,
331 a
->rcreat
, flags
, a
->setblksize
);
332 a
->rtfd
= libxfs_device_to_fd(a
->rtdev
);
333 platform_findsizes(dname
, a
->rtfd
, &a
->rtsize
,
336 if (!check_open(rtname
, flags
, &rawfile
, &blockfile
))
338 a
->rtdev
= libxfs_device_open(rawfile
,
339 a
->rcreat
, flags
, a
->setblksize
);
340 a
->rtfd
= libxfs_device_to_fd(a
->rtdev
);
341 platform_findsizes(rawfile
, a
->rtfd
,
342 &a
->rtsize
, &a
->rtbsize
);
348 fprintf(stderr
, _("%s: can't get size for data subvolume\n"),
352 if (a
->logBBsize
< 0) {
353 fprintf(stderr
, _("%s: can't get size for log subvolume\n"),
358 fprintf(stderr
, _("%s: can't get size for realtime subvolume\n"),
364 if (!libxfs_bhash_size
)
365 libxfs_bhash_size
= LIBXFS_BHASHSIZE(sbp
);
366 libxfs_bcache
= cache_init(a
->bcache_flags
, libxfs_bhash_size
,
367 &libxfs_bcache_operations
);
368 use_xfs_buf_lock
= a
->usebuflock
;
380 if (!rval
&& a
->ddev
)
381 libxfs_device_close(a
->ddev
);
382 if (!rval
&& a
->logdev
)
383 libxfs_device_close(a
->logdev
);
384 if (!rval
&& a
->rtdev
)
385 libxfs_device_close(a
->rtdev
);
391 * Initialize/destroy all of the zone allocators we use.
394 manage_zones(int release
)
396 extern kmem_zone_t
*xfs_buf_zone
;
397 extern kmem_zone_t
*xfs_ili_zone
;
398 extern kmem_zone_t
*xfs_ifork_zone
;
399 extern kmem_zone_t
*xfs_buf_item_zone
;
400 extern kmem_zone_t
*xfs_da_state_zone
;
401 extern kmem_zone_t
*xfs_btree_cur_zone
;
402 extern kmem_zone_t
*xfs_bmap_free_item_zone
;
403 extern kmem_zone_t
*xfs_log_item_desc_zone
;
404 extern void xfs_dir_startup();
406 if (release
) { /* free zone allocation */
407 kmem_free(xfs_buf_zone
);
408 kmem_free(xfs_inode_zone
);
409 kmem_free(xfs_ifork_zone
);
410 kmem_free(xfs_buf_item_zone
);
411 kmem_free(xfs_da_state_zone
);
412 kmem_free(xfs_btree_cur_zone
);
413 kmem_free(xfs_bmap_free_item_zone
);
414 kmem_free(xfs_log_item_desc_zone
);
417 /* otherwise initialise zone allocation */
418 xfs_buf_zone
= kmem_zone_init(sizeof(xfs_buf_t
), "xfs_buffer");
419 xfs_inode_zone
= kmem_zone_init(sizeof(struct xfs_inode
), "xfs_inode");
420 xfs_ifork_zone
= kmem_zone_init(sizeof(xfs_ifork_t
), "xfs_ifork");
421 xfs_ili_zone
= kmem_zone_init(
422 sizeof(xfs_inode_log_item_t
), "xfs_inode_log_item");
423 xfs_buf_item_zone
= kmem_zone_init(
424 sizeof(xfs_buf_log_item_t
), "xfs_buf_log_item");
425 xfs_da_state_zone
= kmem_zone_init(
426 sizeof(xfs_da_state_t
), "xfs_da_state");
427 xfs_btree_cur_zone
= kmem_zone_init(
428 sizeof(xfs_btree_cur_t
), "xfs_btree_cur");
429 xfs_bmap_free_item_zone
= kmem_zone_init(
430 sizeof(struct xfs_extent_free_item
),
431 "xfs_bmap_free_item");
432 xfs_log_item_desc_zone
= kmem_zone_init(
433 sizeof(struct xfs_log_item_desc
), "xfs_log_item_desc");
438 * Initialize realtime fields in the mount structure.
442 xfs_mount_t
*mp
, /* file system mount structure */
445 xfs_buf_t
*bp
; /* buffer for last block of subvolume */
446 xfs_daddr_t d
; /* address of last block of subvolume */
447 xfs_sb_t
*sbp
; /* filesystem superblock copy in mount */
450 if (sbp
->sb_rblocks
== 0)
452 if (mp
->m_rtdev_targp
->dev
== 0 && !(flags
& LIBXFS_MOUNT_DEBUGGER
)) {
453 fprintf(stderr
, _("%s: filesystem has a realtime subvolume\n"),
457 mp
->m_rsumlevels
= sbp
->sb_rextslog
+ 1;
459 (uint
)sizeof(xfs_suminfo_t
) * mp
->m_rsumlevels
*
461 mp
->m_rsumsize
= roundup(mp
->m_rsumsize
, sbp
->sb_blocksize
);
462 mp
->m_rbmip
= mp
->m_rsumip
= NULL
;
465 * Allow debugger to be run without the realtime device present.
467 if (flags
& LIBXFS_MOUNT_DEBUGGER
)
471 * Check that the realtime section is an ok size.
473 d
= (xfs_daddr_t
)XFS_FSB_TO_BB(mp
, mp
->m_sb
.sb_rblocks
);
474 if (XFS_BB_TO_FSB(mp
, d
) != mp
->m_sb
.sb_rblocks
) {
475 fprintf(stderr
, _("%s: realtime init - %llu != %llu\n"),
476 progname
, (unsigned long long) XFS_BB_TO_FSB(mp
, d
),
477 (unsigned long long) mp
->m_sb
.sb_rblocks
);
480 bp
= libxfs_readbuf(mp
->m_rtdev
,
481 d
- XFS_FSB_TO_BB(mp
, 1), XFS_FSB_TO_BB(mp
, 1), 0, NULL
);
483 fprintf(stderr
, _("%s: realtime size check failed\n"),
492 libxfs_initialize_perag(
494 xfs_agnumber_t agcount
,
495 xfs_agnumber_t
*maxagi
)
497 xfs_agnumber_t index
, max_metadata
;
498 xfs_agnumber_t first_initialised
= 0;
502 xfs_sb_t
*sbp
= &mp
->m_sb
;
506 * Walk the current per-ag tree so we don't try to initialise AGs
507 * that already exist (growfs case). Allocate and insert all the
508 * AGs we don't find ready for initialisation.
510 for (index
= 0; index
< agcount
; index
++) {
511 pag
= xfs_perag_get(mp
, index
);
516 if (!first_initialised
)
517 first_initialised
= index
;
519 pag
= kmem_zalloc(sizeof(*pag
), KM_MAYFAIL
);
522 pag
->pag_agno
= index
;
525 if (radix_tree_insert(&mp
->m_perag_tree
, index
, pag
)) {
532 * If we mount with the inode64 option, or no inode overflows
533 * the legacy 32-bit address space clear the inode32 option.
535 agino
= XFS_OFFBNO_TO_AGINO(mp
, sbp
->sb_agblocks
- 1, 0);
536 ino
= XFS_AGINO_TO_INO(mp
, agcount
- 1, agino
);
538 if ((mp
->m_flags
& XFS_MOUNT_SMALL_INUMS
) && ino
> XFS_MAXINUMBER_32
)
539 mp
->m_flags
|= XFS_MOUNT_32BITINODES
;
541 mp
->m_flags
&= ~XFS_MOUNT_32BITINODES
;
543 if (mp
->m_flags
& XFS_MOUNT_32BITINODES
) {
545 * Calculate how much should be reserved for inodes to meet
546 * the max inode percentage.
548 if (mp
->m_maxicount
) {
551 icount
= sbp
->sb_dblocks
* sbp
->sb_imax_pct
;
553 icount
+= sbp
->sb_agblocks
- 1;
554 do_div(icount
, sbp
->sb_agblocks
);
555 max_metadata
= icount
;
557 max_metadata
= agcount
;
560 for (index
= 0; index
< agcount
; index
++) {
561 ino
= XFS_AGINO_TO_INO(mp
, index
, agino
);
562 if (ino
> XFS_MAXINUMBER_32
) {
567 pag
= xfs_perag_get(mp
, index
);
568 pag
->pagi_inodeok
= 1;
569 if (index
< max_metadata
)
570 pag
->pagf_metadata
= 1;
574 for (index
= 0; index
< agcount
; index
++) {
575 pag
= xfs_perag_get(mp
, index
);
576 pag
->pagi_inodeok
= 1;
584 mp
->m_ag_prealloc_blocks
= xfs_prealloc_blocks(mp
);
589 for (; index
> first_initialised
; index
--) {
590 pag
= radix_tree_delete(&mp
->m_perag_tree
, index
);
596 static struct xfs_buftarg
*
597 libxfs_buftarg_alloc(
598 struct xfs_mount
*mp
,
601 struct xfs_buftarg
*btp
;
603 btp
= malloc(sizeof(*btp
));
605 fprintf(stderr
, _("%s: buftarg init failed\n"),
616 struct xfs_mount
*mp
,
621 if (mp
->m_ddev_targp
) {
622 /* should already have all buftargs initialised */
623 if (mp
->m_ddev_targp
->dev
!= dev
||
624 mp
->m_ddev_targp
->bt_mount
!= mp
) {
626 _("%s: bad buftarg reinit, ddev\n"),
630 if (!logdev
|| logdev
== dev
) {
631 if (mp
->m_logdev_targp
!= mp
->m_ddev_targp
) {
633 _("%s: bad buftarg reinit, ldev mismatch\n"),
637 } else if (mp
->m_logdev_targp
->dev
!= logdev
||
638 mp
->m_logdev_targp
->bt_mount
!= mp
) {
640 _("%s: bad buftarg reinit, logdev\n"),
644 if (rtdev
&& (mp
->m_rtdev_targp
->dev
!= rtdev
||
645 mp
->m_rtdev_targp
->bt_mount
!= mp
)) {
647 _("%s: bad buftarg reinit, rtdev\n"),
654 mp
->m_ddev_targp
= libxfs_buftarg_alloc(mp
, dev
);
655 if (!logdev
|| logdev
== dev
)
656 mp
->m_logdev_targp
= mp
->m_ddev_targp
;
658 mp
->m_logdev_targp
= libxfs_buftarg_alloc(mp
, logdev
);
659 mp
->m_rtdev_targp
= libxfs_buftarg_alloc(mp
, rtdev
);
663 * Mount structure initialization, provides a filled-in xfs_mount_t
664 * such that the numerous XFS_* macros can be used. If dev is zero,
665 * no IO will be performed (no size checks, read root inodes).
681 libxfs_buftarg_init(mp
, dev
, logdev
, rtdev
);
683 mp
->m_flags
= (LIBXFS_MOUNT_32BITINODES
|LIBXFS_MOUNT_32BITINOOPT
);
685 INIT_RADIX_TREE(&mp
->m_perag_tree
, GFP_KERNEL
);
688 xfs_sb_mount_common(mp
, sb
);
690 xfs_alloc_compute_maxlevels(mp
);
691 xfs_bmap_compute_maxlevels(mp
, XFS_DATA_FORK
);
692 xfs_bmap_compute_maxlevels(mp
, XFS_ATTR_FORK
);
693 xfs_ialloc_compute_maxlevels(mp
);
694 xfs_rmapbt_compute_maxlevels(mp
);
695 xfs_refcountbt_compute_maxlevels(mp
);
697 if (sbp
->sb_imax_pct
) {
698 /* Make sure the maximum inode count is a multiple of the
699 * units we allocate inodes in.
701 mp
->m_maxicount
= (sbp
->sb_dblocks
* sbp
->sb_imax_pct
) / 100;
702 mp
->m_maxicount
= ((mp
->m_maxicount
/ mp
->m_ialloc_blks
) *
703 mp
->m_ialloc_blks
) << sbp
->sb_inopblog
;
707 mp
->m_inode_cluster_size
= XFS_INODE_BIG_CLUSTER_SIZE
;
710 * Set whether we're using stripe alignment.
712 if (xfs_sb_version_hasdalign(&mp
->m_sb
)) {
713 mp
->m_dalign
= sbp
->sb_unit
;
714 mp
->m_swidth
= sbp
->sb_width
;
718 * Set whether we're using inode alignment.
720 if (xfs_sb_version_hasalign(&mp
->m_sb
) &&
721 mp
->m_sb
.sb_inoalignmt
>=
722 XFS_B_TO_FSBT(mp
, mp
->m_inode_cluster_size
))
723 mp
->m_inoalign_mask
= mp
->m_sb
.sb_inoalignmt
- 1;
725 mp
->m_inoalign_mask
= 0;
727 * If we are using stripe alignment, check whether
728 * the stripe unit is a multiple of the inode alignment
730 if (mp
->m_dalign
&& mp
->m_inoalign_mask
&&
731 !(mp
->m_dalign
& mp
->m_inoalign_mask
))
732 mp
->m_sinoalign
= mp
->m_dalign
;
737 * Check that the data (and log if separate) are an ok size.
739 d
= (xfs_daddr_t
) XFS_FSB_TO_BB(mp
, mp
->m_sb
.sb_dblocks
);
740 if (XFS_BB_TO_FSB(mp
, d
) != mp
->m_sb
.sb_dblocks
) {
741 fprintf(stderr
, _("%s: size check failed\n"), progname
);
742 if (!(flags
& LIBXFS_MOUNT_DEBUGGER
))
747 * We automatically convert v1 inodes to v2 inodes now, so if
748 * the NLINK bit is not set we can't operate on the filesystem.
750 if (!(sbp
->sb_versionnum
& XFS_SB_VERSION_NLINKBIT
)) {
753 "%s: V1 inodes unsupported. Please try an older xfsprogs.\n"),
758 /* Check for supported directory formats */
759 if (!(sbp
->sb_versionnum
& XFS_SB_VERSION_DIRV2BIT
)) {
762 "%s: V1 directories unsupported. Please try an older xfsprogs.\n"),
767 /* check for unsupported other features */
768 if (!xfs_sb_good_version(sbp
)) {
770 "%s: Unsupported features detected. Please try a newer xfsprogs.\n"),
777 if (xfs_sb_version_hasattr2(&mp
->m_sb
))
778 mp
->m_flags
|= LIBXFS_MOUNT_ATTR2
;
780 /* Initialize the precomputed transaction reservations values */
783 if (dev
== 0) /* maxtrres, we have no device so leave now */
786 bp
= libxfs_readbuf(mp
->m_dev
,
787 d
- XFS_FSS_TO_BB(mp
, 1), XFS_FSS_TO_BB(mp
, 1),
788 !(flags
& LIBXFS_MOUNT_DEBUGGER
), NULL
);
790 fprintf(stderr
, _("%s: data size check failed\n"), progname
);
791 if (!(flags
& LIBXFS_MOUNT_DEBUGGER
))
796 if (mp
->m_logdev_targp
->dev
&&
797 mp
->m_logdev_targp
->dev
!= mp
->m_ddev_targp
->dev
) {
798 d
= (xfs_daddr_t
) XFS_FSB_TO_BB(mp
, mp
->m_sb
.sb_logblocks
);
799 if ( (XFS_BB_TO_FSB(mp
, d
) != mp
->m_sb
.sb_logblocks
) ||
800 (!(bp
= libxfs_readbuf(mp
->m_logdev_targp
,
801 d
- XFS_FSB_TO_BB(mp
, 1),
802 XFS_FSB_TO_BB(mp
, 1),
803 !(flags
& LIBXFS_MOUNT_DEBUGGER
), NULL
))) ) {
804 fprintf(stderr
, _("%s: log size checks failed\n"),
806 if (!(flags
& LIBXFS_MOUNT_DEBUGGER
))
813 /* Initialize realtime fields in the mount structure */
814 if (rtmount_init(mp
, flags
)) {
815 fprintf(stderr
, _("%s: realtime device init failed\n"),
820 error
= libxfs_initialize_perag(mp
, sbp
->sb_agcount
, &mp
->m_maxagi
);
822 fprintf(stderr
, _("%s: perag init failed\n"),
831 libxfs_rtmount_destroy(xfs_mount_t
*mp
)
837 mp
->m_rsumip
= mp
->m_rbmip
= NULL
;
841 * Release any resource obtained during a mount.
844 libxfs_umount(xfs_mount_t
*mp
)
846 struct xfs_perag
*pag
;
849 libxfs_rtmount_destroy(mp
);
850 libxfs_bcache_purge();
852 for (agno
= 0; agno
< mp
->m_maxagi
; agno
++) {
853 pag
= radix_tree_delete(&mp
->m_perag_tree
, agno
);
857 kmem_free(mp
->m_attr_geo
);
858 kmem_free(mp
->m_dir_geo
);
860 kmem_free(mp
->m_rtdev_targp
);
861 if (mp
->m_logdev_targp
!= mp
->m_ddev_targp
)
862 kmem_free(mp
->m_logdev_targp
);
863 kmem_free(mp
->m_ddev_targp
);
868 * Release any global resources used by libxfs.
874 cache_destroy(libxfs_bcache
);
878 libxfs_device_alignment(void)
880 return platform_align_blockdev();
884 libxfs_report(FILE *fp
)
889 cache_report(fp
, "libxfs_bcache", libxfs_bcache
);
892 c
= asctime(localtime(&t
));
893 fprintf(fp
, "%s", c
);
899 return platform_nproc();
905 return platform_physmem();