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
19 #include <xfs/libxfs.h>
23 char *progname
= "libxfs"; /* default, changed by each tool */
25 struct cache
*libxfs_icache
; /* global inode cache */
26 int libxfs_ihash_size
; /* #buckets in icache */
28 struct cache
*libxfs_bcache
; /* global buffer cache */
29 int libxfs_bhash_size
; /* #buckets in bcache */
31 static void manage_zones(int); /* setup global zones */
34 * dev_map - map open devices to fd.
36 #define MAX_DEVS 10 /* arbitary maximum */
37 int nextfakedev
= -1; /* device number to give to next fake device */
38 static struct dev_to_fd
{
41 } dev_map
[MAX_DEVS
]={{0}};
44 * Checks whether a given device has a mounted, writable
45 * filesystem, returns 1 if it does & fatal (just warns
46 * if not fatal, but allows us to proceed).
48 * Useful to tools which will produce uncertain results
49 * if the filesystem is active - repair, check, logprint.
52 check_isactive(char *name
, char *block
, int fatal
)
56 if (stat64(block
, &st
) < 0)
58 if ((st
.st_mode
& S_IFMT
) != S_IFBLK
)
60 if (platform_check_ismounted(name
, block
, &st
, 0) == 0)
62 return platform_check_iswritable(name
, block
, &st
, fatal
);
65 /* libxfs_device_to_fd:
66 * lookup a device number in the device map
67 * return the associated fd
70 libxfs_device_to_fd(dev_t device
)
74 for (d
= 0; d
< MAX_DEVS
; d
++)
75 if (dev_map
[d
].dev
== device
)
78 fprintf(stderr
, _("%s: %s: device %lld is not open\n"),
79 progname
, __FUNCTION__
, (long long)device
);
84 /* libxfs_device_open:
85 * open a device and return its device number
88 libxfs_device_open(char *path
, int creat
, int xflags
, int setblksize
)
92 int readonly
, dio
, excl
;
95 readonly
= (xflags
& LIBXFS_ISREADONLY
);
96 excl
= (xflags
& LIBXFS_EXCLUSIVELY
) && !creat
;
97 dio
= (xflags
& LIBXFS_DIRECT
) && !creat
&& platform_direct_blockdev();
100 flags
= (readonly
? O_RDONLY
: O_RDWR
) | \
101 (creat
? (O_CREAT
|O_TRUNC
) : 0) | \
102 (dio
? O_DIRECT
: 0) | \
105 if ((fd
= open(path
, flags
, 0666)) < 0) {
106 if (errno
== EINVAL
&& --dio
== 0)
108 fprintf(stderr
, _("%s: cannot open %s: %s\n"),
109 progname
, path
, strerror(errno
));
113 if (fstat64(fd
, &statb
) < 0) {
114 fprintf(stderr
, _("%s: cannot stat %s: %s\n"),
115 progname
, path
, strerror(errno
));
119 if (!readonly
&& setblksize
&& (statb
.st_mode
& S_IFMT
) == S_IFBLK
) {
120 platform_set_blocksize(fd
, path
, 512);
124 * Get the device number from the stat buf - unless
125 * we're not opening a real device, in which case
126 * choose a new fake device number.
128 dev
= (statb
.st_rdev
) ? (statb
.st_rdev
) : (nextfakedev
--);
130 for (d
= 0; d
< MAX_DEVS
; d
++)
131 if (dev_map
[d
].dev
== dev
) {
132 fprintf(stderr
, _("%s: device %lld is already open\n"),
133 progname
, (long long)dev
);
137 for (d
= 0; d
< MAX_DEVS
; d
++)
138 if (!dev_map
[d
].dev
) {
139 dev_map
[d
].dev
= dev
;
145 fprintf(stderr
, _("%s: %s: too many open devices\n"),
146 progname
, __FUNCTION__
);
152 libxfs_device_close(dev_t dev
)
156 for (d
= 0; d
< MAX_DEVS
; d
++)
157 if (dev_map
[d
].dev
== dev
) {
161 dev_map
[d
].dev
= dev_map
[d
].fd
= 0;
164 platform_flush_device(fd
, dev
);
170 fprintf(stderr
, _("%s: %s: device %lld is not open\n"),
171 progname
, __FUNCTION__
, (long long)dev
);
176 check_open(char *path
, int flags
, char **rawfile
, char **blockfile
)
178 int readonly
= (flags
& LIBXFS_ISREADONLY
);
179 int inactive
= (flags
& LIBXFS_ISINACTIVE
);
180 int dangerously
= (flags
& LIBXFS_DANGEROUSLY
);
183 if (stat64(path
, &stbuf
) < 0) {
187 if (!(*rawfile
= platform_findrawpath(path
))) {
188 fprintf(stderr
, _("%s: "
189 "can't find a character device matching %s\n"),
193 if (!(*blockfile
= platform_findblockpath(path
))) {
194 fprintf(stderr
, _("%s: "
195 "can't find a block device matching %s\n"),
199 if (!readonly
&& !inactive
&& platform_check_ismounted(path
, *blockfile
, NULL
, 1))
202 if (inactive
&& check_isactive(path
, *blockfile
, ((readonly
|dangerously
)?1:0)))
209 * libxfs initialization.
210 * Caller gets a 0 on failure (and we print a message), 1 on success.
213 libxfs_init(libxfs_init_t
*a
)
216 char curdir
[MAXPATHLEN
];
229 dpath
[0] = logpath
[0] = rtpath
[0] = '\0';
231 logname
= a
->logname
;
233 a
->dfd
= a
->logfd
= a
->rtfd
= -1;
234 a
->ddev
= a
->logdev
= a
->rtdev
= 0;
235 a
->dbsize
= a
->lbsize
= a
->rtbsize
= 0;
236 a
->dsize
= a
->logBBsize
= a
->logBBstart
= a
->rtsize
= 0;
238 (void)getcwd(curdir
,MAXPATHLEN
);
241 flags
= (a
->isreadonly
| a
->isdirect
);
244 if(!check_open(a
->volname
,flags
,&rawfile
,&blockfile
))
247 fd
= open(rawfile
, O_RDONLY
);
248 dname
= a
->dname
= a
->volname
;
252 if (dname
[0] != '/' && needcd
)
255 a
->ddev
= libxfs_device_open(dname
, a
->dcreat
, flags
,
257 a
->dfd
= libxfs_device_to_fd(a
->ddev
);
259 if (!check_open(dname
, flags
, &rawfile
, &blockfile
))
261 a
->ddev
= libxfs_device_open(rawfile
,
262 a
->dcreat
, flags
, a
->setblksize
);
263 a
->dfd
= libxfs_device_to_fd(a
->ddev
);
264 platform_findsizes(rawfile
, a
->dfd
,
265 &a
->dsize
, &a
->dbsize
);
271 if (logname
[0] != '/' && needcd
)
274 a
->logdev
= libxfs_device_open(logname
,
275 a
->lcreat
, flags
, a
->setblksize
);
276 a
->logfd
= libxfs_device_to_fd(a
->logdev
);
278 if (!check_open(logname
, flags
, &rawfile
, &blockfile
))
280 a
->logdev
= libxfs_device_open(rawfile
,
281 a
->lcreat
, flags
, a
->setblksize
);
282 a
->logfd
= libxfs_device_to_fd(a
->logdev
);
283 platform_findsizes(rawfile
, a
->logfd
,
284 &a
->logBBsize
, &a
->lbsize
);
290 if (rtname
[0] != '/' && needcd
)
293 a
->rtdev
= libxfs_device_open(rtname
,
294 a
->rcreat
, flags
, a
->setblksize
);
295 a
->rtfd
= libxfs_device_to_fd(a
->rtdev
);
297 if (!check_open(rtname
, flags
, &rawfile
, &blockfile
))
299 a
->rtdev
= libxfs_device_open(rawfile
,
300 a
->rcreat
, flags
, a
->setblksize
);
301 a
->rtfd
= libxfs_device_to_fd(a
->rtdev
);
302 platform_findsizes(rawfile
, a
->rtfd
,
303 &a
->rtsize
, &a
->rtbsize
);
309 fprintf(stderr
, _("%s: can't get size for data subvolume\n"),
313 if (a
->logBBsize
< 0) {
314 fprintf(stderr
, _("%s: can't get size for log subvolume\n"),
319 fprintf(stderr
, _("%s: can't get size for realtime subvolume\n"),
325 if (!libxfs_ihash_size
)
326 libxfs_ihash_size
= LIBXFS_IHASHSIZE(sbp
);
327 libxfs_icache
= cache_init(libxfs_ihash_size
, &libxfs_icache_operations
);
328 if (!libxfs_bhash_size
)
329 libxfs_bhash_size
= LIBXFS_BHASHSIZE(sbp
);
330 libxfs_bcache
= cache_init(libxfs_bhash_size
, &libxfs_bcache_operations
);
342 if (!rval
&& a
->ddev
)
343 libxfs_device_close(a
->ddev
);
344 if (!rval
&& a
->logdev
)
345 libxfs_device_close(a
->logdev
);
346 if (!rval
&& a
->rtdev
)
347 libxfs_device_close(a
->rtdev
);
353 * Initialize/destroy all of the zone allocators we use.
356 manage_zones(int release
)
358 extern xfs_zone_t
*xfs_buf_zone
;
359 extern xfs_zone_t
*xfs_ili_zone
;
360 extern xfs_zone_t
*xfs_inode_zone
;
361 extern xfs_zone_t
*xfs_ifork_zone
;
362 extern xfs_zone_t
*xfs_dabuf_zone
;
363 extern xfs_zone_t
*xfs_buf_item_zone
;
364 extern xfs_zone_t
*xfs_da_state_zone
;
365 extern xfs_zone_t
*xfs_btree_cur_zone
;
366 extern xfs_zone_t
*xfs_bmap_free_item_zone
;
367 extern void xfs_dir_startup();
369 if (release
) { /* free zone allocation */
370 libxfs_free(xfs_buf_zone
);
371 libxfs_free(xfs_inode_zone
);
372 libxfs_free(xfs_ifork_zone
);
373 libxfs_free(xfs_dabuf_zone
);
374 libxfs_free(xfs_buf_item_zone
);
375 libxfs_free(xfs_da_state_zone
);
376 libxfs_free(xfs_btree_cur_zone
);
377 libxfs_free(xfs_bmap_free_item_zone
);
380 /* otherwise initialise zone allocation */
381 xfs_buf_zone
= libxfs_zone_init(sizeof(xfs_buf_t
), "xfs_buffer");
382 xfs_inode_zone
= libxfs_zone_init(sizeof(xfs_inode_t
), "xfs_inode");
383 xfs_ifork_zone
= libxfs_zone_init(sizeof(xfs_ifork_t
), "xfs_ifork");
384 xfs_dabuf_zone
= libxfs_zone_init(sizeof(xfs_dabuf_t
), "xfs_dabuf");
385 xfs_ili_zone
= libxfs_zone_init(
386 sizeof(xfs_inode_log_item_t
), "xfs_inode_log_item");
387 xfs_buf_item_zone
= libxfs_zone_init(
388 sizeof(xfs_buf_log_item_t
), "xfs_buf_log_item");
389 xfs_da_state_zone
= libxfs_zone_init(
390 sizeof(xfs_da_state_t
), "xfs_da_state");
391 xfs_btree_cur_zone
= libxfs_zone_init(
392 sizeof(xfs_btree_cur_t
), "xfs_btree_cur");
393 xfs_bmap_free_item_zone
= libxfs_zone_init(
394 sizeof(xfs_bmap_free_item_t
), "xfs_bmap_free_item");
399 * Get the bitmap and summary inodes into the mount structure
403 rtmount_inodes(xfs_mount_t
*mp
)
409 if (sbp
->sb_rbmino
== NULLFSINO
)
411 error
= libxfs_iget(mp
, NULL
, sbp
->sb_rbmino
, 0, &mp
->m_rbmip
, 0);
414 _("%s: cannot read realtime bitmap inode (%d)\n"),
418 ASSERT(mp
->m_rbmip
!= NULL
);
419 ASSERT(sbp
->sb_rsumino
!= NULLFSINO
);
420 error
= libxfs_iget(mp
, NULL
, sbp
->sb_rsumino
, 0, &mp
->m_rsumip
, 0);
422 libxfs_iput(mp
->m_rbmip
, 0);
424 _("%s: cannot read realtime summary inode (%d)\n"),
428 ASSERT(mp
->m_rsumip
!= NULL
);
433 * Initialize realtime fields in the mount structure.
437 xfs_mount_t
*mp
, /* file system mount structure */
440 xfs_buf_t
*bp
; /* buffer for last block of subvolume */
441 xfs_daddr_t d
; /* address of last block of subvolume */
442 xfs_sb_t
*sbp
; /* filesystem superblock copy in mount */
445 if (sbp
->sb_rblocks
== 0)
447 if (mp
->m_rtdev
== 0 && !(flags
& LIBXFS_MOUNT_DEBUGGER
)) {
448 fprintf(stderr
, _("%s: filesystem has a realtime subvolume\n"),
452 mp
->m_rsumlevels
= sbp
->sb_rextslog
+ 1;
454 (uint
)sizeof(xfs_suminfo_t
) * mp
->m_rsumlevels
*
456 mp
->m_rsumsize
= roundup(mp
->m_rsumsize
, sbp
->sb_blocksize
);
457 mp
->m_rbmip
= mp
->m_rsumip
= NULL
;
460 * Allow debugger to be run without the realtime device present.
462 if (flags
& LIBXFS_MOUNT_DEBUGGER
)
466 * Check that the realtime section is an ok size.
468 d
= (xfs_daddr_t
)XFS_FSB_TO_BB(mp
, mp
->m_sb
.sb_rblocks
);
469 if (XFS_BB_TO_FSB(mp
, d
) != mp
->m_sb
.sb_rblocks
) {
470 fprintf(stderr
, _("%s: realtime init - %llu != %llu\n"),
471 progname
, (unsigned long long) XFS_BB_TO_FSB(mp
, d
),
472 (unsigned long long) mp
->m_sb
.sb_rblocks
);
475 bp
= libxfs_readbuf(mp
->m_rtdev
,
476 d
- XFS_FSB_TO_BB(mp
, 1), XFS_FSB_TO_BB(mp
, 1), 0);
478 fprintf(stderr
, _("%s: realtime size check failed\n"),
487 * Mount structure initialization, provides a filled-in xfs_mount_t
488 * such that the numerous XFS_* macros can be used. If dev is zero,
489 * no IO will be performed (no size checks, read root inodes).
508 mp
->m_logdev
= logdev
;
509 mp
->m_flags
= (LIBXFS_MOUNT_32BITINODES
|LIBXFS_MOUNT_32BITINOOPT
);
513 libxfs_mount_common(mp
, sb
);
515 libxfs_alloc_compute_maxlevels(mp
);
516 libxfs_bmap_compute_maxlevels(mp
, XFS_DATA_FORK
);
517 libxfs_bmap_compute_maxlevels(mp
, XFS_ATTR_FORK
);
518 libxfs_ialloc_compute_maxlevels(mp
);
520 if (sbp
->sb_imax_pct
) {
521 /* Make sure the maximum inode count is a multiple of the
522 * units we allocate inodes in.
524 mp
->m_maxicount
= (sbp
->sb_dblocks
* sbp
->sb_imax_pct
) / 100;
525 mp
->m_maxicount
= ((mp
->m_maxicount
/ mp
->m_ialloc_blks
) *
526 mp
->m_ialloc_blks
) << sbp
->sb_inopblog
;
530 mp
->m_inode_cluster_size
= XFS_INODE_BIG_CLUSTER_SIZE
;
533 * Set whether we're using stripe alignment.
535 if (XFS_SB_VERSION_HASDALIGN(&mp
->m_sb
)) {
536 mp
->m_dalign
= sbp
->sb_unit
;
537 mp
->m_swidth
= sbp
->sb_width
;
541 * Set whether we're using inode alignment.
543 if (XFS_SB_VERSION_HASALIGN(&mp
->m_sb
) &&
544 mp
->m_sb
.sb_inoalignmt
>=
545 XFS_B_TO_FSBT(mp
, mp
->m_inode_cluster_size
))
546 mp
->m_inoalign_mask
= mp
->m_sb
.sb_inoalignmt
- 1;
548 mp
->m_inoalign_mask
= 0;
550 * If we are using stripe alignment, check whether
551 * the stripe unit is a multiple of the inode alignment
554 && mp
->m_inoalign_mask
&& !(mp
->m_dalign
& mp
->m_inoalign_mask
))
555 mp
->m_sinoalign
= mp
->m_dalign
;
560 * Check that the data (and log if separate) are an ok size.
562 d
= (xfs_daddr_t
) XFS_FSB_TO_BB(mp
, mp
->m_sb
.sb_dblocks
);
563 if (XFS_BB_TO_FSB(mp
, d
) != mp
->m_sb
.sb_dblocks
) {
564 fprintf(stderr
, _("%s: size check failed\n"), progname
);
565 if (!(flags
& LIBXFS_MOUNT_DEBUGGER
))
569 /* Initialize the appropriate directory manager */
570 if (XFS_SB_VERSION_HASDIRV2(sbp
))
571 libxfs_dir2_mount(mp
);
573 libxfs_dir_mount(mp
);
575 /* Initialize cached values for the attribute manager */
576 mp
->m_attr_magicpct
= (mp
->m_sb
.sb_blocksize
* 37) / 100;
578 /* Initialize the precomputed transaction reservations values */
579 libxfs_trans_init(mp
);
581 if (dev
== 0) /* maxtrres, we have no device so leave now */
584 bp
= libxfs_readbuf(mp
->m_dev
,
585 d
- XFS_FSS_TO_BB(mp
, 1), XFS_FSS_TO_BB(mp
, 1),
586 !(flags
& LIBXFS_MOUNT_DEBUGGER
));
588 fprintf(stderr
, _("%s: data size check failed\n"), progname
);
589 if (!(flags
& LIBXFS_MOUNT_DEBUGGER
))
594 if (mp
->m_logdev
&& mp
->m_logdev
!= mp
->m_dev
) {
595 d
= (xfs_daddr_t
) XFS_FSB_TO_BB(mp
, mp
->m_sb
.sb_logblocks
);
596 if ( (XFS_BB_TO_FSB(mp
, d
) != mp
->m_sb
.sb_logblocks
) ||
597 (!(bp
= libxfs_readbuf(mp
->m_logdev
,
598 d
- XFS_FSB_TO_BB(mp
, 1),
599 XFS_FSB_TO_BB(mp
, 1),
600 !(flags
& LIBXFS_MOUNT_DEBUGGER
)))) ) {
601 fprintf(stderr
, _("%s: log size checks failed\n"),
603 if (!(flags
& LIBXFS_MOUNT_DEBUGGER
))
609 /* Initialize realtime fields in the mount structure */
610 if (rtmount_init(mp
, flags
)) {
611 fprintf(stderr
, _("%s: realtime device init failed\n"),
616 /* Allocate and initialize the per-ag data */
617 size
= sbp
->sb_agcount
* sizeof(xfs_perag_t
);
618 if (size
&& (mp
->m_perag
= calloc(size
, 1)) == NULL
) {
619 fprintf(stderr
, _("%s: failed to alloc %ld bytes: %s\n"),
620 progname
, (long)size
, strerror(errno
));
624 mp
->m_maxagi
= libxfs_initialize_perag(mp
, sbp
->sb_agcount
);
627 * mkfs calls mount before the root inode is allocated.
629 if ((flags
& LIBXFS_MOUNT_ROOTINOS
) && sbp
->sb_rootino
!= NULLFSINO
) {
630 error
= libxfs_iget(mp
, NULL
, sbp
->sb_rootino
, 0,
633 fprintf(stderr
, _("%s: cannot read root inode (%d)\n"),
635 if (!(flags
& LIBXFS_MOUNT_DEBUGGER
))
638 ASSERT(mp
->m_rootip
!= NULL
);
640 if ((flags
& LIBXFS_MOUNT_ROOTINOS
) && rtmount_inodes(mp
)) {
641 libxfs_iput(mp
->m_rootip
, 0);
648 libxfs_rtmount_destroy(xfs_mount_t
*mp
)
651 libxfs_iput(mp
->m_rsumip
, 0);
653 libxfs_iput(mp
->m_rbmip
, 0);
654 mp
->m_rsumip
= mp
->m_rbmip
= NULL
;
658 * Release any resource obtained during a mount.
661 libxfs_umount(xfs_mount_t
*mp
)
663 libxfs_rtmount_destroy(mp
);
664 libxfs_icache_purge();
665 libxfs_bcache_purge();
669 for (agno
= 0; agno
< mp
->m_maxagi
; agno
++) {
670 if (mp
->m_perag
[agno
].pagb_list
)
671 free(mp
->m_perag
[agno
].pagb_list
);
678 * Release any global resources used by libxfs.
684 cache_destroy(libxfs_icache
);
685 cache_destroy(libxfs_bcache
);
689 libxfs_device_alignment(void)
691 return platform_align_blockdev();
695 libxfs_report(FILE *fp
)
700 cache_report(fp
, "libxfs_icache", libxfs_icache
);
701 cache_report(fp
, "libxfs_bcache", libxfs_bcache
);
704 c
= asctime(localtime(&t
));
705 fprintf(fp
, "%s", c
);