2 * Copyright (c) 2000 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 #define ustat __kernel_ustat
38 #include <sys/ustat.h>
39 #include <sys/ioctl.h>
40 #include <sys/mount.h>
42 /* Until glibc catches up... */
44 #define BLKGETSIZE64 _IOR(0x12,114,sizeof(__uint64_t))
47 #define findrawpath(x) x
48 #define findblockpath(x) x
50 char *progname
= "libxfs"; /* default, changed by each tool */
53 * dev_map - map open devices to fd.
55 #define MAX_DEVS 10 /* arbitary maximum */
56 int nextfakedev
= -1; /* device number to give to next fake device */
57 static struct dev_to_fd
{
60 } dev_map
[MAX_DEVS
]={{0}};
63 check_ismounted(char *name
, char *block
)
68 if (stat64(block
, &st
) < 0)
70 if ((st
.st_mode
& S_IFMT
) != S_IFBLK
)
72 if (ustat(st
.st_rdev
, &ust
) >= 0) {
73 fprintf(stderr
, "%s: %s contains a mounted filesystem\n",
81 * Checks whether a given device has a mounted, writable
82 * filesystem, returns 1 if it does & fatal (just warns
83 * if not fatal, but allows us to proceed).
85 * Useful to tools which will produce uncertain results
86 * if the filesystem is active - repair, check, logprint.
89 check_isactive(char *name
, char *block
, int fatal
)
91 #define PROC_MOUNTED "/proc/mounts"
95 struct stat64 st
, mst
;
97 char mounts
[MAXPATHLEN
];
99 if (stat64(block
, &st
) < 0)
101 if ((st
.st_mode
& S_IFMT
) != S_IFBLK
)
103 if (ustat(st
.st_rdev
, &ust
) < 0)
106 strcpy(mounts
, access(PROC_MOUNTED
, R_OK
)? PROC_MOUNTED
: MOUNTED
);
107 if ((f
= setmntent(mounts
, "r")) == NULL
) {
108 fprintf(stderr
, "%s: %s contains a possibly writable, mounted "
109 "filesystem\n", progname
, name
);
112 while ((mnt
= getmntent(f
)) != NULL
) {
113 if (stat64(mnt
->mnt_fsname
, &mst
) < 0)
115 if ((mst
.st_mode
& S_IFMT
) != S_IFBLK
)
117 if (mst
.st_rdev
== st
.st_rdev
118 && hasmntopt(mnt
, MNTOPT_RO
) != NULL
)
122 fprintf(stderr
, "%s: %s contains a writable, mounted "
123 "filesystem\n", progname
, name
);
139 /* Test to see if we are dealing with a regular file rather than a
140 * block device, if we are just use the size returned by stat64
142 if (stat64(path
, &st
) < 0) {
143 fprintf(stderr
, "%s: "
144 "cannot stat the device special file \"%s\": %s\n",
145 progname
, path
, strerror(errno
));
148 if ((st
.st_mode
& S_IFMT
) == S_IFREG
) {
149 return (__int64_t
)(st
.st_size
>> 9);
152 if ((fd
= open(path
, 0)) < 0) {
153 fprintf(stderr
, "%s: "
154 "error opening the device special file \"%s\": %s\n",
155 progname
, path
, strerror(errno
));
158 error
= ioctl(fd
, BLKGETSIZE64
, &size
);
160 /* BLKGETSIZE64 returns size in bytes not 512-byte blocks */
163 /* If BLKGETSIZE64 fails, try BLKGETSIZE */
164 unsigned long tmpsize
;
165 error
= ioctl(fd
, BLKGETSIZE
, &tmpsize
);
167 fprintf(stderr
, "%s: can't determine device size\n",
171 size
= (__uint64_t
)tmpsize
;
176 return (__int64_t
)size
;
180 /* libxfs_device_to_fd:
181 * lookup a device number in the device map
182 * return the associated fd
185 libxfs_device_to_fd(dev_t device
)
189 for (d
=0;d
<MAX_DEVS
;d
++)
190 if (dev_map
[d
].dev
== device
)
191 return dev_map
[d
].fd
;
193 fprintf(stderr
, "%s: device_to_fd: device %lld is not open\n",
194 progname
, (long long)device
);
198 /* libxfs_device_open:
199 * open a device and return its device number
202 libxfs_device_open(char *path
, int creat
, int readonly
, int setblksize
)
210 (readonly
? O_RDONLY
: O_RDWR
) |
211 (creat
? O_CREAT
|O_TRUNC
: 0),
213 fprintf(stderr
, "%s: cannot open %s: %s\n",
214 progname
, path
, strerror(errno
));
218 if (stat(path
, &statb
)<0) {
219 fprintf(stderr
, "%s: cannot stat %s: %s\n",
220 progname
, path
, strerror(errno
));
225 * Set device blocksize to 512 bytes (see bug #801063)
228 #define BLKBSZSET _IOW(0x12,113,sizeof(int)) /* set device block size */
230 if (!readonly
&& setblksize
&& (statb
.st_mode
& S_IFMT
) == S_IFBLK
) {
231 int blocksize
= 512; /* bytes */
232 if (ioctl(fd
, BLKBSZSET
, &blocksize
) < 0) {
233 fprintf(stderr
, "%s: warning - cannot set blocksize on "
234 "block device %s: %s\n",
235 progname
, path
, strerror(errno
));
240 * Get the device number from the stat buf - unless
241 * we're not opening a real device, in which case
242 * choose a new fake device number.
244 dev
=(statb
.st_rdev
)?(statb
.st_rdev
):(nextfakedev
--);
246 for (d
=0;d
<MAX_DEVS
;d
++)
247 if (dev_map
[d
].dev
== dev
) {
248 fprintf(stderr
, "%s: device %lld is already open\n",
249 progname
, (long long)dev
);
253 for (d
=0;d
<MAX_DEVS
;d
++)
254 if (!dev_map
[d
].dev
) {
261 fprintf(stderr
, "%s: device_open: too many open devices\n", progname
);
266 libxfs_device_close(dev_t dev
)
270 for (d
=0;d
<MAX_DEVS
;d
++)
271 if (dev_map
[d
].dev
== dev
) {
275 dev_map
[d
].dev
=dev_map
[d
].fd
=0;
278 ioctl(fd
, BLKFLSBUF
, 0);
284 fprintf(stderr
, "%s: device_close: device %lld is not open\n",
285 progname
, (long long)dev
);
292 * libxfs initialization.
293 * Caller gets a 0 on failure (and we print a message), 1 on success.
296 libxfs_init(libxfs_init_t
*a
)
299 char curdir
[MAXPATHLEN
];
314 dpath
[0] = logpath
[0] = rtpath
[0] = '\0';
316 logname
= a
->logname
;
318 a
->ddev
= a
->logdev
= a
->rtdev
= 0;
319 a
->dfd
= a
->logfd
= a
->rtfd
= -1;
320 a
->dsize
= a
->logBBsize
= a
->logBBstart
= a
->rtsize
= 0;
322 (void)getcwd(curdir
,MAXPATHLEN
);
325 readonly
= (a
->isreadonly
& LIBXFS_ISREADONLY
);
326 inactive
= (a
->isreadonly
& LIBXFS_ISINACTIVE
);
328 if (stat64(a
->volname
, &stbuf
) < 0) {
332 if (!(rawfile
= findrawpath(a
->volname
))) {
333 fprintf(stderr
, "%s: "
334 "can't find a character device matching %s\n",
335 progname
, a
->volname
);
338 if (!(blockfile
= findblockpath(a
->volname
))) {
339 fprintf(stderr
, "%s: "
340 "can't find a block device matching %s\n",
341 progname
, a
->volname
);
344 if (!readonly
&& !inactive
&& check_ismounted(
345 a
->volname
, blockfile
))
347 if (inactive
&& check_isactive(
348 a
->volname
, blockfile
, readonly
))
351 fd
= open(rawfile
, O_RDONLY
);
352 #ifdef HAVE_VOLUME_MANAGER
354 if (ioctl(fd
, DIOCGETVOLDEV
, &getdev
) < 0)
360 dname
= a
->dname
= a
->volname
;
364 fprintf(stderr
, "%s: "
365 "%s is not a volume device name\n",
366 progname
, a
->volname
);
368 fprintf(stderr
, a
->notvolmsg
, a
->volname
);
371 #ifdef HAVE_VOLUME_MANAGER
372 if (getdev
.data_subvol_dev
&& dname
) {
373 fprintf(stderr
, "%s: "
374 "%s has a data subvolume, cannot specify %s\n",
375 progname
, a
->volname
, dname
);
378 if (getdev
.log_subvol_dev
&& logname
) {
379 fprintf(stderr
, "%s: "
380 "%s has a log subvolume, cannot specify %s\n",
381 progname
, a
->volname
, logname
);
384 if (getdev
.rt_subvol_dev
&& rtname
) {
385 fprintf(stderr
, "%s: %s has a realtime subvolume, "
386 "cannot specify %s\n",
387 progname
, a
->volname
, rtname
);
390 if (!dname
&& getdev
.data_subvol_dev
) {
391 strcpy(dpath
, "/tmp/libxfsdXXXXXX");
393 if (mknod(dpath
, S_IFCHR
| 0600,
394 getdev
.data_subvol_dev
) < 0) {
395 fprintf(stderr
, "%s: mknod failed: %s\n",
396 progname
, strerror(errno
));
401 if (!logname
&& getdev
.log_subvol_dev
) {
402 strcpy(logpath
, "/tmp/libxfslXXXXXX");
403 (void)mktemp(logpath
);
404 if (mknod(logpath
, S_IFCHR
| 0600,
405 getdev
.log_subvol_dev
) < 0) {
406 fprintf(stderr
, "%s: mknod failed: %s\n",
407 progname
, strerror(errno
));
412 if (!rtname
&& getdev
.rt_subvol_dev
) {
413 strcpy(rtpath
, "/tmp/libxfsrXXXXXX");
414 (void)mktemp(rtpath
);
415 if (mknod(rtpath
, S_IFCHR
| 0600,
416 getdev
.rt_subvol_dev
) < 0) {
417 fprintf(stderr
, "%s: mknod failed: %s\n",
418 progname
, strerror(errno
));
427 if (dname
[0] != '/' && needcd
)
430 a
->ddev
= libxfs_device_open(dname
, a
->dcreat
, readonly
,
432 a
->dfd
= libxfs_device_to_fd(a
->ddev
);
434 if (stat64(dname
, &stbuf
) < 0) {
435 fprintf(stderr
, "%s: stat64 failed on %s: %s\n",
436 progname
, dname
, strerror(errno
));
439 if (!(rawfile
= findrawpath(dname
))) {
440 fprintf(stderr
, "%s: can't find a char device "
441 "matching %s\n", progname
, dname
);
444 if (!(blockfile
= findblockpath(dname
))) {
445 fprintf(stderr
, "%s: can't find a block device "
446 "matching %s\n", progname
, dname
);
449 if (!readonly
&& !inactive
&& check_ismounted(
452 if (inactive
&& check_isactive(
453 dname
, blockfile
, readonly
))
455 a
->ddev
= libxfs_device_open(rawfile
,
456 a
->dcreat
, readonly
, a
->setblksize
);
457 a
->dfd
= libxfs_device_to_fd(a
->ddev
);
458 a
->dsize
= findsize(rawfile
);
464 if (logname
[0] != '/' && needcd
)
467 a
->logdev
= libxfs_device_open(logname
,
468 a
->lcreat
, readonly
, a
->setblksize
);
469 a
->logfd
= libxfs_device_to_fd(a
->logdev
);
471 if (stat64(logname
, &stbuf
) < 0) {
472 fprintf(stderr
, "%s: stat64 failed on %s: %s\n",
473 progname
, logname
, strerror(errno
));
476 if (!(rawfile
= findrawpath(logname
))) {
477 fprintf(stderr
, "%s: can't find a char device "
478 "matching %s\n", progname
, logname
);
481 if (!(blockfile
= findblockpath(logname
))) {
482 fprintf(stderr
, "%s: can't find a block device "
483 "matching %s\n", progname
, logname
);
486 if (!readonly
&& !inactive
&& check_ismounted(
489 else if (inactive
&& check_isactive(
490 logname
, blockfile
, readonly
))
492 a
->logdev
= libxfs_device_open(rawfile
,
493 a
->lcreat
, readonly
, a
->setblksize
);
494 a
->logfd
= libxfs_device_to_fd(a
->logdev
);
495 a
->logBBsize
= findsize(rawfile
);
501 if (rtname
[0] != '/' && needcd
)
504 a
->rtdev
= libxfs_device_open(rtname
,
505 a
->rcreat
, readonly
, a
->setblksize
);
506 a
->rtfd
= libxfs_device_to_fd(a
->rtdev
);
508 if (stat64(rtname
, &stbuf
) < 0) {
509 fprintf(stderr
, "%s: stat64 failed on %s: %s\n",
510 progname
, rtname
, strerror(errno
));
513 if (!(rawfile
= findrawpath(rtname
))) {
514 fprintf(stderr
, "%s: can't find a char device "
515 "matching %s\n", progname
, rtname
);
518 if (!(blockfile
= findblockpath(rtname
))) {
519 fprintf(stderr
, "%s: can't find a block device "
520 "matching %s\n", progname
, rtname
);
523 if (!readonly
&& !inactive
&& check_ismounted(
526 if (inactive
&& check_isactive(
527 rtname
, blockfile
, readonly
))
529 a
->rtdev
= libxfs_device_open(rawfile
,
530 a
->rcreat
, readonly
, a
->setblksize
);
531 a
->rtfd
= libxfs_device_to_fd(a
->rtdev
);
532 a
->rtsize
= findsize(rawfile
);
538 fprintf(stderr
, "%s: can't get size for data subvolume\n",
542 if (a
->logBBsize
< 0) {
543 fprintf(stderr
, "%s: can't get size for log subvolume\n",
548 fprintf(stderr
, "%s: can't get size for realtime subvolume\n",
564 if (!rval
&& a
->ddev
)
565 libxfs_device_close(a
->ddev
);
566 if (!rval
&& a
->logdev
)
567 libxfs_device_close(a
->logdev
);
568 if (!rval
&& a
->rtdev
)
569 libxfs_device_close(a
->rtdev
);
575 * Initialize/destroy all of the zone allocators we use.
578 manage_zones(int release
)
580 extern xfs_zone_t
*xfs_ili_zone
;
581 extern xfs_zone_t
*xfs_inode_zone
;
582 extern xfs_zone_t
*xfs_ifork_zone
;
583 extern xfs_zone_t
*xfs_dabuf_zone
;
584 extern xfs_zone_t
*xfs_buf_item_zone
;
585 extern xfs_zone_t
*xfs_da_state_zone
;
586 extern xfs_zone_t
*xfs_btree_cur_zone
;
587 extern xfs_zone_t
*xfs_bmap_free_item_zone
;
588 extern void xfs_dir_startup();
590 if (release
) { /* free zone allocation */
591 libxfs_free(xfs_inode_zone
);
592 libxfs_free(xfs_ifork_zone
);
593 libxfs_free(xfs_dabuf_zone
);
594 libxfs_free(xfs_buf_item_zone
);
595 libxfs_free(xfs_da_state_zone
);
596 libxfs_free(xfs_btree_cur_zone
);
597 libxfs_free(xfs_bmap_free_item_zone
);
600 /* otherwise initialise zone allocation */
601 xfs_inode_zone
= libxfs_zone_init(sizeof(xfs_inode_t
), "xfs_inode");
602 xfs_ifork_zone
= libxfs_zone_init(sizeof(xfs_ifork_t
), "xfs_ifork");
603 xfs_dabuf_zone
= libxfs_zone_init(sizeof(xfs_dabuf_t
), "xfs_dabuf");
604 xfs_ili_zone
= libxfs_zone_init(
605 sizeof(xfs_inode_log_item_t
), "xfs_inode_log_item");
606 xfs_buf_item_zone
= libxfs_zone_init(
607 sizeof(xfs_buf_log_item_t
), "xfs_buf_log_item");
608 xfs_da_state_zone
= libxfs_zone_init(
609 sizeof(xfs_da_state_t
), "xfs_da_state");
610 xfs_btree_cur_zone
= libxfs_zone_init(
611 sizeof(xfs_btree_cur_t
), "xfs_btree_cur");
612 xfs_bmap_free_item_zone
= libxfs_zone_init(
613 sizeof(xfs_bmap_free_item_t
), "xfs_bmap_free_item");
618 * Get the bitmap and summary inodes into the mount structure
622 rtmount_inodes(xfs_mount_t
*mp
)
628 if (sbp
->sb_rbmino
== NULLFSINO
)
630 error
= libxfs_iread(mp
, NULL
, sbp
->sb_rbmino
, &mp
->m_rbmip
, 0);
632 fprintf(stderr
, "%s: cannot read realtime bitmap inode (%d)\n",
636 ASSERT(mp
->m_rbmip
!= NULL
);
637 ASSERT(sbp
->sb_rsumino
!= NULLFSINO
);
638 error
= libxfs_iread(mp
, NULL
, sbp
->sb_rsumino
, &mp
->m_rsumip
, 0);
640 fprintf(stderr
, "%s: cannot read realtime summary inode (%d)\n",
644 ASSERT(mp
->m_rsumip
!= NULL
);
648 #define XFS_MOUNT_32BITINODES 0x1
650 * Mount structure initialization, provides a filled-in xfs_mount_t
651 * such that the numerous XFS_* macros can be used. If dev is zero,
652 * no IO will be performed (no size checks, read root inodes).
671 mp
->m_logdev
= logdev
;
672 mp
->m_flags
= XFS_MOUNT_32BITINODES
;
677 libxfs_mount_common(mp
, sb
);
679 libxfs_alloc_compute_maxlevels(mp
);
680 libxfs_bmap_compute_maxlevels(mp
, XFS_DATA_FORK
);
681 libxfs_bmap_compute_maxlevels(mp
, XFS_ATTR_FORK
);
682 libxfs_ialloc_compute_maxlevels(mp
);
684 if (sbp
->sb_imax_pct
) {
685 /* Make sure the maximum inode count is a multiple of the
686 * units we allocate inodes in.
688 mp
->m_maxicount
= (sbp
->sb_dblocks
* sbp
->sb_imax_pct
) / 100;
689 mp
->m_maxicount
= ((mp
->m_maxicount
/ mp
->m_ialloc_blks
) *
690 mp
->m_ialloc_blks
) << sbp
->sb_inopblog
;
694 mp
->m_inode_cluster_size
= XFS_INODE_BIG_CLUSTER_SIZE
;
697 * Set whether we're using inode alignment.
699 if (XFS_SB_VERSION_HASALIGN(&mp
->m_sb
) &&
700 mp
->m_sb
.sb_inoalignmt
>=
701 XFS_B_TO_FSBT(mp
, mp
->m_inode_cluster_size
))
702 mp
->m_inoalign_mask
= mp
->m_sb
.sb_inoalignmt
- 1;
704 mp
->m_inoalign_mask
= 0;
706 * If we are using stripe alignment, check whether
707 * the stripe unit is a multiple of the inode alignment
710 && mp
->m_inoalign_mask
&& !(mp
->m_dalign
& mp
->m_inoalign_mask
))
711 mp
->m_sinoalign
= mp
->m_dalign
;
716 * Check that the data (and log if separate) are an ok size.
718 d
= (xfs_daddr_t
)XFS_FSB_TO_BB(mp
, mp
->m_sb
.sb_dblocks
);
719 if (XFS_BB_TO_FSB(mp
, d
) != mp
->m_sb
.sb_dblocks
) {
720 fprintf(stderr
, "%s: size check failed\n", progname
);
724 /* Initialize the appropriate directory manager */
725 if (XFS_SB_VERSION_HASDIRV2(sbp
))
726 libxfs_dir2_mount(mp
);
728 libxfs_dir_mount(mp
);
730 /* Initialize the precomputed transaction reservations values */
731 libxfs_trans_init(mp
);
733 if (dev
== 0) /* maxtrres, we have no device so leave now */
736 bp
= libxfs_readbuf(mp
->m_dev
, d
- 1, 1, 0);
738 fprintf(stderr
, "%s: data size check failed\n", progname
);
743 if (mp
->m_logdev
&& mp
->m_logdev
!= mp
->m_dev
) {
744 d
= (xfs_daddr_t
)XFS_FSB_TO_BB(mp
, mp
->m_sb
.sb_logblocks
);
745 if ( (XFS_BB_TO_FSB(mp
, d
) != mp
->m_sb
.sb_logblocks
) ||
746 (!(bp
= libxfs_readbuf(mp
->m_logdev
, d
- 1, 1, 1)))) {
747 fprintf(stderr
, "%s: log size checks failed\n",
754 /* Initialize realtime fields in the mount structure */
755 if (libxfs_rtmount_init(mp
)) {
756 fprintf(stderr
, "%s: real-time device init failed\n", progname
);
760 /* Allocate and initialize the per-ag data */
761 size
= sbp
->sb_agcount
* sizeof(xfs_perag_t
);
762 if ((mp
->m_perag
= calloc(size
, 1)) == NULL
) {
763 fprintf(stderr
, "%s: failed to alloc %ld bytes: %s\n",
764 progname
, (long)size
, strerror(errno
));
768 libxfs_initialize_perag(mp
, sbp
->sb_agcount
);
771 * mkfs calls mount before the root inode is allocated.
773 if (rrootinos
&& sbp
->sb_rootino
!= NULLFSINO
) {
774 error
= libxfs_iread(mp
, NULL
, sbp
->sb_rootino
,
777 fprintf(stderr
, "%s: cannot read root inode (%d)\n",
781 ASSERT(mp
->m_rootip
!= NULL
);
783 if (rrootinos
&& rtmount_inodes(mp
))
789 * Release any resourse obtained during a mount.
792 libxfs_umount(xfs_mount_t
*mp
)