ext2_alloc.c revision 30492
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
9 *	The Regents of the University of California.  All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 *    must display the following acknowledgement:
21 *	This product includes software developed by the University of
22 *	California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 *    may be used to endorse or promote products derived from this software
25 *    without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 *	@(#)ext2_alloc.c	8.8 (Berkeley) 2/21/94
40 */
41
42#if !defined(__FreeBSD__)
43#include "quota.h"
44#include "diagnostic.h"
45#else
46#include "opt_quota.h"
47#endif
48
49#include <sys/param.h>
50#include <sys/systm.h>
51#include <sys/vnode.h>
52#include <sys/stat.h>
53#include <sys/mount.h>
54#include <sys/kernel.h>
55#include <sys/syslog.h>
56
57#include <ufs/ufs/quota.h>
58#include <ufs/ufs/inode.h>
59#include <ufs/ufs/ufsmount.h>
60
61#include <gnu/ext2fs/ext2_fs.h>
62#include <gnu/ext2fs/ext2_fs_sb.h>
63#include <gnu/ext2fs/fs.h>
64#include <gnu/ext2fs/ext2_extern.h>
65
66extern u_long nextgennumber;
67
68static void	ext2_fserr __P((struct ext2_sb_info *, u_int, char *));
69
70/*
71 * Linux calls this functions at the following locations:
72 * (1) the inode is freed
73 * (2) a preallocation miss occurs
74 * (3) truncate is called
75 * (4) release_file is called and f_mode & 2
76 *
77 * I call it in ext2_inactive, ext2_truncate, ext2_vfree and in (2)
78 * the call in vfree might be redundant
79 */
80void
81ext2_discard_prealloc(ip)
82	struct inode * ip;
83{
84#ifdef EXT2_PREALLOCATE
85        if (ip->i_prealloc_count) {
86                int i = ip->i_prealloc_count;
87                ip->i_prealloc_count = 0;
88                ext2_free_blocks (ITOV(ip)->v_mount,
89                                  ip->i_prealloc_block,
90                                  i);
91        }
92#endif
93}
94
95/*
96 * Allocate a block in the file system.
97 *
98 * this takes the framework from ffs_alloc. To implement the
99 * actual allocation, it calls ext2_new_block, the ported version
100 * of the same Linux routine.
101 *
102 * we note that this is always called in connection with ext2_blkpref
103 *
104 * preallocation is done as Linux does it
105 */
106int
107ext2_alloc(ip, lbn, bpref, size, cred, bnp)
108	register struct inode *ip;
109	daddr_t lbn, bpref;
110	int size;
111	struct ucred *cred;
112	daddr_t *bnp;
113{
114	register struct ext2_sb_info *fs;
115	daddr_t bno;
116#if QUOTA
117	int error;
118#endif
119
120	*bnp = 0;
121	fs = ip->i_e2fs;
122#if DIAGNOSTIC
123	if ((u_int)size > fs->s_blocksize || blkoff(fs, size) != 0) {
124		printf("dev = 0x%x, bsize = %d, size = %d, fs = %s\n",
125		    ip->i_dev, fs->s_blocksize, size, fs->fs_fsmnt);
126		panic("ext2_alloc: bad size");
127	}
128	if (cred == NOCRED)
129		panic("ext2_alloc: missing credential");
130#endif /* DIAGNOSTIC */
131	if (size == fs->s_blocksize && fs->s_es->s_free_blocks_count == 0)
132		goto nospace;
133	if (cred->cr_uid != 0 &&
134		fs->s_es->s_free_blocks_count < fs->s_es->s_r_blocks_count)
135		goto nospace;
136#if QUOTA
137	if (error = chkdq(ip, (long)btodb(size), cred, 0))
138		return (error);
139#endif
140	if (bpref >= fs->s_es->s_blocks_count)
141		bpref = 0;
142	/* call the Linux code */
143#ifdef EXT2_PREALLOCATE
144	/* To have a preallocation hit, we must
145	 * - have at least one block preallocated
146	 * - and our preferred block must have that block number or one below
147	 */
148        if (ip->i_prealloc_count &&
149            (bpref == ip->i_prealloc_block ||
150             bpref + 1 == ip->i_prealloc_block))
151        {
152                bno = ip->i_prealloc_block++;
153                ip->i_prealloc_count--;
154                /* ext2_debug ("preallocation hit (%lu/%lu).\n",
155                            ++alloc_hits, ++alloc_attempts); */
156
157		/* Linux gets, clears, and releases the buffer at this
158		   point - we don't have to that; we leave it to the caller
159		 */
160        } else {
161                ext2_discard_prealloc (ip);
162                /* ext2_debug ("preallocation miss (%lu/%lu).\n",
163                            alloc_hits, ++alloc_attempts); */
164                if (S_ISREG(ip->i_mode))
165                        bno = ext2_new_block
166                                (ITOV(ip)->v_mount, bpref,
167                                 &ip->i_prealloc_count,
168                                 &ip->i_prealloc_block);
169                else
170			bno = (daddr_t)ext2_new_block(ITOV(ip)->v_mount,
171					bpref, 0, 0);
172        }
173#else
174	bno = (daddr_t)ext2_new_block(ITOV(ip)->v_mount, bpref, 0, 0);
175#endif
176
177	if (bno > 0) {
178		/* set next_alloc fields as done in block_getblk */
179		ip->i_next_alloc_block = lbn;
180		ip->i_next_alloc_goal = bno;
181
182		ip->i_blocks += btodb(size);
183		ip->i_flag |= IN_CHANGE | IN_UPDATE;
184		*bnp = bno;
185		return (0);
186	}
187#if QUOTA
188	/*
189	 * Restore user's disk quota because allocation failed.
190	 */
191	(void) chkdq(ip, (long)-btodb(size), cred, FORCE);
192#endif
193nospace:
194	ext2_fserr(fs, cred->cr_uid, "file system full");
195	uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt);
196	return (ENOSPC);
197}
198
199/*
200 * Reallocate a sequence of blocks into a contiguous sequence of blocks.
201 *
202 * The vnode and an array of buffer pointers for a range of sequential
203 * logical blocks to be made contiguous is given. The allocator attempts
204 * to find a range of sequential blocks starting as close as possible to
205 * an fs_rotdelay offset from the end of the allocation for the logical
206 * block immediately preceeding the current range. If successful, the
207 * physical block numbers in the buffer pointers and in the inode are
208 * changed to reflect the new allocation. If unsuccessful, the allocation
209 * is left unchanged. The success in doing the reallocation is returned.
210 * Note that the error return is not reflected back to the user. Rather
211 * the previous block allocation will be used.
212 */
213
214#ifdef FANCY_REALLOC
215#include <sys/sysctl.h>
216static int doasyncfree = 1;
217#ifdef	OPT_DEBUG
218SYSCTL_INT(_debug, 14, doasyncfree, CTLFLAG_RW, &doasyncfree, 0, "");
219#endif	/* OPT_DEBUG */
220#endif
221
222int
223ext2_reallocblks(ap)
224	struct vop_reallocblks_args /* {
225		struct vnode *a_vp;
226		struct cluster_save *a_buflist;
227	} */ *ap;
228{
229#ifndef FANCY_REALLOC
230/* printf("ext2_reallocblks not implemented\n"); */
231return ENOSPC;
232#else
233
234	struct ext2_sb_info *fs;
235	struct inode *ip;
236	struct vnode *vp;
237	struct buf *sbp, *ebp;
238	daddr_t *bap, *sbap, *ebap;
239	struct cluster_save *buflist;
240	daddr_t start_lbn, end_lbn, soff, eoff, newblk, blkno;
241	struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp;
242	int i, len, start_lvl, end_lvl, pref, ssize;
243	struct timeval tv;
244
245	vp = ap->a_vp;
246	ip = VTOI(vp);
247	fs = ip->i_e2fs;
248#ifdef UNKLAR
249	if (fs->fs_contigsumsize <= 0)
250		return (ENOSPC);
251#endif
252	buflist = ap->a_buflist;
253	len = buflist->bs_nchildren;
254	start_lbn = buflist->bs_children[0]->b_lblkno;
255	end_lbn = start_lbn + len - 1;
256#if DIAGNOSTIC
257	for (i = 1; i < len; i++)
258		if (buflist->bs_children[i]->b_lblkno != start_lbn + i)
259			panic("ext2_reallocblks: non-cluster");
260#endif
261	/*
262	 * If the latest allocation is in a new cylinder group, assume that
263	 * the filesystem has decided to move and do not force it back to
264	 * the previous cylinder group.
265	 */
266	if (dtog(fs, dbtofsb(fs, buflist->bs_children[0]->b_blkno)) !=
267	    dtog(fs, dbtofsb(fs, buflist->bs_children[len - 1]->b_blkno)))
268		return (ENOSPC);
269	if (ufs_getlbns(vp, start_lbn, start_ap, &start_lvl) ||
270	    ufs_getlbns(vp, end_lbn, end_ap, &end_lvl))
271		return (ENOSPC);
272	/*
273	 * Get the starting offset and block map for the first block.
274	 */
275	if (start_lvl == 0) {
276		sbap = &ip->i_db[0];
277		soff = start_lbn;
278	} else {
279		idp = &start_ap[start_lvl - 1];
280		if (bread(vp, idp->in_lbn, (int)fs->s_blocksize, NOCRED, &sbp)) {
281			brelse(sbp);
282			return (ENOSPC);
283		}
284		sbap = (daddr_t *)sbp->b_data;
285		soff = idp->in_off;
286	}
287	/*
288	 * Find the preferred location for the cluster.
289	 */
290	pref = ext2_blkpref(ip, start_lbn, soff, sbap);
291	/*
292	 * If the block range spans two block maps, get the second map.
293	 */
294	if (end_lvl == 0 || (idp = &end_ap[end_lvl - 1])->in_off + 1 >= len) {
295		ssize = len;
296	} else {
297#if DIAGNOSTIC
298		if (start_ap[start_lvl-1].in_lbn == idp->in_lbn)
299			panic("ext2_reallocblk: start == end");
300#endif
301		ssize = len - (idp->in_off + 1);
302		if (bread(vp, idp->in_lbn, (int)fs->s_blocksize, NOCRED, &ebp))
303			goto fail;
304		ebap = (daddr_t *)ebp->b_data;
305	}
306	/*
307	 * Search the block map looking for an allocation of the desired size.
308	 */
309	if ((newblk = (daddr_t)ext2_hashalloc(ip, dtog(fs, pref), (long)pref,
310	    len, (u_long (*)())ext2_clusteralloc)) == 0)
311		goto fail;
312	/*
313	 * We have found a new contiguous block.
314	 *
315	 * First we have to replace the old block pointers with the new
316	 * block pointers in the inode and indirect blocks associated
317	 * with the file.
318	 */
319	blkno = newblk;
320	for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->s_frags_per_block) {
321		if (i == ssize)
322			bap = ebap;
323#if DIAGNOSTIC
324		if (buflist->bs_children[i]->b_blkno != fsbtodb(fs, *bap))
325			panic("ext2_reallocblks: alloc mismatch");
326#endif
327		*bap++ = blkno;
328	}
329	/*
330	 * Next we must write out the modified inode and indirect blocks.
331	 * For strict correctness, the writes should be synchronous since
332	 * the old block values may have been written to disk. In practise
333	 * they are almost never written, but if we are concerned about
334	 * strict correctness, the `doasyncfree' flag should be set to zero.
335	 *
336	 * The test on `doasyncfree' should be changed to test a flag
337	 * that shows whether the associated buffers and inodes have
338	 * been written. The flag should be set when the cluster is
339	 * started and cleared whenever the buffer or inode is flushed.
340	 * We can then check below to see if it is set, and do the
341	 * synchronous write only when it has been cleared.
342	 */
343	if (sbap != &ip->i_db[0]) {
344		if (doasyncfree)
345			bdwrite(sbp);
346		else
347			bwrite(sbp);
348	} else {
349		ip->i_flag |= IN_CHANGE | IN_UPDATE;
350		if (!doasyncfree) {
351			gettime(&tv);
352			UFS_UPDATE(vp, &tv, &tv, MNT_WAIT);
353		}
354	}
355	if (ssize < len)
356		if (doasyncfree)
357			bdwrite(ebp);
358		else
359			bwrite(ebp);
360	/*
361	 * Last, free the old blocks and assign the new blocks to the buffers.
362	 */
363	for (blkno = newblk, i = 0; i < len; i++, blkno += fs->s_frags_per_block) {
364		ext2_blkfree(ip, dbtofsb(fs, buflist->bs_children[i]->b_blkno),
365		    fs->s_blocksize);
366		buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno);
367	}
368	return (0);
369
370fail:
371	if (ssize < len)
372		brelse(ebp);
373	if (sbap != &ip->i_db[0])
374		brelse(sbp);
375	return (ENOSPC);
376
377#endif /* FANCY_REALLOC */
378}
379
380/*
381 * Allocate an inode in the file system.
382 *
383 * we leave the actual allocation strategy to the (modified)
384 * ext2_new_inode(), to make sure we get the policies right
385 */
386int
387ext2_valloc(pvp, mode, cred, vpp)
388	struct vnode *pvp;
389	int mode;
390	struct ucred *cred;
391	struct vnode **vpp;
392{
393	register struct inode *pip;
394	register struct ext2_sb_info *fs;
395	register struct inode *ip;
396	ino_t ino;
397	int i, error;
398#if !defined(__FreeBSD__)
399	struct timeval time;
400#endif
401
402	*vpp = NULL;
403	pip = VTOI(pvp);
404	fs = pip->i_e2fs;
405	if (fs->s_es->s_free_inodes_count == 0)
406		goto noinodes;
407
408	/* call the Linux routine - it returns the inode number only */
409	ino = ext2_new_inode(pip, mode);
410
411	if (ino == 0)
412		goto noinodes;
413	error = VFS_VGET(pvp->v_mount, ino, vpp);
414	if (error) {
415		UFS_VFREE(pvp, ino, mode);
416		return (error);
417	}
418	ip = VTOI(*vpp);
419
420	/*
421	  the question is whether using VGET was such good idea at all -
422	  Linux doesn't read the old inode in when it's allocating a
423	  new one. I will set at least i_size & i_blocks the zero.
424	*/
425	ip->i_mode = 0;
426	ip->i_size = 0;
427	ip->i_blocks = 0;
428	ip->i_flags = 0;
429        /* now we want to make sure that the block pointers are zeroed out */
430        for(i = 0; i < EXT2_NDIR_BLOCKS; i++)
431                ip->i_db[i] = 0;
432
433	/*
434	 * Set up a new generation number for this inode.
435	 * XXX check if this makes sense in ext2
436	 */
437#if !defined(__FreeBSD__)
438	gettime(&time);
439#endif
440	if (++nextgennumber < (u_long)time.tv_sec)
441		nextgennumber = time.tv_sec;
442	ip->i_gen = nextgennumber;
443/*
444printf("ext2_valloc: allocated inode %d\n", ino);
445*/
446	return (0);
447noinodes:
448	ext2_fserr(fs, cred->cr_uid, "out of inodes");
449	uprintf("\n%s: create/symlink failed, no inodes free\n", fs->fs_fsmnt);
450	return (ENOSPC);
451}
452
453/*
454 * Select the desired position for the next block in a file.
455 *
456 * we try to mimic what Remy does in inode_getblk/block_getblk
457 *
458 * we note: blocknr == 0 means that we're about to allocate either
459 * a direct block or a pointer block at the first level of indirection
460 * (In other words, stuff that will go in i_db[] or i_ib[])
461 *
462 * blocknr != 0 means that we're allocating a block that is none
463 * of the above. Then, blocknr tells us the number of the block
464 * that will hold the pointer
465 */
466daddr_t
467ext2_blkpref(ip, lbn, indx, bap, blocknr)
468	struct inode *ip;
469	daddr_t lbn;
470	int indx;
471	daddr_t *bap;
472	daddr_t blocknr;
473{
474	int	tmp;
475
476	/* if the next block is actually what we thought it is,
477	   then set the goal to what we thought it should be
478	*/
479	if(ip->i_next_alloc_block == lbn)
480		return ip->i_next_alloc_goal;
481
482	/* now check whether we were provided with an array that basically
483	   tells us previous blocks to which we want to stay closeby
484	*/
485	if(bap)
486                for (tmp = indx - 1; tmp >= 0; tmp--)
487			if (bap[tmp])
488				return bap[tmp];
489
490	/* else let's fall back to the blocknr, or, if there is none,
491	   follow the rule that a block should be allocated near it's inode
492	*/
493	return blocknr ? blocknr :
494			(daddr_t)(ip->i_block_group *
495			EXT2_BLOCKS_PER_GROUP(ip->i_e2fs)) +
496			ip->i_e2fs->s_es->s_first_data_block;
497}
498
499/*
500 * Free a block or fragment.
501 *
502 * pass on to the Linux code
503 */
504void
505ext2_blkfree(ip, bno, size)
506	register struct inode *ip;
507	daddr_t bno;
508	long size;
509{
510	register struct ext2_sb_info *fs;
511
512	fs = ip->i_e2fs;
513	/*
514	 *	call Linux code with mount *, block number, count
515	 */
516	ext2_free_blocks(ITOV(ip)->v_mount, bno, size / fs->s_frag_size);
517}
518
519/*
520 * Free an inode.
521 *
522 * the maintenance of the actual bitmaps is again up to the linux code
523 */
524int
525ext2_vfree(pvp, ino, mode)
526	struct vnode *pvp;
527	ino_t ino;
528	int mode;
529{
530	register struct ext2_sb_info *fs;
531	register struct inode *pip;
532
533	pip = VTOI(pvp);
534	fs = pip->i_e2fs;
535	if ((u_int)ino >= fs->s_inodes_per_group * fs->s_groups_count)
536		panic("ifree: range: dev = 0x%x, ino = %d, fs = %s",
537		    pip->i_dev, ino, fs->fs_fsmnt);
538
539/* ext2_debug("ext2_vfree (%d, %d) called\n", pip->i_number, mode);
540 */
541	ext2_discard_prealloc(pip);
542
543	/* we need to make sure that ext2_free_inode can adjust the
544	   used_dir_counts in the group summary information - I'd
545	   really like to know what the rationale behind this
546	   'set i_mode to zero to denote an unused inode' is
547	 */
548	mode = pip->i_mode;
549	pip->i_mode = mode;
550	ext2_free_inode(pip);
551	pip->i_mode = mode;
552	return (0);
553}
554
555/*
556 * Fserr prints the name of a file system with an error diagnostic.
557 *
558 * The form of the error message is:
559 *	fs: error message
560 */
561static void
562ext2_fserr(fs, uid, cp)
563	struct ext2_sb_info *fs;
564	u_int uid;
565	char *cp;
566{
567
568	log(LOG_ERR, "uid %d on %s: %s\n", uid, fs->fs_fsmnt, cp);
569}
570