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