lfs_alloc.c revision 1.143 1 1.143 perseant /* $NetBSD: lfs_alloc.c,v 1.143 2025/09/15 18:49:16 perseant Exp $ */
2 1.2 cgd
3 1.17 perseant /*-
4 1.100 ad * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2007 The NetBSD Foundation, Inc.
5 1.17 perseant * All rights reserved.
6 1.17 perseant *
7 1.17 perseant * This code is derived from software contributed to The NetBSD Foundation
8 1.17 perseant * by Konrad E. Schroder <perseant (at) hhhh.org>.
9 1.17 perseant *
10 1.17 perseant * Redistribution and use in source and binary forms, with or without
11 1.17 perseant * modification, are permitted provided that the following conditions
12 1.17 perseant * are met:
13 1.17 perseant * 1. Redistributions of source code must retain the above copyright
14 1.17 perseant * notice, this list of conditions and the following disclaimer.
15 1.17 perseant * 2. Redistributions in binary form must reproduce the above copyright
16 1.17 perseant * notice, this list of conditions and the following disclaimer in the
17 1.17 perseant * documentation and/or other materials provided with the distribution.
18 1.17 perseant *
19 1.17 perseant * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.17 perseant * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.17 perseant * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.17 perseant * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.17 perseant * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.17 perseant * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.17 perseant * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.17 perseant * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.17 perseant * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.17 perseant * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.17 perseant * POSSIBILITY OF SUCH DAMAGE.
30 1.17 perseant */
31 1.1 mycroft /*
32 1.1 mycroft * Copyright (c) 1991, 1993
33 1.1 mycroft * The Regents of the University of California. All rights reserved.
34 1.1 mycroft *
35 1.1 mycroft * Redistribution and use in source and binary forms, with or without
36 1.1 mycroft * modification, are permitted provided that the following conditions
37 1.1 mycroft * are met:
38 1.1 mycroft * 1. Redistributions of source code must retain the above copyright
39 1.1 mycroft * notice, this list of conditions and the following disclaimer.
40 1.1 mycroft * 2. Redistributions in binary form must reproduce the above copyright
41 1.1 mycroft * notice, this list of conditions and the following disclaimer in the
42 1.1 mycroft * documentation and/or other materials provided with the distribution.
43 1.71 agc * 3. Neither the name of the University nor the names of its contributors
44 1.1 mycroft * may be used to endorse or promote products derived from this software
45 1.1 mycroft * without specific prior written permission.
46 1.1 mycroft *
47 1.1 mycroft * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48 1.1 mycroft * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 1.1 mycroft * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 1.1 mycroft * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51 1.1 mycroft * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 1.1 mycroft * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 1.1 mycroft * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 1.1 mycroft * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 1.1 mycroft * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 1.1 mycroft * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 1.1 mycroft * SUCH DAMAGE.
58 1.1 mycroft *
59 1.2 cgd * @(#)lfs_alloc.c 8.4 (Berkeley) 1/4/94
60 1.1 mycroft */
61 1.52 lukem
62 1.52 lukem #include <sys/cdefs.h>
63 1.143 perseant __KERNEL_RCSID(0, "$NetBSD: lfs_alloc.c,v 1.143 2025/09/15 18:49:16 perseant Exp $");
64 1.12 scottr
65 1.47 mrg #if defined(_KERNEL_OPT)
66 1.12 scottr #include "opt_quota.h"
67 1.13 scottr #endif
68 1.1 mycroft
69 1.1 mycroft #include <sys/param.h>
70 1.3 christos #include <sys/systm.h>
71 1.1 mycroft #include <sys/kernel.h>
72 1.1 mycroft #include <sys/buf.h>
73 1.56 perseant #include <sys/lock.h>
74 1.1 mycroft #include <sys/vnode.h>
75 1.1 mycroft #include <sys/syslog.h>
76 1.1 mycroft #include <sys/mount.h>
77 1.87 perseant #include <sys/malloc.h>
78 1.15 thorpej #include <sys/pool.h>
79 1.50 chs #include <sys/proc.h>
80 1.94 elad #include <sys/kauth.h>
81 1.1 mycroft
82 1.114 dholland #include <ufs/lfs/ulfs_quotacommon.h>
83 1.114 dholland #include <ufs/lfs/ulfs_inode.h>
84 1.114 dholland #include <ufs/lfs/ulfsmount.h>
85 1.114 dholland #include <ufs/lfs/ulfs_extern.h>
86 1.1 mycroft
87 1.1 mycroft #include <ufs/lfs/lfs.h>
88 1.124 dholland #include <ufs/lfs/lfs_accessors.h>
89 1.1 mycroft #include <ufs/lfs/lfs_extern.h>
90 1.118 dholland #include <ufs/lfs/lfs_kernel.h>
91 1.1 mycroft
92 1.87 perseant /* Constants for inode free bitmap */
93 1.88 perseant #define BMSHIFT 5 /* 2 ** 5 = 32 */
94 1.88 perseant #define BMMASK ((1 << BMSHIFT) - 1)
95 1.88 perseant #define SET_BITMAP_FREE(F, I) do { \
96 1.88 perseant DLOG((DLOG_ALLOC, "lfs: ino %d wrd %d bit %d set\n", (int)(I), \
97 1.88 perseant (int)((I) >> BMSHIFT), (int)((I) & BMMASK))); \
98 1.139 kamil (F)->lfs_ino_bitmap[(I) >> BMSHIFT] |= (1U << ((I) & BMMASK)); \
99 1.88 perseant } while (0)
100 1.88 perseant #define CLR_BITMAP_FREE(F, I) do { \
101 1.88 perseant DLOG((DLOG_ALLOC, "lfs: ino %d wrd %d bit %d clr\n", (int)(I), \
102 1.88 perseant (int)((I) >> BMSHIFT), (int)((I) & BMMASK))); \
103 1.139 kamil (F)->lfs_ino_bitmap[(I) >> BMSHIFT] &= ~(1U << ((I) & BMMASK)); \
104 1.88 perseant } while(0)
105 1.88 perseant
106 1.87 perseant #define ISSET_BITMAP_FREE(F, I) \
107 1.139 kamil ((F)->lfs_ino_bitmap[(I) >> BMSHIFT] & (1U << ((I) & BMMASK)))
108 1.87 perseant
109 1.44 perseant /*
110 1.65 perseant * Add a new block to the Ifile, to accommodate future file creations.
111 1.65 perseant * Called with the segment lock held.
112 1.56 perseant */
113 1.96 perseant int
114 1.96 perseant lfs_extend_ifile(struct lfs *fs, kauth_cred_t cred)
115 1.44 perseant {
116 1.44 perseant struct vnode *vp;
117 1.44 perseant struct inode *ip;
118 1.126 dholland IFILE64 *ifp64;
119 1.126 dholland IFILE32 *ifp32;
120 1.48 perseant IFILE_V1 *ifp_v1;
121 1.48 perseant struct buf *bp, *cbp;
122 1.44 perseant int error;
123 1.83 christos daddr_t i, blkno, xmax;
124 1.142 perseant ino_t oldhead, maxino, tail;
125 1.48 perseant CLEANERINFO *cip;
126 1.44 perseant
127 1.78 perseant ASSERT_SEGLOCK(fs);
128 1.78 perseant
129 1.132 dholland /* XXX should check or assert that we aren't readonly. */
130 1.132 dholland
131 1.132 dholland /*
132 1.132 dholland * Get a block and extend the ifile inode. Leave the buffer for
133 1.132 dholland * the block in bp.
134 1.132 dholland */
135 1.132 dholland
136 1.44 perseant vp = fs->lfs_ivnode;
137 1.44 perseant ip = VTOI(vp);
138 1.117 christos blkno = lfs_lblkno(fs, ip->i_size);
139 1.122 dholland if ((error = lfs_balloc(vp, ip->i_size, lfs_sb_getbsize(fs), cred, 0,
140 1.44 perseant &bp)) != 0) {
141 1.44 perseant return (error);
142 1.44 perseant }
143 1.122 dholland ip->i_size += lfs_sb_getbsize(fs);
144 1.129 dholland lfs_dino_setsize(fs, ip->i_din, ip->i_size);
145 1.66 fvdl uvm_vnp_setsize(vp, ip->i_size);
146 1.75 perry
147 1.132 dholland /*
148 1.132 dholland * Compute the new number of inodes, and reallocate the in-memory
149 1.132 dholland * inode freemap.
150 1.132 dholland */
151 1.132 dholland
152 1.123 dholland maxino = ((ip->i_size >> lfs_sb_getbshift(fs)) - lfs_sb_getcleansz(fs) -
153 1.122 dholland lfs_sb_getsegtabsz(fs)) * lfs_sb_getifpb(fs);
154 1.88 perseant fs->lfs_ino_bitmap = (lfs_bm_t *)
155 1.88 perseant realloc(fs->lfs_ino_bitmap, ((maxino + BMMASK) >> BMSHIFT) *
156 1.88 perseant sizeof(lfs_bm_t), M_SEGMENT, M_WAITOK);
157 1.88 perseant KASSERT(fs->lfs_ino_bitmap != NULL);
158 1.87 perseant
159 1.132 dholland /* first new inode number */
160 1.122 dholland i = (blkno - lfs_sb_getsegtabsz(fs) - lfs_sb_getcleansz(fs)) *
161 1.122 dholland lfs_sb_getifpb(fs);
162 1.87 perseant
163 1.142 perseant /* inode number to stop at (XXX: why *x*max?) */
164 1.142 perseant xmax = i + lfs_sb_getifpb(fs);
165 1.142 perseant
166 1.87 perseant /*
167 1.87 perseant * We insert the new inodes at the head of the free list.
168 1.87 perseant * Under normal circumstances, the free list is empty here,
169 1.87 perseant * so we are also incidentally placing them at the end (which
170 1.87 perseant * we must do if we are to keep them in order).
171 1.87 perseant */
172 1.142 perseant LFS_GET_HEADFREE(fs, cip, cbp, &oldhead);
173 1.48 perseant LFS_PUT_HEADFREE(fs, cip, cbp, i);
174 1.142 perseant LFS_GET_TAILFREE(fs, cip, cbp, &tail);
175 1.142 perseant if (tail == LFS_UNUSED_INUM) {
176 1.142 perseant tail = xmax - 1;
177 1.142 perseant LFS_PUT_TAILFREE(fs, cip, cbp, tail);
178 1.142 perseant }
179 1.134 riastrad KASSERTMSG((lfs_sb_getfreehd(fs) != LFS_UNUSED_INUM),
180 1.134 riastrad "inode 0 allocated [2]");
181 1.132 dholland
182 1.142 perseant
183 1.132 dholland /*
184 1.132 dholland * Initialize the ifile block.
185 1.132 dholland *
186 1.132 dholland * XXX: these loops should be restructured to use the accessor
187 1.132 dholland * functions instead of using cutpaste polymorphism.
188 1.132 dholland */
189 1.132 dholland
190 1.126 dholland if (fs->lfs_is64) {
191 1.126 dholland for (ifp64 = (IFILE64 *)bp->b_data; i < xmax; ++ifp64) {
192 1.126 dholland SET_BITMAP_FREE(fs, i);
193 1.126 dholland ifp64->if_version = 1;
194 1.126 dholland ifp64->if_daddr = LFS_UNUSED_DADDR;
195 1.126 dholland ifp64->if_nextfree = ++i;
196 1.126 dholland }
197 1.126 dholland ifp64--;
198 1.142 perseant ifp64->if_nextfree = oldhead;
199 1.126 dholland } else if (lfs_sb_getversion(fs) > 1) {
200 1.126 dholland for (ifp32 = (IFILE32 *)bp->b_data; i < xmax; ++ifp32) {
201 1.126 dholland SET_BITMAP_FREE(fs, i);
202 1.126 dholland ifp32->if_version = 1;
203 1.126 dholland ifp32->if_daddr = LFS_UNUSED_DADDR;
204 1.126 dholland ifp32->if_nextfree = ++i;
205 1.126 dholland }
206 1.126 dholland ifp32--;
207 1.142 perseant ifp32->if_nextfree = oldhead;
208 1.126 dholland } else {
209 1.83 christos for (ifp_v1 = (IFILE_V1 *)bp->b_data; i < xmax; ++ifp_v1) {
210 1.89 perseant SET_BITMAP_FREE(fs, i);
211 1.48 perseant ifp_v1->if_version = 1;
212 1.48 perseant ifp_v1->if_daddr = LFS_UNUSED_DADDR;
213 1.48 perseant ifp_v1->if_nextfree = ++i;
214 1.48 perseant }
215 1.48 perseant ifp_v1--;
216 1.142 perseant ifp_v1->if_nextfree = oldhead;
217 1.44 perseant }
218 1.48 perseant
219 1.132 dholland /*
220 1.132 dholland * Write out the new block.
221 1.132 dholland */
222 1.132 dholland
223 1.56 perseant (void) LFS_BWRITE_LOG(bp); /* Ifile */
224 1.44 perseant
225 1.44 perseant return 0;
226 1.44 perseant }
227 1.44 perseant
228 1.132 dholland /*
229 1.132 dholland * Allocate an inode for a new file.
230 1.132 dholland *
231 1.132 dholland * Takes the segment lock. Also (while holding it) takes lfs_lock
232 1.132 dholland * to frob fs->lfs_fmod.
233 1.132 dholland *
234 1.132 dholland * XXX: the mode argument is unused; should just get rid of it.
235 1.132 dholland */
236 1.1 mycroft /* ARGSUSED */
237 1.43 perseant /* VOP_BWRITE 2i times */
238 1.1 mycroft int
239 1.99 christos lfs_valloc(struct vnode *pvp, int mode, kauth_cred_t cred,
240 1.120 hannken ino_t *ino, int *gen)
241 1.3 christos {
242 1.1 mycroft struct lfs *fs;
243 1.48 perseant struct buf *bp, *cbp;
244 1.126 dholland IFILE *ifp;
245 1.1 mycroft int error;
246 1.48 perseant CLEANERINFO *cip;
247 1.1 mycroft
248 1.85 yamt fs = VTOI(pvp)->i_lfs;
249 1.38 perseant if (fs->lfs_ronly)
250 1.38 perseant return EROFS;
251 1.75 perry
252 1.142 perseant if (!(fs->lfs_flags & LFS_NOTYET))
253 1.142 perseant ASSERT_NO_SEGLOCK(fs);
254 1.78 perseant
255 1.56 perseant lfs_seglock(fs, SEGM_PROT);
256 1.17 perseant
257 1.1 mycroft /* Get the head of the freelist. */
258 1.120 hannken LFS_GET_HEADFREE(fs, cip, cbp, ino);
259 1.132 dholland
260 1.132 dholland /* paranoia */
261 1.120 hannken KASSERT(*ino != LFS_UNUSED_INUM && *ino != LFS_IFILE_INUM);
262 1.120 hannken DLOG((DLOG_ALLOC, "lfs_valloc: allocate inode %" PRId64 "\n",
263 1.120 hannken *ino));
264 1.75 perry
265 1.132 dholland /* Update the in-memory inode freemap */
266 1.132 dholland CLR_BITMAP_FREE(fs, *ino);
267 1.132 dholland
268 1.1 mycroft /*
269 1.132 dholland * Fetch the ifile entry and make sure the inode is really
270 1.132 dholland * free.
271 1.1 mycroft */
272 1.120 hannken LFS_IENTRY(ifp, fs, *ino, bp);
273 1.126 dholland if (lfs_if_getdaddr(fs, ifp) != LFS_UNUSED_DADDR)
274 1.120 hannken panic("lfs_valloc: inuse inode %" PRId64 " on the free list",
275 1.120 hannken *ino);
276 1.132 dholland
277 1.132 dholland /* Update the inode freelist head in the superblock. */
278 1.126 dholland LFS_PUT_HEADFREE(fs, cip, cbp, lfs_if_getnextfree(fs, ifp));
279 1.126 dholland DLOG((DLOG_ALLOC, "lfs_valloc: headfree %" PRId64 " -> %ju\n",
280 1.126 dholland *ino, (uintmax_t)lfs_if_getnextfree(fs, ifp)));
281 1.48 perseant
282 1.132 dholland /*
283 1.132 dholland * Retrieve the version number from the ifile entry. It was
284 1.132 dholland * bumped by vfree, so don't bump it again.
285 1.132 dholland */
286 1.126 dholland *gen = lfs_if_getversion(fs, ifp);
287 1.132 dholland
288 1.132 dholland /* Done with ifile entry */
289 1.142 perseant lfs_if_setdaddr(fs, ifp, LFS_UNUSED_DADDR);
290 1.142 perseant lfs_if_setnextfree(fs, ifp, LFS_UNUSED_INUM);
291 1.142 perseant LFS_BWRITE_LOG(bp);
292 1.30 perseant
293 1.122 dholland if (lfs_sb_getfreehd(fs) == LFS_UNUSED_INUM) {
294 1.132 dholland /*
295 1.132 dholland * No more inodes; extend the ifile so that the next
296 1.132 dholland * lfs_valloc will succeed.
297 1.132 dholland */
298 1.96 perseant if ((error = lfs_extend_ifile(fs, cred)) != 0) {
299 1.132 dholland /* restore the freelist */
300 1.120 hannken LFS_PUT_HEADFREE(fs, cip, cbp, *ino);
301 1.132 dholland
302 1.132 dholland /* unlock and return */
303 1.56 perseant lfs_segunlock(fs);
304 1.44 perseant return error;
305 1.1 mycroft }
306 1.1 mycroft }
307 1.134 riastrad KASSERTMSG((lfs_sb_getfreehd(fs) != LFS_UNUSED_INUM),
308 1.134 riastrad "inode 0 allocated [3]");
309 1.48 perseant
310 1.132 dholland /* Set superblock modified bit */
311 1.105 ad mutex_enter(&lfs_lock);
312 1.78 perseant fs->lfs_fmod = 1;
313 1.105 ad mutex_exit(&lfs_lock);
314 1.132 dholland
315 1.132 dholland /* increment file count */
316 1.122 dholland lfs_sb_addnfiles(fs, 1);
317 1.78 perseant
318 1.132 dholland /* done */
319 1.56 perseant lfs_segunlock(fs);
320 1.120 hannken return 0;
321 1.44 perseant }
322 1.44 perseant
323 1.65 perseant /*
324 1.132 dholland * Allocate an inode for a new file, with given inode number and
325 1.132 dholland * version.
326 1.132 dholland *
327 1.132 dholland * Called in the same context as lfs_valloc and therefore shares the
328 1.132 dholland * same locking assumptions.
329 1.65 perseant */
330 1.96 perseant int
331 1.120 hannken lfs_valloc_fixed(struct lfs *fs, ino_t ino, int vers)
332 1.44 perseant {
333 1.120 hannken IFILE *ifp;
334 1.120 hannken struct buf *bp, *cbp;
335 1.142 perseant ino_t headino, thisino, oldnext, tailino;
336 1.120 hannken CLEANERINFO *cip;
337 1.142 perseant int extended = 0;
338 1.40 fvdl
339 1.135 maya if (fs->lfs_ronly)
340 1.135 maya return EROFS;
341 1.135 maya
342 1.142 perseant if (!(fs->lfs_flags & LFS_NOTYET))
343 1.142 perseant ASSERT_NO_SEGLOCK(fs);
344 1.142 perseant
345 1.135 maya
346 1.135 maya lfs_seglock(fs, SEGM_PROT);
347 1.132 dholland
348 1.132 dholland /*
349 1.132 dholland * If the ifile is too short to contain this inum, extend it.
350 1.132 dholland *
351 1.132 dholland * XXX: lfs_extend_ifile should take a size instead of always
352 1.132 dholland * doing just one block at time.
353 1.132 dholland */
354 1.120 hannken while (VTOI(fs->lfs_ivnode)->i_size <= (ino /
355 1.122 dholland lfs_sb_getifpb(fs) + lfs_sb_getcleansz(fs) + lfs_sb_getsegtabsz(fs))
356 1.123 dholland << lfs_sb_getbshift(fs)) {
357 1.142 perseant DLOG((DLOG_ALLOC, "extend ifile to accommodate ino %jd\n",
358 1.142 perseant (intmax_t)ino));
359 1.120 hannken lfs_extend_ifile(fs, NOCRED);
360 1.142 perseant extended = 1;
361 1.120 hannken }
362 1.78 perseant
363 1.132 dholland /*
364 1.142 perseant * Get the inode freelist next pointer.
365 1.132 dholland */
366 1.120 hannken LFS_IENTRY(ifp, fs, ino, bp);
367 1.126 dholland oldnext = lfs_if_getnextfree(fs, ifp);
368 1.120 hannken brelse(bp, 0);
369 1.51 chs
370 1.142 perseant /* Get fail of inode freelist */
371 1.142 perseant LFS_GET_TAILFREE(fs, cip, cbp, &tailino);
372 1.142 perseant
373 1.132 dholland /* Get head of inode freelist */
374 1.130 dholland LFS_GET_HEADFREE(fs, cip, cbp, &headino);
375 1.130 dholland if (headino == ino) {
376 1.132 dholland /* Easy case: the inode we wanted was at the head */
377 1.120 hannken LFS_PUT_HEADFREE(fs, cip, cbp, oldnext);
378 1.120 hannken } else {
379 1.143 perseant ino_t nextfree = 0, maxino, count; /* XXX: gcc */
380 1.126 dholland
381 1.132 dholland /* Have to find the desired inode in the freelist... */
382 1.142 perseant maxino = ((VTOI(fs->lfs_ivnode)->i_size >> lfs_sb_getbshift(fs))
383 1.142 perseant - lfs_sb_getcleansz(fs) - lfs_sb_getsegtabsz(fs))
384 1.142 perseant * lfs_sb_getifpb(fs);
385 1.142 perseant count = 0;
386 1.132 dholland
387 1.130 dholland thisino = headino;
388 1.142 perseant while (thisino != LFS_UNUSED_INUM) {
389 1.132 dholland /* read this ifile entry */
390 1.130 dholland LFS_IENTRY(ifp, fs, thisino, bp);
391 1.126 dholland nextfree = lfs_if_getnextfree(fs, ifp);
392 1.132 dholland /* stop if we find it or we hit the end */
393 1.126 dholland if (nextfree == ino ||
394 1.126 dholland nextfree == LFS_UNUSED_INUM)
395 1.120 hannken break;
396 1.132 dholland /* nope, keep going... */
397 1.130 dholland thisino = nextfree;
398 1.120 hannken brelse(bp, 0);
399 1.142 perseant if (++count > maxino)
400 1.142 perseant break;
401 1.142 perseant }
402 1.142 perseant if (count > maxino) {
403 1.142 perseant panic("loop in free list");
404 1.142 perseant lfs_segunlock(fs);
405 1.142 perseant return ENOENT;
406 1.120 hannken }
407 1.126 dholland if (nextfree == LFS_UNUSED_INUM) {
408 1.132 dholland /* hit the end -- this inode is not available */
409 1.120 hannken brelse(bp, 0);
410 1.135 maya lfs_segunlock(fs);
411 1.142 perseant if (extended)
412 1.142 perseant panic("extended ifile to accommodate but inode not found");
413 1.120 hannken return ENOENT;
414 1.120 hannken }
415 1.132 dholland /* found it; update the next pointer */
416 1.126 dholland lfs_if_setnextfree(fs, ifp, oldnext);
417 1.132 dholland /* write the ifile block */
418 1.120 hannken LFS_BWRITE_LOG(bp);
419 1.142 perseant
420 1.142 perseant /* If our inode was the tail, thisino is now the tail */
421 1.142 perseant if (tailino == ino)
422 1.142 perseant LFS_PUT_TAILFREE(fs, cip, cbp, thisino);
423 1.142 perseant }
424 1.142 perseant
425 1.142 perseant /* Clear nextfree, note daddr, and set generation number */
426 1.142 perseant LFS_IENTRY(ifp, fs, ino, bp);
427 1.142 perseant lfs_if_setversion(fs, ifp, vers);
428 1.142 perseant lfs_if_setnextfree(fs, ifp, LFS_UNUSED_INUM);
429 1.142 perseant LFS_BWRITE_LOG(bp);
430 1.142 perseant
431 1.142 perseant if (lfs_sb_getfreehd(fs) == LFS_UNUSED_INUM) {
432 1.142 perseant int error;
433 1.142 perseant /*
434 1.142 perseant * No more inodes; extend the ifile so that the next
435 1.142 perseant * lfs_valloc will succeed.
436 1.142 perseant */
437 1.142 perseant if ((error = lfs_extend_ifile(fs, NOCRED)) != 0) {
438 1.142 perseant /* restore the freelist */
439 1.142 perseant LFS_PUT_HEADFREE(fs, cip, cbp, ino);
440 1.142 perseant
441 1.142 perseant /* unlock and return */
442 1.142 perseant lfs_segunlock(fs);
443 1.142 perseant return error;
444 1.142 perseant }
445 1.66 fvdl }
446 1.142 perseant KASSERTMSG((lfs_sb_getfreehd(fs) != LFS_UNUSED_INUM),
447 1.142 perseant "inode 0 allocated [4]");
448 1.51 chs
449 1.132 dholland /* done */
450 1.135 maya lfs_segunlock(fs);
451 1.120 hannken return 0;
452 1.1 mycroft }
453 1.1 mycroft
454 1.87 perseant #if 0
455 1.87 perseant /*
456 1.87 perseant * Find the highest-numbered allocated inode.
457 1.87 perseant * This will be used to shrink the Ifile.
458 1.87 perseant */
459 1.87 perseant static inline ino_t
460 1.87 perseant lfs_last_alloc_ino(struct lfs *fs)
461 1.87 perseant {
462 1.87 perseant ino_t ino, maxino;
463 1.87 perseant
464 1.123 dholland maxino = ((fs->lfs_ivnode->v_size >> lfs_sb_getbshift(fs)) -
465 1.131 dholland lfs_sb_getcleansz(fs) - lfs_sb_getsegtabsz(fs)) *
466 1.131 dholland lfs_sb_getifpb(fs);
467 1.87 perseant for (ino = maxino - 1; ino > LFS_UNUSED_INUM; --ino) {
468 1.87 perseant if (ISSET_BITMAP_FREE(fs, ino) == 0)
469 1.87 perseant break;
470 1.87 perseant }
471 1.87 perseant return ino;
472 1.87 perseant }
473 1.87 perseant #endif
474 1.87 perseant
475 1.87 perseant /*
476 1.87 perseant * Find the previous (next lowest numbered) free inode, if any.
477 1.87 perseant * If there is none, return LFS_UNUSED_INUM.
478 1.132 dholland *
479 1.132 dholland * XXX: locking?
480 1.87 perseant */
481 1.87 perseant static inline ino_t
482 1.87 perseant lfs_freelist_prev(struct lfs *fs, ino_t ino)
483 1.87 perseant {
484 1.88 perseant ino_t tino, bound, bb, freehdbb;
485 1.88 perseant
486 1.132 dholland if (lfs_sb_getfreehd(fs) == LFS_UNUSED_INUM) {
487 1.132 dholland /* No free inodes at all */
488 1.88 perseant return LFS_UNUSED_INUM;
489 1.132 dholland }
490 1.88 perseant
491 1.88 perseant /* Search our own word first */
492 1.88 perseant bound = ino & ~BMMASK;
493 1.89 perseant for (tino = ino - 1; tino >= bound && tino > LFS_UNUSED_INUM; tino--)
494 1.88 perseant if (ISSET_BITMAP_FREE(fs, tino))
495 1.88 perseant return tino;
496 1.88 perseant /* If there are no lower words to search, just return */
497 1.88 perseant if (ino >> BMSHIFT == 0)
498 1.88 perseant return LFS_UNUSED_INUM;
499 1.88 perseant
500 1.88 perseant /*
501 1.88 perseant * Find a word with a free inode in it. We have to be a bit
502 1.88 perseant * careful here since ino_t is unsigned.
503 1.88 perseant */
504 1.122 dholland freehdbb = (lfs_sb_getfreehd(fs) >> BMSHIFT);
505 1.88 perseant for (bb = (ino >> BMSHIFT) - 1; bb >= freehdbb && bb > 0; --bb)
506 1.88 perseant if (fs->lfs_ino_bitmap[bb])
507 1.88 perseant break;
508 1.88 perseant if (fs->lfs_ino_bitmap[bb] == 0)
509 1.88 perseant return LFS_UNUSED_INUM;
510 1.88 perseant
511 1.88 perseant /* Search the word we found */
512 1.89 perseant for (tino = (bb << BMSHIFT) | BMMASK; tino >= (bb << BMSHIFT) &&
513 1.89 perseant tino > LFS_UNUSED_INUM; tino--)
514 1.88 perseant if (ISSET_BITMAP_FREE(fs, tino))
515 1.88 perseant break;
516 1.87 perseant
517 1.132 dholland /* Avoid returning reserved inode numbers */
518 1.87 perseant if (tino <= LFS_IFILE_INUM)
519 1.87 perseant tino = LFS_UNUSED_INUM;
520 1.87 perseant
521 1.87 perseant return tino;
522 1.87 perseant }
523 1.87 perseant
524 1.132 dholland /*
525 1.132 dholland * Free an inode.
526 1.132 dholland *
527 1.132 dholland * Takes lfs_seglock. Also (independently) takes vp->v_interlock.
528 1.132 dholland */
529 1.1 mycroft /* ARGUSED */
530 1.43 perseant /* VOP_BWRITE 2i times */
531 1.1 mycroft int
532 1.99 christos lfs_vfree(struct vnode *vp, ino_t ino, int mode)
533 1.3 christos {
534 1.1 mycroft SEGUSE *sup;
535 1.48 perseant CLEANERINFO *cip;
536 1.48 perseant struct buf *cbp, *bp;
537 1.126 dholland IFILE *ifp;
538 1.1 mycroft struct inode *ip;
539 1.1 mycroft struct lfs *fs;
540 1.59 fvdl daddr_t old_iaddr;
541 1.85 yamt ino_t otail;
542 1.75 perry
543 1.1 mycroft /* Get the inode number and file system. */
544 1.30 perseant ip = VTOI(vp);
545 1.1 mycroft fs = ip->i_lfs;
546 1.1 mycroft ino = ip->i_number;
547 1.34 perseant
548 1.132 dholland /* XXX: assert not readonly */
549 1.132 dholland
550 1.78 perseant ASSERT_NO_SEGLOCK(fs);
551 1.88 perseant DLOG((DLOG_ALLOC, "lfs_vfree: free ino %lld\n", (long long)ino));
552 1.78 perseant
553 1.48 perseant /* Drain of pending writes */
554 1.111 rmind mutex_enter(vp->v_interlock);
555 1.125 dholland while (lfs_sb_getversion(fs) > 1 && WRITEINPROG(vp)) {
556 1.111 rmind cv_wait(&vp->v_cv, vp->v_interlock);
557 1.105 ad }
558 1.111 rmind mutex_exit(vp->v_interlock);
559 1.48 perseant
560 1.63 perseant lfs_seglock(fs, SEGM_PROT);
561 1.75 perry
562 1.132 dholland /*
563 1.132 dholland * If the inode was in a dirop, it isn't now.
564 1.132 dholland *
565 1.136 maya * XXX: why are (v_uflag & VU_DIROP) and (ip->i_state & IN_ADIROP)
566 1.132 dholland * not updated together in one function? (and why do both exist,
567 1.132 dholland * anyway?)
568 1.132 dholland */
569 1.137 maya UNMARK_VNODE(vp);
570 1.132 dholland
571 1.105 ad mutex_enter(&lfs_lock);
572 1.103 ad if (vp->v_uflag & VU_DIROP) {
573 1.103 ad vp->v_uflag &= ~VU_DIROP;
574 1.30 perseant --lfs_dirvcount;
575 1.92 perseant --fs->lfs_dirvcount;
576 1.63 perseant TAILQ_REMOVE(&fs->lfs_dchainhd, ip, i_lfs_dchain);
577 1.92 perseant wakeup(&fs->lfs_dirvcount);
578 1.30 perseant wakeup(&lfs_dirvcount);
579 1.105 ad mutex_exit(&lfs_lock);
580 1.120 hannken vrele(vp);
581 1.90 perseant
582 1.90 perseant /*
583 1.90 perseant * If this inode is not going to be written any more, any
584 1.90 perseant * segment accounting left over from its truncation needs
585 1.90 perseant * to occur at the end of the next dirops flush. Attach
586 1.90 perseant * them to the fs-wide list for that purpose.
587 1.90 perseant */
588 1.90 perseant if (LIST_FIRST(&ip->i_lfs_segdhd) != NULL) {
589 1.90 perseant struct segdelta *sd;
590 1.90 perseant
591 1.90 perseant while((sd = LIST_FIRST(&ip->i_lfs_segdhd)) != NULL) {
592 1.90 perseant LIST_REMOVE(sd, list);
593 1.90 perseant LIST_INSERT_HEAD(&fs->lfs_segdhd, sd, list);
594 1.90 perseant }
595 1.90 perseant }
596 1.90 perseant } else {
597 1.90 perseant /*
598 1.90 perseant * If it's not a dirop, we can finalize right away.
599 1.90 perseant */
600 1.105 ad mutex_exit(&lfs_lock);
601 1.90 perseant lfs_finalize_ino_seguse(fs, ip);
602 1.38 perseant }
603 1.30 perseant
604 1.132 dholland /* it is no longer an unwritten inode, so update the counts */
605 1.105 ad mutex_enter(&lfs_lock);
606 1.42 perseant LFS_CLR_UINO(ip, IN_ACCESSED|IN_CLEANING|IN_MODIFIED);
607 1.105 ad mutex_exit(&lfs_lock);
608 1.132 dholland
609 1.132 dholland /* Turn off all inode modification flags */
610 1.136 maya ip->i_state &= ~IN_ALLMOD;
611 1.132 dholland
612 1.132 dholland /* Mark it deleted */
613 1.93 perseant ip->i_lfs_iflags |= LFSI_DELETED;
614 1.93 perseant
615 1.132 dholland /* Mark it free in the in-memory inode freemap */
616 1.132 dholland SET_BITMAP_FREE(fs, ino);
617 1.132 dholland
618 1.1 mycroft /*
619 1.1 mycroft * Set the ifile's inode entry to unused, increment its version number
620 1.48 perseant * and link it onto the free chain.
621 1.1 mycroft */
622 1.132 dholland
623 1.132 dholland /* fetch the ifile entry */
624 1.1 mycroft LFS_IENTRY(ifp, fs, ino, bp);
625 1.132 dholland
626 1.132 dholland /* update the on-disk address (to "nowhere") */
627 1.126 dholland old_iaddr = lfs_if_getdaddr(fs, ifp);
628 1.126 dholland lfs_if_setdaddr(fs, ifp, LFS_UNUSED_DADDR);
629 1.132 dholland
630 1.132 dholland /* bump the version */
631 1.126 dholland lfs_if_setversion(fs, ifp, lfs_if_getversion(fs, ifp) + 1);
632 1.132 dholland
633 1.125 dholland if (lfs_sb_getversion(fs) == 1) {
634 1.126 dholland ino_t nextfree;
635 1.126 dholland
636 1.132 dholland /* insert on freelist */
637 1.126 dholland LFS_GET_HEADFREE(fs, cip, cbp, &nextfree);
638 1.126 dholland lfs_if_setnextfree(fs, ifp, nextfree);
639 1.48 perseant LFS_PUT_HEADFREE(fs, cip, cbp, ino);
640 1.132 dholland
641 1.132 dholland /* write the ifile block */
642 1.56 perseant (void) LFS_BWRITE_LOG(bp); /* Ifile */
643 1.48 perseant } else {
644 1.87 perseant ino_t tino, onf;
645 1.87 perseant
646 1.132 dholland /*
647 1.132 dholland * Clear the freelist next pointer and write the ifile
648 1.132 dholland * block. XXX: why? I'm sure there must be a reason but
649 1.132 dholland * it seems both silly and dangerous.
650 1.132 dholland */
651 1.126 dholland lfs_if_setnextfree(fs, ifp, LFS_UNUSED_INUM);
652 1.56 perseant (void) LFS_BWRITE_LOG(bp); /* Ifile */
653 1.87 perseant
654 1.132 dholland /*
655 1.132 dholland * Insert on freelist in order.
656 1.132 dholland */
657 1.132 dholland
658 1.132 dholland /* Find the next lower (by number) free inode */
659 1.87 perseant tino = lfs_freelist_prev(fs, ino);
660 1.132 dholland
661 1.87 perseant if (tino == LFS_UNUSED_INUM) {
662 1.126 dholland ino_t nextfree;
663 1.126 dholland
664 1.132 dholland /*
665 1.132 dholland * There isn't one; put us on the freelist head.
666 1.132 dholland */
667 1.132 dholland
668 1.132 dholland /* reload the ifile block */
669 1.87 perseant LFS_IENTRY(ifp, fs, ino, bp);
670 1.132 dholland /* update the list */
671 1.126 dholland LFS_GET_HEADFREE(fs, cip, cbp, &nextfree);
672 1.126 dholland lfs_if_setnextfree(fs, ifp, nextfree);
673 1.87 perseant LFS_PUT_HEADFREE(fs, cip, cbp, ino);
674 1.88 perseant DLOG((DLOG_ALLOC, "lfs_vfree: headfree %lld -> %lld\n",
675 1.126 dholland (long long)nextfree, (long long)ino));
676 1.132 dholland /* write the ifile block */
677 1.87 perseant LFS_BWRITE_LOG(bp); /* Ifile */
678 1.87 perseant
679 1.87 perseant /* If the list was empty, set tail too */
680 1.87 perseant LFS_GET_TAILFREE(fs, cip, cbp, &otail);
681 1.87 perseant if (otail == LFS_UNUSED_INUM) {
682 1.87 perseant LFS_PUT_TAILFREE(fs, cip, cbp, ino);
683 1.87 perseant DLOG((DLOG_ALLOC, "lfs_vfree: tailfree %lld "
684 1.87 perseant "-> %lld\n", (long long)otail,
685 1.87 perseant (long long)ino));
686 1.87 perseant }
687 1.87 perseant } else {
688 1.87 perseant /*
689 1.87 perseant * Insert this inode into the list after tino.
690 1.87 perseant * We hold the segment lock so we don't have to
691 1.87 perseant * worry about blocks being written out of order.
692 1.87 perseant */
693 1.132 dholland
694 1.87 perseant DLOG((DLOG_ALLOC, "lfs_vfree: insert ino %lld "
695 1.87 perseant " after %lld\n", ino, tino));
696 1.87 perseant
697 1.132 dholland /* load the previous inode's ifile block */
698 1.87 perseant LFS_IENTRY(ifp, fs, tino, bp);
699 1.132 dholland /* update the list pointer */
700 1.126 dholland onf = lfs_if_getnextfree(fs, ifp);
701 1.126 dholland lfs_if_setnextfree(fs, ifp, ino);
702 1.132 dholland /* write the block */
703 1.87 perseant LFS_BWRITE_LOG(bp); /* Ifile */
704 1.87 perseant
705 1.132 dholland /* load this inode's ifile block */
706 1.87 perseant LFS_IENTRY(ifp, fs, ino, bp);
707 1.132 dholland /* update the list pointer */
708 1.126 dholland lfs_if_setnextfree(fs, ifp, onf);
709 1.132 dholland /* write the block */
710 1.87 perseant LFS_BWRITE_LOG(bp); /* Ifile */
711 1.87 perseant
712 1.87 perseant /* If we're last, put us on the tail */
713 1.87 perseant if (onf == LFS_UNUSED_INUM) {
714 1.87 perseant LFS_GET_TAILFREE(fs, cip, cbp, &otail);
715 1.87 perseant LFS_PUT_TAILFREE(fs, cip, cbp, ino);
716 1.87 perseant DLOG((DLOG_ALLOC, "lfs_vfree: tailfree %lld "
717 1.87 perseant "-> %lld\n", (long long)otail,
718 1.87 perseant (long long)ino));
719 1.87 perseant }
720 1.87 perseant }
721 1.48 perseant }
722 1.132 dholland /* XXX: shouldn't this check be further up *before* we trash the fs? */
723 1.134 riastrad KASSERTMSG((ino != LFS_UNUSED_INUM), "inode 0 freed");
724 1.132 dholland
725 1.132 dholland /*
726 1.132 dholland * Update the segment summary for the segment where the on-disk
727 1.132 dholland * copy used to be.
728 1.132 dholland */
729 1.142 perseant if (!DADDR_IS_BAD(old_iaddr)) {
730 1.132 dholland /* load it */
731 1.117 christos LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, old_iaddr), bp);
732 1.132 dholland /* the number of bytes in the segment should not become < 0 */
733 1.134 riastrad KASSERTMSG((sup->su_nbytes >= DINOSIZE(fs)),
734 1.134 riastrad "lfs_vfree: negative byte count"
735 1.134 riastrad " (segment %" PRIu32 " short by %d)\n",
736 1.134 riastrad lfs_dtosn(fs, old_iaddr),
737 1.134 riastrad (int)DINOSIZE(fs) - sup->su_nbytes);
738 1.132 dholland /* update the number of bytes in the segment */
739 1.127 dholland sup->su_nbytes -= DINOSIZE(fs);
740 1.132 dholland /* write the segment entry */
741 1.117 christos LFS_WRITESEGENTRY(sup, fs, lfs_dtosn(fs, old_iaddr), bp); /* Ifile */
742 1.1 mycroft }
743 1.75 perry
744 1.132 dholland /* Set superblock modified bit. */
745 1.105 ad mutex_enter(&lfs_lock);
746 1.1 mycroft fs->lfs_fmod = 1;
747 1.105 ad mutex_exit(&lfs_lock);
748 1.132 dholland
749 1.132 dholland /* Decrement file count. */
750 1.122 dholland lfs_sb_subnfiles(fs, 1);
751 1.75 perry
752 1.56 perseant lfs_segunlock(fs);
753 1.63 perseant
754 1.1 mycroft return (0);
755 1.1 mycroft }
756 1.87 perseant
757 1.87 perseant /*
758 1.87 perseant * Sort the freelist and set up the free-inode bitmap.
759 1.87 perseant * To be called by lfs_mountfs().
760 1.132 dholland *
761 1.132 dholland * Takes the segmenet lock.
762 1.87 perseant */
763 1.87 perseant void
764 1.141 riastrad lfs_order_freelist(struct lfs *fs, ino_t **orphanp, size_t *norphanp)
765 1.87 perseant {
766 1.87 perseant CLEANERINFO *cip;
767 1.87 perseant IFILE *ifp = NULL;
768 1.87 perseant struct buf *bp;
769 1.87 perseant ino_t ino, firstino, lastino, maxino;
770 1.141 riastrad ino_t *orphan = NULL;
771 1.141 riastrad size_t norphan = 0;
772 1.141 riastrad size_t norphan_alloc = 0;
773 1.141 riastrad
774 1.95 perseant ASSERT_NO_SEGLOCK(fs);
775 1.95 perseant lfs_seglock(fs, SEGM_PROT);
776 1.95 perseant
777 1.132 dholland /* largest inode on fs */
778 1.123 dholland maxino = ((fs->lfs_ivnode->v_size >> lfs_sb_getbshift(fs)) -
779 1.122 dholland lfs_sb_getcleansz(fs) - lfs_sb_getsegtabsz(fs)) * lfs_sb_getifpb(fs);
780 1.132 dholland
781 1.132 dholland /* allocate the in-memory inode freemap */
782 1.132 dholland /* XXX: assert that fs->lfs_ino_bitmap is null here */
783 1.121 dholland fs->lfs_ino_bitmap =
784 1.88 perseant malloc(((maxino + BMMASK) >> BMSHIFT) * sizeof(lfs_bm_t),
785 1.88 perseant M_SEGMENT, M_WAITOK | M_ZERO);
786 1.88 perseant KASSERT(fs->lfs_ino_bitmap != NULL);
787 1.87 perseant
788 1.132 dholland /*
789 1.132 dholland * Scan the ifile.
790 1.132 dholland */
791 1.132 dholland
792 1.87 perseant firstino = lastino = LFS_UNUSED_INUM;
793 1.87 perseant for (ino = 0; ino < maxino; ino++) {
794 1.132 dholland /* Load this inode's ifile entry. */
795 1.122 dholland if (ino % lfs_sb_getifpb(fs) == 0)
796 1.87 perseant LFS_IENTRY(ifp, fs, ino, bp);
797 1.87 perseant else
798 1.128 mlelstv LFS_IENTRY_NEXT(ifp, fs);
799 1.87 perseant
800 1.87 perseant /* Don't put zero or ifile on the free list */
801 1.87 perseant if (ino == LFS_UNUSED_INUM || ino == LFS_IFILE_INUM)
802 1.87 perseant continue;
803 1.87 perseant
804 1.132 dholland /*
805 1.132 dholland * Address orphaned files.
806 1.132 dholland *
807 1.132 dholland * The idea of this is to free inodes belonging to
808 1.132 dholland * files that were unlinked but not reclaimed, I guess
809 1.132 dholland * because if we're going to scan the whole ifile
810 1.132 dholland * anyway it costs very little to do this. I don't
811 1.132 dholland * immediately see any reason this should be disabled,
812 1.132 dholland * but presumably it doesn't work... not sure what
813 1.132 dholland * happens to such files currently. -- dholland 20160806
814 1.132 dholland */
815 1.141 riastrad if (lfs_if_getnextfree(fs, ifp) == LFS_ORPHAN_NEXTFREE(fs)) {
816 1.141 riastrad if (orphan == NULL) {
817 1.141 riastrad norphan_alloc = 32; /* XXX pulled from arse */
818 1.141 riastrad orphan = kmem_zalloc(sizeof(orphan[0]) *
819 1.141 riastrad norphan_alloc, KM_SLEEP);
820 1.141 riastrad } else if (norphan == norphan_alloc) {
821 1.141 riastrad ino_t *orphan_new;
822 1.141 riastrad if (norphan_alloc >= 4096)
823 1.141 riastrad norphan_alloc += 4096;
824 1.141 riastrad else
825 1.141 riastrad norphan_alloc *= 2;
826 1.141 riastrad orphan_new = kmem_zalloc(sizeof(orphan[0]) *
827 1.141 riastrad norphan_alloc, KM_SLEEP);
828 1.141 riastrad memcpy(orphan_new, orphan, sizeof(orphan[0]) *
829 1.141 riastrad norphan);
830 1.141 riastrad kmem_free(orphan, sizeof(orphan[0]) * norphan);
831 1.141 riastrad orphan = orphan_new;
832 1.141 riastrad }
833 1.141 riastrad orphan[norphan++] = ino;
834 1.97 perseant }
835 1.97 perseant
836 1.142 perseant if (DADDR_IS_BAD(lfs_if_getdaddr(fs, ifp))) {
837 1.132 dholland
838 1.132 dholland /*
839 1.132 dholland * This inode is free. Put it on the free list.
840 1.132 dholland */
841 1.132 dholland
842 1.132 dholland if (firstino == LFS_UNUSED_INUM) {
843 1.132 dholland /* XXX: assert lastino == LFS_UNUSED_INUM? */
844 1.132 dholland /* remember the first free inode */
845 1.87 perseant firstino = ino;
846 1.132 dholland } else {
847 1.132 dholland /* release this inode's ifile entry */
848 1.102 ad brelse(bp, 0);
849 1.87 perseant
850 1.132 dholland /* XXX: assert lastino != LFS_UNUSED_INUM? */
851 1.132 dholland
852 1.132 dholland /* load lastino's ifile entry */
853 1.87 perseant LFS_IENTRY(ifp, fs, lastino, bp);
854 1.132 dholland /* set the list pointer */
855 1.126 dholland lfs_if_setnextfree(fs, ifp, ino);
856 1.132 dholland /* write the block */
857 1.87 perseant LFS_BWRITE_LOG(bp);
858 1.132 dholland
859 1.132 dholland /* reload this inode's ifile entry */
860 1.87 perseant LFS_IENTRY(ifp, fs, ino, bp);
861 1.87 perseant }
862 1.132 dholland /* remember the last free inode seen so far */
863 1.87 perseant lastino = ino;
864 1.87 perseant
865 1.132 dholland /* Mark this inode free in the in-memory freemap */
866 1.87 perseant SET_BITMAP_FREE(fs, ino);
867 1.87 perseant }
868 1.87 perseant
869 1.132 dholland /* If moving to the next ifile block, release the buffer. */
870 1.122 dholland if ((ino + 1) % lfs_sb_getifpb(fs) == 0)
871 1.102 ad brelse(bp, 0);
872 1.87 perseant }
873 1.87 perseant
874 1.132 dholland /* Write the freelist head and tail pointers */
875 1.132 dholland /* XXX: do we need to mark the superblock dirty? */
876 1.87 perseant LFS_PUT_HEADFREE(fs, cip, bp, firstino);
877 1.87 perseant LFS_PUT_TAILFREE(fs, cip, bp, lastino);
878 1.95 perseant
879 1.132 dholland /* done */
880 1.95 perseant lfs_segunlock(fs);
881 1.141 riastrad
882 1.141 riastrad /*
883 1.141 riastrad * Shrink the array of orphans so we don't have to carry around
884 1.141 riastrad * the allocation size.
885 1.141 riastrad */
886 1.141 riastrad if (norphan < norphan_alloc) {
887 1.141 riastrad ino_t *orphan_new = kmem_alloc(sizeof(orphan[0]) * norphan,
888 1.141 riastrad KM_SLEEP);
889 1.141 riastrad memcpy(orphan_new, orphan, sizeof(orphan[0]) * norphan);
890 1.141 riastrad kmem_free(orphan, sizeof(orphan[0]) * norphan_alloc);
891 1.141 riastrad orphan = orphan_new;
892 1.141 riastrad norphan_alloc = norphan;
893 1.141 riastrad }
894 1.141 riastrad
895 1.141 riastrad *orphanp = orphan;
896 1.141 riastrad *norphanp = norphan;
897 1.87 perseant }
898 1.97 perseant
899 1.132 dholland /*
900 1.132 dholland * Mark a file orphaned (unlinked but not yet reclaimed) by inode
901 1.132 dholland * number. Do this with a magic freelist next pointer.
902 1.132 dholland *
903 1.132 dholland * XXX: howzabout some locking?
904 1.132 dholland */
905 1.97 perseant void
906 1.97 perseant lfs_orphan(struct lfs *fs, ino_t ino)
907 1.97 perseant {
908 1.97 perseant IFILE *ifp;
909 1.97 perseant struct buf *bp;
910 1.97 perseant
911 1.97 perseant LFS_IENTRY(ifp, fs, ino, bp);
912 1.140 riastrad lfs_if_setnextfree(fs, ifp, LFS_ORPHAN_NEXTFREE(fs));
913 1.97 perseant LFS_BWRITE_LOG(bp);
914 1.97 perseant }
915 1.141 riastrad
916 1.141 riastrad /*
917 1.141 riastrad * Free orphans discovered during mount. This is a separate stage
918 1.141 riastrad * because it requires fs->lfs_suflags to be set up, which is not done
919 1.141 riastrad * by the time we run lfs_order_freelist. It's possible that we could
920 1.141 riastrad * run lfs_order_freelist later (i.e., set up fs->lfs_suflags sooner)
921 1.141 riastrad * but that requires more thought than I can put into this at the
922 1.141 riastrad * moment.
923 1.141 riastrad */
924 1.141 riastrad void
925 1.141 riastrad lfs_free_orphans(struct lfs *fs, ino_t *orphan, size_t norphan)
926 1.141 riastrad {
927 1.141 riastrad size_t i;
928 1.141 riastrad
929 1.141 riastrad for (i = 0; i < norphan; i++) {
930 1.141 riastrad ino_t ino = orphan[i];
931 1.141 riastrad unsigned segno;
932 1.141 riastrad struct vnode *vp;
933 1.141 riastrad struct inode *ip;
934 1.141 riastrad struct buf *bp;
935 1.141 riastrad IFILE *ifp;
936 1.141 riastrad SEGUSE *sup;
937 1.141 riastrad int error;
938 1.141 riastrad
939 1.141 riastrad /* Get the segment the inode is in on disk. */
940 1.141 riastrad LFS_IENTRY(ifp, fs, ino, bp);
941 1.142 perseant KASSERT(!DADDR_IS_BAD(lfs_if_getdaddr(fs, ifp)));
942 1.141 riastrad segno = lfs_dtosn(fs, lfs_if_getdaddr(fs, ifp));
943 1.141 riastrad brelse(bp, 0);
944 1.141 riastrad
945 1.141 riastrad /*
946 1.141 riastrad * Try to get the vnode. If we can't, tough -- hope
947 1.141 riastrad * you have backups!
948 1.141 riastrad */
949 1.141 riastrad error = VFS_VGET(fs->lfs_ivnode->v_mount, ino, LK_EXCLUSIVE,
950 1.141 riastrad &vp);
951 1.141 riastrad if (error) {
952 1.141 riastrad printf("orphan %jd vget error %d\n", (intmax_t)ino,
953 1.141 riastrad error);
954 1.141 riastrad continue;
955 1.141 riastrad }
956 1.141 riastrad
957 1.141 riastrad /*
958 1.141 riastrad * Sanity-check the inode.
959 1.141 riastrad *
960 1.141 riastrad * XXX What to do if it is still referenced?
961 1.141 riastrad */
962 1.141 riastrad ip = VTOI(vp);
963 1.141 riastrad if (ip->i_nlink != 0)
964 1.141 riastrad printf("orphan %jd nlink %d\n", (intmax_t)ino,
965 1.141 riastrad ip->i_nlink);
966 1.141 riastrad
967 1.141 riastrad /*
968 1.141 riastrad * Truncate the inode, to free any blocks allocated for
969 1.141 riastrad * it, and release it, to free the inode number.
970 1.141 riastrad *
971 1.141 riastrad * XXX Isn't it redundant to truncate? Won't vput do
972 1.141 riastrad * that for us?
973 1.141 riastrad */
974 1.141 riastrad error = lfs_truncate(vp, 0, 0, NOCRED);
975 1.141 riastrad if (error)
976 1.141 riastrad printf("orphan %jd truncate error %d", (intmax_t)ino,
977 1.141 riastrad error);
978 1.141 riastrad vput(vp);
979 1.141 riastrad
980 1.141 riastrad /* Update the number of bytes in the segment summary. */
981 1.141 riastrad LFS_SEGENTRY(sup, fs, segno, bp);
982 1.141 riastrad KASSERT(sup->su_nbytes >= DINOSIZE(fs));
983 1.141 riastrad sup->su_nbytes -= DINOSIZE(fs);
984 1.141 riastrad LFS_WRITESEGENTRY(sup, fs, segno, bp);
985 1.141 riastrad
986 1.141 riastrad /* Drop the on-disk address. */
987 1.141 riastrad LFS_IENTRY(ifp, fs, ino, bp);
988 1.141 riastrad lfs_if_setdaddr(fs, ifp, LFS_UNUSED_DADDR);
989 1.141 riastrad LFS_BWRITE_LOG(bp);
990 1.141 riastrad }
991 1.141 riastrad
992 1.141 riastrad if (orphan)
993 1.141 riastrad kmem_free(orphan, sizeof(orphan[0]) * norphan);
994 1.141 riastrad }
995