nilfs_subr.c revision 1.4.2.3 1 1.4.2.3 yamt /* $NetBSD: nilfs_subr.c,v 1.4.2.3 2010/08/11 22:54:34 yamt Exp $ */
2 1.4.2.2 yamt
3 1.4.2.2 yamt /*
4 1.4.2.2 yamt * Copyright (c) 2008, 2009 Reinoud Zandijk
5 1.4.2.2 yamt * All rights reserved.
6 1.4.2.2 yamt *
7 1.4.2.2 yamt * Redistribution and use in source and binary forms, with or without
8 1.4.2.2 yamt * modification, are permitted provided that the following conditions
9 1.4.2.2 yamt * are met:
10 1.4.2.2 yamt * 1. Redistributions of source code must retain the above copyright
11 1.4.2.2 yamt * notice, this list of conditions and the following disclaimer.
12 1.4.2.2 yamt * 2. Redistributions in binary form must reproduce the above copyright
13 1.4.2.2 yamt * notice, this list of conditions and the following disclaimer in the
14 1.4.2.2 yamt * documentation and/or other materials provided with the distribution.
15 1.4.2.2 yamt *
16 1.4.2.2 yamt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 1.4.2.2 yamt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 1.4.2.2 yamt * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 1.4.2.2 yamt * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 1.4.2.2 yamt * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 1.4.2.2 yamt * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 1.4.2.2 yamt * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 1.4.2.2 yamt * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 1.4.2.2 yamt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 1.4.2.2 yamt * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 1.4.2.2 yamt *
27 1.4.2.2 yamt */
28 1.4.2.2 yamt
29 1.4.2.2 yamt #include <sys/cdefs.h>
30 1.4.2.2 yamt #ifndef lint
31 1.4.2.3 yamt __KERNEL_RCSID(0, "$NetBSD: nilfs_subr.c,v 1.4.2.3 2010/08/11 22:54:34 yamt Exp $");
32 1.4.2.2 yamt #endif /* not lint */
33 1.4.2.2 yamt
34 1.4.2.2 yamt #include <sys/param.h>
35 1.4.2.2 yamt #include <sys/systm.h>
36 1.4.2.2 yamt #include <sys/namei.h>
37 1.4.2.2 yamt #include <sys/resourcevar.h> /* defines plimit structure in proc struct */
38 1.4.2.2 yamt #include <sys/kernel.h>
39 1.4.2.2 yamt #include <sys/file.h> /* define FWRITE ... */
40 1.4.2.2 yamt #include <sys/stat.h>
41 1.4.2.2 yamt #include <sys/buf.h>
42 1.4.2.2 yamt #include <sys/proc.h>
43 1.4.2.2 yamt #include <sys/mount.h>
44 1.4.2.2 yamt #include <sys/vnode.h>
45 1.4.2.2 yamt #include <sys/signalvar.h>
46 1.4.2.2 yamt #include <sys/malloc.h>
47 1.4.2.2 yamt #include <sys/dirent.h>
48 1.4.2.2 yamt #include <sys/lockf.h>
49 1.4.2.2 yamt #include <sys/kauth.h>
50 1.4.2.2 yamt #include <sys/dirhash.h>
51 1.4.2.2 yamt
52 1.4.2.2 yamt #include <miscfs/genfs/genfs.h>
53 1.4.2.2 yamt #include <uvm/uvm_extern.h>
54 1.4.2.2 yamt
55 1.4.2.2 yamt #include <fs/nilfs/nilfs_mount.h>
56 1.4.2.2 yamt #include "nilfs.h"
57 1.4.2.2 yamt #include "nilfs_subr.h"
58 1.4.2.2 yamt #include "nilfs_bswap.h"
59 1.4.2.2 yamt
60 1.4.2.2 yamt
61 1.4.2.2 yamt #define VTOI(vnode) ((struct nilfs_node *) (vnode)->v_data)
62 1.4.2.2 yamt
63 1.4.2.3 yamt /* forwards */
64 1.4.2.3 yamt static int nilfs_btree_lookup(struct nilfs_node *node, uint64_t lblocknr,
65 1.4.2.3 yamt uint64_t *vblocknr);
66 1.4.2.3 yamt
67 1.4.2.2 yamt /* basic calculators */
68 1.4.2.2 yamt uint64_t nilfs_get_segnum_of_block(struct nilfs_device *nilfsdev,
69 1.4.2.2 yamt uint64_t blocknr)
70 1.4.2.2 yamt {
71 1.4.2.2 yamt return blocknr / nilfs_rw32(nilfsdev->super.s_blocks_per_segment);
72 1.4.2.2 yamt }
73 1.4.2.2 yamt
74 1.4.2.2 yamt
75 1.4.2.2 yamt void
76 1.4.2.2 yamt nilfs_get_segment_range(struct nilfs_device *nilfsdev, uint64_t segnum,
77 1.4.2.2 yamt uint64_t *seg_start, uint64_t *seg_end)
78 1.4.2.2 yamt {
79 1.4.2.2 yamt uint64_t blks_per_seg;
80 1.4.2.2 yamt
81 1.4.2.2 yamt blks_per_seg = nilfs_rw64(nilfsdev->super.s_blocks_per_segment);
82 1.4.2.2 yamt *seg_start = blks_per_seg * segnum;
83 1.4.2.2 yamt *seg_end = *seg_start + blks_per_seg -1;
84 1.4.2.2 yamt if (segnum == 0)
85 1.4.2.2 yamt *seg_start = nilfs_rw64(nilfsdev->super.s_first_data_block);
86 1.4.2.2 yamt }
87 1.4.2.2 yamt
88 1.4.2.2 yamt
89 1.4.2.2 yamt void nilfs_calc_mdt_consts(struct nilfs_device *nilfsdev,
90 1.4.2.2 yamt struct nilfs_mdt *mdt, int entry_size)
91 1.4.2.2 yamt {
92 1.4.2.2 yamt uint32_t blocksize = nilfsdev->blocksize;
93 1.4.2.2 yamt
94 1.4.2.2 yamt mdt->entries_per_group = blocksize * 8; /* bits in sector */
95 1.4.2.2 yamt mdt->entries_per_block = blocksize / entry_size;
96 1.4.2.2 yamt
97 1.4.2.2 yamt mdt->blocks_per_group =
98 1.4.2.2 yamt (mdt->entries_per_group -1) / mdt->entries_per_block + 1 + 1;
99 1.4.2.2 yamt mdt->groups_per_desc_block =
100 1.4.2.2 yamt blocksize / sizeof(struct nilfs_block_group_desc);
101 1.4.2.2 yamt mdt->blocks_per_desc_block =
102 1.4.2.2 yamt mdt->groups_per_desc_block * mdt->blocks_per_group + 1;
103 1.4.2.2 yamt }
104 1.4.2.2 yamt
105 1.4.2.2 yamt
106 1.4.2.2 yamt /* from NetBSD's src/sys/net/if_ethersubr.c */
107 1.4.2.2 yamt uint32_t
108 1.4.2.2 yamt crc32_le(uint32_t crc, const uint8_t *buf, size_t len)
109 1.4.2.2 yamt {
110 1.4.2.2 yamt static const uint32_t crctab[] = {
111 1.4.2.2 yamt 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
112 1.4.2.2 yamt 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
113 1.4.2.2 yamt 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
114 1.4.2.2 yamt 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
115 1.4.2.2 yamt };
116 1.4.2.2 yamt size_t i;
117 1.4.2.2 yamt
118 1.4.2.2 yamt for (i = 0; i < len; i++) {
119 1.4.2.2 yamt crc ^= buf[i];
120 1.4.2.2 yamt crc = (crc >> 4) ^ crctab[crc & 0xf];
121 1.4.2.2 yamt crc = (crc >> 4) ^ crctab[crc & 0xf];
122 1.4.2.2 yamt }
123 1.4.2.2 yamt
124 1.4.2.2 yamt return (crc);
125 1.4.2.2 yamt }
126 1.4.2.2 yamt
127 1.4.2.2 yamt
128 1.4.2.2 yamt static int
129 1.4.2.2 yamt nilfs_calchash(uint64_t ino)
130 1.4.2.2 yamt {
131 1.4.2.2 yamt return (int) ino;
132 1.4.2.2 yamt }
133 1.4.2.2 yamt
134 1.4.2.2 yamt
135 1.4.2.2 yamt /* dev reading */
136 1.4.2.2 yamt static int
137 1.4.2.2 yamt nilfs_dev_bread(struct nilfs_device *nilfsdev, uint64_t blocknr,
138 1.4.2.2 yamt struct kauth_cred *cred, int flags, struct buf **bpp)
139 1.4.2.2 yamt {
140 1.4.2.2 yamt int blk2dev = nilfsdev->blocksize / DEV_BSIZE;
141 1.4.2.2 yamt
142 1.4.2.2 yamt return bread(nilfsdev->devvp, blocknr * blk2dev, nilfsdev->blocksize,
143 1.4.2.2 yamt NOCRED, 0, bpp);
144 1.4.2.2 yamt }
145 1.4.2.2 yamt
146 1.4.2.2 yamt
147 1.4.2.2 yamt /* read on a node */
148 1.4.2.2 yamt int
149 1.4.2.2 yamt nilfs_bread(struct nilfs_node *node, uint64_t blocknr,
150 1.4.2.2 yamt struct kauth_cred *cred, int flags, struct buf **bpp)
151 1.4.2.2 yamt {
152 1.4.2.3 yamt uint64_t vblocknr;
153 1.4.2.3 yamt int error;
154 1.4.2.3 yamt
155 1.4.2.3 yamt error = nilfs_btree_lookup(node, blocknr, &vblocknr);
156 1.4.2.3 yamt if (error)
157 1.4.2.3 yamt return error;
158 1.4.2.3 yamt return bread(node->vnode, vblocknr, node->nilfsdev->blocksize,
159 1.4.2.2 yamt cred, flags, bpp);
160 1.4.2.2 yamt }
161 1.4.2.2 yamt
162 1.4.2.2 yamt
163 1.4.2.2 yamt /* segment-log reading */
164 1.4.2.2 yamt int
165 1.4.2.2 yamt nilfs_get_segment_log(struct nilfs_device *nilfsdev, uint64_t *blocknr,
166 1.4.2.2 yamt uint64_t *offset, struct buf **bpp, int len, void *blob)
167 1.4.2.2 yamt {
168 1.4.2.2 yamt int blocksize = nilfsdev->blocksize;
169 1.4.2.2 yamt int error;
170 1.4.2.2 yamt
171 1.4.2.2 yamt KASSERT(len <= blocksize);
172 1.4.2.2 yamt
173 1.4.2.2 yamt if (*offset + len > blocksize) {
174 1.4.2.2 yamt *blocknr = *blocknr + 1;
175 1.4.2.2 yamt *offset = 0;
176 1.4.2.2 yamt }
177 1.4.2.2 yamt if (*offset == 0) {
178 1.4.2.2 yamt if (*bpp)
179 1.4.2.2 yamt brelse(*bpp, BC_AGE);
180 1.4.2.2 yamt /* read in block */
181 1.4.2.2 yamt error = nilfs_dev_bread(nilfsdev, *blocknr, NOCRED, 0, bpp);
182 1.4.2.2 yamt if (error)
183 1.4.2.2 yamt return error;
184 1.4.2.2 yamt }
185 1.4.2.2 yamt memcpy(blob, ((uint8_t *) (*bpp)->b_data) + *offset, len);
186 1.4.2.2 yamt *offset += len;
187 1.4.2.2 yamt
188 1.4.2.2 yamt return 0;
189 1.4.2.2 yamt }
190 1.4.2.2 yamt
191 1.4.2.2 yamt /* -------------------------------------------------------------------------- */
192 1.4.2.2 yamt
193 1.4.2.2 yamt /* btree operations */
194 1.4.2.2 yamt
195 1.4.2.2 yamt static int
196 1.4.2.2 yamt nilfs_btree_lookup_level(struct nilfs_node *node, uint64_t lblocknr,
197 1.4.2.2 yamt uint64_t btree_vblknr, int level, uint64_t *vblocknr)
198 1.4.2.2 yamt {
199 1.4.2.2 yamt struct nilfs_device *nilfsdev = node->nilfsdev;
200 1.4.2.2 yamt struct nilfs_btree_node *btree_hdr;
201 1.4.2.2 yamt struct buf *bp;
202 1.4.2.2 yamt uint64_t btree_blknr;
203 1.4.2.2 yamt uint64_t *dkeys, *dptrs, child_btree_blk;
204 1.4.2.2 yamt uint8_t *pos;
205 1.4.2.2 yamt int i, error, selected;
206 1.4.2.2 yamt
207 1.4.2.2 yamt DPRINTF(TRANSLATE, ("nilfs_btree_lookup_level ino %"PRIu64", "
208 1.4.2.2 yamt "lblocknr %"PRIu64", btree_vblknr %"PRIu64", level %d\n",
209 1.4.2.2 yamt node->ino, lblocknr, btree_vblknr, level));
210 1.4.2.2 yamt
211 1.4.2.2 yamt /* translate btree_vblknr */
212 1.4.2.2 yamt error = nilfs_nvtop(node, 1, &btree_vblknr, &btree_blknr);
213 1.4.2.2 yamt if (error)
214 1.4.2.2 yamt return error;
215 1.4.2.2 yamt
216 1.4.2.2 yamt /* get our block */
217 1.4.2.2 yamt error = nilfs_dev_bread(nilfsdev, btree_blknr, NOCRED, 0, &bp);
218 1.4.2.2 yamt if (error) {
219 1.4.2.2 yamt brelse(bp, BC_AGE);
220 1.4.2.2 yamt return error;
221 1.4.2.2 yamt }
222 1.4.2.2 yamt
223 1.4.2.2 yamt btree_hdr = (struct nilfs_btree_node *) bp->b_data;
224 1.4.2.2 yamt pos = (uint8_t *) bp->b_data +
225 1.4.2.2 yamt sizeof(struct nilfs_btree_node) +
226 1.4.2.2 yamt NILFS_BTREE_NODE_EXTRA_PAD_SIZE;
227 1.4.2.2 yamt dkeys = (uint64_t *) pos;
228 1.4.2.2 yamt dptrs = dkeys + NILFS_BTREE_NODE_NCHILDREN_MAX(nilfsdev->blocksize);
229 1.4.2.2 yamt
230 1.4.2.2 yamt assert((btree_hdr->bn_flags & NILFS_BTREE_NODE_ROOT) == 0);
231 1.4.2.2 yamt
232 1.4.2.2 yamt /* select matching child XXX could use binary search */
233 1.4.2.2 yamt selected = 0;
234 1.4.2.2 yamt for (i = 0; i < nilfs_rw16(btree_hdr->bn_nchildren); i++) {
235 1.4.2.2 yamt if (dkeys[i] > lblocknr)
236 1.4.2.2 yamt break;
237 1.4.2.2 yamt selected = i;
238 1.4.2.2 yamt }
239 1.4.2.2 yamt
240 1.4.2.2 yamt if (level == 1) {
241 1.4.2.2 yamt /* if found it mapped */
242 1.4.2.2 yamt if (dkeys[selected] == lblocknr)
243 1.4.2.2 yamt *vblocknr = dptrs[selected];
244 1.4.2.2 yamt brelse(bp, BC_AGE);
245 1.4.2.2 yamt return 0;
246 1.4.2.2 yamt }
247 1.4.2.2 yamt
248 1.4.2.2 yamt /* lookup in selected child */
249 1.4.2.2 yamt assert(dkeys[selected] <= lblocknr);
250 1.4.2.2 yamt child_btree_blk = dptrs[selected];
251 1.4.2.2 yamt brelse(bp, BC_AGE);
252 1.4.2.2 yamt
253 1.4.2.2 yamt return nilfs_btree_lookup_level(node, lblocknr,
254 1.4.2.2 yamt child_btree_blk, btree_hdr->bn_level-1, vblocknr);
255 1.4.2.2 yamt }
256 1.4.2.2 yamt
257 1.4.2.2 yamt
258 1.4.2.2 yamt /* internal function */
259 1.4.2.2 yamt static int
260 1.4.2.2 yamt nilfs_btree_lookup(struct nilfs_node *node, uint64_t lblocknr,
261 1.4.2.2 yamt uint64_t *vblocknr)
262 1.4.2.2 yamt {
263 1.4.2.2 yamt struct nilfs_inode *inode = &node->inode;
264 1.4.2.2 yamt struct nilfs_btree_node *btree_hdr;
265 1.4.2.2 yamt uint64_t *dkeys, *dptrs, *dtrans;
266 1.4.2.2 yamt int i, selected;
267 1.4.2.2 yamt int error;
268 1.4.2.2 yamt
269 1.4.2.2 yamt DPRINTF(TRANSLATE, ("nilfs_btree_lookup ino %"PRIu64", "
270 1.4.2.2 yamt "lblocknr %"PRIu64"\n", node->ino, lblocknr));
271 1.4.2.2 yamt
272 1.4.2.2 yamt btree_hdr = (struct nilfs_btree_node *) &inode->i_bmap[0];
273 1.4.2.2 yamt dkeys = &inode->i_bmap[1];
274 1.4.2.2 yamt dptrs = dkeys + NILFS_BTREE_ROOT_NCHILDREN_MAX;
275 1.4.2.2 yamt dtrans = &inode->i_bmap[1];
276 1.4.2.2 yamt
277 1.4.2.2 yamt /* SMALL, direct lookup */
278 1.4.2.2 yamt *vblocknr = 0;
279 1.4.2.2 yamt if ((btree_hdr->bn_flags & NILFS_BMAP_LARGE) == 0) {
280 1.4.2.2 yamt if (lblocknr < NILFS_DIRECT_NBLOCKS) {
281 1.4.2.2 yamt *vblocknr = dtrans[lblocknr];
282 1.4.2.2 yamt return 0;
283 1.4.2.2 yamt }
284 1.4.2.2 yamt /* not mapped XXX could be considered error here */
285 1.4.2.2 yamt return 0;
286 1.4.2.2 yamt }
287 1.4.2.2 yamt
288 1.4.2.2 yamt /* LARGE, select matching child; XXX could use binary search */
289 1.4.2.2 yamt dtrans = NULL;
290 1.4.2.2 yamt error = 0;
291 1.4.2.2 yamt selected = 0;
292 1.4.2.2 yamt for (i = 0; i < nilfs_rw16(btree_hdr->bn_nchildren); i++) {
293 1.4.2.2 yamt if (dkeys[i] > lblocknr)
294 1.4.2.2 yamt break;
295 1.4.2.2 yamt selected = i;
296 1.4.2.2 yamt }
297 1.4.2.2 yamt
298 1.4.2.2 yamt /* if selected key > lblocknr, its not mapped */
299 1.4.2.2 yamt if (dkeys[selected] > lblocknr)
300 1.4.2.2 yamt return 0;
301 1.4.2.2 yamt
302 1.4.2.2 yamt /* overshooting? then not mapped */
303 1.4.2.2 yamt if (selected == nilfs_rw16(btree_hdr->bn_nchildren))
304 1.4.2.2 yamt return 0;
305 1.4.2.2 yamt
306 1.4.2.2 yamt /* level should be > 1 or otherwise it should be a direct one */
307 1.4.2.2 yamt assert(btree_hdr->bn_level > 1);
308 1.4.2.2 yamt
309 1.4.2.2 yamt /* lookup in selected child */
310 1.4.2.2 yamt assert(dkeys[selected] <= lblocknr);
311 1.4.2.2 yamt error = nilfs_btree_lookup_level(node, lblocknr,
312 1.4.2.2 yamt dptrs[selected], btree_hdr->bn_level-1, vblocknr);
313 1.4.2.2 yamt
314 1.4.2.2 yamt return error;
315 1.4.2.2 yamt }
316 1.4.2.2 yamt
317 1.4.2.2 yamt
318 1.4.2.2 yamt /* node should be locked on entry to prevent btree changes (unlikely) */
319 1.4.2.2 yamt int
320 1.4.2.2 yamt nilfs_btree_nlookup(struct nilfs_node *node, uint64_t from, uint64_t blks,
321 1.4.2.2 yamt uint64_t *l2vmap)
322 1.4.2.2 yamt {
323 1.4.2.2 yamt uint64_t lblocknr, *vblocknr;
324 1.4.2.2 yamt int i, error;
325 1.4.2.2 yamt
326 1.4.2.2 yamt /* TODO / OPTI multiple translations in one go possible */
327 1.4.2.2 yamt error = EINVAL;
328 1.4.2.2 yamt for (i = 0; i < blks; i++) {
329 1.4.2.2 yamt lblocknr = from + i;
330 1.4.2.2 yamt vblocknr = l2vmap + i;
331 1.4.2.2 yamt error = nilfs_btree_lookup(node, lblocknr, vblocknr);
332 1.4.2.2 yamt
333 1.4.2.2 yamt DPRINTF(TRANSLATE, ("btree_nlookup ino %"PRIu64", "
334 1.4.2.2 yamt "lblocknr %"PRIu64" -> %"PRIu64"\n",
335 1.4.2.2 yamt node->ino, lblocknr, *vblocknr));
336 1.4.2.2 yamt if (error)
337 1.4.2.2 yamt break;
338 1.4.2.2 yamt }
339 1.4.2.2 yamt
340 1.4.2.2 yamt return error;
341 1.4.2.2 yamt }
342 1.4.2.2 yamt
343 1.4.2.2 yamt /* --------------------------------------------------------------------- */
344 1.4.2.2 yamt
345 1.4.2.2 yamt /* vtop operations */
346 1.4.2.2 yamt
347 1.4.2.2 yamt /* translate index to a file block number and an entry */
348 1.4.2.2 yamt static void
349 1.4.2.2 yamt nilfs_mdt_trans(struct nilfs_mdt *mdt, uint64_t index,
350 1.4.2.2 yamt uint64_t *blocknr, uint32_t *entry_in_block)
351 1.4.2.2 yamt {
352 1.4.2.2 yamt uint64_t blknr;
353 1.4.2.2 yamt uint64_t group, group_offset, blocknr_in_group;
354 1.4.2.2 yamt uint64_t desc_block, desc_offset;
355 1.4.2.2 yamt
356 1.4.2.2 yamt /* calculate our offset in the file */
357 1.4.2.2 yamt group = index / mdt->entries_per_group;
358 1.4.2.2 yamt group_offset = index % mdt->entries_per_group;
359 1.4.2.2 yamt desc_block = group / mdt->groups_per_desc_block;
360 1.4.2.2 yamt desc_offset = group % mdt->groups_per_desc_block;
361 1.4.2.2 yamt blocknr_in_group = group_offset / mdt->entries_per_block;
362 1.4.2.2 yamt
363 1.4.2.2 yamt /* to descgroup offset */
364 1.4.2.2 yamt blknr = 1 + desc_block * mdt->blocks_per_desc_block;
365 1.4.2.2 yamt
366 1.4.2.2 yamt /* to group offset */
367 1.4.2.2 yamt blknr += desc_offset * mdt->blocks_per_group;
368 1.4.2.2 yamt
369 1.4.2.2 yamt /* to actual file block */
370 1.4.2.2 yamt blknr += 1 + blocknr_in_group;
371 1.4.2.2 yamt
372 1.4.2.2 yamt *blocknr = blknr;
373 1.4.2.2 yamt *entry_in_block = group_offset % mdt->entries_per_block;
374 1.4.2.2 yamt }
375 1.4.2.2 yamt
376 1.4.2.2 yamt
377 1.4.2.2 yamt static int
378 1.4.2.2 yamt nilfs_vtop(struct nilfs_device *nilfsdev, uint64_t vblocknr, uint64_t *pblocknr)
379 1.4.2.2 yamt {
380 1.4.2.2 yamt struct nilfs_dat_entry *entry;
381 1.4.2.2 yamt struct buf *bp;
382 1.4.2.2 yamt uint64_t ldatblknr;
383 1.4.2.2 yamt uint32_t entry_in_block;
384 1.4.2.2 yamt int error;
385 1.4.2.2 yamt
386 1.4.2.2 yamt nilfs_mdt_trans(&nilfsdev->dat_mdt, vblocknr,
387 1.4.2.2 yamt &ldatblknr, &entry_in_block);
388 1.4.2.2 yamt
389 1.4.2.2 yamt error = nilfs_bread(nilfsdev->dat_node, ldatblknr, NOCRED, 0, &bp);
390 1.4.2.2 yamt if (error) {
391 1.4.2.2 yamt printf("vtop: can't read in DAT block %"PRIu64"!\n", ldatblknr);
392 1.4.2.2 yamt brelse(bp, BC_AGE);
393 1.4.2.2 yamt return error;
394 1.4.2.2 yamt }
395 1.4.2.2 yamt
396 1.4.2.2 yamt /* get our translation */
397 1.4.2.2 yamt entry = ((struct nilfs_dat_entry *) bp->b_data) + entry_in_block;
398 1.4.2.2 yamt #if 0
399 1.4.2.2 yamt printf("\tvblk %4"PRIu64" -> %"PRIu64" for "
400 1.4.2.2 yamt "checkpoint %"PRIu64" to %"PRIu64"\n",
401 1.4.2.2 yamt vblocknr,
402 1.4.2.2 yamt nilfs_rw64(entry->de_blocknr),
403 1.4.2.2 yamt nilfs_rw64(entry->de_start),
404 1.4.2.2 yamt nilfs_rw64(entry->de_end));
405 1.4.2.2 yamt #endif
406 1.4.2.2 yamt
407 1.4.2.2 yamt *pblocknr = nilfs_rw64(entry->de_blocknr);
408 1.4.2.2 yamt brelse(bp, BC_AGE);
409 1.4.2.2 yamt
410 1.4.2.2 yamt return 0;
411 1.4.2.2 yamt }
412 1.4.2.2 yamt
413 1.4.2.2 yamt
414 1.4.2.2 yamt int
415 1.4.2.2 yamt nilfs_nvtop(struct nilfs_node *node, uint64_t blks, uint64_t *l2vmap,
416 1.4.2.2 yamt uint64_t *v2pmap)
417 1.4.2.2 yamt {
418 1.4.2.2 yamt uint64_t vblocknr, *pblocknr;
419 1.4.2.2 yamt int i, error;
420 1.4.2.2 yamt
421 1.4.2.2 yamt /* the DAT inode is the only one not mapped virtual */
422 1.4.2.2 yamt if (node->ino == NILFS_DAT_INO) {
423 1.4.2.2 yamt memcpy(v2pmap, l2vmap, blks * sizeof(uint64_t));
424 1.4.2.2 yamt return 0;
425 1.4.2.2 yamt }
426 1.4.2.2 yamt
427 1.4.2.2 yamt /* TODO / OPTI more translations in one go */
428 1.4.2.2 yamt error = 0;
429 1.4.2.2 yamt for (i = 0; i < blks; i++) {
430 1.4.2.2 yamt vblocknr = l2vmap[i];
431 1.4.2.2 yamt pblocknr = v2pmap + i;
432 1.4.2.2 yamt *pblocknr = 0;
433 1.4.2.2 yamt
434 1.4.2.2 yamt /* only translate valid vblocknrs */
435 1.4.2.2 yamt if (vblocknr == 0)
436 1.4.2.2 yamt continue;
437 1.4.2.2 yamt error = nilfs_vtop(node->nilfsdev, vblocknr, pblocknr);
438 1.4.2.2 yamt if (error)
439 1.4.2.2 yamt break;
440 1.4.2.2 yamt }
441 1.4.2.2 yamt
442 1.4.2.2 yamt return error;
443 1.4.2.2 yamt }
444 1.4.2.2 yamt
445 1.4.2.2 yamt /* --------------------------------------------------------------------- */
446 1.4.2.2 yamt
447 1.4.2.2 yamt struct nilfs_recover_info {
448 1.4.2.2 yamt uint64_t segnum;
449 1.4.2.2 yamt uint64_t pseg;
450 1.4.2.2 yamt
451 1.4.2.2 yamt struct nilfs_segment_summary segsum;
452 1.4.2.2 yamt struct nilfs_super_root super_root;
453 1.4.2.2 yamt STAILQ_ENTRY(nilfs_recover_info) next;
454 1.4.2.2 yamt };
455 1.4.2.2 yamt
456 1.4.2.2 yamt
457 1.4.2.2 yamt /*
458 1.4.2.2 yamt * Helper functions of nilfs_mount() that actually mounts the disc.
459 1.4.2.2 yamt */
460 1.4.2.2 yamt static int
461 1.4.2.2 yamt nilfs_load_segsum(struct nilfs_device *nilfsdev,
462 1.4.2.2 yamt struct nilfs_recover_info *ri)
463 1.4.2.2 yamt {
464 1.4.2.2 yamt struct buf *bp;
465 1.4.2.2 yamt uint64_t blocknr, offset;
466 1.4.2.2 yamt uint32_t segsum_struct_size;
467 1.4.2.2 yamt uint32_t magic;
468 1.4.2.2 yamt int error;
469 1.4.2.2 yamt
470 1.4.2.2 yamt segsum_struct_size = sizeof(struct nilfs_segment_summary);
471 1.4.2.2 yamt
472 1.4.2.2 yamt /* read in segsum structure */
473 1.4.2.2 yamt bp = NULL;
474 1.4.2.2 yamt blocknr = ri->pseg;
475 1.4.2.2 yamt offset = 0;
476 1.4.2.2 yamt error = nilfs_get_segment_log(nilfsdev,
477 1.4.2.2 yamt &blocknr, &offset, &bp,
478 1.4.2.2 yamt segsum_struct_size, (void *) &ri->segsum);
479 1.4.2.2 yamt if (error)
480 1.4.2.2 yamt goto out;
481 1.4.2.2 yamt
482 1.4.2.2 yamt /* sanity checks */
483 1.4.2.2 yamt magic = nilfs_rw32(ri->segsum.ss_magic);
484 1.4.2.2 yamt if (magic != NILFS_SEGSUM_MAGIC) {
485 1.4.2.2 yamt DPRINTF(VOLUMES, ("nilfs: bad magic in pseg %"PRIu64"\n",
486 1.4.2.2 yamt ri->pseg));
487 1.4.2.2 yamt error = EINVAL;
488 1.4.2.2 yamt goto out;
489 1.4.2.2 yamt }
490 1.4.2.2 yamt
491 1.4.2.2 yamt /* TODO check segment summary checksum */
492 1.4.2.2 yamt /* TODO check data checksum */
493 1.4.2.2 yamt
494 1.4.2.2 yamt out:
495 1.4.2.2 yamt if (bp)
496 1.4.2.2 yamt brelse(bp, BC_AGE);
497 1.4.2.2 yamt
498 1.4.2.2 yamt return error;
499 1.4.2.2 yamt }
500 1.4.2.2 yamt
501 1.4.2.2 yamt
502 1.4.2.2 yamt static int
503 1.4.2.2 yamt nilfs_load_super_root(struct nilfs_device *nilfsdev,
504 1.4.2.2 yamt struct nilfs_recover_info *ri)
505 1.4.2.2 yamt {
506 1.4.2.2 yamt struct nilfs_segment_summary *segsum = &ri->segsum;
507 1.4.2.2 yamt struct nilfs_super_root *super_root;
508 1.4.2.2 yamt struct buf *bp;
509 1.4.2.2 yamt uint64_t blocknr, offset;
510 1.4.2.2 yamt uint32_t segsum_size, size;
511 1.4.2.2 yamt uint32_t nsumblk, nfileblk;
512 1.4.2.2 yamt uint32_t super_root_crc, comp_crc;
513 1.4.2.2 yamt int off, error;
514 1.4.2.2 yamt
515 1.4.2.2 yamt /* process segment summary */
516 1.4.2.2 yamt segsum_size = nilfs_rw32(segsum->ss_sumbytes);
517 1.4.2.2 yamt nsumblk = (segsum_size - 1) / nilfsdev->blocksize + 1;
518 1.4.2.2 yamt nfileblk = nilfs_rw32(segsum->ss_nblocks) - nsumblk;
519 1.4.2.2 yamt
520 1.4.2.2 yamt /* check if there is a superroot */
521 1.4.2.2 yamt if ((nilfs_rw16(segsum->ss_flags) & NILFS_SS_SR) == 0) {
522 1.4.2.2 yamt DPRINTF(VOLUMES, ("nilfs: no super root in pseg %"PRIu64"\n",
523 1.4.2.2 yamt ri->pseg));
524 1.4.2.2 yamt return ENOENT;
525 1.4.2.2 yamt }
526 1.4.2.2 yamt
527 1.4.2.2 yamt /* get our super root, located at the end of the pseg */
528 1.4.2.2 yamt blocknr = ri->pseg + nsumblk + nfileblk - 1;
529 1.4.2.2 yamt offset = 0;
530 1.4.2.2 yamt size = sizeof(struct nilfs_super_root);
531 1.4.2.2 yamt bp = NULL;
532 1.4.2.2 yamt error = nilfs_get_segment_log(nilfsdev,
533 1.4.2.2 yamt &blocknr, &offset, &bp,
534 1.4.2.2 yamt size, (void *) &nilfsdev->super_root);
535 1.4.2.2 yamt if (bp)
536 1.4.2.2 yamt brelse(bp, BC_AGE);
537 1.4.2.2 yamt if (error) {
538 1.4.2.2 yamt printf("read in of superroot failed\n");
539 1.4.2.2 yamt return EIO;
540 1.4.2.2 yamt }
541 1.4.2.2 yamt
542 1.4.2.2 yamt /* check super root crc */
543 1.4.2.2 yamt super_root = &nilfsdev->super_root;
544 1.4.2.2 yamt super_root_crc = nilfs_rw32(super_root->sr_sum);
545 1.4.2.2 yamt off = sizeof(super_root->sr_sum);
546 1.4.2.2 yamt comp_crc = crc32_le(nilfs_rw32(nilfsdev->super.s_crc_seed),
547 1.4.2.2 yamt (uint8_t *) super_root + off,
548 1.4.2.2 yamt NILFS_SR_BYTES - off);
549 1.4.2.2 yamt if (super_root_crc != comp_crc) {
550 1.4.2.2 yamt DPRINTF(VOLUMES, (" invalid superroot, likely from old format\n"));
551 1.4.2.2 yamt return EINVAL;
552 1.4.2.2 yamt }
553 1.4.2.2 yamt
554 1.4.2.2 yamt DPRINTF(VOLUMES, (" got valid superroot\n"));
555 1.4.2.2 yamt
556 1.4.2.2 yamt return 0;
557 1.4.2.2 yamt }
558 1.4.2.2 yamt
559 1.4.2.2 yamt /*
560 1.4.2.2 yamt * Search for the last super root recorded.
561 1.4.2.2 yamt */
562 1.4.2.2 yamt void
563 1.4.2.2 yamt nilfs_search_super_root(struct nilfs_device *nilfsdev)
564 1.4.2.2 yamt {
565 1.4.2.2 yamt struct nilfs_super_block *super;
566 1.4.2.2 yamt struct nilfs_segment_summary *segsum;
567 1.4.2.2 yamt struct nilfs_recover_info *ri, *ori, *i_ri;
568 1.4.2.2 yamt STAILQ_HEAD(,nilfs_recover_info) ri_list;
569 1.4.2.2 yamt uint64_t seg_start, seg_end, cno;
570 1.4.2.2 yamt uint32_t segsum_size;
571 1.4.2.2 yamt uint32_t nsumblk, nfileblk;
572 1.4.2.2 yamt int error;
573 1.4.2.2 yamt
574 1.4.2.2 yamt STAILQ_INIT(&ri_list);
575 1.4.2.2 yamt
576 1.4.2.2 yamt /* search for last super root */
577 1.4.2.2 yamt ri = malloc(sizeof(struct nilfs_recover_info), M_NILFSTEMP, M_WAITOK);
578 1.4.2.2 yamt memset(ri, 0, sizeof(struct nilfs_recover_info));
579 1.4.2.2 yamt
580 1.4.2.2 yamt /* if enabled, start from the specified position */
581 1.4.2.2 yamt if (0) {
582 1.4.2.2 yamt /* start from set start */
583 1.4.2.2 yamt nilfsdev->super.s_last_pseg = nilfsdev->super.s_first_data_block;
584 1.4.2.2 yamt nilfsdev->super.s_last_cno = nilfs_rw64(1);
585 1.4.2.2 yamt }
586 1.4.2.2 yamt
587 1.4.2.2 yamt ri->pseg = nilfs_rw64(nilfsdev->super.s_last_pseg); /* blknr */
588 1.4.2.2 yamt ri->segnum = nilfs_get_segnum_of_block(nilfsdev, ri->pseg);
589 1.4.2.2 yamt
590 1.4.2.2 yamt error = 0;
591 1.4.2.2 yamt cno = nilfs_rw64(nilfsdev->super.s_last_cno);
592 1.4.2.2 yamt DPRINTF(VOLUMES, ("nilfs: seach_super_root start in pseg %"PRIu64"\n",
593 1.4.2.2 yamt ri->pseg));
594 1.4.2.2 yamt for (;;) {
595 1.4.2.2 yamt DPRINTF(VOLUMES, (" at pseg %"PRIu64"\n", ri->pseg));
596 1.4.2.2 yamt error = nilfs_load_segsum(nilfsdev, ri);
597 1.4.2.2 yamt if (error)
598 1.4.2.2 yamt break;
599 1.4.2.2 yamt
600 1.4.2.2 yamt segsum = &ri->segsum;
601 1.4.2.2 yamt
602 1.4.2.2 yamt /* try to load super root */
603 1.4.2.2 yamt if (nilfs_rw16(segsum->ss_flags) & NILFS_SS_SR) {
604 1.4.2.2 yamt DPRINTF(VOLUMES, (" try super root\n"));
605 1.4.2.2 yamt error = nilfs_load_super_root(nilfsdev, ri);
606 1.4.2.2 yamt if (error)
607 1.4.2.2 yamt break; /* confused */
608 1.4.2.2 yamt /* wipe current list of ri */
609 1.4.2.2 yamt while (!STAILQ_EMPTY(&ri_list)) {
610 1.4.2.2 yamt i_ri = STAILQ_FIRST(&ri_list);
611 1.4.2.2 yamt STAILQ_REMOVE_HEAD(&ri_list, next);
612 1.4.2.2 yamt free(i_ri, M_NILFSTEMP);
613 1.4.2.2 yamt }
614 1.4.2.2 yamt super = &nilfsdev->super;
615 1.4.2.2 yamt
616 1.4.2.2 yamt super->s_last_pseg = nilfs_rw64(ri->pseg);
617 1.4.2.2 yamt super->s_last_cno = cno++;
618 1.4.2.2 yamt super->s_last_seq = segsum->ss_seq;
619 1.4.2.2 yamt super->s_state = nilfs_rw16(NILFS_VALID_FS);
620 1.4.2.2 yamt } else {
621 1.4.2.2 yamt STAILQ_INSERT_TAIL(&ri_list, ri, next);
622 1.4.2.2 yamt ori = ri;
623 1.4.2.2 yamt ri = malloc(sizeof(struct nilfs_recover_info),
624 1.4.2.2 yamt M_NILFSTEMP, M_WAITOK);
625 1.4.2.2 yamt memset(ri, 0, sizeof(struct nilfs_recover_info));
626 1.4.2.2 yamt ri->segnum = ori->segnum;
627 1.4.2.2 yamt ri->pseg = ori->pseg;
628 1.4.2.2 yamt /* segsum keeps pointing to the `old' ri */
629 1.4.2.2 yamt }
630 1.4.2.2 yamt
631 1.4.2.2 yamt /* continue to the next pseg */
632 1.4.2.2 yamt segsum_size = nilfs_rw32(segsum->ss_sumbytes);
633 1.4.2.2 yamt nsumblk = (segsum_size - 1) / nilfsdev->blocksize + 1;
634 1.4.2.2 yamt nfileblk = nilfs_rw32(segsum->ss_nblocks) - nsumblk;
635 1.4.2.2 yamt
636 1.4.2.2 yamt /* calculate next partial segment location */
637 1.4.2.2 yamt ri->pseg += nsumblk + nfileblk;
638 1.4.2.2 yamt
639 1.4.2.2 yamt /* did we reach the end of the segment? if so, go to the next */
640 1.4.2.2 yamt nilfs_get_segment_range(nilfsdev, ri->segnum, &seg_start, &seg_end);
641 1.4.2.2 yamt if (ri->pseg >= seg_end)
642 1.4.2.2 yamt ri->pseg = nilfs_rw64(segsum->ss_next);
643 1.4.2.2 yamt ri->segnum = nilfs_get_segnum_of_block(nilfsdev, ri->pseg);
644 1.4.2.2 yamt }
645 1.4.2.2 yamt
646 1.4.2.2 yamt /*
647 1.4.2.2 yamt * XXX No roll-forward yet of the remaining partial segments.
648 1.4.2.2 yamt */
649 1.4.2.2 yamt
650 1.4.2.2 yamt /* wipe current list of ri */
651 1.4.2.2 yamt while (!STAILQ_EMPTY(&ri_list)) {
652 1.4.2.2 yamt i_ri = STAILQ_FIRST(&ri_list);
653 1.4.2.2 yamt STAILQ_REMOVE_HEAD(&ri_list, next);
654 1.4.2.2 yamt printf("nilfs: ignoring pseg at %"PRIu64"\n", i_ri->pseg);
655 1.4.2.2 yamt free(i_ri, M_NILFSTEMP);
656 1.4.2.2 yamt }
657 1.4.2.2 yamt free(ri, M_NILFSTEMP);
658 1.4.2.2 yamt }
659 1.4.2.2 yamt
660 1.4.2.2 yamt /* --------------------------------------------------------------------- */
661 1.4.2.2 yamt
662 1.4.2.2 yamt /*
663 1.4.2.2 yamt * Genfs interfacing
664 1.4.2.2 yamt *
665 1.4.2.2 yamt * static const struct genfs_ops nilfs_genfsops = {
666 1.4.2.2 yamt * .gop_size = genfs_size,
667 1.4.2.2 yamt * size of transfers
668 1.4.2.2 yamt * .gop_alloc = nilfs_gop_alloc,
669 1.4.2.2 yamt * allocate len bytes at offset
670 1.4.2.2 yamt * .gop_write = genfs_gop_write,
671 1.4.2.2 yamt * putpages interface code
672 1.4.2.2 yamt * .gop_markupdate = nilfs_gop_markupdate,
673 1.4.2.2 yamt * set update/modify flags etc.
674 1.4.2.2 yamt * }
675 1.4.2.2 yamt */
676 1.4.2.2 yamt
677 1.4.2.2 yamt /*
678 1.4.2.2 yamt * Callback from genfs to allocate len bytes at offset off; only called when
679 1.4.2.2 yamt * filling up gaps in the allocation.
680 1.4.2.2 yamt */
681 1.4.2.2 yamt static int
682 1.4.2.2 yamt nilfs_gop_alloc(struct vnode *vp, off_t off,
683 1.4.2.2 yamt off_t len, int flags, kauth_cred_t cred)
684 1.4.2.2 yamt {
685 1.4.2.2 yamt DPRINTF(NOTIMPL, ("nilfs_gop_alloc not implemented\n"));
686 1.4.2.2 yamt DPRINTF(ALLOC, ("nilfs_gop_alloc called for %"PRIu64" bytes\n", len));
687 1.4.2.2 yamt
688 1.4.2.2 yamt return 0;
689 1.4.2.2 yamt }
690 1.4.2.2 yamt
691 1.4.2.2 yamt
692 1.4.2.2 yamt /*
693 1.4.2.2 yamt * callback from genfs to update our flags
694 1.4.2.2 yamt */
695 1.4.2.2 yamt static void
696 1.4.2.2 yamt nilfs_gop_markupdate(struct vnode *vp, int flags)
697 1.4.2.2 yamt {
698 1.4.2.2 yamt struct nilfs_node *nilfs_node = VTOI(vp);
699 1.4.2.2 yamt u_long mask = 0;
700 1.4.2.2 yamt
701 1.4.2.2 yamt if ((flags & GOP_UPDATE_ACCESSED) != 0) {
702 1.4.2.2 yamt mask = IN_ACCESS;
703 1.4.2.2 yamt }
704 1.4.2.2 yamt if ((flags & GOP_UPDATE_MODIFIED) != 0) {
705 1.4.2.2 yamt if (vp->v_type == VREG) {
706 1.4.2.2 yamt mask |= IN_CHANGE | IN_UPDATE;
707 1.4.2.2 yamt } else {
708 1.4.2.2 yamt mask |= IN_MODIFY;
709 1.4.2.2 yamt }
710 1.4.2.2 yamt }
711 1.4.2.2 yamt if (mask) {
712 1.4.2.2 yamt nilfs_node->i_flags |= mask;
713 1.4.2.2 yamt }
714 1.4.2.2 yamt }
715 1.4.2.2 yamt
716 1.4.2.2 yamt
717 1.4.2.2 yamt static const struct genfs_ops nilfs_genfsops = {
718 1.4.2.2 yamt .gop_size = genfs_size,
719 1.4.2.2 yamt .gop_alloc = nilfs_gop_alloc,
720 1.4.2.2 yamt .gop_write = genfs_gop_write_rwmap,
721 1.4.2.2 yamt .gop_markupdate = nilfs_gop_markupdate,
722 1.4.2.2 yamt };
723 1.4.2.2 yamt
724 1.4.2.2 yamt /* --------------------------------------------------------------------- */
725 1.4.2.2 yamt
726 1.4.2.2 yamt static void
727 1.4.2.2 yamt nilfs_register_node(struct nilfs_node *node)
728 1.4.2.2 yamt {
729 1.4.2.2 yamt struct nilfs_mount *ump;
730 1.4.2.2 yamt struct nilfs_node *chk;
731 1.4.2.2 yamt uint32_t hashline;
732 1.4.2.2 yamt
733 1.4.2.2 yamt ump = node->ump;
734 1.4.2.2 yamt mutex_enter(&ump->ihash_lock);
735 1.4.2.2 yamt
736 1.4.2.2 yamt /* add to our hash table */
737 1.4.2.2 yamt hashline = nilfs_calchash(node->ino) & NILFS_INODE_HASHMASK;
738 1.4.2.2 yamt #ifdef DEBUG
739 1.4.2.2 yamt LIST_FOREACH(chk, &ump->nilfs_nodes[hashline], hashchain) {
740 1.4.2.2 yamt assert(chk);
741 1.4.2.2 yamt if (chk->ino == node->ino)
742 1.4.2.2 yamt panic("Double node entered\n");
743 1.4.2.2 yamt }
744 1.4.2.2 yamt #else
745 1.4.2.2 yamt chk = NULL;
746 1.4.2.2 yamt #endif
747 1.4.2.2 yamt LIST_INSERT_HEAD(&ump->nilfs_nodes[hashline], node, hashchain);
748 1.4.2.2 yamt
749 1.4.2.2 yamt mutex_exit(&ump->ihash_lock);
750 1.4.2.2 yamt }
751 1.4.2.2 yamt
752 1.4.2.2 yamt
753 1.4.2.2 yamt static void
754 1.4.2.2 yamt nilfs_deregister_node(struct nilfs_node *node)
755 1.4.2.2 yamt {
756 1.4.2.2 yamt struct nilfs_mount *ump;
757 1.4.2.2 yamt
758 1.4.2.2 yamt ump = node->ump;
759 1.4.2.2 yamt mutex_enter(&ump->ihash_lock);
760 1.4.2.2 yamt
761 1.4.2.2 yamt /* remove from hash list */
762 1.4.2.2 yamt LIST_REMOVE(node, hashchain);
763 1.4.2.2 yamt
764 1.4.2.2 yamt mutex_exit(&ump->ihash_lock);
765 1.4.2.2 yamt }
766 1.4.2.2 yamt
767 1.4.2.2 yamt
768 1.4.2.2 yamt static struct nilfs_node *
769 1.4.2.2 yamt nilfs_hash_lookup(struct nilfs_mount *ump, ino_t ino)
770 1.4.2.2 yamt {
771 1.4.2.2 yamt struct nilfs_node *node;
772 1.4.2.2 yamt struct vnode *vp;
773 1.4.2.2 yamt uint32_t hashline;
774 1.4.2.2 yamt
775 1.4.2.2 yamt loop:
776 1.4.2.2 yamt mutex_enter(&ump->ihash_lock);
777 1.4.2.2 yamt
778 1.4.2.2 yamt /* search our hash table */
779 1.4.2.2 yamt hashline = nilfs_calchash(ino) & NILFS_INODE_HASHMASK;
780 1.4.2.2 yamt LIST_FOREACH(node, &ump->nilfs_nodes[hashline], hashchain) {
781 1.4.2.2 yamt assert(node);
782 1.4.2.2 yamt if (node->ino == ino) {
783 1.4.2.2 yamt vp = node->vnode;
784 1.4.2.2 yamt assert(vp);
785 1.4.2.2 yamt mutex_enter(&vp->v_interlock);
786 1.4.2.2 yamt mutex_exit(&ump->ihash_lock);
787 1.4.2.3 yamt if (vget(vp, LK_EXCLUSIVE))
788 1.4.2.2 yamt goto loop;
789 1.4.2.2 yamt return node;
790 1.4.2.2 yamt }
791 1.4.2.2 yamt }
792 1.4.2.2 yamt mutex_exit(&ump->ihash_lock);
793 1.4.2.2 yamt
794 1.4.2.2 yamt return NULL;
795 1.4.2.2 yamt }
796 1.4.2.2 yamt
797 1.4.2.2 yamt
798 1.4.2.2 yamt /* node action implementators */
799 1.4.2.2 yamt extern int (**nilfs_vnodeop_p)(void *);
800 1.4.2.2 yamt
801 1.4.2.2 yamt int
802 1.4.2.2 yamt nilfs_get_node_raw(struct nilfs_device *nilfsdev, struct nilfs_mount *ump,
803 1.4.2.2 yamt uint64_t ino, struct nilfs_inode *inode, struct nilfs_node **nodep)
804 1.4.2.2 yamt {
805 1.4.2.2 yamt struct nilfs_node *node;
806 1.4.2.2 yamt struct vnode *nvp;
807 1.4.2.2 yamt struct mount *mp;
808 1.4.2.2 yamt int (**vnodeops)(void *);
809 1.4.2.2 yamt int error;
810 1.4.2.2 yamt
811 1.4.2.2 yamt *nodep = NULL;
812 1.4.2.2 yamt vnodeops = nilfs_vnodeop_p;
813 1.4.2.2 yamt
814 1.4.2.2 yamt /* associate with mountpoint if present*/
815 1.4.2.2 yamt mp = ump? ump->vfs_mountp : NULL;
816 1.4.2.2 yamt error = getnewvnode(VT_NILFS, mp, vnodeops, &nvp);
817 1.4.2.2 yamt if (error)
818 1.4.2.2 yamt return error;
819 1.4.2.2 yamt
820 1.4.2.2 yamt /* lock node */
821 1.4.2.2 yamt error = vn_lock(nvp, LK_EXCLUSIVE | LK_RETRY);
822 1.4.2.2 yamt if (error) {
823 1.4.2.2 yamt nvp->v_data = NULL;
824 1.4.2.2 yamt ungetnewvnode(nvp);
825 1.4.2.2 yamt return error;
826 1.4.2.2 yamt }
827 1.4.2.2 yamt
828 1.4.2.2 yamt node = pool_get(&nilfs_node_pool, PR_WAITOK);
829 1.4.2.2 yamt memset(node, 0, sizeof(struct nilfs_node));
830 1.4.2.2 yamt
831 1.4.2.2 yamt /* crosslink */
832 1.4.2.2 yamt node->vnode = nvp;
833 1.4.2.2 yamt node->ump = ump;
834 1.4.2.2 yamt node->nilfsdev = nilfsdev;
835 1.4.2.2 yamt nvp->v_data = node;
836 1.4.2.2 yamt
837 1.4.2.2 yamt /* initiase nilfs node */
838 1.4.2.2 yamt node->ino = ino;
839 1.4.2.2 yamt node->inode = *inode;
840 1.4.2.2 yamt node->lockf = NULL;
841 1.4.2.2 yamt
842 1.4.2.2 yamt /* needed? */
843 1.4.2.2 yamt mutex_init(&node->node_mutex, MUTEX_DEFAULT, IPL_NONE);
844 1.4.2.2 yamt cv_init(&node->node_lock, "nilfs_nlk");
845 1.4.2.2 yamt
846 1.4.2.2 yamt /* initialise genfs */
847 1.4.2.2 yamt genfs_node_init(nvp, &nilfs_genfsops);
848 1.4.2.2 yamt
849 1.4.2.2 yamt /* check if we're fetching the root */
850 1.4.2.2 yamt if (ino == NILFS_ROOT_INO)
851 1.4.2.2 yamt nvp->v_vflag |= VV_ROOT;
852 1.4.2.2 yamt
853 1.4.2.2 yamt /* update vnode's file type XXX is there a function for this? */
854 1.4.2.2 yamt nvp->v_type = VREG;
855 1.4.2.2 yamt if (S_ISDIR(inode->i_mode))
856 1.4.2.2 yamt nvp->v_type = VDIR;
857 1.4.2.2 yamt if (S_ISLNK(inode->i_mode))
858 1.4.2.2 yamt nvp->v_type = VLNK;
859 1.4.2.2 yamt #if 0
860 1.4.2.2 yamt if (S_ISCHR(inode->i_mode))
861 1.4.2.2 yamt nvp->v_type = VCHR;
862 1.4.2.2 yamt if (S_ISBLK(inode->i_mode))
863 1.4.2.2 yamt nvp->v_type = VBLK;
864 1.4.2.2 yamt #endif
865 1.4.2.2 yamt /* XXX what else? */
866 1.4.2.2 yamt
867 1.4.2.2 yamt /* fixup inode size for system nodes */
868 1.4.2.2 yamt if ((ino < NILFS_USER_INO) && (ino != NILFS_ROOT_INO)) {
869 1.4.2.2 yamt DPRINTF(VOLUMES, ("NEED TO GET my size for inode %"PRIu64"\n",
870 1.4.2.2 yamt ino));
871 1.4.2.2 yamt /* for now set it to maximum, -1 is illegal */
872 1.4.2.2 yamt inode->i_size = nilfs_rw64(((uint64_t) -2));
873 1.4.2.2 yamt }
874 1.4.2.2 yamt
875 1.4.2.2 yamt uvm_vnp_setsize(nvp, nilfs_rw64(inode->i_size));
876 1.4.2.2 yamt
877 1.4.2.2 yamt if (ump)
878 1.4.2.2 yamt nilfs_register_node(node);
879 1.4.2.2 yamt
880 1.4.2.2 yamt /* return node */
881 1.4.2.2 yamt *nodep = node;
882 1.4.2.2 yamt return 0;
883 1.4.2.2 yamt }
884 1.4.2.2 yamt
885 1.4.2.2 yamt
886 1.4.2.2 yamt int
887 1.4.2.2 yamt nilfs_get_node(struct nilfs_mount *ump, uint64_t ino, struct nilfs_node **nodep)
888 1.4.2.2 yamt {
889 1.4.2.2 yamt struct nilfs_device *nilfsdev;
890 1.4.2.2 yamt struct nilfs_inode inode, *entry;
891 1.4.2.2 yamt struct buf *bp;
892 1.4.2.2 yamt uint64_t ivblocknr;
893 1.4.2.2 yamt uint32_t entry_in_block;
894 1.4.2.2 yamt int error;
895 1.4.2.2 yamt
896 1.4.2.2 yamt /* lookup node in hash table */
897 1.4.2.2 yamt *nodep = nilfs_hash_lookup(ump, ino);
898 1.4.2.2 yamt if (*nodep)
899 1.4.2.2 yamt return 0;
900 1.4.2.2 yamt
901 1.4.2.2 yamt /* lock to disallow simultanious creation of same udf_node */
902 1.4.2.2 yamt mutex_enter(&ump->get_node_lock);
903 1.4.2.2 yamt
904 1.4.2.2 yamt /* relookup since it could be created while waiting for the mutex */
905 1.4.2.2 yamt *nodep = nilfs_hash_lookup(ump, ino);
906 1.4.2.2 yamt if (*nodep) {
907 1.4.2.2 yamt mutex_exit(&ump->get_node_lock);
908 1.4.2.2 yamt return 0;
909 1.4.2.2 yamt }
910 1.4.2.2 yamt
911 1.4.2.2 yamt /* create new inode; XXX check could be handier */
912 1.4.2.2 yamt if ((ino < NILFS_ATIME_INO) && (ino != NILFS_ROOT_INO)) {
913 1.4.2.2 yamt printf("nilfs_get_node: system ino %"PRIu64" not in mount "
914 1.4.2.2 yamt "point!\n", ino);
915 1.4.2.2 yamt mutex_exit(&ump->get_node_lock);
916 1.4.2.2 yamt return ENOENT;
917 1.4.2.2 yamt }
918 1.4.2.2 yamt
919 1.4.2.2 yamt /* lookup inode in the ifile */
920 1.4.2.2 yamt DPRINTF(NODE, ("lookup ino %"PRIu64"\n", ino));
921 1.4.2.2 yamt
922 1.4.2.2 yamt /* lookup inode structure in mountpoints ifile */
923 1.4.2.2 yamt nilfsdev = ump->nilfsdev;
924 1.4.2.2 yamt nilfs_mdt_trans(&nilfsdev->ifile_mdt, ino, &ivblocknr, &entry_in_block);
925 1.4.2.2 yamt
926 1.4.2.2 yamt error = nilfs_bread(ump->ifile_node, ivblocknr, NOCRED, 0, &bp);
927 1.4.2.2 yamt if (error) {
928 1.4.2.2 yamt mutex_exit(&ump->get_node_lock);
929 1.4.2.2 yamt return ENOENT;
930 1.4.2.2 yamt }
931 1.4.2.2 yamt
932 1.4.2.2 yamt /* get inode entry */
933 1.4.2.2 yamt entry = (struct nilfs_inode *) bp->b_data + entry_in_block;
934 1.4.2.2 yamt inode = *entry;
935 1.4.2.2 yamt brelse(bp, BC_AGE);
936 1.4.2.2 yamt
937 1.4.2.2 yamt /* get node */
938 1.4.2.2 yamt error = nilfs_get_node_raw(ump->nilfsdev, ump, ino, &inode, nodep);
939 1.4.2.2 yamt mutex_exit(&ump->get_node_lock);
940 1.4.2.2 yamt
941 1.4.2.2 yamt return error;
942 1.4.2.2 yamt }
943 1.4.2.2 yamt
944 1.4.2.2 yamt
945 1.4.2.2 yamt void
946 1.4.2.2 yamt nilfs_dispose_node(struct nilfs_node **nodep)
947 1.4.2.2 yamt {
948 1.4.2.2 yamt struct vnode *vp;
949 1.4.2.2 yamt struct nilfs_node *node;
950 1.4.2.2 yamt
951 1.4.2.2 yamt /* protect against rogue values */
952 1.4.2.2 yamt if (!*nodep)
953 1.4.2.2 yamt return;
954 1.4.2.2 yamt
955 1.4.2.2 yamt node = *nodep;
956 1.4.2.2 yamt vp = node->vnode;
957 1.4.2.2 yamt
958 1.4.2.2 yamt /* remove dirhash if present */
959 1.4.2.2 yamt dirhash_purge(&node->dir_hash);
960 1.4.2.2 yamt
961 1.4.2.2 yamt /* remove from our hash lookup table */
962 1.4.2.2 yamt if (node->ump)
963 1.4.2.2 yamt nilfs_deregister_node(node);
964 1.4.2.2 yamt
965 1.4.2.2 yamt /* destroy our locks */
966 1.4.2.2 yamt mutex_destroy(&node->node_mutex);
967 1.4.2.2 yamt cv_destroy(&node->node_lock);
968 1.4.2.2 yamt
969 1.4.2.2 yamt /* dissociate from our vnode */
970 1.4.2.2 yamt genfs_node_destroy(node->vnode);
971 1.4.2.2 yamt vp->v_data = NULL;
972 1.4.2.2 yamt
973 1.4.2.2 yamt /* free our associated memory */
974 1.4.2.2 yamt pool_put(&nilfs_node_pool, node);
975 1.4.2.2 yamt
976 1.4.2.2 yamt *nodep = NULL;
977 1.4.2.2 yamt }
978 1.4.2.2 yamt
979 1.4.2.2 yamt
980 1.4.2.2 yamt void
981 1.4.2.2 yamt nilfs_itimes(struct nilfs_node *node, struct timespec *acc,
982 1.4.2.2 yamt struct timespec *mod, struct timespec *birth)
983 1.4.2.2 yamt {
984 1.4.2.2 yamt }
985 1.4.2.2 yamt
986 1.4.2.2 yamt
987 1.4.2.2 yamt int
988 1.4.2.2 yamt nilfs_update(struct vnode *node, struct timespec *acc,
989 1.4.2.2 yamt struct timespec *mod, struct timespec *birth, int updflags)
990 1.4.2.2 yamt {
991 1.4.2.2 yamt return EROFS;
992 1.4.2.2 yamt }
993 1.4.2.2 yamt
994 1.4.2.2 yamt
995 1.4.2.2 yamt int
996 1.4.2.2 yamt nilfs_chsize(struct vnode *vp, u_quad_t newsize, kauth_cred_t cred)
997 1.4.2.2 yamt {
998 1.4.2.2 yamt return EROFS;
999 1.4.2.2 yamt }
1000 1.4.2.2 yamt
1001 1.4.2.2 yamt
1002 1.4.2.2 yamt
1003 1.4.2.2 yamt int
1004 1.4.2.2 yamt nilfs_grow_node(struct nilfs_node *node, uint64_t new_size)
1005 1.4.2.2 yamt {
1006 1.4.2.2 yamt return EROFS;
1007 1.4.2.2 yamt }
1008 1.4.2.2 yamt
1009 1.4.2.2 yamt
1010 1.4.2.2 yamt int
1011 1.4.2.2 yamt nilfs_shrink_node(struct nilfs_node *node, uint64_t new_size)
1012 1.4.2.2 yamt {
1013 1.4.2.2 yamt return EROFS;
1014 1.4.2.2 yamt }
1015 1.4.2.2 yamt
1016 1.4.2.2 yamt
1017 1.4.2.2 yamt static int
1018 1.4.2.2 yamt dirhash_fill(struct nilfs_node *dir_node)
1019 1.4.2.2 yamt {
1020 1.4.2.2 yamt struct vnode *dvp = dir_node->vnode;
1021 1.4.2.2 yamt struct dirhash *dirh;
1022 1.4.2.2 yamt struct nilfs_dir_entry *ndirent;
1023 1.4.2.2 yamt struct dirent dirent;
1024 1.4.2.2 yamt struct buf *bp;
1025 1.4.2.2 yamt uint64_t file_size, diroffset, blkoff;
1026 1.4.2.2 yamt uint64_t blocknr;
1027 1.4.2.2 yamt uint32_t blocksize = dir_node->nilfsdev->blocksize;
1028 1.4.2.2 yamt uint8_t *pos, name_len;
1029 1.4.2.2 yamt int error;
1030 1.4.2.2 yamt
1031 1.4.2.2 yamt DPRINTF(CALL, ("dirhash_fill called\n"));
1032 1.4.2.2 yamt
1033 1.4.2.2 yamt if (dvp->v_type != VDIR)
1034 1.4.2.2 yamt return ENOTDIR;
1035 1.4.2.2 yamt
1036 1.4.2.2 yamt /* make sure we have a dirhash to work on */
1037 1.4.2.2 yamt dirh = dir_node->dir_hash;
1038 1.4.2.2 yamt KASSERT(dirh);
1039 1.4.2.2 yamt KASSERT(dirh->refcnt > 0);
1040 1.4.2.2 yamt
1041 1.4.2.2 yamt if (dirh->flags & DIRH_BROKEN)
1042 1.4.2.2 yamt return EIO;
1043 1.4.2.2 yamt
1044 1.4.2.2 yamt if (dirh->flags & DIRH_COMPLETE)
1045 1.4.2.2 yamt return 0;
1046 1.4.2.2 yamt
1047 1.4.2.2 yamt DPRINTF(DIRHASH, ("Filling directory hash\n"));
1048 1.4.2.2 yamt
1049 1.4.2.2 yamt /* make sure we have a clean dirhash to add to */
1050 1.4.2.2 yamt dirhash_purge_entries(dirh);
1051 1.4.2.2 yamt
1052 1.4.2.2 yamt /* get directory filesize */
1053 1.4.2.2 yamt file_size = nilfs_rw64(dir_node->inode.i_size);
1054 1.4.2.2 yamt
1055 1.4.2.2 yamt /* walk the directory */
1056 1.4.2.2 yamt error = 0;
1057 1.4.2.2 yamt diroffset = 0;
1058 1.4.2.2 yamt
1059 1.4.2.2 yamt blocknr = diroffset / blocksize;
1060 1.4.2.2 yamt blkoff = diroffset % blocksize;
1061 1.4.2.2 yamt error = nilfs_bread(dir_node, blocknr, NOCRED, 0, &bp);
1062 1.4.2.2 yamt if (error) {
1063 1.4.2.2 yamt dirh->flags |= DIRH_BROKEN;
1064 1.4.2.2 yamt dirhash_purge_entries(dirh);
1065 1.4.2.2 yamt return EIO;
1066 1.4.2.2 yamt }
1067 1.4.2.2 yamt while (diroffset < file_size) {
1068 1.4.2.2 yamt DPRINTF(READDIR, ("filldir : offset = %"PRIu64"\n",
1069 1.4.2.2 yamt diroffset));
1070 1.4.2.2 yamt if (blkoff >= blocksize) {
1071 1.4.2.2 yamt blkoff = 0; blocknr++;
1072 1.4.2.2 yamt brelse(bp, BC_AGE);
1073 1.4.2.2 yamt error = nilfs_bread(dir_node, blocknr, NOCRED, 0,
1074 1.4.2.2 yamt &bp);
1075 1.4.2.2 yamt if (error) {
1076 1.4.2.2 yamt dirh->flags |= DIRH_BROKEN;
1077 1.4.2.2 yamt dirhash_purge_entries(dirh);
1078 1.4.2.2 yamt return EIO;
1079 1.4.2.2 yamt }
1080 1.4.2.2 yamt }
1081 1.4.2.2 yamt
1082 1.4.2.2 yamt /* read in one dirent */
1083 1.4.2.2 yamt pos = (uint8_t *) bp->b_data + blkoff;
1084 1.4.2.2 yamt ndirent = (struct nilfs_dir_entry *) pos;
1085 1.4.2.2 yamt name_len = ndirent->name_len;
1086 1.4.2.2 yamt
1087 1.4.2.2 yamt memset(&dirent, 0, sizeof(struct dirent));
1088 1.4.2.2 yamt dirent.d_fileno = nilfs_rw64(ndirent->inode);
1089 1.4.2.2 yamt dirent.d_type = ndirent->file_type; /* 1:1 ? */
1090 1.4.2.2 yamt dirent.d_namlen = name_len;
1091 1.4.2.2 yamt strncpy(dirent.d_name, ndirent->name, name_len);
1092 1.4.2.2 yamt dirent.d_reclen = _DIRENT_SIZE(&dirent);
1093 1.4.2.2 yamt DPRINTF(DIRHASH, ("copying `%*.*s`\n", name_len,
1094 1.4.2.2 yamt name_len, dirent.d_name));
1095 1.4.2.2 yamt
1096 1.4.2.2 yamt /* XXX is it deleted? extra free space? */
1097 1.4.2.2 yamt dirhash_enter(dirh, &dirent, diroffset,
1098 1.4.2.2 yamt nilfs_rw16(ndirent->rec_len), 0);
1099 1.4.2.2 yamt
1100 1.4.2.2 yamt /* advance */
1101 1.4.2.2 yamt diroffset += nilfs_rw16(ndirent->rec_len);
1102 1.4.2.2 yamt blkoff += nilfs_rw16(ndirent->rec_len);
1103 1.4.2.2 yamt }
1104 1.4.2.2 yamt brelse(bp, BC_AGE);
1105 1.4.2.2 yamt
1106 1.4.2.2 yamt dirh->flags |= DIRH_COMPLETE;
1107 1.4.2.2 yamt
1108 1.4.2.2 yamt return 0;
1109 1.4.2.2 yamt }
1110 1.4.2.2 yamt
1111 1.4.2.2 yamt
1112 1.4.2.2 yamt int
1113 1.4.2.2 yamt nilfs_lookup_name_in_dir(struct vnode *dvp, const char *name, int namelen,
1114 1.4.2.2 yamt uint64_t *ino, int *found)
1115 1.4.2.2 yamt {
1116 1.4.2.2 yamt struct nilfs_node *dir_node = VTOI(dvp);
1117 1.4.2.2 yamt struct nilfs_dir_entry *ndirent;
1118 1.4.2.2 yamt struct dirhash *dirh;
1119 1.4.2.2 yamt struct dirhash_entry *dirh_ep;
1120 1.4.2.2 yamt struct buf *bp;
1121 1.4.2.2 yamt uint64_t diroffset, blkoff;
1122 1.4.2.2 yamt uint64_t blocknr;
1123 1.4.2.2 yamt uint32_t blocksize = dir_node->nilfsdev->blocksize;
1124 1.4.2.2 yamt uint8_t *pos;
1125 1.4.2.2 yamt int hit, error;
1126 1.4.2.2 yamt
1127 1.4.2.2 yamt /* set default return */
1128 1.4.2.2 yamt *found = 0;
1129 1.4.2.2 yamt
1130 1.4.2.2 yamt /* get our dirhash and make sure its read in */
1131 1.4.2.2 yamt dirhash_get(&dir_node->dir_hash);
1132 1.4.2.2 yamt error = dirhash_fill(dir_node);
1133 1.4.2.2 yamt if (error) {
1134 1.4.2.2 yamt dirhash_put(dir_node->dir_hash);
1135 1.4.2.2 yamt return error;
1136 1.4.2.2 yamt }
1137 1.4.2.2 yamt dirh = dir_node->dir_hash;
1138 1.4.2.2 yamt
1139 1.4.2.2 yamt /* allocate temporary space for fid */
1140 1.4.2.2 yamt
1141 1.4.2.2 yamt DPRINTF(DIRHASH, ("dirhash_lookup looking for `%*.*s`\n",
1142 1.4.2.2 yamt namelen, namelen, name));
1143 1.4.2.2 yamt
1144 1.4.2.2 yamt /* search our dirhash hits */
1145 1.4.2.2 yamt *ino = 0;
1146 1.4.2.2 yamt dirh_ep = NULL;
1147 1.4.2.2 yamt for (;;) {
1148 1.4.2.2 yamt hit = dirhash_lookup(dirh, name, namelen, &dirh_ep);
1149 1.4.2.2 yamt /* if no hit, abort the search */
1150 1.4.2.2 yamt if (!hit)
1151 1.4.2.2 yamt break;
1152 1.4.2.2 yamt
1153 1.4.2.2 yamt /* check this hit */
1154 1.4.2.2 yamt diroffset = dirh_ep->offset;
1155 1.4.2.2 yamt
1156 1.4.2.2 yamt blocknr = diroffset / blocksize;
1157 1.4.2.2 yamt blkoff = diroffset % blocksize;
1158 1.4.2.2 yamt error = nilfs_bread(dir_node, blocknr, NOCRED, 0, &bp);
1159 1.4.2.2 yamt if (error)
1160 1.4.2.2 yamt return EIO;
1161 1.4.2.2 yamt
1162 1.4.2.2 yamt /* read in one dirent */
1163 1.4.2.2 yamt pos = (uint8_t *) bp->b_data + blkoff;
1164 1.4.2.2 yamt ndirent = (struct nilfs_dir_entry *) pos;
1165 1.4.2.2 yamt
1166 1.4.2.2 yamt DPRINTF(DIRHASH, ("dirhash_lookup\tchecking `%*.*s`\n",
1167 1.4.2.2 yamt ndirent->name_len, ndirent->name_len, ndirent->name));
1168 1.4.2.2 yamt
1169 1.4.2.2 yamt /* see if its our entry */
1170 1.4.2.2 yamt KASSERT(ndirent->name_len == namelen);
1171 1.4.2.2 yamt if (strncmp(ndirent->name, name, namelen) == 0) {
1172 1.4.2.2 yamt *found = 1;
1173 1.4.2.2 yamt *ino = nilfs_rw64(ndirent->inode);
1174 1.4.2.2 yamt brelse(bp, BC_AGE);
1175 1.4.2.2 yamt break;
1176 1.4.2.2 yamt }
1177 1.4.2.2 yamt brelse(bp, BC_AGE);
1178 1.4.2.2 yamt }
1179 1.4.2.2 yamt
1180 1.4.2.2 yamt dirhash_put(dir_node->dir_hash);
1181 1.4.2.2 yamt
1182 1.4.2.2 yamt return error;
1183 1.4.2.2 yamt }
1184 1.4.2.2 yamt
1185 1.4.2.2 yamt
1186 1.4.2.2 yamt int
1187 1.4.2.2 yamt nilfs_dir_detach(struct nilfs_mount *ump, struct nilfs_node *dir_node, struct nilfs_node *node, struct componentname *cnp)
1188 1.4.2.2 yamt {
1189 1.4.2.2 yamt return EROFS;
1190 1.4.2.2 yamt }
1191 1.4.2.2 yamt
1192 1.4.2.2 yamt
1193 1.4.2.2 yamt int
1194 1.4.2.2 yamt nilfs_dir_attach(struct nilfs_mount *ump, struct nilfs_node *dir_node, struct nilfs_node *node, struct vattr *vap, struct componentname *cnp)
1195 1.4.2.2 yamt {
1196 1.4.2.2 yamt return EROFS;
1197 1.4.2.2 yamt }
1198 1.4.2.2 yamt
1199 1.4.2.2 yamt
1200 1.4.2.2 yamt /* XXX return vnode? */
1201 1.4.2.2 yamt int
1202 1.4.2.2 yamt nilfs_create_node(struct vnode *dvp, struct vnode **vpp, struct vattr *vap, struct componentname *cnp)
1203 1.4.2.2 yamt {
1204 1.4.2.2 yamt return EROFS;
1205 1.4.2.2 yamt }
1206 1.4.2.2 yamt
1207 1.4.2.2 yamt
1208 1.4.2.2 yamt void
1209 1.4.2.2 yamt nilfs_delete_node(struct nilfs_node *node)
1210 1.4.2.2 yamt {
1211 1.4.2.2 yamt }
1212 1.4.2.2 yamt
1213 1.4.2.2 yamt
1214