xref: /freebsd/sys/fs/ext2fs/ext2_subr.c (revision 29363fb446372cb3f10bc98664e9767c53fbb457)
1e09c00caSUlf Lilleengen /*-
2e09c00caSUlf Lilleengen  *  modified for Lites 1.1
3e09c00caSUlf Lilleengen  *
4e09c00caSUlf Lilleengen  *  Aug 1995, Godmar Back (gback@cs.utah.edu)
5e09c00caSUlf Lilleengen  *  University of Utah, Department of Computer Science
6e09c00caSUlf Lilleengen  */
7e09c00caSUlf Lilleengen /*-
851369649SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
951369649SPedro F. Giffuni  *
10e09c00caSUlf Lilleengen  * Copyright (c) 1982, 1986, 1989, 1993
11e09c00caSUlf Lilleengen  *	The Regents of the University of California.  All rights reserved.
12e09c00caSUlf Lilleengen  *
13e09c00caSUlf Lilleengen  * Redistribution and use in source and binary forms, with or without
14e09c00caSUlf Lilleengen  * modification, are permitted provided that the following conditions
15e09c00caSUlf Lilleengen  * are met:
16e09c00caSUlf Lilleengen  * 1. Redistributions of source code must retain the above copyright
17e09c00caSUlf Lilleengen  *    notice, this list of conditions and the following disclaimer.
18e09c00caSUlf Lilleengen  * 2. Redistributions in binary form must reproduce the above copyright
19e09c00caSUlf Lilleengen  *    notice, this list of conditions and the following disclaimer in the
20e09c00caSUlf Lilleengen  *    documentation and/or other materials provided with the distribution.
21fca15474SPedro F. Giffuni  * 3. Neither the name of the University nor the names of its contributors
22e09c00caSUlf Lilleengen  *    may be used to endorse or promote products derived from this software
23e09c00caSUlf Lilleengen  *    without specific prior written permission.
24e09c00caSUlf Lilleengen  *
25e09c00caSUlf Lilleengen  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26e09c00caSUlf Lilleengen  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27e09c00caSUlf Lilleengen  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28e09c00caSUlf Lilleengen  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29e09c00caSUlf Lilleengen  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30e09c00caSUlf Lilleengen  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31e09c00caSUlf Lilleengen  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32e09c00caSUlf Lilleengen  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33e09c00caSUlf Lilleengen  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34e09c00caSUlf Lilleengen  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35e09c00caSUlf Lilleengen  * SUCH DAMAGE.
36e09c00caSUlf Lilleengen  */
37e09c00caSUlf Lilleengen 
38e09c00caSUlf Lilleengen #include <sys/param.h>
39e09c00caSUlf Lilleengen 
40e09c00caSUlf Lilleengen #include <sys/proc.h>
41ebc94b66SFedor Uporov #include <sys/sdt.h>
42e09c00caSUlf Lilleengen #include <sys/systm.h>
43e09c00caSUlf Lilleengen #include <sys/bio.h>
44e09c00caSUlf Lilleengen #include <sys/buf.h>
45e09c00caSUlf Lilleengen #include <sys/lock.h>
46e09c00caSUlf Lilleengen #include <sys/ucred.h>
47e09c00caSUlf Lilleengen #include <sys/vnode.h>
48e09c00caSUlf Lilleengen 
49e06e5241SFedor Uporov #include <fs/ext2fs/fs.h>
50e09c00caSUlf Lilleengen #include <fs/ext2fs/inode.h>
51e09c00caSUlf Lilleengen #include <fs/ext2fs/ext2fs.h>
523acd9182SFedor Uporov #include <fs/ext2fs/ext2_extern.h>
53e09c00caSUlf Lilleengen #include <fs/ext2fs/fs.h>
54d7511a40SPedro F. Giffuni #include <fs/ext2fs/ext2_extents.h>
55d7511a40SPedro F. Giffuni #include <fs/ext2fs/ext2_mount.h>
56d7511a40SPedro F. Giffuni #include <fs/ext2fs/ext2_dinode.h>
57e09c00caSUlf Lilleengen 
58e09c00caSUlf Lilleengen /*
59e09c00caSUlf Lilleengen  * Return buffer with the contents of block "offset" from the beginning of
60e09c00caSUlf Lilleengen  * directory "ip".  If "res" is non-zero, fill it in with a pointer to the
61e09c00caSUlf Lilleengen  * remaining space in the directory.
62e09c00caSUlf Lilleengen  */
63e09c00caSUlf Lilleengen int
ext2_blkatoff(struct vnode * vp,off_t offset,char ** res,struct buf ** bpp)64a9d1b299SPedro F. Giffuni ext2_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp)
65e09c00caSUlf Lilleengen {
66e09c00caSUlf Lilleengen 	struct inode *ip;
67e09c00caSUlf Lilleengen 	struct m_ext2fs *fs;
68e09c00caSUlf Lilleengen 	struct buf *bp;
69da057ed2SPedro F. Giffuni 	e2fs_lbn_t lbn;
70b394cd1eSFedor Uporov 	int error, bsize;
71e09c00caSUlf Lilleengen 
72e09c00caSUlf Lilleengen 	ip = VTOI(vp);
73e09c00caSUlf Lilleengen 	fs = ip->i_e2fs;
74e09c00caSUlf Lilleengen 	lbn = lblkno(fs, offset);
75e09c00caSUlf Lilleengen 	bsize = blksize(fs, ip, lbn);
76d7511a40SPedro F. Giffuni 
77e09c00caSUlf Lilleengen 	if ((error = bread(vp, lbn, bsize, NOCRED, &bp)) != 0) {
78e09c00caSUlf Lilleengen 		brelse(bp);
79e09c00caSUlf Lilleengen 		return (error);
80e09c00caSUlf Lilleengen 	}
81512f29d1SFedor Uporov 	error = ext2_dir_blk_csum_verify(ip, bp);
82512f29d1SFedor Uporov 	if (error != 0) {
83512f29d1SFedor Uporov 		brelse(bp);
84512f29d1SFedor Uporov 		return (error);
85512f29d1SFedor Uporov 	}
86e09c00caSUlf Lilleengen 	if (res)
87e09c00caSUlf Lilleengen 		*res = (char *)bp->b_data + blkoff(fs, offset);
88b394cd1eSFedor Uporov 
89e09c00caSUlf Lilleengen 	*bpp = bp;
90b394cd1eSFedor Uporov 
91e09c00caSUlf Lilleengen 	return (0);
92e09c00caSUlf Lilleengen }
93e09c00caSUlf Lilleengen 
945b63c125SPedro F. Giffuni /*
955b63c125SPedro F. Giffuni  * Update the cluster map because of an allocation of free like ffs.
965b63c125SPedro F. Giffuni  *
975b63c125SPedro F. Giffuni  * Cnt == 1 means free; cnt == -1 means allocating.
985b63c125SPedro F. Giffuni  */
995b63c125SPedro F. Giffuni void
ext2_clusteracct(struct m_ext2fs * fs,char * bbp,int cg,e4fs_daddr_t bno,int cnt)100ffbde5eaSFedor Uporov ext2_clusteracct(struct m_ext2fs *fs, char *bbp, int cg, e4fs_daddr_t bno, int cnt)
1015b63c125SPedro F. Giffuni {
1025b63c125SPedro F. Giffuni 	int32_t *sump = fs->e2fs_clustersum[cg].cs_sum;
1035b63c125SPedro F. Giffuni 	int32_t *lp;
104ffbde5eaSFedor Uporov 	e4fs_daddr_t start, end, loc, forw, back;
105ffbde5eaSFedor Uporov 	int bit, i;
1065b63c125SPedro F. Giffuni 
1075b63c125SPedro F. Giffuni 	/* Initialize the cluster summary array. */
1085b63c125SPedro F. Giffuni 	if (fs->e2fs_clustersum[cg].cs_init == 0) {
1095b63c125SPedro F. Giffuni 		int run = 0;
110bf9a211dSPedro F. Giffuni 
1115b63c125SPedro F. Giffuni 		bit = 1;
1125b63c125SPedro F. Giffuni 		loc = 0;
1135b63c125SPedro F. Giffuni 
114*cd3acfe7SFedor Uporov 		for (i = 0; i < fs->e2fs_fpg; i++) {
1155b63c125SPedro F. Giffuni 			if ((bbp[loc] & bit) == 0)
1165b63c125SPedro F. Giffuni 				run++;
1175b63c125SPedro F. Giffuni 			else if (run != 0) {
1185b63c125SPedro F. Giffuni 				if (run > fs->e2fs_contigsumsize)
1195b63c125SPedro F. Giffuni 					run = fs->e2fs_contigsumsize;
1205b63c125SPedro F. Giffuni 				sump[run]++;
1215b63c125SPedro F. Giffuni 				run = 0;
1225b63c125SPedro F. Giffuni 			}
1235b63c125SPedro F. Giffuni 			if ((i & (NBBY - 1)) != (NBBY - 1))
1245b63c125SPedro F. Giffuni 				bit <<= 1;
1255b63c125SPedro F. Giffuni 			else {
1265b63c125SPedro F. Giffuni 				loc++;
1275b63c125SPedro F. Giffuni 				bit = 1;
1285b63c125SPedro F. Giffuni 			}
1295b63c125SPedro F. Giffuni 		}
1305b63c125SPedro F. Giffuni 		if (run != 0) {
1315b63c125SPedro F. Giffuni 			if (run > fs->e2fs_contigsumsize)
1325b63c125SPedro F. Giffuni 				run = fs->e2fs_contigsumsize;
1335b63c125SPedro F. Giffuni 			sump[run]++;
1345b63c125SPedro F. Giffuni 		}
1355b63c125SPedro F. Giffuni 		fs->e2fs_clustersum[cg].cs_init = 1;
1365b63c125SPedro F. Giffuni 	}
1375b63c125SPedro F. Giffuni 
1385b63c125SPedro F. Giffuni 	if (fs->e2fs_contigsumsize <= 0)
1395b63c125SPedro F. Giffuni 		return;
1405b63c125SPedro F. Giffuni 
1415b63c125SPedro F. Giffuni 	/* Find the size of the cluster going forward. */
1425b63c125SPedro F. Giffuni 	start = bno + 1;
1435b63c125SPedro F. Giffuni 	end = start + fs->e2fs_contigsumsize;
144*cd3acfe7SFedor Uporov 	if (end > fs->e2fs_fpg)
145*cd3acfe7SFedor Uporov 		end = fs->e2fs_fpg;
1465b63c125SPedro F. Giffuni 	loc = start / NBBY;
1475b63c125SPedro F. Giffuni 	bit = 1 << (start % NBBY);
1485b63c125SPedro F. Giffuni 	for (i = start; i < end; i++) {
1495b63c125SPedro F. Giffuni 		if ((bbp[loc] & bit) != 0)
1505b63c125SPedro F. Giffuni 			break;
1515b63c125SPedro F. Giffuni 		if ((i & (NBBY - 1)) != (NBBY - 1))
1525b63c125SPedro F. Giffuni 			bit <<= 1;
1535b63c125SPedro F. Giffuni 		else {
1545b63c125SPedro F. Giffuni 			loc++;
1555b63c125SPedro F. Giffuni 			bit = 1;
1565b63c125SPedro F. Giffuni 		}
1575b63c125SPedro F. Giffuni 	}
1585b63c125SPedro F. Giffuni 	forw = i - start;
1595b63c125SPedro F. Giffuni 
1605b63c125SPedro F. Giffuni 	/* Find the size of the cluster going backward. */
1615b63c125SPedro F. Giffuni 	start = bno - 1;
1625b63c125SPedro F. Giffuni 	end = start - fs->e2fs_contigsumsize;
1635b63c125SPedro F. Giffuni 	if (end < 0)
1645b63c125SPedro F. Giffuni 		end = -1;
1655b63c125SPedro F. Giffuni 	loc = start / NBBY;
1665b63c125SPedro F. Giffuni 	bit = 1 << (start % NBBY);
1675b63c125SPedro F. Giffuni 	for (i = start; i > end; i--) {
1685b63c125SPedro F. Giffuni 		if ((bbp[loc] & bit) != 0)
1695b63c125SPedro F. Giffuni 			break;
1705b63c125SPedro F. Giffuni 		if ((i & (NBBY - 1)) != 0)
1715b63c125SPedro F. Giffuni 			bit >>= 1;
1725b63c125SPedro F. Giffuni 		else {
1735b63c125SPedro F. Giffuni 			loc--;
1745b63c125SPedro F. Giffuni 			bit = 1 << (NBBY - 1);
1755b63c125SPedro F. Giffuni 		}
1765b63c125SPedro F. Giffuni 	}
1775b63c125SPedro F. Giffuni 	back = start - i;
1785b63c125SPedro F. Giffuni 
1795b63c125SPedro F. Giffuni 	/*
1805b63c125SPedro F. Giffuni 	 * Account for old cluster and the possibly new forward and
1815b63c125SPedro F. Giffuni 	 * back clusters.
1825b63c125SPedro F. Giffuni 	 */
1835b63c125SPedro F. Giffuni 	i = back + forw + 1;
1845b63c125SPedro F. Giffuni 	if (i > fs->e2fs_contigsumsize)
1855b63c125SPedro F. Giffuni 		i = fs->e2fs_contigsumsize;
1865b63c125SPedro F. Giffuni 	sump[i] += cnt;
1875b63c125SPedro F. Giffuni 	if (back > 0)
1885b63c125SPedro F. Giffuni 		sump[back] -= cnt;
1895b63c125SPedro F. Giffuni 	if (forw > 0)
1905b63c125SPedro F. Giffuni 		sump[forw] -= cnt;
1915b63c125SPedro F. Giffuni 
1925b63c125SPedro F. Giffuni 	/* Update cluster summary information. */
1935b63c125SPedro F. Giffuni 	lp = &sump[fs->e2fs_contigsumsize];
1945b63c125SPedro F. Giffuni 	for (i = fs->e2fs_contigsumsize; i > 0; i--)
1955b63c125SPedro F. Giffuni 		if (*lp-- > 0)
1965b63c125SPedro F. Giffuni 			break;
1975b63c125SPedro F. Giffuni 	fs->e2fs_maxcluster[cg] = i;
1985b63c125SPedro F. Giffuni }
199