Deleted Added
full compact
ext2_alloc.c (153110) ext2_alloc.c (202283)
1/*-
2 * modified for Lites 1.1
3 *
4 * Aug 1995, Godmar Back (gback@cs.utah.edu)
5 * University of Utah, Department of Computer Science
6 */
7/*-
8 * Copyright (c) 1982, 1986, 1989, 1993

--- 19 unchanged lines hidden (view full) ---

28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)ffs_alloc.c 8.8 (Berkeley) 2/21/94
1/*-
2 * modified for Lites 1.1
3 *
4 * Aug 1995, Godmar Back (gback@cs.utah.edu)
5 * University of Utah, Department of Computer Science
6 */
7/*-
8 * Copyright (c) 1982, 1986, 1989, 1993

--- 19 unchanged lines hidden (view full) ---

28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)ffs_alloc.c 8.8 (Berkeley) 2/21/94
36 * $FreeBSD: head/sys/gnu/fs/ext2fs/ext2_alloc.c 153110 2005-12-05 11:58:35Z ru $
36 * $FreeBSD: head/sys/fs/ext2fs/ext2_alloc.c 202283 2010-01-14 14:30:54Z lulf $
37 */
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/conf.h>
42#include <sys/vnode.h>
43#include <sys/stat.h>
44#include <sys/mount.h>
45#include <sys/syslog.h>
37 */
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/conf.h>
42#include <sys/vnode.h>
43#include <sys/stat.h>
44#include <sys/mount.h>
45#include <sys/syslog.h>
46#include <sys/buf.h>
46
47
47#include <gnu/fs/ext2fs/inode.h>
48#include <gnu/fs/ext2fs/ext2_mount.h>
49#include <gnu/fs/ext2fs/ext2_fs.h>
50#include <gnu/fs/ext2fs/ext2_fs_sb.h>
51#include <gnu/fs/ext2fs/fs.h>
52#include <gnu/fs/ext2fs/ext2_extern.h>
48#include
49#include
50#include <fs/ext2fs/ext2fs.h>
51#include <fs/ext2fs/fs.h>
52#include <fs/ext2fs/ext2_extern.h>
53
53
54static void ext2_fserr(struct ext2_sb_info *, u_int, char *);
55
54static daddr_t ext2_alloccg(struct inode *, int, daddr_t, int);
55static u_long ext2_dirpref(struct inode *);
56static void ext2_fserr(struct m_ext2fs *, uid_t, char *);
57static u_long ext2_hashalloc(struct inode *, int, long, int,
58 daddr_t (*)(struct inode *, int, daddr_t,
59 int));
60static daddr_t ext2_nodealloccg(struct inode *, int, daddr_t, int);
61static daddr_t ext2_mapsearch(struct m_ext2fs *, char *, daddr_t);
56/*
62/*
57 * Linux calls this functions at the following locations:
58 * (1) the inode is freed
59 * (2) a preallocation miss occurs
60 * (3) truncate is called
61 * (4) release_file is called and f_mode & 2
62 *
63 * I call it in ext2_inactive, ext2_truncate, ext2_vfree and in (2)
64 * the call in vfree might be redundant
65 */
66void
67ext2_discard_prealloc(ip)
68 struct inode * ip;
69{
70#ifdef EXT2_PREALLOCATE
71 if (ip->i_prealloc_count) {
72 int i = ip->i_prealloc_count;
73 ip->i_prealloc_count = 0;
74 ext2_free_blocks (ITOV(ip)->v_mount,
75 ip->i_prealloc_block,
76 i);
77 }
78#endif
79}
80
81/*
82 * Allocate a block in the file system.
63 * Allocate a block in the file system.
83 *
84 * this takes the framework from ffs_alloc. To implement the
85 * actual allocation, it calls ext2_new_block, the ported version
86 * of the same Linux routine.
87 *
64 *
88 * we note that this is always called in connection with ext2_blkpref
65 * A preference may be optionally specified. If a preference is given
66 * the following hierarchy is used to allocate a block:
67 * 1) allocate the requested block.
68 * 2) allocate a rotationally optimal block in the same cylinder.
69 * 3) allocate a block in the same cylinder group.
70 * 4) quadradically rehash into other cylinder groups, until an
71 * available block is located.
72 * If no block preference is given the following hierarchy is used
73 * to allocate a block:
74 * 1) allocate a block in the cylinder group that contains the
75 * inode for the file.
76 * 2) quadradically rehash into other cylinder groups, until an
77 * available block is located.
89 *
78 *
90 * preallocation is done as Linux does it
79 * A preference may be optionally specified. If a preference is given
80 * the following hierarchy is used to allocate a block:
81 * 1) allocate the requested block.
82 * 2) allocate a rotationally optimal block in the same cylinder.
83 * 3) allocate a block in the same cylinder group.
84 * 4) quadradically rehash into other cylinder groups, until an
85 * available block is located.
86 * If no block preference is given the following hierarchy is used
87 * to allocate a block:
88 * 1) allocate a block in the cylinder group that contains the
89 * inode for the file.
90 * 2) quadradically rehash into other cylinder groups, until an
91 * available block is located.
91 */
92 */
93
92int
93ext2_alloc(ip, lbn, bpref, size, cred, bnp)
94 struct inode *ip;
95 int32_t lbn, bpref;
96 int size;
97 struct ucred *cred;
98 int32_t *bnp;
99{
94int
95ext2_alloc(ip, lbn, bpref, size, cred, bnp)
96 struct inode *ip;
97 int32_t lbn, bpref;
98 int size;
99 struct ucred *cred;
100 int32_t *bnp;
101{
100 struct ext2_sb_info *fs;
102 struct m_ext2fs *fs;
103 struct ext2mount *ump;
101 int32_t bno;
104 int32_t bno;
102
105 int cg;
103 *bnp = 0;
104 fs = ip->i_e2fs;
106 *bnp = 0;
107 fs = ip->i_e2fs;
108 ump = ip->i_ump;
109 mtx_assert(EXT2_MTX(ump), MA_OWNED);
105#ifdef DIAGNOSTIC
110#ifdef DIAGNOSTIC
106 if ((u_int)size > fs->s_blocksize || blkoff(fs, size) != 0) {
111 if ((u_int)size > fs->e2fs_bsize || blkoff(fs, size) != 0) {
107 vn_printf(ip->i_devvp, "bsize = %lu, size = %d, fs = %s\n",
112 vn_printf(ip->i_devvp, "bsize = %lu, size = %d, fs = %s\n",
108 fs->s_blocksize, size, fs->fs_fsmnt);
113 (long unsigned int)fs->e2fs_bsize, size, fs->e2fs_fsmnt);
109 panic("ext2_alloc: bad size");
110 }
111 if (cred == NOCRED)
112 panic("ext2_alloc: missing credential");
113#endif /* DIAGNOSTIC */
114 panic("ext2_alloc: bad size");
115 }
116 if (cred == NOCRED)
117 panic("ext2_alloc: missing credential");
118#endif /* DIAGNOSTIC */
114 if (size == fs->s_blocksize && fs->s_es->s_free_blocks_count == 0)
119 if (size == fs->e2fs_bsize && fs->e2fs->e2fs_fbcount == 0)
115 goto nospace;
116 if (cred->cr_uid != 0 &&
120 goto nospace;
121 if (cred->cr_uid != 0 &&
117 fs->s_es->s_free_blocks_count < fs->s_es->s_r_blocks_count)
122 fs->e2fs->e2fs_fbcount < fs->e2fs->e2fs_rbcount)
118 goto nospace;
123 goto nospace;
119 if (bpref >= fs->s_es->s_blocks_count)
124 if (bpref >= fs->e2fs->e2fs_bcount)
120 bpref = 0;
125 bpref = 0;
121 /* call the Linux code */
122#ifdef EXT2_PREALLOCATE
123 /* To have a preallocation hit, we must
124 * - have at least one block preallocated
125 * - and our preferred block must have that block number or one below
126 */
127 if (ip->i_prealloc_count &&
128 (bpref == ip->i_prealloc_block ||
129 bpref + 1 == ip->i_prealloc_block))
130 {
131 bno = ip->i_prealloc_block++;
132 ip->i_prealloc_count--;
133 /* ext2_debug ("preallocation hit (%lu/%lu).\n",
134 ++alloc_hits, ++alloc_attempts); */
135
136 /* Linux gets, clears, and releases the buffer at this
137 point - we don't have to that; we leave it to the caller
138 */
139 } else {
140 ext2_discard_prealloc (ip);
141 /* ext2_debug ("preallocation miss (%lu/%lu).\n",
142 alloc_hits, ++alloc_attempts); */
143 if (S_ISREG(ip->i_mode))
144 bno = ext2_new_block
145 (ITOV(ip)->v_mount, bpref,
146 &ip->i_prealloc_count,
147 &ip->i_prealloc_block);
148 else
149 bno = (int32_t)ext2_new_block(ITOV(ip)->v_mount,
150 bpref, 0, 0);
126 if (bpref == 0)
127 cg = ino_to_cg(fs, ip->i_number);
128 else
129 cg = dtog(fs, bpref);
130 bno = (daddr_t)ext2_hashalloc(ip, cg, bpref, fs->e2fs_bsize,
131 ext2_alloccg);
132 if (bno > 0) {
133 ip->i_blocks += btodb(fs->e2fs_bsize);
134 ip->i_flag |= IN_CHANGE | IN_UPDATE;
135 *bnp = bno;
136 return (0);
151 }
137 }
152#else
153 bno = (int32_t)ext2_new_block(ITOV(ip)->v_mount, bpref, 0, 0);
154#endif
155
156 if (bno > 0) {
157 /* set next_alloc fields as done in block_getblk */
158 ip->i_next_alloc_block = lbn;
159 ip->i_next_alloc_goal = bno;
160
161 ip->i_blocks += btodb(size);
162 ip->i_flag |= IN_CHANGE | IN_UPDATE;
163 *bnp = bno;
164 return (0);
165 }
166nospace:
138nospace:
139 EXT2_UNLOCK(ump);
167 ext2_fserr(fs, cred->cr_uid, "file system full");
140 ext2_fserr(fs, cred->cr_uid, "file system full");
168 uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt);
141 uprintf("\n%s: write failed, file system is full\n", fs->e2fs_fsmnt);
169 return (ENOSPC);
170}
171
172/*
173 * Reallocate a sequence of blocks into a contiguous sequence of blocks.
174 *
175 * The vnode and an array of buffer pointers for a range of sequential
176 * logical blocks to be made contiguous is given. The allocator attempts

--- 5 unchanged lines hidden (view full) ---

182 * is left unchanged. The success in doing the reallocation is returned.
183 * Note that the error return is not reflected back to the user. Rather
184 * the previous block allocation will be used.
185 */
186
187#ifdef FANCY_REALLOC
188#include <sys/sysctl.h>
189static int doasyncfree = 1;
142 return (ENOSPC);
143}
144
145/*
146 * Reallocate a sequence of blocks into a contiguous sequence of blocks.
147 *
148 * The vnode and an array of buffer pointers for a range of sequential
149 * logical blocks to be made contiguous is given. The allocator attempts

--- 5 unchanged lines hidden (view full) ---

155 * is left unchanged. The success in doing the reallocation is returned.
156 * Note that the error return is not reflected back to the user. Rather
157 * the previous block allocation will be used.
158 */
159
160#ifdef FANCY_REALLOC
161#include <sys/sysctl.h>
162static int doasyncfree = 1;
163static int doreallocblks = 1;
164
190#ifdef OPT_DEBUG
191SYSCTL_INT(_debug, 14, doasyncfree, CTLFLAG_RW, &doasyncfree, 0, "");
192#endif /* OPT_DEBUG */
193#endif
194
195int
196ext2_reallocblks(ap)
197 struct vop_reallocblks_args /* {
198 struct vnode *a_vp;
199 struct cluster_save *a_buflist;
200 } */ *ap;
201{
202#ifndef FANCY_REALLOC
203/* printf("ext2_reallocblks not implemented\n"); */
204return ENOSPC;
205#else
206
165#ifdef OPT_DEBUG
166SYSCTL_INT(_debug, 14, doasyncfree, CTLFLAG_RW, &doasyncfree, 0, "");
167#endif /* OPT_DEBUG */
168#endif
169
170int
171ext2_reallocblks(ap)
172 struct vop_reallocblks_args /* {
173 struct vnode *a_vp;
174 struct cluster_save *a_buflist;
175 } */ *ap;
176{
177#ifndef FANCY_REALLOC
178/* printf("ext2_reallocblks not implemented\n"); */
179return ENOSPC;
180#else
181
207 struct ext2_sb_info *fs;
182 struct m_ext2fs *fs;
208 struct inode *ip;
209 struct vnode *vp;
210 struct buf *sbp, *ebp;
183 struct inode *ip;
184 struct vnode *vp;
185 struct buf *sbp, *ebp;
211 int32_t *bap, *sbap, *ebap;
186 int32_t *bap, *sbap, *ebap = 0;
187 struct ext2mount *ump;
212 struct cluster_save *buflist;
188 struct cluster_save *buflist;
213 int32_t start_lbn, end_lbn, soff, eoff, newblk, blkno;
214 struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp;
189 struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp;
190 int32_t start_lbn, end_lbn, soff, newblk, blkno =0;
215 int i, len, start_lvl, end_lvl, pref, ssize;
216
217 vp = ap->a_vp;
218 ip = VTOI(vp);
219 fs = ip->i_e2fs;
191 int i, len, start_lvl, end_lvl, pref, ssize;
192
193 vp = ap->a_vp;
194 ip = VTOI(vp);
195 fs = ip->i_e2fs;
196 ump = ip->i_ump;
220#ifdef UNKLAR
221 if (fs->fs_contigsumsize <= 0)
222 return (ENOSPC);
223#endif
224 buflist = ap->a_buflist;
225 len = buflist->bs_nchildren;
226 start_lbn = buflist->bs_children[0]->b_lblkno;
227 end_lbn = start_lbn + len - 1;

--- 5 unchanged lines hidden (view full) ---

233 /*
234 * If the latest allocation is in a new cylinder group, assume that
235 * the filesystem has decided to move and do not force it back to
236 * the previous cylinder group.
237 */
238 if (dtog(fs, dbtofsb(fs, buflist->bs_children[0]->b_blkno)) !=
239 dtog(fs, dbtofsb(fs, buflist->bs_children[len - 1]->b_blkno)))
240 return (ENOSPC);
197#ifdef UNKLAR
198 if (fs->fs_contigsumsize <= 0)
199 return (ENOSPC);
200#endif
201 buflist = ap->a_buflist;
202 len = buflist->bs_nchildren;
203 start_lbn = buflist->bs_children[0]->b_lblkno;
204 end_lbn = start_lbn + len - 1;

--- 5 unchanged lines hidden (view full) ---

210 /*
211 * If the latest allocation is in a new cylinder group, assume that
212 * the filesystem has decided to move and do not force it back to
213 * the previous cylinder group.
214 */
215 if (dtog(fs, dbtofsb(fs, buflist->bs_children[0]->b_blkno)) !=
216 dtog(fs, dbtofsb(fs, buflist->bs_children[len - 1]->b_blkno)))
217 return (ENOSPC);
241 if (ufs_getlbns(vp, start_lbn, start_ap, &start_lvl) ||
242 ufs_getlbns(vp, end_lbn, end_ap, &end_lvl))
218 if (ext2_getlbns(vp, start_lbn, start_ap, &start_lvl) ||
219 ext2_getlbns(vp, end_lbn, end_ap, &end_lvl))
243 return (ENOSPC);
244 /*
245 * Get the starting offset and block map for the first block.
246 */
247 if (start_lvl == 0) {
248 sbap = &ip->i_db[0];
249 soff = start_lbn;
250 } else {
251 idp = &start_ap[start_lvl - 1];
220 return (ENOSPC);
221 /*
222 * Get the starting offset and block map for the first block.
223 */
224 if (start_lvl == 0) {
225 sbap = &ip->i_db[0];
226 soff = start_lbn;
227 } else {
228 idp = &start_ap[start_lvl - 1];
252 if (bread(vp, idp->in_lbn, (int)fs->s_blocksize, NOCRED, &sbp)) {
229 if (bread(vp, idp->in_lbn, (int)fs->e2fs_bsize, NOCRED, &sbp)) {
253 brelse(sbp);
254 return (ENOSPC);
255 }
256 sbap = (int32_t *)sbp->b_data;
257 soff = idp->in_off;
258 }
259 /*
260 * Find the preferred location for the cluster.
261 */
230 brelse(sbp);
231 return (ENOSPC);
232 }
233 sbap = (int32_t *)sbp->b_data;
234 soff = idp->in_off;
235 }
236 /*
237 * Find the preferred location for the cluster.
238 */
262 pref = ext2_blkpref(ip, start_lbn, soff, sbap);
239 EXT2_LOCK(ump);
240 pref = ext2_blkpref(ip, start_lbn, soff, sbap, blkno);
263 /*
264 * If the block range spans two block maps, get the second map.
265 */
266 if (end_lvl == 0 || (idp = &end_ap[end_lvl - 1])->in_off + 1 >= len) {
267 ssize = len;
268 } else {
269#ifdef DIAGNOSTIC
270 if (start_ap[start_lvl-1].in_lbn == idp->in_lbn)
271 panic("ext2_reallocblk: start == end");
272#endif
273 ssize = len - (idp->in_off + 1);
241 /*
242 * If the block range spans two block maps, get the second map.
243 */
244 if (end_lvl == 0 || (idp = &end_ap[end_lvl - 1])->in_off + 1 >= len) {
245 ssize = len;
246 } else {
247#ifdef DIAGNOSTIC
248 if (start_ap[start_lvl-1].in_lbn == idp->in_lbn)
249 panic("ext2_reallocblk: start == end");
250#endif
251 ssize = len - (idp->in_off + 1);
274 if (bread(vp, idp->in_lbn, (int)fs->s_blocksize, NOCRED, &ebp))
252 if (bread(vp, idp->in_lbn, (int)fs->e2fs_bsize, NOCRED, &ebp)){
253 EXT2_UNLOCK(ump);
275 goto fail;
254 goto fail;
255 }
276 ebap = (int32_t *)ebp->b_data;
277 }
278 /*
279 * Search the block map looking for an allocation of the desired size.
280 */
256 ebap = (int32_t *)ebp->b_data;
257 }
258 /*
259 * Search the block map looking for an allocation of the desired size.
260 */
281 if ((newblk = (int32_t)ext2_hashalloc(ip, dtog(fs, pref), (long)pref,
282 len, (u_long (*)())ext2_clusteralloc)) == 0)
261 if ((newblk = (int32_t)ext2_hashalloc(ip, dtog(fs, pref), pref,
262 len, ext2_clusteralloc)) == 0){
263 EXT2_UNLOCK(ump);
283 goto fail;
264 goto fail;
265 }
284 /*
285 * We have found a new contiguous block.
286 *
287 * First we have to replace the old block pointers with the new
288 * block pointers in the inode and indirect blocks associated
289 * with the file.
290 */
291 blkno = newblk;
266 /*
267 * We have found a new contiguous block.
268 *
269 * First we have to replace the old block pointers with the new
270 * block pointers in the inode and indirect blocks associated
271 * with the file.
272 */
273 blkno = newblk;
292 for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->s_frags_per_block) {
274 for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->e2fs_fpb) {
293 if (i == ssize)
294 bap = ebap;
275 if (i == ssize)
276 bap = ebap;
277 soff = -i;
295#ifdef DIAGNOSTIC
296 if (buflist->bs_children[i]->b_blkno != fsbtodb(fs, *bap))
297 panic("ext2_reallocblks: alloc mismatch");
298#endif
299 *bap++ = blkno;
300 }
301 /*
302 * Next we must write out the modified inode and indirect blocks.

--- 14 unchanged lines hidden (view full) ---

317 bdwrite(sbp);
318 else
319 bwrite(sbp);
320 } else {
321 ip->i_flag |= IN_CHANGE | IN_UPDATE;
322 if (!doasyncfree)
323 ext2_update(vp, 1);
324 }
278#ifdef DIAGNOSTIC
279 if (buflist->bs_children[i]->b_blkno != fsbtodb(fs, *bap))
280 panic("ext2_reallocblks: alloc mismatch");
281#endif
282 *bap++ = blkno;
283 }
284 /*
285 * Next we must write out the modified inode and indirect blocks.

--- 14 unchanged lines hidden (view full) ---

300 bdwrite(sbp);
301 else
302 bwrite(sbp);
303 } else {
304 ip->i_flag |= IN_CHANGE | IN_UPDATE;
305 if (!doasyncfree)
306 ext2_update(vp, 1);
307 }
325 if (ssize < len)
308 if (ssize < len) {
326 if (doasyncfree)
327 bdwrite(ebp);
328 else
329 bwrite(ebp);
309 if (doasyncfree)
310 bdwrite(ebp);
311 else
312 bwrite(ebp);
313 }
330 /*
331 * Last, free the old blocks and assign the new blocks to the buffers.
332 */
314 /*
315 * Last, free the old blocks and assign the new blocks to the buffers.
316 */
333 for (blkno = newblk, i = 0; i < len; i++, blkno += fs->s_frags_per_block) {
317 for (blkno = newblk, i = 0; i < len; i++, blkno += fs->e2fs_fpb) {
334 ext2_blkfree(ip, dbtofsb(fs, buflist->bs_children[i]->b_blkno),
318 ext2_blkfree(ip, dbtofsb(fs, buflist->bs_children[i]->b_blkno),
335 fs->s_blocksize);
319 fs->e2fs_bsize);
336 buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno);
337 }
338 return (0);
339
340fail:
341 if (ssize < len)
342 brelse(ebp);
343 if (sbap != &ip->i_db[0])
344 brelse(sbp);
345 return (ENOSPC);
346
347#endif /* FANCY_REALLOC */
348}
349
350/*
351 * Allocate an inode in the file system.
352 *
320 buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno);
321 }
322 return (0);
323
324fail:
325 if (ssize < len)
326 brelse(ebp);
327 if (sbap != &ip->i_db[0])
328 brelse(sbp);
329 return (ENOSPC);
330
331#endif /* FANCY_REALLOC */
332}
333
334/*
335 * Allocate an inode in the file system.
336 *
353 * we leave the actual allocation strategy to the (modified)
354 * ext2_new_inode(), to make sure we get the policies right
355 */
356int
357ext2_valloc(pvp, mode, cred, vpp)
358 struct vnode *pvp;
359 int mode;
360 struct ucred *cred;
361 struct vnode **vpp;
362{
363 struct inode *pip;
337 */
338int
339ext2_valloc(pvp, mode, cred, vpp)
340 struct vnode *pvp;
341 int mode;
342 struct ucred *cred;
343 struct vnode **vpp;
344{
345 struct inode *pip;
364 struct ext2_sb_info *fs;
346 struct m_ext2fs *fs;
365 struct inode *ip;
347 struct inode *ip;
366 ino_t ino;
367 int i, error;
348 struct ext2mount *ump;
349 ino_t ino, ipref;
350 int i, error, cg;
368
369 *vpp = NULL;
370 pip = VTOI(pvp);
371 fs = pip->i_e2fs;
351
352 *vpp = NULL;
353 pip = VTOI(pvp);
354 fs = pip->i_e2fs;
372 if (fs->s_es->s_free_inodes_count == 0)
355 ump = pip->i_ump;
356
357 EXT2_LOCK(ump);
358 if (fs->e2fs->e2fs_ficount == 0)
373 goto noinodes;
359 goto noinodes;
360 /*
361 * If it is a directory then obtain a cylinder group based on
362 * ext2_dirpref else obtain it using ino_to_cg. The preferred inode is
363 * always the next inode.
364 */
365 if((mode & IFMT) == IFDIR) {
366 cg = ext2_dirpref(pip);
367 if (fs->e2fs_contigdirs[cg] < 255)
368 fs->e2fs_contigdirs[cg]++;
369 } else {
370 cg = ino_to_cg(fs, pip->i_number);
371 if (fs->e2fs_contigdirs[cg] > 0)
372 fs->e2fs_contigdirs[cg]--;
373 }
374 ipref = cg * fs->e2fs->e2fs_ipg + 1;
375 ino = (ino_t)ext2_hashalloc(pip, cg, (long)ipref, mode, ext2_nodealloccg);
374
376
375 /* call the Linux routine - it returns the inode number only */
376 ino = ext2_new_inode(pip, mode);
377
378 if (ino == 0)
377 if (ino == 0)
379 goto noinodes;
380 error = VFS_VGET(pvp->v_mount, ino, LK_EXCLUSIVE, vpp);
381 if (error) {
382 ext2_vfree(pvp, ino, mode);
383 return (error);
384 }
385 ip = VTOI(*vpp);
386

--- 18 unchanged lines hidden (view full) ---

405 */
406 if (ip->i_gen == 0 || ++ip->i_gen == 0)
407 ip->i_gen = random() / 2 + 1;
408/*
409printf("ext2_valloc: allocated inode %d\n", ino);
410*/
411 return (0);
412noinodes:
378 goto noinodes;
379 error = VFS_VGET(pvp->v_mount, ino, LK_EXCLUSIVE, vpp);
380 if (error) {
381 ext2_vfree(pvp, ino, mode);
382 return (error);
383 }
384 ip = VTOI(*vpp);
385

--- 18 unchanged lines hidden (view full) ---

404 */
405 if (ip->i_gen == 0 || ++ip->i_gen == 0)
406 ip->i_gen = random() / 2 + 1;
407/*
408printf("ext2_valloc: allocated inode %d\n", ino);
409*/
410 return (0);
411noinodes:
412 EXT2_UNLOCK(ump);
413 ext2_fserr(fs, cred->cr_uid, "out of inodes");
413 ext2_fserr(fs, cred->cr_uid, "out of inodes");
414 uprintf("\n%s: create/symlink failed, no inodes free\n", fs->fs_fsmnt);
414 uprintf("\n%s: create/symlink failed, no inodes free\n", fs->e2fs_fsmnt);
415 return (ENOSPC);
416}
417
418/*
415 return (ENOSPC);
416}
417
418/*
419 * Find a cylinder to place a directory.
420 *
421 * The policy implemented by this algorithm is to allocate a
422 * directory inode in the same cylinder group as its parent
423 * directory, but also to reserve space for its files inodes
424 * and data. Restrict the number of directories which may be
425 * allocated one after another in the same cylinder group
426 * without intervening allocation of files.
427 *
428 * If we allocate a first level directory then force allocation
429 * in another cylinder group.
430 *
431 */
432static u_long
433ext2_dirpref(struct inode *pip)
434{
435 struct m_ext2fs *fs;
436 int cg, prefcg, dirsize, cgsize;
437 int avgifree, avgbfree, avgndir, curdirsize;
438 int minifree, minbfree, maxndir;
439 int mincg, minndir;
440 int maxcontigdirs;
441
442 mtx_assert(EXT2_MTX(pip->i_ump), MA_OWNED);
443 fs = pip->i_e2fs;
444
445 avgifree = fs->e2fs->e2fs_ficount / fs->e2fs_gcount;
446 avgbfree = fs->e2fs->e2fs_fbcount / fs->e2fs_gcount;
447 avgndir = fs->e2fs_total_dir / fs->e2fs_gcount;
448
449 /*
450 * Force allocation in another cg if creating a first level dir.
451 */
452 ASSERT_VOP_LOCKED(ITOV(pip), "ext2fs_dirpref");
453 if (ITOV(pip)->v_vflag & VV_ROOT) {
454 prefcg = arc4random() % fs->e2fs_gcount;
455 mincg = prefcg;
456 minndir = fs->e2fs_ipg;
457 for (cg = prefcg; cg < fs->e2fs_gcount; cg++)
458 if (fs->e2fs_gd[cg].ext2bgd_ndirs < minndir &&
459 fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree &&
460 fs->e2fs_gd[cg].ext2bgd_nbfree >= avgbfree) {
461 mincg = cg;
462 minndir = fs->e2fs_gd[cg].ext2bgd_ndirs;
463 }
464 for (cg = 0; cg < prefcg; cg++)
465 if (fs->e2fs_gd[cg].ext2bgd_ndirs < minndir &&
466 fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree &&
467 fs->e2fs_gd[cg].ext2bgd_nbfree >= avgbfree) {
468 mincg = cg;
469 minndir = fs->e2fs_gd[cg].ext2bgd_ndirs;
470 }
471
472 return (mincg);
473 }
474
475 /*
476 * Count various limits which used for
477 * optimal allocation of a directory inode.
478 */
479 maxndir = min(avgndir + fs->e2fs_ipg / 16, fs->e2fs_ipg);
480 minifree = avgifree - avgifree / 4;
481 if (minifree < 1)
482 minifree = 1;
483 minbfree = avgbfree - avgbfree / 4;
484 if (minbfree < 1)
485 minbfree = 1;
486 cgsize = fs->e2fs_fsize * fs->e2fs_fpg;
487 dirsize = AVGDIRSIZE;
488 curdirsize = avgndir ? (cgsize - avgbfree * fs->e2fs_bsize) / avgndir : 0;
489 if (dirsize < curdirsize)
490 dirsize = curdirsize;
491 if (dirsize <= 0)
492 maxcontigdirs = 0; /* dirsize overflowed */
493 else
494 maxcontigdirs = min((avgbfree * fs->e2fs_bsize) / dirsize, 255);
495 maxcontigdirs = min(maxcontigdirs, fs->e2fs_ipg / AFPDIR);
496 if (maxcontigdirs == 0)
497 maxcontigdirs = 1;
498
499 /*
500 * Limit number of dirs in one cg and reserve space for
501 * regular files, but only if we have no deficit in
502 * inodes or space.
503 */
504 prefcg = ino_to_cg(fs, pip->i_number);
505 for (cg = prefcg; cg < fs->e2fs_gcount; cg++)
506 if (fs->e2fs_gd[cg].ext2bgd_ndirs < maxndir &&
507 fs->e2fs_gd[cg].ext2bgd_nifree >= minifree &&
508 fs->e2fs_gd[cg].ext2bgd_nbfree >= minbfree) {
509 if (fs->e2fs_contigdirs[cg] < maxcontigdirs)
510 return (cg);
511 }
512 for (cg = 0; cg < prefcg; cg++)
513 if (fs->e2fs_gd[cg].ext2bgd_ndirs < maxndir &&
514 fs->e2fs_gd[cg].ext2bgd_nifree >= minifree &&
515 fs->e2fs_gd[cg].ext2bgd_nbfree >= minbfree) {
516 if (fs->e2fs_contigdirs[cg] < maxcontigdirs)
517 return (cg);
518 }
519 /*
520 * This is a backstop when we have deficit in space.
521 */
522 for (cg = prefcg; cg < fs->e2fs_gcount; cg++)
523 if (fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree)
524 return (cg);
525 for (cg = 0; cg < prefcg; cg++)
526 if (fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree)
527 break;
528 return (cg);
529}
530
531/*
419 * Select the desired position for the next block in a file.
420 *
421 * we try to mimic what Remy does in inode_getblk/block_getblk
422 *
423 * we note: blocknr == 0 means that we're about to allocate either
424 * a direct block or a pointer block at the first level of indirection
425 * (In other words, stuff that will go in i_db[] or i_ib[])
426 *

--- 5 unchanged lines hidden (view full) ---

432ext2_blkpref(ip, lbn, indx, bap, blocknr)
433 struct inode *ip;
434 int32_t lbn;
435 int indx;
436 int32_t *bap;
437 int32_t blocknr;
438{
439 int tmp;
532 * Select the desired position for the next block in a file.
533 *
534 * we try to mimic what Remy does in inode_getblk/block_getblk
535 *
536 * we note: blocknr == 0 means that we're about to allocate either
537 * a direct block or a pointer block at the first level of indirection
538 * (In other words, stuff that will go in i_db[] or i_ib[])
539 *

--- 5 unchanged lines hidden (view full) ---

545ext2_blkpref(ip, lbn, indx, bap, blocknr)
546 struct inode *ip;
547 int32_t lbn;
548 int indx;
549 int32_t *bap;
550 int32_t blocknr;
551{
552 int tmp;
553 mtx_assert(EXT2_MTX(ip->i_ump), MA_OWNED);
440
441 /* if the next block is actually what we thought it is,
442 then set the goal to what we thought it should be
443 */
554
555 /* if the next block is actually what we thought it is,
556 then set the goal to what we thought it should be
557 */
444 if(ip->i_next_alloc_block == lbn)
558 if(ip->i_next_alloc_block == lbn && ip->i_next_alloc_goal != 0)
445 return ip->i_next_alloc_goal;
446
447 /* now check whether we were provided with an array that basically
448 tells us previous blocks to which we want to stay closeby
449 */
450 if(bap)
451 for (tmp = indx - 1; tmp >= 0; tmp--)
452 if (bap[tmp])
453 return bap[tmp];
454
455 /* else let's fall back to the blocknr, or, if there is none,
456 follow the rule that a block should be allocated near its inode
457 */
458 return blocknr ? blocknr :
459 (int32_t)(ip->i_block_group *
460 EXT2_BLOCKS_PER_GROUP(ip->i_e2fs)) +
559 return ip->i_next_alloc_goal;
560
561 /* now check whether we were provided with an array that basically
562 tells us previous blocks to which we want to stay closeby
563 */
564 if(bap)
565 for (tmp = indx - 1; tmp >= 0; tmp--)
566 if (bap[tmp])
567 return bap[tmp];
568
569 /* else let's fall back to the blocknr, or, if there is none,
570 follow the rule that a block should be allocated near its inode
571 */
572 return blocknr ? blocknr :
573 (int32_t)(ip->i_block_group *
574 EXT2_BLOCKS_PER_GROUP(ip->i_e2fs)) +
461 ip->i_e2fs->s_es->s_first_data_block;
575 ip->i_e2fs->e2fs->e2fs_first_dblock;
462}
463
464/*
576}
577
578/*
579 * Implement the cylinder overflow algorithm.
580 *
581 * The policy implemented by this algorithm is:
582 * 1) allocate the block in its requested cylinder group.
583 * 2) quadradically rehash on the cylinder group number.
584 * 3) brute force search for a free block.
585 */
586static u_long
587ext2_hashalloc(struct inode *ip, int cg, long pref, int size,
588 daddr_t (*allocator)(struct inode *, int, daddr_t, int))
589{
590 struct m_ext2fs *fs;
591 ino_t result;
592 int i, icg = cg;
593
594 mtx_assert(EXT2_MTX(ip->i_ump), MA_OWNED);
595 fs = ip->i_e2fs;
596 /*
597 * 1: preferred cylinder group
598 */
599 result = (*allocator)(ip, cg, pref, size);
600 if (result)
601 return (result);
602 /*
603 * 2: quadratic rehash
604 */
605 for (i = 1; i < fs->e2fs_gcount; i *= 2) {
606 cg += i;
607 if (cg >= fs->e2fs_gcount)
608 cg -= fs->e2fs_gcount;
609 result = (*allocator)(ip, cg, 0, size);
610 if (result)
611 return (result);
612 }
613 /*
614 * 3: brute force search
615 * Note that we start at i == 2, since 0 was checked initially,
616 * and 1 is always checked in the quadratic rehash.
617 */
618 cg = (icg + 2) % fs->e2fs_gcount;
619 for (i = 2; i < fs->e2fs_gcount; i++) {
620 result = (*allocator)(ip, cg, 0, size);
621 if (result)
622 return (result);
623 cg++;
624 if (cg == fs->e2fs_gcount)
625 cg = 0;
626 }
627 return (0);
628}
629
630/*
631 * Determine whether a block can be allocated.
632 *
633 * Check to see if a block of the appropriate size is available,
634 * and if it is, allocate it.
635 */
636static daddr_t
637ext2_alloccg(struct inode *ip, int cg, daddr_t bpref, int size)
638{
639 struct m_ext2fs *fs;
640 struct buf *bp;
641 struct ext2mount *ump;
642 int error, bno, start, end, loc;
643 char *bbp;
644 /* XXX ondisk32 */
645 fs = ip->i_e2fs;
646 ump = ip->i_ump;
647 if (fs->e2fs_gd[cg].ext2bgd_nbfree == 0)
648 return (0);
649 EXT2_UNLOCK(ump);
650 error = bread(ip->i_devvp, fsbtodb(fs,
651 fs->e2fs_gd[cg].ext2bgd_b_bitmap),
652 (int)fs->e2fs_bsize, NOCRED, &bp);
653 if (error) {
654 brelse(bp);
655 EXT2_LOCK(ump);
656 return (0);
657 }
658 bbp = (char *)bp->b_data;
659
660 if (dtog(fs, bpref) != cg)
661 bpref = 0;
662 if (bpref != 0) {
663 bpref = dtogd(fs, bpref);
664 /*
665 * if the requested block is available, use it
666 */
667 if (isclr(bbp, bpref)) {
668 bno = bpref;
669 goto gotit;
670 }
671 }
672 /*
673 * no blocks in the requested cylinder, so take next
674 * available one in this cylinder group.
675 * first try to get 8 contigous blocks, then fall back to a single
676 * block.
677 */
678 if (bpref)
679 start = dtogd(fs, bpref) / NBBY;
680 else
681 start = 0;
682 end = howmany(fs->e2fs->e2fs_fpg, NBBY) - start;
683 for (loc = start; loc < end; loc++) {
684 if (bbp[loc] == 0) {
685 bno = loc * NBBY;
686 goto gotit;
687 }
688 }
689 for (loc = 0; loc < start; loc++) {
690 if (bbp[loc] == 0) {
691 bno = loc * NBBY;
692 goto gotit;
693 }
694 }
695
696 bno = ext2_mapsearch(fs, bbp, bpref);
697 if (bno < 0){
698 brelse(bp);
699 EXT2_LOCK(ump);
700 return (0);
701 }
702gotit:
703#ifdef DIAGNOSTIC
704 if (isset(bbp, (daddr_t)bno)) {
705 printf("ext2fs_alloccgblk: cg=%d bno=%d fs=%s\n",
706 cg, bno, fs->e2fs_fsmnt);
707 panic("ext2fs_alloccg: dup alloc");
708 }
709#endif
710 setbit(bbp, (daddr_t)bno);
711 EXT2_LOCK(ump);
712 fs->e2fs->e2fs_fbcount--;
713 fs->e2fs_gd[cg].ext2bgd_nbfree--;
714 fs->e2fs_fmod = 1;
715 EXT2_UNLOCK(ump);
716 bdwrite(bp);
717 return (cg * fs->e2fs->e2fs_fpg + fs->e2fs->e2fs_first_dblock + bno);
718}
719
720/*
721 * Determine whether an inode can be allocated.
722 *
723 * Check to see if an inode is available, and if it is,
724 * allocate it using tode in the specified cylinder group.
725 */
726static daddr_t
727ext2_nodealloccg(struct inode *ip, int cg, daddr_t ipref, int mode)
728{
729 struct m_ext2fs *fs;
730 struct buf *bp;
731 struct ext2mount *ump;
732 int error, start, len, loc, map, i;
733 char *ibp;
734 ipref--; /* to avoid a lot of (ipref -1) */
735 if (ipref == -1)
736 ipref = 0;
737 fs = ip->i_e2fs;
738 ump = ip->i_ump;
739 if (fs->e2fs_gd[cg].ext2bgd_nifree == 0)
740 return (0);
741 EXT2_UNLOCK(ump);
742 error = bread(ip->i_devvp, fsbtodb(fs,
743 fs->e2fs_gd[cg].ext2bgd_i_bitmap),
744 (int)fs->e2fs_bsize, NOCRED, &bp);
745 if (error) {
746 brelse(bp);
747 EXT2_LOCK(ump);
748 return (0);
749 }
750 ibp = (char *)bp->b_data;
751 if (ipref) {
752 ipref %= fs->e2fs->e2fs_ipg;
753 if (isclr(ibp, ipref))
754 goto gotit;
755 }
756 start = ipref / NBBY;
757 len = howmany(fs->e2fs->e2fs_ipg - ipref, NBBY);
758 loc = skpc(0xff, len, &ibp[start]);
759 if (loc == 0) {
760 len = start + 1;
761 start = 0;
762 loc = skpc(0xff, len, &ibp[0]);
763 if (loc == 0) {
764 printf("cg = %d, ipref = %lld, fs = %s\n",
765 cg, (long long)ipref, fs->e2fs_fsmnt);
766 panic("ext2fs_nodealloccg: map corrupted");
767 /* NOTREACHED */
768 }
769 }
770 i = start + len - loc;
771 map = ibp[i];
772 ipref = i * NBBY;
773 for (i = 1; i < (1 << NBBY); i <<= 1, ipref++) {
774 if ((map & i) == 0) {
775 goto gotit;
776 }
777 }
778 printf("fs = %s\n", fs->e2fs_fsmnt);
779 panic("ext2fs_nodealloccg: block not in map");
780 /* NOTREACHED */
781gotit:
782 setbit(ibp, ipref);
783 EXT2_LOCK(ump);
784 fs->e2fs_gd[cg].ext2bgd_nifree--;
785 fs->e2fs->e2fs_ficount--;
786 fs->e2fs_fmod = 1;
787 if ((mode & IFMT) == IFDIR) {
788 fs->e2fs_gd[cg].ext2bgd_ndirs++;
789 fs->e2fs_total_dir++;
790 }
791 EXT2_UNLOCK(ump);
792 bdwrite(bp);
793 return (cg * fs->e2fs->e2fs_ipg + ipref +1);
794}
795
796/*
465 * Free a block or fragment.
466 *
797 * Free a block or fragment.
798 *
467 * pass on to the Linux code
468 */
469void
470ext2_blkfree(ip, bno, size)
471 struct inode *ip;
472 int32_t bno;
473 long size;
474{
799 */
800void
801ext2_blkfree(ip, bno, size)
802 struct inode *ip;
803 int32_t bno;
804 long size;
805{
475 struct ext2_sb_info *fs;
806 struct m_ext2fs *fs;
807 struct buf *bp;
808 struct ext2mount *ump;
809 int cg, error;
810 char *bbp;
476
477 fs = ip->i_e2fs;
811
812 fs = ip->i_e2fs;
478 /*
479 * call Linux code with mount *, block number, count
480 */
481 ext2_free_blocks(ITOV(ip)->v_mount, bno, size / fs->s_frag_size);
813 ump = ip->i_ump;
814 cg = dtog(fs, bno);
815 if ((u_int)bno >= fs->e2fs->e2fs_bcount) {
816 printf("bad block %lld, ino %llu\n", (long long)bno,
817 (unsigned long long)ip->i_number);
818 ext2_fserr(fs, ip->i_uid, "bad block");
819 return;
820 }
821 error = bread(ip->i_devvp,
822 fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap),
823 (int)fs->e2fs_bsize, NOCRED, &bp);
824 if (error) {
825 brelse(bp);
826 return;
827 }
828 bbp = (char *)bp->b_data;
829 bno = dtogd(fs, bno);
830 if (isclr(bbp, bno)) {
831 printf("block = %lld, fs = %s\n",
832 (long long)bno, fs->e2fs_fsmnt);
833 panic("blkfree: freeing free block");
834 }
835 clrbit(bbp, bno);
836 EXT2_LOCK(ump);
837 fs->e2fs->e2fs_fbcount++;
838 fs->e2fs_gd[cg].ext2bgd_nbfree++;
839 fs->e2fs_fmod = 1;
840 EXT2_UNLOCK(ump);
841 bdwrite(bp);
482}
483
484/*
485 * Free an inode.
486 *
842}
843
844/*
845 * Free an inode.
846 *
487 * the maintenance of the actual bitmaps is again up to the linux code
488 */
489int
490ext2_vfree(pvp, ino, mode)
491 struct vnode *pvp;
492 ino_t ino;
493 int mode;
494{
847 */
848int
849ext2_vfree(pvp, ino, mode)
850 struct vnode *pvp;
851 ino_t ino;
852 int mode;
853{
495 struct ext2_sb_info *fs;
854 struct m_ext2fs *fs;
496 struct inode *pip;
855 struct inode *pip;
497 mode_t save_i_mode;
856 struct buf *bp;
857 struct ext2mount *ump;
858 int error, cg;
859 char * ibp;
860/* mode_t save_i_mode; */
498
499 pip = VTOI(pvp);
500 fs = pip->i_e2fs;
861
862 pip = VTOI(pvp);
863 fs = pip->i_e2fs;
501 if ((u_int)ino > fs->s_inodes_per_group * fs->s_groups_count)
864 ump = pip->i_ump;
865 if ((u_int)ino > fs->e2fs_ipg * fs->e2fs_gcount)
502 panic("ext2_vfree: range: devvp = %p, ino = %d, fs = %s",
866 panic("ext2_vfree: range: devvp = %p, ino = %d, fs = %s",
503 pip->i_devvp, ino, fs->fs_fsmnt);
867 pip->i_devvp, ino, fs->e2fs_fsmnt);
504
868
505/* ext2_debug("ext2_vfree (%d, %d) called\n", pip->i_number, mode);
869 cg = ino_to_cg(fs, ino);
870 error = bread(pip->i_devvp,
871 fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_i_bitmap),
872 (int)fs->e2fs_bsize, NOCRED, &bp);
873 if (error) {
874 brelse(bp);
875 return (0);
876 }
877 ibp = (char *)bp->b_data;
878 ino = (ino - 1) % fs->e2fs->e2fs_ipg;
879 if (isclr(ibp, ino)) {
880 printf("ino = %llu, fs = %s\n",
881 (unsigned long long)ino, fs->e2fs_fsmnt);
882 if (fs->e2fs_ronly == 0)
883 panic("ifree: freeing free inode");
884 }
885 clrbit(ibp, ino);
886 EXT2_LOCK(ump);
887 fs->e2fs->e2fs_ficount++;
888 fs->e2fs_gd[cg].ext2bgd_nifree++;
889 if ((mode & IFMT) == IFDIR) {
890 fs->e2fs_gd[cg].ext2bgd_ndirs--;
891 fs->e2fs_total_dir--;
892 }
893 fs->e2fs_fmod = 1;
894 EXT2_UNLOCK(ump);
895 bdwrite(bp);
896 return (0);
897}
898
899/*
900 * Find a block in the specified cylinder group.
901 *
902 * It is a panic if a request is made to find a block if none are
903 * available.
506 */
904 */
507 ext2_discard_prealloc(pip);
905static daddr_t
906ext2_mapsearch(struct m_ext2fs *fs, char *bbp, daddr_t bpref)
907{
908 daddr_t bno;
909 int start, len, loc, i, map;
508
910
509 /* we need to make sure that ext2_free_inode can adjust the
510 used_dir_counts in the group summary information - I'd
511 really like to know what the rationale behind this
512 'set i_mode to zero to denote an unused inode' is
911 /*
912 * find the fragment by searching through the free block
913 * map for an appropriate bit pattern
513 */
914 */
514 save_i_mode = pip->i_mode;
515 pip->i_mode = mode;
516 ext2_free_inode(pip);
517 pip->i_mode = save_i_mode;
518 return (0);
915 if (bpref)
916 start = dtogd(fs, bpref) / NBBY;
917 else
918 start = 0;
919 len = howmany(fs->e2fs->e2fs_fpg, NBBY) - start;
920 loc = skpc(0xff, len, &bbp[start]);
921 if (loc == 0) {
922 len = start + 1;
923 start = 0;
924 loc = skpc(0xff, len, &bbp[start]);
925 if (loc == 0) {
926 printf("start = %d, len = %d, fs = %s\n",
927 start, len, fs->e2fs_fsmnt);
928 panic("ext2fs_alloccg: map corrupted");
929 /* NOTREACHED */
930 }
931 }
932 i = start + len - loc;
933 map = bbp[i];
934 bno = i * NBBY;
935 for (i = 1; i < (1 << NBBY); i <<= 1, bno++) {
936 if ((map & i) == 0)
937 return (bno);
938 }
939 printf("fs = %s\n", fs->e2fs_fsmnt);
940 panic("ext2fs_mapsearch: block not in map");
941 /* NOTREACHED */
519}
520
521/*
522 * Fserr prints the name of a file system with an error diagnostic.
523 *
524 * The form of the error message is:
525 * fs: error message
526 */
527static void
528ext2_fserr(fs, uid, cp)
942}
943
944/*
945 * Fserr prints the name of a file system with an error diagnostic.
946 *
947 * The form of the error message is:
948 * fs: error message
949 */
950static void
951ext2_fserr(fs, uid, cp)
529 struct ext2_sb_info *fs;
530 u_int uid;
952 struct m_ext2fs *fs;
953 uid_t uid;
531 char *cp;
532{
533
954 char *cp;
955{
956
534 log(LOG_ERR, "uid %d on %s: %s\n", uid, fs->fs_fsmnt, cp);
957 log(LOG_ERR, "uid %u on %s: %s\n", uid, fs->e2fs_fsmnt, cp);
535}
958}
959
960int
961cg_has_sb(int i)
962{
963 int a3, a5, a7;
964
965 if (i == 0 || i == 1)
966 return 1;
967 for (a3 = 3, a5 = 5, a7 = 7;
968 a3 <= i || a5 <= i || a7 <= i;
969 a3 *= 3, a5 *= 5, a7 *= 7)
970 if (i == a3 || i == a5 || i == a7)
971 return 1;
972 return 0;
973}