xref: /dflybsd-src/sys/vfs/ext2fs/ext2_subr.c (revision cfe603905713d4e92a7956678970d5dff8e913f2)
1*cfe60390STomohiro Kusumi /*-
2*cfe60390STomohiro Kusumi  *  modified for Lites 1.1
3*cfe60390STomohiro Kusumi  *
4*cfe60390STomohiro Kusumi  *  Aug 1995, Godmar Back (gback@cs.utah.edu)
5*cfe60390STomohiro Kusumi  *  University of Utah, Department of Computer Science
6*cfe60390STomohiro Kusumi  */
7*cfe60390STomohiro Kusumi /*-
8*cfe60390STomohiro Kusumi  * SPDX-License-Identifier: BSD-3-Clause
9*cfe60390STomohiro Kusumi  *
10*cfe60390STomohiro Kusumi  * Copyright (c) 1982, 1986, 1989, 1993
11*cfe60390STomohiro Kusumi  *	The Regents of the University of California.  All rights reserved.
12*cfe60390STomohiro Kusumi  *
13*cfe60390STomohiro Kusumi  * Redistribution and use in source and binary forms, with or without
14*cfe60390STomohiro Kusumi  * modification, are permitted provided that the following conditions
15*cfe60390STomohiro Kusumi  * are met:
16*cfe60390STomohiro Kusumi  * 1. Redistributions of source code must retain the above copyright
17*cfe60390STomohiro Kusumi  *    notice, this list of conditions and the following disclaimer.
18*cfe60390STomohiro Kusumi  * 2. Redistributions in binary form must reproduce the above copyright
19*cfe60390STomohiro Kusumi  *    notice, this list of conditions and the following disclaimer in the
20*cfe60390STomohiro Kusumi  *    documentation and/or other materials provided with the distribution.
21*cfe60390STomohiro Kusumi  * 3. Neither the name of the University nor the names of its contributors
22*cfe60390STomohiro Kusumi  *    may be used to endorse or promote products derived from this software
23*cfe60390STomohiro Kusumi  *    without specific prior written permission.
24*cfe60390STomohiro Kusumi  *
25*cfe60390STomohiro Kusumi  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26*cfe60390STomohiro Kusumi  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27*cfe60390STomohiro Kusumi  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28*cfe60390STomohiro Kusumi  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29*cfe60390STomohiro Kusumi  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30*cfe60390STomohiro Kusumi  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31*cfe60390STomohiro Kusumi  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32*cfe60390STomohiro Kusumi  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33*cfe60390STomohiro Kusumi  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34*cfe60390STomohiro Kusumi  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35*cfe60390STomohiro Kusumi  * SUCH DAMAGE.
36*cfe60390STomohiro Kusumi  *
37*cfe60390STomohiro Kusumi  *	@(#)ffs_subr.c	8.2 (Berkeley) 9/21/93
38*cfe60390STomohiro Kusumi  * $FreeBSD$
39*cfe60390STomohiro Kusumi  */
40*cfe60390STomohiro Kusumi 
41*cfe60390STomohiro Kusumi #include <sys/param.h>
42*cfe60390STomohiro Kusumi 
43*cfe60390STomohiro Kusumi #include <sys/proc.h>
44*cfe60390STomohiro Kusumi #include <sys/systm.h>
45*cfe60390STomohiro Kusumi #include <sys/bio.h>
46*cfe60390STomohiro Kusumi #include <sys/buf2.h>
47*cfe60390STomohiro Kusumi #include <sys/lock.h>
48*cfe60390STomohiro Kusumi #include <sys/ucred.h>
49*cfe60390STomohiro Kusumi #include <sys/vnode.h>
50*cfe60390STomohiro Kusumi #include <sys/mount.h>
51*cfe60390STomohiro Kusumi #include <sys/malloc.h>
52*cfe60390STomohiro Kusumi 
53*cfe60390STomohiro Kusumi #include <vfs/ext2fs/fs.h>
54*cfe60390STomohiro Kusumi #include <vfs/ext2fs/inode.h>
55*cfe60390STomohiro Kusumi #include <vfs/ext2fs/ext2fs.h>
56*cfe60390STomohiro Kusumi #include <vfs/ext2fs/ext2_extern.h>
57*cfe60390STomohiro Kusumi #include <vfs/ext2fs/fs.h>
58*cfe60390STomohiro Kusumi #include <vfs/ext2fs/ext2_extents.h>
59*cfe60390STomohiro Kusumi #include <vfs/ext2fs/ext2_mount.h>
60*cfe60390STomohiro Kusumi #include <vfs/ext2fs/ext2_dinode.h>
61*cfe60390STomohiro Kusumi 
62*cfe60390STomohiro Kusumi void
63*cfe60390STomohiro Kusumi ext2_free(void *addr, struct malloc_type *type, const char *func)
64*cfe60390STomohiro Kusumi {
65*cfe60390STomohiro Kusumi 	if (addr == NULL) {
66*cfe60390STomohiro Kusumi 		printf("%s: trying to free NULL pointer\n", func);
67*cfe60390STomohiro Kusumi 		return;
68*cfe60390STomohiro Kusumi 	}
69*cfe60390STomohiro Kusumi 	kfree(addr, type);
70*cfe60390STomohiro Kusumi }
71*cfe60390STomohiro Kusumi 
72*cfe60390STomohiro Kusumi int
73*cfe60390STomohiro Kusumi ext2_bread(struct vnode *vp, off_t loffset, int size, struct buf **bpp)
74*cfe60390STomohiro Kusumi {
75*cfe60390STomohiro Kusumi 	struct buf *bp;
76*cfe60390STomohiro Kusumi 	int error;
77*cfe60390STomohiro Kusumi 
78*cfe60390STomohiro Kusumi 	*bpp = NULL;
79*cfe60390STomohiro Kusumi 	error = bread(vp, loffset, size, &bp);
80*cfe60390STomohiro Kusumi 	if (error) {
81*cfe60390STomohiro Kusumi 		ext2_brelse(bp);
82*cfe60390STomohiro Kusumi 		return (error);
83*cfe60390STomohiro Kusumi 	}
84*cfe60390STomohiro Kusumi 
85*cfe60390STomohiro Kusumi 	*bpp = bp;
86*cfe60390STomohiro Kusumi 	return (0);
87*cfe60390STomohiro Kusumi }
88*cfe60390STomohiro Kusumi 
89*cfe60390STomohiro Kusumi int
90*cfe60390STomohiro Kusumi ext2_breadn(struct vnode *vp, off_t loffset, int size, off_t *raoffset,
91*cfe60390STomohiro Kusumi     int *rabsize, int cnt, struct buf **bpp)
92*cfe60390STomohiro Kusumi {
93*cfe60390STomohiro Kusumi 	struct buf *bp;
94*cfe60390STomohiro Kusumi 	int error;
95*cfe60390STomohiro Kusumi 
96*cfe60390STomohiro Kusumi 	*bpp = NULL;
97*cfe60390STomohiro Kusumi 	error = breadn(vp, loffset, size, raoffset, rabsize, cnt, &bp);
98*cfe60390STomohiro Kusumi 	if (error) {
99*cfe60390STomohiro Kusumi 		ext2_brelse(bp);
100*cfe60390STomohiro Kusumi 		return (error);
101*cfe60390STomohiro Kusumi 	}
102*cfe60390STomohiro Kusumi 
103*cfe60390STomohiro Kusumi 	*bpp = bp;
104*cfe60390STomohiro Kusumi 	return (0);
105*cfe60390STomohiro Kusumi }
106*cfe60390STomohiro Kusumi 
107*cfe60390STomohiro Kusumi int
108*cfe60390STomohiro Kusumi ext2_cluster_read(struct vnode *vp, off_t filesize, off_t loffset, int blksize,
109*cfe60390STomohiro Kusumi     size_t minreq, size_t maxreq, struct buf **bpp)
110*cfe60390STomohiro Kusumi {
111*cfe60390STomohiro Kusumi 	struct buf *bp;
112*cfe60390STomohiro Kusumi 	int error;
113*cfe60390STomohiro Kusumi 
114*cfe60390STomohiro Kusumi 	*bpp = NULL;
115*cfe60390STomohiro Kusumi 	error = cluster_read(vp, filesize, loffset, blksize, minreq, maxreq,
116*cfe60390STomohiro Kusumi 	    &bp);
117*cfe60390STomohiro Kusumi 	if (error) {
118*cfe60390STomohiro Kusumi 		ext2_brelse(bp);
119*cfe60390STomohiro Kusumi 		return (error);
120*cfe60390STomohiro Kusumi 	}
121*cfe60390STomohiro Kusumi 
122*cfe60390STomohiro Kusumi 	*bpp = bp;
123*cfe60390STomohiro Kusumi 	return (0);
124*cfe60390STomohiro Kusumi }
125*cfe60390STomohiro Kusumi 
126*cfe60390STomohiro Kusumi void
127*cfe60390STomohiro Kusumi ext2_brelse(struct buf *bp)
128*cfe60390STomohiro Kusumi {
129*cfe60390STomohiro Kusumi 	if (bp == NULL)
130*cfe60390STomohiro Kusumi 		return;
131*cfe60390STomohiro Kusumi 	brelse(bp);
132*cfe60390STomohiro Kusumi }
133*cfe60390STomohiro Kusumi 
134*cfe60390STomohiro Kusumi void
135*cfe60390STomohiro Kusumi ext2_bqrelse(struct buf *bp)
136*cfe60390STomohiro Kusumi {
137*cfe60390STomohiro Kusumi 	if (bp == NULL)
138*cfe60390STomohiro Kusumi 		return;
139*cfe60390STomohiro Kusumi 	bqrelse(bp);
140*cfe60390STomohiro Kusumi }
141*cfe60390STomohiro Kusumi 
142*cfe60390STomohiro Kusumi /*
143*cfe60390STomohiro Kusumi  * Return buffer with the contents of block "offset" from the beginning of
144*cfe60390STomohiro Kusumi  * directory "ip".  If "res" is non-zero, fill it in with a pointer to the
145*cfe60390STomohiro Kusumi  * remaining space in the directory.
146*cfe60390STomohiro Kusumi  */
147*cfe60390STomohiro Kusumi int
148*cfe60390STomohiro Kusumi ext2_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp)
149*cfe60390STomohiro Kusumi {
150*cfe60390STomohiro Kusumi 	struct inode *ip;
151*cfe60390STomohiro Kusumi 	struct m_ext2fs *fs;
152*cfe60390STomohiro Kusumi 	struct buf *bp;
153*cfe60390STomohiro Kusumi 	e2fs_lbn_t lbn;
154*cfe60390STomohiro Kusumi 	int error, bsize;
155*cfe60390STomohiro Kusumi 
156*cfe60390STomohiro Kusumi 	ip = VTOI(vp);
157*cfe60390STomohiro Kusumi 	fs = ip->i_e2fs;
158*cfe60390STomohiro Kusumi 	lbn = lblkno(fs, offset);
159*cfe60390STomohiro Kusumi 	bsize = blksize(fs, ip, lbn);
160*cfe60390STomohiro Kusumi 
161*cfe60390STomohiro Kusumi 	if ((error = ext2_bread(vp, lblktodoff(fs, lbn), bsize, &bp)) != 0) {
162*cfe60390STomohiro Kusumi 		ext2_brelse(bp);
163*cfe60390STomohiro Kusumi 		return (error);
164*cfe60390STomohiro Kusumi 	}
165*cfe60390STomohiro Kusumi 	error = ext2_dir_blk_csum_verify(ip, bp);
166*cfe60390STomohiro Kusumi 	if (error != 0) {
167*cfe60390STomohiro Kusumi 		ext2_brelse(bp);
168*cfe60390STomohiro Kusumi 		return (error);
169*cfe60390STomohiro Kusumi 	}
170*cfe60390STomohiro Kusumi 	if (res)
171*cfe60390STomohiro Kusumi 		*res = (char *)bp->b_data + blkoff(fs, offset);
172*cfe60390STomohiro Kusumi 
173*cfe60390STomohiro Kusumi 	*bpp = bp;
174*cfe60390STomohiro Kusumi 
175*cfe60390STomohiro Kusumi 	return (0);
176*cfe60390STomohiro Kusumi }
177*cfe60390STomohiro Kusumi 
178*cfe60390STomohiro Kusumi /*
179*cfe60390STomohiro Kusumi  * Update the cluster map because of an allocation of free like ffs.
180*cfe60390STomohiro Kusumi  *
181*cfe60390STomohiro Kusumi  * Cnt == 1 means free; cnt == -1 means allocating.
182*cfe60390STomohiro Kusumi  */
183*cfe60390STomohiro Kusumi void
184*cfe60390STomohiro Kusumi ext2_clusteracct(struct m_ext2fs *fs, char *bbp, int cg, e4fs_daddr_t bno, int cnt)
185*cfe60390STomohiro Kusumi {
186*cfe60390STomohiro Kusumi 	int32_t *sump = fs->e2fs_clustersum[cg].cs_sum;
187*cfe60390STomohiro Kusumi 	int32_t *lp;
188*cfe60390STomohiro Kusumi 	e4fs_daddr_t start, end, loc, forw, back;
189*cfe60390STomohiro Kusumi 	int bit, i;
190*cfe60390STomohiro Kusumi 
191*cfe60390STomohiro Kusumi 	/* Initialize the cluster summary array. */
192*cfe60390STomohiro Kusumi 	if (fs->e2fs_clustersum[cg].cs_init == 0) {
193*cfe60390STomohiro Kusumi 		int run = 0;
194*cfe60390STomohiro Kusumi 
195*cfe60390STomohiro Kusumi 		bit = 1;
196*cfe60390STomohiro Kusumi 		loc = 0;
197*cfe60390STomohiro Kusumi 
198*cfe60390STomohiro Kusumi 		for (i = 0; i < fs->e2fs_fpg; i++) {
199*cfe60390STomohiro Kusumi 			if ((bbp[loc] & bit) == 0)
200*cfe60390STomohiro Kusumi 				run++;
201*cfe60390STomohiro Kusumi 			else if (run != 0) {
202*cfe60390STomohiro Kusumi 				if (run > fs->e2fs_contigsumsize)
203*cfe60390STomohiro Kusumi 					run = fs->e2fs_contigsumsize;
204*cfe60390STomohiro Kusumi 				sump[run]++;
205*cfe60390STomohiro Kusumi 				run = 0;
206*cfe60390STomohiro Kusumi 			}
207*cfe60390STomohiro Kusumi 			if ((i & (NBBY - 1)) != (NBBY - 1))
208*cfe60390STomohiro Kusumi 				bit <<= 1;
209*cfe60390STomohiro Kusumi 			else {
210*cfe60390STomohiro Kusumi 				loc++;
211*cfe60390STomohiro Kusumi 				bit = 1;
212*cfe60390STomohiro Kusumi 			}
213*cfe60390STomohiro Kusumi 		}
214*cfe60390STomohiro Kusumi 		if (run != 0) {
215*cfe60390STomohiro Kusumi 			if (run > fs->e2fs_contigsumsize)
216*cfe60390STomohiro Kusumi 				run = fs->e2fs_contigsumsize;
217*cfe60390STomohiro Kusumi 			sump[run]++;
218*cfe60390STomohiro Kusumi 		}
219*cfe60390STomohiro Kusumi 		fs->e2fs_clustersum[cg].cs_init = 1;
220*cfe60390STomohiro Kusumi 	}
221*cfe60390STomohiro Kusumi 
222*cfe60390STomohiro Kusumi 	if (fs->e2fs_contigsumsize <= 0)
223*cfe60390STomohiro Kusumi 		return;
224*cfe60390STomohiro Kusumi 
225*cfe60390STomohiro Kusumi 	/* Find the size of the cluster going forward. */
226*cfe60390STomohiro Kusumi 	start = bno + 1;
227*cfe60390STomohiro Kusumi 	end = start + fs->e2fs_contigsumsize;
228*cfe60390STomohiro Kusumi 	if (end > fs->e2fs_fpg)
229*cfe60390STomohiro Kusumi 		end = fs->e2fs_fpg;
230*cfe60390STomohiro Kusumi 	loc = start / NBBY;
231*cfe60390STomohiro Kusumi 	bit = 1 << (start % NBBY);
232*cfe60390STomohiro Kusumi 	for (i = start; i < end; i++) {
233*cfe60390STomohiro Kusumi 		if ((bbp[loc] & bit) != 0)
234*cfe60390STomohiro Kusumi 			break;
235*cfe60390STomohiro Kusumi 		if ((i & (NBBY - 1)) != (NBBY - 1))
236*cfe60390STomohiro Kusumi 			bit <<= 1;
237*cfe60390STomohiro Kusumi 		else {
238*cfe60390STomohiro Kusumi 			loc++;
239*cfe60390STomohiro Kusumi 			bit = 1;
240*cfe60390STomohiro Kusumi 		}
241*cfe60390STomohiro Kusumi 	}
242*cfe60390STomohiro Kusumi 	forw = i - start;
243*cfe60390STomohiro Kusumi 
244*cfe60390STomohiro Kusumi 	/* Find the size of the cluster going backward. */
245*cfe60390STomohiro Kusumi 	start = bno - 1;
246*cfe60390STomohiro Kusumi 	end = start - fs->e2fs_contigsumsize;
247*cfe60390STomohiro Kusumi 	if (end < 0)
248*cfe60390STomohiro Kusumi 		end = -1;
249*cfe60390STomohiro Kusumi 	loc = start / NBBY;
250*cfe60390STomohiro Kusumi 	bit = 1 << (start % NBBY);
251*cfe60390STomohiro Kusumi 	for (i = start; i > end; i--) {
252*cfe60390STomohiro Kusumi 		if ((bbp[loc] & bit) != 0)
253*cfe60390STomohiro Kusumi 			break;
254*cfe60390STomohiro Kusumi 		if ((i & (NBBY - 1)) != 0)
255*cfe60390STomohiro Kusumi 			bit >>= 1;
256*cfe60390STomohiro Kusumi 		else {
257*cfe60390STomohiro Kusumi 			loc--;
258*cfe60390STomohiro Kusumi 			bit = 1 << (NBBY - 1);
259*cfe60390STomohiro Kusumi 		}
260*cfe60390STomohiro Kusumi 	}
261*cfe60390STomohiro Kusumi 	back = start - i;
262*cfe60390STomohiro Kusumi 
263*cfe60390STomohiro Kusumi 	/*
264*cfe60390STomohiro Kusumi 	 * Account for old cluster and the possibly new forward and
265*cfe60390STomohiro Kusumi 	 * back clusters.
266*cfe60390STomohiro Kusumi 	 */
267*cfe60390STomohiro Kusumi 	i = back + forw + 1;
268*cfe60390STomohiro Kusumi 	if (i > fs->e2fs_contigsumsize)
269*cfe60390STomohiro Kusumi 		i = fs->e2fs_contigsumsize;
270*cfe60390STomohiro Kusumi 	sump[i] += cnt;
271*cfe60390STomohiro Kusumi 	if (back > 0)
272*cfe60390STomohiro Kusumi 		sump[back] -= cnt;
273*cfe60390STomohiro Kusumi 	if (forw > 0)
274*cfe60390STomohiro Kusumi 		sump[forw] -= cnt;
275*cfe60390STomohiro Kusumi 
276*cfe60390STomohiro Kusumi 	/* Update cluster summary information. */
277*cfe60390STomohiro Kusumi 	lp = &sump[fs->e2fs_contigsumsize];
278*cfe60390STomohiro Kusumi 	for (i = fs->e2fs_contigsumsize; i > 0; i--)
279*cfe60390STomohiro Kusumi 		if (*lp-- > 0)
280*cfe60390STomohiro Kusumi 			break;
281*cfe60390STomohiro Kusumi 	fs->e2fs_maxcluster[cg] = i;
282*cfe60390STomohiro Kusumi }
283