xref: /minix3/sys/ufs/lfs/lfs_alloc.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: lfs_alloc.c,v 1.130 2015/09/13 07:53:37 dholland Exp $	*/
2d65f6f70SBen Gras 
3d65f6f70SBen Gras /*-
4d65f6f70SBen Gras  * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2007 The NetBSD Foundation, Inc.
5d65f6f70SBen Gras  * All rights reserved.
6d65f6f70SBen Gras  *
7d65f6f70SBen Gras  * This code is derived from software contributed to The NetBSD Foundation
8d65f6f70SBen Gras  * by Konrad E. Schroder <perseant@hhhh.org>.
9d65f6f70SBen Gras  *
10d65f6f70SBen Gras  * Redistribution and use in source and binary forms, with or without
11d65f6f70SBen Gras  * modification, are permitted provided that the following conditions
12d65f6f70SBen Gras  * are met:
13d65f6f70SBen Gras  * 1. Redistributions of source code must retain the above copyright
14d65f6f70SBen Gras  *    notice, this list of conditions and the following disclaimer.
15d65f6f70SBen Gras  * 2. Redistributions in binary form must reproduce the above copyright
16d65f6f70SBen Gras  *    notice, this list of conditions and the following disclaimer in the
17d65f6f70SBen Gras  *    documentation and/or other materials provided with the distribution.
18d65f6f70SBen Gras  *
19d65f6f70SBen Gras  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20d65f6f70SBen Gras  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21d65f6f70SBen Gras  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22d65f6f70SBen Gras  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23d65f6f70SBen Gras  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24d65f6f70SBen Gras  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25d65f6f70SBen Gras  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26d65f6f70SBen Gras  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27d65f6f70SBen Gras  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28d65f6f70SBen Gras  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29d65f6f70SBen Gras  * POSSIBILITY OF SUCH DAMAGE.
30d65f6f70SBen Gras  */
31d65f6f70SBen Gras /*
32d65f6f70SBen Gras  * Copyright (c) 1991, 1993
33d65f6f70SBen Gras  *	The Regents of the University of California.  All rights reserved.
34d65f6f70SBen Gras  *
35d65f6f70SBen Gras  * Redistribution and use in source and binary forms, with or without
36d65f6f70SBen Gras  * modification, are permitted provided that the following conditions
37d65f6f70SBen Gras  * are met:
38d65f6f70SBen Gras  * 1. Redistributions of source code must retain the above copyright
39d65f6f70SBen Gras  *    notice, this list of conditions and the following disclaimer.
40d65f6f70SBen Gras  * 2. Redistributions in binary form must reproduce the above copyright
41d65f6f70SBen Gras  *    notice, this list of conditions and the following disclaimer in the
42d65f6f70SBen Gras  *    documentation and/or other materials provided with the distribution.
43d65f6f70SBen Gras  * 3. Neither the name of the University nor the names of its contributors
44d65f6f70SBen Gras  *    may be used to endorse or promote products derived from this software
45d65f6f70SBen Gras  *    without specific prior written permission.
46d65f6f70SBen Gras  *
47d65f6f70SBen Gras  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48d65f6f70SBen Gras  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49d65f6f70SBen Gras  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50d65f6f70SBen Gras  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51d65f6f70SBen Gras  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52d65f6f70SBen Gras  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53d65f6f70SBen Gras  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54d65f6f70SBen Gras  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55d65f6f70SBen Gras  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56d65f6f70SBen Gras  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57d65f6f70SBen Gras  * SUCH DAMAGE.
58d65f6f70SBen Gras  *
59d65f6f70SBen Gras  *	@(#)lfs_alloc.c	8.4 (Berkeley) 1/4/94
60d65f6f70SBen Gras  */
61d65f6f70SBen Gras 
62d65f6f70SBen Gras #include <sys/cdefs.h>
63*0a6a1f1dSLionel Sambuc __KERNEL_RCSID(0, "$NetBSD: lfs_alloc.c,v 1.130 2015/09/13 07:53:37 dholland Exp $");
64d65f6f70SBen Gras 
65d65f6f70SBen Gras #if defined(_KERNEL_OPT)
66d65f6f70SBen Gras #include "opt_quota.h"
67d65f6f70SBen Gras #endif
68d65f6f70SBen Gras 
69d65f6f70SBen Gras #include <sys/param.h>
70d65f6f70SBen Gras #include <sys/systm.h>
71d65f6f70SBen Gras #include <sys/kernel.h>
72d65f6f70SBen Gras #include <sys/buf.h>
73d65f6f70SBen Gras #include <sys/lock.h>
74d65f6f70SBen Gras #include <sys/vnode.h>
75d65f6f70SBen Gras #include <sys/syslog.h>
76d65f6f70SBen Gras #include <sys/mount.h>
77d65f6f70SBen Gras #include <sys/malloc.h>
78d65f6f70SBen Gras #include <sys/pool.h>
79d65f6f70SBen Gras #include <sys/proc.h>
80d65f6f70SBen Gras #include <sys/tree.h>
81d65f6f70SBen Gras #include <sys/kauth.h>
82d65f6f70SBen Gras 
8384d9c625SLionel Sambuc #include <ufs/lfs/ulfs_quotacommon.h>
8484d9c625SLionel Sambuc #include <ufs/lfs/ulfs_inode.h>
8584d9c625SLionel Sambuc #include <ufs/lfs/ulfsmount.h>
8684d9c625SLionel Sambuc #include <ufs/lfs/ulfs_extern.h>
87d65f6f70SBen Gras 
88d65f6f70SBen Gras #include <ufs/lfs/lfs.h>
89*0a6a1f1dSLionel Sambuc #include <ufs/lfs/lfs_accessors.h>
90d65f6f70SBen Gras #include <ufs/lfs/lfs_extern.h>
9184d9c625SLionel Sambuc #include <ufs/lfs/lfs_kernel.h>
92d65f6f70SBen Gras 
93d65f6f70SBen Gras /* Constants for inode free bitmap */
94d65f6f70SBen Gras #define BMSHIFT 5	/* 2 ** 5 = 32 */
95d65f6f70SBen Gras #define BMMASK  ((1 << BMSHIFT) - 1)
96d65f6f70SBen Gras #define SET_BITMAP_FREE(F, I) do { \
97d65f6f70SBen Gras 	DLOG((DLOG_ALLOC, "lfs: ino %d wrd %d bit %d set\n", (int)(I), 	\
98d65f6f70SBen Gras 	     (int)((I) >> BMSHIFT), (int)((I) & BMMASK)));		\
99d65f6f70SBen Gras 	(F)->lfs_ino_bitmap[(I) >> BMSHIFT] |= (1 << ((I) & BMMASK));	\
100d65f6f70SBen Gras } while (0)
101d65f6f70SBen Gras #define CLR_BITMAP_FREE(F, I) do { \
102d65f6f70SBen Gras 	DLOG((DLOG_ALLOC, "lfs: ino %d wrd %d bit %d clr\n", (int)(I), 	\
103d65f6f70SBen Gras 	     (int)((I) >> BMSHIFT), (int)((I) & BMMASK)));		\
104d65f6f70SBen Gras 	(F)->lfs_ino_bitmap[(I) >> BMSHIFT] &= ~(1 << ((I) & BMMASK));	\
105d65f6f70SBen Gras } while(0)
106d65f6f70SBen Gras 
107d65f6f70SBen Gras #define ISSET_BITMAP_FREE(F, I) \
108d65f6f70SBen Gras 	((F)->lfs_ino_bitmap[(I) >> BMSHIFT] & (1 << ((I) & BMMASK)))
109d65f6f70SBen Gras 
110d65f6f70SBen Gras /*
111d65f6f70SBen Gras  * Add a new block to the Ifile, to accommodate future file creations.
112d65f6f70SBen Gras  * Called with the segment lock held.
113d65f6f70SBen Gras  */
114d65f6f70SBen Gras int
lfs_extend_ifile(struct lfs * fs,kauth_cred_t cred)115d65f6f70SBen Gras lfs_extend_ifile(struct lfs *fs, kauth_cred_t cred)
116d65f6f70SBen Gras {
117d65f6f70SBen Gras 	struct vnode *vp;
118d65f6f70SBen Gras 	struct inode *ip;
119*0a6a1f1dSLionel Sambuc 	IFILE64 *ifp64;
120*0a6a1f1dSLionel Sambuc 	IFILE32 *ifp32;
121d65f6f70SBen Gras 	IFILE_V1 *ifp_v1;
122d65f6f70SBen Gras 	struct buf *bp, *cbp;
123d65f6f70SBen Gras 	int error;
124d65f6f70SBen Gras 	daddr_t i, blkno, xmax;
125d65f6f70SBen Gras 	ino_t oldlast, maxino;
126d65f6f70SBen Gras 	CLEANERINFO *cip;
127d65f6f70SBen Gras 
128d65f6f70SBen Gras 	ASSERT_SEGLOCK(fs);
129d65f6f70SBen Gras 
130d65f6f70SBen Gras 	vp = fs->lfs_ivnode;
131d65f6f70SBen Gras 	ip = VTOI(vp);
13284d9c625SLionel Sambuc 	blkno = lfs_lblkno(fs, ip->i_size);
133*0a6a1f1dSLionel Sambuc 	if ((error = lfs_balloc(vp, ip->i_size, lfs_sb_getbsize(fs), cred, 0,
134d65f6f70SBen Gras 				&bp)) != 0) {
135d65f6f70SBen Gras 		return (error);
136d65f6f70SBen Gras 	}
137*0a6a1f1dSLionel Sambuc 	ip->i_size += lfs_sb_getbsize(fs);
138*0a6a1f1dSLionel Sambuc 	lfs_dino_setsize(fs, ip->i_din, ip->i_size);
139d65f6f70SBen Gras 	uvm_vnp_setsize(vp, ip->i_size);
140d65f6f70SBen Gras 
141*0a6a1f1dSLionel Sambuc 	maxino = ((ip->i_size >> lfs_sb_getbshift(fs)) - lfs_sb_getcleansz(fs) -
142*0a6a1f1dSLionel Sambuc 		  lfs_sb_getsegtabsz(fs)) * lfs_sb_getifpb(fs);
143d65f6f70SBen Gras 	fs->lfs_ino_bitmap = (lfs_bm_t *)
144d65f6f70SBen Gras 		realloc(fs->lfs_ino_bitmap, ((maxino + BMMASK) >> BMSHIFT) *
145d65f6f70SBen Gras 			sizeof(lfs_bm_t), M_SEGMENT, M_WAITOK);
146d65f6f70SBen Gras 	KASSERT(fs->lfs_ino_bitmap != NULL);
147d65f6f70SBen Gras 
148*0a6a1f1dSLionel Sambuc 	i = (blkno - lfs_sb_getsegtabsz(fs) - lfs_sb_getcleansz(fs)) *
149*0a6a1f1dSLionel Sambuc 		lfs_sb_getifpb(fs);
150d65f6f70SBen Gras 
151d65f6f70SBen Gras 	/*
152d65f6f70SBen Gras 	 * We insert the new inodes at the head of the free list.
153d65f6f70SBen Gras 	 * Under normal circumstances, the free list is empty here,
154d65f6f70SBen Gras 	 * so we are also incidentally placing them at the end (which
155d65f6f70SBen Gras 	 * we must do if we are to keep them in order).
156d65f6f70SBen Gras 	 */
157d65f6f70SBen Gras 	LFS_GET_HEADFREE(fs, cip, cbp, &oldlast);
158d65f6f70SBen Gras 	LFS_PUT_HEADFREE(fs, cip, cbp, i);
159d65f6f70SBen Gras #ifdef DIAGNOSTIC
160*0a6a1f1dSLionel Sambuc 	if (lfs_sb_getfreehd(fs) == LFS_UNUSED_INUM)
161d65f6f70SBen Gras 		panic("inode 0 allocated [2]");
162d65f6f70SBen Gras #endif /* DIAGNOSTIC */
163*0a6a1f1dSLionel Sambuc 	xmax = i + lfs_sb_getifpb(fs);
164d65f6f70SBen Gras 
165*0a6a1f1dSLionel Sambuc 	if (fs->lfs_is64) {
166*0a6a1f1dSLionel Sambuc 		for (ifp64 = (IFILE64 *)bp->b_data; i < xmax; ++ifp64) {
167*0a6a1f1dSLionel Sambuc 			SET_BITMAP_FREE(fs, i);
168*0a6a1f1dSLionel Sambuc 			ifp64->if_version = 1;
169*0a6a1f1dSLionel Sambuc 			ifp64->if_daddr = LFS_UNUSED_DADDR;
170*0a6a1f1dSLionel Sambuc 			ifp64->if_nextfree = ++i;
171*0a6a1f1dSLionel Sambuc 		}
172*0a6a1f1dSLionel Sambuc 		ifp64--;
173*0a6a1f1dSLionel Sambuc 		ifp64->if_nextfree = oldlast;
174*0a6a1f1dSLionel Sambuc 	} else if (lfs_sb_getversion(fs) > 1) {
175*0a6a1f1dSLionel Sambuc 		for (ifp32 = (IFILE32 *)bp->b_data; i < xmax; ++ifp32) {
176*0a6a1f1dSLionel Sambuc 			SET_BITMAP_FREE(fs, i);
177*0a6a1f1dSLionel Sambuc 			ifp32->if_version = 1;
178*0a6a1f1dSLionel Sambuc 			ifp32->if_daddr = LFS_UNUSED_DADDR;
179*0a6a1f1dSLionel Sambuc 			ifp32->if_nextfree = ++i;
180*0a6a1f1dSLionel Sambuc 		}
181*0a6a1f1dSLionel Sambuc 		ifp32--;
182*0a6a1f1dSLionel Sambuc 		ifp32->if_nextfree = oldlast;
183*0a6a1f1dSLionel Sambuc 	} else {
184d65f6f70SBen Gras 		for (ifp_v1 = (IFILE_V1 *)bp->b_data; i < xmax; ++ifp_v1) {
185d65f6f70SBen Gras 			SET_BITMAP_FREE(fs, i);
186d65f6f70SBen Gras 			ifp_v1->if_version = 1;
187d65f6f70SBen Gras 			ifp_v1->if_daddr = LFS_UNUSED_DADDR;
188d65f6f70SBen Gras 			ifp_v1->if_nextfree = ++i;
189d65f6f70SBen Gras 		}
190d65f6f70SBen Gras 		ifp_v1--;
191d65f6f70SBen Gras 		ifp_v1->if_nextfree = oldlast;
192d65f6f70SBen Gras 	}
193d65f6f70SBen Gras 	LFS_PUT_TAILFREE(fs, cip, cbp, xmax - 1);
194d65f6f70SBen Gras 
195d65f6f70SBen Gras 	(void) LFS_BWRITE_LOG(bp); /* Ifile */
196d65f6f70SBen Gras 
197d65f6f70SBen Gras 	return 0;
198d65f6f70SBen Gras }
199d65f6f70SBen Gras 
200d65f6f70SBen Gras /* Allocate a new inode. */
201d65f6f70SBen Gras /* ARGSUSED */
202d65f6f70SBen Gras /* VOP_BWRITE 2i times */
203d65f6f70SBen Gras int
lfs_valloc(struct vnode * pvp,int mode,kauth_cred_t cred,ino_t * ino,int * gen)204d65f6f70SBen Gras lfs_valloc(struct vnode *pvp, int mode, kauth_cred_t cred,
205*0a6a1f1dSLionel Sambuc     ino_t *ino, int *gen)
206d65f6f70SBen Gras {
207d65f6f70SBen Gras 	struct lfs *fs;
208d65f6f70SBen Gras 	struct buf *bp, *cbp;
209*0a6a1f1dSLionel Sambuc 	IFILE *ifp;
210d65f6f70SBen Gras 	int error;
211d65f6f70SBen Gras 	CLEANERINFO *cip;
212d65f6f70SBen Gras 
213d65f6f70SBen Gras 	fs = VTOI(pvp)->i_lfs;
214d65f6f70SBen Gras 	if (fs->lfs_ronly)
215d65f6f70SBen Gras 		return EROFS;
216d65f6f70SBen Gras 
217d65f6f70SBen Gras 	ASSERT_NO_SEGLOCK(fs);
218d65f6f70SBen Gras 
219d65f6f70SBen Gras 	lfs_seglock(fs, SEGM_PROT);
220d65f6f70SBen Gras 
221d65f6f70SBen Gras 	/* Get the head of the freelist. */
222*0a6a1f1dSLionel Sambuc 	LFS_GET_HEADFREE(fs, cip, cbp, ino);
223*0a6a1f1dSLionel Sambuc 	KASSERT(*ino != LFS_UNUSED_INUM && *ino != LFS_IFILE_INUM);
224d65f6f70SBen Gras 
225*0a6a1f1dSLionel Sambuc 	DLOG((DLOG_ALLOC, "lfs_valloc: allocate inode %" PRId64 "\n",
226*0a6a1f1dSLionel Sambuc 	     *ino));
227d65f6f70SBen Gras 
228d65f6f70SBen Gras 	/*
229d65f6f70SBen Gras 	 * Remove the inode from the free list and write the new start
230d65f6f70SBen Gras 	 * of the free list into the superblock.
231d65f6f70SBen Gras 	 */
232*0a6a1f1dSLionel Sambuc 	CLR_BITMAP_FREE(fs, *ino);
233*0a6a1f1dSLionel Sambuc 	LFS_IENTRY(ifp, fs, *ino, bp);
234*0a6a1f1dSLionel Sambuc 	if (lfs_if_getdaddr(fs, ifp) != LFS_UNUSED_DADDR)
235*0a6a1f1dSLionel Sambuc 		panic("lfs_valloc: inuse inode %" PRId64 " on the free list",
236*0a6a1f1dSLionel Sambuc 		    *ino);
237*0a6a1f1dSLionel Sambuc 	LFS_PUT_HEADFREE(fs, cip, cbp, lfs_if_getnextfree(fs, ifp));
238*0a6a1f1dSLionel Sambuc 	DLOG((DLOG_ALLOC, "lfs_valloc: headfree %" PRId64 " -> %ju\n",
239*0a6a1f1dSLionel Sambuc 	     *ino, (uintmax_t)lfs_if_getnextfree(fs, ifp)));
240d65f6f70SBen Gras 
241*0a6a1f1dSLionel Sambuc 	/* version was updated by vfree */
242*0a6a1f1dSLionel Sambuc 	*gen = lfs_if_getversion(fs, ifp);
243d65f6f70SBen Gras 	brelse(bp, 0);
244d65f6f70SBen Gras 
245d65f6f70SBen Gras 	/* Extend IFILE so that the next lfs_valloc will succeed. */
246*0a6a1f1dSLionel Sambuc 	if (lfs_sb_getfreehd(fs) == LFS_UNUSED_INUM) {
247d65f6f70SBen Gras 		if ((error = lfs_extend_ifile(fs, cred)) != 0) {
248*0a6a1f1dSLionel Sambuc 			LFS_PUT_HEADFREE(fs, cip, cbp, *ino);
249d65f6f70SBen Gras 			lfs_segunlock(fs);
250d65f6f70SBen Gras 			return error;
251d65f6f70SBen Gras 		}
252d65f6f70SBen Gras 	}
253d65f6f70SBen Gras #ifdef DIAGNOSTIC
254*0a6a1f1dSLionel Sambuc 	if (lfs_sb_getfreehd(fs) == LFS_UNUSED_INUM)
255d65f6f70SBen Gras 		panic("inode 0 allocated [3]");
256d65f6f70SBen Gras #endif /* DIAGNOSTIC */
257d65f6f70SBen Gras 
258d65f6f70SBen Gras 	/* Set superblock modified bit and increment file count. */
259d65f6f70SBen Gras 	mutex_enter(&lfs_lock);
260d65f6f70SBen Gras 	fs->lfs_fmod = 1;
261d65f6f70SBen Gras 	mutex_exit(&lfs_lock);
262*0a6a1f1dSLionel Sambuc 	lfs_sb_addnfiles(fs, 1);
263d65f6f70SBen Gras 
264d65f6f70SBen Gras 	lfs_segunlock(fs);
265d65f6f70SBen Gras 
266*0a6a1f1dSLionel Sambuc 	return 0;
267d65f6f70SBen Gras }
268d65f6f70SBen Gras 
269d65f6f70SBen Gras /*
270*0a6a1f1dSLionel Sambuc  * Allocate a new inode with given inode number and version.
271d65f6f70SBen Gras  */
272d65f6f70SBen Gras int
lfs_valloc_fixed(struct lfs * fs,ino_t ino,int vers)273*0a6a1f1dSLionel Sambuc lfs_valloc_fixed(struct lfs *fs, ino_t ino, int vers)
274d65f6f70SBen Gras {
275*0a6a1f1dSLionel Sambuc 	IFILE *ifp;
276*0a6a1f1dSLionel Sambuc 	struct buf *bp, *cbp;
277*0a6a1f1dSLionel Sambuc 	ino_t headino, thisino, oldnext;
278*0a6a1f1dSLionel Sambuc 	CLEANERINFO *cip;
279d65f6f70SBen Gras 
280*0a6a1f1dSLionel Sambuc 	/* If the Ifile is too short to contain this inum, extend it */
281*0a6a1f1dSLionel Sambuc 	while (VTOI(fs->lfs_ivnode)->i_size <= (ino /
282*0a6a1f1dSLionel Sambuc 		lfs_sb_getifpb(fs) + lfs_sb_getcleansz(fs) + lfs_sb_getsegtabsz(fs))
283*0a6a1f1dSLionel Sambuc 		<< lfs_sb_getbshift(fs)) {
284*0a6a1f1dSLionel Sambuc 		lfs_extend_ifile(fs, NOCRED);
285d65f6f70SBen Gras 	}
286d65f6f70SBen Gras 
287*0a6a1f1dSLionel Sambuc 	LFS_IENTRY(ifp, fs, ino, bp);
288*0a6a1f1dSLionel Sambuc 	oldnext = lfs_if_getnextfree(fs, ifp);
289*0a6a1f1dSLionel Sambuc 	lfs_if_setversion(fs, ifp, vers);
290*0a6a1f1dSLionel Sambuc 	brelse(bp, 0);
291d65f6f70SBen Gras 
292*0a6a1f1dSLionel Sambuc 	LFS_GET_HEADFREE(fs, cip, cbp, &headino);
293*0a6a1f1dSLionel Sambuc 	if (headino == ino) {
294*0a6a1f1dSLionel Sambuc 		LFS_PUT_HEADFREE(fs, cip, cbp, oldnext);
295*0a6a1f1dSLionel Sambuc 	} else {
296*0a6a1f1dSLionel Sambuc 		ino_t nextfree;
297d65f6f70SBen Gras 
298*0a6a1f1dSLionel Sambuc 		thisino = headino;
299*0a6a1f1dSLionel Sambuc 		while (1) {
300*0a6a1f1dSLionel Sambuc 			LFS_IENTRY(ifp, fs, thisino, bp);
301*0a6a1f1dSLionel Sambuc 			nextfree = lfs_if_getnextfree(fs, ifp);
302*0a6a1f1dSLionel Sambuc 			if (nextfree == ino ||
303*0a6a1f1dSLionel Sambuc 			    nextfree == LFS_UNUSED_INUM)
304*0a6a1f1dSLionel Sambuc 				break;
305*0a6a1f1dSLionel Sambuc 			thisino = nextfree;
306*0a6a1f1dSLionel Sambuc 			brelse(bp, 0);
307*0a6a1f1dSLionel Sambuc 		}
308*0a6a1f1dSLionel Sambuc 		if (nextfree == LFS_UNUSED_INUM) {
309*0a6a1f1dSLionel Sambuc 			brelse(bp, 0);
310*0a6a1f1dSLionel Sambuc 			return ENOENT;
311*0a6a1f1dSLionel Sambuc 		}
312*0a6a1f1dSLionel Sambuc 		lfs_if_setnextfree(fs, ifp, oldnext);
313*0a6a1f1dSLionel Sambuc 		LFS_BWRITE_LOG(bp);
314d65f6f70SBen Gras 	}
315d65f6f70SBen Gras 
316*0a6a1f1dSLionel Sambuc 	return 0;
317d65f6f70SBen Gras }
318d65f6f70SBen Gras 
319d65f6f70SBen Gras #if 0
320d65f6f70SBen Gras /*
321d65f6f70SBen Gras  * Find the highest-numbered allocated inode.
322d65f6f70SBen Gras  * This will be used to shrink the Ifile.
323d65f6f70SBen Gras  */
324d65f6f70SBen Gras static inline ino_t
325d65f6f70SBen Gras lfs_last_alloc_ino(struct lfs *fs)
326d65f6f70SBen Gras {
327d65f6f70SBen Gras 	ino_t ino, maxino;
328d65f6f70SBen Gras 
329*0a6a1f1dSLionel Sambuc 	maxino = ((fs->lfs_ivnode->v_size >> lfs_sb_getbshift(fs)) -
330*0a6a1f1dSLionel Sambuc 		  lfs_sb_getcleansz(fs) - lfs_sb_getsegtabsz(fs)) * fs->lfs_ifpb;
331d65f6f70SBen Gras 	for (ino = maxino - 1; ino > LFS_UNUSED_INUM; --ino) {
332d65f6f70SBen Gras 		if (ISSET_BITMAP_FREE(fs, ino) == 0)
333d65f6f70SBen Gras 			break;
334d65f6f70SBen Gras 	}
335d65f6f70SBen Gras 	return ino;
336d65f6f70SBen Gras }
337d65f6f70SBen Gras #endif
338d65f6f70SBen Gras 
339d65f6f70SBen Gras /*
340d65f6f70SBen Gras  * Find the previous (next lowest numbered) free inode, if any.
341d65f6f70SBen Gras  * If there is none, return LFS_UNUSED_INUM.
342d65f6f70SBen Gras  */
343d65f6f70SBen Gras static inline ino_t
lfs_freelist_prev(struct lfs * fs,ino_t ino)344d65f6f70SBen Gras lfs_freelist_prev(struct lfs *fs, ino_t ino)
345d65f6f70SBen Gras {
346d65f6f70SBen Gras 	ino_t tino, bound, bb, freehdbb;
347d65f6f70SBen Gras 
348*0a6a1f1dSLionel Sambuc 	if (lfs_sb_getfreehd(fs) == LFS_UNUSED_INUM)	 /* No free inodes at all */
349d65f6f70SBen Gras 		return LFS_UNUSED_INUM;
350d65f6f70SBen Gras 
351d65f6f70SBen Gras 	/* Search our own word first */
352d65f6f70SBen Gras 	bound = ino & ~BMMASK;
353d65f6f70SBen Gras 	for (tino = ino - 1; tino >= bound && tino > LFS_UNUSED_INUM; tino--)
354d65f6f70SBen Gras 		if (ISSET_BITMAP_FREE(fs, tino))
355d65f6f70SBen Gras 			return tino;
356d65f6f70SBen Gras 	/* If there are no lower words to search, just return */
357d65f6f70SBen Gras 	if (ino >> BMSHIFT == 0)
358d65f6f70SBen Gras 		return LFS_UNUSED_INUM;
359d65f6f70SBen Gras 
360d65f6f70SBen Gras 	/*
361d65f6f70SBen Gras 	 * Find a word with a free inode in it.  We have to be a bit
362d65f6f70SBen Gras 	 * careful here since ino_t is unsigned.
363d65f6f70SBen Gras 	 */
364*0a6a1f1dSLionel Sambuc 	freehdbb = (lfs_sb_getfreehd(fs) >> BMSHIFT);
365d65f6f70SBen Gras 	for (bb = (ino >> BMSHIFT) - 1; bb >= freehdbb && bb > 0; --bb)
366d65f6f70SBen Gras 		if (fs->lfs_ino_bitmap[bb])
367d65f6f70SBen Gras 			break;
368d65f6f70SBen Gras 	if (fs->lfs_ino_bitmap[bb] == 0)
369d65f6f70SBen Gras 		return LFS_UNUSED_INUM;
370d65f6f70SBen Gras 
371d65f6f70SBen Gras 	/* Search the word we found */
372d65f6f70SBen Gras 	for (tino = (bb << BMSHIFT) | BMMASK; tino >= (bb << BMSHIFT) &&
373d65f6f70SBen Gras 	     tino > LFS_UNUSED_INUM; tino--)
374d65f6f70SBen Gras 		if (ISSET_BITMAP_FREE(fs, tino))
375d65f6f70SBen Gras 			break;
376d65f6f70SBen Gras 
377d65f6f70SBen Gras 	if (tino <= LFS_IFILE_INUM)
378d65f6f70SBen Gras 		tino = LFS_UNUSED_INUM;
379d65f6f70SBen Gras 
380d65f6f70SBen Gras 	return tino;
381d65f6f70SBen Gras }
382d65f6f70SBen Gras 
383d65f6f70SBen Gras /* Free an inode. */
384d65f6f70SBen Gras /* ARGUSED */
385d65f6f70SBen Gras /* VOP_BWRITE 2i times */
386d65f6f70SBen Gras int
lfs_vfree(struct vnode * vp,ino_t ino,int mode)387d65f6f70SBen Gras lfs_vfree(struct vnode *vp, ino_t ino, int mode)
388d65f6f70SBen Gras {
389d65f6f70SBen Gras 	SEGUSE *sup;
390d65f6f70SBen Gras 	CLEANERINFO *cip;
391d65f6f70SBen Gras 	struct buf *cbp, *bp;
392*0a6a1f1dSLionel Sambuc 	IFILE *ifp;
393d65f6f70SBen Gras 	struct inode *ip;
394d65f6f70SBen Gras 	struct lfs *fs;
395d65f6f70SBen Gras 	daddr_t old_iaddr;
396d65f6f70SBen Gras 	ino_t otail;
397d65f6f70SBen Gras 
398d65f6f70SBen Gras 	/* Get the inode number and file system. */
399d65f6f70SBen Gras 	ip = VTOI(vp);
400d65f6f70SBen Gras 	fs = ip->i_lfs;
401d65f6f70SBen Gras 	ino = ip->i_number;
402d65f6f70SBen Gras 
403d65f6f70SBen Gras 	ASSERT_NO_SEGLOCK(fs);
404d65f6f70SBen Gras 	DLOG((DLOG_ALLOC, "lfs_vfree: free ino %lld\n", (long long)ino));
405d65f6f70SBen Gras 
406d65f6f70SBen Gras 	/* Drain of pending writes */
407d65f6f70SBen Gras 	mutex_enter(vp->v_interlock);
408*0a6a1f1dSLionel Sambuc 	while (lfs_sb_getversion(fs) > 1 && WRITEINPROG(vp)) {
409d65f6f70SBen Gras 		cv_wait(&vp->v_cv, vp->v_interlock);
410d65f6f70SBen Gras 	}
411d65f6f70SBen Gras 	mutex_exit(vp->v_interlock);
412d65f6f70SBen Gras 
413d65f6f70SBen Gras 	lfs_seglock(fs, SEGM_PROT);
414d65f6f70SBen Gras 
415d65f6f70SBen Gras 	lfs_unmark_vnode(vp);
416d65f6f70SBen Gras 	mutex_enter(&lfs_lock);
417d65f6f70SBen Gras 	if (vp->v_uflag & VU_DIROP) {
418d65f6f70SBen Gras 		vp->v_uflag &= ~VU_DIROP;
419d65f6f70SBen Gras 		--lfs_dirvcount;
420d65f6f70SBen Gras 		--fs->lfs_dirvcount;
421d65f6f70SBen Gras 		TAILQ_REMOVE(&fs->lfs_dchainhd, ip, i_lfs_dchain);
422d65f6f70SBen Gras 		wakeup(&fs->lfs_dirvcount);
423d65f6f70SBen Gras 		wakeup(&lfs_dirvcount);
424d65f6f70SBen Gras 		mutex_exit(&lfs_lock);
425*0a6a1f1dSLionel Sambuc 		vrele(vp);
426d65f6f70SBen Gras 
427d65f6f70SBen Gras 		/*
428d65f6f70SBen Gras 		 * If this inode is not going to be written any more, any
429d65f6f70SBen Gras 		 * segment accounting left over from its truncation needs
430d65f6f70SBen Gras 		 * to occur at the end of the next dirops flush.  Attach
431d65f6f70SBen Gras 		 * them to the fs-wide list for that purpose.
432d65f6f70SBen Gras 		 */
433d65f6f70SBen Gras 		if (LIST_FIRST(&ip->i_lfs_segdhd) != NULL) {
434d65f6f70SBen Gras 			struct segdelta *sd;
435d65f6f70SBen Gras 
436d65f6f70SBen Gras 			while((sd = LIST_FIRST(&ip->i_lfs_segdhd)) != NULL) {
437d65f6f70SBen Gras 				LIST_REMOVE(sd, list);
438d65f6f70SBen Gras 				LIST_INSERT_HEAD(&fs->lfs_segdhd, sd, list);
439d65f6f70SBen Gras 			}
440d65f6f70SBen Gras 		}
441d65f6f70SBen Gras 	} else {
442d65f6f70SBen Gras 		/*
443d65f6f70SBen Gras 		 * If it's not a dirop, we can finalize right away.
444d65f6f70SBen Gras 		 */
445d65f6f70SBen Gras 		mutex_exit(&lfs_lock);
446d65f6f70SBen Gras 		lfs_finalize_ino_seguse(fs, ip);
447d65f6f70SBen Gras 	}
448d65f6f70SBen Gras 
449d65f6f70SBen Gras 	mutex_enter(&lfs_lock);
450d65f6f70SBen Gras 	LFS_CLR_UINO(ip, IN_ACCESSED|IN_CLEANING|IN_MODIFIED);
451d65f6f70SBen Gras 	mutex_exit(&lfs_lock);
452d65f6f70SBen Gras 	ip->i_flag &= ~IN_ALLMOD;
453d65f6f70SBen Gras 	ip->i_lfs_iflags |= LFSI_DELETED;
454d65f6f70SBen Gras 
455d65f6f70SBen Gras 	/*
456d65f6f70SBen Gras 	 * Set the ifile's inode entry to unused, increment its version number
457d65f6f70SBen Gras 	 * and link it onto the free chain.
458d65f6f70SBen Gras 	 */
459d65f6f70SBen Gras 	SET_BITMAP_FREE(fs, ino);
460d65f6f70SBen Gras 	LFS_IENTRY(ifp, fs, ino, bp);
461*0a6a1f1dSLionel Sambuc 	old_iaddr = lfs_if_getdaddr(fs, ifp);
462*0a6a1f1dSLionel Sambuc 	lfs_if_setdaddr(fs, ifp, LFS_UNUSED_DADDR);
463*0a6a1f1dSLionel Sambuc 	lfs_if_setversion(fs, ifp, lfs_if_getversion(fs, ifp) + 1);
464*0a6a1f1dSLionel Sambuc 	if (lfs_sb_getversion(fs) == 1) {
465*0a6a1f1dSLionel Sambuc 		ino_t nextfree;
466*0a6a1f1dSLionel Sambuc 
467*0a6a1f1dSLionel Sambuc 		LFS_GET_HEADFREE(fs, cip, cbp, &nextfree);
468*0a6a1f1dSLionel Sambuc 		lfs_if_setnextfree(fs, ifp, nextfree);
469d65f6f70SBen Gras 		LFS_PUT_HEADFREE(fs, cip, cbp, ino);
470d65f6f70SBen Gras 		(void) LFS_BWRITE_LOG(bp); /* Ifile */
471d65f6f70SBen Gras 	} else {
472d65f6f70SBen Gras 		ino_t tino, onf;
473d65f6f70SBen Gras 
474*0a6a1f1dSLionel Sambuc 		lfs_if_setnextfree(fs, ifp, LFS_UNUSED_INUM);
475d65f6f70SBen Gras 		(void) LFS_BWRITE_LOG(bp); /* Ifile */
476d65f6f70SBen Gras 
477d65f6f70SBen Gras 		tino = lfs_freelist_prev(fs, ino);
478d65f6f70SBen Gras 		if (tino == LFS_UNUSED_INUM) {
479*0a6a1f1dSLionel Sambuc 			ino_t nextfree;
480*0a6a1f1dSLionel Sambuc 
481d65f6f70SBen Gras 			/* Nothing free below us, put us on the head */
482d65f6f70SBen Gras 			LFS_IENTRY(ifp, fs, ino, bp);
483*0a6a1f1dSLionel Sambuc 			LFS_GET_HEADFREE(fs, cip, cbp, &nextfree);
484*0a6a1f1dSLionel Sambuc 			lfs_if_setnextfree(fs, ifp, nextfree);
485d65f6f70SBen Gras 			LFS_PUT_HEADFREE(fs, cip, cbp, ino);
486d65f6f70SBen Gras 			DLOG((DLOG_ALLOC, "lfs_vfree: headfree %lld -> %lld\n",
487*0a6a1f1dSLionel Sambuc 			     (long long)nextfree, (long long)ino));
488d65f6f70SBen Gras 			LFS_BWRITE_LOG(bp); /* Ifile */
489d65f6f70SBen Gras 
490d65f6f70SBen Gras 			/* If the list was empty, set tail too */
491d65f6f70SBen Gras 			LFS_GET_TAILFREE(fs, cip, cbp, &otail);
492d65f6f70SBen Gras 			if (otail == LFS_UNUSED_INUM) {
493d65f6f70SBen Gras 				LFS_PUT_TAILFREE(fs, cip, cbp, ino);
494d65f6f70SBen Gras 				DLOG((DLOG_ALLOC, "lfs_vfree: tailfree %lld "
495d65f6f70SBen Gras 				      "-> %lld\n", (long long)otail,
496d65f6f70SBen Gras 				      (long long)ino));
497d65f6f70SBen Gras 			}
498d65f6f70SBen Gras 		} else {
499d65f6f70SBen Gras 			/*
500d65f6f70SBen Gras 			 * Insert this inode into the list after tino.
501d65f6f70SBen Gras 			 * We hold the segment lock so we don't have to
502d65f6f70SBen Gras 			 * worry about blocks being written out of order.
503d65f6f70SBen Gras 			 */
504d65f6f70SBen Gras 			DLOG((DLOG_ALLOC, "lfs_vfree: insert ino %lld "
505d65f6f70SBen Gras 			      " after %lld\n", ino, tino));
506d65f6f70SBen Gras 
507d65f6f70SBen Gras 			LFS_IENTRY(ifp, fs, tino, bp);
508*0a6a1f1dSLionel Sambuc 			onf = lfs_if_getnextfree(fs, ifp);
509*0a6a1f1dSLionel Sambuc 			lfs_if_setnextfree(fs, ifp, ino);
510d65f6f70SBen Gras 			LFS_BWRITE_LOG(bp);	/* Ifile */
511d65f6f70SBen Gras 
512d65f6f70SBen Gras 			LFS_IENTRY(ifp, fs, ino, bp);
513*0a6a1f1dSLionel Sambuc 			lfs_if_setnextfree(fs, ifp, onf);
514d65f6f70SBen Gras 			LFS_BWRITE_LOG(bp);	/* Ifile */
515d65f6f70SBen Gras 
516d65f6f70SBen Gras 			/* If we're last, put us on the tail */
517d65f6f70SBen Gras 			if (onf == LFS_UNUSED_INUM) {
518d65f6f70SBen Gras 				LFS_GET_TAILFREE(fs, cip, cbp, &otail);
519d65f6f70SBen Gras 				LFS_PUT_TAILFREE(fs, cip, cbp, ino);
520d65f6f70SBen Gras 				DLOG((DLOG_ALLOC, "lfs_vfree: tailfree %lld "
521d65f6f70SBen Gras 				      "-> %lld\n", (long long)otail,
522d65f6f70SBen Gras 				      (long long)ino));
523d65f6f70SBen Gras 			}
524d65f6f70SBen Gras 		}
525d65f6f70SBen Gras 	}
526d65f6f70SBen Gras #ifdef DIAGNOSTIC
527d65f6f70SBen Gras 	if (ino == LFS_UNUSED_INUM) {
528d65f6f70SBen Gras 		panic("inode 0 freed");
529d65f6f70SBen Gras 	}
530d65f6f70SBen Gras #endif /* DIAGNOSTIC */
531d65f6f70SBen Gras 	if (old_iaddr != LFS_UNUSED_DADDR) {
53284d9c625SLionel Sambuc 		LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, old_iaddr), bp);
533d65f6f70SBen Gras #ifdef DIAGNOSTIC
534*0a6a1f1dSLionel Sambuc 		if (sup->su_nbytes < DINOSIZE(fs)) {
535d65f6f70SBen Gras 			printf("lfs_vfree: negative byte count"
536d65f6f70SBen Gras 			       " (segment %" PRIu32 " short by %d)\n",
53784d9c625SLionel Sambuc 			       lfs_dtosn(fs, old_iaddr),
538*0a6a1f1dSLionel Sambuc 			       (int)DINOSIZE(fs) -
539d65f6f70SBen Gras 				    sup->su_nbytes);
540d65f6f70SBen Gras 			panic("lfs_vfree: negative byte count");
541*0a6a1f1dSLionel Sambuc 			sup->su_nbytes = DINOSIZE(fs);
542d65f6f70SBen Gras 		}
543d65f6f70SBen Gras #endif
544*0a6a1f1dSLionel Sambuc 		sup->su_nbytes -= DINOSIZE(fs);
54584d9c625SLionel Sambuc 		LFS_WRITESEGENTRY(sup, fs, lfs_dtosn(fs, old_iaddr), bp); /* Ifile */
546d65f6f70SBen Gras 	}
547d65f6f70SBen Gras 
548d65f6f70SBen Gras 	/* Set superblock modified bit and decrement file count. */
549d65f6f70SBen Gras 	mutex_enter(&lfs_lock);
550d65f6f70SBen Gras 	fs->lfs_fmod = 1;
551d65f6f70SBen Gras 	mutex_exit(&lfs_lock);
552*0a6a1f1dSLionel Sambuc 	lfs_sb_subnfiles(fs, 1);
553d65f6f70SBen Gras 
554d65f6f70SBen Gras 	lfs_segunlock(fs);
555d65f6f70SBen Gras 
556d65f6f70SBen Gras 	return (0);
557d65f6f70SBen Gras }
558d65f6f70SBen Gras 
559d65f6f70SBen Gras /*
560d65f6f70SBen Gras  * Sort the freelist and set up the free-inode bitmap.
561d65f6f70SBen Gras  * To be called by lfs_mountfs().
562d65f6f70SBen Gras  */
563d65f6f70SBen Gras void
lfs_order_freelist(struct lfs * fs)564d65f6f70SBen Gras lfs_order_freelist(struct lfs *fs)
565d65f6f70SBen Gras {
566d65f6f70SBen Gras 	CLEANERINFO *cip;
567d65f6f70SBen Gras 	IFILE *ifp = NULL;
568d65f6f70SBen Gras 	struct buf *bp;
569d65f6f70SBen Gras 	ino_t ino, firstino, lastino, maxino;
570d65f6f70SBen Gras #ifdef notyet
571d65f6f70SBen Gras 	struct vnode *vp;
572d65f6f70SBen Gras #endif
573d65f6f70SBen Gras 
574d65f6f70SBen Gras 	ASSERT_NO_SEGLOCK(fs);
575d65f6f70SBen Gras 	lfs_seglock(fs, SEGM_PROT);
576d65f6f70SBen Gras 
577*0a6a1f1dSLionel Sambuc 	maxino = ((fs->lfs_ivnode->v_size >> lfs_sb_getbshift(fs)) -
578*0a6a1f1dSLionel Sambuc 		  lfs_sb_getcleansz(fs) - lfs_sb_getsegtabsz(fs)) * lfs_sb_getifpb(fs);
579*0a6a1f1dSLionel Sambuc 	fs->lfs_ino_bitmap =
580d65f6f70SBen Gras 		malloc(((maxino + BMMASK) >> BMSHIFT) * sizeof(lfs_bm_t),
581d65f6f70SBen Gras 		       M_SEGMENT, M_WAITOK | M_ZERO);
582d65f6f70SBen Gras 	KASSERT(fs->lfs_ino_bitmap != NULL);
583d65f6f70SBen Gras 
584d65f6f70SBen Gras 	firstino = lastino = LFS_UNUSED_INUM;
585d65f6f70SBen Gras 	for (ino = 0; ino < maxino; ino++) {
586*0a6a1f1dSLionel Sambuc 		if (ino % lfs_sb_getifpb(fs) == 0)
587d65f6f70SBen Gras 			LFS_IENTRY(ifp, fs, ino, bp);
588d65f6f70SBen Gras 		else
589*0a6a1f1dSLionel Sambuc 			LFS_IENTRY_NEXT(ifp, fs);
590d65f6f70SBen Gras 
591d65f6f70SBen Gras 		/* Don't put zero or ifile on the free list */
592d65f6f70SBen Gras 		if (ino == LFS_UNUSED_INUM || ino == LFS_IFILE_INUM)
593d65f6f70SBen Gras 			continue;
594d65f6f70SBen Gras 
595d65f6f70SBen Gras #ifdef notyet
596d65f6f70SBen Gras 		/* Address orphaned files */
597*0a6a1f1dSLionel Sambuc 		if (lfs_if_getnextfree(fs, ifp) == LFS_ORPHAN_NEXTFREE &&
598d65f6f70SBen Gras 		    VFS_VGET(fs->lfs_ivnode->v_mount, ino, &vp) == 0) {
599*0a6a1f1dSLionel Sambuc 			unsigned segno;
600*0a6a1f1dSLionel Sambuc 
601*0a6a1f1dSLionel Sambuc 			segno = lfs_dtosn(fs, lfs_if_getdaddr(fs, ifp));
602d65f6f70SBen Gras 			lfs_truncate(vp, 0, 0, NOCRED);
603d65f6f70SBen Gras 			vput(vp);
604*0a6a1f1dSLionel Sambuc 			LFS_SEGENTRY(sup, fs, segno, bp);
605*0a6a1f1dSLionel Sambuc 			KASSERT(sup->su_nbytes >= LFS_DINODE1_SIZE);
606*0a6a1f1dSLionel Sambuc 			sup->su_nbytes -= LFS_DINODE1_SIZE;
607*0a6a1f1dSLionel Sambuc 			LFS_WRITESEGENTRY(sup, fs, segno, bp);
608d65f6f70SBen Gras 
609d65f6f70SBen Gras 			/* Set up to fall through to next section */
610*0a6a1f1dSLionel Sambuc 			lfs_if_setdaddr(fs, ifp, LFS_UNUSED_DADDR);
611d65f6f70SBen Gras 			LFS_BWRITE_LOG(bp);
612d65f6f70SBen Gras 			LFS_IENTRY(ifp, fs, ino, bp);
613d65f6f70SBen Gras 		}
614d65f6f70SBen Gras #endif
615d65f6f70SBen Gras 
616*0a6a1f1dSLionel Sambuc 		if (lfs_if_getdaddr(fs, ifp) == LFS_UNUSED_DADDR) {
617d65f6f70SBen Gras 			if (firstino == LFS_UNUSED_INUM)
618d65f6f70SBen Gras 				firstino = ino;
619d65f6f70SBen Gras 			else {
620d65f6f70SBen Gras 				brelse(bp, 0);
621d65f6f70SBen Gras 
622d65f6f70SBen Gras 				LFS_IENTRY(ifp, fs, lastino, bp);
623*0a6a1f1dSLionel Sambuc 				lfs_if_setnextfree(fs, ifp, ino);
624d65f6f70SBen Gras 				LFS_BWRITE_LOG(bp);
625d65f6f70SBen Gras 
626d65f6f70SBen Gras 				LFS_IENTRY(ifp, fs, ino, bp);
627d65f6f70SBen Gras 			}
628d65f6f70SBen Gras 			lastino = ino;
629d65f6f70SBen Gras 
630d65f6f70SBen Gras 			SET_BITMAP_FREE(fs, ino);
631d65f6f70SBen Gras 		}
632d65f6f70SBen Gras 
633*0a6a1f1dSLionel Sambuc 		if ((ino + 1) % lfs_sb_getifpb(fs) == 0)
634d65f6f70SBen Gras 			brelse(bp, 0);
635d65f6f70SBen Gras 	}
636d65f6f70SBen Gras 
637d65f6f70SBen Gras 	LFS_PUT_HEADFREE(fs, cip, bp, firstino);
638d65f6f70SBen Gras 	LFS_PUT_TAILFREE(fs, cip, bp, lastino);
639d65f6f70SBen Gras 
640d65f6f70SBen Gras 	lfs_segunlock(fs);
641d65f6f70SBen Gras }
642d65f6f70SBen Gras 
643d65f6f70SBen Gras void
lfs_orphan(struct lfs * fs,ino_t ino)644d65f6f70SBen Gras lfs_orphan(struct lfs *fs, ino_t ino)
645d65f6f70SBen Gras {
646d65f6f70SBen Gras 	IFILE *ifp;
647d65f6f70SBen Gras 	struct buf *bp;
648d65f6f70SBen Gras 
649d65f6f70SBen Gras 	LFS_IENTRY(ifp, fs, ino, bp);
650*0a6a1f1dSLionel Sambuc 	lfs_if_setnextfree(fs, ifp, LFS_ORPHAN_NEXTFREE);
651d65f6f70SBen Gras 	LFS_BWRITE_LOG(bp);
652d65f6f70SBen Gras }
653