xref: /minix3/sys/ufs/lfs/lfs_syscalls.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: lfs_syscalls.c,v 1.170 2015/09/01 06:08:37 dholland Exp $	*/
2d65f6f70SBen Gras 
3d65f6f70SBen Gras /*-
4d65f6f70SBen Gras  * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2007, 2007, 2008
5d65f6f70SBen Gras  *    The NetBSD Foundation, Inc.
6d65f6f70SBen Gras  * All rights reserved.
7d65f6f70SBen Gras  *
8d65f6f70SBen Gras  * This code is derived from software contributed to The NetBSD Foundation
9d65f6f70SBen Gras  * by Konrad E. Schroder <perseant@hhhh.org>.
10d65f6f70SBen Gras  *
11d65f6f70SBen Gras  * Redistribution and use in source and binary forms, with or without
12d65f6f70SBen Gras  * modification, are permitted provided that the following conditions
13d65f6f70SBen Gras  * are met:
14d65f6f70SBen Gras  * 1. Redistributions of source code must retain the above copyright
15d65f6f70SBen Gras  *    notice, this list of conditions and the following disclaimer.
16d65f6f70SBen Gras  * 2. Redistributions in binary form must reproduce the above copyright
17d65f6f70SBen Gras  *    notice, this list of conditions and the following disclaimer in the
18d65f6f70SBen Gras  *    documentation and/or other materials provided with the distribution.
19d65f6f70SBen Gras  *
20d65f6f70SBen Gras  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21d65f6f70SBen Gras  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22d65f6f70SBen Gras  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23d65f6f70SBen Gras  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24d65f6f70SBen Gras  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25d65f6f70SBen Gras  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26d65f6f70SBen Gras  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27d65f6f70SBen Gras  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28d65f6f70SBen Gras  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29d65f6f70SBen Gras  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30d65f6f70SBen Gras  * POSSIBILITY OF SUCH DAMAGE.
31d65f6f70SBen Gras  */
32d65f6f70SBen Gras /*-
33d65f6f70SBen Gras  * Copyright (c) 1991, 1993, 1994
34d65f6f70SBen Gras  *	The Regents of the University of California.  All rights reserved.
35d65f6f70SBen Gras  *
36d65f6f70SBen Gras  * Redistribution and use in source and binary forms, with or without
37d65f6f70SBen Gras  * modification, are permitted provided that the following conditions
38d65f6f70SBen Gras  * are met:
39d65f6f70SBen Gras  * 1. Redistributions of source code must retain the above copyright
40d65f6f70SBen Gras  *    notice, this list of conditions and the following disclaimer.
41d65f6f70SBen Gras  * 2. Redistributions in binary form must reproduce the above copyright
42d65f6f70SBen Gras  *    notice, this list of conditions and the following disclaimer in the
43d65f6f70SBen Gras  *    documentation and/or other materials provided with the distribution.
44d65f6f70SBen Gras  * 3. Neither the name of the University nor the names of its contributors
45d65f6f70SBen Gras  *    may be used to endorse or promote products derived from this software
46d65f6f70SBen Gras  *    without specific prior written permission.
47d65f6f70SBen Gras  *
48d65f6f70SBen Gras  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49d65f6f70SBen Gras  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50d65f6f70SBen Gras  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51d65f6f70SBen Gras  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52d65f6f70SBen Gras  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53d65f6f70SBen Gras  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54d65f6f70SBen Gras  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55d65f6f70SBen Gras  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56d65f6f70SBen Gras  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57d65f6f70SBen Gras  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58d65f6f70SBen Gras  * SUCH DAMAGE.
59d65f6f70SBen Gras  *
60d65f6f70SBen Gras  *	@(#)lfs_syscalls.c	8.10 (Berkeley) 5/14/95
61d65f6f70SBen Gras  */
62d65f6f70SBen Gras 
63d65f6f70SBen Gras #include <sys/cdefs.h>
64*0a6a1f1dSLionel Sambuc __KERNEL_RCSID(0, "$NetBSD: lfs_syscalls.c,v 1.170 2015/09/01 06:08:37 dholland Exp $");
65d65f6f70SBen Gras 
66d65f6f70SBen Gras #ifndef LFS
67d65f6f70SBen Gras # define LFS		/* for prototypes in syscallargs.h */
68d65f6f70SBen Gras #endif
69d65f6f70SBen Gras 
70d65f6f70SBen Gras #include <sys/param.h>
71d65f6f70SBen Gras #include <sys/systm.h>
72d65f6f70SBen Gras #include <sys/proc.h>
73d65f6f70SBen Gras #include <sys/buf.h>
74d65f6f70SBen Gras #include <sys/mount.h>
75d65f6f70SBen Gras #include <sys/vnode.h>
76d65f6f70SBen Gras #include <sys/kernel.h>
77d65f6f70SBen Gras #include <sys/kauth.h>
78d65f6f70SBen Gras #include <sys/syscallargs.h>
79d65f6f70SBen Gras 
8084d9c625SLionel Sambuc #include <ufs/lfs/ulfs_inode.h>
8184d9c625SLionel Sambuc #include <ufs/lfs/ulfsmount.h>
8284d9c625SLionel Sambuc #include <ufs/lfs/ulfs_extern.h>
83d65f6f70SBen Gras 
84d65f6f70SBen Gras #include <ufs/lfs/lfs.h>
85*0a6a1f1dSLionel Sambuc #include <ufs/lfs/lfs_accessors.h>
8684d9c625SLionel Sambuc #include <ufs/lfs/lfs_kernel.h>
87d65f6f70SBen Gras #include <ufs/lfs/lfs_extern.h>
88d65f6f70SBen Gras 
89*0a6a1f1dSLionel Sambuc static int lfs_fastvget(struct mount *, ino_t, BLOCK_INFO *, int,
90*0a6a1f1dSLionel Sambuc     struct vnode **);
91*0a6a1f1dSLionel Sambuc static struct buf *lfs_fakebuf(struct lfs *, struct vnode *, daddr_t,
92*0a6a1f1dSLionel Sambuc     size_t, void *);
93d65f6f70SBen Gras 
94d65f6f70SBen Gras /*
95d65f6f70SBen Gras  * sys_lfs_markv:
96d65f6f70SBen Gras  *
97d65f6f70SBen Gras  * This will mark inodes and blocks dirty, so they are written into the log.
98d65f6f70SBen Gras  * It will block until all the blocks have been written.  The segment create
99d65f6f70SBen Gras  * time passed in the block_info and inode_info structures is used to decide
100d65f6f70SBen Gras  * if the data is valid for each block (in case some process dirtied a block
101d65f6f70SBen Gras  * or inode that is being cleaned between the determination that a block is
102d65f6f70SBen Gras  * live and the lfs_markv call).
103d65f6f70SBen Gras  *
104d65f6f70SBen Gras  *  0 on success
105d65f6f70SBen Gras  * -1/errno is return on error.
106d65f6f70SBen Gras  */
107d65f6f70SBen Gras #ifdef USE_64BIT_SYSCALLS
108d65f6f70SBen Gras int
sys_lfs_markv(struct lwp * l,const struct sys_lfs_markv_args * uap,register_t * retval)109d65f6f70SBen Gras sys_lfs_markv(struct lwp *l, const struct sys_lfs_markv_args *uap, register_t *retval)
110d65f6f70SBen Gras {
111d65f6f70SBen Gras 	/* {
112d65f6f70SBen Gras 		syscallarg(fsid_t *) fsidp;
113d65f6f70SBen Gras 		syscallarg(struct block_info *) blkiov;
114d65f6f70SBen Gras 		syscallarg(int) blkcnt;
115d65f6f70SBen Gras 	} */
116d65f6f70SBen Gras 	BLOCK_INFO *blkiov;
117d65f6f70SBen Gras 	int blkcnt, error;
118d65f6f70SBen Gras 	fsid_t fsid;
119d65f6f70SBen Gras 	struct lfs *fs;
120d65f6f70SBen Gras 	struct mount *mntp;
121d65f6f70SBen Gras 
122d65f6f70SBen Gras 	if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0)
123d65f6f70SBen Gras 		return (error);
124d65f6f70SBen Gras 
125d65f6f70SBen Gras 	if ((mntp = vfs_getvfs(fsidp)) == NULL)
126d65f6f70SBen Gras 		return (ENOENT);
12784d9c625SLionel Sambuc 	fs = VFSTOULFS(mntp)->um_lfs;
128d65f6f70SBen Gras 
129d65f6f70SBen Gras 	blkcnt = SCARG(uap, blkcnt);
130d65f6f70SBen Gras 	if ((u_int) blkcnt > LFS_MARKV_MAXBLKCNT)
131d65f6f70SBen Gras 		return (EINVAL);
132d65f6f70SBen Gras 
133d65f6f70SBen Gras 	KERNEL_LOCK(1, NULL);
134d65f6f70SBen Gras 	blkiov = lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO), LFS_NB_BLKIOV);
135d65f6f70SBen Gras 	if ((error = copyin(SCARG(uap, blkiov), blkiov,
136d65f6f70SBen Gras 			    blkcnt * sizeof(BLOCK_INFO))) != 0)
137d65f6f70SBen Gras 		goto out;
138d65f6f70SBen Gras 
139d65f6f70SBen Gras 	if ((error = lfs_markv(p, &fsid, blkiov, blkcnt)) == 0)
140d65f6f70SBen Gras 		copyout(blkiov, SCARG(uap, blkiov),
141d65f6f70SBen Gras 			blkcnt * sizeof(BLOCK_INFO));
142d65f6f70SBen Gras     out:
143d65f6f70SBen Gras 	lfs_free(fs, blkiov, LFS_NB_BLKIOV);
144d65f6f70SBen Gras 	KERNEL_UNLOCK_ONE(NULL);
145d65f6f70SBen Gras 	return error;
146d65f6f70SBen Gras }
147d65f6f70SBen Gras #else
148d65f6f70SBen Gras int
sys_lfs_markv(struct lwp * l,const struct sys_lfs_markv_args * uap,register_t * retval)149d65f6f70SBen Gras sys_lfs_markv(struct lwp *l, const struct sys_lfs_markv_args *uap, register_t *retval)
150d65f6f70SBen Gras {
151d65f6f70SBen Gras 	/* {
152d65f6f70SBen Gras 		syscallarg(fsid_t *) fsidp;
153d65f6f70SBen Gras 		syscallarg(struct block_info *) blkiov;
154d65f6f70SBen Gras 		syscallarg(int) blkcnt;
155d65f6f70SBen Gras 	} */
156d65f6f70SBen Gras 	BLOCK_INFO *blkiov;
157d65f6f70SBen Gras 	BLOCK_INFO_15 *blkiov15;
158d65f6f70SBen Gras 	int i, blkcnt, error;
159d65f6f70SBen Gras 	fsid_t fsid;
160d65f6f70SBen Gras 	struct lfs *fs;
161d65f6f70SBen Gras 	struct mount *mntp;
162d65f6f70SBen Gras 
163d65f6f70SBen Gras 	if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0)
164d65f6f70SBen Gras 		return (error);
165d65f6f70SBen Gras 
166d65f6f70SBen Gras 	if ((mntp = vfs_getvfs(&fsid)) == NULL)
167d65f6f70SBen Gras 		return (ENOENT);
16884d9c625SLionel Sambuc 	fs = VFSTOULFS(mntp)->um_lfs;
169d65f6f70SBen Gras 
170d65f6f70SBen Gras 	blkcnt = SCARG(uap, blkcnt);
171d65f6f70SBen Gras 	if ((u_int) blkcnt > LFS_MARKV_MAXBLKCNT)
172d65f6f70SBen Gras 		return (EINVAL);
173d65f6f70SBen Gras 
174d65f6f70SBen Gras 	KERNEL_LOCK(1, NULL);
175d65f6f70SBen Gras 	blkiov = lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO), LFS_NB_BLKIOV);
176d65f6f70SBen Gras 	blkiov15 = lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO_15), LFS_NB_BLKIOV);
177d65f6f70SBen Gras 	if ((error = copyin(SCARG(uap, blkiov), blkiov15,
178d65f6f70SBen Gras 			    blkcnt * sizeof(BLOCK_INFO_15))) != 0)
179d65f6f70SBen Gras 		goto out;
180d65f6f70SBen Gras 
181d65f6f70SBen Gras 	for (i = 0; i < blkcnt; i++) {
182d65f6f70SBen Gras 		blkiov[i].bi_inode     = blkiov15[i].bi_inode;
183d65f6f70SBen Gras 		blkiov[i].bi_lbn       = blkiov15[i].bi_lbn;
184d65f6f70SBen Gras 		blkiov[i].bi_daddr     = blkiov15[i].bi_daddr;
185d65f6f70SBen Gras 		blkiov[i].bi_segcreate = blkiov15[i].bi_segcreate;
186d65f6f70SBen Gras 		blkiov[i].bi_version   = blkiov15[i].bi_version;
187d65f6f70SBen Gras 		blkiov[i].bi_bp	       = blkiov15[i].bi_bp;
188d65f6f70SBen Gras 		blkiov[i].bi_size      = blkiov15[i].bi_size;
189d65f6f70SBen Gras 	}
190d65f6f70SBen Gras 
191*0a6a1f1dSLionel Sambuc 	if ((error = lfs_markv(l, &fsid, blkiov, blkcnt)) == 0) {
192d65f6f70SBen Gras 		for (i = 0; i < blkcnt; i++) {
193d65f6f70SBen Gras 			blkiov15[i].bi_inode	 = blkiov[i].bi_inode;
194d65f6f70SBen Gras 			blkiov15[i].bi_lbn	 = blkiov[i].bi_lbn;
195d65f6f70SBen Gras 			blkiov15[i].bi_daddr	 = blkiov[i].bi_daddr;
196d65f6f70SBen Gras 			blkiov15[i].bi_segcreate = blkiov[i].bi_segcreate;
197d65f6f70SBen Gras 			blkiov15[i].bi_version	 = blkiov[i].bi_version;
198d65f6f70SBen Gras 			blkiov15[i].bi_bp	 = blkiov[i].bi_bp;
199d65f6f70SBen Gras 			blkiov15[i].bi_size	 = blkiov[i].bi_size;
200d65f6f70SBen Gras 		}
201d65f6f70SBen Gras 		copyout(blkiov15, SCARG(uap, blkiov),
202d65f6f70SBen Gras 			blkcnt * sizeof(BLOCK_INFO_15));
203d65f6f70SBen Gras 	}
204d65f6f70SBen Gras     out:
205d65f6f70SBen Gras 	lfs_free(fs, blkiov, LFS_NB_BLKIOV);
206d65f6f70SBen Gras 	lfs_free(fs, blkiov15, LFS_NB_BLKIOV);
207d65f6f70SBen Gras 	KERNEL_UNLOCK_ONE(NULL);
208d65f6f70SBen Gras 	return error;
209d65f6f70SBen Gras }
210d65f6f70SBen Gras #endif
211d65f6f70SBen Gras 
212d65f6f70SBen Gras #define	LFS_MARKV_MAX_BLOCKS	(LFS_MAX_BUFS)
213d65f6f70SBen Gras 
214d65f6f70SBen Gras int
lfs_markv(struct lwp * l,fsid_t * fsidp,BLOCK_INFO * blkiov,int blkcnt)215*0a6a1f1dSLionel Sambuc lfs_markv(struct lwp *l, fsid_t *fsidp, BLOCK_INFO *blkiov,
216d65f6f70SBen Gras     int blkcnt)
217d65f6f70SBen Gras {
218d65f6f70SBen Gras 	BLOCK_INFO *blkp;
219d65f6f70SBen Gras 	IFILE *ifp;
220d65f6f70SBen Gras 	struct buf *bp;
221d65f6f70SBen Gras 	struct inode *ip = NULL;
222d65f6f70SBen Gras 	struct lfs *fs;
223d65f6f70SBen Gras 	struct mount *mntp;
224*0a6a1f1dSLionel Sambuc 	struct ulfsmount *ump;
225*0a6a1f1dSLionel Sambuc 	struct vnode *vp;
226d65f6f70SBen Gras 	ino_t lastino;
227*0a6a1f1dSLionel Sambuc 	daddr_t b_daddr;
228d65f6f70SBen Gras 	int cnt, error;
229d65f6f70SBen Gras 	int do_again = 0;
230d65f6f70SBen Gras 	int numrefed = 0;
231d65f6f70SBen Gras 	ino_t maxino;
232d65f6f70SBen Gras 	size_t obsize;
233d65f6f70SBen Gras 
234d65f6f70SBen Gras 	/* number of blocks/inodes that we have already bwrite'ed */
235d65f6f70SBen Gras 	int nblkwritten, ninowritten;
236d65f6f70SBen Gras 
237*0a6a1f1dSLionel Sambuc 	error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_LFS,
238*0a6a1f1dSLionel Sambuc 	    KAUTH_REQ_SYSTEM_LFS_MARKV, NULL, NULL, NULL);
239*0a6a1f1dSLionel Sambuc 	if (error)
240*0a6a1f1dSLionel Sambuc 		return (error);
241*0a6a1f1dSLionel Sambuc 
242d65f6f70SBen Gras 	if ((mntp = vfs_getvfs(fsidp)) == NULL)
243d65f6f70SBen Gras 		return (ENOENT);
244d65f6f70SBen Gras 
245*0a6a1f1dSLionel Sambuc 	ump = VFSTOULFS(mntp);
246*0a6a1f1dSLionel Sambuc 	fs = ump->um_lfs;
247d65f6f70SBen Gras 
248d65f6f70SBen Gras 	if (fs->lfs_ronly)
249d65f6f70SBen Gras 		return EROFS;
250d65f6f70SBen Gras 
251*0a6a1f1dSLionel Sambuc 	maxino = (lfs_fragstoblks(fs, lfs_dino_getblocks(fs, VTOI(fs->lfs_ivnode)->i_din)) -
252*0a6a1f1dSLionel Sambuc 		      lfs_sb_getcleansz(fs) - lfs_sb_getsegtabsz(fs)) * lfs_sb_getifpb(fs);
253d65f6f70SBen Gras 
254d65f6f70SBen Gras 	cnt = blkcnt;
255d65f6f70SBen Gras 
256d65f6f70SBen Gras 	if ((error = vfs_busy(mntp, NULL)) != 0)
257d65f6f70SBen Gras 		return (error);
258d65f6f70SBen Gras 
259d65f6f70SBen Gras 	/*
260d65f6f70SBen Gras 	 * This seglock is just to prevent the fact that we might have to sleep
261d65f6f70SBen Gras 	 * from allowing the possibility that our blocks might become
262d65f6f70SBen Gras 	 * invalid.
263d65f6f70SBen Gras 	 *
264d65f6f70SBen Gras 	 * It is also important to note here that unless we specify SEGM_CKP,
265d65f6f70SBen Gras 	 * any Ifile blocks that we might be asked to clean will never get
266d65f6f70SBen Gras 	 * to the disk.
267d65f6f70SBen Gras 	 */
268d65f6f70SBen Gras 	lfs_seglock(fs, SEGM_CLEAN | SEGM_CKP | SEGM_SYNC);
269d65f6f70SBen Gras 
270d65f6f70SBen Gras 	/* Mark blocks/inodes dirty.  */
271d65f6f70SBen Gras 	error = 0;
272d65f6f70SBen Gras 
273d65f6f70SBen Gras 	/* these were inside the initialization for the for loop */
274*0a6a1f1dSLionel Sambuc 	vp = NULL;
275d65f6f70SBen Gras 	lastino = LFS_UNUSED_INUM;
276d65f6f70SBen Gras 	nblkwritten = ninowritten = 0;
277d65f6f70SBen Gras 	for (blkp = blkiov; cnt--; ++blkp)
278d65f6f70SBen Gras 	{
279d65f6f70SBen Gras 		/* Bounds-check incoming data, avoid panic for failed VGET */
280d65f6f70SBen Gras 		if (blkp->bi_inode <= 0 || blkp->bi_inode >= maxino) {
281d65f6f70SBen Gras 			error = EINVAL;
282d65f6f70SBen Gras 			goto err3;
283d65f6f70SBen Gras 		}
284d65f6f70SBen Gras 		/*
285d65f6f70SBen Gras 		 * Get the IFILE entry (only once) and see if the file still
286d65f6f70SBen Gras 		 * exists.
287d65f6f70SBen Gras 		 */
288d65f6f70SBen Gras 		if (lastino != blkp->bi_inode) {
289d65f6f70SBen Gras 			/*
290*0a6a1f1dSLionel Sambuc 			 * Finish the old file, if there was one.
291d65f6f70SBen Gras 			 */
292*0a6a1f1dSLionel Sambuc 			if (vp != NULL) {
293*0a6a1f1dSLionel Sambuc 				vput(vp);
294*0a6a1f1dSLionel Sambuc 				vp = NULL;
295d65f6f70SBen Gras 				numrefed--;
296d65f6f70SBen Gras 			}
297d65f6f70SBen Gras 
298d65f6f70SBen Gras 			/*
299d65f6f70SBen Gras 			 * Start a new file
300d65f6f70SBen Gras 			 */
301d65f6f70SBen Gras 			lastino = blkp->bi_inode;
302d65f6f70SBen Gras 
303d65f6f70SBen Gras 			/* Get the vnode/inode. */
304*0a6a1f1dSLionel Sambuc 			error = lfs_fastvget(mntp, blkp->bi_inode, blkp,
305*0a6a1f1dSLionel Sambuc 			    LK_EXCLUSIVE | LK_NOWAIT, &vp);
306d65f6f70SBen Gras 			if (error) {
307d65f6f70SBen Gras 				DLOG((DLOG_CLEAN, "lfs_markv: lfs_fastvget"
308d65f6f70SBen Gras 				      " failed with %d (ino %d, segment %d)\n",
309d65f6f70SBen Gras 				      error, blkp->bi_inode,
31084d9c625SLionel Sambuc 				      lfs_dtosn(fs, blkp->bi_daddr)));
311d65f6f70SBen Gras 				/*
312d65f6f70SBen Gras 				 * If we got EAGAIN, that means that the
313d65f6f70SBen Gras 				 * Inode was locked.  This is
314d65f6f70SBen Gras 				 * recoverable: just clean the rest of
315d65f6f70SBen Gras 				 * this segment, and let the cleaner try
316d65f6f70SBen Gras 				 * again with another.	(When the
317d65f6f70SBen Gras 				 * cleaner runs again, this segment will
318d65f6f70SBen Gras 				 * sort high on the list, since it is
319*0a6a1f1dSLionel Sambuc 				 * now almost entirely empty.)
320d65f6f70SBen Gras 				 */
321d65f6f70SBen Gras 				if (error == EAGAIN) {
322d65f6f70SBen Gras 					error = 0;
323d65f6f70SBen Gras 					do_again++;
324*0a6a1f1dSLionel Sambuc 				} else
325*0a6a1f1dSLionel Sambuc 					KASSERT(error == ENOENT);
326*0a6a1f1dSLionel Sambuc 				KASSERT(vp == NULL);
327d65f6f70SBen Gras 				ip = NULL;
328d65f6f70SBen Gras 				continue;
329d65f6f70SBen Gras 			}
330*0a6a1f1dSLionel Sambuc 
331d65f6f70SBen Gras 			ip = VTOI(vp);
332*0a6a1f1dSLionel Sambuc 			numrefed++;
333d65f6f70SBen Gras 			ninowritten++;
334*0a6a1f1dSLionel Sambuc 		} else if (vp == NULL) {
335d65f6f70SBen Gras 			/*
336d65f6f70SBen Gras 			 * This can only happen if the vnode is dead (or
337d65f6f70SBen Gras 			 * in any case we can't get it...e.g., it is
338d65f6f70SBen Gras 			 * inlocked).  Keep going.
339d65f6f70SBen Gras 			 */
340d65f6f70SBen Gras 			continue;
341d65f6f70SBen Gras 		}
342d65f6f70SBen Gras 
343d65f6f70SBen Gras 		/* Past this point we are guaranteed that vp, ip are valid. */
344d65f6f70SBen Gras 
345d65f6f70SBen Gras 		/* Can't clean VU_DIROP directories in case of truncation */
346d65f6f70SBen Gras 		/* XXX - maybe we should mark removed dirs specially? */
347d65f6f70SBen Gras 		if (vp->v_type == VDIR && (vp->v_uflag & VU_DIROP)) {
348d65f6f70SBen Gras 			do_again++;
349d65f6f70SBen Gras 			continue;
350d65f6f70SBen Gras 		}
351d65f6f70SBen Gras 
352d65f6f70SBen Gras 		/* If this BLOCK_INFO didn't contain a block, keep going. */
353d65f6f70SBen Gras 		if (blkp->bi_lbn == LFS_UNUSED_LBN) {
354d65f6f70SBen Gras 			/* XXX need to make sure that the inode gets written in this case */
355d65f6f70SBen Gras 			/* XXX but only write the inode if it's the right one */
356d65f6f70SBen Gras 			if (blkp->bi_inode != LFS_IFILE_INUM) {
357d65f6f70SBen Gras 				LFS_IENTRY(ifp, fs, blkp->bi_inode, bp);
358*0a6a1f1dSLionel Sambuc 				if (lfs_if_getdaddr(fs, ifp) == blkp->bi_daddr) {
359d65f6f70SBen Gras 					mutex_enter(&lfs_lock);
360d65f6f70SBen Gras 					LFS_SET_UINO(ip, IN_CLEANING);
361d65f6f70SBen Gras 					mutex_exit(&lfs_lock);
362d65f6f70SBen Gras 				}
363d65f6f70SBen Gras 				brelse(bp, 0);
364d65f6f70SBen Gras 			}
365d65f6f70SBen Gras 			continue;
366d65f6f70SBen Gras 		}
367d65f6f70SBen Gras 
368d65f6f70SBen Gras 		b_daddr = 0;
369d65f6f70SBen Gras 		if (VOP_BMAP(vp, blkp->bi_lbn, NULL, &b_daddr, NULL) ||
37084d9c625SLionel Sambuc 		    LFS_DBTOFSB(fs, b_daddr) != blkp->bi_daddr)
371d65f6f70SBen Gras 		{
37284d9c625SLionel Sambuc 			if (lfs_dtosn(fs, LFS_DBTOFSB(fs, b_daddr)) ==
37384d9c625SLionel Sambuc 			    lfs_dtosn(fs, blkp->bi_daddr))
374d65f6f70SBen Gras 			{
375*0a6a1f1dSLionel Sambuc 				DLOG((DLOG_CLEAN, "lfs_markv: wrong da same seg: %jx vs %jx\n",
376*0a6a1f1dSLionel Sambuc 				      (intmax_t)blkp->bi_daddr, (intmax_t)LFS_DBTOFSB(fs, b_daddr)));
377d65f6f70SBen Gras 			}
378d65f6f70SBen Gras 			do_again++;
379d65f6f70SBen Gras 			continue;
380d65f6f70SBen Gras 		}
381d65f6f70SBen Gras 
382d65f6f70SBen Gras 		/*
383d65f6f70SBen Gras 		 * Check block sizes.  The blocks being cleaned come from
384d65f6f70SBen Gras 		 * disk, so they should have the same size as their on-disk
385d65f6f70SBen Gras 		 * counterparts.
386d65f6f70SBen Gras 		 */
387d65f6f70SBen Gras 		if (blkp->bi_lbn >= 0)
38884d9c625SLionel Sambuc 			obsize = lfs_blksize(fs, ip, blkp->bi_lbn);
389d65f6f70SBen Gras 		else
390*0a6a1f1dSLionel Sambuc 			obsize = lfs_sb_getbsize(fs);
391d65f6f70SBen Gras 		/* Check for fragment size change */
39284d9c625SLionel Sambuc 		if (blkp->bi_lbn >= 0 && blkp->bi_lbn < ULFS_NDADDR) {
393d65f6f70SBen Gras 			obsize = ip->i_lfs_fragsize[blkp->bi_lbn];
394d65f6f70SBen Gras 		}
395d65f6f70SBen Gras 		if (obsize != blkp->bi_size) {
396*0a6a1f1dSLionel Sambuc 			DLOG((DLOG_CLEAN, "lfs_markv: ino %d lbn %jd wrong"
397d65f6f70SBen Gras 			      " size (%ld != %d), try again\n",
398*0a6a1f1dSLionel Sambuc 			      blkp->bi_inode, (intmax_t)blkp->bi_lbn,
399d65f6f70SBen Gras 			      (long) obsize, blkp->bi_size));
400d65f6f70SBen Gras 			do_again++;
401d65f6f70SBen Gras 			continue;
402d65f6f70SBen Gras 		}
403d65f6f70SBen Gras 
404d65f6f70SBen Gras 		/*
405d65f6f70SBen Gras 		 * If we get to here, then we are keeping the block.  If
406d65f6f70SBen Gras 		 * it is an indirect block, we want to actually put it
407d65f6f70SBen Gras 		 * in the buffer cache so that it can be updated in the
408d65f6f70SBen Gras 		 * finish_meta section.	 If it's not, we need to
409d65f6f70SBen Gras 		 * allocate a fake buffer so that writeseg can perform
410d65f6f70SBen Gras 		 * the copyin and write the buffer.
411d65f6f70SBen Gras 		 */
412d65f6f70SBen Gras 		if (ip->i_number != LFS_IFILE_INUM && blkp->bi_lbn >= 0) {
413d65f6f70SBen Gras 			/* Data Block */
414d65f6f70SBen Gras 			bp = lfs_fakebuf(fs, vp, blkp->bi_lbn,
415d65f6f70SBen Gras 					 blkp->bi_size, blkp->bi_bp);
416d65f6f70SBen Gras 			/* Pretend we used bread() to get it */
41784d9c625SLionel Sambuc 			bp->b_blkno = LFS_FSBTODB(fs, blkp->bi_daddr);
418d65f6f70SBen Gras 		} else {
419d65f6f70SBen Gras 			/* Indirect block or ifile */
420*0a6a1f1dSLionel Sambuc 			if (blkp->bi_size != lfs_sb_getbsize(fs) &&
421d65f6f70SBen Gras 			    ip->i_number != LFS_IFILE_INUM)
422d65f6f70SBen Gras 				panic("lfs_markv: partial indirect block?"
423d65f6f70SBen Gras 				    " size=%d\n", blkp->bi_size);
424d65f6f70SBen Gras 			bp = getblk(vp, blkp->bi_lbn, blkp->bi_size, 0, 0);
425d65f6f70SBen Gras 			if (!(bp->b_oflags & (BO_DONE|BO_DELWRI))) {
426d65f6f70SBen Gras 				/*
427d65f6f70SBen Gras 				 * The block in question was not found
428d65f6f70SBen Gras 				 * in the cache; i.e., the block that
429d65f6f70SBen Gras 				 * getblk() returned is empty.	So, we
430d65f6f70SBen Gras 				 * can (and should) copy in the
431d65f6f70SBen Gras 				 * contents, because we've already
432d65f6f70SBen Gras 				 * determined that this was the right
433d65f6f70SBen Gras 				 * version of this block on disk.
434d65f6f70SBen Gras 				 *
435d65f6f70SBen Gras 				 * And, it can't have changed underneath
436d65f6f70SBen Gras 				 * us, because we have the segment lock.
437d65f6f70SBen Gras 				 */
438d65f6f70SBen Gras 				error = copyin(blkp->bi_bp, bp->b_data, blkp->bi_size);
439d65f6f70SBen Gras 				if (error)
440d65f6f70SBen Gras 					goto err2;
441d65f6f70SBen Gras 			}
442d65f6f70SBen Gras 		}
443d65f6f70SBen Gras 		if ((error = lfs_bwrite_ext(bp, BW_CLEAN)) != 0)
444d65f6f70SBen Gras 			goto err2;
445d65f6f70SBen Gras 
446d65f6f70SBen Gras 		nblkwritten++;
447d65f6f70SBen Gras 		/*
448d65f6f70SBen Gras 		 * XXX should account indirect blocks and ifile pages as well
449d65f6f70SBen Gras 		 */
450*0a6a1f1dSLionel Sambuc 		if (nblkwritten + lfs_lblkno(fs, ninowritten * DINOSIZE(fs))
451d65f6f70SBen Gras 		    > LFS_MARKV_MAX_BLOCKS) {
452d65f6f70SBen Gras 			DLOG((DLOG_CLEAN, "lfs_markv: writing %d blks %d inos\n",
453d65f6f70SBen Gras 			      nblkwritten, ninowritten));
454d65f6f70SBen Gras 			lfs_segwrite(mntp, SEGM_CLEAN);
455d65f6f70SBen Gras 			nblkwritten = ninowritten = 0;
456d65f6f70SBen Gras 		}
457d65f6f70SBen Gras 	}
458d65f6f70SBen Gras 
459d65f6f70SBen Gras 	/*
460d65f6f70SBen Gras 	 * Finish the old file, if there was one
461d65f6f70SBen Gras 	 */
462*0a6a1f1dSLionel Sambuc 	if (vp != NULL) {
463*0a6a1f1dSLionel Sambuc 		vput(vp);
464*0a6a1f1dSLionel Sambuc 		vp = NULL;
465d65f6f70SBen Gras 		numrefed--;
466d65f6f70SBen Gras 	}
467d65f6f70SBen Gras 
468d65f6f70SBen Gras #ifdef DIAGNOSTIC
469d65f6f70SBen Gras 	if (numrefed != 0)
470d65f6f70SBen Gras 		panic("lfs_markv: numrefed=%d", numrefed);
471d65f6f70SBen Gras #endif
472d65f6f70SBen Gras 	DLOG((DLOG_CLEAN, "lfs_markv: writing %d blks %d inos (check point)\n",
473d65f6f70SBen Gras 	      nblkwritten, ninowritten));
474d65f6f70SBen Gras 
475d65f6f70SBen Gras 	/*
476d65f6f70SBen Gras 	 * The last write has to be SEGM_SYNC, because of calling semantics.
477d65f6f70SBen Gras 	 * It also has to be SEGM_CKP, because otherwise we could write
478d65f6f70SBen Gras 	 * over the newly cleaned data contained in a checkpoint, and then
479d65f6f70SBen Gras 	 * we'd be unhappy at recovery time.
480d65f6f70SBen Gras 	 */
481d65f6f70SBen Gras 	lfs_segwrite(mntp, SEGM_CLEAN | SEGM_CKP | SEGM_SYNC);
482d65f6f70SBen Gras 
483d65f6f70SBen Gras 	lfs_segunlock(fs);
484d65f6f70SBen Gras 
485d65f6f70SBen Gras 	vfs_unbusy(mntp, false, NULL);
486d65f6f70SBen Gras 	if (error)
487d65f6f70SBen Gras 		return (error);
488d65f6f70SBen Gras 	else if (do_again)
489d65f6f70SBen Gras 		return EAGAIN;
490d65f6f70SBen Gras 
491d65f6f70SBen Gras 	return 0;
492d65f6f70SBen Gras 
493d65f6f70SBen Gras err2:
494d65f6f70SBen Gras 	DLOG((DLOG_CLEAN, "lfs_markv err2\n"));
495d65f6f70SBen Gras 
496d65f6f70SBen Gras 	/*
497d65f6f70SBen Gras 	 * XXX we're here because copyin() failed.
498d65f6f70SBen Gras 	 * XXX it means that we can't trust the cleanerd.  too bad.
499d65f6f70SBen Gras 	 * XXX how can we recover from this?
500d65f6f70SBen Gras 	 */
501d65f6f70SBen Gras 
502d65f6f70SBen Gras err3:
503d65f6f70SBen Gras 	/*
504d65f6f70SBen Gras 	 * XXX should do segwrite here anyway?
505d65f6f70SBen Gras 	 */
506d65f6f70SBen Gras 
507*0a6a1f1dSLionel Sambuc 	if (vp != NULL) {
508*0a6a1f1dSLionel Sambuc 		vput(vp);
509*0a6a1f1dSLionel Sambuc 		vp = NULL;
510d65f6f70SBen Gras 		--numrefed;
511d65f6f70SBen Gras 	}
512d65f6f70SBen Gras 
513d65f6f70SBen Gras 	lfs_segunlock(fs);
514d65f6f70SBen Gras 	vfs_unbusy(mntp, false, NULL);
515d65f6f70SBen Gras #ifdef DIAGNOSTIC
516d65f6f70SBen Gras 	if (numrefed != 0)
517d65f6f70SBen Gras 		panic("lfs_markv: numrefed=%d", numrefed);
518d65f6f70SBen Gras #endif
519d65f6f70SBen Gras 
520d65f6f70SBen Gras 	return (error);
521d65f6f70SBen Gras }
522d65f6f70SBen Gras 
523d65f6f70SBen Gras /*
524d65f6f70SBen Gras  * sys_lfs_bmapv:
525d65f6f70SBen Gras  *
526d65f6f70SBen Gras  * This will fill in the current disk address for arrays of blocks.
527d65f6f70SBen Gras  *
528d65f6f70SBen Gras  *  0 on success
529d65f6f70SBen Gras  * -1/errno is return on error.
530d65f6f70SBen Gras  */
531d65f6f70SBen Gras #ifdef USE_64BIT_SYSCALLS
532d65f6f70SBen Gras int
sys_lfs_bmapv(struct lwp * l,const struct sys_lfs_bmapv_args * uap,register_t * retval)533d65f6f70SBen Gras sys_lfs_bmapv(struct lwp *l, const struct sys_lfs_bmapv_args *uap, register_t *retval)
534d65f6f70SBen Gras {
535d65f6f70SBen Gras 	/* {
536d65f6f70SBen Gras 		syscallarg(fsid_t *) fsidp;
537d65f6f70SBen Gras 		syscallarg(struct block_info *) blkiov;
538d65f6f70SBen Gras 		syscallarg(int) blkcnt;
539d65f6f70SBen Gras 	} */
540d65f6f70SBen Gras 	BLOCK_INFO *blkiov;
541d65f6f70SBen Gras 	int blkcnt, error;
542d65f6f70SBen Gras 	fsid_t fsid;
543d65f6f70SBen Gras 	struct lfs *fs;
544d65f6f70SBen Gras 	struct mount *mntp;
545d65f6f70SBen Gras 
546d65f6f70SBen Gras 	if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0)
547d65f6f70SBen Gras 		return (error);
548d65f6f70SBen Gras 
549d65f6f70SBen Gras 	if ((mntp = vfs_getvfs(&fsid)) == NULL)
550d65f6f70SBen Gras 		return (ENOENT);
55184d9c625SLionel Sambuc 	fs = VFSTOULFS(mntp)->um_lfs;
552d65f6f70SBen Gras 
553d65f6f70SBen Gras 	blkcnt = SCARG(uap, blkcnt);
554d65f6f70SBen Gras 	if ((u_int) blkcnt > SIZE_T_MAX / sizeof(BLOCK_INFO))
555d65f6f70SBen Gras 		return (EINVAL);
556d65f6f70SBen Gras 	KERNEL_LOCK(1, NULL);
557d65f6f70SBen Gras 	blkiov = lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO), LFS_NB_BLKIOV);
558d65f6f70SBen Gras 	if ((error = copyin(SCARG(uap, blkiov), blkiov,
559d65f6f70SBen Gras 			    blkcnt * sizeof(BLOCK_INFO))) != 0)
560d65f6f70SBen Gras 		goto out;
561d65f6f70SBen Gras 
562d65f6f70SBen Gras 	if ((error = lfs_bmapv(p, &fsid, blkiov, blkcnt)) == 0)
563d65f6f70SBen Gras 		copyout(blkiov, SCARG(uap, blkiov),
564d65f6f70SBen Gras 			blkcnt * sizeof(BLOCK_INFO));
565d65f6f70SBen Gras     out:
566d65f6f70SBen Gras 	lfs_free(fs, blkiov, LFS_NB_BLKIOV);
567d65f6f70SBen Gras 	KERNEL_UNLOCK_ONE(NULL);
568d65f6f70SBen Gras 	return error;
569d65f6f70SBen Gras }
570d65f6f70SBen Gras #else
571d65f6f70SBen Gras int
sys_lfs_bmapv(struct lwp * l,const struct sys_lfs_bmapv_args * uap,register_t * retval)572d65f6f70SBen Gras sys_lfs_bmapv(struct lwp *l, const struct sys_lfs_bmapv_args *uap, register_t *retval)
573d65f6f70SBen Gras {
574d65f6f70SBen Gras 	/* {
575d65f6f70SBen Gras 		syscallarg(fsid_t *) fsidp;
576d65f6f70SBen Gras 		syscallarg(struct block_info *) blkiov;
577d65f6f70SBen Gras 		syscallarg(int) blkcnt;
578d65f6f70SBen Gras 	} */
579d65f6f70SBen Gras 	BLOCK_INFO *blkiov;
580d65f6f70SBen Gras 	BLOCK_INFO_15 *blkiov15;
581d65f6f70SBen Gras 	int i, blkcnt, error;
582d65f6f70SBen Gras 	fsid_t fsid;
583d65f6f70SBen Gras 	struct lfs *fs;
584d65f6f70SBen Gras 	struct mount *mntp;
585d65f6f70SBen Gras 
586d65f6f70SBen Gras 	if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0)
587d65f6f70SBen Gras 		return (error);
588d65f6f70SBen Gras 
589d65f6f70SBen Gras 	if ((mntp = vfs_getvfs(&fsid)) == NULL)
590d65f6f70SBen Gras 		return (ENOENT);
59184d9c625SLionel Sambuc 	fs = VFSTOULFS(mntp)->um_lfs;
592d65f6f70SBen Gras 
593d65f6f70SBen Gras 	blkcnt = SCARG(uap, blkcnt);
594d65f6f70SBen Gras 	if ((size_t) blkcnt > SIZE_T_MAX / sizeof(BLOCK_INFO))
595d65f6f70SBen Gras 		return (EINVAL);
596d65f6f70SBen Gras 	KERNEL_LOCK(1, NULL);
597d65f6f70SBen Gras 	blkiov = lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO), LFS_NB_BLKIOV);
598d65f6f70SBen Gras 	blkiov15 = lfs_malloc(fs, blkcnt * sizeof(BLOCK_INFO_15), LFS_NB_BLKIOV);
599d65f6f70SBen Gras 	if ((error = copyin(SCARG(uap, blkiov), blkiov15,
600d65f6f70SBen Gras 			    blkcnt * sizeof(BLOCK_INFO_15))) != 0)
601d65f6f70SBen Gras 		goto out;
602d65f6f70SBen Gras 
603d65f6f70SBen Gras 	for (i = 0; i < blkcnt; i++) {
604d65f6f70SBen Gras 		blkiov[i].bi_inode     = blkiov15[i].bi_inode;
605d65f6f70SBen Gras 		blkiov[i].bi_lbn       = blkiov15[i].bi_lbn;
606d65f6f70SBen Gras 		blkiov[i].bi_daddr     = blkiov15[i].bi_daddr;
607d65f6f70SBen Gras 		blkiov[i].bi_segcreate = blkiov15[i].bi_segcreate;
608d65f6f70SBen Gras 		blkiov[i].bi_version   = blkiov15[i].bi_version;
609d65f6f70SBen Gras 		blkiov[i].bi_bp	       = blkiov15[i].bi_bp;
610d65f6f70SBen Gras 		blkiov[i].bi_size      = blkiov15[i].bi_size;
611d65f6f70SBen Gras 	}
612d65f6f70SBen Gras 
613*0a6a1f1dSLionel Sambuc 	if ((error = lfs_bmapv(l, &fsid, blkiov, blkcnt)) == 0) {
614d65f6f70SBen Gras 		for (i = 0; i < blkcnt; i++) {
615d65f6f70SBen Gras 			blkiov15[i].bi_inode	 = blkiov[i].bi_inode;
616d65f6f70SBen Gras 			blkiov15[i].bi_lbn	 = blkiov[i].bi_lbn;
617d65f6f70SBen Gras 			blkiov15[i].bi_daddr	 = blkiov[i].bi_daddr;
618d65f6f70SBen Gras 			blkiov15[i].bi_segcreate = blkiov[i].bi_segcreate;
619d65f6f70SBen Gras 			blkiov15[i].bi_version	 = blkiov[i].bi_version;
620d65f6f70SBen Gras 			blkiov15[i].bi_bp	 = blkiov[i].bi_bp;
621d65f6f70SBen Gras 			blkiov15[i].bi_size	 = blkiov[i].bi_size;
622d65f6f70SBen Gras 		}
623d65f6f70SBen Gras 		copyout(blkiov15, SCARG(uap, blkiov),
624d65f6f70SBen Gras 			blkcnt * sizeof(BLOCK_INFO_15));
625d65f6f70SBen Gras 	}
626d65f6f70SBen Gras     out:
627d65f6f70SBen Gras 	lfs_free(fs, blkiov, LFS_NB_BLKIOV);
628d65f6f70SBen Gras 	lfs_free(fs, blkiov15, LFS_NB_BLKIOV);
629d65f6f70SBen Gras 	KERNEL_UNLOCK_ONE(NULL);
630d65f6f70SBen Gras 	return error;
631d65f6f70SBen Gras }
632d65f6f70SBen Gras #endif
633d65f6f70SBen Gras 
634d65f6f70SBen Gras int
lfs_bmapv(struct lwp * l,fsid_t * fsidp,BLOCK_INFO * blkiov,int blkcnt)635*0a6a1f1dSLionel Sambuc lfs_bmapv(struct lwp *l, fsid_t *fsidp, BLOCK_INFO *blkiov, int blkcnt)
636d65f6f70SBen Gras {
637d65f6f70SBen Gras 	BLOCK_INFO *blkp;
638d65f6f70SBen Gras 	IFILE *ifp;
639d65f6f70SBen Gras 	struct buf *bp;
640d65f6f70SBen Gras 	struct inode *ip = NULL;
641d65f6f70SBen Gras 	struct lfs *fs;
642d65f6f70SBen Gras 	struct mount *mntp;
64384d9c625SLionel Sambuc 	struct ulfsmount *ump;
644d65f6f70SBen Gras 	struct vnode *vp;
645d65f6f70SBen Gras 	ino_t lastino;
646d65f6f70SBen Gras 	daddr_t v_daddr;
647d65f6f70SBen Gras 	int cnt, error;
648d65f6f70SBen Gras 	int numrefed = 0;
649d65f6f70SBen Gras 
650*0a6a1f1dSLionel Sambuc 	error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_LFS,
651*0a6a1f1dSLionel Sambuc 	    KAUTH_REQ_SYSTEM_LFS_BMAPV, NULL, NULL, NULL);
652*0a6a1f1dSLionel Sambuc 	if (error)
653*0a6a1f1dSLionel Sambuc 		return (error);
654d65f6f70SBen Gras 
655d65f6f70SBen Gras 	if ((mntp = vfs_getvfs(fsidp)) == NULL)
656d65f6f70SBen Gras 		return (ENOENT);
657d65f6f70SBen Gras 
65884d9c625SLionel Sambuc 	ump = VFSTOULFS(mntp);
659d65f6f70SBen Gras 	if ((error = vfs_busy(mntp, NULL)) != 0)
660d65f6f70SBen Gras 		return (error);
661d65f6f70SBen Gras 
662*0a6a1f1dSLionel Sambuc 	if (ump->um_cleaner_thread == NULL)
663*0a6a1f1dSLionel Sambuc 		ump->um_cleaner_thread = curlwp;
664*0a6a1f1dSLionel Sambuc 	KASSERT(ump->um_cleaner_thread == curlwp);
665*0a6a1f1dSLionel Sambuc 
666d65f6f70SBen Gras 	cnt = blkcnt;
667d65f6f70SBen Gras 
66884d9c625SLionel Sambuc 	fs = VFSTOULFS(mntp)->um_lfs;
669d65f6f70SBen Gras 
670d65f6f70SBen Gras 	error = 0;
671d65f6f70SBen Gras 
672d65f6f70SBen Gras 	/* these were inside the initialization for the for loop */
673*0a6a1f1dSLionel Sambuc 	vp = NULL;
674d65f6f70SBen Gras 	v_daddr = LFS_UNUSED_DADDR;
675d65f6f70SBen Gras 	lastino = LFS_UNUSED_INUM;
676d65f6f70SBen Gras 	for (blkp = blkiov; cnt--; ++blkp)
677d65f6f70SBen Gras 	{
678d65f6f70SBen Gras 		/*
679d65f6f70SBen Gras 		 * Get the IFILE entry (only once) and see if the file still
680d65f6f70SBen Gras 		 * exists.
681d65f6f70SBen Gras 		 */
682d65f6f70SBen Gras 		if (lastino != blkp->bi_inode) {
683d65f6f70SBen Gras 			/*
684*0a6a1f1dSLionel Sambuc 			 * Finish the old file, if there was one.
685d65f6f70SBen Gras 			 */
686*0a6a1f1dSLionel Sambuc 			if (vp != NULL) {
687*0a6a1f1dSLionel Sambuc 				vput(vp);
688*0a6a1f1dSLionel Sambuc 				vp = NULL;
689d65f6f70SBen Gras 				numrefed--;
690d65f6f70SBen Gras 			}
691d65f6f70SBen Gras 
692d65f6f70SBen Gras 			/*
693d65f6f70SBen Gras 			 * Start a new file
694d65f6f70SBen Gras 			 */
695d65f6f70SBen Gras 			lastino = blkp->bi_inode;
696d65f6f70SBen Gras 			if (blkp->bi_inode == LFS_IFILE_INUM)
697*0a6a1f1dSLionel Sambuc 				v_daddr = lfs_sb_getidaddr(fs);
698d65f6f70SBen Gras 			else {
699d65f6f70SBen Gras 				LFS_IENTRY(ifp, fs, blkp->bi_inode, bp);
700*0a6a1f1dSLionel Sambuc 				v_daddr = lfs_if_getdaddr(fs, ifp);
701d65f6f70SBen Gras 				brelse(bp, 0);
702d65f6f70SBen Gras 			}
703d65f6f70SBen Gras 			if (v_daddr == LFS_UNUSED_DADDR) {
704d65f6f70SBen Gras 				blkp->bi_daddr = LFS_UNUSED_DADDR;
705d65f6f70SBen Gras 				continue;
706d65f6f70SBen Gras 			}
707*0a6a1f1dSLionel Sambuc 			error = lfs_fastvget(mntp, blkp->bi_inode, NULL,
708*0a6a1f1dSLionel Sambuc 			    LK_SHARED, &vp);
709d65f6f70SBen Gras 			if (error) {
710*0a6a1f1dSLionel Sambuc 				DLOG((DLOG_CLEAN, "lfs_bmapv: lfs_fastvget ino"
711d65f6f70SBen Gras 				      "%d failed with %d",
712d65f6f70SBen Gras 				      blkp->bi_inode,error));
713*0a6a1f1dSLionel Sambuc 				KASSERT(vp == NULL);
714d65f6f70SBen Gras 				continue;
715d65f6f70SBen Gras 			} else {
716d65f6f70SBen Gras 				KASSERT(VOP_ISLOCKED(vp));
717d65f6f70SBen Gras 				numrefed++;
718d65f6f70SBen Gras 			}
719d65f6f70SBen Gras 			ip = VTOI(vp);
720*0a6a1f1dSLionel Sambuc 		} else if (vp == NULL) {
721d65f6f70SBen Gras 			/*
722d65f6f70SBen Gras 			 * This can only happen if the vnode is dead.
723d65f6f70SBen Gras 			 * Keep going.	Note that we DO NOT set the
724d65f6f70SBen Gras 			 * bi_addr to anything -- if we failed to get
725d65f6f70SBen Gras 			 * the vnode, for example, we want to assume
726d65f6f70SBen Gras 			 * conservatively that all of its blocks *are*
727d65f6f70SBen Gras 			 * located in the segment in question.
728d65f6f70SBen Gras 			 * lfs_markv will throw them out if we are
729d65f6f70SBen Gras 			 * wrong.
730d65f6f70SBen Gras 			 */
731d65f6f70SBen Gras 			continue;
732d65f6f70SBen Gras 		}
733d65f6f70SBen Gras 
734d65f6f70SBen Gras 		/* Past this point we are guaranteed that vp, ip are valid. */
735d65f6f70SBen Gras 
736d65f6f70SBen Gras 		if (blkp->bi_lbn == LFS_UNUSED_LBN) {
737d65f6f70SBen Gras 			/*
738d65f6f70SBen Gras 			 * We just want the inode address, which is
739d65f6f70SBen Gras 			 * conveniently in v_daddr.
740d65f6f70SBen Gras 			 */
741d65f6f70SBen Gras 			blkp->bi_daddr = v_daddr;
742d65f6f70SBen Gras 		} else {
743d65f6f70SBen Gras 			daddr_t bi_daddr;
744d65f6f70SBen Gras 
745d65f6f70SBen Gras 			error = VOP_BMAP(vp, blkp->bi_lbn, NULL,
746d65f6f70SBen Gras 					 &bi_daddr, NULL);
747d65f6f70SBen Gras 			if (error)
748d65f6f70SBen Gras 			{
749d65f6f70SBen Gras 				blkp->bi_daddr = LFS_UNUSED_DADDR;
750d65f6f70SBen Gras 				continue;
751d65f6f70SBen Gras 			}
75284d9c625SLionel Sambuc 			blkp->bi_daddr = LFS_DBTOFSB(fs, bi_daddr);
753d65f6f70SBen Gras 			/* Fill in the block size, too */
754d65f6f70SBen Gras 			if (blkp->bi_lbn >= 0)
75584d9c625SLionel Sambuc 				blkp->bi_size = lfs_blksize(fs, ip, blkp->bi_lbn);
756d65f6f70SBen Gras 			else
757*0a6a1f1dSLionel Sambuc 				blkp->bi_size = lfs_sb_getbsize(fs);
758d65f6f70SBen Gras 		}
759d65f6f70SBen Gras 	}
760d65f6f70SBen Gras 
761d65f6f70SBen Gras 	/*
762*0a6a1f1dSLionel Sambuc 	 * Finish the old file, if there was one.
763d65f6f70SBen Gras 	 */
764*0a6a1f1dSLionel Sambuc 	if (vp != NULL) {
765*0a6a1f1dSLionel Sambuc 		vput(vp);
766*0a6a1f1dSLionel Sambuc 		vp = NULL;
767d65f6f70SBen Gras 		numrefed--;
768d65f6f70SBen Gras 	}
769d65f6f70SBen Gras 
770d65f6f70SBen Gras #ifdef DIAGNOSTIC
771d65f6f70SBen Gras 	if (numrefed != 0)
772d65f6f70SBen Gras 		panic("lfs_bmapv: numrefed=%d", numrefed);
773d65f6f70SBen Gras #endif
774d65f6f70SBen Gras 
775d65f6f70SBen Gras 	vfs_unbusy(mntp, false, NULL);
776d65f6f70SBen Gras 
777d65f6f70SBen Gras 	return 0;
778d65f6f70SBen Gras }
779d65f6f70SBen Gras 
780d65f6f70SBen Gras /*
781d65f6f70SBen Gras  * sys_lfs_segclean:
782d65f6f70SBen Gras  *
783d65f6f70SBen Gras  * Mark the segment clean.
784d65f6f70SBen Gras  *
785d65f6f70SBen Gras  *  0 on success
786d65f6f70SBen Gras  * -1/errno is return on error.
787d65f6f70SBen Gras  */
788d65f6f70SBen Gras int
sys_lfs_segclean(struct lwp * l,const struct sys_lfs_segclean_args * uap,register_t * retval)789d65f6f70SBen Gras sys_lfs_segclean(struct lwp *l, const struct sys_lfs_segclean_args *uap, register_t *retval)
790d65f6f70SBen Gras {
791d65f6f70SBen Gras 	/* {
792d65f6f70SBen Gras 		syscallarg(fsid_t *) fsidp;
793d65f6f70SBen Gras 		syscallarg(u_long) segment;
794d65f6f70SBen Gras 	} */
795d65f6f70SBen Gras 	struct lfs *fs;
796d65f6f70SBen Gras 	struct mount *mntp;
797d65f6f70SBen Gras 	fsid_t fsid;
798d65f6f70SBen Gras 	int error;
799d65f6f70SBen Gras 	unsigned long segnum;
800d65f6f70SBen Gras 
80184d9c625SLionel Sambuc 	error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_LFS,
80284d9c625SLionel Sambuc 	    KAUTH_REQ_SYSTEM_LFS_SEGCLEAN, NULL, NULL, NULL);
80384d9c625SLionel Sambuc 	if (error)
804d65f6f70SBen Gras 		return (error);
805d65f6f70SBen Gras 
806d65f6f70SBen Gras 	if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0)
807d65f6f70SBen Gras 		return (error);
808d65f6f70SBen Gras 	if ((mntp = vfs_getvfs(&fsid)) == NULL)
809d65f6f70SBen Gras 		return (ENOENT);
810d65f6f70SBen Gras 
81184d9c625SLionel Sambuc 	fs = VFSTOULFS(mntp)->um_lfs;
812d65f6f70SBen Gras 	segnum = SCARG(uap, segment);
813d65f6f70SBen Gras 
814d65f6f70SBen Gras 	if ((error = vfs_busy(mntp, NULL)) != 0)
815d65f6f70SBen Gras 		return (error);
816d65f6f70SBen Gras 
817d65f6f70SBen Gras 	KERNEL_LOCK(1, NULL);
818d65f6f70SBen Gras 	lfs_seglock(fs, SEGM_PROT);
819d65f6f70SBen Gras 	error = lfs_do_segclean(fs, segnum);
820d65f6f70SBen Gras 	lfs_segunlock(fs);
821d65f6f70SBen Gras 	KERNEL_UNLOCK_ONE(NULL);
822d65f6f70SBen Gras 	vfs_unbusy(mntp, false, NULL);
823d65f6f70SBen Gras 	return error;
824d65f6f70SBen Gras }
825d65f6f70SBen Gras 
826d65f6f70SBen Gras /*
827d65f6f70SBen Gras  * Actually mark the segment clean.
828d65f6f70SBen Gras  * Must be called with the segment lock held.
829d65f6f70SBen Gras  */
830d65f6f70SBen Gras int
lfs_do_segclean(struct lfs * fs,unsigned long segnum)831d65f6f70SBen Gras lfs_do_segclean(struct lfs *fs, unsigned long segnum)
832d65f6f70SBen Gras {
833d65f6f70SBen Gras 	extern int lfs_dostats;
834d65f6f70SBen Gras 	struct buf *bp;
835d65f6f70SBen Gras 	CLEANERINFO *cip;
836d65f6f70SBen Gras 	SEGUSE *sup;
837d65f6f70SBen Gras 
838*0a6a1f1dSLionel Sambuc 	if (lfs_dtosn(fs, lfs_sb_getcurseg(fs)) == segnum) {
839d65f6f70SBen Gras 		return (EBUSY);
840d65f6f70SBen Gras 	}
841d65f6f70SBen Gras 
842d65f6f70SBen Gras 	LFS_SEGENTRY(sup, fs, segnum, bp);
843d65f6f70SBen Gras 	if (sup->su_nbytes) {
844d65f6f70SBen Gras 		DLOG((DLOG_CLEAN, "lfs_segclean: not cleaning segment %lu:"
845d65f6f70SBen Gras 		      " %d live bytes\n", segnum, sup->su_nbytes));
846d65f6f70SBen Gras 		brelse(bp, 0);
847d65f6f70SBen Gras 		return (EBUSY);
848d65f6f70SBen Gras 	}
849d65f6f70SBen Gras 	if (sup->su_flags & SEGUSE_ACTIVE) {
850d65f6f70SBen Gras 		DLOG((DLOG_CLEAN, "lfs_segclean: not cleaning segment %lu:"
851d65f6f70SBen Gras 		      " segment is active\n", segnum));
852d65f6f70SBen Gras 		brelse(bp, 0);
853d65f6f70SBen Gras 		return (EBUSY);
854d65f6f70SBen Gras 	}
855d65f6f70SBen Gras 	if (!(sup->su_flags & SEGUSE_DIRTY)) {
856d65f6f70SBen Gras 		DLOG((DLOG_CLEAN, "lfs_segclean: not cleaning segment %lu:"
857d65f6f70SBen Gras 		      " segment is already clean\n", segnum));
858d65f6f70SBen Gras 		brelse(bp, 0);
859d65f6f70SBen Gras 		return (EALREADY);
860d65f6f70SBen Gras 	}
861d65f6f70SBen Gras 
862*0a6a1f1dSLionel Sambuc 	lfs_sb_addavail(fs, lfs_segtod(fs, 1));
863d65f6f70SBen Gras 	if (sup->su_flags & SEGUSE_SUPERBLOCK)
864*0a6a1f1dSLionel Sambuc 		lfs_sb_subavail(fs, lfs_btofsb(fs, LFS_SBPAD));
865*0a6a1f1dSLionel Sambuc 	if (lfs_sb_getversion(fs) > 1 && segnum == 0 &&
866*0a6a1f1dSLionel Sambuc 	    lfs_sb_gets0addr(fs) < lfs_btofsb(fs, LFS_LABELPAD))
867*0a6a1f1dSLionel Sambuc 		lfs_sb_subavail(fs, lfs_btofsb(fs, LFS_LABELPAD) - lfs_sb_gets0addr(fs));
868d65f6f70SBen Gras 	mutex_enter(&lfs_lock);
869*0a6a1f1dSLionel Sambuc 	lfs_sb_addbfree(fs, sup->su_nsums * lfs_btofsb(fs, lfs_sb_getsumsize(fs)) +
870*0a6a1f1dSLionel Sambuc 		lfs_btofsb(fs, sup->su_ninos * lfs_sb_getibsize(fs)));
871*0a6a1f1dSLionel Sambuc 	lfs_sb_subdmeta(fs, sup->su_nsums * lfs_btofsb(fs, lfs_sb_getsumsize(fs)) +
872*0a6a1f1dSLionel Sambuc 		lfs_btofsb(fs, sup->su_ninos * lfs_sb_getibsize(fs)));
873*0a6a1f1dSLionel Sambuc 	if (lfs_sb_getdmeta(fs) < 0)
874*0a6a1f1dSLionel Sambuc 		lfs_sb_setdmeta(fs, 0);
875d65f6f70SBen Gras 	mutex_exit(&lfs_lock);
876d65f6f70SBen Gras 	sup->su_flags &= ~SEGUSE_DIRTY;
877d65f6f70SBen Gras 	LFS_WRITESEGENTRY(sup, fs, segnum, bp);
878d65f6f70SBen Gras 
879d65f6f70SBen Gras 	LFS_CLEANERINFO(cip, fs, bp);
880*0a6a1f1dSLionel Sambuc 	lfs_ci_shiftdirtytoclean(fs, cip, 1);
881*0a6a1f1dSLionel Sambuc 	lfs_sb_setnclean(fs, lfs_ci_getclean(fs, cip));
882d65f6f70SBen Gras 	mutex_enter(&lfs_lock);
883*0a6a1f1dSLionel Sambuc 	lfs_ci_setbfree(fs, cip, lfs_sb_getbfree(fs));
884*0a6a1f1dSLionel Sambuc 	lfs_ci_setavail(fs, cip, lfs_sb_getavail(fs)
885*0a6a1f1dSLionel Sambuc 			- fs->lfs_ravail - fs->lfs_favail);
886*0a6a1f1dSLionel Sambuc 	wakeup(&fs->lfs_availsleep);
887d65f6f70SBen Gras 	mutex_exit(&lfs_lock);
888d65f6f70SBen Gras 	(void) LFS_BWRITE_LOG(bp);
889d65f6f70SBen Gras 
890d65f6f70SBen Gras 	if (lfs_dostats)
891d65f6f70SBen Gras 		++lfs_stats.segs_reclaimed;
892d65f6f70SBen Gras 
893d65f6f70SBen Gras 	return (0);
894d65f6f70SBen Gras }
895d65f6f70SBen Gras 
896d65f6f70SBen Gras /*
897d65f6f70SBen Gras  * This will block until a segment in file system fsid is written.  A timeout
898d65f6f70SBen Gras  * in milliseconds may be specified which will awake the cleaner automatically.
899d65f6f70SBen Gras  * An fsid of -1 means any file system, and a timeout of 0 means forever.
900d65f6f70SBen Gras  */
901d65f6f70SBen Gras int
lfs_segwait(fsid_t * fsidp,struct timeval * tv)902d65f6f70SBen Gras lfs_segwait(fsid_t *fsidp, struct timeval *tv)
903d65f6f70SBen Gras {
904d65f6f70SBen Gras 	struct mount *mntp;
905d65f6f70SBen Gras 	void *addr;
906d65f6f70SBen Gras 	u_long timeout;
907d65f6f70SBen Gras 	int error;
908d65f6f70SBen Gras 
909d65f6f70SBen Gras 	KERNEL_LOCK(1, NULL);
910d65f6f70SBen Gras 	if (fsidp == NULL || (mntp = vfs_getvfs(fsidp)) == NULL)
911d65f6f70SBen Gras 		addr = &lfs_allclean_wakeup;
912d65f6f70SBen Gras 	else
913*0a6a1f1dSLionel Sambuc 		addr = &VFSTOULFS(mntp)->um_lfs->lfs_nextsegsleep;
914d65f6f70SBen Gras 	/*
915d65f6f70SBen Gras 	 * XXX THIS COULD SLEEP FOREVER IF TIMEOUT IS {0,0}!
916d65f6f70SBen Gras 	 * XXX IS THAT WHAT IS INTENDED?
917d65f6f70SBen Gras 	 */
918d65f6f70SBen Gras 	timeout = tvtohz(tv);
919d65f6f70SBen Gras 	error = tsleep(addr, PCATCH | PVFS, "segment", timeout);
920d65f6f70SBen Gras 	KERNEL_UNLOCK_ONE(NULL);
921d65f6f70SBen Gras 	return (error == ERESTART ? EINTR : 0);
922d65f6f70SBen Gras }
923d65f6f70SBen Gras 
924d65f6f70SBen Gras /*
925d65f6f70SBen Gras  * sys_lfs_segwait:
926d65f6f70SBen Gras  *
927d65f6f70SBen Gras  * System call wrapper around lfs_segwait().
928d65f6f70SBen Gras  *
929d65f6f70SBen Gras  *  0 on success
930d65f6f70SBen Gras  *  1 on timeout
931d65f6f70SBen Gras  * -1/errno is return on error.
932d65f6f70SBen Gras  */
933d65f6f70SBen Gras int
sys___lfs_segwait50(struct lwp * l,const struct sys___lfs_segwait50_args * uap,register_t * retval)934d65f6f70SBen Gras sys___lfs_segwait50(struct lwp *l, const struct sys___lfs_segwait50_args *uap,
935d65f6f70SBen Gras     register_t *retval)
936d65f6f70SBen Gras {
937d65f6f70SBen Gras 	/* {
938d65f6f70SBen Gras 		syscallarg(fsid_t *) fsidp;
939d65f6f70SBen Gras 		syscallarg(struct timeval *) tv;
940d65f6f70SBen Gras 	} */
941d65f6f70SBen Gras 	struct timeval atv;
942d65f6f70SBen Gras 	fsid_t fsid;
943d65f6f70SBen Gras 	int error;
944d65f6f70SBen Gras 
945d65f6f70SBen Gras 	/* XXX need we be su to segwait? */
94684d9c625SLionel Sambuc 	error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_LFS,
94784d9c625SLionel Sambuc 	    KAUTH_REQ_SYSTEM_LFS_SEGWAIT, NULL, NULL, NULL);
94884d9c625SLionel Sambuc 	if (error)
949d65f6f70SBen Gras 		return (error);
950d65f6f70SBen Gras 	if ((error = copyin(SCARG(uap, fsidp), &fsid, sizeof(fsid_t))) != 0)
951d65f6f70SBen Gras 		return (error);
952d65f6f70SBen Gras 
953d65f6f70SBen Gras 	if (SCARG(uap, tv)) {
954d65f6f70SBen Gras 		error = copyin(SCARG(uap, tv), &atv, sizeof(struct timeval));
955d65f6f70SBen Gras 		if (error)
956d65f6f70SBen Gras 			return (error);
957d65f6f70SBen Gras 		if (itimerfix(&atv))
958d65f6f70SBen Gras 			return (EINVAL);
959d65f6f70SBen Gras 	} else /* NULL or invalid */
960d65f6f70SBen Gras 		atv.tv_sec = atv.tv_usec = 0;
961d65f6f70SBen Gras 	return lfs_segwait(&fsid, &atv);
962d65f6f70SBen Gras }
963d65f6f70SBen Gras 
964d65f6f70SBen Gras /*
965*0a6a1f1dSLionel Sambuc  * VFS_VGET call specialized for the cleaner.  If the cleaner is
966d65f6f70SBen Gras  * processing IINFO structures, it may have the ondisk inode already, so
967d65f6f70SBen Gras  * don't go retrieving it again.
968d65f6f70SBen Gras  *
969*0a6a1f1dSLionel Sambuc  * Return the vnode referenced and locked.
970d65f6f70SBen Gras  */
971d65f6f70SBen Gras 
972*0a6a1f1dSLionel Sambuc static int
lfs_fastvget(struct mount * mp,ino_t ino,BLOCK_INFO * blkp,int lk_flags,struct vnode ** vpp)973*0a6a1f1dSLionel Sambuc lfs_fastvget(struct mount *mp, ino_t ino, BLOCK_INFO *blkp, int lk_flags,
974*0a6a1f1dSLionel Sambuc     struct vnode **vpp)
975d65f6f70SBen Gras {
97684d9c625SLionel Sambuc 	struct ulfsmount *ump;
977*0a6a1f1dSLionel Sambuc 	int error;
978d65f6f70SBen Gras 
97984d9c625SLionel Sambuc 	ump = VFSTOULFS(mp);
980*0a6a1f1dSLionel Sambuc 	ump->um_cleaner_hint = blkp;
981*0a6a1f1dSLionel Sambuc 	error = vcache_get(mp, &ino, sizeof(ino), vpp);
982*0a6a1f1dSLionel Sambuc 	ump->um_cleaner_hint = NULL;
983*0a6a1f1dSLionel Sambuc 	if (error)
984*0a6a1f1dSLionel Sambuc 		return error;
985*0a6a1f1dSLionel Sambuc 	error = vn_lock(*vpp, lk_flags);
986d65f6f70SBen Gras 	if (error) {
987*0a6a1f1dSLionel Sambuc 		if (error == EBUSY)
988*0a6a1f1dSLionel Sambuc 			error = EAGAIN;
989*0a6a1f1dSLionel Sambuc 		vrele(*vpp);
990d65f6f70SBen Gras 		*vpp = NULL;
991*0a6a1f1dSLionel Sambuc 		return error;
992d65f6f70SBen Gras 	}
993d65f6f70SBen Gras 
994*0a6a1f1dSLionel Sambuc 	return 0;
995d65f6f70SBen Gras }
996d65f6f70SBen Gras 
997d65f6f70SBen Gras /*
998d65f6f70SBen Gras  * Make up a "fake" cleaner buffer, copy the data from userland into it.
999d65f6f70SBen Gras  */
1000*0a6a1f1dSLionel Sambuc static struct buf *
lfs_fakebuf(struct lfs * fs,struct vnode * vp,daddr_t lbn,size_t size,void * uaddr)1001*0a6a1f1dSLionel Sambuc lfs_fakebuf(struct lfs *fs, struct vnode *vp, daddr_t lbn, size_t size, void *uaddr)
1002d65f6f70SBen Gras {
1003d65f6f70SBen Gras 	struct buf *bp;
1004d65f6f70SBen Gras 	int error;
1005d65f6f70SBen Gras 
1006d65f6f70SBen Gras 	KASSERT(VTOI(vp)->i_number != LFS_IFILE_INUM);
1007d65f6f70SBen Gras 
1008d65f6f70SBen Gras 	bp = lfs_newbuf(VTOI(vp)->i_lfs, vp, lbn, size, LFS_NB_CLEAN);
1009d65f6f70SBen Gras 	error = copyin(uaddr, bp->b_data, size);
1010d65f6f70SBen Gras 	if (error) {
1011d65f6f70SBen Gras 		lfs_freebuf(fs, bp);
1012d65f6f70SBen Gras 		return NULL;
1013d65f6f70SBen Gras 	}
1014d65f6f70SBen Gras 	KDASSERT(bp->b_iodone == lfs_callback);
1015d65f6f70SBen Gras 
1016d65f6f70SBen Gras #if 0
1017d65f6f70SBen Gras 	mutex_enter(&lfs_lock);
1018d65f6f70SBen Gras 	++fs->lfs_iocount;
1019d65f6f70SBen Gras 	mutex_exit(&lfs_lock);
1020d65f6f70SBen Gras #endif
1021d65f6f70SBen Gras 	bp->b_bufsize = size;
1022d65f6f70SBen Gras 	bp->b_bcount = size;
1023d65f6f70SBen Gras 	return (bp);
1024d65f6f70SBen Gras }
1025