4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright (c) 2016 by Delphix. All rights reserved.
28 #include <sys/types.h>
29 #include <sys/param.h>
30 #include <sys/vnode.h>
31 #include <sys/fs/ufs_fsdir.h>
32 #include <sys/fs/ufs_fs.h>
33 #include <sys/fs/ufs_inode.h>
34 #include <sys/sysmacros.h>
35 #include <sys/bootvfs.h>
36 #include <sys/filep.h>
39 #include "../common/util.h"
41 #include <sys/sunddi.h>
44 extern void *bkmem_alloc(size_t);
45 extern void bkmem_free(void *, size_t);
46 extern int cf_check_compressed(fileid_t
*);
47 extern void cf_close(fileid_t
*);
48 extern void cf_seek(fileid_t
*, off_t
, int);
49 extern int cf_read(fileid_t
*, caddr_t
, size_t);
53 #define dprintf if (bootrd_debug) printf
55 #define printf kobj_printf
56 #define dprintf if (bootrd_debug) kobj_printf
59 extern void kobj_printf(char *, ...);
63 * This fd is used when talking to the device file itself.
65 static fileid_t
*head
;
67 /* Only got one of these...ergo, only 1 fs open at once */
76 static int bufs_close(int);
77 static void bufs_closeall(int);
78 static ino_t
find(fileid_t
*filep
, char *path
);
79 static ino_t
dlook(fileid_t
*filep
, char *path
);
80 static daddr32_t
sbmap(fileid_t
*filep
, daddr32_t bn
);
81 static struct direct
*readdir(struct dirinfo
*dstuff
);
82 static void set_cache(int, void *, uint_t
);
83 static void *get_cache(int);
84 static void free_cache();
88 * There is only 1 open (mounted) device at any given time.
89 * So we can keep a single, global devp file descriptor to
90 * use to index into the di[] array. This is not true for the
91 * fi[] array. We can have more than one file open at once,
92 * so there is no global fd for the fi[].
93 * The user program must save the fd passed back from open()
94 * and use it to do subsequent read()'s.
98 openi(fileid_t
*filep
, ino_t inode
)
101 devid_t
*devp
= filep
->fi_devp
;
103 filep
->fi_inode
= get_cache((int)inode
);
104 if (filep
->fi_inode
!= 0)
107 filep
->fi_offset
= 0;
108 filep
->fi_blocknum
= fsbtodb(&devp
->un_fs
.di_fs
,
109 itod(&devp
->un_fs
.di_fs
, inode
));
111 /* never more than 1 disk block */
112 filep
->fi_count
= devp
->un_fs
.di_fs
.fs_bsize
;
113 filep
->fi_memp
= 0; /* cached read */
114 if (diskread(filep
) != 0) {
118 dp
= (struct dinode
*)filep
->fi_memp
;
119 filep
->fi_inode
= (struct inode
*)
120 bkmem_alloc(sizeof (struct inode
));
121 bzero((char *)filep
->fi_inode
, sizeof (struct inode
));
122 filep
->fi_inode
->i_ic
=
123 dp
[itoo(&devp
->un_fs
.di_fs
, inode
)].di_un
.di_icom
;
124 filep
->fi_inode
->i_number
= inode
;
125 set_cache((int)inode
, (void *)filep
->fi_inode
, sizeof (struct inode
));
132 fileid_t
*filep
= head
;
135 while ((filep
= filep
->fi_forw
) != head
)
136 if (fd
== filep
->fi_filedes
)
137 return (filep
->fi_taken
? filep
: 0);
144 find(fileid_t
*filep
, char *path
)
149 char lpath
[MAXPATHLEN
];
150 char *lpathp
= lpath
;
154 if (path
== NULL
|| *path
== '\0') {
155 printf("null path\n");
159 dprintf("openi: %s\n", path
);
161 bzero(lpath
, sizeof (lpath
));
162 bcopy(path
, lpath
, strlen(path
));
163 devp
= filep
->fi_devp
;
165 /* if at the beginning of pathname get root inode */
166 r
= (lpathp
== lpath
);
167 if (r
&& openi(filep
, (ino_t
)UFSROOTINO
))
169 while (*lpathp
== '/')
170 lpathp
++; /* skip leading slashes */
172 while (*q
!= '/' && *q
!= '\0')
173 q
++; /* find end of component */
175 *q
= '\0'; /* terminate component */
177 /* Bail out early if opening root */
178 if (r
&& (*lpathp
== '\0'))
179 return ((ino_t
)UFSROOTINO
);
180 if ((inode
= dlook(filep
, lpathp
)) != 0) {
181 if (openi(filep
, inode
))
183 if ((filep
->fi_inode
->i_smode
& IFMT
) == IFLNK
) {
185 fsbtodb(&devp
->un_fs
.di_fs
,
186 filep
->fi_inode
->i_db
[0]);
187 filep
->fi_count
= DEV_BSIZE
;
189 if (diskread(filep
) != 0)
191 len
= strlen(filep
->fi_memp
);
192 if (filep
->fi_memp
[0] == '/')
195 /* copy rest of unprocessed path up */
196 bcopy(q
, lpathp
+ len
, strlen(q
+ 1) + 2);
197 /* point to unprocessed path */
199 /* prepend link in before unprocessed path */
200 bcopy(filep
->fi_memp
, lpathp
, len
);
217 sbmap(fileid_t
*filep
, daddr32_t bn
)
219 struct inode
*inodep
;
225 devp
= filep
->fi_devp
;
226 inodep
= filep
->fi_inode
;
230 * blocks 0..NDADDR are direct blocks
238 * addresses NIADDR have single and double indirect blocks.
239 * the first step is to determine how many levels of indirection.
243 for (j
= NIADDR
; j
> 0; j
--) {
244 sh
*= NINDIR(&devp
->un_fs
.di_fs
);
250 return ((daddr32_t
)0);
254 * fetch the first indirect block address from the inode
256 nb
= inodep
->i_ib
[NIADDR
- j
];
258 return ((daddr32_t
)0);
262 * fetch through the indirect blocks
264 for (; j
<= NIADDR
; j
++) {
265 filep
->fi_blocknum
= fsbtodb(&devp
->un_fs
.di_fs
, nb
);
266 filep
->fi_count
= devp
->un_fs
.di_fs
.fs_bsize
;
268 if (diskread(filep
) != 0)
270 bap
= (daddr32_t
*)filep
->fi_memp
;
271 sh
/= NINDIR(&devp
->un_fs
.di_fs
);
272 i
= (bn
/ sh
) % NINDIR(&devp
->un_fs
.di_fs
);
275 return ((daddr32_t
)0);
282 dlook(fileid_t
*filep
, char *path
)
289 ip
= filep
->fi_inode
;
290 if (path
== NULL
|| *path
== '\0')
293 dprintf("dlook: %s\n", path
);
295 if ((ip
->i_smode
& IFMT
) != IFDIR
) {
298 if (ip
->i_size
== 0) {
304 for (dp
= readdir(&dirp
); dp
!= NULL
; dp
= readdir(&dirp
)) {
307 if (dp
->d_namlen
== len
&& strcmp(path
, dp
->d_name
) == 0) {
310 /* Allow "*" to print all names at that level, w/out match */
311 if (strcmp(path
, "*") == 0)
312 dprintf("%s\n", dp
->d_name
);
318 * get next entry in a directory.
321 readdir(struct dirinfo
*dstuff
)
330 devp
= filep
->fi_devp
;
332 if (dstuff
->loc
>= filep
->fi_inode
->i_size
) {
335 off
= blkoff(&devp
->un_fs
.di_fs
, dstuff
->loc
);
336 dprintf("readdir: off = 0x%x\n", off
);
338 lbn
= lblkno(&devp
->un_fs
.di_fs
, dstuff
->loc
);
339 d
= sbmap(filep
, lbn
);
344 filep
->fi_blocknum
= fsbtodb(&devp
->un_fs
.di_fs
, d
);
346 blksize(&devp
->un_fs
.di_fs
, filep
->fi_inode
, lbn
);
348 if (diskread(filep
) != 0) {
352 dp
= (struct direct
*)(filep
->fi_memp
+ off
);
353 dstuff
->loc
+= dp
->d_reclen
;
356 dprintf("readdir: name = %s\n", dp
->d_name
);
362 * Get the next block of data from the file. If possible, dma right into
366 getblock(fileid_t
*filep
, caddr_t buf
, int count
, int *rcount
)
374 dprintf("getblock: buf 0x%p, count 0x%x\n", (void *)buf
, count
);
376 devp
= filep
->fi_devp
;
378 if ((signed)filep
->fi_count
<= 0) {
380 /* find the amt left to be read in the file */
381 diff
= filep
->fi_inode
->i_size
- filep
->fi_offset
;
383 printf("Short read\n");
387 fs
= &devp
->un_fs
.di_fs
;
388 /* which block (or frag) in the file do we read? */
389 lbn
= lblkno(fs
, filep
->fi_offset
);
391 /* which physical block on the device do we read? */
392 filep
->fi_blocknum
= fsbtodb(fs
, sbmap(filep
, lbn
));
394 off
= blkoff(fs
, filep
->fi_offset
);
396 /* either blksize or fragsize */
397 size
= blksize(fs
, filep
->fi_inode
, lbn
);
398 filep
->fi_count
= size
;
399 filep
->fi_memp
= filep
->fi_buf
;
402 * optimization if we are reading large blocks of data then
403 * we can go directly to user's buffer
406 if (off
== 0 && count
>= size
) {
407 filep
->fi_memp
= buf
;
408 if (diskread(filep
)) {
414 } else if (diskread(filep
))
417 if (filep
->fi_offset
- off
+ size
>= filep
->fi_inode
->i_size
)
418 filep
->fi_count
= diff
+ off
;
419 filep
->fi_count
-= off
;
420 p
= &filep
->fi_memp
[off
];
427 * Get the next block of data from the file. Don't attempt to go directly
431 getblock_noopt(fileid_t
*filep
)
439 dprintf("getblock_noopt: start\n");
441 devp
= filep
->fi_devp
;
443 if ((signed)filep
->fi_count
<= 0) {
445 /* find the amt left to be read in the file */
446 diff
= filep
->fi_inode
->i_size
- filep
->fi_offset
;
448 printf("Short read\n");
452 fs
= &devp
->un_fs
.di_fs
;
453 /* which block (or frag) in the file do we read? */
454 lbn
= lblkno(fs
, filep
->fi_offset
);
456 /* which physical block on the device do we read? */
457 filep
->fi_blocknum
= fsbtodb(fs
, sbmap(filep
, lbn
));
459 off
= blkoff(fs
, filep
->fi_offset
);
461 /* either blksize or fragsize */
462 size
= blksize(fs
, filep
->fi_inode
, lbn
);
463 filep
->fi_count
= size
;
464 /* reading on a ramdisk, just get a pointer to the data */
465 filep
->fi_memp
= NULL
;
470 if (filep
->fi_offset
- off
+ size
>= filep
->fi_inode
->i_size
)
471 filep
->fi_count
= diff
+ off
;
472 filep
->fi_count
-= off
;
473 p
= &filep
->fi_memp
[off
];
481 * This is the high-level read function. It works like this.
482 * We assume that our IO device buffers up some amount of
483 * data and that we can get a ptr to it. Thus we need
484 * to actually call the device func about filesize/blocksize times
485 * and this greatly increases our IO speed. When we already
486 * have data in the buffer, we just return that data (with bcopy() ).
490 bufs_read(int fd
, caddr_t buf
, size_t count
)
497 if (!(filep
= find_fp(fd
))) {
501 if ((filep
->fi_flags
& FI_COMPRESSED
) == 0 &&
502 filep
->fi_offset
+ count
> filep
->fi_inode
->i_size
)
503 count
= filep
->fi_inode
->i_size
- filep
->fi_offset
;
506 if ((i
= count
) == 0)
511 if (filep
->fi_flags
& FI_COMPRESSED
) {
512 if ((j
= cf_read(filep
, buf
, count
)) < 0)
513 return (0); /* encountered an error */
515 i
= j
; /* short read, must have hit EOF */
517 /* If we need to reload the buffer, do so */
518 if ((j
= filep
->fi_count
) == 0) {
519 (void) getblock(filep
, buf
, i
, &rcount
);
522 filep
->fi_offset
+= rcount
;
525 /* else just bcopy from our buffer */
527 bcopy(filep
->fi_memp
, buf
, (unsigned)j
);
532 filep
->fi_offset
+= j
;
533 filep
->fi_count
-= j
;
540 * This routine will open a device as it is known by the V2 OBP.
542 * err = mountroot(string);
544 * err = -1 on failure
545 * string: char string describing the properties of the device.
546 * We must not dork with any fi[]'s here. Save that for later.
550 bufs_mountroot(char *str
)
552 if (ufs_devp
) /* already mounted */
555 ufs_devp
= (devid_t
*)bkmem_alloc(sizeof (devid_t
));
556 ufs_devp
->di_taken
= 1;
557 ufs_devp
->di_dcookie
= 0;
558 ufs_devp
->di_desc
= (char *)bkmem_alloc(strlen(str
) + 1);
559 (void) strcpy(ufs_devp
->di_desc
, str
);
560 bzero(ufs_devp
->un_fs
.dummy
, SBSIZE
);
561 head
= (fileid_t
*)bkmem_alloc(sizeof (fileid_t
));
562 head
->fi_back
= head
->fi_forw
= head
;
563 head
->fi_filedes
= 0;
566 /* Setup read of the superblock */
567 head
->fi_devp
= ufs_devp
;
568 head
->fi_blocknum
= SBLOCK
;
569 head
->fi_count
= (uint_t
)SBSIZE
;
570 head
->fi_memp
= (caddr_t
)&(ufs_devp
->un_fs
.di_fs
);
573 if (diskread(head
)) {
574 printf("failed to read superblock\n");
575 (void) bufs_closeall(1);
579 if (ufs_devp
->un_fs
.di_fs
.fs_magic
!= FS_MAGIC
) {
580 dprintf("fs magic = 0x%x\n", ufs_devp
->un_fs
.di_fs
.fs_magic
);
581 (void) bufs_closeall(1);
584 dprintf("mountroot succeeded\n");
589 * Unmount the currently mounted root fs. In practice, this means
590 * closing all open files and releasing resources. All of this
591 * is done by closeall().
595 bufs_unmountroot(void)
597 if (ufs_devp
== NULL
)
600 (void) bufs_closeall(1);
606 * We allocate an fd here for use when talking
607 * to the file itself.
612 bufs_open(char *filename
, int flags
)
616 static int filedes
= 1;
618 dprintf("open: %s\n", filename
);
620 /* build and link a new file descriptor */
621 filep
= (fileid_t
*)bkmem_alloc(sizeof (fileid_t
));
622 filep
->fi_back
= head
->fi_back
;
623 filep
->fi_forw
= head
;
624 head
->fi_back
->fi_forw
= filep
;
625 head
->fi_back
= filep
;
626 filep
->fi_filedes
= filedes
++;
628 filep
->fi_path
= (char *)bkmem_alloc(strlen(filename
) + 1);
629 (void) strcpy(filep
->fi_path
, filename
);
630 filep
->fi_devp
= ufs_devp
; /* dev is already "mounted" */
631 filep
->fi_inode
= NULL
;
632 bzero(filep
->fi_buf
, MAXBSIZE
);
633 filep
->fi_getblock
= getblock_noopt
;
636 inode
= find(filep
, (char *)filename
);
637 if (inode
== (ino_t
)0) {
638 dprintf("open: cannot find %s\n", filename
);
639 (void) bufs_close(filep
->fi_filedes
);
642 if (openi(filep
, inode
)) {
643 printf("open: cannot open %s\n", filename
);
644 (void) bufs_close(filep
->fi_filedes
);
648 filep
->fi_offset
= filep
->fi_count
= 0;
650 if (cf_check_compressed(filep
) != 0)
652 return (filep
->fi_filedes
);
656 * We don't do any IO here.
657 * We just play games with the device pointers.
661 bufs_lseek(int fd
, off_t addr
, int whence
)
665 /* Make sure user knows what file they are talking to */
666 if (!(filep
= find_fp(fd
)))
669 if (filep
->fi_flags
& FI_COMPRESSED
) {
670 cf_seek(filep
, addr
, whence
);
674 filep
->fi_offset
+= addr
;
677 filep
->fi_offset
= addr
;
681 printf("lseek(): invalid whence value %d\n", whence
);
684 filep
->fi_blocknum
= addr
/ DEV_BSIZE
;
694 bufs_fstat(int fd
, struct bootstat
*stp
)
699 if (!(filep
= find_fp(fd
)))
702 ip
= filep
->fi_inode
;
710 switch (ip
->i_smode
& IFMT
) {
712 stp
->st_mode
= S_IFLNK
;
715 stp
->st_mode
= S_IFREG
;
721 * NOTE: this size will be the compressed size for a compressed file
722 * This could confuse the caller since we decompress the file behind
723 * the scenes when the file is read.
725 stp
->st_size
= ip
->i_size
;
726 stp
->st_atim
.tv_sec
= ip
->i_atime
.tv_sec
;
727 stp
->st_atim
.tv_nsec
= ip
->i_atime
.tv_usec
* 1000;
728 stp
->st_mtim
.tv_sec
= ip
->i_mtime
.tv_sec
;
729 stp
->st_mtim
.tv_nsec
= ip
->i_mtime
.tv_usec
* 1000;
730 stp
->st_ctim
.tv_sec
= ip
->i_ctime
.tv_sec
;
731 stp
->st_ctim
.tv_nsec
= ip
->i_ctime
.tv_usec
* 1000;
742 /* Make sure user knows what file they are talking to */
743 if (!(filep
= find_fp(fd
)))
746 if (filep
->fi_taken
&& (filep
!= head
)) {
747 /* Clear the ranks */
748 bkmem_free(filep
->fi_path
, strlen(filep
->fi_path
)+1);
749 filep
->fi_blocknum
= filep
->fi_count
= filep
->fi_offset
= 0;
750 filep
->fi_memp
= (caddr_t
)0;
754 /* unlink and deallocate node */
755 filep
->fi_forw
->fi_back
= filep
->fi_back
;
756 filep
->fi_back
->fi_forw
= filep
->fi_forw
;
758 bkmem_free((char *)filep
, sizeof (fileid_t
));
763 printf("\nFile descrip %d not allocated!", fd
);
770 bufs_closeall(int flag
)
772 fileid_t
*filep
= head
;
774 while ((filep
= filep
->fi_forw
) != head
)
776 if (bufs_close(filep
->fi_filedes
))
777 printf("Filesystem may be inconsistent.\n");
779 ufs_devp
->di_taken
= 0;
780 bkmem_free((char *)ufs_devp
, sizeof (devid_t
));
781 bkmem_free((char *)head
, sizeof (fileid_t
));
782 ufs_devp
= (devid_t
*)NULL
;
783 head
= (fileid_t
*)NULL
;
787 static struct cache
{
795 set_cache(int key
, void *data
, uint_t size
)
797 struct cache
*entry
= bkmem_alloc(sizeof (*entry
));
802 entry
->next
= icache
;
813 struct cache
*entry
= icache
;
815 if (entry
->key
== key
)
816 return (entry
->data
);
825 struct cache
*next
, *entry
= icache
;
828 bkmem_free(entry
->data
, entry
->size
);
829 bkmem_free(entry
, sizeof (*entry
));
835 struct boot_fs_ops bufs_ops
= {