1995-11-05 23:25:12 +00:00
|
|
|
/*
|
|
|
|
* modified for Lites 1.1
|
|
|
|
*
|
|
|
|
* Aug 1995, Godmar Back (gback@cs.utah.edu)
|
|
|
|
* University of Utah, Department of Computer Science
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* Copyright (c) 1982, 1986, 1989, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 4. Neither the name of the University nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
2002-03-23 13:41:52 +00:00
|
|
|
* @(#)ffs_alloc.c 8.8 (Berkeley) 2/21/94
|
2000-04-15 17:14:22 +00:00
|
|
|
* $FreeBSD$
|
1995-11-05 23:25:12 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
1999-08-23 22:05:49 +00:00
|
|
|
#include <sys/conf.h>
|
1995-11-05 23:25:12 +00:00
|
|
|
#include <sys/vnode.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/mount.h>
|
|
|
|
#include <sys/syslog.h>
|
|
|
|
|
2002-05-16 19:08:03 +00:00
|
|
|
#include <gnu/ext2fs/inode.h>
|
|
|
|
#include <gnu/ext2fs/ext2_mount.h>
|
1995-11-05 23:25:12 +00:00
|
|
|
#include <gnu/ext2fs/ext2_fs.h>
|
|
|
|
#include <gnu/ext2fs/ext2_fs_sb.h>
|
|
|
|
#include <gnu/ext2fs/fs.h>
|
|
|
|
#include <gnu/ext2fs/ext2_extern.h>
|
|
|
|
|
2002-03-19 22:40:48 +00:00
|
|
|
static void ext2_fserr(struct ext2_sb_info *, u_int, char *);
|
1995-11-05 23:25:12 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Linux calls this functions at the following locations:
|
|
|
|
* (1) the inode is freed
|
|
|
|
* (2) a preallocation miss occurs
|
|
|
|
* (3) truncate is called
|
|
|
|
* (4) release_file is called and f_mode & 2
|
|
|
|
*
|
|
|
|
* I call it in ext2_inactive, ext2_truncate, ext2_vfree and in (2)
|
|
|
|
* the call in vfree might be redundant
|
|
|
|
*/
|
1997-04-01 15:22:59 +00:00
|
|
|
void
|
|
|
|
ext2_discard_prealloc(ip)
|
|
|
|
struct inode * ip;
|
1995-11-05 23:25:12 +00:00
|
|
|
{
|
|
|
|
#ifdef EXT2_PREALLOCATE
|
|
|
|
if (ip->i_prealloc_count) {
|
|
|
|
int i = ip->i_prealloc_count;
|
|
|
|
ip->i_prealloc_count = 0;
|
|
|
|
ext2_free_blocks (ITOV(ip)->v_mount,
|
|
|
|
ip->i_prealloc_block,
|
|
|
|
i);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Allocate a block in the file system.
|
|
|
|
*
|
|
|
|
* this takes the framework from ffs_alloc. To implement the
|
|
|
|
* actual allocation, it calls ext2_new_block, the ported version
|
|
|
|
* of the same Linux routine.
|
|
|
|
*
|
|
|
|
* we note that this is always called in connection with ext2_blkpref
|
|
|
|
*
|
|
|
|
* preallocation is done as Linux does it
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
ext2_alloc(ip, lbn, bpref, size, cred, bnp)
|
2002-05-16 19:43:28 +00:00
|
|
|
struct inode *ip;
|
2002-05-18 19:12:38 +00:00
|
|
|
int32_t lbn, bpref;
|
1995-11-05 23:25:12 +00:00
|
|
|
int size;
|
|
|
|
struct ucred *cred;
|
2002-05-18 19:12:38 +00:00
|
|
|
int32_t *bnp;
|
1995-11-05 23:25:12 +00:00
|
|
|
{
|
2002-05-16 19:43:28 +00:00
|
|
|
struct ext2_sb_info *fs;
|
2002-05-18 19:12:38 +00:00
|
|
|
int32_t bno;
|
1995-11-05 23:25:12 +00:00
|
|
|
|
|
|
|
*bnp = 0;
|
|
|
|
fs = ip->i_e2fs;
|
|
|
|
#if DIAGNOSTIC
|
|
|
|
if ((u_int)size > fs->s_blocksize || blkoff(fs, size) != 0) {
|
1999-08-23 20:35:21 +00:00
|
|
|
printf("dev = %s, bsize = %lu, size = %d, fs = %s\n",
|
|
|
|
devtoname(ip->i_dev), fs->s_blocksize, size, fs->fs_fsmnt);
|
1995-11-05 23:25:12 +00:00
|
|
|
panic("ext2_alloc: bad size");
|
|
|
|
}
|
|
|
|
if (cred == NOCRED)
|
1997-04-01 15:22:59 +00:00
|
|
|
panic("ext2_alloc: missing credential");
|
1995-11-05 23:25:12 +00:00
|
|
|
#endif /* DIAGNOSTIC */
|
|
|
|
if (size == fs->s_blocksize && fs->s_es->s_free_blocks_count == 0)
|
|
|
|
goto nospace;
|
|
|
|
if (cred->cr_uid != 0 &&
|
|
|
|
fs->s_es->s_free_blocks_count < fs->s_es->s_r_blocks_count)
|
|
|
|
goto nospace;
|
|
|
|
if (bpref >= fs->s_es->s_blocks_count)
|
|
|
|
bpref = 0;
|
|
|
|
/* call the Linux code */
|
|
|
|
#ifdef EXT2_PREALLOCATE
|
|
|
|
/* To have a preallocation hit, we must
|
|
|
|
* - have at least one block preallocated
|
|
|
|
* - and our preferred block must have that block number or one below
|
|
|
|
*/
|
|
|
|
if (ip->i_prealloc_count &&
|
|
|
|
(bpref == ip->i_prealloc_block ||
|
|
|
|
bpref + 1 == ip->i_prealloc_block))
|
|
|
|
{
|
|
|
|
bno = ip->i_prealloc_block++;
|
|
|
|
ip->i_prealloc_count--;
|
|
|
|
/* ext2_debug ("preallocation hit (%lu/%lu).\n",
|
|
|
|
++alloc_hits, ++alloc_attempts); */
|
|
|
|
|
|
|
|
/* Linux gets, clears, and releases the buffer at this
|
|
|
|
point - we don't have to that; we leave it to the caller
|
|
|
|
*/
|
|
|
|
} else {
|
|
|
|
ext2_discard_prealloc (ip);
|
|
|
|
/* ext2_debug ("preallocation miss (%lu/%lu).\n",
|
|
|
|
alloc_hits, ++alloc_attempts); */
|
|
|
|
if (S_ISREG(ip->i_mode))
|
|
|
|
bno = ext2_new_block
|
|
|
|
(ITOV(ip)->v_mount, bpref,
|
|
|
|
&ip->i_prealloc_count,
|
|
|
|
&ip->i_prealloc_block);
|
|
|
|
else
|
2002-05-18 19:12:38 +00:00
|
|
|
bno = (int32_t)ext2_new_block(ITOV(ip)->v_mount,
|
1995-11-05 23:25:12 +00:00
|
|
|
bpref, 0, 0);
|
|
|
|
}
|
|
|
|
#else
|
2002-05-18 19:12:38 +00:00
|
|
|
bno = (int32_t)ext2_new_block(ITOV(ip)->v_mount, bpref, 0, 0);
|
1995-11-05 23:25:12 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (bno > 0) {
|
|
|
|
/* set next_alloc fields as done in block_getblk */
|
|
|
|
ip->i_next_alloc_block = lbn;
|
|
|
|
ip->i_next_alloc_goal = bno;
|
|
|
|
|
|
|
|
ip->i_blocks += btodb(size);
|
|
|
|
ip->i_flag |= IN_CHANGE | IN_UPDATE;
|
|
|
|
*bnp = bno;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
nospace:
|
|
|
|
ext2_fserr(fs, cred->cr_uid, "file system full");
|
|
|
|
uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt);
|
|
|
|
return (ENOSPC);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reallocate a sequence of blocks into a contiguous sequence of blocks.
|
|
|
|
*
|
|
|
|
* The vnode and an array of buffer pointers for a range of sequential
|
|
|
|
* logical blocks to be made contiguous is given. The allocator attempts
|
|
|
|
* to find a range of sequential blocks starting as close as possible to
|
|
|
|
* an fs_rotdelay offset from the end of the allocation for the logical
|
2001-02-18 10:25:42 +00:00
|
|
|
* block immediately preceding the current range. If successful, the
|
1995-11-05 23:25:12 +00:00
|
|
|
* physical block numbers in the buffer pointers and in the inode are
|
|
|
|
* changed to reflect the new allocation. If unsuccessful, the allocation
|
|
|
|
* is left unchanged. The success in doing the reallocation is returned.
|
|
|
|
* Note that the error return is not reflected back to the user. Rather
|
|
|
|
* the previous block allocation will be used.
|
|
|
|
*/
|
1996-06-12 05:11:41 +00:00
|
|
|
|
|
|
|
#ifdef FANCY_REALLOC
|
1995-11-05 23:25:12 +00:00
|
|
|
#include <sys/sysctl.h>
|
|
|
|
static int doasyncfree = 1;
|
|
|
|
#ifdef OPT_DEBUG
|
1995-11-14 09:40:06 +00:00
|
|
|
SYSCTL_INT(_debug, 14, doasyncfree, CTLFLAG_RW, &doasyncfree, 0, "");
|
1995-11-05 23:25:12 +00:00
|
|
|
#endif /* OPT_DEBUG */
|
1996-06-12 05:11:41 +00:00
|
|
|
#endif
|
|
|
|
|
1995-11-05 23:25:12 +00:00
|
|
|
int
|
|
|
|
ext2_reallocblks(ap)
|
|
|
|
struct vop_reallocblks_args /* {
|
|
|
|
struct vnode *a_vp;
|
|
|
|
struct cluster_save *a_buflist;
|
|
|
|
} */ *ap;
|
|
|
|
{
|
|
|
|
#ifndef FANCY_REALLOC
|
|
|
|
/* printf("ext2_reallocblks not implemented\n"); */
|
|
|
|
return ENOSPC;
|
|
|
|
#else
|
|
|
|
|
|
|
|
struct ext2_sb_info *fs;
|
|
|
|
struct inode *ip;
|
|
|
|
struct vnode *vp;
|
|
|
|
struct buf *sbp, *ebp;
|
2002-05-18 19:12:38 +00:00
|
|
|
int32_t *bap, *sbap, *ebap;
|
1995-11-05 23:25:12 +00:00
|
|
|
struct cluster_save *buflist;
|
2002-05-18 19:12:38 +00:00
|
|
|
int32_t start_lbn, end_lbn, soff, eoff, newblk, blkno;
|
1995-11-05 23:25:12 +00:00
|
|
|
struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp;
|
|
|
|
int i, len, start_lvl, end_lvl, pref, ssize;
|
|
|
|
|
|
|
|
vp = ap->a_vp;
|
|
|
|
ip = VTOI(vp);
|
|
|
|
fs = ip->i_e2fs;
|
|
|
|
#ifdef UNKLAR
|
|
|
|
if (fs->fs_contigsumsize <= 0)
|
|
|
|
return (ENOSPC);
|
|
|
|
#endif
|
|
|
|
buflist = ap->a_buflist;
|
|
|
|
len = buflist->bs_nchildren;
|
|
|
|
start_lbn = buflist->bs_children[0]->b_lblkno;
|
|
|
|
end_lbn = start_lbn + len - 1;
|
|
|
|
#if DIAGNOSTIC
|
|
|
|
for (i = 1; i < len; i++)
|
|
|
|
if (buflist->bs_children[i]->b_lblkno != start_lbn + i)
|
|
|
|
panic("ext2_reallocblks: non-cluster");
|
|
|
|
#endif
|
|
|
|
/*
|
|
|
|
* If the latest allocation is in a new cylinder group, assume that
|
|
|
|
* the filesystem has decided to move and do not force it back to
|
|
|
|
* the previous cylinder group.
|
|
|
|
*/
|
|
|
|
if (dtog(fs, dbtofsb(fs, buflist->bs_children[0]->b_blkno)) !=
|
|
|
|
dtog(fs, dbtofsb(fs, buflist->bs_children[len - 1]->b_blkno)))
|
|
|
|
return (ENOSPC);
|
|
|
|
if (ufs_getlbns(vp, start_lbn, start_ap, &start_lvl) ||
|
|
|
|
ufs_getlbns(vp, end_lbn, end_ap, &end_lvl))
|
|
|
|
return (ENOSPC);
|
|
|
|
/*
|
|
|
|
* Get the starting offset and block map for the first block.
|
|
|
|
*/
|
|
|
|
if (start_lvl == 0) {
|
|
|
|
sbap = &ip->i_db[0];
|
|
|
|
soff = start_lbn;
|
|
|
|
} else {
|
|
|
|
idp = &start_ap[start_lvl - 1];
|
|
|
|
if (bread(vp, idp->in_lbn, (int)fs->s_blocksize, NOCRED, &sbp)) {
|
|
|
|
brelse(sbp);
|
|
|
|
return (ENOSPC);
|
|
|
|
}
|
2002-05-18 19:12:38 +00:00
|
|
|
sbap = (int32_t *)sbp->b_data;
|
1995-11-05 23:25:12 +00:00
|
|
|
soff = idp->in_off;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Find the preferred location for the cluster.
|
|
|
|
*/
|
|
|
|
pref = ext2_blkpref(ip, start_lbn, soff, sbap);
|
|
|
|
/*
|
|
|
|
* If the block range spans two block maps, get the second map.
|
|
|
|
*/
|
|
|
|
if (end_lvl == 0 || (idp = &end_ap[end_lvl - 1])->in_off + 1 >= len) {
|
|
|
|
ssize = len;
|
|
|
|
} else {
|
|
|
|
#if DIAGNOSTIC
|
|
|
|
if (start_ap[start_lvl-1].in_lbn == idp->in_lbn)
|
|
|
|
panic("ext2_reallocblk: start == end");
|
|
|
|
#endif
|
|
|
|
ssize = len - (idp->in_off + 1);
|
|
|
|
if (bread(vp, idp->in_lbn, (int)fs->s_blocksize, NOCRED, &ebp))
|
|
|
|
goto fail;
|
2002-05-18 19:12:38 +00:00
|
|
|
ebap = (int32_t *)ebp->b_data;
|
1995-11-05 23:25:12 +00:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Search the block map looking for an allocation of the desired size.
|
|
|
|
*/
|
2002-05-18 19:12:38 +00:00
|
|
|
if ((newblk = (int32_t)ext2_hashalloc(ip, dtog(fs, pref), (long)pref,
|
1995-11-05 23:25:12 +00:00
|
|
|
len, (u_long (*)())ext2_clusteralloc)) == 0)
|
|
|
|
goto fail;
|
|
|
|
/*
|
|
|
|
* We have found a new contiguous block.
|
|
|
|
*
|
|
|
|
* First we have to replace the old block pointers with the new
|
|
|
|
* block pointers in the inode and indirect blocks associated
|
|
|
|
* with the file.
|
|
|
|
*/
|
|
|
|
blkno = newblk;
|
|
|
|
for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->s_frags_per_block) {
|
|
|
|
if (i == ssize)
|
|
|
|
bap = ebap;
|
|
|
|
#if DIAGNOSTIC
|
|
|
|
if (buflist->bs_children[i]->b_blkno != fsbtodb(fs, *bap))
|
|
|
|
panic("ext2_reallocblks: alloc mismatch");
|
|
|
|
#endif
|
|
|
|
*bap++ = blkno;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Next we must write out the modified inode and indirect blocks.
|
|
|
|
* For strict correctness, the writes should be synchronous since
|
|
|
|
* the old block values may have been written to disk. In practise
|
|
|
|
* they are almost never written, but if we are concerned about
|
|
|
|
* strict correctness, the `doasyncfree' flag should be set to zero.
|
|
|
|
*
|
|
|
|
* The test on `doasyncfree' should be changed to test a flag
|
|
|
|
* that shows whether the associated buffers and inodes have
|
|
|
|
* been written. The flag should be set when the cluster is
|
|
|
|
* started and cleared whenever the buffer or inode is flushed.
|
|
|
|
* We can then check below to see if it is set, and do the
|
|
|
|
* synchronous write only when it has been cleared.
|
|
|
|
*/
|
|
|
|
if (sbap != &ip->i_db[0]) {
|
|
|
|
if (doasyncfree)
|
|
|
|
bdwrite(sbp);
|
|
|
|
else
|
|
|
|
bwrite(sbp);
|
|
|
|
} else {
|
|
|
|
ip->i_flag |= IN_CHANGE | IN_UPDATE;
|
1999-01-07 16:14:19 +00:00
|
|
|
if (!doasyncfree)
|
2002-05-16 19:08:03 +00:00
|
|
|
ext2_update(vp, 1);
|
1995-11-05 23:25:12 +00:00
|
|
|
}
|
|
|
|
if (ssize < len)
|
|
|
|
if (doasyncfree)
|
|
|
|
bdwrite(ebp);
|
|
|
|
else
|
|
|
|
bwrite(ebp);
|
|
|
|
/*
|
|
|
|
* Last, free the old blocks and assign the new blocks to the buffers.
|
|
|
|
*/
|
|
|
|
for (blkno = newblk, i = 0; i < len; i++, blkno += fs->s_frags_per_block) {
|
|
|
|
ext2_blkfree(ip, dbtofsb(fs, buflist->bs_children[i]->b_blkno),
|
|
|
|
fs->s_blocksize);
|
|
|
|
buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno);
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
fail:
|
|
|
|
if (ssize < len)
|
|
|
|
brelse(ebp);
|
|
|
|
if (sbap != &ip->i_db[0])
|
|
|
|
brelse(sbp);
|
|
|
|
return (ENOSPC);
|
|
|
|
|
|
|
|
#endif /* FANCY_REALLOC */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Allocate an inode in the file system.
|
|
|
|
*
|
|
|
|
* we leave the actual allocation strategy to the (modified)
|
|
|
|
* ext2_new_inode(), to make sure we get the policies right
|
|
|
|
*/
|
|
|
|
int
|
VFS mega cleanup commit (x/N)
1. Add new file "sys/kern/vfs_default.c" where default actions for
VOPs go. Implement proper defaults for ABORTOP, BWRITE, LEASE,
POLL, REVOKE and STRATEGY. Various stuff spread over the entire
tree belongs here.
2. Change VOP_BLKATOFF to a normal function in cd9660.
3. Kill VOP_BLKATOFF, VOP_TRUNCATE, VOP_VFREE, VOP_VALLOC. These
are private interface functions between UFS and the underlying
storage manager layer (FFS/LFS/MFS/EXT2FS). The functions now
live in struct ufsmount instead.
4. Remove a kludge of VOP_ functions in all filesystems, that did
nothing but obscure the simplicity and break the expandability.
If a filesystem doesn't implement VOP_FOO, it shouldn't have an
entry for it in its vnops table. The system will try to DTRT
if it is not implemented. There are still some cruft left, but
the bulk of it is done.
5. Fix another VCALL in vfs_cache.c (thanks Bruce!)
1997-10-16 10:50:27 +00:00
|
|
|
ext2_valloc(pvp, mode, cred, vpp)
|
|
|
|
struct vnode *pvp;
|
|
|
|
int mode;
|
|
|
|
struct ucred *cred;
|
|
|
|
struct vnode **vpp;
|
1995-11-05 23:25:12 +00:00
|
|
|
{
|
2002-05-16 19:43:28 +00:00
|
|
|
struct inode *pip;
|
|
|
|
struct ext2_sb_info *fs;
|
|
|
|
struct inode *ip;
|
1995-11-08 04:50:00 +00:00
|
|
|
ino_t ino;
|
1995-11-05 23:25:12 +00:00
|
|
|
int i, error;
|
|
|
|
|
VFS mega cleanup commit (x/N)
1. Add new file "sys/kern/vfs_default.c" where default actions for
VOPs go. Implement proper defaults for ABORTOP, BWRITE, LEASE,
POLL, REVOKE and STRATEGY. Various stuff spread over the entire
tree belongs here.
2. Change VOP_BLKATOFF to a normal function in cd9660.
3. Kill VOP_BLKATOFF, VOP_TRUNCATE, VOP_VFREE, VOP_VALLOC. These
are private interface functions between UFS and the underlying
storage manager layer (FFS/LFS/MFS/EXT2FS). The functions now
live in struct ufsmount instead.
4. Remove a kludge of VOP_ functions in all filesystems, that did
nothing but obscure the simplicity and break the expandability.
If a filesystem doesn't implement VOP_FOO, it shouldn't have an
entry for it in its vnops table. The system will try to DTRT
if it is not implemented. There are still some cruft left, but
the bulk of it is done.
5. Fix another VCALL in vfs_cache.c (thanks Bruce!)
1997-10-16 10:50:27 +00:00
|
|
|
*vpp = NULL;
|
1995-11-05 23:25:12 +00:00
|
|
|
pip = VTOI(pvp);
|
|
|
|
fs = pip->i_e2fs;
|
|
|
|
if (fs->s_es->s_free_inodes_count == 0)
|
|
|
|
goto noinodes;
|
|
|
|
|
|
|
|
/* call the Linux routine - it returns the inode number only */
|
|
|
|
ino = ext2_new_inode(pip, mode);
|
|
|
|
|
|
|
|
if (ino == 0)
|
|
|
|
goto noinodes;
|
2002-03-17 01:25:47 +00:00
|
|
|
error = VFS_VGET(pvp->v_mount, ino, LK_EXCLUSIVE, vpp);
|
1995-11-05 23:25:12 +00:00
|
|
|
if (error) {
|
2002-05-16 19:08:03 +00:00
|
|
|
ext2_vfree(pvp, ino, mode);
|
1995-11-05 23:25:12 +00:00
|
|
|
return (error);
|
|
|
|
}
|
VFS mega cleanup commit (x/N)
1. Add new file "sys/kern/vfs_default.c" where default actions for
VOPs go. Implement proper defaults for ABORTOP, BWRITE, LEASE,
POLL, REVOKE and STRATEGY. Various stuff spread over the entire
tree belongs here.
2. Change VOP_BLKATOFF to a normal function in cd9660.
3. Kill VOP_BLKATOFF, VOP_TRUNCATE, VOP_VFREE, VOP_VALLOC. These
are private interface functions between UFS and the underlying
storage manager layer (FFS/LFS/MFS/EXT2FS). The functions now
live in struct ufsmount instead.
4. Remove a kludge of VOP_ functions in all filesystems, that did
nothing but obscure the simplicity and break the expandability.
If a filesystem doesn't implement VOP_FOO, it shouldn't have an
entry for it in its vnops table. The system will try to DTRT
if it is not implemented. There are still some cruft left, but
the bulk of it is done.
5. Fix another VCALL in vfs_cache.c (thanks Bruce!)
1997-10-16 10:50:27 +00:00
|
|
|
ip = VTOI(*vpp);
|
1995-11-05 23:25:12 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
the question is whether using VGET was such good idea at all -
|
|
|
|
Linux doesn't read the old inode in when it's allocating a
|
|
|
|
new one. I will set at least i_size & i_blocks the zero.
|
|
|
|
*/
|
|
|
|
ip->i_mode = 0;
|
|
|
|
ip->i_size = 0;
|
|
|
|
ip->i_blocks = 0;
|
|
|
|
ip->i_flags = 0;
|
|
|
|
/* now we want to make sure that the block pointers are zeroed out */
|
1998-09-29 08:07:32 +00:00
|
|
|
for (i = 0; i < NDADDR; i++)
|
1995-11-05 23:25:12 +00:00
|
|
|
ip->i_db[i] = 0;
|
1998-09-29 08:07:32 +00:00
|
|
|
for (i = 0; i < NIADDR; i++)
|
|
|
|
ip->i_ib[i] = 0;
|
1995-11-05 23:25:12 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up a new generation number for this inode.
|
|
|
|
* XXX check if this makes sense in ext2
|
|
|
|
*/
|
1997-12-02 11:42:28 +00:00
|
|
|
if (ip->i_gen == 0 || ++ip->i_gen == 0)
|
|
|
|
ip->i_gen = random() / 2 + 1;
|
1995-11-05 23:25:12 +00:00
|
|
|
/*
|
|
|
|
printf("ext2_valloc: allocated inode %d\n", ino);
|
|
|
|
*/
|
|
|
|
return (0);
|
|
|
|
noinodes:
|
VFS mega cleanup commit (x/N)
1. Add new file "sys/kern/vfs_default.c" where default actions for
VOPs go. Implement proper defaults for ABORTOP, BWRITE, LEASE,
POLL, REVOKE and STRATEGY. Various stuff spread over the entire
tree belongs here.
2. Change VOP_BLKATOFF to a normal function in cd9660.
3. Kill VOP_BLKATOFF, VOP_TRUNCATE, VOP_VFREE, VOP_VALLOC. These
are private interface functions between UFS and the underlying
storage manager layer (FFS/LFS/MFS/EXT2FS). The functions now
live in struct ufsmount instead.
4. Remove a kludge of VOP_ functions in all filesystems, that did
nothing but obscure the simplicity and break the expandability.
If a filesystem doesn't implement VOP_FOO, it shouldn't have an
entry for it in its vnops table. The system will try to DTRT
if it is not implemented. There are still some cruft left, but
the bulk of it is done.
5. Fix another VCALL in vfs_cache.c (thanks Bruce!)
1997-10-16 10:50:27 +00:00
|
|
|
ext2_fserr(fs, cred->cr_uid, "out of inodes");
|
1995-11-05 23:25:12 +00:00
|
|
|
uprintf("\n%s: create/symlink failed, no inodes free\n", fs->fs_fsmnt);
|
|
|
|
return (ENOSPC);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Select the desired position for the next block in a file.
|
|
|
|
*
|
|
|
|
* we try to mimic what Remy does in inode_getblk/block_getblk
|
|
|
|
*
|
|
|
|
* we note: blocknr == 0 means that we're about to allocate either
|
|
|
|
* a direct block or a pointer block at the first level of indirection
|
|
|
|
* (In other words, stuff that will go in i_db[] or i_ib[])
|
|
|
|
*
|
|
|
|
* blocknr != 0 means that we're allocating a block that is none
|
|
|
|
* of the above. Then, blocknr tells us the number of the block
|
|
|
|
* that will hold the pointer
|
|
|
|
*/
|
2002-05-18 19:12:38 +00:00
|
|
|
int32_t
|
1995-11-05 23:25:12 +00:00
|
|
|
ext2_blkpref(ip, lbn, indx, bap, blocknr)
|
|
|
|
struct inode *ip;
|
2002-05-18 19:12:38 +00:00
|
|
|
int32_t lbn;
|
1995-11-05 23:25:12 +00:00
|
|
|
int indx;
|
2002-05-18 19:12:38 +00:00
|
|
|
int32_t *bap;
|
|
|
|
int32_t blocknr;
|
1995-11-05 23:25:12 +00:00
|
|
|
{
|
|
|
|
int tmp;
|
|
|
|
|
|
|
|
/* if the next block is actually what we thought it is,
|
|
|
|
then set the goal to what we thought it should be
|
|
|
|
*/
|
|
|
|
if(ip->i_next_alloc_block == lbn)
|
|
|
|
return ip->i_next_alloc_goal;
|
|
|
|
|
|
|
|
/* now check whether we were provided with an array that basically
|
|
|
|
tells us previous blocks to which we want to stay closeby
|
|
|
|
*/
|
|
|
|
if(bap)
|
|
|
|
for (tmp = indx - 1; tmp >= 0; tmp--)
|
|
|
|
if (bap[tmp])
|
|
|
|
return bap[tmp];
|
|
|
|
|
|
|
|
/* else let's fall back to the blocknr, or, if there is none,
|
1998-04-17 22:37:19 +00:00
|
|
|
follow the rule that a block should be allocated near its inode
|
1995-11-05 23:25:12 +00:00
|
|
|
*/
|
|
|
|
return blocknr ? blocknr :
|
2002-05-18 19:12:38 +00:00
|
|
|
(int32_t)(ip->i_block_group *
|
1995-11-05 23:25:12 +00:00
|
|
|
EXT2_BLOCKS_PER_GROUP(ip->i_e2fs)) +
|
|
|
|
ip->i_e2fs->s_es->s_first_data_block;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Free a block or fragment.
|
|
|
|
*
|
|
|
|
* pass on to the Linux code
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
ext2_blkfree(ip, bno, size)
|
2002-05-16 19:43:28 +00:00
|
|
|
struct inode *ip;
|
2002-05-18 19:12:38 +00:00
|
|
|
int32_t bno;
|
1995-11-05 23:25:12 +00:00
|
|
|
long size;
|
|
|
|
{
|
2002-05-16 19:43:28 +00:00
|
|
|
struct ext2_sb_info *fs;
|
1995-11-05 23:25:12 +00:00
|
|
|
|
|
|
|
fs = ip->i_e2fs;
|
|
|
|
/*
|
|
|
|
* call Linux code with mount *, block number, count
|
|
|
|
*/
|
|
|
|
ext2_free_blocks(ITOV(ip)->v_mount, bno, size / fs->s_frag_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Free an inode.
|
|
|
|
*
|
|
|
|
* the maintenance of the actual bitmaps is again up to the linux code
|
|
|
|
*/
|
|
|
|
int
|
VFS mega cleanup commit (x/N)
1. Add new file "sys/kern/vfs_default.c" where default actions for
VOPs go. Implement proper defaults for ABORTOP, BWRITE, LEASE,
POLL, REVOKE and STRATEGY. Various stuff spread over the entire
tree belongs here.
2. Change VOP_BLKATOFF to a normal function in cd9660.
3. Kill VOP_BLKATOFF, VOP_TRUNCATE, VOP_VFREE, VOP_VALLOC. These
are private interface functions between UFS and the underlying
storage manager layer (FFS/LFS/MFS/EXT2FS). The functions now
live in struct ufsmount instead.
4. Remove a kludge of VOP_ functions in all filesystems, that did
nothing but obscure the simplicity and break the expandability.
If a filesystem doesn't implement VOP_FOO, it shouldn't have an
entry for it in its vnops table. The system will try to DTRT
if it is not implemented. There are still some cruft left, but
the bulk of it is done.
5. Fix another VCALL in vfs_cache.c (thanks Bruce!)
1997-10-16 10:50:27 +00:00
|
|
|
ext2_vfree(pvp, ino, mode)
|
|
|
|
struct vnode *pvp;
|
|
|
|
ino_t ino;
|
|
|
|
int mode;
|
1995-11-05 23:25:12 +00:00
|
|
|
{
|
2002-05-16 19:43:28 +00:00
|
|
|
struct ext2_sb_info *fs;
|
|
|
|
struct inode *pip;
|
|
|
|
mode_t save_i_mode;
|
1995-11-05 23:25:12 +00:00
|
|
|
|
VFS mega cleanup commit (x/N)
1. Add new file "sys/kern/vfs_default.c" where default actions for
VOPs go. Implement proper defaults for ABORTOP, BWRITE, LEASE,
POLL, REVOKE and STRATEGY. Various stuff spread over the entire
tree belongs here.
2. Change VOP_BLKATOFF to a normal function in cd9660.
3. Kill VOP_BLKATOFF, VOP_TRUNCATE, VOP_VFREE, VOP_VALLOC. These
are private interface functions between UFS and the underlying
storage manager layer (FFS/LFS/MFS/EXT2FS). The functions now
live in struct ufsmount instead.
4. Remove a kludge of VOP_ functions in all filesystems, that did
nothing but obscure the simplicity and break the expandability.
If a filesystem doesn't implement VOP_FOO, it shouldn't have an
entry for it in its vnops table. The system will try to DTRT
if it is not implemented. There are still some cruft left, but
the bulk of it is done.
5. Fix another VCALL in vfs_cache.c (thanks Bruce!)
1997-10-16 10:50:27 +00:00
|
|
|
pip = VTOI(pvp);
|
1995-11-05 23:25:12 +00:00
|
|
|
fs = pip->i_e2fs;
|
2002-05-18 21:33:07 +00:00
|
|
|
if ((u_int)ino > fs->s_inodes_per_group * fs->s_groups_count)
|
1999-05-13 06:27:51 +00:00
|
|
|
panic("ext2_vfree: range: dev = (%d, %d), ino = %d, fs = %s",
|
|
|
|
major(pip->i_dev), minor(pip->i_dev), ino, fs->fs_fsmnt);
|
1995-11-05 23:25:12 +00:00
|
|
|
|
VFS mega cleanup commit (x/N)
1. Add new file "sys/kern/vfs_default.c" where default actions for
VOPs go. Implement proper defaults for ABORTOP, BWRITE, LEASE,
POLL, REVOKE and STRATEGY. Various stuff spread over the entire
tree belongs here.
2. Change VOP_BLKATOFF to a normal function in cd9660.
3. Kill VOP_BLKATOFF, VOP_TRUNCATE, VOP_VFREE, VOP_VALLOC. These
are private interface functions between UFS and the underlying
storage manager layer (FFS/LFS/MFS/EXT2FS). The functions now
live in struct ufsmount instead.
4. Remove a kludge of VOP_ functions in all filesystems, that did
nothing but obscure the simplicity and break the expandability.
If a filesystem doesn't implement VOP_FOO, it shouldn't have an
entry for it in its vnops table. The system will try to DTRT
if it is not implemented. There are still some cruft left, but
the bulk of it is done.
5. Fix another VCALL in vfs_cache.c (thanks Bruce!)
1997-10-16 10:50:27 +00:00
|
|
|
/* ext2_debug("ext2_vfree (%d, %d) called\n", pip->i_number, mode);
|
1995-11-05 23:25:12 +00:00
|
|
|
*/
|
|
|
|
ext2_discard_prealloc(pip);
|
|
|
|
|
|
|
|
/* we need to make sure that ext2_free_inode can adjust the
|
|
|
|
used_dir_counts in the group summary information - I'd
|
|
|
|
really like to know what the rationale behind this
|
|
|
|
'set i_mode to zero to denote an unused inode' is
|
|
|
|
*/
|
1997-12-03 16:46:21 +00:00
|
|
|
save_i_mode = pip->i_mode;
|
1995-11-05 23:25:12 +00:00
|
|
|
pip->i_mode = mode;
|
1997-12-03 16:46:21 +00:00
|
|
|
ext2_free_inode(pip);
|
|
|
|
pip->i_mode = save_i_mode;
|
1995-11-05 23:25:12 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Fserr prints the name of a file system with an error diagnostic.
|
|
|
|
*
|
|
|
|
* The form of the error message is:
|
|
|
|
* fs: error message
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ext2_fserr(fs, uid, cp)
|
|
|
|
struct ext2_sb_info *fs;
|
|
|
|
u_int uid;
|
|
|
|
char *cp;
|
|
|
|
{
|
|
|
|
|
|
|
|
log(LOG_ERR, "uid %d on %s: %s\n", uid, fs->fs_fsmnt, cp);
|
|
|
|
}
|