1 /* $NetBSD: v7fs_inode.c,v 1.2 2011/07/18 21:51:49 apb Exp $ */
4 * Copyright (c) 2011 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #if HAVE_NBTOOL_CONFIG_H
33 #include "nbtool_config.h"
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: v7fs_inode.c,v 1.2 2011/07/18 21:51:49 apb Exp $");
38 #if defined _KERNEL_OPT
43 #include <sys/systm.h>
44 #include <sys/param.h>
53 #include "v7fs_impl.h"
54 #include "v7fs_endian.h"
55 #include "v7fs_inode.h"
56 #include "v7fs_superblock.h"
58 #ifdef V7FS_INODE_DEBUG
59 #define DPRINTF(fmt, args...) printf("%s: " fmt, __func__, ##args)
61 #define DPRINTF(fmt, args...) ((void)0)
64 static void v7fs_inode_setup_disk_image(const struct v7fs_self
*,
65 struct v7fs_inode
*, struct v7fs_inode_diskimage
*);
66 static int v7fs_inode_inquire_disk_location(const struct v7fs_self
*,
67 v7fs_ino_t
, v7fs_daddr_t
*, v7fs_daddr_t
*);
68 #ifdef V7FS_INODE_DEBUG
69 static int v7fs_inode_block_sanity(const struct v7fs_superblock
*,
73 v7fs_inode_block_sanity(const struct v7fs_superblock
*sb
, v7fs_daddr_t blk
)
76 if ((blk
< V7FS_ILIST_SECTOR
) || (blk
>= sb
->datablock_start_sector
)) {
77 DPRINTF("invalid inode block#%d (%d-%d)\n", blk
,
78 V7FS_ILIST_SECTOR
, sb
->datablock_start_sector
);
84 #endif /* V7FS_INODE_DEBUG */
87 v7fs_inode_number_sanity(const struct v7fs_superblock
*sb
, v7fs_ino_t ino
)
90 if (ino
< V7FS_ROOT_INODE
|| ((size_t)ino
>= V7FS_MAX_INODE(sb
))) {
91 DPRINTF("invalid inode#%d (%d-%zu)\n", ino
,
92 V7FS_ROOT_INODE
, V7FS_MAX_INODE(sb
));
100 v7fs_inode_allocate(struct v7fs_self
*fs
, v7fs_ino_t
*ino
)
102 struct v7fs_superblock
*sb
= &fs
->superblock
;
103 v7fs_ino_t inode_number
;
108 if (sb
->total_freeinode
== 0) {
109 DPRINTF("inode exhausted!(1)\n");
113 /* If there is no free inode cache, update it. */
114 if (sb
->nfreeinode
<= 0 && (error
= v7fs_freeinode_update(fs
))) {
115 DPRINTF("inode exhausted!(2)\n");
118 /* Get inode from superblock cache. */
119 KDASSERT(sb
->nfreeinode
<= V7FS_MAX_FREEINODE
);
120 inode_number
= sb
->freeinode
[--sb
->nfreeinode
];
121 sb
->total_freeinode
--;
124 if ((error
= v7fs_inode_number_sanity(sb
, inode_number
))) {
125 DPRINTF("new inode#%d %d %d\n", inode_number
, sb
->nfreeinode
,
126 sb
->total_freeinode
);
127 DPRINTF("free inode list corupt\n");
139 v7fs_inode_deallocate(struct v7fs_self
*fs
, v7fs_ino_t ino
)
141 struct v7fs_superblock
*sb
= &fs
->superblock
;
142 struct v7fs_inode inode
;
144 memset(&inode
, 0, sizeof(inode
));
145 inode
.inode_number
= ino
;
146 v7fs_inode_writeback(fs
, &inode
);
149 if (sb
->nfreeinode
< V7FS_MAX_FREEINODE
) {
150 /* link to freeinode list. */
151 sb
->freeinode
[sb
->nfreeinode
++] = ino
;
153 /* If superblock inode cache is full, this inode charged by
154 v7fs_freeinode_update() later. */
155 sb
->total_freeinode
++;
161 v7fs_inode_setup_memory_image(const struct v7fs_self
*fs __unused
,
162 struct v7fs_inode
*mem
, struct v7fs_inode_diskimage
*disk
)
164 #define conv16(m) (mem->m = V7FS_VAL16(fs, (disk->m)))
165 #define conv32(m) (mem->m = V7FS_VAL32(fs, (disk->m)))
169 memset(mem
, 0, sizeof(*mem
));
179 for (i
= 0; i
< V7FS_NADDR
; i
++) {
180 int j
= i
* 3; /* 3 byte each. (v7fs_daddr is 24bit) */
181 /* expand to 4byte with endian conversion. */
182 addr
= V7FS_VAL24_READ(fs
, &disk
->addr
[j
]);
186 if (v7fs_inode_iscdev(mem
) || v7fs_inode_isbdev(mem
)) {
187 mem
->device
= mem
->addr
[0];
195 v7fs_inode_setup_disk_image(const struct v7fs_self
*fs __unused
,
196 struct v7fs_inode
*mem
, struct v7fs_inode_diskimage
*disk
)
198 #define conv16(m) (disk->m = V7FS_VAL16(fs, (mem->m)))
199 #define conv32(m) (disk->m = V7FS_VAL32(fs, (mem->m)))
211 for (i
= 0; i
< V7FS_NADDR
; i
++) {
212 int j
= i
* 3; /* 3 byte each. */
213 V7FS_VAL24_WRITE(fs
, mem
->addr
[i
], disk
->addr
+ j
);
219 /* Load inode from disk. */
221 v7fs_inode_load(struct v7fs_self
*fs
, struct v7fs_inode
*p
, v7fs_ino_t n
)
223 v7fs_daddr_t blk
, ofs
;
224 struct v7fs_inode_diskimage
*di
;
227 if (v7fs_inode_inquire_disk_location(fs
, n
, &blk
, &ofs
) != 0)
231 if (!(buf
= scratch_read(fs
, blk
))) {
236 di
= (struct v7fs_inode_diskimage
*)buf
;
238 /* Decode disk address, convert endian. */
239 v7fs_inode_setup_memory_image(fs
, p
, di
+ ofs
);
242 scratch_free(fs
, buf
);
247 /* Write back inode to disk. */
249 v7fs_inode_writeback(struct v7fs_self
*fs
, struct v7fs_inode
*mem
)
251 struct v7fs_inode_diskimage disk
;
252 v7fs_ino_t ino
= mem
->inode_number
;
258 if (v7fs_inode_inquire_disk_location(fs
, ino
, &blk
, &ofs
) != 0)
261 v7fs_inode_setup_disk_image(fs
, mem
, &disk
);
264 if (!(buf
= scratch_read(fs
, blk
))) {
268 struct v7fs_inode_diskimage
*di
= (struct v7fs_inode_diskimage
*)buf
;
269 di
[ofs
] = disk
; /* structure copy; */
270 if (!fs
->io
.write(fs
->io
.cookie
, buf
, blk
))
274 scratch_free(fs
, buf
);
280 v7fs_inode_inquire_disk_location(const struct v7fs_self
*fs
281 __unused
, v7fs_ino_t n
, v7fs_daddr_t
*block
,
282 v7fs_daddr_t
*offset
)
284 v7fs_daddr_t ofs
, blk
;
285 #ifdef V7FS_INODE_DEBUG
286 v7fs_inode_number_sanity(&fs
->superblock
, n
);
288 ofs
= (n
- 1/*inode start from 1*/) *
289 sizeof(struct v7fs_inode_diskimage
);
290 blk
= ofs
>> V7FS_BSHIFT
;
292 *block
= blk
+ V7FS_ILIST_SECTOR
;
293 *offset
= (ofs
- blk
* V7FS_BSIZE
) /
294 sizeof(struct v7fs_inode_diskimage
);
295 #ifdef V7FS_INODE_DEBUG
296 return v7fs_inode_block_sanity(&fs
->superblock
, *block
);