2 * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
33 #include <xfs/libxfs.h>
37 #define findrawpath(x) x
38 #define findblockpath(x) x
40 char *progname
= "libxfs"; /* default, changed by each tool */
43 * dev_map - map open devices to fd.
45 #define MAX_DEVS 10 /* arbitary maximum */
46 int nextfakedev
= -1; /* device number to give to next fake device */
47 static struct dev_to_fd
{
50 } dev_map
[MAX_DEVS
]={{0}};
53 * Checks whether a given device has a mounted, writable
54 * filesystem, returns 1 if it does & fatal (just warns
55 * if not fatal, but allows us to proceed).
57 * Useful to tools which will produce uncertain results
58 * if the filesystem is active - repair, check, logprint.
61 check_isactive(char *name
, char *block
, int fatal
)
65 if (stat64(block
, &st
) < 0)
67 if ((st
.st_mode
& S_IFMT
) != S_IFBLK
)
69 if (platform_check_ismounted(name
, block
, &st
, 0) == 0)
71 return platform_check_iswritable(name
, block
, &st
, fatal
);
74 /* libxfs_device_to_fd:
75 * lookup a device number in the device map
76 * return the associated fd
79 libxfs_device_to_fd(dev_t device
)
83 for (d
= 0; d
< MAX_DEVS
; d
++)
84 if (dev_map
[d
].dev
== device
)
87 fprintf(stderr
, _("%s: %s: device %lld is not open\n"),
88 progname
, __FUNCTION__
, (long long)device
);
92 /* libxfs_device_open:
93 * open a device and return its device number
96 libxfs_device_open(char *path
, int creat
, int xflags
, int setblksize
)
103 readonly
= (xflags
& LIBXFS_ISREADONLY
);
104 excl
= (xflags
& LIBXFS_EXCLUSIVELY
) && !creat
;
106 flags
= (readonly
? O_RDONLY
: O_RDWR
) | \
107 (creat
? (O_CREAT
|O_TRUNC
) : 0) | \
109 if ((fd
= open(path
, flags
, 0666)) < 0) {
110 fprintf(stderr
, _("%s: cannot open %s: %s\n"),
111 progname
, path
, strerror(errno
));
115 if (fstat64(fd
, &statb
) < 0) {
116 fprintf(stderr
, _("%s: cannot stat %s: %s\n"),
117 progname
, path
, strerror(errno
));
121 if (!readonly
&& setblksize
&& (statb
.st_mode
& S_IFMT
) == S_IFBLK
) {
122 platform_set_blocksize(fd
, path
, 512);
126 * Get the device number from the stat buf - unless
127 * we're not opening a real device, in which case
128 * choose a new fake device number.
130 dev
= (statb
.st_rdev
) ? (statb
.st_rdev
) : (nextfakedev
--);
132 for (d
= 0; d
< MAX_DEVS
; d
++)
133 if (dev_map
[d
].dev
== dev
) {
134 fprintf(stderr
, _("%s: device %lld is already open\n"),
135 progname
, (long long)dev
);
139 for (d
= 0; d
< MAX_DEVS
; d
++)
140 if (!dev_map
[d
].dev
) {
141 dev_map
[d
].dev
= dev
;
147 fprintf(stderr
, _("%s: %s: too many open devices\n"),
148 progname
, __FUNCTION__
);
153 libxfs_device_close(dev_t dev
)
157 for (d
= 0; d
< MAX_DEVS
; d
++)
158 if (dev_map
[d
].dev
== dev
) {
162 dev_map
[d
].dev
= dev_map
[d
].fd
= 0;
165 platform_flush_device(fd
, dev
);
171 fprintf(stderr
, _("%s: %s: device %lld is not open\n"),
172 progname
, __FUNCTION__
, (long long)dev
);
177 check_open(char *path
, int flags
, char **rawfile
, char **blockfile
)
179 int readonly
= (flags
& LIBXFS_ISREADONLY
);
180 int inactive
= (flags
& LIBXFS_ISINACTIVE
);
181 int dangerously
= (flags
& LIBXFS_DANGEROUSLY
);
184 if (stat64(path
, &stbuf
) < 0) {
188 if (!(*rawfile
= findrawpath(path
))) {
189 fprintf(stderr
, _("%s: "
190 "can't find a character device matching %s\n"),
194 if (!(*blockfile
= findblockpath(path
))) {
195 fprintf(stderr
, _("%s: "
196 "can't find a block device matching %s\n"),
200 if (!readonly
&& !inactive
&& platform_check_ismounted(path
, *blockfile
, NULL
, 1))
203 if (inactive
&& check_isactive(path
, *blockfile
, ((readonly
|dangerously
)?1:0)))
210 * libxfs initialization.
211 * Caller gets a 0 on failure (and we print a message), 1 on success.
214 libxfs_init(libxfs_init_t
*a
)
217 char curdir
[MAXPATHLEN
];
230 dpath
[0] = logpath
[0] = rtpath
[0] = '\0';
232 logname
= a
->logname
;
234 a
->dfd
= a
->logfd
= a
->rtfd
= -1;
235 a
->ddev
= a
->logdev
= a
->rtdev
= 0;
236 a
->dbsize
= a
->lbsize
= a
->rtbsize
= 0;
237 a
->dsize
= a
->logBBsize
= a
->logBBstart
= a
->rtsize
= 0;
239 (void)getcwd(curdir
,MAXPATHLEN
);
242 flags
= a
->isreadonly
;
245 if(!check_open(a
->volname
,flags
,&rawfile
,&blockfile
))
248 fd
= open(rawfile
, O_RDONLY
);
249 #ifdef HAVE_VOLUME_MANAGER
251 if (ioctl(fd
, DIOCGETVOLDEV
, &getdev
) < 0)
257 dname
= a
->dname
= a
->volname
;
261 fprintf(stderr
, _("%s: "
262 "%s is not a volume device name\n"),
263 progname
, a
->volname
);
265 fprintf(stderr
, a
->notvolmsg
, a
->volname
);
268 #ifdef HAVE_VOLUME_MANAGER
269 if (getdev
.data_subvol_dev
&& dname
) {
270 fprintf(stderr
, _("%s: "
271 "%s has a data subvolume, cannot specify %s\n"),
272 progname
, a
->volname
, dname
);
275 if (getdev
.log_subvol_dev
&& logname
) {
276 fprintf(stderr
, _("%s: "
277 "%s has a log subvolume, cannot specify %s\n"),
278 progname
, a
->volname
, logname
);
281 if (getdev
.rt_subvol_dev
&& rtname
) {
282 fprintf(stderr
, _("%s: %s has a realtime subvolume, "
283 "cannot specify %s\n"),
284 progname
, a
->volname
, rtname
);
287 if (!dname
&& getdev
.data_subvol_dev
) {
288 strcpy(dpath
, "/tmp/libxfsdXXXXXX");
290 if (mknod(dpath
, S_IFCHR
| 0600,
291 getdev
.data_subvol_dev
) < 0) {
292 fprintf(stderr
, _("%s: mknod failed: %s\n"),
293 progname
, strerror(errno
));
298 if (!logname
&& getdev
.log_subvol_dev
) {
299 strcpy(logpath
, "/tmp/libxfslXXXXXX");
300 (void)mktemp(logpath
);
301 if (mknod(logpath
, S_IFCHR
| 0600,
302 getdev
.log_subvol_dev
) < 0) {
303 fprintf(stderr
, _("%s: mknod failed: %s\n"),
304 progname
, strerror(errno
));
309 if (!rtname
&& getdev
.rt_subvol_dev
) {
310 strcpy(rtpath
, "/tmp/libxfsrXXXXXX");
311 (void)mktemp(rtpath
);
312 if (mknod(rtpath
, S_IFCHR
| 0600,
313 getdev
.rt_subvol_dev
) < 0) {
314 fprintf(stderr
, _("%s: mknod failed: %s\n"),
315 progname
, strerror(errno
));
324 if (dname
[0] != '/' && needcd
)
327 a
->ddev
= libxfs_device_open(dname
, a
->dcreat
, flags
,
329 a
->dfd
= libxfs_device_to_fd(a
->ddev
);
331 if (!check_open(dname
, flags
, &rawfile
, &blockfile
))
333 a
->ddev
= libxfs_device_open(rawfile
,
334 a
->dcreat
, flags
, a
->setblksize
);
335 a
->dfd
= libxfs_device_to_fd(a
->ddev
);
336 platform_findsizes(rawfile
, a
->dfd
,
337 &a
->dsize
, &a
->dbsize
);
343 if (logname
[0] != '/' && needcd
)
346 a
->logdev
= libxfs_device_open(logname
,
347 a
->lcreat
, flags
, a
->setblksize
);
348 a
->logfd
= libxfs_device_to_fd(a
->logdev
);
350 if (!check_open(logname
, flags
, &rawfile
, &blockfile
))
352 a
->logdev
= libxfs_device_open(rawfile
,
353 a
->lcreat
, flags
, a
->setblksize
);
354 a
->logfd
= libxfs_device_to_fd(a
->logdev
);
355 platform_findsizes(rawfile
, a
->logfd
,
356 &a
->logBBsize
, &a
->lbsize
);
362 if (rtname
[0] != '/' && needcd
)
365 a
->rtdev
= libxfs_device_open(rtname
,
366 a
->rcreat
, flags
, a
->setblksize
);
367 a
->rtfd
= libxfs_device_to_fd(a
->rtdev
);
369 if (!check_open(rtname
, flags
, &rawfile
, &blockfile
))
371 a
->rtdev
= libxfs_device_open(rawfile
,
372 a
->rcreat
, flags
, a
->setblksize
);
373 a
->rtfd
= libxfs_device_to_fd(a
->rtdev
);
374 platform_findsizes(rawfile
, a
->rtfd
,
375 &a
->rtsize
, &a
->rtbsize
);
381 fprintf(stderr
, _("%s: can't get size for data subvolume\n"),
385 if (a
->logBBsize
< 0) {
386 fprintf(stderr
, _("%s: can't get size for log subvolume\n"),
391 fprintf(stderr
, _("%s: can't get size for realtime subvolume\n"),
407 if (!rval
&& a
->ddev
)
408 libxfs_device_close(a
->ddev
);
409 if (!rval
&& a
->logdev
)
410 libxfs_device_close(a
->logdev
);
411 if (!rval
&& a
->rtdev
)
412 libxfs_device_close(a
->rtdev
);
418 * Initialize/destroy all of the zone allocators we use.
421 manage_zones(int release
)
423 extern xfs_zone_t
*xfs_ili_zone
;
424 extern xfs_zone_t
*xfs_inode_zone
;
425 extern xfs_zone_t
*xfs_ifork_zone
;
426 extern xfs_zone_t
*xfs_dabuf_zone
;
427 extern xfs_zone_t
*xfs_buf_item_zone
;
428 extern xfs_zone_t
*xfs_da_state_zone
;
429 extern xfs_zone_t
*xfs_btree_cur_zone
;
430 extern xfs_zone_t
*xfs_bmap_free_item_zone
;
431 extern void xfs_dir_startup();
433 if (release
) { /* free zone allocation */
434 libxfs_free(xfs_inode_zone
);
435 libxfs_free(xfs_ifork_zone
);
436 libxfs_free(xfs_dabuf_zone
);
437 libxfs_free(xfs_buf_item_zone
);
438 libxfs_free(xfs_da_state_zone
);
439 libxfs_free(xfs_btree_cur_zone
);
440 libxfs_free(xfs_bmap_free_item_zone
);
443 /* otherwise initialise zone allocation */
444 xfs_inode_zone
= libxfs_zone_init(sizeof(xfs_inode_t
), "xfs_inode");
445 xfs_ifork_zone
= libxfs_zone_init(sizeof(xfs_ifork_t
), "xfs_ifork");
446 xfs_dabuf_zone
= libxfs_zone_init(sizeof(xfs_dabuf_t
), "xfs_dabuf");
447 xfs_ili_zone
= libxfs_zone_init(
448 sizeof(xfs_inode_log_item_t
), "xfs_inode_log_item");
449 xfs_buf_item_zone
= libxfs_zone_init(
450 sizeof(xfs_buf_log_item_t
), "xfs_buf_log_item");
451 xfs_da_state_zone
= libxfs_zone_init(
452 sizeof(xfs_da_state_t
), "xfs_da_state");
453 xfs_btree_cur_zone
= libxfs_zone_init(
454 sizeof(xfs_btree_cur_t
), "xfs_btree_cur");
455 xfs_bmap_free_item_zone
= libxfs_zone_init(
456 sizeof(xfs_bmap_free_item_t
), "xfs_bmap_free_item");
461 * Get the bitmap and summary inodes into the mount structure
465 rtmount_inodes(xfs_mount_t
*mp
)
471 if (sbp
->sb_rbmino
== NULLFSINO
)
473 error
= libxfs_iread(mp
, NULL
, sbp
->sb_rbmino
, &mp
->m_rbmip
, 0);
476 _("%s: cannot read realtime bitmap inode (%d)\n"),
480 ASSERT(mp
->m_rbmip
!= NULL
);
481 ASSERT(sbp
->sb_rsumino
!= NULLFSINO
);
482 error
= libxfs_iread(mp
, NULL
, sbp
->sb_rsumino
, &mp
->m_rsumip
, 0);
485 _("%s: cannot read realtime summary inode (%d)\n"),
489 ASSERT(mp
->m_rsumip
!= NULL
);
494 * Initialize realtime fields in the mount structure.
498 xfs_mount_t
*mp
, /* file system mount structure */
501 xfs_buf_t
*bp
; /* buffer for last block of subvolume */
502 xfs_daddr_t d
; /* address of last block of subvolume */
503 xfs_sb_t
*sbp
; /* filesystem superblock copy in mount */
506 if (sbp
->sb_rblocks
== 0)
508 if (mp
->m_rtdev
== 0 && !(flags
& LIBXFS_MOUNT_DEBUGGER
)) {
509 fprintf(stderr
, _("%s: filesystem has a realtime subvolume\n"),
513 mp
->m_rsumlevels
= sbp
->sb_rextslog
+ 1;
515 (uint
)sizeof(xfs_suminfo_t
) * mp
->m_rsumlevels
*
517 mp
->m_rsumsize
= roundup(mp
->m_rsumsize
, sbp
->sb_blocksize
);
518 mp
->m_rbmip
= mp
->m_rsumip
= NULL
;
521 * Allow debugger to be run without the realtime device present.
523 if (flags
& LIBXFS_MOUNT_DEBUGGER
)
527 * Check that the realtime section is an ok size.
529 d
= (xfs_daddr_t
)XFS_FSB_TO_BB(mp
, mp
->m_sb
.sb_rblocks
);
530 if (XFS_BB_TO_FSB(mp
, d
) != mp
->m_sb
.sb_rblocks
) {
531 fprintf(stderr
, _("%s: realtime init - %llu != %llu\n"),
532 progname
, (unsigned long long) XFS_BB_TO_FSB(mp
, d
),
533 (unsigned long long) mp
->m_sb
.sb_rblocks
);
536 bp
= libxfs_readbuf(mp
->m_rtdev
,
537 d
- XFS_FSB_TO_BB(mp
, 1), XFS_FSB_TO_BB(mp
, 1), 0);
539 fprintf(stderr
, _("%s: realtime size check failed\n"),
547 #define XFS_MOUNT_32BITINODES 0x1
548 #define XFS_MOUNT_32BITINOOPT 0x2
550 * Mount structure initialization, provides a filled-in xfs_mount_t
551 * such that the numerous XFS_* macros can be used. If dev is zero,
552 * no IO will be performed (no size checks, read root inodes).
571 mp
->m_logdev
= logdev
;
572 mp
->m_flags
= (XFS_MOUNT_32BITINODES
|XFS_MOUNT_32BITINOOPT
);
577 libxfs_mount_common(mp
, sb
);
579 libxfs_alloc_compute_maxlevels(mp
);
580 libxfs_bmap_compute_maxlevels(mp
, XFS_DATA_FORK
);
581 libxfs_bmap_compute_maxlevels(mp
, XFS_ATTR_FORK
);
582 libxfs_ialloc_compute_maxlevels(mp
);
584 if (sbp
->sb_imax_pct
) {
585 /* Make sure the maximum inode count is a multiple of the
586 * units we allocate inodes in.
588 mp
->m_maxicount
= (sbp
->sb_dblocks
* sbp
->sb_imax_pct
) / 100;
589 mp
->m_maxicount
= ((mp
->m_maxicount
/ mp
->m_ialloc_blks
) *
590 mp
->m_ialloc_blks
) << sbp
->sb_inopblog
;
594 mp
->m_inode_cluster_size
= XFS_INODE_BIG_CLUSTER_SIZE
;
597 * Set whether we're using stripe alignment.
599 if (XFS_SB_VERSION_HASDALIGN(&mp
->m_sb
)) {
600 mp
->m_dalign
= sbp
->sb_unit
;
601 mp
->m_swidth
= sbp
->sb_width
;
605 * Set whether we're using inode alignment.
607 if (XFS_SB_VERSION_HASALIGN(&mp
->m_sb
) &&
608 mp
->m_sb
.sb_inoalignmt
>=
609 XFS_B_TO_FSBT(mp
, mp
->m_inode_cluster_size
))
610 mp
->m_inoalign_mask
= mp
->m_sb
.sb_inoalignmt
- 1;
612 mp
->m_inoalign_mask
= 0;
614 * If we are using stripe alignment, check whether
615 * the stripe unit is a multiple of the inode alignment
618 && mp
->m_inoalign_mask
&& !(mp
->m_dalign
& mp
->m_inoalign_mask
))
619 mp
->m_sinoalign
= mp
->m_dalign
;
624 * Check that the data (and log if separate) are an ok size.
626 d
= (xfs_daddr_t
) XFS_FSB_TO_BB(mp
, mp
->m_sb
.sb_dblocks
);
627 if (XFS_BB_TO_FSB(mp
, d
) != mp
->m_sb
.sb_dblocks
) {
628 fprintf(stderr
, _("%s: size check failed\n"), progname
);
629 if (!(flags
& LIBXFS_MOUNT_DEBUGGER
))
633 /* Initialize the appropriate directory manager */
634 if (XFS_SB_VERSION_HASDIRV2(sbp
))
635 libxfs_dir2_mount(mp
);
637 libxfs_dir_mount(mp
);
639 /* Initialize the precomputed transaction reservations values */
640 libxfs_trans_init(mp
);
642 if (dev
== 0) /* maxtrres, we have no device so leave now */
645 bp
= libxfs_readbuf(mp
->m_dev
,
646 d
- XFS_FSS_TO_BB(mp
, 1), XFS_FSS_TO_BB(mp
, 1),
647 !(flags
& LIBXFS_MOUNT_DEBUGGER
));
649 fprintf(stderr
, _("%s: data size check failed\n"), progname
);
650 if (!(flags
& LIBXFS_MOUNT_DEBUGGER
))
655 if (mp
->m_logdev
&& mp
->m_logdev
!= mp
->m_dev
) {
656 d
= (xfs_daddr_t
) XFS_FSB_TO_BB(mp
, mp
->m_sb
.sb_logblocks
);
657 if ( (XFS_BB_TO_FSB(mp
, d
) != mp
->m_sb
.sb_logblocks
) ||
658 (!(bp
= libxfs_readbuf(mp
->m_logdev
,
659 d
- XFS_FSB_TO_BB(mp
, 1),
660 XFS_FSB_TO_BB(mp
, 1),
661 !(flags
& LIBXFS_MOUNT_DEBUGGER
)))) ) {
662 fprintf(stderr
, _("%s: log size checks failed\n"),
664 if (!(flags
& LIBXFS_MOUNT_DEBUGGER
))
670 /* Initialize realtime fields in the mount structure */
671 if (rtmount_init(mp
, flags
)) {
672 fprintf(stderr
, _("%s: realtime device init failed\n"),
677 /* Allocate and initialize the per-ag data */
678 size
= sbp
->sb_agcount
* sizeof(xfs_perag_t
);
679 if (size
&& (mp
->m_perag
= calloc(size
, 1)) == NULL
) {
680 fprintf(stderr
, _("%s: failed to alloc %ld bytes: %s\n"),
681 progname
, (long)size
, strerror(errno
));
685 libxfs_initialize_perag(mp
, sbp
->sb_agcount
);
688 * mkfs calls mount before the root inode is allocated.
690 if ((flags
& LIBXFS_MOUNT_ROOTINOS
) && sbp
->sb_rootino
!= NULLFSINO
) {
691 error
= libxfs_iread(mp
, NULL
, sbp
->sb_rootino
,
694 fprintf(stderr
, _("%s: cannot read root inode (%d)\n"),
696 if (!(flags
& LIBXFS_MOUNT_DEBUGGER
))
699 ASSERT(mp
->m_rootip
!= NULL
);
701 if ((flags
& LIBXFS_MOUNT_ROOTINOS
) && rtmount_inodes(mp
))
707 * Release any resource obtained during a mount.
710 libxfs_umount(xfs_mount_t
*mp
)
715 for (agno
= 0; agno
< mp
->m_maxagi
; agno
++) {
716 if (mp
->m_perag
[agno
].pagb_list
)
717 free(mp
->m_perag
[agno
].pagb_list
);