Move ext2fs from src/gnu to src/gnu/fs.

Discussed on arch@.

Reviewed by:	kan
Approved by:	re (blanket), kan
Discussed with:	dumbbell
This commit is contained in:
Craig Rodrigues 2005-06-15 16:43:07 +00:00
parent e28e75cfd6
commit 88a2c1983d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=147401
22 changed files with 0 additions and 9058 deletions

View File

@ -1,35 +0,0 @@
$FreeBSD$
Most of the files in this directory are written by Godmar Back or modified
by him using the CSRG sources. Those files are covered by the Berkeley-style
copyright. However the following files are covered by GPL. Since the policy
of the FreeBSD project is to keep the files with the more restrictive
copyright in the gnu tree and it is a good idea to keep the filesystem code
all together, the EXT2FS in its entirety resides under the gnu tree. Note
that only the files below are under the GPL. In the eventuality that these
files are redesigned or rewritten, this tree can be moved back into the less
restrictive FreeBSD tree.
ext2_bitmap.c (in the cvs attic)
ext2_fs.h
ext2_fs_i.h
ext2_fs_sb.h
ext2_linux_balloc.c
ext2_linux_ialloc.c
ext2_super.c (in the cvs attic)
ext2_vfsops.c (has some GPL'ed code from ext2_super.c)
i386-bitops.h
PS.
THANKS GODMAR!!!
Note that this port has been modified by John Dyson and others on
the FreeBSD team, and it is best to send the bug reports to the FreeBSD
team. If there are any non-FreeBSD specific bugs, fixes will be sent to
Godmar to help him fix the original code base. It is also our intention
to send Godmar any FreeBSD specific porting changes so that he can keep
control of his code....
John
dyson@freebsd.org

View File

@ -1,535 +0,0 @@
/*-
* 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.
*
* @(#)ffs_alloc.c 8.8 (Berkeley) 2/21/94
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/vnode.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <sys/syslog.h>
#include <gnu/ext2fs/inode.h>
#include <gnu/ext2fs/ext2_mount.h>
#include <gnu/ext2fs/ext2_fs.h>
#include <gnu/ext2fs/ext2_fs_sb.h>
#include <gnu/ext2fs/fs.h>
#include <gnu/ext2fs/ext2_extern.h>
static void ext2_fserr(struct ext2_sb_info *, u_int, char *);
/*
* 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
*/
void
ext2_discard_prealloc(ip)
struct inode * ip;
{
#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)
struct inode *ip;
int32_t lbn, bpref;
int size;
struct ucred *cred;
int32_t *bnp;
{
struct ext2_sb_info *fs;
int32_t bno;
*bnp = 0;
fs = ip->i_e2fs;
#if DIAGNOSTIC
if ((u_int)size > fs->s_blocksize || blkoff(fs, size) != 0) {
vn_printf(ip->i_devvp, "bsize = %lu, size = %d, fs = %s\n",
fs->s_blocksize, size, fs->fs_fsmnt);
panic("ext2_alloc: bad size");
}
if (cred == NOCRED)
panic("ext2_alloc: missing credential");
#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
bno = (int32_t)ext2_new_block(ITOV(ip)->v_mount,
bpref, 0, 0);
}
#else
bno = (int32_t)ext2_new_block(ITOV(ip)->v_mount, bpref, 0, 0);
#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
* block immediately preceding the current range. If successful, the
* 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.
*/
#ifdef FANCY_REALLOC
#include <sys/sysctl.h>
static int doasyncfree = 1;
#ifdef OPT_DEBUG
SYSCTL_INT(_debug, 14, doasyncfree, CTLFLAG_RW, &doasyncfree, 0, "");
#endif /* OPT_DEBUG */
#endif
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;
int32_t *bap, *sbap, *ebap;
struct cluster_save *buflist;
int32_t start_lbn, end_lbn, soff, eoff, newblk, blkno;
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);
}
sbap = (int32_t *)sbp->b_data;
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;
ebap = (int32_t *)ebp->b_data;
}
/*
* Search the block map looking for an allocation of the desired size.
*/
if ((newblk = (int32_t)ext2_hashalloc(ip, dtog(fs, pref), (long)pref,
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;
if (!doasyncfree)
ext2_update(vp, 1);
}
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
ext2_valloc(pvp, mode, cred, vpp)
struct vnode *pvp;
int mode;
struct ucred *cred;
struct vnode **vpp;
{
struct inode *pip;
struct ext2_sb_info *fs;
struct inode *ip;
ino_t ino;
int i, error;
*vpp = NULL;
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;
error = VFS_VGET(pvp->v_mount, ino, LK_EXCLUSIVE, vpp);
if (error) {
ext2_vfree(pvp, ino, mode);
return (error);
}
ip = VTOI(*vpp);
/*
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 */
for (i = 0; i < NDADDR; i++)
ip->i_db[i] = 0;
for (i = 0; i < NIADDR; i++)
ip->i_ib[i] = 0;
/*
* Set up a new generation number for this inode.
* XXX check if this makes sense in ext2
*/
if (ip->i_gen == 0 || ++ip->i_gen == 0)
ip->i_gen = random() / 2 + 1;
/*
printf("ext2_valloc: allocated inode %d\n", ino);
*/
return (0);
noinodes:
ext2_fserr(fs, cred->cr_uid, "out of inodes");
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
*/
int32_t
ext2_blkpref(ip, lbn, indx, bap, blocknr)
struct inode *ip;
int32_t lbn;
int indx;
int32_t *bap;
int32_t blocknr;
{
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,
follow the rule that a block should be allocated near its inode
*/
return blocknr ? blocknr :
(int32_t)(ip->i_block_group *
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)
struct inode *ip;
int32_t bno;
long size;
{
struct ext2_sb_info *fs;
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
ext2_vfree(pvp, ino, mode)
struct vnode *pvp;
ino_t ino;
int mode;
{
struct ext2_sb_info *fs;
struct inode *pip;
mode_t save_i_mode;
pip = VTOI(pvp);
fs = pip->i_e2fs;
if ((u_int)ino > fs->s_inodes_per_group * fs->s_groups_count)
panic("ext2_vfree: range: devvp = %p, ino = %d, fs = %s",
pip->i_devvp, ino, fs->fs_fsmnt);
/* ext2_debug("ext2_vfree (%d, %d) called\n", pip->i_number, mode);
*/
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
*/
save_i_mode = pip->i_mode;
pip->i_mode = mode;
ext2_free_inode(pip);
pip->i_mode = save_i_mode;
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);
}

View File

@ -1,310 +0,0 @@
/*-
* 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.
*
* @(#)ffs_balloc.c 8.4 (Berkeley) 9/23/93
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/lock.h>
#include <sys/ucred.h>
#include <sys/vnode.h>
#include <gnu/ext2fs/inode.h>
#include <gnu/ext2fs/ext2_fs.h>
#include <gnu/ext2fs/ext2_fs_sb.h>
#include <gnu/ext2fs/fs.h>
#include <gnu/ext2fs/ext2_extern.h>
/*
* Balloc defines the structure of file system storage
* by allocating the physical blocks on a device given
* the inode and the logical block number in a file.
*/
int
ext2_balloc(ip, bn, size, cred, bpp, flags)
struct inode *ip;
int32_t bn;
int size;
struct ucred *cred;
struct buf **bpp;
int flags;
{
struct ext2_sb_info *fs;
int32_t nb;
struct buf *bp, *nbp;
struct vnode *vp = ITOV(ip);
struct indir indirs[NIADDR + 2];
int32_t newb, lbn, *bap, pref;
int osize, nsize, num, i, error;
/*
ext2_debug("ext2_balloc called (%d, %d, %d)\n",
ip->i_number, (int)bn, (int)size);
*/
*bpp = NULL;
if (bn < 0)
return (EFBIG);
fs = ip->i_e2fs;
lbn = bn;
/*
* check if this is a sequential block allocation.
* If so, increment next_alloc fields to allow ext2_blkpref
* to make a good guess
*/
if (lbn == ip->i_next_alloc_block + 1) {
ip->i_next_alloc_block++;
ip->i_next_alloc_goal++;
}
/*
* The first NDADDR blocks are direct blocks
*/
if (bn < NDADDR) {
nb = ip->i_db[bn];
/* no new block is to be allocated, and no need to expand
the file */
if (nb != 0 && ip->i_size >= (bn + 1) * fs->s_blocksize) {
error = bread(vp, bn, fs->s_blocksize, NOCRED, &bp);
if (error) {
brelse(bp);
return (error);
}
bp->b_blkno = fsbtodb(fs, nb);
*bpp = bp;
return (0);
}
if (nb != 0) {
/*
* Consider need to reallocate a fragment.
*/
osize = fragroundup(fs, blkoff(fs, ip->i_size));
nsize = fragroundup(fs, size);
if (nsize <= osize) {
error = bread(vp, bn, osize, NOCRED, &bp);
if (error) {
brelse(bp);
return (error);
}
bp->b_blkno = fsbtodb(fs, nb);
} else {
/* Godmar thinks: this shouldn't happen w/o fragments */
printf("nsize %d(%d) > osize %d(%d) nb %d\n",
(int)nsize, (int)size, (int)osize,
(int)ip->i_size, (int)nb);
panic(
"ext2_balloc: Something is terribly wrong");
/*
* please note there haven't been any changes from here on -
* FFS seems to work.
*/
}
} else {
if (ip->i_size < (bn + 1) * fs->s_blocksize)
nsize = fragroundup(fs, size);
else
nsize = fs->s_blocksize;
error = ext2_alloc(ip, bn,
ext2_blkpref(ip, bn, (int)bn, &ip->i_db[0], 0),
nsize, cred, &newb);
if (error)
return (error);
bp = getblk(vp, bn, nsize, 0, 0, 0);
bp->b_blkno = fsbtodb(fs, newb);
if (flags & B_CLRBUF)
vfs_bio_clrbuf(bp);
}
ip->i_db[bn] = dbtofsb(fs, bp->b_blkno);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
*bpp = bp;
return (0);
}
/*
* Determine the number of levels of indirection.
*/
pref = 0;
if ((error = ext2_getlbns(vp, bn, indirs, &num)) != 0)
return(error);
#if DIAGNOSTIC
if (num < 1)
panic ("ext2_balloc: ext2_getlbns returned indirect block");
#endif
/*
* Fetch the first indirect block allocating if necessary.
*/
--num;
nb = ip->i_ib[indirs[0].in_off];
if (nb == 0) {
#if 0
pref = ext2_blkpref(ip, lbn, 0, (int32_t *)0, 0);
#else
/* see the comment by ext2_blkpref. What we do here is
to pretend that it'd be good for a block holding indirect
pointers to be allocated near its predecessor in terms
of indirection, or the last direct block.
We shamelessly exploit the fact that i_ib immediately
follows i_db.
Godmar thinks it make sense to allocate i_ib[0] immediately
after i_db[11], but it's not utterly clear whether this also
applies to i_ib[1] and i_ib[0]
*/
pref = ext2_blkpref(ip, lbn, indirs[0].in_off +
EXT2_NDIR_BLOCKS, &ip->i_db[0], 0);
#endif
if ((error = ext2_alloc(ip, lbn, pref, (int)fs->s_blocksize,
cred, &newb)) != 0)
return (error);
nb = newb;
bp = getblk(vp, indirs[1].in_lbn, fs->s_blocksize, 0, 0, 0);
bp->b_blkno = fsbtodb(fs, newb);
vfs_bio_clrbuf(bp);
/*
* Write synchronously so that indirect blocks
* never point at garbage.
*/
if ((error = bwrite(bp)) != 0) {
ext2_blkfree(ip, nb, fs->s_blocksize);
return (error);
}
ip->i_ib[indirs[0].in_off] = newb;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
}
/*
* Fetch through the indirect blocks, allocating as necessary.
*/
for (i = 1;;) {
error = bread(vp,
indirs[i].in_lbn, (int)fs->s_blocksize, NOCRED, &bp);
if (error) {
brelse(bp);
return (error);
}
bap = (int32_t *)bp->b_data;
nb = bap[indirs[i].in_off];
if (i == num)
break;
i += 1;
if (nb != 0) {
brelse(bp);
continue;
}
if (pref == 0)
#if 1
/* see the comment above and by ext2_blkpref
* I think this implements Linux policy, but
* does it really make sense to allocate to
* block containing pointers together ?
* Also, will it ever succeed ?
*/
pref = ext2_blkpref(ip, lbn, indirs[i].in_off, bap,
bp->b_lblkno);
#else
pref = ext2_blkpref(ip, lbn, 0, (int32_t *)0, 0);
#endif
if ((error =
ext2_alloc(ip, lbn, pref, (int)fs->s_blocksize, cred, &newb)) != 0) {
brelse(bp);
return (error);
}
nb = newb;
nbp = getblk(vp, indirs[i].in_lbn, fs->s_blocksize, 0, 0, 0);
nbp->b_blkno = fsbtodb(fs, nb);
vfs_bio_clrbuf(nbp);
/*
* Write synchronously so that indirect blocks
* never point at garbage.
*/
if ((error = bwrite(nbp)) != 0) {
ext2_blkfree(ip, nb, fs->s_blocksize);
brelse(bp);
return (error);
}
bap[indirs[i - 1].in_off] = nb;
/*
* If required, write synchronously, otherwise use
* delayed write.
*/
if (flags & B_SYNC) {
bwrite(bp);
} else {
bdwrite(bp);
}
}
/*
* Get the data block, allocating if necessary.
*/
if (nb == 0) {
pref = ext2_blkpref(ip, lbn, indirs[i].in_off, &bap[0],
bp->b_lblkno);
if ((error = ext2_alloc(ip,
lbn, pref, (int)fs->s_blocksize, cred, &newb)) != 0) {
brelse(bp);
return (error);
}
nb = newb;
nbp = getblk(vp, lbn, fs->s_blocksize, 0, 0, 0);
nbp->b_blkno = fsbtodb(fs, nb);
if (flags & B_CLRBUF)
vfs_bio_clrbuf(nbp);
bap[indirs[i].in_off] = nb;
/*
* If required, write synchronously, otherwise use
* delayed write.
*/
if (flags & B_SYNC) {
bwrite(bp);
} else {
bdwrite(bp);
}
*bpp = nbp;
return (0);
}
brelse(bp);
if (flags & B_CLRBUF) {
error = bread(vp, lbn, (int)fs->s_blocksize, NOCRED, &nbp);
if (error) {
brelse(nbp);
return (error);
}
} else {
nbp = getblk(vp, lbn, fs->s_blocksize, 0, 0, 0);
nbp->b_blkno = fsbtodb(fs, nb);
}
*bpp = nbp;
return (0);
}

View File

@ -1,114 +0,0 @@
/*-
* Copyright (c) 2003 Marcel Moolenaar
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*
* $FreeBSD$
*/
#ifndef _SYS_GNU_EXT2FS_EXT2_BITOPS_H_
#define _SYS_GNU_EXT2FS_EXT2_BITOPS_H_
#define find_first_zero_bit(data, sz) find_next_zero_bit(data, sz, 0)
static __inline int
clear_bit(int no, void *data)
{
uint32_t *p;
uint32_t mask, new, old;
p = (uint32_t*)data + (no >> 5);
mask = (1U << (no & 31));
do {
old = *p;
new = old & ~mask;
} while (!atomic_cmpset_32(p, old, new));
return (old & mask);
}
static __inline int
set_bit(int no, void *data)
{
uint32_t *p;
uint32_t mask, new, old;
p = (uint32_t*)data + (no >> 5);
mask = (1U << (no & 31));
do {
old = *p;
new = old | mask;
} while (!atomic_cmpset_32(p, old, new));
return (old & mask);
}
static __inline int
test_bit(int no, void *data)
{
uint32_t *p;
uint32_t mask;
p = (uint32_t*)data + (no >> 5);
mask = (1U << (no & 31));
return (*p & mask);
}
static __inline size_t
find_next_zero_bit(void *data, size_t sz, size_t ofs)
{
uint32_t *p;
uint32_t mask;
int bit;
p = (uint32_t*)data + (ofs >> 5);
if (ofs & 31) {
mask = ~0U << (ofs & 31);
bit = *p | ~mask;
if (bit != ~0U)
return (ffs(~bit) + ofs - 1);
p++;
ofs = (ofs + 31U) & ~31U;
}
while(*p == ~0U && ofs < sz) {
p++;
ofs += 32;
}
if (ofs == sz)
return (ofs);
bit = *p;
return (ffs(~bit) + ofs - 1);
}
static __inline void *
memscan(void *data, int c, size_t sz)
{
uint8_t *p;
p = data;
while (sz && *p != c) {
p++;
sz--;
}
return (p);
}
#endif /* _SYS_GNU_EXT2FS_EXT2_BITOPS_H_ */

View File

@ -1,335 +0,0 @@
/*-
* Copyright (c) 1989, 1991, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* 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.
*
* @(#)ufs_bmap.c 8.7 (Berkeley) 3/21/95
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/proc.h>
#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/resourcevar.h>
#include <sys/stat.h>
#include <gnu/ext2fs/inode.h>
#include <gnu/ext2fs/ext2_fs.h>
#include <gnu/ext2fs/ext2_fs_sb.h>
#include <gnu/ext2fs/ext2_mount.h>
#include <gnu/ext2fs/ext2_extern.h>
/*
* Bmap converts a the logical block number of a file to its physical block
* number on the disk. The conversion is done by using the logical block
* number to index into the array of block pointers described by the dinode.
*/
int
ext2_bmap(ap)
struct vop_bmap_args /* {
struct vnode *a_vp;
daddr_t a_bn;
struct bufobj **a_bop;
daddr_t *a_bnp;
int *a_runp;
int *a_runb;
} */ *ap;
{
int32_t blkno;
int error;
/*
* Check for underlying vnode requests and ensure that logical
* to physical mapping is requested.
*/
if (ap->a_bop != NULL)
*ap->a_bop = &VTOI(ap->a_vp)->i_devvp->v_bufobj;
if (ap->a_bnp == NULL)
return (0);
error = ext2_bmaparray(ap->a_vp, ap->a_bn, &blkno,
ap->a_runp, ap->a_runb);
*ap->a_bnp = blkno;
return (error);
}
/*
* Indirect blocks are now on the vnode for the file. They are given negative
* logical block numbers. Indirect blocks are addressed by the negative
* address of the first data block to which they point. Double indirect blocks
* are addressed by one less than the address of the first indirect block to
* which they point. Triple indirect blocks are addressed by one less than
* the address of the first double indirect block to which they point.
*
* ufs_bmaparray does the bmap conversion, and if requested returns the
* array of logical blocks which must be traversed to get to a block.
* Each entry contains the offset into that block that gets you to the
* next block and the disk address of the block (if it is assigned).
*/
int
ext2_bmaparray(vp, bn, bnp, runp, runb)
struct vnode *vp;
int32_t bn;
int32_t *bnp;
int *runp;
int *runb;
{
struct inode *ip;
struct buf *bp;
struct ext2mount *ump;
struct mount *mp;
struct vnode *devvp;
struct indir a[NIADDR+1], *ap;
int32_t daddr;
long metalbn;
int error, num, maxrun = 0, bsize;
int *nump;
ap = NULL;
ip = VTOI(vp);
mp = vp->v_mount;
ump = VFSTOEXT2(mp);
devvp = ump->um_devvp;
bsize = EXT2_BLOCK_SIZE(ump->um_e2fs);
if (runp) {
maxrun = mp->mnt_iosize_max / bsize - 1;
*runp = 0;
}
if (runb) {
*runb = 0;
}
ap = a;
nump = &num;
error = ext2_getlbns(vp, bn, ap, nump);
if (error)
return (error);
num = *nump;
if (num == 0) {
*bnp = blkptrtodb(ump, ip->i_db[bn]);
if (*bnp == 0) {
*bnp = -1;
} else if (runp) {
int32_t bnb = bn;
for (++bn; bn < NDADDR && *runp < maxrun &&
is_sequential(ump, ip->i_db[bn - 1], ip->i_db[bn]);
++bn, ++*runp);
bn = bnb;
if (runb && (bn > 0)) {
for (--bn; (bn >= 0) && (*runb < maxrun) &&
is_sequential(ump, ip->i_db[bn],
ip->i_db[bn+1]);
--bn, ++*runb);
}
}
return (0);
}
/* Get disk address out of indirect block array */
daddr = ip->i_ib[ap->in_off];
for (bp = NULL, ++ap; --num; ++ap) {
/*
* Exit the loop if there is no disk address assigned yet and
* the indirect block isn't in the cache, or if we were
* looking for an indirect block and we've found it.
*/
metalbn = ap->in_lbn;
if ((daddr == 0 && !incore(&vp->v_bufobj, metalbn)) || metalbn == bn)
break;
/*
* If we get here, we've either got the block in the cache
* or we have a disk address for it, go fetch it.
*/
if (bp)
bqrelse(bp);
ap->in_exists = 1;
bp = getblk(vp, metalbn, bsize, 0, 0, 0);
if ((bp->b_flags & B_CACHE) == 0) {
#ifdef DIAGNOSTIC
if (!daddr)
panic("ufs_bmaparray: indirect block not in cache");
#endif
bp->b_blkno = blkptrtodb(ump, daddr);
bp->b_iocmd = BIO_READ;
bp->b_flags &= ~B_INVAL;
bp->b_ioflags &= ~BIO_ERROR;
vfs_busy_pages(bp, 0);
bp->b_iooffset = dbtob(bp->b_blkno);
bstrategy(bp);
curproc->p_stats->p_ru.ru_inblock++; /* XXX */
error = bufwait(bp);
if (error) {
brelse(bp);
return (error);
}
}
daddr = ((int32_t *)bp->b_data)[ap->in_off];
if (num == 1 && daddr && runp) {
for (bn = ap->in_off + 1;
bn < MNINDIR(ump) && *runp < maxrun &&
is_sequential(ump,
((int32_t *)bp->b_data)[bn - 1],
((int32_t *)bp->b_data)[bn]);
++bn, ++*runp);
bn = ap->in_off;
if (runb && bn) {
for(--bn; bn >= 0 && *runb < maxrun &&
is_sequential(ump, ((int32_t *)bp->b_data)[bn],
((int32_t *)bp->b_data)[bn+1]);
--bn, ++*runb);
}
}
}
if (bp)
bqrelse(bp);
/*
* Since this is FFS independent code, we are out of scope for the
* definitions of BLK_NOCOPY and BLK_SNAP, but we do know that they
* will fall in the range 1..um_seqinc, so we use that test and
* return a request for a zeroed out buffer if attempts are made
* to read a BLK_NOCOPY or BLK_SNAP block.
*/
if ((ip->i_flags & SF_SNAPSHOT) && daddr > 0 && daddr < ump->um_seqinc){
*bnp = -1;
return (0);
}
*bnp = blkptrtodb(ump, daddr);
if (*bnp == 0) {
*bnp = -1;
}
return (0);
}
/*
* Create an array of logical block number/offset pairs which represent the
* path of indirect blocks required to access a data block. The first "pair"
* contains the logical block number of the appropriate single, double or
* triple indirect block and the offset into the inode indirect block array.
* Note, the logical block number of the inode single/double/triple indirect
* block appears twice in the array, once with the offset into the i_ib and
* once with the offset into the page itself.
*/
int
ext2_getlbns(vp, bn, ap, nump)
struct vnode *vp;
int32_t bn;
struct indir *ap;
int *nump;
{
long blockcnt, metalbn, realbn;
struct ext2mount *ump;
int i, numlevels, off;
int64_t qblockcnt;
ump = VFSTOEXT2(vp->v_mount);
if (nump)
*nump = 0;
numlevels = 0;
realbn = bn;
if ((long)bn < 0)
bn = -(long)bn;
/* The first NDADDR blocks are direct blocks. */
if (bn < NDADDR)
return (0);
/*
* Determine the number of levels of indirection. After this loop
* is done, blockcnt indicates the number of data blocks possible
* at the previous level of indirection, and NIADDR - i is the number
* of levels of indirection needed to locate the requested block.
*/
for (blockcnt = 1, i = NIADDR, bn -= NDADDR;; i--, bn -= blockcnt) {
if (i == 0)
return (EFBIG);
/*
* Use int64_t's here to avoid overflow for triple indirect
* blocks when longs have 32 bits and the block size is more
* than 4K.
*/
qblockcnt = (int64_t)blockcnt * MNINDIR(ump);
if (bn < qblockcnt)
break;
blockcnt = qblockcnt;
}
/* Calculate the address of the first meta-block. */
if (realbn >= 0)
metalbn = -(realbn - bn + NIADDR - i);
else
metalbn = -(-realbn - bn + NIADDR - i);
/*
* At each iteration, off is the offset into the bap array which is
* an array of disk addresses at the current level of indirection.
* The logical block number and the offset in that block are stored
* into the argument array.
*/
ap->in_lbn = metalbn;
ap->in_off = off = NIADDR - i;
ap->in_exists = 0;
ap++;
for (++numlevels; i <= NIADDR; i++) {
/* If searching for a meta-data block, quit when found. */
if (metalbn == realbn)
break;
off = (bn / blockcnt) % MNINDIR(ump);
++numlevels;
ap->in_lbn = metalbn;
ap->in_off = off;
ap->in_exists = 0;
++ap;
metalbn -= -1 + off * blockcnt;
blockcnt /= MNINDIR(ump);
}
if (nump)
*nump = numlevels;
return (0);
}

View File

@ -1,104 +0,0 @@
/*-
* modified for EXT2FS support in Lites 1.1
*
* Aug 1995, Godmar Back (gback@cs.utah.edu)
* University of Utah, Department of Computer Science
*/
/*-
* Copyright (c) 1991, 1993, 1994
* 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.
*
* @(#)ffs_extern.h 8.3 (Berkeley) 4/16/94
* $FreeBSD$
*/
#ifndef _SYS_GNU_EXT2FS_EXT2_EXTERN_H_
#define _SYS_GNU_EXT2FS_EXT2_EXTERN_H_
struct ext2_inode;
struct indir;
struct inode;
struct mount;
struct vfsconf;
struct vnode;
int ext2_alloc(struct inode *,
int32_t, int32_t, int, struct ucred *, int32_t *);
int ext2_balloc(struct inode *,
int32_t, int, struct ucred *, struct buf **, int);
int ext2_blkatoff(struct vnode *, off_t, char **, struct buf **);
void ext2_blkfree(struct inode *, int32_t, long);
int32_t ext2_blkpref(struct inode *, int32_t, int, int32_t *, int32_t);
int ext2_bmap(struct vop_bmap_args *);
int ext2_bmaparray(struct vnode *, int32_t, int32_t *, int *, int *);
void ext2_dirbad(struct inode *ip, doff_t offset, char *how);
void ext2_ei2i(struct ext2_inode *, struct inode *);
int ext2_getlbns(struct vnode *, int32_t, struct indir *, int *);
void ext2_i2ei(struct inode *, struct ext2_inode *);
void ext2_itimes(struct vnode *vp);
int ext2_reallocblks(struct vop_reallocblks_args *);
int ext2_reclaim(struct vop_reclaim_args *);
void ext2_setblock(struct ext2_sb_info *, u_char *, int32_t);
int ext2_truncate(struct vnode *, off_t, int, struct ucred *, struct thread *);
int ext2_update(struct vnode *, int);
int ext2_valloc(struct vnode *, int, struct ucred *, struct vnode **);
int ext2_vfree(struct vnode *, ino_t, int);
int ext2_vinit(struct mount *, struct vop_vector *, struct vnode **vpp);
int ext2_lookup(struct vop_cachedlookup_args *);
int ext2_readdir(struct vop_readdir_args *);
void ext2_print_inode(struct inode *);
int ext2_direnter(struct inode *,
struct vnode *, struct componentname *);
int ext2_dirremove(struct vnode *, struct componentname *);
int ext2_dirrewrite(struct inode *,
struct inode *, struct componentname *);
int ext2_dirempty(struct inode *, ino_t, struct ucred *);
int ext2_checkpath(struct inode *, struct inode *, struct ucred *);
struct ext2_group_desc * get_group_desc(struct mount * ,
unsigned int , struct buf ** );
int ext2_group_sparse(int group);
void ext2_discard_prealloc(struct inode *);
int ext2_inactive(struct vop_inactive_args *);
int ext2_new_block(struct mount * mp, unsigned long goal,
u_int32_t *prealloc_count, u_int32_t *prealloc_block);
ino_t ext2_new_inode(const struct inode * dir, int mode);
unsigned long ext2_count_free(struct buf *map, unsigned int numchars);
void ext2_free_blocks(struct mount *mp, unsigned long block,
unsigned long count);
void ext2_free_inode(struct inode * inode);
void mark_buffer_dirty(struct buf *bh);
/* Flags to low-level allocation routines. */
#define B_CLRBUF 0x01 /* Request allocated buffer be cleared. */
#define B_SYNC 0x02 /* Do all allocations synchronously. */
#define B_METAONLY 0x04 /* Return indirect block buffer. */
#define B_NOWAIT 0x08 /* do not sleep to await lock */
extern struct vop_vector ext2_vnodeops;
extern struct vop_vector ext2_fifoops;
#endif /* !_SYS_GNU_EXT2FS_EXT2_EXTERN_H_ */

View File

@ -1,550 +0,0 @@
/*-
* modified for EXT2FS support in Lites 1.1
*
* Aug 1995, Godmar Back (gback@cs.utah.edu)
* University of Utah, Department of Computer Science
*
* $FreeBSD$
*/
/*-
* linux/include/linux/ext2_fs.h
*
* Copyright (C) 1992, 1993, 1994, 1995
* Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* from
*
* linux/include/linux/minix_fs.h
*
* Copyright (C) 1991, 1992 Linus Torvalds
*/
#ifndef _LINUX_EXT2_FS_H
#define _LINUX_EXT2_FS_H
#include <sys/types.h>
#define __u32 u_int32_t
#define u32 u_int32_t
#define __u16 u_int16_t
#define __u8 u_int8_t
#define __s32 int32_t
#define __s16 int16_t
#define __s8 int8_t
#define umode_t mode_t
#define loff_t off_t
/*
* The second extended filesystem constants/structures
*/
/*
* Define EXT2FS_DEBUG to produce debug messages
*/
#undef EXT2FS_DEBUG
/*
* Define EXT2_PREALLOCATE to preallocate data blocks for expanding files
*/
#define EXT2_PREALLOCATE
#define EXT2_DEFAULT_PREALLOC_BLOCKS 8
/*
* The second extended file system version
*/
#define EXT2FS_DATE "95/08/09"
#define EXT2FS_VERSION "0.5b"
/*
* Debug code
*/
#ifdef EXT2FS_DEBUG
# define ext2_debug(f, a...) { \
printf ("EXT2-fs DEBUG (%s, %d): %s:", \
__FILE__, __LINE__, __func__); \
printf (f, ## a); \
}
#else
# define ext2_debug(f, a...) /**/
#endif
/*
* Special inodes numbers
*/
#define EXT2_BAD_INO 1 /* Bad blocks inode */
#define EXT2_ROOT_INO 2 /* Root inode */
#define EXT2_ACL_IDX_INO 3 /* ACL inode */
#define EXT2_ACL_DATA_INO 4 /* ACL inode */
#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
/* First non-reserved inode for old ext2 filesystems */
#define EXT2_GOOD_OLD_FIRST_INO 11
/*
* The second extended file system magic number
*/
#define EXT2_SUPER_MAGIC 0xEF53
/*
* Maximal count of links to a file
*/
#define EXT2_LINK_MAX 32000
/*
* Note: under FreeBSD, the "user" versions of the following macros are
* used (and must be used) in most cases, because ((s)->u.ext2_sb.s_es is
* not accessible. This depends on __KERNEL__ not being defined for
* kernel builds under FreeBSD.
*/
/*
* Macro-instructions used to manage several block sizes
*/
#define EXT2_MIN_BLOCK_SIZE 1024
#define EXT2_MAX_BLOCK_SIZE 4096
#define EXT2_MIN_BLOCK_LOG_SIZE 10
#if defined(__KERNEL__) || (defined(__FreeBSD__) && defined(_KERNEL))
# define EXT2_BLOCK_SIZE(s) ((s)->s_blocksize)
#else
# define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size)
#endif
#define EXT2_ACLE_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_acl_entry))
#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
#ifdef __KERNEL__
# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
#else
# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
#endif
#ifdef notyet
#ifdef __KERNEL__
#define EXT2_ADDR_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_addr_per_block_bits)
#define EXT2_INODE_SIZE(s) ((s)->u.ext2_sb.s_inode_size)
#define EXT2_FIRST_INO(s) ((s)->u.ext2_sb.s_first_ino)
#else
#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
EXT2_GOOD_OLD_INODE_SIZE : \
(s)->s_inode_size)
#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
EXT2_GOOD_OLD_FIRST_INO : \
(s)->s_first_ino)
#endif
#else /* !notyet */
#define EXT2_INODES_PER_BLOCK(s) ((s)->s_inodes_per_block)
/* Should be sizeof(struct ext2_inode): */
#define EXT2_INODE_SIZE 128
#define EXT2_FIRST_INO 11
#endif /* notyet */
/*
* Macro-instructions used to manage fragments
*/
#define EXT2_MIN_FRAG_SIZE 1024
#define EXT2_MAX_FRAG_SIZE 4096
#define EXT2_MIN_FRAG_LOG_SIZE 10
#ifdef __KERNEL__
# define EXT2_FRAG_SIZE(s) ((s)->u.ext2_sb.s_frag_size)
# define EXT2_FRAGS_PER_BLOCK(s) ((s)->u.ext2_sb.s_frags_per_block)
#else
# if defined(_KERNEL) && defined(__FreeBSD__)
# define EXT2_FRAG_SIZE(s) ((s)->s_frag_size)
# else
# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size)
# endif
# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s))
#endif
/*
* ACL structures
*/
struct ext2_acl_header /* Header of Access Control Lists */
{
__u32 aclh_size;
__u32 aclh_file_count;
__u32 aclh_acle_count;
__u32 aclh_first_acle;
};
struct ext2_acl_entry /* Access Control List Entry */
{
__u32 acle_size;
__u16 acle_perms; /* Access permissions */
__u16 acle_type; /* Type of entry */
__u16 acle_tag; /* User or group identity */
__u16 acle_pad1;
__u32 acle_next; /* Pointer on next entry for the */
/* same inode or on next free entry */
};
/*
* Structure of a blocks group descriptor
*/
struct ext2_group_desc
{
__u32 bg_block_bitmap; /* Blocks bitmap block */
__u32 bg_inode_bitmap; /* Inodes bitmap block */
__u32 bg_inode_table; /* Inodes table block */
__u16 bg_free_blocks_count; /* Free blocks count */
__u16 bg_free_inodes_count; /* Free inodes count */
__u16 bg_used_dirs_count; /* Directories count */
__u16 bg_pad;
__u32 bg_reserved[3];
};
/*
* Macro-instructions used to manage group descriptors
*/
#ifdef __KERNEL__
# define EXT2_BLOCKS_PER_GROUP(s) ((s)->u.ext2_sb.s_blocks_per_group)
# define EXT2_DESC_PER_BLOCK(s) ((s)->u.ext2_sb.s_desc_per_block)
# define EXT2_INODES_PER_GROUP(s) ((s)->u.ext2_sb.s_inodes_per_group)
# define EXT2_DESC_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_desc_per_block_bits)
#else
# define EXT2_BLOCKS_PER_GROUP(s) ((s)->s_blocks_per_group)
# define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
# define EXT2_INODES_PER_GROUP(s) ((s)->s_inodes_per_group)
#endif
/*
* Constants relative to the data blocks
*/
#define EXT2_NDIR_BLOCKS 12
#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
#define EXT2_MAXSYMLINKLEN (EXT2_N_BLOCKS * sizeof (__u32))
/*
* Inode flags
*/
#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */
#define EXT2_UNRM_FL 0x00000002 /* Undelete */
#define EXT2_COMPR_FL 0x00000004 /* Compress file */
#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */
#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */
#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */
#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */
#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */
/* Reserved for compression usage... */
#define EXT2_DIRTY_FL 0x00000100
#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
#define EXT2_NOCOMP_FL 0x00000400 /* Don't compress */
#define EXT2_ECOMPR_FL 0x00000800 /* Compression error */
/* End compression flags --- maybe not all used */
#define EXT2_BTREE_FL 0x00001000 /* btree format dir */
#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
#define EXT2_FL_USER_VISIBLE 0x00001FFF /* User visible flags */
#define EXT2_FL_USER_MODIFIABLE 0x000000FF /* User modifiable flags */
/*
* ioctl commands
*/
#define EXT2_IOC_GETFLAGS _IOR('f', 1, long)
#define EXT2_IOC_SETFLAGS _IOW('f', 2, long)
#define EXT2_IOC_GETVERSION _IOR('v', 1, long)
#define EXT2_IOC_SETVERSION _IOW('v', 2, long)
/*
* Structure of an inode on the disk
*/
struct ext2_inode {
__u16 i_mode; /* File mode */
__u16 i_uid; /* Owner Uid */
__u32 i_size; /* Size in bytes */
__u32 i_atime; /* Access time */
__u32 i_ctime; /* Creation time */
__u32 i_mtime; /* Modification time */
__u32 i_dtime; /* Deletion Time */
__u16 i_gid; /* Group Id */
__u16 i_links_count; /* Links count */
__u32 i_blocks; /* Blocks count */
__u32 i_flags; /* File flags */
union {
struct {
__u32 l_i_reserved1;
} linux1;
struct {
__u32 h_i_translator;
} hurd1;
struct {
__u32 m_i_reserved1;
} masix1;
} osd1; /* OS dependent 1 */
__u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
__u32 i_generation; /* File version (for NFS) */
__u32 i_file_acl; /* File ACL */
__u32 i_dir_acl; /* Directory ACL */
__u32 i_faddr; /* Fragment address */
union {
struct {
__u8 l_i_frag; /* Fragment number */
__u8 l_i_fsize; /* Fragment size */
__u16 i_pad1;
__u32 l_i_reserved2[2];
} linux2;
struct {
__u8 h_i_frag; /* Fragment number */
__u8 h_i_fsize; /* Fragment size */
__u16 h_i_mode_high;
__u16 h_i_uid_high;
__u16 h_i_gid_high;
__u32 h_i_author;
} hurd2;
struct {
__u8 m_i_frag; /* Fragment number */
__u8 m_i_fsize; /* Fragment size */
__u16 m_pad1;
__u32 m_i_reserved2[2];
} masix2;
} osd2; /* OS dependent 2 */
};
#define i_size_high i_dir_acl
#if defined(__KERNEL__) || defined(__linux__)
#define i_reserved1 osd1.linux1.l_i_reserved1
#define i_frag osd2.linux2.l_i_frag
#define i_fsize osd2.linux2.l_i_fsize
#define i_reserved2 osd2.linux2.l_i_reserved2
#endif
#ifdef __hurd__
#define i_translator osd1.hurd1.h_i_translator
#define i_frag osd2.hurd2.h_i_frag;
#define i_fsize osd2.hurd2.h_i_fsize;
#define i_uid_high osd2.hurd2.h_i_uid_high
#define i_gid_high osd2.hurd2.h_i_gid_high
#define i_author osd2.hurd2.h_i_author
#endif
#ifdef __masix__
#define i_reserved1 osd1.masix1.m_i_reserved1
#define i_frag osd2.masix2.m_i_frag
#define i_fsize osd2.masix2.m_i_fsize
#define i_reserved2 osd2.masix2.m_i_reserved2
#endif
/*
* File system states
*/
#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */
#define EXT2_ERROR_FS 0x0002 /* Errors detected */
/*
* Mount flags
*/
#define EXT2_MOUNT_CHECK_NORMAL 0x0001 /* Do some more checks */
#define EXT2_MOUNT_CHECK_STRICT 0x0002 /* Do again more checks */
#define EXT2_MOUNT_CHECK (EXT2_MOUNT_CHECK_NORMAL | \
EXT2_MOUNT_CHECK_STRICT)
#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */
#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */
#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */
#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */
#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
#define test_opt(sb, opt) ((sb)->u.ext2_sb.s_mount_opt & \
EXT2_MOUNT_##opt)
/*
* Maximal mount counts between two filesystem checks
*/
#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */
#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */
/*
* Behaviour when detecting errors
*/
#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */
#define EXT2_ERRORS_RO 2 /* Remount fs read-only */
#define EXT2_ERRORS_PANIC 3 /* Panic */
#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE
/*
* Structure of the super block
*/
struct ext2_super_block {
__u32 s_inodes_count; /* Inodes count */
__u32 s_blocks_count; /* Blocks count */
__u32 s_r_blocks_count; /* Reserved blocks count */
__u32 s_free_blocks_count; /* Free blocks count */
__u32 s_free_inodes_count; /* Free inodes count */
__u32 s_first_data_block; /* First Data Block */
__u32 s_log_block_size; /* Block size */
__s32 s_log_frag_size; /* Fragment size */
__u32 s_blocks_per_group; /* # Blocks per group */
__u32 s_frags_per_group; /* # Fragments per group */
__u32 s_inodes_per_group; /* # Inodes per group */
__u32 s_mtime; /* Mount time */
__u32 s_wtime; /* Write time */
__u16 s_mnt_count; /* Mount count */
__s16 s_max_mnt_count; /* Maximal mount count */
__u16 s_magic; /* Magic signature */
__u16 s_state; /* File system state */
__u16 s_errors; /* Behaviour when detecting errors */
__u16 s_minor_rev_level; /* minor revision level */
__u32 s_lastcheck; /* time of last check */
__u32 s_checkinterval; /* max. time between checks */
__u32 s_creator_os; /* OS */
__u32 s_rev_level; /* Revision level */
__u16 s_def_resuid; /* Default uid for reserved blocks */
__u16 s_def_resgid; /* Default gid for reserved blocks */
/*
* These fields are for EXT2_DYNAMIC_REV superblocks only.
*
* Note: the difference between the compatible feature set and
* the incompatible feature set is that if there is a bit set
* in the incompatible feature set that the kernel doesn't
* know about, it should refuse to mount the filesystem.
*
* e2fsck's requirements are more strict; if it doesn't know
* about a feature in either the compatible or incompatible
* feature set, it must abort and not try to meddle with
* things it doesn't understand...
*/
__u32 s_first_ino; /* First non-reserved inode */
__u16 s_inode_size; /* size of inode structure */
__u16 s_block_group_nr; /* block group # of this superblock */
__u32 s_feature_compat; /* compatible feature set */
__u32 s_feature_incompat; /* incompatible feature set */
__u32 s_feature_ro_compat; /* readonly-compatible feature set */
__u8 s_uuid[16]; /* 128-bit uuid for volume */
char s_volume_name[16]; /* volume name */
char s_last_mounted[64]; /* directory where last mounted */
__u32 s_algorithm_usage_bitmap; /* For compression */
/*
* Performance hints. Directory preallocation should only
* happen if the EXT2_COMPAT_PREALLOC flag is on.
*/
__u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
__u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
__u16 s_padding1;
__u32 s_reserved[204]; /* Padding to the end of the block */
};
#ifdef __KERNEL__
#define EXT2_SB(sb) (&((sb)->u.ext2_sb))
#else
/* Assume that user mode programs are passing in an ext2fs superblock, not
* a kernel struct super_block. This will allow us to call the feature-test
* macros from user land. */
#define EXT2_SB(sb) (sb)
#endif
/*
* Codes for operating systems
*/
#define EXT2_OS_LINUX 0
#define EXT2_OS_HURD 1
#define EXT2_OS_MASIX 2
#define EXT2_OS_FREEBSD 3
#define EXT2_OS_LITES 4
/*
* Revision levels
*/
#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV
#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV
#define EXT2_GOOD_OLD_INODE_SIZE 128
/*
* Feature set definitions
*/
#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \
( EXT2_SB(sb)->s_feature_compat & (mask) )
#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \
( EXT2_SB(sb)->s_feature_ro_compat & (mask) )
#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \
( EXT2_SB(sb)->s_feature_incompat & (mask) )
#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001
#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
#define EXT2_FEATURE_COMPAT_SUPP 0
#define EXT2_FEATURE_INCOMPAT_SUPP EXT2_FEATURE_INCOMPAT_FILETYPE
#ifdef notyet
#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
#else
#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
EXT2_FEATURE_RO_COMPAT_LARGE_FILE)
#endif
/*
* Default values for user and/or group using reserved blocks
*/
#define EXT2_DEF_RESUID 0
#define EXT2_DEF_RESGID 0
/*
* Structure of a directory entry
*/
#define EXT2_NAME_LEN 255
struct ext2_dir_entry {
__u32 inode; /* Inode number */
__u16 rec_len; /* Directory entry length */
__u16 name_len; /* Name length */
char name[EXT2_NAME_LEN]; /* File name */
};
/*
* The new version of the directory entry. Since EXT2 structures are
* stored in intel byte order, and the name_len field could never be
* bigger than 255 chars, it's safe to reclaim the extra byte for the
* file_type field.
*/
struct ext2_dir_entry_2 {
__u32 inode; /* Inode number */
__u16 rec_len; /* Directory entry length */
__u8 name_len; /* Name length */
__u8 file_type;
char name[EXT2_NAME_LEN]; /* File name */
};
/*
* Ext2 directory file types. Only the low 3 bits are used. The
* other bits are reserved for now.
*/
#define EXT2_FT_UNKNOWN 0
#define EXT2_FT_REG_FILE 1
#define EXT2_FT_DIR 2
#define EXT2_FT_CHRDEV 3
#define EXT2_FT_BLKDEV 4
#define EXT2_FT_FIFO 5
#define EXT2_FT_SOCK 6
#define EXT2_FT_SYMLINK 7
#define EXT2_FT_MAX 8
/*
* EXT2_DIR_PAD defines the directory entries boundaries
*
* NOTE: It must be a multiple of 4
*/
#define EXT2_DIR_PAD 4
#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
~EXT2_DIR_ROUND)
#endif /* _LINUX_EXT2_FS_H */

View File

@ -1,83 +0,0 @@
/*-
* modified for EXT2FS support in Lites 1.1
*
* Aug 1995, Godmar Back (gback@cs.utah.edu)
* University of Utah, Department of Computer Science
*
* $FreeBSD$
*/
/*-
* linux/include/linux/ext2_fs_sb.h
*
* Copyright (C) 1992, 1993, 1994, 1995
* Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* from
*
* linux/include/linux/minix_fs_sb.h
*
* Copyright (C) 1991, 1992 Linus Torvalds
*/
#ifndef _LINUX_EXT2_FS_SB
#define _LINUX_EXT2_FS_SB
/*
* The following is not needed anymore since the descriptors buffer
* heads are now dynamically allocated
*/
/* #define EXT2_MAX_GROUP_DESC 8 */
#define EXT2_MAX_GROUP_LOADED 8
#define buffer_head buf
#define MAXMNTLEN 512
/*
* second extended-fs super-block data in memory
*/
struct ext2_sb_info {
unsigned long s_frag_size; /* Size of a fragment in bytes */
unsigned long s_frags_per_block;/* Number of fragments per block */
unsigned long s_inodes_per_block;/* Number of inodes per block */
unsigned long s_frags_per_group;/* Number of fragments in a group */
unsigned long s_blocks_per_group;/* Number of blocks in a group */
unsigned long s_inodes_per_group;/* Number of inodes in a group */
unsigned long s_itb_per_group; /* Number of inode table blocks per group */
unsigned long s_db_per_group; /* Number of descriptor blocks per group */
unsigned long s_desc_per_block; /* Number of group descriptors per block */
unsigned long s_groups_count; /* Number of groups in the fs */
struct buffer_head * s_sbh; /* Buffer containing the super block */
struct ext2_super_block * s_es; /* Pointer to the super block in the buffer */
struct buffer_head ** s_group_desc;
unsigned short s_loaded_inode_bitmaps;
unsigned short s_loaded_block_bitmaps;
unsigned long s_inode_bitmap_number[EXT2_MAX_GROUP_LOADED];
struct buffer_head * s_inode_bitmap[EXT2_MAX_GROUP_LOADED];
unsigned long s_block_bitmap_number[EXT2_MAX_GROUP_LOADED];
struct buffer_head * s_block_bitmap[EXT2_MAX_GROUP_LOADED];
int s_rename_lock;
unsigned long s_mount_opt;
unsigned short s_resuid;
unsigned short s_resgid;
unsigned short s_mount_state;
/*
stuff that FFS keeps in its super block or that linux
has in its non-ext2 specific super block and which is
generally considered useful
*/
unsigned long s_blocksize;
unsigned long s_blocksize_bits;
unsigned int s_bshift; /* = log2(s_blocksize) */
quad_t s_qbmask; /* = s_blocksize - 1 */
unsigned int s_fsbtodb; /* shift to get disk block */
char s_rd_only; /* read-only */
char s_dirt; /* fs modified flag */
char s_wasvalid; /* valid at mount time */
off_t fs_maxfilesize;
char fs_fsmnt[MAXMNTLEN]; /* name mounted on */
};
#endif /* _LINUX_EXT2_FS_SB */

View File

@ -1,536 +0,0 @@
/*-
* 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.
*
* @(#)ffs_inode.c 8.5 (Berkeley) 12/30/93
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mount.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/vnode.h>
#include <sys/malloc.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
#include <gnu/ext2fs/inode.h>
#include <gnu/ext2fs/ext2_mount.h>
#include <gnu/ext2fs/ext2_fs.h>
#include <gnu/ext2fs/ext2_fs_sb.h>
#include <gnu/ext2fs/fs.h>
#include <gnu/ext2fs/ext2_extern.h>
static int ext2_indirtrunc(struct inode *, int32_t, int32_t, int32_t, int,
long *);
/*
* Update the access, modified, and inode change times as specified by the
* IN_ACCESS, IN_UPDATE, and IN_CHANGE flags respectively. Write the inode
* to disk if the IN_MODIFIED flag is set (it may be set initially, or by
* the timestamp update). The IN_LAZYMOD flag is set to force a write
* later if not now. If we write now, then clear both IN_MODIFIED and
* IN_LAZYMOD to reflect the presumably successful write, and if waitfor is
* set, then wait for the write to complete.
*/
int
ext2_update(vp, waitfor)
struct vnode *vp;
int waitfor;
{
struct ext2_sb_info *fs;
struct buf *bp;
struct inode *ip;
int error;
ext2_itimes(vp);
ip = VTOI(vp);
if ((ip->i_flag & IN_MODIFIED) == 0)
return (0);
ip->i_flag &= ~(IN_LAZYMOD | IN_MODIFIED);
if (vp->v_mount->mnt_flag & MNT_RDONLY)
return (0);
fs = ip->i_e2fs;
if ((error = bread(ip->i_devvp,
fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
(int)fs->s_blocksize, NOCRED, &bp)) != 0) {
brelse(bp);
return (error);
}
ext2_i2ei(ip, (struct ext2_inode *)((char *)bp->b_data +
EXT2_INODE_SIZE * ino_to_fsbo(fs, ip->i_number)));
if (waitfor && (vp->v_mount->mnt_flag & MNT_ASYNC) == 0)
return (bwrite(bp));
else {
bdwrite(bp);
return (0);
}
}
#define SINGLE 0 /* index of single indirect block */
#define DOUBLE 1 /* index of double indirect block */
#define TRIPLE 2 /* index of triple indirect block */
/*
* Truncate the inode oip to at most length size, freeing the
* disk blocks.
*/
int
ext2_truncate(vp, length, flags, cred, td)
struct vnode *vp;
off_t length;
int flags;
struct ucred *cred;
struct thread *td;
{
struct vnode *ovp = vp;
int32_t lastblock;
struct inode *oip;
int32_t bn, lbn, lastiblock[NIADDR], indir_lbn[NIADDR];
int32_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR];
struct ext2_sb_info *fs;
struct buf *bp;
int offset, size, level;
long count, nblocks, blocksreleased = 0;
int aflags, error, i, allerror;
off_t osize;
/*
printf("ext2_truncate called %d to %d\n", VTOI(ovp)->i_number, length);
*/ /*
* negative file sizes will totally break the code below and
* are not meaningful anyways.
*/
if (length < 0)
return EFBIG;
oip = VTOI(ovp);
if (ovp->v_type == VLNK &&
oip->i_size < ovp->v_mount->mnt_maxsymlinklen) {
#if DIAGNOSTIC
if (length != 0)
panic("ext2_truncate: partial truncate of symlink");
#endif
bzero((char *)&oip->i_shortlink, (u_int)oip->i_size);
oip->i_size = 0;
oip->i_flag |= IN_CHANGE | IN_UPDATE;
return (ext2_update(ovp, 1));
}
if (oip->i_size == length) {
oip->i_flag |= IN_CHANGE | IN_UPDATE;
return (ext2_update(ovp, 0));
}
fs = oip->i_e2fs;
osize = oip->i_size;
ext2_discard_prealloc(oip);
/*
* Lengthen the size of the file. We must ensure that the
* last byte of the file is allocated. Since the smallest
* value of oszie is 0, length will be at least 1.
*/
if (osize < length) {
if (length > oip->i_e2fs->fs_maxfilesize)
return (EFBIG);
offset = blkoff(fs, length - 1);
lbn = lblkno(fs, length - 1);
aflags = B_CLRBUF;
if (flags & IO_SYNC)
aflags |= B_SYNC;
vnode_pager_setsize(ovp, length);
if ((error = ext2_balloc(oip, lbn, offset + 1, cred, &bp,
aflags)) != 0)
return (error);
oip->i_size = length;
if (aflags & IO_SYNC)
bwrite(bp);
else
bawrite(bp);
oip->i_flag |= IN_CHANGE | IN_UPDATE;
return (ext2_update(ovp, 1));
}
/*
* Shorten the size of the file. If the file is not being
* truncated to a block boundry, the contents of the
* partial block following the end of the file must be
* zero'ed in case it ever become accessible again because
* of subsequent file growth.
*/
/* I don't understand the comment above */
offset = blkoff(fs, length);
if (offset == 0) {
oip->i_size = length;
} else {
lbn = lblkno(fs, length);
aflags = B_CLRBUF;
if (flags & IO_SYNC)
aflags |= B_SYNC;
if ((error = ext2_balloc(oip, lbn, offset, cred, &bp,
aflags)) != 0)
return (error);
oip->i_size = length;
size = blksize(fs, oip, lbn);
bzero((char *)bp->b_data + offset, (u_int)(size - offset));
allocbuf(bp, size);
if (aflags & IO_SYNC)
bwrite(bp);
else
bawrite(bp);
}
/*
* Calculate index into inode's block list of
* last direct and indirect blocks (if any)
* which we want to keep. Lastblock is -1 when
* the file is truncated to 0.
*/
lastblock = lblkno(fs, length + fs->s_blocksize - 1) - 1;
lastiblock[SINGLE] = lastblock - NDADDR;
lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR(fs);
lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR(fs) * NINDIR(fs);
nblocks = btodb(fs->s_blocksize);
/*
* Update file and block pointers on disk before we start freeing
* blocks. If we crash before free'ing blocks below, the blocks
* will be returned to the free list. lastiblock values are also
* normalized to -1 for calls to ext2_indirtrunc below.
*/
bcopy((caddr_t)&oip->i_db[0], (caddr_t)oldblks, sizeof oldblks);
for (level = TRIPLE; level >= SINGLE; level--)
if (lastiblock[level] < 0) {
oip->i_ib[level] = 0;
lastiblock[level] = -1;
}
for (i = NDADDR - 1; i > lastblock; i--)
oip->i_db[i] = 0;
oip->i_flag |= IN_CHANGE | IN_UPDATE;
allerror = ext2_update(ovp, 1);
/*
* Having written the new inode to disk, save its new configuration
* and put back the old block pointers long enough to process them.
* Note that we save the new block configuration so we can check it
* when we are done.
*/
bcopy((caddr_t)&oip->i_db[0], (caddr_t)newblks, sizeof newblks);
bcopy((caddr_t)oldblks, (caddr_t)&oip->i_db[0], sizeof oldblks);
oip->i_size = osize;
error = vtruncbuf(ovp, cred, td, length, (int)fs->s_blocksize);
if (error && (allerror == 0))
allerror = error;
/*
* Indirect blocks first.
*/
indir_lbn[SINGLE] = -NDADDR;
indir_lbn[DOUBLE] = indir_lbn[SINGLE] - NINDIR(fs) - 1;
indir_lbn[TRIPLE] = indir_lbn[DOUBLE] - NINDIR(fs) * NINDIR(fs) - 1;
for (level = TRIPLE; level >= SINGLE; level--) {
bn = oip->i_ib[level];
if (bn != 0) {
error = ext2_indirtrunc(oip, indir_lbn[level],
fsbtodb(fs, bn), lastiblock[level], level, &count);
if (error)
allerror = error;
blocksreleased += count;
if (lastiblock[level] < 0) {
oip->i_ib[level] = 0;
ext2_blkfree(oip, bn, fs->s_frag_size);
blocksreleased += nblocks;
}
}
if (lastiblock[level] >= 0)
goto done;
}
/*
* All whole direct blocks or frags.
*/
for (i = NDADDR - 1; i > lastblock; i--) {
long bsize;
bn = oip->i_db[i];
if (bn == 0)
continue;
oip->i_db[i] = 0;
bsize = blksize(fs, oip, i);
ext2_blkfree(oip, bn, bsize);
blocksreleased += btodb(bsize);
}
if (lastblock < 0)
goto done;
/*
* Finally, look for a change in size of the
* last direct block; release any frags.
*/
bn = oip->i_db[lastblock];
if (bn != 0) {
long oldspace, newspace;
/*
* Calculate amount of space we're giving
* back as old block size minus new block size.
*/
oldspace = blksize(fs, oip, lastblock);
oip->i_size = length;
newspace = blksize(fs, oip, lastblock);
if (newspace == 0)
panic("itrunc: newspace");
if (oldspace - newspace > 0) {
/*
* Block number of space to be free'd is
* the old block # plus the number of frags
* required for the storage we're keeping.
*/
bn += numfrags(fs, newspace);
ext2_blkfree(oip, bn, oldspace - newspace);
blocksreleased += btodb(oldspace - newspace);
}
}
done:
#if DIAGNOSTIC
for (level = SINGLE; level <= TRIPLE; level++)
if (newblks[NDADDR + level] != oip->i_ib[level])
panic("itrunc1");
for (i = 0; i < NDADDR; i++)
if (newblks[i] != oip->i_db[i])
panic("itrunc2");
VI_LOCK(ovp);
if (length == 0 && (ovp->v_bufobj.bo_dirty.bv_cnt != 0 ||
ovp->v_bufobj.bo_clean.bv_cnt != 0))
panic("itrunc3");
VI_UNLOCK(ovp);
#endif /* DIAGNOSTIC */
/*
* Put back the real size.
*/
oip->i_size = length;
oip->i_blocks -= blocksreleased;
if (oip->i_blocks < 0) /* sanity */
oip->i_blocks = 0;
oip->i_flag |= IN_CHANGE;
vnode_pager_setsize(ovp, length);
return (allerror);
}
/*
* Release blocks associated with the inode ip and stored in the indirect
* block bn. Blocks are free'd in LIFO order up to (but not including)
* lastbn. If level is greater than SINGLE, the block is an indirect block
* and recursive calls to indirtrunc must be used to cleanse other indirect
* blocks.
*
* NB: triple indirect blocks are untested.
*/
static int
ext2_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
struct inode *ip;
int32_t lbn, lastbn;
int32_t dbn;
int level;
long *countp;
{
struct buf *bp;
struct ext2_sb_info *fs = ip->i_e2fs;
struct vnode *vp;
int32_t *bap, *copy, nb, nlbn, last;
long blkcount, factor;
int i, nblocks, blocksreleased = 0;
int error = 0, allerror = 0;
/*
* Calculate index in current block of last
* block to be kept. -1 indicates the entire
* block so we need not calculate the index.
*/
factor = 1;
for (i = SINGLE; i < level; i++)
factor *= NINDIR(fs);
last = lastbn;
if (lastbn > 0)
last /= factor;
nblocks = btodb(fs->s_blocksize);
/*
* Get buffer of block pointers, zero those entries corresponding
* to blocks to be free'd, and update on disk copy first. Since
* double(triple) indirect before single(double) indirect, calls
* to bmap on these blocks will fail. However, we already have
* the on disk address, so we have to set the b_blkno field
* explicitly instead of letting bread do everything for us.
*/
vp = ITOV(ip);
bp = getblk(vp, lbn, (int)fs->s_blocksize, 0, 0, 0);
if (bp->b_flags & (B_DONE | B_DELWRI)) {
} else {
bp->b_iocmd = BIO_READ;
if (bp->b_bcount > bp->b_bufsize)
panic("ext2_indirtrunc: bad buffer size");
bp->b_blkno = dbn;
vfs_busy_pages(bp, 0);
bp->b_iooffset = dbtob(bp->b_blkno);
bstrategy(bp);
error = bufwait(bp);
}
if (error) {
brelse(bp);
*countp = 0;
return (error);
}
bap = (int32_t *)bp->b_data;
MALLOC(copy, int32_t *, fs->s_blocksize, M_TEMP, M_WAITOK);
bcopy((caddr_t)bap, (caddr_t)copy, (u_int)fs->s_blocksize);
bzero((caddr_t)&bap[last + 1],
(u_int)(NINDIR(fs) - (last + 1)) * sizeof (int32_t));
if (last == -1)
bp->b_flags |= B_INVAL;
error = bwrite(bp);
if (error)
allerror = error;
bap = copy;
/*
* Recursively free totally unused blocks.
*/
for (i = NINDIR(fs) - 1, nlbn = lbn + 1 - i * factor; i > last;
i--, nlbn += factor) {
nb = bap[i];
if (nb == 0)
continue;
if (level > SINGLE) {
if ((error = ext2_indirtrunc(ip, nlbn,
fsbtodb(fs, nb), (int32_t)-1, level - 1, &blkcount)) != 0)
allerror = error;
blocksreleased += blkcount;
}
ext2_blkfree(ip, nb, fs->s_blocksize);
blocksreleased += nblocks;
}
/*
* Recursively free last partial block.
*/
if (level > SINGLE && lastbn >= 0) {
last = lastbn % factor;
nb = bap[i];
if (nb != 0) {
if ((error = ext2_indirtrunc(ip, nlbn, fsbtodb(fs, nb),
last, level - 1, &blkcount)) != 0)
allerror = error;
blocksreleased += blkcount;
}
}
FREE(copy, M_TEMP);
*countp = blocksreleased;
return (allerror);
}
/*
* discard preallocated blocks
*/
int
ext2_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
struct thread *a_td;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
struct inode *ip = VTOI(vp);
struct thread *td = ap->a_td;
int mode, error = 0;
ext2_discard_prealloc(ip);
if (prtactive && vrefcnt(vp) != 0)
vprint("ext2_inactive: pushing active", vp);
/*
* Ignore inodes related to stale file handles.
*/
if (ip->i_mode == 0)
goto out;
if (ip->i_nlink <= 0) {
(void) vn_write_suspend_wait(vp, NULL, V_WAIT);
error = ext2_truncate(vp, (off_t)0, 0, NOCRED, td);
ip->i_rdev = 0;
mode = ip->i_mode;
ip->i_mode = 0;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
ext2_vfree(vp, ip->i_number, mode);
}
if (ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) {
if ((ip->i_flag & (IN_CHANGE | IN_UPDATE | IN_MODIFIED)) == 0 &&
vn_write_suspend_wait(vp, NULL, V_NOWAIT)) {
ip->i_flag &= ~IN_ACCESS;
} else {
(void) vn_write_suspend_wait(vp, NULL, V_WAIT);
ext2_update(vp, 0);
}
}
out:
/*
* If we are done with the inode, reclaim it
* so that it can be reused immediately.
*/
if (ip->i_mode == 0)
vrecycle(vp, td);
return (error);
}
/*
* Reclaim an inode so that it can be used for other purposes.
*/
int
ext2_reclaim(ap)
struct vop_reclaim_args /* {
struct vnode *a_vp;
struct thread *a_td;
} */ *ap;
{
struct inode *ip;
struct vnode *vp = ap->a_vp;
if (prtactive && vrefcnt(vp) != 0)
vprint("ufs_reclaim: pushing active", vp);
ip = VTOI(vp);
if (ip->i_flag & IN_LAZYMOD) {
ip->i_flag |= IN_MODIFIED;
ext2_update(vp, 0);
}
vfs_hash_remove(vp);
FREE(vp->v_data, M_EXT2NODE);
vp->v_data = 0;
vnode_destroy_vobject(vp);
return (0);
}

View File

@ -1,135 +0,0 @@
/*-
* Copyright (c) 1995 The University of Utah and
* the Computer Systems Laboratory at the University of Utah (CSL).
* All rights reserved.
*
* Permission to use, copy, modify and distribute this software is hereby
* granted provided that (1) source code retains these copyright, permission,
* and disclaimer notices, and (2) redistributions including binaries
* reproduce the notices in supporting documentation, and (3) all advertising
* materials mentioning features or use of this software display the following
* acknowledgement: ``This product includes software developed by the
* Computer Systems Laboratory at the University of Utah.''
*
* THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
* IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
* ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* CSL requests users of this software to return to csl-dist@cs.utah.edu any
* improvements that they make and grant CSL redistribution rights.
*
* Utah $Hdr$
* $FreeBSD$
*/
/*
* routines to convert on disk ext2 inodes into inodes and back
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/lock.h>
#include <sys/stat.h>
#include <sys/vnode.h>
#include <gnu/ext2fs/inode.h>
#include <gnu/ext2fs/ext2_fs.h>
#include <gnu/ext2fs/ext2_extern.h>
void
ext2_print_inode( in )
struct inode *in;
{
int i;
printf( "Inode: %5d", in->i_number);
printf( /* "Inode: %5d" */
" Type: %10s Mode: 0x%o Flags: 0x%x Version: %d\n",
"n/a", in->i_mode, in->i_flags, in->i_gen);
printf( "User: %5lu Group: %5lu Size: %lu\n",
(unsigned long)in->i_uid, (unsigned long)in->i_gid,
(unsigned long)in->i_size);
printf( "Links: %3d Blockcount: %d\n",
in->i_nlink, in->i_blocks);
printf( "ctime: 0x%x", in->i_ctime);
printf( "atime: 0x%x", in->i_atime);
printf( "mtime: 0x%x", in->i_mtime);
printf( "BLOCKS: ");
for(i=0; i < (in->i_blocks <= 24 ? ((in->i_blocks+1)/2): 12); i++)
printf("%d ", in->i_db[i]);
printf("\n");
}
/*
* raw ext2 inode to inode
*/
void
ext2_ei2i(ei, ip)
struct ext2_inode *ei;
struct inode *ip;
{
int i;
ip->i_nlink = ei->i_links_count;
/* Godmar thinks - if the link count is zero, then the inode is
unused - according to ext2 standards. Ufs marks this fact
by setting i_mode to zero - why ?
I can see that this might lead to problems in an undelete.
*/
ip->i_mode = ei->i_links_count ? ei->i_mode : 0;
ip->i_size = ei->i_size;
if (S_ISREG(ip->i_mode))
ip->i_size |= ((u_int64_t)ei->i_size_high) << 32;
ip->i_atime = ei->i_atime;
ip->i_mtime = ei->i_mtime;
ip->i_ctime = ei->i_ctime;
ip->i_flags = 0;
ip->i_flags |= (ei->i_flags & EXT2_APPEND_FL) ? APPEND : 0;
ip->i_flags |= (ei->i_flags & EXT2_IMMUTABLE_FL) ? IMMUTABLE : 0;
ip->i_blocks = ei->i_blocks;
ip->i_gen = ei->i_generation;
ip->i_uid = ei->i_uid;
ip->i_gid = ei->i_gid;
/* XXX use memcpy */
for(i = 0; i < NDADDR; i++)
ip->i_db[i] = ei->i_block[i];
for(i = 0; i < NIADDR; i++)
ip->i_ib[i] = ei->i_block[EXT2_NDIR_BLOCKS + i];
}
/*
* inode to raw ext2 inode
*/
void
ext2_i2ei(ip, ei)
struct inode *ip;
struct ext2_inode *ei;
{
int i;
ei->i_mode = ip->i_mode;
ei->i_links_count = ip->i_nlink;
/*
Godmar thinks: if dtime is nonzero, ext2 says this inode
has been deleted, this would correspond to a zero link count
*/
ei->i_dtime = ei->i_links_count ? 0 : ip->i_mtime;
ei->i_size = ip->i_size;
if (S_ISREG(ip->i_mode))
ei->i_size_high = ip->i_size >> 32;
ei->i_atime = ip->i_atime;
ei->i_mtime = ip->i_mtime;
ei->i_ctime = ip->i_ctime;
ei->i_flags = ip->i_flags;
ei->i_flags = 0;
ei->i_flags |= (ip->i_flags & APPEND) ? EXT2_APPEND_FL: 0;
ei->i_flags |= (ip->i_flags & IMMUTABLE) ? EXT2_IMMUTABLE_FL: 0;
ei->i_blocks = ip->i_blocks;
ei->i_generation = ip->i_gen;
ei->i_uid = ip->i_uid;
ei->i_gid = ip->i_gid;
/* XXX use memcpy */
for(i = 0; i < NDADDR; i++)
ei->i_block[i] = ip->i_db[i];
for(i = 0; i < NIADDR; i++)
ei->i_block[EXT2_NDIR_BLOCKS + i] = ip->i_ib[i];
}

View File

@ -1,610 +0,0 @@
/*-
* modified for Lites 1.1
*
* Aug 1995, Godmar Back (gback@cs.utah.edu)
* University of Utah, Department of Computer Science
*
* $FreeBSD$
*/
/*-
* linux/fs/ext2/balloc.c
*
* Copyright (C) 1992, 1993, 1994, 1995
* Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* Enhanced block allocation by Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
*/
/*
* The free blocks are managed by bitmaps. A file system contains several
* blocks groups. Each group contains 1 bitmap block for blocks, 1 bitmap
* block for inodes, N blocks for the inode table and data blocks.
*
* The file system contains group descriptors which are located after the
* super block. Each descriptor contains the number of the bitmap block and
* the free blocks count in the block. The descriptors are loaded in memory
* when a file system is mounted (see ext2_read_super).
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/mount.h>
#include <sys/vnode.h>
#include <gnu/ext2fs/inode.h>
#include <gnu/ext2fs/ext2_mount.h>
#include <gnu/ext2fs/ext2_extern.h>
#include <gnu/ext2fs/ext2_fs.h>
#include <gnu/ext2fs/ext2_fs_sb.h>
#include <gnu/ext2fs/fs.h>
#ifdef __i386__
#include <gnu/ext2fs/i386-bitops.h>
#else
#include <gnu/ext2fs/ext2_bitops.h>
#endif
#define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1)
/* got rid of get_group_desc since it can already be found in
* ext2_linux_ialloc.c
*/
static void read_block_bitmap (struct mount * mp,
unsigned int block_group,
unsigned long bitmap_nr)
{
struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs;
struct ext2_group_desc * gdp;
struct buffer_head * bh;
int error;
gdp = get_group_desc (mp, block_group, NULL);
if ((error = bread (VFSTOEXT2(mp)->um_devvp,
fsbtodb(sb, gdp->bg_block_bitmap),sb->s_blocksize, NOCRED, &bh)) != 0)
panic ( "read_block_bitmap: "
"Cannot read block bitmap - "
"block_group = %d, block_bitmap = %lu",
block_group, (unsigned long) gdp->bg_block_bitmap);
sb->s_block_bitmap_number[bitmap_nr] = block_group;
sb->s_block_bitmap[bitmap_nr] = bh;
LCK_BUF(bh)
}
/*
* load_block_bitmap loads the block bitmap for a blocks group
*
* It maintains a cache for the last bitmaps loaded. This cache is managed
* with a LRU algorithm.
*
* Notes:
* 1/ There is one cache per mounted file system.
* 2/ If the file system contains less than EXT2_MAX_GROUP_LOADED groups,
* this function reads the bitmap without maintaining a LRU cache.
*/
static int load__block_bitmap (struct mount * mp,
unsigned int block_group)
{
int i, j;
struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs;
unsigned long block_bitmap_number;
struct buffer_head * block_bitmap;
if (block_group >= sb->s_groups_count)
panic ( "load_block_bitmap: "
"block_group >= groups_count - "
"block_group = %d, groups_count = %lu",
block_group, sb->s_groups_count);
if (sb->s_groups_count <= EXT2_MAX_GROUP_LOADED) {
if (sb->s_block_bitmap[block_group]) {
if (sb->s_block_bitmap_number[block_group] !=
block_group)
panic ( "load_block_bitmap: "
"block_group != block_bitmap_number");
else
return block_group;
} else {
read_block_bitmap (mp, block_group, block_group);
return block_group;
}
}
for (i = 0; i < sb->s_loaded_block_bitmaps &&
sb->s_block_bitmap_number[i] != block_group; i++)
;
if (i < sb->s_loaded_block_bitmaps &&
sb->s_block_bitmap_number[i] == block_group) {
block_bitmap_number = sb->s_block_bitmap_number[i];
block_bitmap = sb->s_block_bitmap[i];
for (j = i; j > 0; j--) {
sb->s_block_bitmap_number[j] =
sb->s_block_bitmap_number[j - 1];
sb->s_block_bitmap[j] =
sb->s_block_bitmap[j - 1];
}
sb->s_block_bitmap_number[0] = block_bitmap_number;
sb->s_block_bitmap[0] = block_bitmap;
} else {
if (sb->s_loaded_block_bitmaps < EXT2_MAX_GROUP_LOADED)
sb->s_loaded_block_bitmaps++;
else
ULCK_BUF(sb->s_block_bitmap[EXT2_MAX_GROUP_LOADED - 1])
for (j = sb->s_loaded_block_bitmaps - 1; j > 0; j--) {
sb->s_block_bitmap_number[j] =
sb->s_block_bitmap_number[j - 1];
sb->s_block_bitmap[j] =
sb->s_block_bitmap[j - 1];
}
read_block_bitmap (mp, block_group, 0);
}
return 0;
}
static __inline int load_block_bitmap (struct mount * mp,
unsigned int block_group)
{
struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs;
if (sb->s_loaded_block_bitmaps > 0 &&
sb->s_block_bitmap_number[0] == block_group)
return 0;
if (sb->s_groups_count <= EXT2_MAX_GROUP_LOADED &&
sb->s_block_bitmap_number[block_group] == block_group &&
sb->s_block_bitmap[block_group])
return block_group;
return load__block_bitmap (mp, block_group);
}
void ext2_free_blocks (struct mount * mp, unsigned long block,
unsigned long count)
{
struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs;
struct buffer_head * bh;
struct buffer_head * bh2;
unsigned long block_group;
unsigned long bit;
unsigned long i;
int bitmap_nr;
struct ext2_group_desc * gdp;
struct ext2_super_block * es;
if (!sb) {
printf ("ext2_free_blocks: nonexistent device");
return;
}
es = sb->s_es;
lock_super (VFSTOEXT2(mp)->um_devvp);
if (block < es->s_first_data_block ||
(block + count) > es->s_blocks_count) {
printf ( "ext2_free_blocks: "
"Freeing blocks not in datazone - "
"block = %lu, count = %lu", block, count);
unlock_super (VFSTOEXT2(mp)->um_devvp);
return;
}
ext2_debug ("freeing blocks %lu to %lu\n", block, block+count-1);
block_group = (block - es->s_first_data_block) /
EXT2_BLOCKS_PER_GROUP(sb);
bit = (block - es->s_first_data_block) % EXT2_BLOCKS_PER_GROUP(sb);
if (bit + count > EXT2_BLOCKS_PER_GROUP(sb))
panic ( "ext2_free_blocks: "
"Freeing blocks across group boundary - "
"Block = %lu, count = %lu",
block, count);
bitmap_nr = load_block_bitmap (mp, block_group);
bh = sb->s_block_bitmap[bitmap_nr];
gdp = get_group_desc (mp, block_group, &bh2);
if (/* test_opt (sb, CHECK_STRICT) && assume always strict ! */
(in_range (gdp->bg_block_bitmap, block, count) ||
in_range (gdp->bg_inode_bitmap, block, count) ||
in_range (block, gdp->bg_inode_table,
sb->s_itb_per_group) ||
in_range (block + count - 1, gdp->bg_inode_table,
sb->s_itb_per_group)))
panic ( "ext2_free_blocks: "
"Freeing blocks in system zones - "
"Block = %lu, count = %lu",
block, count);
for (i = 0; i < count; i++) {
if (!clear_bit (bit + i, bh->b_data))
printf ("ext2_free_blocks: "
"bit already cleared for block %lu",
block);
else {
gdp->bg_free_blocks_count++;
es->s_free_blocks_count++;
}
}
mark_buffer_dirty(bh2);
mark_buffer_dirty(bh);
/****
if (sb->s_flags & MS_SYNCHRONOUS) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
}
****/
sb->s_dirt = 1;
unlock_super (VFSTOEXT2(mp)->um_devvp);
return;
}
/*
* ext2_new_block uses a goal block to assist allocation. If the goal is
* free, or there is a free block within 32 blocks of the goal, that block
* is allocated. Otherwise a forward search is made for a free block; within
* each block group the search first looks for an entire free byte in the block
* bitmap, and then for any free bit if that fails.
*/
int ext2_new_block (struct mount * mp, unsigned long goal,
u_int32_t * prealloc_count,
u_int32_t * prealloc_block)
{
struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs;
struct buffer_head * bh;
struct buffer_head * bh2;
char * p, * r;
int i, j, k, tmp;
int bitmap_nr;
struct ext2_group_desc * gdp;
struct ext2_super_block * es;
#ifdef EXT2FS_DEBUG
static int goal_hits = 0, goal_attempts = 0;
#endif
if (!sb) {
printf ("ext2_new_block: nonexistent device");
return 0;
}
es = sb->s_es;
lock_super (VFSTOEXT2(mp)->um_devvp);
ext2_debug ("goal=%lu.\n", goal);
repeat:
/*
* First, test whether the goal block is free.
*/
if (goal < es->s_first_data_block || goal >= es->s_blocks_count)
goal = es->s_first_data_block;
i = (goal - es->s_first_data_block) / EXT2_BLOCKS_PER_GROUP(sb);
gdp = get_group_desc (mp, i, &bh2);
if (gdp->bg_free_blocks_count > 0) {
j = ((goal - es->s_first_data_block) % EXT2_BLOCKS_PER_GROUP(sb));
#ifdef EXT2FS_DEBUG
if (j)
goal_attempts++;
#endif
bitmap_nr = load_block_bitmap (mp, i);
bh = sb->s_block_bitmap[bitmap_nr];
ext2_debug ("goal is at %d:%d.\n", i, j);
if (!test_bit(j, bh->b_data)) {
#ifdef EXT2FS_DEBUG
goal_hits++;
ext2_debug ("goal bit allocated.\n");
#endif
goto got_block;
}
if (j) {
/*
* The goal was occupied; search forward for a free
* block within the next XX blocks.
*
* end_goal is more or less random, but it has to be
* less than EXT2_BLOCKS_PER_GROUP. Aligning up to the
* next 64-bit boundary is simple..
*/
int end_goal = (j + 63) & ~63;
j = find_next_zero_bit(bh->b_data, end_goal, j);
if (j < end_goal)
goto got_block;
}
ext2_debug ("Bit not found near goal\n");
/*
* There has been no free block found in the near vicinity
* of the goal: do a search forward through the block groups,
* searching in each group first for an entire free byte in
* the bitmap and then for any free bit.
*
* Search first in the remainder of the current group; then,
* cyclicly search through the rest of the groups.
*/
p = ((char *) bh->b_data) + (j >> 3);
r = memscan(p, 0, (EXT2_BLOCKS_PER_GROUP(sb) - j + 7) >> 3);
k = (r - ((char *) bh->b_data)) << 3;
if (k < EXT2_BLOCKS_PER_GROUP(sb)) {
j = k;
goto search_back;
}
k = find_next_zero_bit ((unsigned long *) bh->b_data,
EXT2_BLOCKS_PER_GROUP(sb),
j);
if (k < EXT2_BLOCKS_PER_GROUP(sb)) {
j = k;
goto got_block;
}
}
ext2_debug ("Bit not found in block group %d.\n", i);
/*
* Now search the rest of the groups. We assume that
* i and gdp correctly point to the last group visited.
*/
for (k = 0; k < sb->s_groups_count; k++) {
i++;
if (i >= sb->s_groups_count)
i = 0;
gdp = get_group_desc (mp, i, &bh2);
if (gdp->bg_free_blocks_count > 0)
break;
}
if (k >= sb->s_groups_count) {
unlock_super (VFSTOEXT2(mp)->um_devvp);
return 0;
}
bitmap_nr = load_block_bitmap (mp, i);
bh = sb->s_block_bitmap[bitmap_nr];
r = memscan(bh->b_data, 0, EXT2_BLOCKS_PER_GROUP(sb) >> 3);
j = (r - bh->b_data) << 3;
if (j < EXT2_BLOCKS_PER_GROUP(sb))
goto search_back;
else
j = find_first_zero_bit ((unsigned long *) bh->b_data,
EXT2_BLOCKS_PER_GROUP(sb));
if (j >= EXT2_BLOCKS_PER_GROUP(sb)) {
printf ( "ext2_new_block: "
"Free blocks count corrupted for block group %d", i);
unlock_super (VFSTOEXT2(mp)->um_devvp);
return 0;
}
search_back:
/*
* We have succeeded in finding a free byte in the block
* bitmap. Now search backwards up to 7 bits to find the
* start of this group of free blocks.
*/
for (k = 0; k < 7 && j > 0 && !test_bit (j - 1, bh->b_data); k++, j--);
got_block:
ext2_debug ("using block group %d(%d)\n", i, gdp->bg_free_blocks_count);
tmp = j + i * EXT2_BLOCKS_PER_GROUP(sb) + es->s_first_data_block;
if (/* test_opt (sb, CHECK_STRICT) && we are always strict. */
(tmp == gdp->bg_block_bitmap ||
tmp == gdp->bg_inode_bitmap ||
in_range (tmp, gdp->bg_inode_table, sb->s_itb_per_group)))
panic ( "ext2_new_block: "
"Allocating block in system zone - "
"%dth block = %u in group %u", j, tmp, i);
if (set_bit (j, bh->b_data)) {
printf ( "ext2_new_block: "
"bit already set for block %d", j);
goto repeat;
}
ext2_debug ("found bit %d\n", j);
/*
* Do block preallocation now if required.
*/
#ifdef EXT2_PREALLOCATE
if (prealloc_block) {
*prealloc_count = 0;
*prealloc_block = tmp + 1;
for (k = 1;
k < 8 && (j + k) < EXT2_BLOCKS_PER_GROUP(sb); k++) {
if (set_bit (j + k, bh->b_data))
break;
(*prealloc_count)++;
}
gdp->bg_free_blocks_count -= *prealloc_count;
es->s_free_blocks_count -= *prealloc_count;
ext2_debug ("Preallocated a further %lu bits.\n",
*prealloc_count);
}
#endif
j = tmp;
mark_buffer_dirty(bh);
/****
if (sb->s_flags & MS_SYNCHRONOUS) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
}
****/
if (j >= es->s_blocks_count) {
printf ( "ext2_new_block: "
"block >= blocks count - "
"block_group = %d, block=%d", i, j);
unlock_super (VFSTOEXT2(mp)->um_devvp);
return 0;
}
ext2_debug ("allocating block %d. "
"Goal hits %d of %d.\n", j, goal_hits, goal_attempts);
gdp->bg_free_blocks_count--;
mark_buffer_dirty(bh2);
es->s_free_blocks_count--;
sb->s_dirt = 1;
unlock_super (VFSTOEXT2(mp)->um_devvp);
return j;
}
#ifdef unused
static unsigned long ext2_count_free_blocks (struct mount * mp)
{
struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs;
#ifdef EXT2FS_DEBUG
struct ext2_super_block * es;
unsigned long desc_count, bitmap_count, x;
int bitmap_nr;
struct ext2_group_desc * gdp;
int i;
lock_super (VFSTOEXT2(mp)->um_devvp);
es = sb->s_es;
desc_count = 0;
bitmap_count = 0;
gdp = NULL;
for (i = 0; i < sb->s_groups_count; i++) {
gdp = get_group_desc (mp, i, NULL);
desc_count += gdp->bg_free_blocks_count;
bitmap_nr = load_block_bitmap (mp, i);
x = ext2_count_free (sb->s_block_bitmap[bitmap_nr],
sb->s_blocksize);
ext2_debug ("group %d: stored = %d, counted = %lu\n",
i, gdp->bg_free_blocks_count, x);
bitmap_count += x;
}
ext2_debug( "stored = %lu, computed = %lu, %lu\n",
es->s_free_blocks_count, desc_count, bitmap_count);
unlock_super (VFSTOEXT2(mp)->um_devvp);
return bitmap_count;
#else
return sb->s_es->s_free_blocks_count;
#endif
}
#endif /* unused */
static __inline int block_in_use (unsigned long block,
struct ext2_sb_info * sb,
unsigned char * map)
{
return test_bit ((block - sb->s_es->s_first_data_block) %
EXT2_BLOCKS_PER_GROUP(sb), map);
}
static int test_root(int a, int b)
{
if (a == 0)
return 1;
while (1) {
if (a == 1)
return 1;
if (a % b)
return 0;
a = a / b;
}
}
int ext2_group_sparse(int group)
{
return (test_root(group, 3) || test_root(group, 5) ||
test_root(group, 7));
}
#ifdef unused
static void ext2_check_blocks_bitmap (struct mount * mp)
{
struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs;
struct buffer_head * bh;
struct ext2_super_block * es;
unsigned long desc_count, bitmap_count, x;
unsigned long desc_blocks;
int bitmap_nr;
struct ext2_group_desc * gdp;
int i, j;
lock_super (VFSTOEXT2(mp)->um_devvp);
es = sb->s_es;
desc_count = 0;
bitmap_count = 0;
gdp = NULL;
desc_blocks = (sb->s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /
EXT2_DESC_PER_BLOCK(sb);
for (i = 0; i < sb->s_groups_count; i++) {
gdp = get_group_desc (mp, i, NULL);
desc_count += gdp->bg_free_blocks_count;
bitmap_nr = load_block_bitmap (mp, i);
bh = sb->s_block_bitmap[bitmap_nr];
if (!(es->s_feature_ro_compat &
EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) ||
ext2_group_sparse(i)) {
if (!test_bit (0, bh->b_data))
printf ("ext2_check_blocks_bitmap: "
"Superblock in group %d "
"is marked free", i);
for (j = 0; j < desc_blocks; j++)
if (!test_bit (j + 1, bh->b_data))
printf ("ext2_check_blocks_bitmap: "
"Descriptor block #%d in group "
"%d is marked free", j, i);
}
if (!block_in_use (gdp->bg_block_bitmap, sb, bh->b_data))
printf ("ext2_check_blocks_bitmap: "
"Block bitmap for group %d is marked free",
i);
if (!block_in_use (gdp->bg_inode_bitmap, sb, bh->b_data))
printf ("ext2_check_blocks_bitmap: "
"Inode bitmap for group %d is marked free",
i);
for (j = 0; j < sb->s_itb_per_group; j++)
if (!block_in_use (gdp->bg_inode_table + j, sb, bh->b_data))
printf ("ext2_check_blocks_bitmap: "
"Block #%d of the inode table in "
"group %d is marked free", j, i);
x = ext2_count_free (bh, sb->s_blocksize);
if (gdp->bg_free_blocks_count != x)
printf ("ext2_check_blocks_bitmap: "
"Wrong free blocks count for group %d, "
"stored = %d, counted = %lu", i,
gdp->bg_free_blocks_count, x);
bitmap_count += x;
}
if (es->s_free_blocks_count != bitmap_count)
printf ("ext2_check_blocks_bitmap: "
"Wrong free blocks count in super block, "
"stored = %lu, counted = %lu",
(unsigned long) es->s_free_blocks_count, bitmap_count);
unlock_super (VFSTOEXT2(mp)->um_devvp);
}
#endif /* unused */
/*
* this function is taken from
* linux/fs/ext2/bitmap.c
*/
static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
unsigned long ext2_count_free (struct buffer_head * map, unsigned int numchars)
{
unsigned int i;
unsigned long sum = 0;
if (!map)
return (0);
for (i = 0; i < numchars; i++)
sum += nibblemap[map->b_data[i] & 0xf] +
nibblemap[(map->b_data[i] >> 4) & 0xf];
return (sum);
}

View File

@ -1,512 +0,0 @@
/*-
* modified for Lites 1.1
*
* Aug 1995, Godmar Back (gback@cs.utah.edu)
* University of Utah, Department of Computer Science
*
* $FreeBSD$
*/
/*-
* linux/fs/ext2/ialloc.c
*
* Copyright (C) 1992, 1993, 1994, 1995
* Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* BSD ufs-inspired inode and directory allocation by
* Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
*/
/*
* The free inodes are managed by bitmaps. A file system contains several
* blocks groups. Each group contains 1 bitmap block for blocks, 1 bitmap
* block for inodes, N blocks for the inode table and data blocks.
*
* The file system contains group descriptors which are located after the
* super block. Each descriptor contains the number of the bitmap block and
* the free blocks count in the block. The descriptors are loaded in memory
* when a file system is mounted (see ext2_read_super).
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/mount.h>
#include <sys/vnode.h>
#include <gnu/ext2fs/inode.h>
#include <gnu/ext2fs/ext2_mount.h>
#include <gnu/ext2fs/ext2_extern.h>
#include <gnu/ext2fs/ext2_fs.h>
#include <gnu/ext2fs/ext2_fs_sb.h>
#include <gnu/ext2fs/fs.h>
#include <sys/stat.h>
#ifdef __i386__
#include <gnu/ext2fs/i386-bitops.h>
#else
#include <gnu/ext2fs/ext2_bitops.h>
#endif
/* this is supposed to mark a buffer dirty on ready for delayed writing
*/
void mark_buffer_dirty(struct buf *bh)
{
int s;
s = splbio();
bh->b_flags |= B_DIRTY;
splx(s);
}
struct ext2_group_desc * get_group_desc (struct mount * mp,
unsigned int block_group,
struct buffer_head ** bh)
{
struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs;
unsigned long group_desc;
unsigned long desc;
struct ext2_group_desc * gdp;
if (block_group >= sb->s_groups_count)
panic ("get_group_desc: "
"block_group >= groups_count - "
"block_group = %d, groups_count = %lu",
block_group, sb->s_groups_count);
group_desc = block_group / EXT2_DESC_PER_BLOCK(sb);
desc = block_group % EXT2_DESC_PER_BLOCK(sb);
if (!sb->s_group_desc[group_desc])
panic ( "get_group_desc:"
"Group descriptor not loaded - "
"block_group = %d, group_desc = %lu, desc = %lu",
block_group, group_desc, desc);
gdp = (struct ext2_group_desc *)
sb->s_group_desc[group_desc]->b_data;
if (bh)
*bh = sb->s_group_desc[group_desc];
return gdp + desc;
}
static void read_inode_bitmap (struct mount * mp,
unsigned long block_group,
unsigned int bitmap_nr)
{
struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs;
struct ext2_group_desc * gdp;
struct buffer_head * bh;
int error;
gdp = get_group_desc (mp, block_group, NULL);
if ((error = bread (VFSTOEXT2(mp)->um_devvp,
fsbtodb(sb, gdp->bg_inode_bitmap),
sb->s_blocksize,
NOCRED, &bh)) != 0)
panic ( "read_inode_bitmap:"
"Cannot read inode bitmap - "
"block_group = %lu, inode_bitmap = %lu",
block_group, (unsigned long) gdp->bg_inode_bitmap);
sb->s_inode_bitmap_number[bitmap_nr] = block_group;
sb->s_inode_bitmap[bitmap_nr] = bh;
LCK_BUF(bh)
}
/*
* load_inode_bitmap loads the inode bitmap for a blocks group
*
* It maintains a cache for the last bitmaps loaded. This cache is managed
* with a LRU algorithm.
*
* Notes:
* 1/ There is one cache per mounted file system.
* 2/ If the file system contains less than EXT2_MAX_GROUP_LOADED groups,
* this function reads the bitmap without maintaining a LRU cache.
*/
static int load_inode_bitmap (struct mount * mp,
unsigned int block_group)
{
struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs;
int i, j;
unsigned long inode_bitmap_number;
struct buffer_head * inode_bitmap;
if (block_group >= sb->s_groups_count)
panic ("load_inode_bitmap:"
"block_group >= groups_count - "
"block_group = %d, groups_count = %lu",
block_group, sb->s_groups_count);
if (sb->s_loaded_inode_bitmaps > 0 &&
sb->s_inode_bitmap_number[0] == block_group)
return 0;
if (sb->s_groups_count <= EXT2_MAX_GROUP_LOADED) {
if (sb->s_inode_bitmap[block_group]) {
if (sb->s_inode_bitmap_number[block_group] !=
block_group)
panic ( "load_inode_bitmap:"
"block_group != inode_bitmap_number");
else
return block_group;
} else {
read_inode_bitmap (mp, block_group, block_group);
return block_group;
}
}
for (i = 0; i < sb->s_loaded_inode_bitmaps &&
sb->s_inode_bitmap_number[i] != block_group;
i++)
;
if (i < sb->s_loaded_inode_bitmaps &&
sb->s_inode_bitmap_number[i] == block_group) {
inode_bitmap_number = sb->s_inode_bitmap_number[i];
inode_bitmap = sb->s_inode_bitmap[i];
for (j = i; j > 0; j--) {
sb->s_inode_bitmap_number[j] =
sb->s_inode_bitmap_number[j - 1];
sb->s_inode_bitmap[j] =
sb->s_inode_bitmap[j - 1];
}
sb->s_inode_bitmap_number[0] = inode_bitmap_number;
sb->s_inode_bitmap[0] = inode_bitmap;
} else {
if (sb->s_loaded_inode_bitmaps < EXT2_MAX_GROUP_LOADED)
sb->s_loaded_inode_bitmaps++;
else
ULCK_BUF(sb->s_inode_bitmap[EXT2_MAX_GROUP_LOADED - 1])
for (j = sb->s_loaded_inode_bitmaps - 1; j > 0; j--) {
sb->s_inode_bitmap_number[j] =
sb->s_inode_bitmap_number[j - 1];
sb->s_inode_bitmap[j] =
sb->s_inode_bitmap[j - 1];
}
read_inode_bitmap (mp, block_group, 0);
}
return 0;
}
void ext2_free_inode (struct inode * inode)
{
struct ext2_sb_info * sb;
struct buffer_head * bh;
struct buffer_head * bh2;
unsigned long block_group;
unsigned long bit;
int bitmap_nr;
struct ext2_group_desc * gdp;
struct ext2_super_block * es;
if (!inode)
return;
if (inode->i_nlink) {
printf ("ext2_free_inode: inode has nlink=%d\n",
inode->i_nlink);
return;
}
ext2_debug ("freeing inode %lu\n", inode->i_number);
sb = inode->i_e2fs;
lock_super (DEVVP(inode));
if (inode->i_number < EXT2_FIRST_INO ||
inode->i_number > sb->s_es->s_inodes_count) {
printf ("free_inode reserved inode or nonexistent inode");
unlock_super (DEVVP(inode));
return;
}
es = sb->s_es;
block_group = (inode->i_number - 1) / EXT2_INODES_PER_GROUP(sb);
bit = (inode->i_number - 1) % EXT2_INODES_PER_GROUP(sb);
bitmap_nr = load_inode_bitmap (ITOV(inode)->v_mount, block_group);
bh = sb->s_inode_bitmap[bitmap_nr];
if (!clear_bit (bit, bh->b_data))
printf ( "ext2_free_inode:"
"bit already cleared for inode %lu",
(unsigned long)inode->i_number);
else {
gdp = get_group_desc (ITOV(inode)->v_mount, block_group, &bh2);
gdp->bg_free_inodes_count++;
if (S_ISDIR(inode->i_mode))
gdp->bg_used_dirs_count--;
mark_buffer_dirty(bh2);
es->s_free_inodes_count++;
}
mark_buffer_dirty(bh);
/*** XXX
if (sb->s_flags & MS_SYNCHRONOUS) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
}
***/
sb->s_dirt = 1;
unlock_super (DEVVP(inode));
}
#if linux
/*
* This function increments the inode version number
*
* This may be used one day by the NFS server
*/
static void inc_inode_version (struct inode * inode,
struct ext2_group_desc *gdp,
int mode)
{
unsigned long inode_block;
struct buffer_head * bh;
struct ext2_inode * raw_inode;
inode_block = gdp->bg_inode_table + (((inode->i_number - 1) %
EXT2_INODES_PER_GROUP(inode->i_sb)) /
EXT2_INODES_PER_BLOCK(inode->i_sb));
bh = bread (inode->i_sb->s_dev, inode_block, inode->i_sb->s_blocksize);
if (!bh) {
printf ("inc_inode_version Cannot load inode table block - "
"inode=%lu, inode_block=%lu\n",
inode->i_number, inode_block);
inode->u.ext2_i.i_version = 1;
return;
}
raw_inode = ((struct ext2_inode *) bh->b_data) +
(((inode->i_number - 1) %
EXT2_INODES_PER_GROUP(inode->i_sb)) %
EXT2_INODES_PER_BLOCK(inode->i_sb));
raw_inode->i_version++;
inode->u.ext2_i.i_version = raw_inode->i_version;
bdwrite (bh);
}
#endif /* linux */
/*
* There are two policies for allocating an inode. If the new inode is
* a directory, then a forward search is made for a block group with both
* free space and a low directory-to-inode ratio; if that fails, then of
* the groups with above-average free space, that group with the fewest
* directories already is chosen.
*
* For other inodes, search forward from the parent directory\'s block
* group to find a free inode.
*/
/*
* this functino has been reduced to the actual 'find the inode number' part
*/
ino_t ext2_new_inode (const struct inode * dir, int mode)
{
struct ext2_sb_info * sb;
struct buffer_head * bh;
struct buffer_head * bh2;
int i, j, avefreei;
int bitmap_nr;
struct ext2_group_desc * gdp;
struct ext2_group_desc * tmp;
struct ext2_super_block * es;
if (!dir)
return 0;
sb = dir->i_e2fs;
lock_super (DEVVP(dir));
es = sb->s_es;
repeat:
gdp = NULL; i=0;
if (S_ISDIR(mode)) {
avefreei = es->s_free_inodes_count /
sb->s_groups_count;
/* I am not yet convinced that this next bit is necessary.
i = dir->u.ext2_i.i_block_group;
for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) {
tmp = get_group_desc (sb, i, &bh2);
if ((tmp->bg_used_dirs_count << 8) <
tmp->bg_free_inodes_count) {
gdp = tmp;
break;
}
else
i = ++i % sb->u.ext2_sb.s_groups_count;
}
*/
if (!gdp) {
for (j = 0; j < sb->s_groups_count; j++) {
tmp = get_group_desc(ITOV(dir)->v_mount,j,&bh2);
if (tmp->bg_free_inodes_count &&
tmp->bg_free_inodes_count >= avefreei) {
if (!gdp ||
(tmp->bg_free_blocks_count >
gdp->bg_free_blocks_count)) {
i = j;
gdp = tmp;
}
}
}
}
}
else
{
/*
* Try to place the inode in its parent directory
*/
i = dir->i_block_group;
tmp = get_group_desc (ITOV(dir)->v_mount, i, &bh2);
if (tmp->bg_free_inodes_count)
gdp = tmp;
else
{
/*
* Use a quadratic hash to find a group with a
* free inode
*/
for (j = 1; j < sb->s_groups_count; j <<= 1) {
i += j;
if (i >= sb->s_groups_count)
i -= sb->s_groups_count;
tmp = get_group_desc(ITOV(dir)->v_mount,i,&bh2);
if (tmp->bg_free_inodes_count) {
gdp = tmp;
break;
}
}
}
if (!gdp) {
/*
* That failed: try linear search for a free inode
*/
i = dir->i_block_group + 1;
for (j = 2; j < sb->s_groups_count; j++) {
if (++i >= sb->s_groups_count)
i = 0;
tmp = get_group_desc(ITOV(dir)->v_mount,i,&bh2);
if (tmp->bg_free_inodes_count) {
gdp = tmp;
break;
}
}
}
}
if (!gdp) {
unlock_super (DEVVP(dir));
return 0;
}
bitmap_nr = load_inode_bitmap (ITOV(dir)->v_mount, i);
bh = sb->s_inode_bitmap[bitmap_nr];
if ((j = find_first_zero_bit ((unsigned long *) bh->b_data,
EXT2_INODES_PER_GROUP(sb))) <
EXT2_INODES_PER_GROUP(sb)) {
if (set_bit (j, bh->b_data)) {
printf ( "ext2_new_inode:"
"bit already set for inode %d", j);
goto repeat;
}
/* Linux now does the following:
mark_buffer_dirty(bh);
if (sb->s_flags & MS_SYNCHRONOUS) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
}
*/
mark_buffer_dirty(bh);
} else {
if (gdp->bg_free_inodes_count != 0) {
printf ( "ext2_new_inode:"
"Free inodes count corrupted in group %d",
i);
unlock_super (DEVVP(dir));
return 0;
}
goto repeat;
}
j += i * EXT2_INODES_PER_GROUP(sb) + 1;
if (j < EXT2_FIRST_INO || j > es->s_inodes_count) {
printf ( "ext2_new_inode:"
"reserved inode or inode > inodes count - "
"block_group = %d,inode=%d", i, j);
unlock_super (DEVVP(dir));
return 0;
}
gdp->bg_free_inodes_count--;
if (S_ISDIR(mode))
gdp->bg_used_dirs_count++;
mark_buffer_dirty(bh2);
es->s_free_inodes_count--;
/* mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); */
sb->s_dirt = 1;
unlock_super (DEVVP(dir));
return j;
}
#ifdef unused
static unsigned long ext2_count_free_inodes (struct mount * mp)
{
#ifdef EXT2FS_DEBUG
struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs;
struct ext2_super_block * es;
unsigned long desc_count, bitmap_count, x;
int bitmap_nr;
struct ext2_group_desc * gdp;
int i;
lock_super (VFSTOEXT2(mp)->um_devvp);
es = sb->s_es;
desc_count = 0;
bitmap_count = 0;
gdp = NULL;
for (i = 0; i < sb->s_groups_count; i++) {
gdp = get_group_desc (mp, i, NULL);
desc_count += gdp->bg_free_inodes_count;
bitmap_nr = load_inode_bitmap (mp, i);
x = ext2_count_free (sb->s_inode_bitmap[bitmap_nr],
EXT2_INODES_PER_GROUP(sb) / 8);
ext2_debug ("group %d: stored = %d, counted = %lu\n",
i, gdp->bg_free_inodes_count, x);
bitmap_count += x;
}
ext2_debug("stored = %lu, computed = %lu, %lu\n",
es->s_free_inodes_count, desc_count, bitmap_count);
unlock_super (VFSTOEXT2(mp)->um_devvp);
return desc_count;
#else
return VFSTOEXT2(mp)->um_e2fsb->s_free_inodes_count;
#endif
}
#endif /* unused */
#ifdef LATER
void ext2_check_inodes_bitmap (struct mount * mp)
{
struct ext2_super_block * es;
unsigned long desc_count, bitmap_count, x;
int bitmap_nr;
struct ext2_group_desc * gdp;
int i;
lock_super (sb);
es = sb->u.ext2_sb.s_es;
desc_count = 0;
bitmap_count = 0;
gdp = NULL;
for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
gdp = get_group_desc (sb, i, NULL);
desc_count += gdp->bg_free_inodes_count;
bitmap_nr = load_inode_bitmap (sb, i);
x = ext2_count_free (sb->u.ext2_sb.s_inode_bitmap[bitmap_nr],
EXT2_INODES_PER_GROUP(sb) / 8);
if (gdp->bg_free_inodes_count != x)
printf ( "ext2_check_inodes_bitmap:"
"Wrong free inodes count in group %d, "
"stored = %d, counted = %lu", i,
gdp->bg_free_inodes_count, x);
bitmap_count += x;
}
if (es->s_free_inodes_count != bitmap_count)
printf ( "ext2_check_inodes_bitmap:"
"Wrong free inodes count in super block, "
"stored = %lu, counted = %lu",
(unsigned long) es->s_free_inodes_count, bitmap_count);
unlock_super (sb);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,73 +0,0 @@
/*-
* 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.
*
* @(#)ufsmount.h 8.6 (Berkeley) 3/30/95
* $FreeBSD$
*/
#ifndef _SYS_GNU_EXT2FS_EXT2_MOUNT_H_
#define _SYS_GNU_EXT2FS_EXT2_MOUNT_H_
#ifdef _KERNEL
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_EXT2NODE);
#endif
struct vnode;
/* This structure describes the ext2fs specific mount structure data. */
struct ext2mount {
struct mount *um_mountp; /* filesystem vfs structure */
struct cdev *um_dev; /* device mounted */
struct vnode *um_devvp; /* block device mounted vnode */
struct ext2_sb_info *um_e2fs; /* EXT2FS */
#define em_e2fsb um_e2fs->s_es
u_long um_nindir; /* indirect ptrs per block */
u_long um_bptrtodb; /* indir ptr to disk block */
u_long um_seqinc; /* inc between seq blocks */
struct g_consumer *um_cp;
struct bufobj *um_bo;
};
/* Convert mount ptr to ext2fsmount ptr. */
#define VFSTOEXT2(mp) ((struct ext2mount *)((mp)->mnt_data))
/*
* Macros to access file system parameters in the ufsmount structure.
* Used by ufs_bmap.
*/
#define MNINDIR(ump) ((ump)->um_nindir)
#define blkptrtodb(ump, b) ((b) << (ump)->um_bptrtodb)
#define is_sequential(ump, a, b) ((b) == (a) + ump->um_seqinc)
#endif /* _KERNEL */
#endif

View File

@ -1,304 +0,0 @@
/*-
* modified for Lites 1.1
*
* Aug 1995, Godmar Back (gback@cs.utah.edu)
* University of Utah, Department of Computer Science
*/
/*-
* Copyright (c) 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.
*
* @(#)ufs_readwrite.c 8.7 (Berkeley) 1/21/94
* $FreeBSD$
*/
#define BLKSIZE(a, b, c) blksize(a, b, c)
#define FS struct ext2_sb_info
#define I_FS i_e2fs
#define READ ext2_read
#define READ_S "ext2_read"
#define WRITE ext2_write
#define WRITE_S "ext2_write"
/*
* Vnode op for reading.
*/
/* ARGSUSED */
static int
READ(ap)
struct vop_read_args /* {
struct vnode *a_vp;
struct uio *a_uio;
int a_ioflag;
struct ucred *a_cred;
} */ *ap;
{
struct vnode *vp;
struct inode *ip;
struct uio *uio;
FS *fs;
struct buf *bp;
daddr_t lbn, nextlbn;
off_t bytesinfile;
long size, xfersize, blkoffset;
int error, orig_resid;
int seqcount = ap->a_ioflag >> IO_SEQSHIFT;
u_short mode;
vp = ap->a_vp;
ip = VTOI(vp);
mode = ip->i_mode;
uio = ap->a_uio;
#ifdef DIAGNOSTIC
if (uio->uio_rw != UIO_READ)
panic("%s: mode", READ_S);
if (vp->v_type == VLNK) {
if ((int)ip->i_size < vp->v_mount->mnt_maxsymlinklen)
panic("%s: short symlink", READ_S);
} else if (vp->v_type != VREG && vp->v_type != VDIR)
panic("%s: type %d", READ_S, vp->v_type);
#endif
fs = ip->I_FS;
if ((uoff_t)uio->uio_offset > fs->fs_maxfilesize)
return (EFBIG);
orig_resid = uio->uio_resid;
for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) {
if ((bytesinfile = ip->i_size - uio->uio_offset) <= 0)
break;
lbn = lblkno(fs, uio->uio_offset);
nextlbn = lbn + 1;
size = BLKSIZE(fs, ip, lbn);
blkoffset = blkoff(fs, uio->uio_offset);
xfersize = fs->s_frag_size - blkoffset;
if (uio->uio_resid < xfersize)
xfersize = uio->uio_resid;
if (bytesinfile < xfersize)
xfersize = bytesinfile;
if (lblktosize(fs, nextlbn) >= ip->i_size)
error = bread(vp, lbn, size, NOCRED, &bp);
else if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0)
error = cluster_read(vp,
ip->i_size, lbn, size, NOCRED,
uio->uio_resid, (ap->a_ioflag >> IO_SEQSHIFT), &bp);
else if (seqcount > 1) {
int nextsize = BLKSIZE(fs, ip, nextlbn);
error = breadn(vp, lbn,
size, &nextlbn, &nextsize, 1, NOCRED, &bp);
} else
error = bread(vp, lbn, size, NOCRED, &bp);
if (error) {
brelse(bp);
bp = NULL;
break;
}
/*
* We should only get non-zero b_resid when an I/O error
* has occurred, which should cause us to break above.
* However, if the short read did not cause an error,
* then we want to ensure that we do not uiomove bad
* or uninitialized data.
*/
size -= bp->b_resid;
if (size < xfersize) {
if (size == 0)
break;
xfersize = size;
}
error =
uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio);
if (error)
break;
bqrelse(bp);
}
if (bp != NULL)
bqrelse(bp);
if (orig_resid > 0 && (error == 0 || uio->uio_resid != orig_resid) &&
(vp->v_mount->mnt_flag & MNT_NOATIME) == 0)
ip->i_flag |= IN_ACCESS;
return (error);
}
/*
* Vnode op for writing.
*/
static int
WRITE(ap)
struct vop_write_args /* {
struct vnode *a_vp;
struct uio *a_uio;
int a_ioflag;
struct ucred *a_cred;
} */ *ap;
{
struct vnode *vp;
struct uio *uio;
struct inode *ip;
FS *fs;
struct buf *bp;
struct thread *td;
daddr_t lbn;
off_t osize;
int seqcount;
int blkoffset, error, flags, ioflag, resid, size, xfersize;
ioflag = ap->a_ioflag;
seqcount = ap->a_ioflag >> IO_SEQSHIFT;
uio = ap->a_uio;
vp = ap->a_vp;
ip = VTOI(vp);
#ifdef DIAGNOSTIC
if (uio->uio_rw != UIO_WRITE)
panic("%s: mode", WRITE_S);
#endif
switch (vp->v_type) {
case VREG:
if (ioflag & IO_APPEND)
uio->uio_offset = ip->i_size;
if ((ip->i_flags & APPEND) && uio->uio_offset != ip->i_size)
return (EPERM);
/* FALLTHROUGH */
case VLNK:
break;
case VDIR:
if ((ioflag & IO_SYNC) == 0)
panic("%s: nonsync dir write", WRITE_S);
break;
default:
panic("%s: type", WRITE_S);
}
fs = ip->I_FS;
if (uio->uio_offset < 0 ||
(uoff_t)uio->uio_offset + uio->uio_resid > fs->fs_maxfilesize)
return (EFBIG);
/*
* Maybe this should be above the vnode op call, but so long as
* file servers have no limits, I don't think it matters.
*/
td = uio->uio_td;
if (vp->v_type == VREG && td != NULL) {
PROC_LOCK(td->td_proc);
if (uio->uio_offset + uio->uio_resid >
lim_cur(td->td_proc, RLIMIT_FSIZE)) {
psignal(td->td_proc, SIGXFSZ);
PROC_UNLOCK(td->td_proc);
return (EFBIG);
}
PROC_UNLOCK(td->td_proc);
}
resid = uio->uio_resid;
osize = ip->i_size;
flags = ioflag & IO_SYNC ? B_SYNC : 0;
for (error = 0; uio->uio_resid > 0;) {
lbn = lblkno(fs, uio->uio_offset);
blkoffset = blkoff(fs, uio->uio_offset);
xfersize = fs->s_frag_size - blkoffset;
if (uio->uio_resid < xfersize)
xfersize = uio->uio_resid;
if (uio->uio_offset + xfersize > ip->i_size)
vnode_pager_setsize(vp, uio->uio_offset + xfersize);
/*
* Avoid a data-consistency race between write() and mmap()
* by ensuring that newly allocated blocks are zerod. The
* race can occur even in the case where the write covers
* the entire block.
*/
flags |= B_CLRBUF;
#if 0
if (fs->s_frag_size > xfersize)
flags |= B_CLRBUF;
else
flags &= ~B_CLRBUF;
#endif
error = ext2_balloc(ip,
lbn, blkoffset + xfersize, ap->a_cred, &bp, flags);
if (error)
break;
if (uio->uio_offset + xfersize > ip->i_size) {
ip->i_size = uio->uio_offset + xfersize;
}
size = BLKSIZE(fs, ip, lbn) - bp->b_resid;
if (size < xfersize)
xfersize = size;
error =
uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio);
if ((ioflag & IO_VMIO) &&
(LIST_FIRST(&bp->b_dep) == NULL)) /* in ext2fs? */
bp->b_flags |= B_RELBUF;
if (ioflag & IO_SYNC) {
(void)bwrite(bp);
} else if (xfersize + blkoffset == fs->s_frag_size) {
if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERW) == 0) {
bp->b_flags |= B_CLUSTEROK;
cluster_write(vp, bp, ip->i_size, seqcount);
} else {
bawrite(bp);
}
} else {
bp->b_flags |= B_CLUSTEROK;
bdwrite(bp);
}
if (error || xfersize == 0)
break;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
}
/*
* If we successfully wrote any data, and we are not the superuser
* we clear the setuid and setgid bits as a precaution against
* tampering.
*/
if (resid > uio->uio_resid && ap->a_cred && ap->a_cred->cr_uid != 0)
ip->i_mode &= ~(ISUID | ISGID);
if (error) {
if (ioflag & IO_UNIT) {
(void)ext2_truncate(vp, osize,
ioflag & IO_SYNC, ap->a_cred, uio->uio_td);
uio->uio_offset -= resid - uio->uio_resid;
uio->uio_resid = resid;
}
} else if (resid > uio->uio_resid && (ioflag & IO_SYNC))
error = ext2_update(vp, 1);
return (error);
}

View File

@ -1,120 +0,0 @@
/*-
* 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.
*
* @(#)ffs_subr.c 8.2 (Berkeley) 9/21/93
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/lock.h>
#include <sys/ucred.h>
#include <sys/vnode.h>
#include <gnu/ext2fs/inode.h>
#include <gnu/ext2fs/ext2_extern.h>
#include <gnu/ext2fs/ext2_fs_sb.h>
#include <gnu/ext2fs/fs.h>
#ifdef KDB
void ext2_checkoverlap(struct buf *, struct inode *);
#endif
/*
* Return buffer with the contents of block "offset" from the beginning of
* directory "ip". If "res" is non-zero, fill it in with a pointer to the
* remaining space in the directory.
*/
int
ext2_blkatoff(vp, offset, res, bpp)
struct vnode *vp;
off_t offset;
char **res;
struct buf **bpp;
{
struct inode *ip;
struct ext2_sb_info *fs;
struct buf *bp;
int32_t lbn;
int bsize, error;
ip = VTOI(vp);
fs = ip->i_e2fs;
lbn = lblkno(fs, offset);
bsize = blksize(fs, ip, lbn);
*bpp = NULL;
if ((error = bread(vp, lbn, bsize, NOCRED, &bp)) != 0) {
brelse(bp);
return (error);
}
if (res)
*res = (char *)bp->b_data + blkoff(fs, offset);
*bpp = bp;
return (0);
}
#ifdef KDB
void
ext2_checkoverlap(bp, ip)
struct buf *bp;
struct inode *ip;
{
struct buf *ebp, *ep;
int32_t start, last;
struct vnode *vp;
ebp = &buf[nbuf];
start = bp->b_blkno;
last = start + btodb(bp->b_bcount) - 1;
for (ep = buf; ep < ebp; ep++) {
if (ep == bp || (ep->b_flags & B_INVAL))
continue;
vp = ip->i_devvp;
/* look for overlap */
if (ep->b_bcount == 0 || ep->b_blkno > last ||
ep->b_blkno + btodb(ep->b_bcount) <= start)
continue;
vprint("Disk overlap", vp);
(void)printf("\tstart %d, end %d overlap start %lld, end %ld\n",
start, last, (long long)ep->b_blkno,
(long)(ep->b_blkno + btodb(ep->b_bcount) - 1));
panic("Disk buffer overlap");
}
}
#endif /* KDB */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,170 +0,0 @@
/*-
* modified for EXT2FS support in Lites 1.1
*
* Aug 1995, Godmar Back (gback@cs.utah.edu)
* University of Utah, Department of Computer Science
*/
/*-
* Copyright (c) 1982, 1986, 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.
*
* @(#)fs.h 8.7 (Berkeley) 4/19/94
* $FreeBSD$
*/
/*
* Each disk drive contains some number of file systems.
* A file system consists of a number of cylinder groups.
* Each cylinder group has inodes and data.
*
* A file system is described by its super-block, which in turn
* describes the cylinder groups. The super-block is critical
* data and is replicated in each cylinder group to protect against
* catastrophic loss. This is done at `newfs' time and the critical
* super-block data does not change, so the copies need not be
* referenced further unless disaster strikes.
*
* The first boot and super blocks are given in absolute disk addresses.
* The byte-offset forms are preferred, as they don't imply a sector size.
*/
#define SBSIZE 1024
#define SBLOCK 2
/*
* The path name on which the file system is mounted is maintained
* in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in
* the super block for this name.
*/
#define MAXMNTLEN 512
/*
* Macros for access to superblock array structures
*/
/*
* Convert cylinder group to base address of its global summary info.
*/
#define fs_cs(fs, cgindx) (((struct ext2_group_desc *) \
(fs->s_group_desc[cgindx / EXT2_DESC_PER_BLOCK(fs)]->b_data)) \
[cgindx % EXT2_DESC_PER_BLOCK(fs)])
/*
* Turn file system block numbers into disk block addresses.
* This maps file system blocks to device size blocks.
*/
#define fsbtodb(fs, b) ((b) << ((fs)->s_fsbtodb))
#define dbtofsb(fs, b) ((b) >> ((fs)->s_fsbtodb))
/* get group containing inode */
#define ino_to_cg(fs, x) (((x) - 1) / EXT2_INODES_PER_GROUP(fs))
/* get block containing inode from its number x */
#define ino_to_fsba(fs, x) fs_cs(fs, ino_to_cg(fs, x)).bg_inode_table + \
(((x)-1) % EXT2_INODES_PER_GROUP(fs))/EXT2_INODES_PER_BLOCK(fs)
/* get offset for inode in block */
#define ino_to_fsbo(fs, x) ((x-1) % EXT2_INODES_PER_BLOCK(fs))
/*
* Give cylinder group number for a file system block.
* Give cylinder group block number for a file system block.
*/
#define dtog(fs, d) (((d) - fs->s_es->s_first_data_block) / \
EXT2_BLOCKS_PER_GROUP(fs))
#define dtogd(fs, d) (((d) - fs->s_es->s_first_data_block) % \
EXT2_BLOCKS_PER_GROUP(fs))
/*
* The following macros optimize certain frequently calculated
* quantities by using shifts and masks in place of divisions
* modulos and multiplications.
*/
#define blkoff(fs, loc) /* calculates (loc % fs->fs_bsize) */ \
((loc) & (fs)->s_qbmask)
#define lblktosize(fs, blk) /* calculates (blk * fs->fs_bsize) */ \
((blk) << (fs->s_bshift))
#define lblkno(fs, loc) /* calculates (loc / fs->fs_bsize) */ \
((loc) >> (fs->s_bshift))
/* no fragments -> logical block number equal # of frags */
#define numfrags(fs, loc) /* calculates (loc / fs->fs_fsize) */ \
((loc) >> (fs->s_bshift))
#define fragroundup(fs, size) /* calculates roundup(size, fs->fs_fsize) */ \
roundup(size, fs->s_frag_size)
/* was (((size) + (fs)->fs_qfmask) & (fs)->fs_fmask) */
/*
* Determining the size of a file block in the file system.
* easy w/o fragments
*/
#define blksize(fs, ip, lbn) ((fs)->s_frag_size)
/*
* INOPB is the number of inodes in a secondary storage block.
*/
#define INOPB(fs) EXT2_INODES_PER_BLOCK(fs)
/*
* NINDIR is the number of indirects in a file system block.
*/
#define NINDIR(fs) (EXT2_ADDR_PER_BLOCK(fs))
extern int inside[], around[];
extern u_char *fragtbl[];
/* a few remarks about superblock locking/unlocking
* Linux provides special routines for doing so
* I haven't figured out yet what BSD does
* I think I'll try a VOP_LOCK/VOP_UNLOCK on the device vnode
*/
#define DEVVP(inode) (VFSTOEXT2(ITOV(inode)->v_mount)->um_devvp)
#define lock_super(devvp) vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, curthread)
#define unlock_super(devvp) VOP_UNLOCK(devvp, 0, curthread)
/*
* Historically, ext2fs kept it's metadata buffers on the LOCKED queue. Now,
* we simply change the lock owner to kern so that it may be released from
* another context. Later, we release the buffer, and conditionally write it
* when we're done.
*/
#define LCK_BUF(bp) BUF_KERNPROC(bp);
#define ULCK_BUF(bp) { \
long flags; \
int s; \
s = splbio(); \
flags = (bp)->b_flags; \
(bp)->b_flags &= ~(B_DIRTY); \
splx(s); \
if (flags & B_DIRTY) \
bwrite(bp); \
else \
brelse(bp); \
}

View File

@ -1,162 +0,0 @@
/* $FreeBSD$ */
/*
* this is mixture of i386/bitops.h and asm/string.h
* taken from the Linux source tree
*
* XXX replace with Mach routines or reprogram in C
*/
#ifndef _SYS_GNU_EXT2FS_I386_BITOPS_H_
#define _SYS_GNU_EXT2FS_I386_BITOPS_H_
/*-
* Copyright 1992, Linus Torvalds.
*/
/*
* These have to be done with inline assembly: that way the bit-setting
* is guaranteed to be atomic. All bit operations return 0 if the bit
* was cleared before the operation and != 0 if it was not.
*
* bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
*/
/*
* Some hacks to defeat gcc over-optimizations..
*/
struct __dummy { unsigned long a[100]; };
#define ADDR (*(struct __dummy *) addr)
static __inline__ int set_bit(int nr, void * addr)
{
int oldbit;
__asm__ __volatile__("btsl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
:"ir" (nr));
return oldbit;
}
static __inline__ int clear_bit(int nr, void * addr)
{
int oldbit;
__asm__ __volatile__("btrl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
:"ir" (nr));
return oldbit;
}
static __inline__ int change_bit(int nr, void * addr)
{
int oldbit;
__asm__ __volatile__("btcl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
:"ir" (nr));
return oldbit;
}
/*
* This routine doesn't need to be atomic, but it's faster to code it
* this way.
*/
static __inline__ int test_bit(int nr, void * addr)
{
int oldbit;
__asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit)
:"m" (ADDR),"ir" (nr));
return oldbit;
}
/*
* Find-bit routines..
*/
static __inline__ int find_first_zero_bit(void * addr, unsigned size)
{
int res;
int _count = (size + 31) >> 5;
if (!size)
return 0;
__asm__(" \n\
cld \n\
movl $-1,%%eax \n\
xorl %%edx,%%edx \n\
repe; scasl \n\
je 1f \n\
xorl -4(%%edi),%%eax \n\
subl $4,%%edi \n\
bsfl %%eax,%%edx \n\
1: subl %%ebx,%%edi \n\
shll $3,%%edi \n\
addl %%edi,%%edx"
: "=c" (_count), "=D" (addr), "=d" (res)
: "0" (_count), "1" (addr), "b" (addr)
: "ax");
return res;
}
static __inline__ int find_next_zero_bit (void * addr, int size, int offset)
{
unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
int set = 0, bit = offset & 31, res;
if (bit) {
/*
* Look for zero in first byte
*/
__asm__(" \n\
bsfl %1,%0 \n\
jne 1f \n\
movl $32, %0 \n\
1: "
: "=r" (set)
: "r" (~(*p >> bit)));
if (set < (32 - bit))
return set + offset;
set = 32 - bit;
p++;
}
/*
* No zero yet, search remaining full bytes for a zero
*/
res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
return (offset + set + res);
}
/*
* ffz = Find First Zero in word. Undefined if no zero exists,
* so code should check against ~0UL first..
*/
static __inline__ unsigned long ffz(unsigned long word)
{
__asm__("bsfl %1,%0"
:"=r" (word)
:"r" (~word));
return word;
}
/*
* memscan() taken from linux asm/string.h
*/
/*
* find the first occurrence of byte 'c', or 1 past the area if none
*/
static __inline__ char * memscan(void * addr, unsigned char c, int size)
{
if (!size)
return addr;
__asm__(" \n\
cld \n\
repnz; scasb \n\
jnz 1f \n\
dec %%edi \n\
1: "
: "=D" (addr), "=c" (size)
: "0" (addr), "1" (size), "a" (c));
return addr;
}
#endif /* !_SYS_GNU_EXT2FS_I386_BITOPS_H_ */

View File

@ -1,171 +0,0 @@
/*-
* Copyright (c) 1982, 1989, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* 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.
*
* @(#)inode.h 8.9 (Berkeley) 5/14/95
* $FreeBSD$
*/
#ifndef _SYS_GNU_EXT2FS_INODE_H_
#define _SYS_GNU_EXT2FS_INODE_H_
#include <sys/lock.h>
#include <sys/queue.h>
#define ROOTINO ((ino_t)2)
#define NDADDR 12 /* Direct addresses in inode. */
#define NIADDR 3 /* Indirect addresses in inode. */
/*
* This must agree with the definition in <ufs/ufs/dir.h>.
*/
#define doff_t int32_t
/*
* The inode is used to describe each active (or recently active) file in the
* EXT2FS filesystem. It is composed of two types of information. The first
* part is the information that is needed only while the file is active (such
* as the identity of the file and linkage to speed its lookup). The second
* part is the permanent meta-data associated with the file which is read in
* from the permanent dinode from long term storage when the file becomes
* active, and is put back when the file is no longer being used.
*/
struct inode {
struct vnode *i_vnode;/* Vnode associated with this inode. */
struct vnode *i_devvp;/* Vnode for block I/O. */
u_int32_t i_flag; /* flags, see below */
ino_t i_number; /* The identity of the inode. */
struct ext2_sb_info *i_e2fs; /* EXT2FS */
u_quad_t i_modrev; /* Revision level for NFS lease. */
struct lockf *i_lockf;/* Head of byte-level lock list. */
/*
* Side effects; used during directory lookup.
*/
int32_t i_count; /* Size of free slot in directory. */
doff_t i_endoff; /* End of useful stuff in directory. */
doff_t i_diroff; /* Offset in dir, where we found last entry. */
doff_t i_offset; /* Offset of free space in directory. */
ino_t i_ino; /* Inode number of found directory. */
u_int32_t i_reclen; /* Size of found directory entry. */
u_int32_t i_block_group;
u_int32_t i_next_alloc_block;
u_int32_t i_next_alloc_goal;
u_int32_t i_prealloc_block;
u_int32_t i_prealloc_count;
/* Fields from struct dinode in UFS. */
u_int16_t i_mode; /* IFMT, permissions; see below. */
int16_t i_nlink; /* File link count. */
u_int64_t i_size; /* File byte count. */
int32_t i_atime; /* Last access time. */
int32_t i_atimensec; /* Last access time. */
int32_t i_mtime; /* Last modified time. */
int32_t i_mtimensec; /* Last modified time. */
int32_t i_ctime; /* Last inode change time. */
int32_t i_ctimensec; /* Last inode change time. */
int32_t i_db[NDADDR]; /* Direct disk blocks. */
int32_t i_ib[NIADDR]; /* Indirect disk blocks. */
u_int32_t i_flags; /* Status flags (chflags). */
int32_t i_blocks; /* Blocks actually held. */
int32_t i_gen; /* Generation number. */
u_int32_t i_uid; /* File owner. */
u_int32_t i_gid; /* File group. */
};
/*
* The di_db fields may be overlaid with other information for
* file types that do not have associated disk storage. Block
* and character devices overlay the first data block with their
* dev_t value. Short symbolic links place their path in the
* di_db area.
*/
#define i_shortlink i_db
#define i_rdev i_db[0]
#define MAXSYMLINKLEN ((NDADDR + NIADDR) * sizeof(int32_t))
/* File permissions. */
#define IEXEC 0000100 /* Executable. */
#define IWRITE 0000200 /* Writeable. */
#define IREAD 0000400 /* Readable. */
#define ISVTX 0001000 /* Sticky bit. */
#define ISGID 0002000 /* Set-gid. */
#define ISUID 0004000 /* Set-uid. */
/* File types. */
#define IFMT 0170000 /* Mask of file type. */
#define IFIFO 0010000 /* Named pipe (fifo). */
#define IFCHR 0020000 /* Character device. */
#define IFDIR 0040000 /* Directory file. */
#define IFBLK 0060000 /* Block device. */
#define IFREG 0100000 /* Regular file. */
#define IFLNK 0120000 /* Symbolic link. */
#define IFSOCK 0140000 /* UNIX domain socket. */
#define IFWHT 0160000 /* Whiteout. */
/* These flags are kept in i_flag. */
#define IN_ACCESS 0x0001 /* Access time update request. */
#define IN_CHANGE 0x0002 /* Inode change time update request. */
#define IN_UPDATE 0x0004 /* Modification time update request. */
#define IN_MODIFIED 0x0008 /* Inode has been modified. */
#define IN_RENAME 0x0010 /* Inode is being renamed. */
#define IN_HASHED 0x0020 /* Inode is on hash list */
#define IN_LAZYMOD 0x0040 /* Modified, but don't write yet. */
#define IN_SPACECOUNTED 0x0080 /* Blocks to be freed in free count. */
#ifdef _KERNEL
/*
* Structure used to pass around logical block paths generated by
* ext2_getlbns and used by truncate and bmap code.
*/
struct indir {
int32_t in_lbn; /* Logical block number. */
int in_off; /* Offset in buffer. */
int in_exists; /* Flag if the block exists. */
};
/* Convert between inode pointers and vnode pointers. */
#define VTOI(vp) ((struct inode *)(vp)->v_data)
#define ITOV(ip) ((ip)->i_vnode)
/* This overlays the fid structure (see mount.h). */
struct ufid {
u_int16_t ufid_len; /* Length of structure. */
u_int16_t ufid_pad; /* Force 32-bit alignment. */
ino_t ufid_ino; /* File number (ino). */
int32_t ufid_gen; /* Generation number. */
};
#endif /* _KERNEL */
#endif /* !_SYS_GNU_EXT2FS_INODE_H_ */

View File

@ -1,250 +0,0 @@
/*-
* $Id: bitops.h,v 1.31 2000/09/23 02:09:21 davem Exp $
* bitops.h: Bit string operations on the V9.
*
* Copyright 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
*/
/* $FreeBSD$ */
#ifndef _SPARC64_BITOPS_H
#define _SPARC64_BITOPS_H
#include <asm/byteorder.h>
extern long __test_and_set_bit(unsigned long nr, volatile void *addr);
extern long __test_and_clear_bit(unsigned long nr, volatile void *addr);
extern long __test_and_change_bit(unsigned long nr, volatile void *addr);
#define test_and_set_bit(nr,addr) (__test_and_set_bit(nr,addr)!=0)
#define test_and_clear_bit(nr,addr) (__test_and_clear_bit(nr,addr)!=0)
#define test_and_change_bit(nr,addr) (__test_and_change_bit(nr,addr)!=0)
#define set_bit(nr,addr) ((void)__test_and_set_bit(nr,addr))
#define clear_bit(nr,addr) ((void)__test_and_clear_bit(nr,addr))
#define change_bit(nr,addr) ((void)__test_and_change_bit(nr,addr))
#define smp_mb__before_clear_bit() do { } while(0)
#define smp_mb__after_clear_bit() do { } while(0)
extern __inline__ int test_bit(int nr, __const__ void *addr)
{
return (1UL & (((__const__ long *) addr)[nr >> 6] >> (nr & 63))) != 0UL;
}
/* The easy/cheese version for now. */
extern __inline__ unsigned long ffz(unsigned long word)
{
unsigned long result;
#ifdef ULTRA_HAS_POPULATION_COUNT /* Thanks for nothing Sun... */
__asm__ __volatile__("
brz,pn %0, 1f
neg %0, %%g1
xnor %0, %%g1, %%g2
popc %%g2, %0
1: " : "=&r" (result)
: "0" (word)
: "g1", "g2");
#else
#if 1 /* def EASY_CHEESE_VERSION */
result = 0;
while(word & 1) {
result++;
word >>= 1;
}
#else
unsigned long tmp;
result = 0;
tmp = ~word & -~word;
if (!(unsigned)tmp) {
tmp >>= 32;
result = 32;
}
if (!(unsigned short)tmp) {
tmp >>= 16;
result += 16;
}
if (!(unsigned char)tmp) {
tmp >>= 8;
result += 8;
}
if (tmp & 0xf0) result += 4;
if (tmp & 0xcc) result += 2;
if (tmp & 0xaa) result ++;
#endif
#endif
return result;
}
#ifdef __KERNEL__
/*
* ffs: find first bit set. This is defined the same way as
* the libc and compiler builtin ffs routines, therefore
* differs in spirit from the above ffz (man ffs).
*/
#define ffs(x) generic_ffs(x)
/*
* hweightN: returns the hamming weight (i.e. the number
* of bits set) of a N-bit word
*/
#ifdef ULTRA_HAS_POPULATION_COUNT
extern __inline__ unsigned int hweight32(unsigned int w)
{
unsigned int res;
__asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffffffff));
return res;
}
extern __inline__ unsigned int hweight16(unsigned int w)
{
unsigned int res;
__asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffff));
return res;
}
extern __inline__ unsigned int hweight8(unsigned int w)
{
unsigned int res;
__asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xff));
return res;
}
#else
#define hweight32(x) generic_hweight32(x)
#define hweight16(x) generic_hweight16(x)
#define hweight8(x) generic_hweight8(x)
#endif
#endif /* __KERNEL__ */
/* find_next_zero_bit() finds the first zero bit in a bit string of length
* 'size' bits, starting the search at bit 'offset'. This is largely based
* on Linus's ALPHA routines, which are pretty portable BTW.
*/
extern __inline__ unsigned long find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
{
unsigned long *p = ((unsigned long *) addr) + (offset >> 6);
unsigned long result = offset & ~63UL;
unsigned long tmp;
if (offset >= size)
return size;
size -= result;
offset &= 63UL;
if (offset) {
tmp = *(p++);
tmp |= ~0UL >> (64-offset);
if (size < 64)
goto found_first;
if (~tmp)
goto found_middle;
size -= 64;
result += 64;
}
while (size & ~63UL) {
if (~(tmp = *(p++)))
goto found_middle;
result += 64;
size -= 64;
}
if (!size)
return result;
tmp = *p;
found_first:
tmp |= ~0UL << size;
if (tmp == ~0UL) /* Are any bits zero? */
return result + size; /* Nope. */
found_middle:
return result + ffz(tmp);
}
#define find_first_zero_bit(addr, size) \
find_next_zero_bit((addr), (size), 0)
extern long __test_and_set_le_bit(int nr, volatile void *addr);
extern long __test_and_clear_le_bit(int nr, volatile void *addr);
#define test_and_set_le_bit(nr,addr) (__test_and_set_le_bit(nr,addr)!=0)
#define test_and_clear_le_bit(nr,addr) (__test_and_clear_le_bit(nr,addr)!=0)
#define set_le_bit(nr,addr) ((void)__test_and_set_le_bit(nr,addr))
#define clear_le_bit(nr,addr) ((void)__test_and_clear_le_bit(nr,addr))
extern __inline__ int test_le_bit(int nr, __const__ void * addr)
{
int mask;
__const__ unsigned char *ADDR = (__const__ unsigned char *) addr;
ADDR += nr >> 3;
mask = 1 << (nr & 0x07);
return ((mask & *ADDR) != 0);
}
#define find_first_zero_le_bit(addr, size) \
find_next_zero_le_bit((addr), (size), 0)
extern __inline__ unsigned long find_next_zero_le_bit(void *addr, unsigned long size, unsigned long offset)
{
unsigned long *p = ((unsigned long *) addr) + (offset >> 6);
unsigned long result = offset & ~63UL;
unsigned long tmp;
if (offset >= size)
return size;
size -= result;
offset &= 63UL;
if(offset) {
tmp = __swab64p(p++);
tmp |= (~0UL >> (64-offset));
if(size < 64)
goto found_first;
if(~tmp)
goto found_middle;
size -= 64;
result += 64;
}
while(size & ~63) {
if(~(tmp = __swab64p(p++)))
goto found_middle;
result += 64;
size -= 64;
}
if(!size)
return result;
tmp = __swab64p(p);
found_first:
tmp |= (~0UL << size);
if (tmp == ~0UL) /* Are any bits zero? */
return result + size; /* Nope. */
found_middle:
return result + ffz(tmp);
}
#ifdef __KERNEL__
#define ext2_set_bit test_and_set_le_bit
#define ext2_clear_bit test_and_clear_le_bit
#define ext2_test_bit test_le_bit
#define ext2_find_first_zero_bit find_first_zero_le_bit
#define ext2_find_next_zero_bit find_next_zero_le_bit
/* Bitmap functions for the minix filesystem. */
#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
#define minix_set_bit(nr,addr) set_bit(nr,addr)
#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
#define minix_test_bit(nr,addr) test_bit(nr,addr)
#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
#endif /* __KERNEL__ */
#endif /* defined(_SPARC64_BITOPS_H) */