diff options
-rw-r--r-- | sys/conf/files | 21 | ||||
-rw-r--r-- | sys/fs/ext2fs/ext2_alloc.c | 973 | ||||
-rw-r--r-- | sys/fs/ext2fs/ext2_balloc.c (renamed from sys/gnu/fs/ext2fs/ext2_balloc.c) | 118 | ||||
-rw-r--r-- | sys/fs/ext2fs/ext2_bmap.c (renamed from sys/gnu/fs/ext2fs/ext2_bmap.c) | 13 | ||||
-rwxr-xr-x | sys/fs/ext2fs/ext2_dinode.h | 78 | ||||
-rwxr-xr-x | sys/fs/ext2fs/ext2_dir.h | 81 | ||||
-rw-r--r-- | sys/fs/ext2fs/ext2_extern.h (renamed from sys/gnu/fs/ext2fs/ext2_extern.h) | 27 | ||||
-rw-r--r-- | sys/fs/ext2fs/ext2_inode.c (renamed from sys/gnu/fs/ext2fs/ext2_inode.c) | 105 | ||||
-rw-r--r-- | sys/fs/ext2fs/ext2_inode_cnv.c (renamed from sys/gnu/fs/ext2fs/ext2_inode_cnv.c) | 81 | ||||
-rw-r--r-- | sys/fs/ext2fs/ext2_lookup.c (renamed from sys/gnu/fs/ext2fs/ext2_lookup.c) | 287 | ||||
-rw-r--r-- | sys/fs/ext2fs/ext2_mount.h (renamed from sys/gnu/fs/ext2fs/ext2_mount.h) | 14 | ||||
-rw-r--r-- | sys/fs/ext2fs/ext2_readwrite.c (renamed from sys/gnu/fs/ext2fs/ext2_readwrite.c) | 93 | ||||
-rw-r--r-- | sys/fs/ext2fs/ext2_subr.c (renamed from sys/gnu/fs/ext2fs/ext2_subr.c) | 10 | ||||
-rw-r--r-- | sys/fs/ext2fs/ext2_vfsops.c (renamed from sys/gnu/fs/ext2fs/ext2_vfsops.c) | 457 | ||||
-rw-r--r-- | sys/fs/ext2fs/ext2_vnops.c (renamed from sys/gnu/fs/ext2fs/ext2_vnops.c) | 75 | ||||
-rwxr-xr-x | sys/fs/ext2fs/ext2fs.h | 329 | ||||
-rw-r--r-- | sys/fs/ext2fs/fs.h (renamed from sys/gnu/fs/ext2fs/fs.h) | 82 | ||||
-rw-r--r-- | sys/fs/ext2fs/inode.h (renamed from sys/gnu/fs/ext2fs/inode.h) | 14 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/COPYRIGHT.INFO | 35 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_alloc.c | 535 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_bitops.h | 114 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_fs.h | 556 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_fs_sb.h | 100 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_linux_balloc.c | 624 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_linux_ialloc.c | 526 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/i386-bitops.h | 175 | ||||
-rw-r--r-- | sys/gnu/fs/reiserfs/reiserfs_fs.h | 19 | ||||
-rw-r--r-- | sys/modules/ext2fs/Makefile | 6 |
28 files changed, 2155 insertions, 3393 deletions
diff --git a/sys/conf/files b/sys/conf/files index 71a8e537d850..7be16769a91f 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1956,18 +1956,15 @@ geom/virstor/binstream.c optional geom_virstor geom/virstor/g_virstor.c optional geom_virstor geom/virstor/g_virstor_md.c optional geom_virstor geom/zero/g_zero.c optional geom_zero -gnu/fs/ext2fs/ext2_alloc.c optional ext2fs \ - warning "kernel contains GPL contaminated ext2fs filesystem" -gnu/fs/ext2fs/ext2_balloc.c optional ext2fs -gnu/fs/ext2fs/ext2_bmap.c optional ext2fs -gnu/fs/ext2fs/ext2_inode.c optional ext2fs -gnu/fs/ext2fs/ext2_inode_cnv.c optional ext2fs -gnu/fs/ext2fs/ext2_linux_balloc.c optional ext2fs -gnu/fs/ext2fs/ext2_linux_ialloc.c optional ext2fs -gnu/fs/ext2fs/ext2_lookup.c optional ext2fs -gnu/fs/ext2fs/ext2_subr.c optional ext2fs -gnu/fs/ext2fs/ext2_vfsops.c optional ext2fs -gnu/fs/ext2fs/ext2_vnops.c optional ext2fs +fs/ext2fs/ext2_alloc.c optional ext2fs +fs/ext2fs/ext2_balloc.c optional ext2fs +fs/ext2fs/ext2_bmap.c optional ext2fs +fs/ext2fs/ext2_inode.c optional ext2fs +fs/ext2fs/ext2_inode_cnv.c optional ext2fs +fs/ext2fs/ext2_lookup.c optional ext2fs +fs/ext2fs/ext2_subr.c optional ext2fs +fs/ext2fs/ext2_vfsops.c optional ext2fs +fs/ext2fs/ext2_vnops.c optional ext2fs gnu/fs/reiserfs/reiserfs_hashes.c optional reiserfs \ warning "kernel contains GPL contaminated ReiserFS filesystem" gnu/fs/reiserfs/reiserfs_inode.c optional reiserfs diff --git a/sys/fs/ext2fs/ext2_alloc.c b/sys/fs/ext2fs/ext2_alloc.c new file mode 100644 index 000000000000..1095100aa9b6 --- /dev/null +++ b/sys/fs/ext2fs/ext2_alloc.c @@ -0,0 +1,973 @@ +/*- + * 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 <sys/buf.h> + +#include <fs/ext2fs/inode.h> +#include <fs/ext2fs/ext2_mount.h> +#include <fs/ext2fs/ext2fs.h> +#include <fs/ext2fs/fs.h> +#include <fs/ext2fs/ext2_extern.h> + +static daddr_t ext2_alloccg(struct inode *, int, daddr_t, int); +static u_long ext2_dirpref(struct inode *); +static void ext2_fserr(struct m_ext2fs *, uid_t, char *); +static u_long ext2_hashalloc(struct inode *, int, long, int, + daddr_t (*)(struct inode *, int, daddr_t, + int)); +static daddr_t ext2_nodealloccg(struct inode *, int, daddr_t, int); +static daddr_t ext2_mapsearch(struct m_ext2fs *, char *, daddr_t); +/* + * Allocate a block in the file system. + * + * A preference may be optionally specified. If a preference is given + * the following hierarchy is used to allocate a block: + * 1) allocate the requested block. + * 2) allocate a rotationally optimal block in the same cylinder. + * 3) allocate a block in the same cylinder group. + * 4) quadradically rehash into other cylinder groups, until an + * available block is located. + * If no block preference is given the following hierarchy is used + * to allocate a block: + * 1) allocate a block in the cylinder group that contains the + * inode for the file. + * 2) quadradically rehash into other cylinder groups, until an + * available block is located. + * + * A preference may be optionally specified. If a preference is given + * the following hierarchy is used to allocate a block: + * 1) allocate the requested block. + * 2) allocate a rotationally optimal block in the same cylinder. + * 3) allocate a block in the same cylinder group. + * 4) quadradically rehash into other cylinder groups, until an + * available block is located. + * If no block preference is given the following hierarchy is used + * to allocate a block: + * 1) allocate a block in the cylinder group that contains the + * inode for the file. + * 2) quadradically rehash into other cylinder groups, until an + * available block is located. + */ + +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 m_ext2fs *fs; + struct ext2mount *ump; + int32_t bno; + int cg; + *bnp = 0; + fs = ip->i_e2fs; + ump = ip->i_ump; + mtx_assert(EXT2_MTX(ump), MA_OWNED); +#ifdef DIAGNOSTIC + if ((u_int)size > fs->e2fs_bsize || blkoff(fs, size) != 0) { + vn_printf(ip->i_devvp, "bsize = %lu, size = %d, fs = %s\n", + (long unsigned int)fs->e2fs_bsize, size, fs->e2fs_fsmnt); + panic("ext2_alloc: bad size"); + } + if (cred == NOCRED) + panic("ext2_alloc: missing credential"); +#endif /* DIAGNOSTIC */ + if (size == fs->e2fs_bsize && fs->e2fs->e2fs_fbcount == 0) + goto nospace; + if (cred->cr_uid != 0 && + fs->e2fs->e2fs_fbcount < fs->e2fs->e2fs_rbcount) + goto nospace; + if (bpref >= fs->e2fs->e2fs_bcount) + bpref = 0; + if (bpref == 0) + cg = ino_to_cg(fs, ip->i_number); + else + cg = dtog(fs, bpref); + bno = (daddr_t)ext2_hashalloc(ip, cg, bpref, fs->e2fs_bsize, + ext2_alloccg); + if (bno > 0) { + ip->i_blocks += btodb(fs->e2fs_bsize); + ip->i_flag |= IN_CHANGE | IN_UPDATE; + *bnp = bno; + return (0); + } +nospace: + EXT2_UNLOCK(ump); + ext2_fserr(fs, cred->cr_uid, "file system full"); + uprintf("\n%s: write failed, file system is full\n", fs->e2fs_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; +static int doreallocblks = 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 m_ext2fs *fs; + struct inode *ip; + struct vnode *vp; + struct buf *sbp, *ebp; + int32_t *bap, *sbap, *ebap = 0; + struct ext2mount *ump; + struct cluster_save *buflist; + struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp; + int32_t start_lbn, end_lbn, soff, newblk, blkno =0; + int i, len, start_lvl, end_lvl, pref, ssize; + + vp = ap->a_vp; + ip = VTOI(vp); + fs = ip->i_e2fs; + ump = ip->i_ump; +#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; +#ifdef 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 (ext2_getlbns(vp, start_lbn, start_ap, &start_lvl) || + ext2_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->e2fs_bsize, NOCRED, &sbp)) { + brelse(sbp); + return (ENOSPC); + } + sbap = (int32_t *)sbp->b_data; + soff = idp->in_off; + } + /* + * Find the preferred location for the cluster. + */ + EXT2_LOCK(ump); + pref = ext2_blkpref(ip, start_lbn, soff, sbap, blkno); + /* + * 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 { +#ifdef 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->e2fs_bsize, NOCRED, &ebp)){ + EXT2_UNLOCK(ump); + 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), pref, + len, ext2_clusteralloc)) == 0){ + EXT2_UNLOCK(ump); + 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->e2fs_fpb) { + if (i == ssize) + bap = ebap; + soff = -i; +#ifdef 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->e2fs_fpb) { + ext2_blkfree(ip, dbtofsb(fs, buflist->bs_children[i]->b_blkno), + fs->e2fs_bsize); + 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. + * + */ +int +ext2_valloc(pvp, mode, cred, vpp) + struct vnode *pvp; + int mode; + struct ucred *cred; + struct vnode **vpp; +{ + struct inode *pip; + struct m_ext2fs *fs; + struct inode *ip; + struct ext2mount *ump; + ino_t ino, ipref; + int i, error, cg; + + *vpp = NULL; + pip = VTOI(pvp); + fs = pip->i_e2fs; + ump = pip->i_ump; + + EXT2_LOCK(ump); + if (fs->e2fs->e2fs_ficount == 0) + goto noinodes; + /* + * If it is a directory then obtain a cylinder group based on + * ext2_dirpref else obtain it using ino_to_cg. The preferred inode is + * always the next inode. + */ + if((mode & IFMT) == IFDIR) { + cg = ext2_dirpref(pip); + if (fs->e2fs_contigdirs[cg] < 255) + fs->e2fs_contigdirs[cg]++; + } else { + cg = ino_to_cg(fs, pip->i_number); + if (fs->e2fs_contigdirs[cg] > 0) + fs->e2fs_contigdirs[cg]--; + } + ipref = cg * fs->e2fs->e2fs_ipg + 1; + ino = (ino_t)ext2_hashalloc(pip, cg, (long)ipref, mode, ext2_nodealloccg); + + 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_UNLOCK(ump); + ext2_fserr(fs, cred->cr_uid, "out of inodes"); + uprintf("\n%s: create/symlink failed, no inodes free\n", fs->e2fs_fsmnt); + return (ENOSPC); +} + +/* + * Find a cylinder to place a directory. + * + * The policy implemented by this algorithm is to allocate a + * directory inode in the same cylinder group as its parent + * directory, but also to reserve space for its files inodes + * and data. Restrict the number of directories which may be + * allocated one after another in the same cylinder group + * without intervening allocation of files. + * + * If we allocate a first level directory then force allocation + * in another cylinder group. + * + */ +static u_long +ext2_dirpref(struct inode *pip) +{ + struct m_ext2fs *fs; + int cg, prefcg, dirsize, cgsize; + int avgifree, avgbfree, avgndir, curdirsize; + int minifree, minbfree, maxndir; + int mincg, minndir; + int maxcontigdirs; + + mtx_assert(EXT2_MTX(pip->i_ump), MA_OWNED); + fs = pip->i_e2fs; + + avgifree = fs->e2fs->e2fs_ficount / fs->e2fs_gcount; + avgbfree = fs->e2fs->e2fs_fbcount / fs->e2fs_gcount; + avgndir = fs->e2fs_total_dir / fs->e2fs_gcount; + + /* + * Force allocation in another cg if creating a first level dir. + */ + ASSERT_VOP_LOCKED(ITOV(pip), "ext2fs_dirpref"); + if (ITOV(pip)->v_vflag & VV_ROOT) { + prefcg = arc4random() % fs->e2fs_gcount; + mincg = prefcg; + minndir = fs->e2fs_ipg; + for (cg = prefcg; cg < fs->e2fs_gcount; cg++) + if (fs->e2fs_gd[cg].ext2bgd_ndirs < minndir && + fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree && + fs->e2fs_gd[cg].ext2bgd_nbfree >= avgbfree) { + mincg = cg; + minndir = fs->e2fs_gd[cg].ext2bgd_ndirs; + } + for (cg = 0; cg < prefcg; cg++) + if (fs->e2fs_gd[cg].ext2bgd_ndirs < minndir && + fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree && + fs->e2fs_gd[cg].ext2bgd_nbfree >= avgbfree) { + mincg = cg; + minndir = fs->e2fs_gd[cg].ext2bgd_ndirs; + } + + return (mincg); + } + + /* + * Count various limits which used for + * optimal allocation of a directory inode. + */ + maxndir = min(avgndir + fs->e2fs_ipg / 16, fs->e2fs_ipg); + minifree = avgifree - avgifree / 4; + if (minifree < 1) + minifree = 1; + minbfree = avgbfree - avgbfree / 4; + if (minbfree < 1) + minbfree = 1; + cgsize = fs->e2fs_fsize * fs->e2fs_fpg; + dirsize = AVGDIRSIZE; + curdirsize = avgndir ? (cgsize - avgbfree * fs->e2fs_bsize) / avgndir : 0; + if (dirsize < curdirsize) + dirsize = curdirsize; + if (dirsize <= 0) + maxcontigdirs = 0; /* dirsize overflowed */ + else + maxcontigdirs = min((avgbfree * fs->e2fs_bsize) / dirsize, 255); + maxcontigdirs = min(maxcontigdirs, fs->e2fs_ipg / AFPDIR); + if (maxcontigdirs == 0) + maxcontigdirs = 1; + + /* + * Limit number of dirs in one cg and reserve space for + * regular files, but only if we have no deficit in + * inodes or space. + */ + prefcg = ino_to_cg(fs, pip->i_number); + for (cg = prefcg; cg < fs->e2fs_gcount; cg++) + if (fs->e2fs_gd[cg].ext2bgd_ndirs < maxndir && + fs->e2fs_gd[cg].ext2bgd_nifree >= minifree && + fs->e2fs_gd[cg].ext2bgd_nbfree >= minbfree) { + if (fs->e2fs_contigdirs[cg] < maxcontigdirs) + return (cg); + } + for (cg = 0; cg < prefcg; cg++) + if (fs->e2fs_gd[cg].ext2bgd_ndirs < maxndir && + fs->e2fs_gd[cg].ext2bgd_nifree >= minifree && + fs->e2fs_gd[cg].ext2bgd_nbfree >= minbfree) { + if (fs->e2fs_contigdirs[cg] < maxcontigdirs) + return (cg); + } + /* + * This is a backstop when we have deficit in space. + */ + for (cg = prefcg; cg < fs->e2fs_gcount; cg++) + if (fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree) + return (cg); + for (cg = 0; cg < prefcg; cg++) + if (fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree) + break; + return (cg); +} + +/* + * 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; + mtx_assert(EXT2_MTX(ip->i_ump), MA_OWNED); + + /* 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 && ip->i_next_alloc_goal != 0) + 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->e2fs->e2fs_first_dblock; +} + +/* + * Implement the cylinder overflow algorithm. + * + * The policy implemented by this algorithm is: + * 1) allocate the block in its requested cylinder group. + * 2) quadradically rehash on the cylinder group number. + * 3) brute force search for a free block. + */ +static u_long +ext2_hashalloc(struct inode *ip, int cg, long pref, int size, + daddr_t (*allocator)(struct inode *, int, daddr_t, int)) +{ + struct m_ext2fs *fs; + ino_t result; + int i, icg = cg; + + mtx_assert(EXT2_MTX(ip->i_ump), MA_OWNED); + fs = ip->i_e2fs; + /* + * 1: preferred cylinder group + */ + result = (*allocator)(ip, cg, pref, size); + if (result) + return (result); + /* + * 2: quadratic rehash + */ + for (i = 1; i < fs->e2fs_gcount; i *= 2) { + cg += i; + if (cg >= fs->e2fs_gcount) + cg -= fs->e2fs_gcount; + result = (*allocator)(ip, cg, 0, size); + if (result) + return (result); + } + /* + * 3: brute force search + * Note that we start at i == 2, since 0 was checked initially, + * and 1 is always checked in the quadratic rehash. + */ + cg = (icg + 2) % fs->e2fs_gcount; + for (i = 2; i < fs->e2fs_gcount; i++) { + result = (*allocator)(ip, cg, 0, size); + if (result) + return (result); + cg++; + if (cg == fs->e2fs_gcount) + cg = 0; + } + return (0); +} + +/* + * Determine whether a block can be allocated. + * + * Check to see if a block of the appropriate size is available, + * and if it is, allocate it. + */ +static daddr_t +ext2_alloccg(struct inode *ip, int cg, daddr_t bpref, int size) +{ + struct m_ext2fs *fs; + struct buf *bp; + struct ext2mount *ump; + int error, bno, start, end, loc; + char *bbp; + /* XXX ondisk32 */ + fs = ip->i_e2fs; + ump = ip->i_ump; + if (fs->e2fs_gd[cg].ext2bgd_nbfree == 0) + return (0); + EXT2_UNLOCK(ump); + error = bread(ip->i_devvp, fsbtodb(fs, + fs->e2fs_gd[cg].ext2bgd_b_bitmap), + (int)fs->e2fs_bsize, NOCRED, &bp); + if (error) { + brelse(bp); + EXT2_LOCK(ump); + return (0); + } + bbp = (char *)bp->b_data; + + if (dtog(fs, bpref) != cg) + bpref = 0; + if (bpref != 0) { + bpref = dtogd(fs, bpref); + /* + * if the requested block is available, use it + */ + if (isclr(bbp, bpref)) { + bno = bpref; + goto gotit; + } + } + /* + * no blocks in the requested cylinder, so take next + * available one in this cylinder group. + * first try to get 8 contigous blocks, then fall back to a single + * block. + */ + if (bpref) + start = dtogd(fs, bpref) / NBBY; + else + start = 0; + end = howmany(fs->e2fs->e2fs_fpg, NBBY) - start; + for (loc = start; loc < end; loc++) { + if (bbp[loc] == 0) { + bno = loc * NBBY; + goto gotit; + } + } + for (loc = 0; loc < start; loc++) { + if (bbp[loc] == 0) { + bno = loc * NBBY; + goto gotit; + } + } + + bno = ext2_mapsearch(fs, bbp, bpref); + if (bno < 0){ + brelse(bp); + EXT2_LOCK(ump); + return (0); + } +gotit: +#ifdef DIAGNOSTIC + if (isset(bbp, (daddr_t)bno)) { + printf("ext2fs_alloccgblk: cg=%d bno=%d fs=%s\n", + cg, bno, fs->e2fs_fsmnt); + panic("ext2fs_alloccg: dup alloc"); + } +#endif + setbit(bbp, (daddr_t)bno); + EXT2_LOCK(ump); + fs->e2fs->e2fs_fbcount--; + fs->e2fs_gd[cg].ext2bgd_nbfree--; + fs->e2fs_fmod = 1; + EXT2_UNLOCK(ump); + bdwrite(bp); + return (cg * fs->e2fs->e2fs_fpg + fs->e2fs->e2fs_first_dblock + bno); +} + +/* + * Determine whether an inode can be allocated. + * + * Check to see if an inode is available, and if it is, + * allocate it using tode in the specified cylinder group. + */ +static daddr_t +ext2_nodealloccg(struct inode *ip, int cg, daddr_t ipref, int mode) +{ + struct m_ext2fs *fs; + struct buf *bp; + struct ext2mount *ump; + int error, start, len, loc, map, i; + char *ibp; + ipref--; /* to avoid a lot of (ipref -1) */ + if (ipref == -1) + ipref = 0; + fs = ip->i_e2fs; + ump = ip->i_ump; + if (fs->e2fs_gd[cg].ext2bgd_nifree == 0) + return (0); + EXT2_UNLOCK(ump); + error = bread(ip->i_devvp, fsbtodb(fs, + fs->e2fs_gd[cg].ext2bgd_i_bitmap), + (int)fs->e2fs_bsize, NOCRED, &bp); + if (error) { + brelse(bp); + EXT2_LOCK(ump); + return (0); + } + ibp = (char *)bp->b_data; + if (ipref) { + ipref %= fs->e2fs->e2fs_ipg; + if (isclr(ibp, ipref)) + goto gotit; + } + start = ipref / NBBY; + len = howmany(fs->e2fs->e2fs_ipg - ipref, NBBY); + loc = skpc(0xff, len, &ibp[start]); + if (loc == 0) { + len = start + 1; + start = 0; + loc = skpc(0xff, len, &ibp[0]); + if (loc == 0) { + printf("cg = %d, ipref = %lld, fs = %s\n", + cg, (long long)ipref, fs->e2fs_fsmnt); + panic("ext2fs_nodealloccg: map corrupted"); + /* NOTREACHED */ + } + } + i = start + len - loc; + map = ibp[i]; + ipref = i * NBBY; + for (i = 1; i < (1 << NBBY); i <<= 1, ipref++) { + if ((map & i) == 0) { + goto gotit; + } + } + printf("fs = %s\n", fs->e2fs_fsmnt); + panic("ext2fs_nodealloccg: block not in map"); + /* NOTREACHED */ +gotit: + setbit(ibp, ipref); + EXT2_LOCK(ump); + fs->e2fs_gd[cg].ext2bgd_nifree--; + fs->e2fs->e2fs_ficount--; + fs->e2fs_fmod = 1; + if ((mode & IFMT) == IFDIR) { + fs->e2fs_gd[cg].ext2bgd_ndirs++; + fs->e2fs_total_dir++; + } + EXT2_UNLOCK(ump); + bdwrite(bp); + return (cg * fs->e2fs->e2fs_ipg + ipref +1); +} + +/* + * Free a block or fragment. + * + */ +void +ext2_blkfree(ip, bno, size) + struct inode *ip; + int32_t bno; + long size; +{ + struct m_ext2fs *fs; + struct buf *bp; + struct ext2mount *ump; + int cg, error; + char *bbp; + + fs = ip->i_e2fs; + ump = ip->i_ump; + cg = dtog(fs, bno); + if ((u_int)bno >= fs->e2fs->e2fs_bcount) { + printf("bad block %lld, ino %llu\n", (long long)bno, + (unsigned long long)ip->i_number); + ext2_fserr(fs, ip->i_uid, "bad block"); + return; + } + error = bread(ip->i_devvp, + fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap), + (int)fs->e2fs_bsize, NOCRED, &bp); + if (error) { + brelse(bp); + return; + } + bbp = (char *)bp->b_data; + bno = dtogd(fs, bno); + if (isclr(bbp, bno)) { + printf("block = %lld, fs = %s\n", + (long long)bno, fs->e2fs_fsmnt); + panic("blkfree: freeing free block"); + } + clrbit(bbp, bno); + EXT2_LOCK(ump); + fs->e2fs->e2fs_fbcount++; + fs->e2fs_gd[cg].ext2bgd_nbfree++; + fs->e2fs_fmod = 1; + EXT2_UNLOCK(ump); + bdwrite(bp); +} + +/* + * Free an inode. + * + */ +int +ext2_vfree(pvp, ino, mode) + struct vnode *pvp; + ino_t ino; + int mode; +{ + struct m_ext2fs *fs; + struct inode *pip; + struct buf *bp; + struct ext2mount *ump; + int error, cg; + char * ibp; +/* mode_t save_i_mode; */ + + pip = VTOI(pvp); + fs = pip->i_e2fs; + ump = pip->i_ump; + if ((u_int)ino > fs->e2fs_ipg * fs->e2fs_gcount) + panic("ext2_vfree: range: devvp = %p, ino = %d, fs = %s", + pip->i_devvp, ino, fs->e2fs_fsmnt); + + cg = ino_to_cg(fs, ino); + error = bread(pip->i_devvp, + fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_i_bitmap), + (int)fs->e2fs_bsize, NOCRED, &bp); + if (error) { + brelse(bp); + return (0); + } + ibp = (char *)bp->b_data; + ino = (ino - 1) % fs->e2fs->e2fs_ipg; + if (isclr(ibp, ino)) { + printf("ino = %llu, fs = %s\n", + (unsigned long long)ino, fs->e2fs_fsmnt); + if (fs->e2fs_ronly == 0) + panic("ifree: freeing free inode"); + } + clrbit(ibp, ino); + EXT2_LOCK(ump); + fs->e2fs->e2fs_ficount++; + fs->e2fs_gd[cg].ext2bgd_nifree++; + if ((mode & IFMT) == IFDIR) { + fs->e2fs_gd[cg].ext2bgd_ndirs--; + fs->e2fs_total_dir--; + } + fs->e2fs_fmod = 1; + EXT2_UNLOCK(ump); + bdwrite(bp); + return (0); +} + +/* + * Find a block in the specified cylinder group. + * + * It is a panic if a request is made to find a block if none are + * available. + */ +static daddr_t +ext2_mapsearch(struct m_ext2fs *fs, char *bbp, daddr_t bpref) +{ + daddr_t bno; + int start, len, loc, i, map; + + /* + * find the fragment by searching through the free block + * map for an appropriate bit pattern + */ + if (bpref) + start = dtogd(fs, bpref) / NBBY; + else + start = 0; + len = howmany(fs->e2fs->e2fs_fpg, NBBY) - start; + loc = skpc(0xff, len, &bbp[start]); + if (loc == 0) { + len = start + 1; + start = 0; + loc = skpc(0xff, len, &bbp[start]); + if (loc == 0) { + printf("start = %d, len = %d, fs = %s\n", + start, len, fs->e2fs_fsmnt); + panic("ext2fs_alloccg: map corrupted"); + /* NOTREACHED */ + } + } + i = start + len - loc; + map = bbp[i]; + bno = i * NBBY; + for (i = 1; i < (1 << NBBY); i <<= 1, bno++) { + if ((map & i) == 0) + return (bno); + } + printf("fs = %s\n", fs->e2fs_fsmnt); + panic("ext2fs_mapsearch: block not in map"); + /* NOTREACHED */ +} + +/* + * 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 m_ext2fs *fs; + uid_t uid; + char *cp; +{ + + log(LOG_ERR, "uid %u on %s: %s\n", uid, fs->e2fs_fsmnt, cp); +} + +int +cg_has_sb(int i) +{ + int a3, a5, a7; + + if (i == 0 || i == 1) + return 1; + for (a3 = 3, a5 = 5, a7 = 7; + a3 <= i || a5 <= i || a7 <= i; + a3 *= 3, a5 *= 5, a7 *= 7) + if (i == a3 || i == a5 || i == a7) + return 1; + return 0; +} diff --git a/sys/gnu/fs/ext2fs/ext2_balloc.c b/sys/fs/ext2fs/ext2_balloc.c index e46414c5bf99..124ac32ddf1c 100644 --- a/sys/gnu/fs/ext2fs/ext2_balloc.c +++ b/sys/fs/ext2fs/ext2_balloc.c @@ -44,42 +44,39 @@ #include <sys/ucred.h> #include <sys/vnode.h> -#include <gnu/fs/ext2fs/inode.h> -#include <gnu/fs/ext2fs/ext2_fs.h> -#include <gnu/fs/ext2fs/ext2_fs_sb.h> -#include <gnu/fs/ext2fs/fs.h> -#include <gnu/fs/ext2fs/ext2_extern.h> - +#include <fs/ext2fs/inode.h> +#include <fs/ext2fs/ext2fs.h> +#include <fs/ext2fs/fs.h> +#include <fs/ext2fs/ext2_extern.h> +#include <fs/ext2fs/ext2_mount.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) +ext2_balloc(ip, lbn, size, cred, bpp, flags) struct inode *ip; - int32_t bn; + int32_t lbn; int size; struct ucred *cred; struct buf **bpp; int flags; { - struct ext2_sb_info *fs; + struct m_ext2fs *fs; + struct ext2mount *ump; int32_t nb; struct buf *bp, *nbp; struct vnode *vp = ITOV(ip); struct indir indirs[NIADDR + 2]; - int32_t newb, lbn, *bap, pref; + int32_t newb, *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) + if (lbn < 0) return (EFBIG); fs = ip->i_e2fs; - lbn = bn; + ump = ip->i_ump; /* * check if this is a sequential block allocation. @@ -94,12 +91,12 @@ ext2_debug("ext2_balloc called (%d, %d, %d)\n", /* * The first NDADDR blocks are direct blocks */ - if (bn < NDADDR) { - nb = ip->i_db[bn]; + if (lbn < NDADDR) { + nb = ip->i_db[lbn]; /* 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 (nb != 0 && ip->i_size >= (lbn + 1) * fs->e2fs_bsize) { + error = bread(vp, lbn, fs->e2fs_bsize, NOCRED, &bp); if (error) { brelse(bp); return (error); @@ -115,7 +112,7 @@ ext2_debug("ext2_balloc called (%d, %d, %d)\n", osize = fragroundup(fs, blkoff(fs, ip->i_size)); nsize = fragroundup(fs, size); if (nsize <= osize) { - error = bread(vp, bn, osize, NOCRED, &bp); + error = bread(vp, lbn, osize, NOCRED, &bp); if (error) { brelse(bp); return (error); @@ -134,21 +131,22 @@ ext2_debug("ext2_balloc called (%d, %d, %d)\n", */ } } else { - if (ip->i_size < (bn + 1) * fs->s_blocksize) + if (ip->i_size < (lbn + 1) * fs->e2fs_bsize) 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 = fs->e2fs_bsize; + EXT2_LOCK(ump); + error = ext2_alloc(ip, lbn, + ext2_blkpref(ip, lbn, (int)lbn, &ip->i_db[0], 0), nsize, cred, &newb); if (error) return (error); - bp = getblk(vp, bn, nsize, 0, 0, 0); + bp = getblk(vp, lbn, 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_db[lbn] = dbtofsb(fs, bp->b_blkno); ip->i_flag |= IN_CHANGE | IN_UPDATE; *bpp = bp; return (0); @@ -157,7 +155,7 @@ ext2_debug("ext2_balloc called (%d, %d, %d)\n", * Determine the number of levels of indirection. */ pref = 0; - if ((error = ext2_getlbns(vp, bn, indirs, &num)) != 0) + if ((error = ext2_getlbns(vp, lbn, indirs, &num)) != 0) return(error); #ifdef DIAGNOSTIC if (num < 1) @@ -169,28 +167,14 @@ ext2_debug("ext2_balloc called (%d, %d, %d)\n", --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] - */ - + EXT2_LOCK(ump); 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) + if ((error = ext2_alloc(ip, lbn, pref, + (int)fs->e2fs_bsize, cred, &newb))) return (error); nb = newb; - bp = getblk(vp, indirs[1].in_lbn, fs->s_blocksize, 0, 0, 0); + bp = getblk(vp, indirs[1].in_lbn, fs->e2fs_bsize, 0, 0, 0); bp->b_blkno = fsbtodb(fs, newb); vfs_bio_clrbuf(bp); /* @@ -198,7 +182,7 @@ ext2_debug("ext2_balloc called (%d, %d, %d)\n", * never point at garbage. */ if ((error = bwrite(bp)) != 0) { - ext2_blkfree(ip, nb, fs->s_blocksize); + ext2_blkfree(ip, nb, fs->e2fs_bsize); return (error); } ip->i_ib[indirs[0].in_off] = newb; @@ -209,7 +193,7 @@ ext2_debug("ext2_balloc called (%d, %d, %d)\n", */ for (i = 1;;) { error = bread(vp, - indirs[i].in_lbn, (int)fs->s_blocksize, NOCRED, &bp); + indirs[i].in_lbn, (int)fs->e2fs_bsize, NOCRED, &bp); if (error) { brelse(bp); return (error); @@ -220,29 +204,20 @@ ext2_debug("ext2_balloc called (%d, %d, %d)\n", break; i += 1; if (nb != 0) { - brelse(bp); + bqrelse(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 ? - */ + EXT2_LOCK(ump); + if (pref == 0) 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) { + error = ext2_alloc(ip, lbn, pref, (int)fs->e2fs_bsize, cred, &newb); + if (error) { brelse(bp); return (error); } nb = newb; - nbp = getblk(vp, indirs[i].in_lbn, fs->s_blocksize, 0, 0, 0); + nbp = getblk(vp, indirs[i].in_lbn, fs->e2fs_bsize, 0, 0, 0); nbp->b_blkno = fsbtodb(fs, nb); vfs_bio_clrbuf(nbp); /* @@ -250,7 +225,8 @@ ext2_debug("ext2_balloc called (%d, %d, %d)\n", * never point at garbage. */ if ((error = bwrite(nbp)) != 0) { - ext2_blkfree(ip, nb, fs->s_blocksize); + ext2_blkfree(ip, nb, fs->e2fs_bsize); + EXT2_UNLOCK(ump); brelse(bp); return (error); } @@ -262,6 +238,8 @@ ext2_debug("ext2_balloc called (%d, %d, %d)\n", if (flags & B_SYNC) { bwrite(bp); } else { + if (bp->b_bufsize == fs->e2fs_bsize) + bp->b_flags |= B_CLUSTEROK; bdwrite(bp); } } @@ -269,15 +247,16 @@ ext2_debug("ext2_balloc called (%d, %d, %d)\n", * Get the data block, allocating if necessary. */ if (nb == 0) { + EXT2_LOCK(ump); 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) { + lbn, pref, (int)fs->e2fs_bsize, cred, &newb)) != 0) { brelse(bp); return (error); } nb = newb; - nbp = getblk(vp, lbn, fs->s_blocksize, 0, 0, 0); + nbp = getblk(vp, lbn, fs->e2fs_bsize, 0, 0, 0); nbp->b_blkno = fsbtodb(fs, nb); if (flags & B_CLRBUF) vfs_bio_clrbuf(nbp); @@ -289,6 +268,8 @@ ext2_debug("ext2_balloc called (%d, %d, %d)\n", if (flags & B_SYNC) { bwrite(bp); } else { + if (bp->b_bufsize == fs->e2fs_bsize) + bp->b_flags |= B_CLUSTEROK; bdwrite(bp); } *bpp = nbp; @@ -296,15 +277,16 @@ ext2_debug("ext2_balloc called (%d, %d, %d)\n", } brelse(bp); if (flags & B_CLRBUF) { - error = bread(vp, lbn, (int)fs->s_blocksize, NOCRED, &nbp); + error = bread(vp, lbn, (int)fs->e2fs_bsize, NOCRED, &nbp); if (error) { brelse(nbp); return (error); } } else { - nbp = getblk(vp, lbn, fs->s_blocksize, 0, 0, 0); + nbp = getblk(vp, lbn, fs->e2fs_bsize, 0, 0, 0); nbp->b_blkno = fsbtodb(fs, nb); } *bpp = nbp; return (0); } + diff --git a/sys/gnu/fs/ext2fs/ext2_bmap.c b/sys/fs/ext2fs/ext2_bmap.c index 85cfbf948bf6..c742188d479b 100644 --- a/sys/gnu/fs/ext2fs/ext2_bmap.c +++ b/sys/fs/ext2fs/ext2_bmap.c @@ -45,14 +45,13 @@ #include <sys/resourcevar.h> #include <sys/stat.h> -#include <gnu/fs/ext2fs/inode.h> -#include <gnu/fs/ext2fs/ext2_fs.h> -#include <gnu/fs/ext2fs/ext2_fs_sb.h> -#include <gnu/fs/ext2fs/ext2_mount.h> -#include <gnu/fs/ext2fs/ext2_extern.h> +#include <fs/ext2fs/inode.h> +#include <fs/ext2fs/ext2fs.h> +#include <fs/ext2fs/ext2_mount.h> +#include <fs/ext2fs/ext2_extern.h> /* - * Bmap converts a the logical block number of a file to its physical block + * Bmap converts 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. */ @@ -93,7 +92,7 @@ ext2_bmap(ap) * 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 + * ext2_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). diff --git a/sys/fs/ext2fs/ext2_dinode.h b/sys/fs/ext2fs/ext2_dinode.h new file mode 100755 index 000000000000..3e45060e566f --- /dev/null +++ b/sys/fs/ext2fs/ext2_dinode.h @@ -0,0 +1,78 @@ +/*- + * Copyright (c) 2009 Aditya Sarawgi + * 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 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef _FS_EXT2FS_EXT2_DINODE_H_ +#define _FS_EXT2FS_EXT2_DINODE_H_ + +#define e2di_size_high e2di_dacl + +/* + * Inode flags + * The current implementation uses only EXT2_IMMUTABLE and EXT2_APPEND flags + */ +#define EXT2_SECRM 0x00000001 /* Secure deletion */ +#define EXT2_UNRM 0x00000002 /* Undelete */ +#define EXT2_COMPR 0x00000004 /* Compress file */ +#define EXT2_SYNC 0x00000008 /* Synchronous updates */ +#define EXT2_IMMUTABLE 0x00000010 /* Immutable file */ +#define EXT2_APPEND 0x00000020 /* writes to file may only append */ +#define EXT2_NODUMP 0x00000040 /* do not dump file */ +#define EXT2_NOATIME 0x00000080 /* do not update atime */ + + +/* + * Structure of an inode on the disk + */ +struct ext2fs_dinode { + u_int16_t e2di_mode; /* 0: IFMT, permissions; see below. */ + u_int16_t e2di_uid; /* 2: Owner UID */ + u_int32_t e2di_size; /* 4: Size (in bytes) */ + u_int32_t e2di_atime; /* 8: Access time */ + u_int32_t e2di_ctime; /* 12: Create time */ + u_int32_t e2di_mtime; /* 16: Modification time */ + u_int32_t e2di_dtime; /* 20: Deletion time */ + u_int16_t e2di_gid; /* 24: Owner GID */ + u_int16_t e2di_nlink; /* 26: File link count */ + u_int32_t e2di_nblock; /* 28: Blocks count */ + u_int32_t e2di_flags; /* 32: Status flags (chflags) */ + u_int32_t e2di_linux_reserved1; /* 36 */ + u_int32_t e2di_blocks[EXT2_N_BLOCKS]; /* 40: disk blocks */ + u_int32_t e2di_gen; /* 100: generation number */ + u_int32_t e2di_facl; /* 104: file ACL (not implemented) */ + u_int32_t e2di_dacl; /* 108: dir ACL (not implemented) */ + u_int32_t e2di_faddr; /* 112: fragment address */ + u_int8_t e2di_nfrag; /* 116: fragment number */ + u_int8_t e2di_fsize; /* 117: fragment size */ + u_int16_t e2di_linux_reserved2; /* 118 */ + u_int16_t e2di_uid_high; /* 120: Owner UID top 16 bits */ + u_int16_t e2di_gid_high; /* 122: Owner GID top 16 bits */ + u_int32_t e2di_linux_reserved3; /* 124 */ +}; + +#endif /* _FS_EXT2FS_EXT2_DINODE_H_ */ + diff --git a/sys/fs/ext2fs/ext2_dir.h b/sys/fs/ext2fs/ext2_dir.h new file mode 100755 index 000000000000..06762682b1b9 --- /dev/null +++ b/sys/fs/ext2fs/ext2_dir.h @@ -0,0 +1,81 @@ +/*- + * Copyright (c) 2009 Aditya Sarawgi + * 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 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef _FS_EXT2FS_EXT2_DIR_H_ +#define _FS_EXT2FS_EXT2_DIR_H_ + +/* + * Structure of a directory entry + */ +#define EXT2FS_MAXNAMLEN 255 + +struct ext2fs_direct { + u_int32_t e2d_ino; /* inode number of entry */ + u_int16_t e2d_reclen; /* length of this record */ + u_int16_t e2d_namlen; /* length of string in d_name */ + char e2d_name[EXT2FS_MAXNAMLEN];/* name with length<=EXT2FS_MAXNAMLEN */ +}; +/* + * 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 ext2fs_direct_2 { + u_int32_t e2d_ino; /* inode number of entry */ + u_int16_t e2d_reclen; /* length of this record */ + u_int8_t e2d_namlen; /* length of string in d_name */ + u_int8_t e2d_type; /* file type */ + char e2d_name[EXT2FS_MAXNAMLEN];/* name with length<=EXT2FS_MAXNAMLEN */ +}; +/* + * 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 /* !_FS_EXT2FS_EXT2_DIR_H_ */ + diff --git a/sys/gnu/fs/ext2fs/ext2_extern.h b/sys/fs/ext2fs/ext2_extern.h index 24c8f4572948..60905cbca3ac 100644 --- a/sys/gnu/fs/ext2fs/ext2_extern.h +++ b/sys/fs/ext2fs/ext2_extern.h @@ -36,10 +36,10 @@ * $FreeBSD$ */ -#ifndef _SYS_GNU_EXT2FS_EXT2_EXTERN_H_ -#define _SYS_GNU_EXT2FS_EXT2_EXTERN_H_ +#ifndef _FS_EXT2FS_EXT2_EXTERN_H_ +#define _FS_EXT2FS_EXT2_EXTERN_H_ -struct ext2_inode; +struct ext2fs_dinode; struct indir; struct inode; struct mount; @@ -56,13 +56,13 @@ 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 *); +void ext2_ei2i(struct ext2fs_dinode *, struct inode *); int ext2_getlbns(struct vnode *, int32_t, struct indir *, int *); -void ext2_i2ei(struct inode *, struct ext2_inode *); +void ext2_i2ei(struct inode *, struct ext2fs_dinode *); 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); +void ext2_setblock(struct m_ext2fs *, 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 **); @@ -78,19 +78,8 @@ 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 cg_has_sb(int i); 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. */ @@ -101,4 +90,4 @@ void mark_buffer_dirty(struct buf *bh); extern struct vop_vector ext2_vnodeops; extern struct vop_vector ext2_fifoops; -#endif /* !_SYS_GNU_EXT2FS_EXT2_EXTERN_H_ */ +#endif /* !_FS_EXT2FS_EXT2_EXTERN_H_ */ diff --git a/sys/gnu/fs/ext2fs/ext2_inode.c b/sys/fs/ext2fs/ext2_inode.c index 0a62c3000443..2cf60a72407f 100644 --- a/sys/gnu/fs/ext2fs/ext2_inode.c +++ b/sys/fs/ext2fs/ext2_inode.c @@ -47,12 +47,11 @@ #include <vm/vm.h> #include <vm/vm_extern.h> -#include <gnu/fs/ext2fs/inode.h> -#include <gnu/fs/ext2fs/ext2_mount.h> -#include <gnu/fs/ext2fs/ext2_fs.h> -#include <gnu/fs/ext2fs/ext2_fs_sb.h> -#include <gnu/fs/ext2fs/fs.h> -#include <gnu/fs/ext2fs/ext2_extern.h> +#include <fs/ext2fs/inode.h> +#include <fs/ext2fs/ext2_mount.h> +#include <fs/ext2fs/ext2fs.h> +#include <fs/ext2fs/fs.h> +#include <fs/ext2fs/ext2_extern.h> static int ext2_indirtrunc(struct inode *, int32_t, int32_t, int32_t, int, long *); @@ -71,26 +70,27 @@ ext2_update(vp, waitfor) struct vnode *vp; int waitfor; { - struct ext2_sb_info *fs; + struct m_ext2fs *fs; struct buf *bp; struct inode *ip; int error; + ASSERT_VOP_ELOCKED(vp, "ext2_update"); 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) + if ((ip->i_flag & IN_MODIFIED) == 0 && waitfor == 0) return (0); + ip->i_flag &= ~(IN_LAZYACCESS | IN_LAZYMOD | IN_MODIFIED); fs = ip->i_e2fs; + if(fs->e2fs_ronly) + return (0); if ((error = bread(ip->i_devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)), - (int)fs->s_blocksize, NOCRED, &bp)) != 0) { + (int)fs->e2fs_bsize, NOCRED, &bp)) != 0) { brelse(bp); return (error); } - ext2_i2ei(ip, (struct ext2_inode *)((char *)bp->b_data + + ext2_i2ei(ip, (struct ext2fs_dinode *)((char *)bp->b_data + EXT2_INODE_SIZE(fs) * ino_to_fsbo(fs, ip->i_number))); if (waitfor && (vp->v_mount->mnt_kern_flag & MNTK_ASYNC) == 0) return (bwrite(bp)); @@ -120,22 +120,22 @@ ext2_truncate(vp, length, flags, cred, td) 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 bufobj *bo; + struct m_ext2fs *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); + bo = &ovp->v_bufobj; + + ASSERT_VOP_LOCKED(vp, "ext2_truncate"); + + if (length < 0) + return (EINVAL); + if (ovp->v_type == VLNK && oip->i_size < ovp->v_mount->mnt_maxsymlinklen) { #ifdef DIAGNOSTIC @@ -153,27 +153,32 @@ printf("ext2_truncate called %d to %d\n", VTOI(ovp)->i_number, length); } 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. + * value of osize is 0, length will be at least 1. */ if (osize < length) { - if (length > oip->i_e2fs->fs_maxfilesize) + if (length > oip->i_e2fs->e2fs_maxfilesize) return (EFBIG); + vnode_pager_setsize(ovp, length); 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) + error = ext2_balloc(oip, lbn, offset + 1, cred, &bp, aflags); + if (error) { + vnode_pager_setsize(vp, osize); return (error); + } oip->i_size = length; - if (aflags & IO_SYNC) + if (bp->b_bufsize == fs->e2fs_bsize) + bp->b_flags |= B_CLUSTEROK; + if (aflags & B_SYNC) bwrite(bp); + else if (ovp->v_mount->mnt_flag & MNT_ASYNC) + bdwrite(bp); else bawrite(bp); oip->i_flag |= IN_CHANGE | IN_UPDATE; @@ -195,15 +200,19 @@ printf("ext2_truncate called %d to %d\n", VTOI(ovp)->i_number, length); aflags = B_CLRBUF; if (flags & IO_SYNC) aflags |= B_SYNC; - if ((error = ext2_balloc(oip, lbn, offset, cred, &bp, - aflags)) != 0) + error = ext2_balloc(oip, lbn, offset, cred, &bp, aflags); + if (error) 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) + if (bp->b_bufsize == fs->e2fs_bsize) + bp->b_flags |= B_CLUSTEROK; + if (aflags & B_SYNC) bwrite(bp); + else if (ovp->v_mount->mnt_flag & MNT_ASYNC) + bdwrite(bp); else bawrite(bp); } @@ -213,11 +222,11 @@ printf("ext2_truncate called %d to %d\n", VTOI(ovp)->i_number, length); * which we want to keep. Lastblock is -1 when * the file is truncated to 0. */ - lastblock = lblkno(fs, length + fs->s_blocksize - 1) - 1; + lastblock = lblkno(fs, length + fs->e2fs_bsize - 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); + nblocks = btodb(fs->e2fs_bsize); /* * Update file and block pointers on disk before we start freeing * blocks. If we crash before free'ing blocks below, the blocks @@ -244,10 +253,11 @@ printf("ext2_truncate called %d to %d\n", VTOI(ovp)->i_number, length); 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); + error = vtruncbuf(ovp, cred, td, length, (int)fs->e2fs_bsize); if (error && (allerror == 0)) allerror = error; - + vnode_pager_setsize(ovp, length); + /* * Indirect blocks first. */ @@ -264,7 +274,7 @@ printf("ext2_truncate called %d to %d\n", VTOI(ovp)->i_number, length); blocksreleased += count; if (lastiblock[level] < 0) { oip->i_ib[level] = 0; - ext2_blkfree(oip, bn, fs->s_frag_size); + ext2_blkfree(oip, bn, fs->e2fs_fsize); blocksreleased += nblocks; } } @@ -325,11 +335,11 @@ done: 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)) + BO_LOCK(bo); + if (length == 0 && (bo->bo_dirty.bv_cnt != 0 || + bo->bo_clean.bv_cnt != 0)) panic("itrunc3"); - VI_UNLOCK(ovp); + BO_UNLOCK(bo); #endif /* DIAGNOSTIC */ /* * Put back the real size. @@ -362,7 +372,7 @@ ext2_indirtrunc(ip, lbn, dbn, lastbn, level, countp) long *countp; { struct buf *bp; - struct ext2_sb_info *fs = ip->i_e2fs; + struct m_ext2fs *fs = ip->i_e2fs; struct vnode *vp; int32_t *bap, *copy, nb, nlbn, last; long blkcount, factor; @@ -380,7 +390,7 @@ ext2_indirtrunc(ip, lbn, dbn, lastbn, level, countp) last = lastbn; if (lastbn > 0) last /= factor; - nblocks = btodb(fs->s_blocksize); + nblocks = btodb(fs->e2fs_bsize); /* * Get buffer of block pointers, zero those entries corresponding * to blocks to be free'd, and update on disk copy first. Since @@ -390,7 +400,7 @@ ext2_indirtrunc(ip, lbn, dbn, lastbn, level, countp) * explicitly instead of letting bread do everything for us. */ vp = ITOV(ip); - bp = getblk(vp, lbn, (int)fs->s_blocksize, 0, 0, 0); + bp = getblk(vp, lbn, (int)fs->e2fs_bsize, 0, 0, 0); if (bp->b_flags & (B_DONE | B_DELWRI)) { } else { bp->b_iocmd = BIO_READ; @@ -409,8 +419,8 @@ ext2_indirtrunc(ip, lbn, dbn, lastbn, level, countp) } bap = (int32_t *)bp->b_data; - copy = malloc(fs->s_blocksize, M_TEMP, M_WAITOK); - bcopy((caddr_t)bap, (caddr_t)copy, (u_int)fs->s_blocksize); + copy = malloc(fs->e2fs_bsize, M_TEMP, M_WAITOK); + bcopy((caddr_t)bap, (caddr_t)copy, (u_int)fs->e2fs_bsize); bzero((caddr_t)&bap[last + 1], (u_int)(NINDIR(fs) - (last + 1)) * sizeof (int32_t)); if (last == -1) @@ -434,7 +444,7 @@ ext2_indirtrunc(ip, lbn, dbn, lastbn, level, countp) allerror = error; blocksreleased += blkcount; } - ext2_blkfree(ip, nb, fs->s_blocksize); + ext2_blkfree(ip, nb, fs->e2fs_bsize); blocksreleased += nblocks; } @@ -471,7 +481,6 @@ ext2_inactive(ap) 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); diff --git a/sys/gnu/fs/ext2fs/ext2_inode_cnv.c b/sys/fs/ext2fs/ext2_inode_cnv.c index 412a47ccc002..b042a5a458f0 100644 --- a/sys/gnu/fs/ext2fs/ext2_inode_cnv.c +++ b/sys/fs/ext2fs/ext2_inode_cnv.c @@ -31,9 +31,10 @@ #include <sys/stat.h> #include <sys/vnode.h> -#include <gnu/fs/ext2fs/inode.h> -#include <gnu/fs/ext2fs/ext2_fs.h> -#include <gnu/fs/ext2fs/ext2_extern.h> +#include <fs/ext2fs/inode.h> +#include <fs/ext2fs/ext2fs.h> +#include <fs/ext2fs/ext2_extern.h> +#include <fs/ext2fs/ext2_dinode.h> void ext2_print_inode( in ) @@ -64,37 +65,37 @@ ext2_print_inode( in ) */ void ext2_ei2i(ei, ip) - struct ext2_inode *ei; + struct ext2fs_dinode *ei; struct inode *ip; { int i; - ip->i_nlink = ei->i_links_count; + ip->i_nlink = ei->e2di_nlink; /* 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; + ip->i_mode = ei->e2di_nlink ? ei->e2di_mode : 0; + ip->i_size = ei->e2di_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_size |= ((u_int64_t)ei->e2di_size_high) << 32; + ip->i_atime = ei->e2di_atime; + ip->i_mtime = ei->e2di_mtime; + ip->i_ctime = ei->e2di_ctime; ip->i_flags = 0; - ip->i_flags |= (ei->i_flags & EXT2_APPEND_FL) ? SF_APPEND : 0; - ip->i_flags |= (ei->i_flags & EXT2_IMMUTABLE_FL) ? SF_IMMUTABLE : 0; - ip->i_flags |= (ei->i_flags & EXT2_NODUMP_FL) ? UF_NODUMP : 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; + ip->i_flags |= (ei->e2di_flags & EXT2_APPEND) ? SF_APPEND : 0; + ip->i_flags |= (ei->e2di_flags & EXT2_IMMUTABLE) ? SF_IMMUTABLE : 0; + ip->i_flags |= (ei->e2di_flags & EXT2_NODUMP) ? UF_NODUMP : 0; + ip->i_blocks = ei->e2di_nblock; + ip->i_gen = ei->e2di_gen; + ip->i_uid = ei->e2di_uid; + ip->i_gid = ei->e2di_gid; /* XXX use memcpy */ for(i = 0; i < NDADDR; i++) - ip->i_db[i] = ei->i_block[i]; + ip->i_db[i] = ei->e2di_blocks[i]; for(i = 0; i < NIADDR; i++) - ip->i_ib[i] = ei->i_block[EXT2_NDIR_BLOCKS + i]; + ip->i_ib[i] = ei->e2di_blocks[EXT2_NDIR_BLOCKS + i]; } /* @@ -103,35 +104,35 @@ ext2_ei2i(ei, ip) void ext2_i2ei(ip, ei) struct inode *ip; - struct ext2_inode *ei; + struct ext2fs_dinode *ei; { int i; - ei->i_mode = ip->i_mode; - ei->i_links_count = ip->i_nlink; + ei->e2di_mode = ip->i_mode; + ei->e2di_nlink = 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; + ei->e2di_dtime = ei->e2di_nlink ? 0 : ip->i_mtime; + ei->e2di_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 & SF_APPEND) ? EXT2_APPEND_FL: 0; - ei->i_flags |= (ip->i_flags & SF_IMMUTABLE) ? EXT2_IMMUTABLE_FL: 0; - ei->i_flags |= (ip->i_flags & UF_NODUMP) ? EXT2_NODUMP_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; + ei->e2di_size_high = ip->i_size >> 32; + ei->e2di_atime = ip->i_atime; + ei->e2di_mtime = ip->i_mtime; + ei->e2di_ctime = ip->i_ctime; + ei->e2di_flags = ip->i_flags; + ei->e2di_flags = 0; + ei->e2di_flags |= (ip->i_flags & SF_APPEND) ? EXT2_APPEND: 0; + ei->e2di_flags |= (ip->i_flags & SF_IMMUTABLE) ? EXT2_IMMUTABLE: 0; + ei->e2di_flags |= (ip->i_flags & UF_NODUMP) ? EXT2_NODUMP: 0; + ei->e2di_nblock = ip->i_blocks; + ei->e2di_gen = ip->i_gen; + ei->e2di_uid = ip->i_uid; + ei->e2di_gid = ip->i_gid; /* XXX use memcpy */ for(i = 0; i < NDADDR; i++) - ei->i_block[i] = ip->i_db[i]; + ei->e2di_blocks[i] = ip->i_db[i]; for(i = 0; i < NIADDR; i++) - ei->i_block[EXT2_NDIR_BLOCKS + i] = ip->i_ib[i]; + ei->e2di_blocks[EXT2_NDIR_BLOCKS + i] = ip->i_ib[i]; } diff --git a/sys/gnu/fs/ext2fs/ext2_lookup.c b/sys/fs/ext2fs/ext2_lookup.c index 6ab41e5aa1b4..56963b25d15e 100644 --- a/sys/gnu/fs/ext2fs/ext2_lookup.c +++ b/sys/fs/ext2fs/ext2_lookup.c @@ -55,11 +55,11 @@ #include <ufs/ufs/dir.h> -#include <gnu/fs/ext2fs/inode.h> -#include <gnu/fs/ext2fs/ext2_mount.h> -#include <gnu/fs/ext2fs/ext2_extern.h> -#include <gnu/fs/ext2fs/ext2_fs.h> -#include <gnu/fs/ext2fs/ext2_fs_sb.h> +#include <fs/ext2fs/inode.h> +#include <fs/ext2fs/ext2_mount.h> +#include <fs/ext2fs/ext2_extern.h> +#include <fs/ext2fs/ext2fs.h> +#include <fs/ext2fs/ext2_dir.h> #ifdef DIAGNOSTIC static int dirchk = 1; @@ -112,7 +112,7 @@ static u_char dt_to_ext2_ft[] = { ((dt) > sizeof(dt_to_ext2_ft) / sizeof(dt_to_ext2_ft[0]) ? \ EXT2_FT_UNKNOWN : dt_to_ext2_ft[(dt)]) -static int ext2_dirbadentry(struct vnode *dp, struct ext2_dir_entry_2 *de, +static int ext2_dirbadentry(struct vnode *dp, struct ext2fs_direct_2 *de, int entryoffsetinblock); /* @@ -144,13 +144,13 @@ ext2_readdir(ap) struct uio *uio = ap->a_uio; int count, error; - struct ext2_dir_entry_2 *edp, *dp; + struct ext2fs_direct_2 *edp, *dp; int ncookies; struct dirent dstdp; struct uio auio; struct iovec aiov; caddr_t dirbuf; - int DIRBLKSIZ = VTOI(ap->a_vp)->i_e2fs->s_blocksize; + int DIRBLKSIZ = VTOI(ap->a_vp)->i_e2fs->e2fs_bsize; int readcnt; off_t startoffset = uio->uio_offset; @@ -166,12 +166,6 @@ ext2_readdir(ap) count -= (uio->uio_offset + count) & (DIRBLKSIZ -1); if (count <= 0) count += DIRBLKSIZ; - -#ifdef EXT2FS_DEBUG - printf("ext2_readdir: uio_offset = %lld, uio_resid = %d, count = %d\n", - uio->uio_offset, uio->uio_resid, count); -#endif - auio = *uio; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; @@ -183,10 +177,10 @@ ext2_readdir(ap) error = VOP_READ(ap->a_vp, &auio, 0, ap->a_cred); if (error == 0) { readcnt = count - auio.uio_resid; - edp = (struct ext2_dir_entry_2 *)&dirbuf[readcnt]; + edp = (struct ext2fs_direct_2 *)&dirbuf[readcnt]; ncookies = 0; bzero(&dstdp, offsetof(struct dirent, d_name)); - for (dp = (struct ext2_dir_entry_2 *)dirbuf; + for (dp = (struct ext2fs_direct_2 *)dirbuf; !error && uio->uio_resid > 0 && dp < edp; ) { /*- * "New" ext2fs directory entries differ in 3 ways @@ -204,20 +198,20 @@ ext2_readdir(ap) * because ext2fs uses a machine-independent disk * layout. */ - dstdp.d_fileno = dp->inode; - dstdp.d_type = FTTODT(dp->file_type); - dstdp.d_namlen = dp->name_len; + dstdp.d_fileno = dp->e2d_ino; + dstdp.d_type = FTTODT(dp->e2d_type); + dstdp.d_namlen = dp->e2d_namlen; dstdp.d_reclen = GENERIC_DIRSIZ(&dstdp); - bcopy(dp->name, dstdp.d_name, dstdp.d_namlen); + bcopy(dp->e2d_name, dstdp.d_name, dstdp.d_namlen); bzero(dstdp.d_name + dstdp.d_namlen, dstdp.d_reclen - offsetof(struct dirent, d_name) - dstdp.d_namlen); - if (dp->rec_len > 0) { + if (dp->e2d_reclen > 0) { if(dstdp.d_reclen <= uio->uio_resid) { /* advance dp */ - dp = (struct ext2_dir_entry_2 *) - ((char *)dp + dp->rec_len); + dp = (struct ext2fs_direct_2 *) + ((char *)dp + dp->e2d_reclen); error = uiomove(&dstdp, dstdp.d_reclen, uio); if (!error) @@ -241,11 +235,11 @@ ext2_readdir(ap) cookies = malloc(ncookies * sizeof(u_long), M_TEMP, M_WAITOK); off = startoffset; - for (dp = (struct ext2_dir_entry_2 *)dirbuf, + for (dp = (struct ext2fs_direct_2 *)dirbuf, cookiep = cookies, ecookies = cookies + ncookies; cookiep < ecookies; - dp = (struct ext2_dir_entry_2 *)((caddr_t) dp + dp->rec_len)) { - off += dp->rec_len; + dp = (struct ext2fs_direct_2 *)((caddr_t) dp + dp->e2d_reclen)) { + off += dp->e2d_reclen; *cookiep++ = (u_long) off; } *ap->a_ncookies = ncookies; @@ -299,11 +293,13 @@ ext2_lookup(ap) struct vnode *vdp; /* vnode for directory being searched */ struct inode *dp; /* inode for directory being searched */ struct buf *bp; /* a buffer of directory entries */ - struct ext2_dir_entry_2 *ep; /* the current directory entry */ + struct ext2fs_direct_2 *ep; /* the current directory entry */ int entryoffsetinblock; /* offset of ep in bp's buffer */ enum {NONE, COMPACT, FOUND} slotstatus; doff_t slotoffset; /* offset of area with free space */ int slotsize; /* size of area at slotoffset */ + doff_t i_diroff; /* cached i_diroff value */ + doff_t i_offset; /* cached i_offset value */ int slotfreespace; /* amount of space free in slot */ int slotneeded; /* size of the entry we're seeking */ int numdirpasses; /* strategy for directory search */ @@ -319,9 +315,10 @@ ext2_lookup(ap) struct ucred *cred = cnp->cn_cred; int flags = cnp->cn_flags; int nameiop = cnp->cn_nameiop; - ino_t saved_ino; + ino_t ino; + int ltype; - int DIRBLKSIZ = VTOI(ap->a_dvp)->i_e2fs->s_blocksize; + int DIRBLKSIZ = VTOI(ap->a_dvp)->i_e2fs->e2fs_bsize; bp = NULL; slotoffset = -1; @@ -338,6 +335,8 @@ ext2_lookup(ap) * we watch for a place to put the new file in * case it doesn't already exist. */ + ino = 0; + i_diroff = dp->i_diroff; slotstatus = FOUND; slotfreespace = slotsize = slotneeded = 0; if ((nameiop == CREATE || nameiop == RENAME) && @@ -361,34 +360,34 @@ ext2_lookup(ap) * of simplicity. */ bmask = VFSTOEXT2(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1; - if (nameiop != LOOKUP || dp->i_diroff == 0 || - dp->i_diroff > dp->i_size) { + if (nameiop != LOOKUP || i_diroff == 0 || + i_diroff > dp->i_size) { entryoffsetinblock = 0; - dp->i_offset = 0; + i_offset = 0; numdirpasses = 1; } else { - dp->i_offset = dp->i_diroff; - if ((entryoffsetinblock = dp->i_offset & bmask) && - (error = ext2_blkatoff(vdp, (off_t)dp->i_offset, NULL, + i_offset = i_diroff; + if ((entryoffsetinblock = i_offset & bmask) && + (error = ext2_blkatoff(vdp, (off_t)i_offset, NULL, &bp))) return (error); numdirpasses = 2; nchstats.ncs_2passes++; } - prevoff = dp->i_offset; - endsearch = roundup(dp->i_size, DIRBLKSIZ); + prevoff = i_offset; + endsearch = roundup2(dp->i_size, DIRBLKSIZ); enduseful = 0; searchloop: - while (dp->i_offset < endsearch) { + while (i_offset < endsearch) { /* * If necessary, get the next directory block. */ - if ((dp->i_offset & bmask) == 0) { + if ((i_offset & bmask) == 0) { if (bp != NULL) brelse(bp); if ((error = - ext2_blkatoff(vdp, (off_t)dp->i_offset, NULL, + ext2_blkatoff(vdp, (off_t)i_offset, NULL, &bp)) != 0) return (error); entryoffsetinblock = 0; @@ -409,14 +408,14 @@ searchloop: * directory. Complete checks can be run by setting * "vfs.e2fs.dirchk" to be true. */ - ep = (struct ext2_dir_entry_2 *) + ep = (struct ext2fs_direct_2 *) ((char *)bp->b_data + entryoffsetinblock); - if (ep->rec_len == 0 || + if (ep->e2d_reclen == 0 || (dirchk && ext2_dirbadentry(vdp, ep, entryoffsetinblock))) { int i; - ext2_dirbad(dp, dp->i_offset, "mangled entry"); + ext2_dirbad(dp, i_offset, "mangled entry"); i = DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)); - dp->i_offset += i; + i_offset += i; entryoffsetinblock += i; continue; } @@ -428,23 +427,23 @@ searchloop: * compaction is viable. */ if (slotstatus != FOUND) { - int size = ep->rec_len; + int size = ep->e2d_reclen; - if (ep->inode != 0) - size -= EXT2_DIR_REC_LEN(ep->name_len); + if (ep->e2d_ino != 0) + size -= EXT2_DIR_REC_LEN(ep->e2d_namlen); if (size > 0) { if (size >= slotneeded) { slotstatus = FOUND; - slotoffset = dp->i_offset; - slotsize = ep->rec_len; + slotoffset = i_offset; + slotsize = ep->e2d_reclen; } else if (slotstatus == NONE) { slotfreespace += size; if (slotoffset == -1) - slotoffset = dp->i_offset; + slotoffset = i_offset; if (slotfreespace >= slotneeded) { slotstatus = COMPACT; - slotsize = dp->i_offset + - ep->rec_len - slotoffset; + slotsize = i_offset + + ep->e2d_reclen - slotoffset; } } } @@ -453,26 +452,25 @@ searchloop: /* * Check for a name match. */ - if (ep->inode) { - namlen = ep->name_len; + if (ep->e2d_ino) { + namlen = ep->e2d_namlen; if (namlen == cnp->cn_namelen && - !bcmp(cnp->cn_nameptr, ep->name, + !bcmp(cnp->cn_nameptr, ep->e2d_name, (unsigned)namlen)) { /* * Save directory entry's inode number and * reclen in ndp->ni_ufs area, and release * directory buffer. */ - dp->i_ino = ep->inode; - dp->i_reclen = ep->rec_len; + ino = ep->e2d_ino; goto found; } } - prevoff = dp->i_offset; - dp->i_offset += ep->rec_len; - entryoffsetinblock += ep->rec_len; - if (ep->inode) - enduseful = dp->i_offset; + prevoff = i_offset; + i_offset += ep->e2d_reclen; + entryoffsetinblock += ep->e2d_reclen; + if (ep->e2d_ino) + enduseful = i_offset; } /* notfound: */ /* @@ -481,10 +479,11 @@ searchloop: */ if (numdirpasses == 2) { numdirpasses--; - dp->i_offset = 0; - endsearch = dp->i_diroff; + i_offset = 0; + endsearch = i_diroff; goto searchloop; } + dp->i_offset = i_offset; if (bp != NULL) brelse(bp); /* @@ -510,7 +509,7 @@ searchloop: * dp->i_offset + dp->i_count. */ if (slotstatus == NONE) { - dp->i_offset = roundup(dp->i_size, DIRBLKSIZ); + dp->i_offset = roundup2(dp->i_size, DIRBLKSIZ); dp->i_count = 0; enduseful = dp->i_offset; } else { @@ -519,7 +518,7 @@ searchloop: if (enduseful < slotoffset + slotsize) enduseful = slotoffset + slotsize; } - dp->i_endoff = roundup(enduseful, DIRBLKSIZ); + dp->i_endoff = roundup2(enduseful, DIRBLKSIZ); dp->i_flag |= IN_CHANGE | IN_UPDATE; /* * We return with the directory locked, so that @@ -551,10 +550,10 @@ found: * Check that directory length properly reflects presence * of this entry. */ - if (entryoffsetinblock + EXT2_DIR_REC_LEN(ep->name_len) + if (entryoffsetinblock + EXT2_DIR_REC_LEN(ep->e2d_namlen) > dp->i_size) { - ext2_dirbad(dp, dp->i_offset, "i_size too small"); - dp->i_size = entryoffsetinblock+EXT2_DIR_REC_LEN(ep->name_len); + ext2_dirbad(dp, i_offset, "i_size too small"); + dp->i_size = entryoffsetinblock+EXT2_DIR_REC_LEN(ep->e2d_namlen); dp->i_flag |= IN_CHANGE | IN_UPDATE; } brelse(bp); @@ -565,8 +564,8 @@ found: * in the cache as to where the entry was found. */ if ((flags & ISLASTCN) && nameiop == LOOKUP) - dp->i_diroff = dp->i_offset &~ (DIRBLKSIZ - 1); - + dp->i_diroff = i_offset &~ (DIRBLKSIZ - 1); + dp->i_offset = i_offset; /* * If deleting, and at end of pathname, return * parameters which can be used to remove file. @@ -587,12 +586,12 @@ found: dp->i_count = 0; else dp->i_count = dp->i_offset - prevoff; - if (dp->i_number == dp->i_ino) { + if (dp->i_number == ino) { VREF(vdp); *vpp = vdp; return (0); } - if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, LK_EXCLUSIVE, + if ((error = VFS_VGET(vdp->v_mount, ino, LK_EXCLUSIVE, &tdp)) != 0) return (error); /* @@ -625,9 +624,9 @@ found: * Careful about locking second inode. * This can only occur if the target is ".". */ - if (dp->i_number == dp->i_ino) + if (dp->i_number == ino) return (EISDIR); - if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, LK_EXCLUSIVE, + if ((error = VFS_VGET(vdp->v_mount, ino, LK_EXCLUSIVE, &tdp)) != 0) return (error); *vpp = tdp; @@ -656,18 +655,29 @@ found: */ pdp = vdp; if (flags & ISDOTDOT) { - saved_ino = dp->i_ino; + ltype = VOP_ISLOCKED(pdp); VOP_UNLOCK(pdp, 0); /* race to get the inode */ - error = VFS_VGET(vdp->v_mount, saved_ino, LK_EXCLUSIVE, &tdp); - vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY); + error = VFS_VGET(vdp->v_mount, ino, cnp->cn_lkflags, &tdp); + vn_lock(pdp, ltype | LK_RETRY); if (error != 0) return (error); *vpp = tdp; - } else if (dp->i_number == dp->i_ino) { + } else if (dp->i_number == ino) { VREF(vdp); /* we want ourself, ie "." */ + /* + * When we lookup "." we still can be asked to lock it + * differently. + */ + ltype = cnp->cn_lkflags & LK_TYPE_MASK; + if (ltype != VOP_ISLOCKED(vdp)) { + if (ltype == LK_EXCLUSIVE) + vn_lock(vdp, LK_UPGRADE | LK_RETRY); + else /* if (ltype == LK_SHARED) */ + vn_lock(vdp, LK_DOWNGRADE | LK_RETRY); + } *vpp = vdp; } else { - if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, LK_EXCLUSIVE, + if ((error = VFS_VGET(vdp->v_mount, ino, cnp->cn_lkflags, &tdp)) != 0) return (error); *vpp = tdp; @@ -690,10 +700,13 @@ ext2_dirbad(ip, offset, how) struct mount *mp; mp = ITOV(ip)->v_mount; - (void)printf("%s: bad dir ino %lu at offset %ld: %s\n", - mp->mnt_stat.f_mntonname, (u_long)ip->i_number, (long)offset, how); if ((mp->mnt_flag & MNT_RDONLY) == 0) - panic("ext2_dirbad: bad dir"); + panic("ext2_dirbad: %s: bad dir ino %lu at offset %ld: %s\n", + mp->mnt_stat.f_mntonname, (u_long)ip->i_number,(long)offset, how); + else + (void)printf("%s: bad dir ino %lu at offset %ld: %s\n", + mp->mnt_stat.f_mntonname, (u_long)ip->i_number, (long)offset, how); + } /* @@ -710,20 +723,20 @@ ext2_dirbad(ip, offset, how) static int ext2_dirbadentry(dp, de, entryoffsetinblock) struct vnode *dp; - struct ext2_dir_entry_2 *de; + struct ext2fs_direct_2 *de; int entryoffsetinblock; { - int DIRBLKSIZ = VTOI(dp)->i_e2fs->s_blocksize; + int DIRBLKSIZ = VTOI(dp)->i_e2fs->e2fs_bsize; char * error_msg = NULL; - if (de->rec_len < EXT2_DIR_REC_LEN(1)) + if (de->e2d_reclen < EXT2_DIR_REC_LEN(1)) error_msg = "rec_len is smaller than minimal"; - else if (de->rec_len % 4 != 0) + else if (de->e2d_reclen % 4 != 0) error_msg = "rec_len % 4 != 0"; - else if (de->rec_len < EXT2_DIR_REC_LEN(de->name_len)) + else if (de->e2d_reclen < EXT2_DIR_REC_LEN(de->e2d_namlen)) error_msg = "reclen is too small for name_len"; - else if (entryoffsetinblock + de->rec_len > DIRBLKSIZ) + else if (entryoffsetinblock + de->e2d_reclen > DIRBLKSIZ) error_msg = "directory entry across blocks"; /* else LATER if (de->inode > dir->i_sb->u.ext2_sb.s_es->s_inodes_count) @@ -733,8 +746,8 @@ ext2_dirbadentry(dp, de, entryoffsetinblock) if (error_msg != NULL) { printf("bad directory entry: %s\n", error_msg); printf("offset=%d, inode=%lu, rec_len=%u, name_len=%u\n", - entryoffsetinblock, (unsigned long)de->inode, - de->rec_len, de->name_len); + entryoffsetinblock, (unsigned long)de->e2d_ino, + de->e2d_reclen, de->e2d_namlen); } return error_msg == NULL ? 0 : 1; } @@ -753,16 +766,16 @@ ext2_direnter(ip, dvp, cnp) struct vnode *dvp; struct componentname *cnp; { - struct ext2_dir_entry_2 *ep, *nep; + struct ext2fs_direct_2 *ep, *nep; struct inode *dp; struct buf *bp; - struct ext2_dir_entry_2 newdir; + struct ext2fs_direct_2 newdir; struct iovec aiov; struct uio auio; u_int dsize; int error, loc, newentrysize, spacefree; char *dirbuf; - int DIRBLKSIZ = ip->i_e2fs->s_blocksize; + int DIRBLKSIZ = ip->i_e2fs->e2fs_bsize; #ifdef DIAGNOSTIC @@ -770,15 +783,15 @@ ext2_direnter(ip, dvp, cnp) panic("direnter: missing name"); #endif dp = VTOI(dvp); - newdir.inode = ip->i_number; - newdir.name_len = cnp->cn_namelen; + newdir.e2d_ino = ip->i_number; + newdir.e2d_namlen = cnp->cn_namelen; if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs, - EXT2_FEATURE_INCOMPAT_FILETYPE)) - newdir.file_type = DTTOFT(IFTODT(ip->i_mode)); + EXT2F_INCOMPAT_FTYPE)) + newdir.e2d_type = DTTOFT(IFTODT(ip->i_mode)); else - newdir.file_type = EXT2_FT_UNKNOWN; - bcopy(cnp->cn_nameptr, newdir.name, (unsigned)cnp->cn_namelen + 1); - newentrysize = EXT2_DIR_REC_LEN(newdir.name_len); + newdir.e2d_type = EXT2_FT_UNKNOWN; + bcopy(cnp->cn_nameptr, newdir.e2d_name, (unsigned)cnp->cn_namelen + 1); + newentrysize = EXT2_DIR_REC_LEN(newdir.e2d_namlen); if (dp->i_count == 0) { /* * If dp->i_count is 0, then namei could find no @@ -789,7 +802,7 @@ ext2_direnter(ip, dvp, cnp) if (dp->i_offset & (DIRBLKSIZ - 1)) panic("ext2_direnter: newblk"); auio.uio_offset = dp->i_offset; - newdir.rec_len = DIRBLKSIZ; + newdir.e2d_reclen = DIRBLKSIZ; auio.uio_resid = newentrysize; aiov.iov_len = newentrysize; aiov.iov_base = (caddr_t)&newdir; @@ -804,7 +817,7 @@ ext2_direnter(ip, dvp, cnp) /* XXX should grow with balloc() */ panic("ext2_direnter: frag size"); else if (!error) { - dp->i_size = roundup(dp->i_size, DIRBLKSIZ); + dp->i_size = roundup2(dp->i_size, DIRBLKSIZ); dp->i_flag |= IN_CHANGE; } return (error); @@ -841,38 +854,38 @@ ext2_direnter(ip, dvp, cnp) * dp->i_offset + dp->i_count would yield the * space. */ - ep = (struct ext2_dir_entry_2 *)dirbuf; - dsize = EXT2_DIR_REC_LEN(ep->name_len); - spacefree = ep->rec_len - dsize; - for (loc = ep->rec_len; loc < dp->i_count; ) { - nep = (struct ext2_dir_entry_2 *)(dirbuf + loc); - if (ep->inode) { + ep = (struct ext2fs_direct_2 *)dirbuf; + dsize = EXT2_DIR_REC_LEN(ep->e2d_namlen); + spacefree = ep->e2d_reclen - dsize; + for (loc = ep->e2d_reclen; loc < dp->i_count; ) { + nep = (struct ext2fs_direct_2 *)(dirbuf + loc); + if (ep->e2d_ino) { /* trim the existing slot */ - ep->rec_len = dsize; - ep = (struct ext2_dir_entry_2 *)((char *)ep + dsize); + ep->e2d_reclen = dsize; + ep = (struct ext2fs_direct_2 *)((char *)ep + dsize); } else { /* overwrite; nothing there; header is ours */ spacefree += dsize; } - dsize = EXT2_DIR_REC_LEN(nep->name_len); - spacefree += nep->rec_len - dsize; - loc += nep->rec_len; + dsize = EXT2_DIR_REC_LEN(nep->e2d_namlen); + spacefree += nep->e2d_reclen - dsize; + loc += nep->e2d_reclen; bcopy((caddr_t)nep, (caddr_t)ep, dsize); } /* * Update the pointer fields in the previous entry (if any), * copy in the new entry, and write out the block. */ - if (ep->inode == 0) { + if (ep->e2d_ino == 0) { if (spacefree + dsize < newentrysize) panic("ext2_direnter: compact1"); - newdir.rec_len = spacefree + dsize; + newdir.e2d_reclen = spacefree + dsize; } else { if (spacefree < newentrysize) panic("ext2_direnter: compact2"); - newdir.rec_len = spacefree; - ep->rec_len = dsize; - ep = (struct ext2_dir_entry_2 *)((char *)ep + dsize); + newdir.e2d_reclen = spacefree; + ep->e2d_reclen = dsize; + ep = (struct ext2fs_direct_2 *)((char *)ep + dsize); } bcopy((caddr_t)&newdir, (caddr_t)ep, (u_int)newentrysize); error = bwrite(bp); @@ -901,7 +914,7 @@ ext2_dirremove(dvp, cnp) struct componentname *cnp; { struct inode *dp; - struct ext2_dir_entry_2 *ep; + struct ext2fs_direct_2 *ep, *rep; struct buf *bp; int error; @@ -914,7 +927,7 @@ ext2_dirremove(dvp, cnp) ext2_blkatoff(dvp, (off_t)dp->i_offset, (char **)&ep, &bp)) != 0) return (error); - ep->inode = 0; + ep->e2d_ino = 0; error = bwrite(bp); dp->i_flag |= IN_CHANGE | IN_UPDATE; return (error); @@ -925,7 +938,13 @@ ext2_dirremove(dvp, cnp) if ((error = ext2_blkatoff(dvp, (off_t)(dp->i_offset - dp->i_count), (char **)&ep, &bp)) != 0) return (error); - ep->rec_len += dp->i_reclen; + + /* Set 'rep' to the entry being removed. */ + if (dp->i_count == 0) + rep = ep; + else + rep = (struct ext2fs_direct_2 *)((char *)ep + ep->e2d_reclen); + ep->e2d_reclen += rep->e2d_reclen; error = bwrite(bp); dp->i_flag |= IN_CHANGE | IN_UPDATE; return (error); @@ -942,19 +961,19 @@ ext2_dirrewrite(dp, ip, cnp) struct componentname *cnp; { struct buf *bp; - struct ext2_dir_entry_2 *ep; + struct ext2fs_direct_2 *ep; struct vnode *vdp = ITOV(dp); int error; if ((error = ext2_blkatoff(vdp, (off_t)dp->i_offset, (char **)&ep, &bp)) != 0) return (error); - ep->inode = ip->i_number; + ep->e2d_ino = ip->i_number; if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs, - EXT2_FEATURE_INCOMPAT_FILETYPE)) - ep->file_type = DTTOFT(IFTODT(ip->i_mode)); + EXT2F_INCOMPAT_FTYPE)) + ep->e2d_type = DTTOFT(IFTODT(ip->i_mode)); else - ep->file_type = EXT2_FT_UNKNOWN; + ep->e2d_type = EXT2_FT_UNKNOWN; error = bwrite(bp); dp->i_flag |= IN_CHANGE | IN_UPDATE; return (error); @@ -977,11 +996,11 @@ ext2_dirempty(ip, parentino, cred) { off_t off; struct dirtemplate dbuf; - struct ext2_dir_entry_2 *dp = (struct ext2_dir_entry_2 *)&dbuf; + struct ext2fs_direct_2 *dp = (struct ext2fs_direct_2 *)&dbuf; int error, count, namlen; #define MINDIRSIZ (sizeof (struct dirtemplate) / 2) - for (off = 0; off < ip->i_size; off += dp->rec_len) { + for (off = 0; off < ip->i_size; off += dp->e2d_reclen) { error = vn_rdwr(UIO_READ, ITOV(ip), (caddr_t)dp, MINDIRSIZ, off, UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK, cred, NOCRED, &count, (struct thread *)0); @@ -992,16 +1011,16 @@ ext2_dirempty(ip, parentino, cred) if (error || count != 0) return (0); /* avoid infinite loops */ - if (dp->rec_len == 0) + if (dp->e2d_reclen == 0) return (0); /* skip empty entries */ - if (dp->inode == 0) + if (dp->e2d_ino == 0) continue; /* accept only "." and ".." */ - namlen = dp->name_len; + namlen = dp->e2d_namlen; if (namlen > 2) return (0); - if (dp->name[0] != '.') + if (dp->e2d_name[0] != '.') return (0); /* * At this point namlen must be 1 or 2. @@ -1010,7 +1029,7 @@ ext2_dirempty(ip, parentino, cred) */ if (namlen == 1) continue; - if (dp->name[1] == '.' && dp->inode == parentino) + if (dp->e2d_name[1] == '.' && dp->e2d_ino == parentino) continue; return (0); } diff --git a/sys/gnu/fs/ext2fs/ext2_mount.h b/sys/fs/ext2fs/ext2_mount.h index 6be0c7d950fb..6bc051c7bc6c 100644 --- a/sys/gnu/fs/ext2fs/ext2_mount.h +++ b/sys/fs/ext2fs/ext2_mount.h @@ -30,8 +30,8 @@ * $FreeBSD$ */ -#ifndef _SYS_GNU_EXT2FS_EXT2_MOUNT_H_ -#define _SYS_GNU_EXT2FS_EXT2_MOUNT_H_ +#ifndef _FS_EXT2FS_EXT2_MOUNT_H_ +#define _FS_EXT2FS_EXT2_MOUNT_H_ #ifdef _KERNEL @@ -47,17 +47,23 @@ struct ext2mount { 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 + struct m_ext2fs *um_e2fs; /* EXT2FS */ +#define em_e2fsb um_e2fs->e2fs 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 mtx um_lock; /* Protects ext2mount & fs */ + struct g_consumer *um_cp; struct bufobj *um_bo; }; +#define EXT2_LOCK(aa) mtx_lock(&(aa)->um_lock) +#define EXT2_UNLOCK(aa) mtx_unlock(&(aa)->um_lock) +#define EXT2_MTX(aa) (&(aa)->um_lock) + /* Convert mount ptr to ext2fsmount ptr. */ #define VFSTOEXT2(mp) ((struct ext2mount *)((mp)->mnt_data)) diff --git a/sys/gnu/fs/ext2fs/ext2_readwrite.c b/sys/fs/ext2fs/ext2_readwrite.c index e533392fd2da..9c9749a21d79 100644 --- a/sys/gnu/fs/ext2fs/ext2_readwrite.c +++ b/sys/fs/ext2fs/ext2_readwrite.c @@ -36,8 +36,9 @@ * $FreeBSD$ */ +/* XXX TODO: remove these obfuscations (as in ffs_vnops.c). */ #define BLKSIZE(a, b, c) blksize(a, b, c) -#define FS struct ext2_sb_info +#define FS struct m_ext2fs #define I_FS i_e2fs #define READ ext2_read #define READ_S "ext2_read" @@ -47,7 +48,6 @@ /* * Vnode op for reading. */ -/* ARGSUSED */ static int READ(ap) struct vop_read_args /* { @@ -65,8 +65,8 @@ READ(ap) daddr_t lbn, nextlbn; off_t bytesinfile; long size, xfersize, blkoffset; - int error, orig_resid; - int seqcount = ap->a_ioflag >> IO_SEQSHIFT; + int error, orig_resid, seqcount; + seqcount = ap->a_ioflag >> IO_SEQSHIFT; u_short mode; vp = ap->a_vp; @@ -84,11 +84,14 @@ READ(ap) } 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; + KASSERT(orig_resid >= 0, ("ext2_read: uio->uio_resid < 0")); + if (orig_resid == 0) + return (0); + KASSERT(uio->uio_offset >= 0, ("ext2_read: uio->uio_offset < 0")); + fs = ip->I_FS; + if (uio->uio_offset < ip->i_size && uio->uio_offset >= fs->e2fs_maxfilesize) + return (EOVERFLOW); for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) { if ((bytesinfile = ip->i_size - uio->uio_offset) <= 0) break; @@ -97,7 +100,7 @@ READ(ap) size = BLKSIZE(fs, ip, lbn); blkoffset = blkoff(fs, uio->uio_offset); - xfersize = fs->s_frag_size - blkoffset; + xfersize = fs->e2fs_fsize - blkoffset; if (uio->uio_resid < xfersize) xfersize = uio->uio_resid; if (bytesinfile < xfersize) @@ -106,9 +109,8 @@ READ(ap) 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); + error = cluster_read(vp, ip->i_size, lbn, size, + NOCRED, blkoffset + uio->uio_resid, seqcount, &bp); else if (seqcount > 1) { int nextsize = BLKSIZE(fs, ip, nextlbn); error = breadn(vp, lbn, @@ -134,8 +136,8 @@ READ(ap) break; xfersize = size; } - error = - uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio); + error = uiomove((char *)bp->b_data + blkoffset, + (int)xfersize, uio); if (error) break; @@ -143,7 +145,7 @@ READ(ap) } if (bp != NULL) bqrelse(bp); - if (orig_resid > 0 && (error == 0 || uio->uio_resid != orig_resid) && + if ((error == 0 || uio->uio_resid != orig_resid) && (vp->v_mount->mnt_flag & MNT_NOATIME) == 0) ip->i_flag |= IN_ACCESS; return (error); @@ -169,11 +171,10 @@ WRITE(ap) struct thread *td; daddr_t lbn; off_t osize; - int seqcount; - int blkoffset, error, flags, ioflag, resid, size, xfersize; + int blkoffset, error, flags, ioflag, resid, size, seqcount, xfersize; ioflag = ap->a_ioflag; - seqcount = ap->a_ioflag >> IO_SEQSHIFT; + seqcount = ioflag >> IO_SEQSHIFT; uio = ap->a_uio; vp = ap->a_vp; ip = VTOI(vp); @@ -193,16 +194,20 @@ WRITE(ap) case VLNK: break; case VDIR: + /* XXX differs from ffs -- this is called from ext2_mkdir(). */ if ((ioflag & IO_SYNC) == 0) - panic("%s: nonsync dir write", WRITE_S); + panic("ext2_write: nonsync dir write"); break; default: - panic("%s: type", WRITE_S); + panic("ext2_write: type %p %d (%jd,%jd)", (void *)vp, + vp->v_type, (intmax_t)uio->uio_offset, + (intmax_t)uio->uio_resid); } + KASSERT(uio->uio_resid >= 0, ("ext2_write: uio->uio_resid < 0")); + KASSERT(uio->uio_offset >= 0, ("ext2_write: uio->uio_offset < 0")); fs = ip->I_FS; - if (uio->uio_offset < 0 || - (uoff_t)uio->uio_offset + uio->uio_resid > fs->fs_maxfilesize) + if ((uoff_t)uio->uio_offset + uio->uio_resid > fs->e2fs_maxfilesize) return (EFBIG); /* * Maybe this should be above the vnode op call, but so long as @@ -227,36 +232,25 @@ WRITE(ap) 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; + xfersize = fs->e2fs_fsize - 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 + * by ensuring that newly allocated blocks are zeroed. 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) + error = ext2_balloc(ip, lbn, blkoffset + xfersize, + ap->a_cred, &bp, flags); + if (error != 0) break; - - if (uio->uio_offset + xfersize > ip->i_size) { + 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; @@ -264,12 +258,12 @@ WRITE(ap) error = uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio); if ((ioflag & IO_VMIO) && - (LIST_FIRST(&bp->b_dep) == NULL)) /* in ext2fs? */ + 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) { + } else if (xfersize + blkoffset == fs->e2fs_fsize) { if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERW) == 0) { bp->b_flags |= B_CLUSTEROK; cluster_write(vp, bp, ip->i_size, seqcount); @@ -282,23 +276,34 @@ WRITE(ap) } 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. + * XXX too late, the tamperer may have opened the file while we + * were writing the data (or before). + * XXX too early, if (error && ioflag & IO_UNIT) then we will + * unwrite the data. */ if (resid > uio->uio_resid && ap->a_cred && ap->a_cred->cr_uid != 0) ip->i_mode &= ~(ISUID | ISGID); if (error) { + /* + * XXX should truncate to the last successfully written + * data if the uiomove() failed. + */ 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); + } + if (uio->uio_resid != resid) { + ip->i_flag |= IN_CHANGE | IN_UPDATE; + if (ioflag & IO_SYNC) + error = ext2_update(vp, 1); + } return (error); } diff --git a/sys/gnu/fs/ext2fs/ext2_subr.c b/sys/fs/ext2fs/ext2_subr.c index 561784294b7b..dcb1b7cd99ce 100644 --- a/sys/gnu/fs/ext2fs/ext2_subr.c +++ b/sys/fs/ext2fs/ext2_subr.c @@ -46,10 +46,10 @@ #include <sys/ucred.h> #include <sys/vnode.h> -#include <gnu/fs/ext2fs/inode.h> -#include <gnu/fs/ext2fs/ext2_extern.h> -#include <gnu/fs/ext2fs/ext2_fs_sb.h> -#include <gnu/fs/ext2fs/fs.h> +#include <fs/ext2fs/inode.h> +#include <fs/ext2fs/ext2_extern.h> +#include <fs/ext2fs/ext2fs.h> +#include <fs/ext2fs/fs.h> #ifdef KDB void ext2_checkoverlap(struct buf *, struct inode *); @@ -68,7 +68,7 @@ ext2_blkatoff(vp, offset, res, bpp) struct buf **bpp; { struct inode *ip; - struct ext2_sb_info *fs; + struct m_ext2fs *fs; struct buf *bp; int32_t lbn; int bsize, error; diff --git a/sys/gnu/fs/ext2fs/ext2_vfsops.c b/sys/fs/ext2fs/ext2_vfsops.c index 20c44ef052ed..7690bb8c53bd 100644 --- a/sys/gnu/fs/ext2fs/ext2_vfsops.c +++ b/sys/fs/ext2fs/ext2_vfsops.c @@ -36,24 +36,6 @@ * $FreeBSD$ */ -/*- - * COPYRIGHT.INFO says this has some GPL'd code from ext2_super.c in it - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - #include <sys/param.h> #include <sys/systm.h> #include <sys/namei.h> @@ -73,19 +55,18 @@ #include <geom/geom.h> #include <geom/geom_vfs.h> -#include <gnu/fs/ext2fs/ext2_mount.h> -#include <gnu/fs/ext2fs/inode.h> +#include <fs/ext2fs/ext2_mount.h> +#include <fs/ext2fs/inode.h> -#include <gnu/fs/ext2fs/fs.h> -#include <gnu/fs/ext2fs/ext2_extern.h> -#include <gnu/fs/ext2fs/ext2_fs_sb.h> -#include <gnu/fs/ext2fs/ext2_fs.h> +#include <fs/ext2fs/fs.h> +#include <fs/ext2fs/ext2_extern.h> +#include <fs/ext2fs/ext2fs.h> static int ext2_flushfiles(struct mount *mp, int flags, struct thread *td); static int ext2_mountfs(struct vnode *, struct mount *); static int ext2_reload(struct mount *mp, struct thread *td); static int ext2_sbupdate(struct ext2mount *, int); - +static int ext2_cgupdate(struct ext2mount *, int); static vfs_unmount_t ext2_unmount; static vfs_root_t ext2_root; static vfs_statfs_t ext2_statfs; @@ -109,10 +90,10 @@ static struct vfsops ext2fs_vfsops = { VFS_SET(ext2fs_vfsops, ext2fs, 0); -static int ext2_check_sb_compat(struct ext2_super_block *es, struct cdev *dev, +static int ext2_check_sb_compat(struct ext2fs *es, struct cdev *dev, int ronly); static int compute_sb_data(struct vnode * devvp, - struct ext2_super_block * es, struct ext2_sb_info * fs); + struct ext2fs * es, struct m_ext2fs * fs); static const char *ext2_opts[] = { "from", "export", "acls", "noexec", "noatime", "union", "suiddir", "multilabel", "nosymfollow", @@ -130,7 +111,7 @@ ext2_mount(struct mount *mp) struct vnode *devvp; struct thread *td; struct ext2mount *ump = 0; - struct ext2_sb_info *fs; + struct m_ext2fs *fs; struct nameidata nd, *ndp = &nd; accmode_t accmode; char *path, *fspec; @@ -158,9 +139,9 @@ ext2_mount(struct mount *mp) */ if (mp->mnt_flag & MNT_UPDATE) { ump = VFSTOEXT2(mp); - fs = ump->um_e2fs; + fs = ump->um_e2fs; error = 0; - if (fs->s_rd_only == 0 && + if (fs->e2fs_ronly == 0 && vfs_flagopt(opts, "ro", NULL, 0)) { error = VFS_SYNC(mp, MNT_WAIT); if (error) @@ -168,15 +149,12 @@ ext2_mount(struct mount *mp) flags = WRITECLOSE; if (mp->mnt_flag & MNT_FORCE) flags |= FORCECLOSE; - if (vfs_busy(mp, MBF_NOWAIT)) - return (EBUSY); error = ext2_flushfiles(mp, flags, td); - vfs_unbusy(mp); - if (!error && fs->s_wasvalid) { - fs->s_es->s_state |= EXT2_VALID_FS; + if ( error == 0 && fs->e2fs_wasvalid && ext2_cgupdate(ump, MNT_WAIT) == 0) { + fs->e2fs->e2fs_state |= E2FS_ISCLEAN; ext2_sbupdate(ump, MNT_WAIT); } - fs->s_rd_only = 1; + fs->e2fs_ronly = 1; vfs_flagopt(opts, "ro", &mp->mnt_flag, MNT_RDONLY); DROP_GIANT(); g_topology_lock(); @@ -189,8 +167,8 @@ ext2_mount(struct mount *mp) if (error) return (error); devvp = ump->um_devvp; - if (fs->s_rd_only && !vfs_flagopt(opts, "ro", NULL, 0)) { - if (ext2_check_sb_compat(fs->s_es, devvp->v_rdev, 0)) + if (fs->e2fs_ronly && !vfs_flagopt(opts, "ro", NULL, 0)) { + if (ext2_check_sb_compat(fs->e2fs, devvp->v_rdev, 0)) return (EPERM); /* @@ -215,21 +193,21 @@ ext2_mount(struct mount *mp) if (error) return (error); - if ((fs->s_es->s_state & EXT2_VALID_FS) == 0 || - (fs->s_es->s_state & EXT2_ERROR_FS)) { + if ((fs->e2fs->e2fs_state & E2FS_ISCLEAN) == 0 || + (fs->e2fs->e2fs_state & E2FS_ERRORS)) { if (mp->mnt_flag & MNT_FORCE) { printf( -"WARNING: %s was not properly dismounted\n", fs->fs_fsmnt); +"WARNING: %s was not properly dismounted\n", fs->e2fs_fsmnt); } else { printf( "WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n", - fs->fs_fsmnt); + fs->e2fs_fsmnt); return (EPERM); } } - fs->s_es->s_state &= ~EXT2_VALID_FS; - ext2_sbupdate(ump, MNT_WAIT); - fs->s_rd_only = 0; + fs->e2fs->e2fs_state &= ~E2FS_ISCLEAN; + (void)ext2_cgupdate(ump, MNT_WAIT); + fs->e2fs_ronly = 0; MNT_ILOCK(mp); mp->mnt_flag &= ~MNT_RDONLY; MNT_IUNLOCK(mp); @@ -294,78 +272,30 @@ ext2_mount(struct mount *mp) * Note that this strncpy() is ok because of a check at the start * of ext2_mount(). */ - strncpy(fs->fs_fsmnt, path, MAXMNTLEN); - fs->fs_fsmnt[MAXMNTLEN - 1] = '\0'; + strncpy(fs->e2fs_fsmnt, path, MAXMNTLEN); + fs->e2fs_fsmnt[MAXMNTLEN - 1] = '\0'; vfs_mountedfrom(mp, fspec); return (0); } -/* - * Checks that the data in the descriptor blocks make sense - * this is taken from ext2/super.c. - */ static int -ext2_check_descriptors(struct ext2_sb_info *sb) +ext2_check_sb_compat(struct ext2fs *es, struct cdev *dev, int ronly) { - struct ext2_group_desc *gdp = NULL; - unsigned long block = sb->s_es->s_first_data_block; - int desc_block = 0; - int i; - for (i = 0; i < sb->s_groups_count; i++) { - /* examine next descriptor block */ - if ((i % EXT2_DESC_PER_BLOCK(sb)) == 0) - gdp = (struct ext2_group_desc *) - sb->s_group_desc[desc_block++]->b_data; - if (gdp->bg_block_bitmap < block || - gdp->bg_block_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb)) { - printf ("ext2_check_descriptors: " - "Block bitmap for group %d" - " not in group (block %lu)!\n", - i, (unsigned long) gdp->bg_block_bitmap); - return (0); - } - if (gdp->bg_inode_bitmap < block || - gdp->bg_inode_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb)) { - printf ("ext2_check_descriptors: " - "Inode bitmap for group %d" - " not in group (block %lu)!\n", - i, (unsigned long) gdp->bg_inode_bitmap); - return (0); - } - if (gdp->bg_inode_table < block || - gdp->bg_inode_table + sb->s_itb_per_group >= - block + EXT2_BLOCKS_PER_GROUP(sb)) { - printf ("ext2_check_descriptors: " - "Inode table for group %d" - " not in group (block %lu)!\n", - i, (unsigned long) gdp->bg_inode_table); - return (0); - } - block += EXT2_BLOCKS_PER_GROUP(sb); - gdp++; - } - return (1); -} - -static int -ext2_check_sb_compat(struct ext2_super_block *es, struct cdev *dev, int ronly) -{ - - if (es->s_magic != EXT2_SUPER_MAGIC) { + if (es->e2fs_magic != E2FS_MAGIC) { printf("ext2fs: %s: wrong magic number %#x (expected %#x)\n", - devtoname(dev), es->s_magic, EXT2_SUPER_MAGIC); + devtoname(dev), es->e2fs_magic, E2FS_MAGIC); return (1); } - if (es->s_rev_level > EXT2_GOOD_OLD_REV) { - if (es->s_feature_incompat & ~EXT2_FEATURE_INCOMPAT_SUPP) { + if (es->e2fs_rev > E2FS_REV0) { + if (es->e2fs_features_incompat & ~EXT2F_INCOMPAT_SUPP) { printf( "WARNING: mount of %s denied due to unsupported optional features\n", devtoname(dev)); return (1); } if (!ronly && - (es->s_feature_ro_compat & ~EXT2_FEATURE_RO_COMPAT_SUPP)) { + (es->e2fs_features_rocompat & ~EXT2F_ROCOMPAT_SUPP)) { printf("WARNING: R/W mount of %s denied due to " "unsupported optional features\n", devtoname(dev)); return (1); @@ -379,52 +309,55 @@ ext2_check_sb_compat(struct ext2_super_block *es, struct cdev *dev, int ronly) * data in the ext2_super_block structure read in. */ static int -compute_sb_data(struct vnode *devvp, struct ext2_super_block *es, - struct ext2_sb_info *fs) +compute_sb_data(struct vnode *devvp, struct ext2fs *es, + struct m_ext2fs *fs) { int db_count, error; - int i, j; + int i; int logic_sb_block = 1; /* XXX for now */ + struct buf *bp; - fs->s_blocksize = EXT2_MIN_BLOCK_SIZE << es->s_log_block_size; - fs->s_bshift = EXT2_MIN_BLOCK_LOG_SIZE + es->s_log_block_size; - fs->s_fsbtodb = es->s_log_block_size + 1; - fs->s_qbmask = fs->s_blocksize - 1; - fs->s_blocksize_bits = es->s_log_block_size + 10; - fs->s_frag_size = EXT2_MIN_FRAG_SIZE << es->s_log_frag_size; - if (fs->s_frag_size) - fs->s_frags_per_block = fs->s_blocksize / fs->s_frag_size; - fs->s_blocks_per_group = es->s_blocks_per_group; - fs->s_frags_per_group = es->s_frags_per_group; - fs->s_inodes_per_group = es->s_inodes_per_group; - if (es->s_rev_level == EXT2_GOOD_OLD_REV) { - fs->s_first_ino = EXT2_GOOD_OLD_FIRST_INO; - fs->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE; + fs->e2fs_bsize = EXT2_MIN_BLOCK_SIZE << es->e2fs_log_bsize; + fs->e2fs_bshift = EXT2_MIN_BLOCK_LOG_SIZE + es->e2fs_log_bsize; + fs->e2fs_fsbtodb = es->e2fs_log_bsize + 1; + fs->e2fs_qbmask = fs->e2fs_bsize - 1; + fs->e2fs_blocksize_bits = es->e2fs_log_bsize + 10; + fs->e2fs_fsize = EXT2_MIN_FRAG_SIZE << es->e2fs_log_fsize; + if (fs->e2fs_fsize) + fs->e2fs_fpb = fs->e2fs_bsize / fs->e2fs_fsize; + fs->e2fs_bpg = es->e2fs_bpg; + fs->e2fs_fpg = es->e2fs_fpg; + fs->e2fs_ipg = es->e2fs_ipg; + if (es->e2fs_rev == E2FS_REV0) { + fs->e2fs_first_inode = E2FS_REV0_FIRST_INO; + fs->e2fs_isize = E2FS_REV0_INODE_SIZE ; } else { - fs->s_first_ino = es->s_first_ino; - fs->s_inode_size = es->s_inode_size; + fs->e2fs_first_inode = es->e2fs_first_ino; + fs->e2fs_isize = es->e2fs_inode_size; /* * Simple sanity check for superblock inode size value. */ - if (fs->s_inode_size < EXT2_GOOD_OLD_INODE_SIZE || - fs->s_inode_size > fs->s_blocksize || - (fs->s_inode_size & (fs->s_inode_size - 1)) != 0) { + if (fs->e2fs_isize < E2FS_REV0_INODE_SIZE || + fs->e2fs_isize > fs->e2fs_bsize || + (fs->e2fs_isize & (fs->e2fs_isize - 1)) != 0) { printf("EXT2-fs: invalid inode size %d\n", - fs->s_inode_size); + fs->e2fs_isize); return (EIO); } } - fs->s_inodes_per_block = fs->s_blocksize / EXT2_INODE_SIZE(fs); - fs->s_itb_per_group = fs->s_inodes_per_group /fs->s_inodes_per_block; - fs->s_desc_per_block = fs->s_blocksize / sizeof (struct ext2_group_desc); + fs->e2fs_ipb = fs->e2fs_bsize / EXT2_INODE_SIZE(fs); + fs->e2fs_itpg = fs->e2fs_ipg /fs->e2fs_ipb; + fs->e2fs_descpb = fs->e2fs_bsize / sizeof (struct ext2_gd); /* s_resuid / s_resgid ? */ - fs->s_groups_count = (es->s_blocks_count - es->s_first_data_block + + fs->e2fs_gcount = (es->e2fs_bcount - es->e2fs_first_dblock + EXT2_BLOCKS_PER_GROUP(fs) - 1) / EXT2_BLOCKS_PER_GROUP(fs); - db_count = (fs->s_groups_count + EXT2_DESC_PER_BLOCK(fs) - 1) / + db_count = (fs->e2fs_gcount + EXT2_DESC_PER_BLOCK(fs) - 1) / EXT2_DESC_PER_BLOCK(fs); - fs->s_gdb_count = db_count; - fs->s_group_desc = malloc(db_count * sizeof (struct buf *), + fs->e2fs_gdbcount = db_count; + fs->e2fs_gd = malloc(db_count * fs->e2fs_bsize, + M_EXT2MNT, M_WAITOK); + fs->e2fs_contigdirs = malloc(fs->e2fs_gcount * sizeof(*fs->e2fs_contigdirs), M_EXT2MNT, M_WAITOK); /* @@ -432,43 +365,34 @@ compute_sb_data(struct vnode *devvp, struct ext2_super_block *es, * Godmar thinks: if the blocksize is greater than 1024, then * the superblock is logically part of block zero. */ - if(fs->s_blocksize > SBSIZE) + if(fs->e2fs_bsize > SBSIZE) logic_sb_block = 0; - for (i = 0; i < db_count; i++) { - error = bread(devvp , fsbtodb(fs, logic_sb_block + i + 1), - fs->s_blocksize, NOCRED, &fs->s_group_desc[i]); - if(error) { - for (j = 0; j < i; j++) - brelse(fs->s_group_desc[j]); - free(fs->s_group_desc, M_EXT2MNT); - printf("EXT2-fs: unable to read group descriptors" - " (%d)\n", error); - return (EIO); + error = bread(devvp , + fsbtodb(fs, logic_sb_block + i + 1 ), + fs->e2fs_bsize, NOCRED, &bp); + if (error) { + free(fs->e2fs_gd, M_EXT2MNT); + brelse(bp); + return (error); } - LCK_BUF(fs->s_group_desc[i]) - } - if(!ext2_check_descriptors(fs)) { - for (j = 0; j < db_count; j++) - ULCK_BUF(fs->s_group_desc[j]) - free(fs->s_group_desc, M_EXT2MNT); - printf("EXT2-fs: (ext2_check_descriptors failure) " - "unable to read group descriptors\n"); - return (EIO); + e2fs_cgload((struct ext2_gd *)bp->b_data, + &fs->e2fs_gd[ + i * fs->e2fs_bsize / sizeof(struct ext2_gd)], + fs->e2fs_bsize); + brelse(bp); + bp = NULL; } - for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) { - fs->s_inode_bitmap_number[i] = 0; - fs->s_inode_bitmap[i] = NULL; - fs->s_block_bitmap_number[i] = 0; - fs->s_block_bitmap[i] = NULL; + fs->e2fs_total_dir = 0; + for (i=0; i < fs->e2fs_gcount; i++){ + fs->e2fs_total_dir += fs->e2fs_gd[i].ext2bgd_ndirs; + fs->e2fs_contigdirs[i] = 0; } - fs->s_loaded_inode_bitmaps = 0; - fs->s_loaded_block_bitmaps = 0; - if (es->s_rev_level == EXT2_GOOD_OLD_REV || - (es->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_LARGE_FILE) == 0) - fs->fs_maxfilesize = 0x7fffffff; + if (es->e2fs_rev == E2FS_REV0 || + (es->e2fs_features_rocompat & EXT2F_ROCOMPAT_LARGEFILE) == 0) + fs->e2fs_maxfilesize = 0x7fffffff; else - fs->fs_maxfilesize = 0x7fffffffffffffff; + fs->e2fs_maxfilesize = 0x7fffffffffffffff; return (0); } @@ -484,6 +408,7 @@ compute_sb_data(struct vnode *devvp, struct ext2_super_block *es, * 4) invalidate all inactive vnodes. * 5) invalidate all cached file data. * 6) re-read inode data for all active vnodes. + * XXX we are missing some steps, in particular # 3, this has to be reviewed. */ static int ext2_reload(struct mount *mp, struct thread *td) @@ -491,8 +416,8 @@ ext2_reload(struct mount *mp, struct thread *td) struct vnode *vp, *mvp, *devvp; struct inode *ip; struct buf *bp; - struct ext2_super_block *es; - struct ext2_sb_info *fs; + struct ext2fs *es; + struct m_ext2fs *fs; int error; if ((mp->mnt_flag & MNT_RDONLY) == 0) @@ -512,13 +437,13 @@ ext2_reload(struct mount *mp, struct thread *td) */ if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0) return (error); - es = (struct ext2_super_block *)bp->b_data; + es = (struct ext2fs *)bp->b_data; if (ext2_check_sb_compat(es, devvp->v_rdev, 0) != 0) { brelse(bp); return (EIO); /* XXX needs translation */ } fs = VFSTOEXT2(mp)->um_e2fs; - bcopy(bp->b_data, fs->s_es, sizeof(struct ext2_super_block)); + bcopy(bp->b_data, fs->e2fs, sizeof(struct ext2fs)); if((error = compute_sb_data(devvp, es, fs)) != 0) { brelse(bp); @@ -554,14 +479,14 @@ loop: */ ip = VTOI(vp); error = bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)), - (int)fs->s_blocksize, NOCRED, &bp); + (int)fs->e2fs_bsize, NOCRED, &bp); if (error) { VOP_UNLOCK(vp, 0); vrele(vp); MNT_VNODE_FOREACH_ABORT(mp, mvp); return (error); } - ext2_ei2i((struct ext2_inode *) ((char *)bp->b_data + + ext2_ei2i((struct ext2fs_dinode *) ((char *)bp->b_data + EXT2_INODE_SIZE(fs) * ino_to_fsbo(fs, ip->i_number)), ip); brelse(bp); VOP_UNLOCK(vp, 0); @@ -580,8 +505,8 @@ ext2_mountfs(struct vnode *devvp, struct mount *mp) { struct ext2mount *ump; struct buf *bp; - struct ext2_sb_info *fs; - struct ext2_super_block *es; + struct m_ext2fs *fs; + struct ext2fs *es; struct cdev *dev = devvp->v_rdev; struct g_consumer *cp; struct bufobj *bo; @@ -622,13 +547,13 @@ ext2_mountfs(struct vnode *devvp, struct mount *mp) ump = NULL; if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0) goto out; - es = (struct ext2_super_block *)bp->b_data; + es = (struct ext2fs *)bp->b_data; if (ext2_check_sb_compat(es, dev, ronly) != 0) { error = EINVAL; /* XXX needs translation */ goto out; } - if ((es->s_state & EXT2_VALID_FS) == 0 || - (es->s_state & EXT2_ERROR_FS)) { + if ((es->e2fs_state & E2FS_ISCLEAN) == 0 || + (es->e2fs_state & E2FS_ERRORS)) { if (ronly || (mp->mnt_flag & MNT_FORCE)) { printf( "WARNING: Filesystem was not properly dismounted\n"); @@ -647,31 +572,28 @@ ext2_mountfs(struct vnode *devvp, struct mount *mp) * we dynamically allocate both an ext2_sb_info and an ext2_super_block * while Linux keeps the super block in a locked buffer. */ - ump->um_e2fs = malloc(sizeof(struct ext2_sb_info), + ump->um_e2fs = malloc(sizeof(struct m_ext2fs), M_EXT2MNT, M_WAITOK); - ump->um_e2fs->s_es = malloc(sizeof(struct ext2_super_block), + ump->um_e2fs->e2fs = malloc(sizeof(struct ext2fs), M_EXT2MNT, M_WAITOK); - bcopy(es, ump->um_e2fs->s_es, (u_int)sizeof(struct ext2_super_block)); - if ((error = compute_sb_data(devvp, ump->um_e2fs->s_es, ump->um_e2fs))) + mtx_init(EXT2_MTX(ump), "EXT2FS", "EXT2FS Lock", MTX_DEF); + bcopy(es, ump->um_e2fs->e2fs, (u_int)sizeof(struct ext2fs)); + if ((error = compute_sb_data(devvp, ump->um_e2fs->e2fs, ump->um_e2fs))) goto out; - /* - * We don't free the group descriptors allocated by compute_sb_data() - * until ext2_unmount(). This is OK since the mount will succeed. - */ brelse(bp); bp = NULL; fs = ump->um_e2fs; - fs->s_rd_only = ronly; /* ronly is set according to mnt_flags */ + fs->e2fs_ronly = ronly; /* ronly is set according to mnt_flags */ /* * If the fs is not mounted read-only, make sure the super block is * always written back on a sync(). */ - fs->s_wasvalid = fs->s_es->s_state & EXT2_VALID_FS ? 1 : 0; + fs->e2fs_wasvalid = fs->e2fs->e2fs_state & E2FS_ISCLEAN ? 1 : 0; if (ronly == 0) { - fs->s_dirt = 1; /* mark it modified */ - fs->s_es->s_state &= ~EXT2_VALID_FS; /* set fs invalid */ + fs->e2fs_fmod = 1; /* mark it modified */ + fs->e2fs->e2fs_state &= ~E2FS_ISCLEAN; /* set fs invalid */ } mp->mnt_data = ump; mp->mnt_stat.f_fsid.val[0] = dev2udev(dev); @@ -691,10 +613,17 @@ ext2_mountfs(struct vnode *devvp, struct mount *mp) * ufs_bmap w/o changse! */ ump->um_nindir = EXT2_ADDR_PER_BLOCK(fs); - ump->um_bptrtodb = fs->s_es->s_log_block_size + 1; + ump->um_bptrtodb = fs->e2fs->e2fs_log_bsize + 1; ump->um_seqinc = EXT2_FRAGS_PER_BLOCK(fs); if (ronly == 0) ext2_sbupdate(ump, MNT_WAIT); + /* + * Initialize filesystem stat information in mount struct. + */ + MNT_ILOCK(mp); + mp->mnt_kern_flag |= MNTK_MPSAFE | MNTK_LOOKUP_SHARED | + MNTK_EXTENDED_SHARED; + MNT_IUNLOCK(mp); return (0); out: if (bp) @@ -707,7 +636,10 @@ out: PICKUP_GIANT(); } if (ump) { - free(ump->um_e2fs->s_es, M_EXT2MNT); + mtx_destroy(EXT2_MTX(ump)); + free(ump->um_e2fs->e2fs_gd, M_EXT2MNT); + free(ump->um_e2fs->e2fs_contigdirs, M_EXT2MNT); + free(ump->um_e2fs->e2fs, M_EXT2MNT); free(ump->um_e2fs, M_EXT2MNT); free(ump, M_EXT2MNT); mp->mnt_data = NULL; @@ -722,8 +654,8 @@ static int ext2_unmount(struct mount *mp, int mntflags) { struct ext2mount *ump; - struct ext2_sb_info *fs; - int error, flags, ronly, i; + struct m_ext2fs *fs; + int error, flags, ronly; flags = 0; if (mntflags & MNT_FORCE) { @@ -735,33 +667,22 @@ ext2_unmount(struct mount *mp, int mntflags) return (error); ump = VFSTOEXT2(mp); fs = ump->um_e2fs; - ronly = fs->s_rd_only; - if (ronly == 0) { - if (fs->s_wasvalid) - fs->s_es->s_state |= EXT2_VALID_FS; - ext2_sbupdate(ump, MNT_WAIT); + ronly = fs->e2fs_ronly; + if (ronly == 0 && ext2_cgupdate(ump, MNT_WAIT) == 0) { + if (fs->e2fs_wasvalid) + fs->e2fs->e2fs_state |= E2FS_ISCLEAN; + ext2_sbupdate(ump, MNT_WAIT); } - /* release buffers containing group descriptors */ - for(i = 0; i < fs->s_gdb_count; i++) - ULCK_BUF(fs->s_group_desc[i]) - free(fs->s_group_desc, M_EXT2MNT); - - /* release cached inode/block bitmaps */ - for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) - if (fs->s_inode_bitmap[i]) - ULCK_BUF(fs->s_inode_bitmap[i]) - for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) - if (fs->s_block_bitmap[i]) - ULCK_BUF(fs->s_block_bitmap[i]) - DROP_GIANT(); g_topology_lock(); g_vfs_close(ump->um_cp); g_topology_unlock(); PICKUP_GIANT(); vrele(ump->um_devvp); - free(fs->s_es, M_EXT2MNT); + free(fs->e2fs_gd, M_EXT2MNT); + free(fs->e2fs_contigdirs, M_EXT2MNT); + free(fs->e2fs, M_EXT2MNT); free(fs, M_EXT2MNT); free(ump, M_EXT2MNT); mp->mnt_data = NULL; @@ -782,50 +703,53 @@ ext2_flushfiles(struct mount *mp, int flags, struct thread *td) error = vflush(mp, 0, flags, td); return (error); } - /* * Get file system statistics. - * taken from ext2/super.c ext2_statfs. */ -static int +int ext2_statfs(struct mount *mp, struct statfs *sbp) { struct ext2mount *ump; - struct ext2_sb_info *fs; - struct ext2_super_block *es; - unsigned long overhead; - int i, nsb; + struct m_ext2fs *fs; + uint32_t overhead, overhead_per_group, ngdb; + int i, ngroups; ump = VFSTOEXT2(mp); fs = ump->um_e2fs; - es = fs->s_es; - - if (es->s_magic != EXT2_SUPER_MAGIC) - panic("ext2_statfs - magic number spoiled"); + if (fs->e2fs->e2fs_magic != E2FS_MAGIC) + panic("ext2fs_statvfs"); /* * Compute the overhead (FS structures) */ - if (es->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) { - nsb = 0; - for (i = 0 ; i < fs->s_groups_count; i++) - if (ext2_group_sparse(i)) - nsb++; - } else - nsb = fs->s_groups_count; - overhead = es->s_first_data_block + - /* Superblocks and block group descriptors: */ - nsb * (1 + fs->s_gdb_count) + - /* Inode bitmap, block bitmap, and inode table: */ - fs->s_groups_count * (1 + 1 + fs->s_itb_per_group); + overhead_per_group = + 1 /* block bitmap */ + + 1 /* inode bitmap */ + + fs->e2fs_itpg; + overhead = fs->e2fs->e2fs_first_dblock + + fs->e2fs_gcount * overhead_per_group; + if (fs->e2fs->e2fs_rev > E2FS_REV0 && + fs->e2fs->e2fs_features_rocompat & EXT2F_ROCOMPAT_SPARSESUPER) { + for (i = 0, ngroups = 0; i < fs->e2fs_gcount; i++) { + if (cg_has_sb(i)) + ngroups++; + } + } else { + ngroups = fs->e2fs_gcount; + } + ngdb = fs->e2fs_gdbcount; + if (fs->e2fs->e2fs_rev > E2FS_REV0 && + fs->e2fs->e2fs_features_compat & EXT2F_COMPAT_RESIZE) + ngdb += fs->e2fs->e2fs_reserved_ngdb; + overhead += ngroups * (1 /* superblock */ + ngdb); sbp->f_bsize = EXT2_FRAG_SIZE(fs); sbp->f_iosize = EXT2_BLOCK_SIZE(fs); - sbp->f_blocks = es->s_blocks_count - overhead; - sbp->f_bfree = es->s_free_blocks_count; - sbp->f_bavail = sbp->f_bfree - es->s_r_blocks_count; - sbp->f_files = es->s_inodes_count; - sbp->f_ffree = es->s_free_inodes_count; + sbp->f_blocks = fs->e2fs->e2fs_bcount - overhead; + sbp->f_bfree = fs->e2fs->e2fs_fbcount; + sbp->f_bavail = sbp->f_bfree - fs->e2fs->e2fs_rbcount; + sbp->f_files = fs->e2fs->e2fs_icount; + sbp->f_ffree = fs->e2fs->e2fs_ficount; return (0); } @@ -843,13 +767,13 @@ ext2_sync(struct mount *mp, int waitfor) struct thread *td; struct inode *ip; struct ext2mount *ump = VFSTOEXT2(mp); - struct ext2_sb_info *fs; + struct m_ext2fs *fs; int error, allerror = 0; td = curthread; fs = ump->um_e2fs; - if (fs->s_dirt != 0 && fs->s_rd_only != 0) { /* XXX */ - printf("fs = %s\n", fs->fs_fsmnt); + if (fs->e2fs_fmod != 0 && fs->e2fs_ronly != 0) { /* XXX */ + printf("fs = %s\n", fs->e2fs_fsmnt); panic("ext2_sync: rofs mod"); } @@ -904,10 +828,10 @@ loop: /* * Write back modified superblock. */ - if (fs->s_dirt != 0) { - fs->s_dirt = 0; - fs->s_es->s_wtime = time_second; - if ((error = ext2_sbupdate(ump, waitfor)) != 0) + if (fs->e2fs_fmod != 0) { + fs->e2fs_fmod = 0; + fs->e2fs->e2fs_wtime = time_second; + if ((error = ext2_cgupdate(ump, waitfor)) != 0) allerror = error; } return (allerror); @@ -922,7 +846,7 @@ loop: static int ext2_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp) { - struct ext2_sb_info *fs; + struct m_ext2fs *fs; struct inode *ip; struct ext2mount *ump; struct buf *bp; @@ -958,6 +882,7 @@ ext2_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp) vp->v_data = ip; ip->i_vnode = vp; ip->i_e2fs = fs = ump->um_e2fs; + ip->i_ump = ump; ip->i_number = ino; lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL); @@ -973,20 +898,20 @@ ext2_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp) /* Read in the disk contents for the inode, copy into the inode. */ if ((error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)), - (int)fs->s_blocksize, NOCRED, &bp)) != 0) { + (int)fs->e2fs_bsize, NOCRED, &bp)) != 0) { /* * The inode does not contain anything useful, so it would * be misleading to leave it on its hash chain. With mode * still zero, it will be unlinked and returned to the free * list by vput(). */ - vput(vp); brelse(bp); + vput(vp); *vpp = NULL; return (error); } /* convert ext2 inode to dinode */ - ext2_ei2i((struct ext2_inode *) ((char *)bp->b_data + EXT2_INODE_SIZE(fs) * + ext2_ei2i((struct ext2fs_dinode *) ((char *)bp->b_data + EXT2_INODE_SIZE(fs) * ino_to_fsbo(fs, ino)), ip); ip->i_block_group = ino_to_cg(fs, ino); ip->i_next_alloc_block = 0; @@ -1000,14 +925,14 @@ ext2_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp) * although for regular files and directories only */ if(S_ISDIR(ip->i_mode) || S_ISREG(ip->i_mode)) { - used_blocks = (ip->i_size+fs->s_blocksize-1) / fs->s_blocksize; + used_blocks = (ip->i_size+fs->e2fs_bsize-1) / fs->e2fs_bsize; for(i = used_blocks; i < EXT2_NDIR_BLOCKS; i++) ip->i_db[i] = 0; } /* ext2_print_inode(ip); */ - brelse(bp); + bqrelse(bp); /* * Initialize the vnode from the inode, check for aliases. @@ -1053,13 +978,13 @@ ext2_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) struct inode *ip; struct ufid *ufhp; struct vnode *nvp; - struct ext2_sb_info *fs; + struct m_ext2fs *fs; int error; ufhp = (struct ufid *)fhp; fs = VFSTOEXT2(mp)->um_e2fs; if (ufhp->ufid_ino < ROOTINO || - ufhp->ufid_ino > fs->s_groups_count * fs->s_es->s_inodes_per_group) + ufhp->ufid_ino > fs->e2fs_gcount * fs->e2fs->e2fs_ipg) return (ESTALE); error = VFS_VGET(mp, ufhp->ufid_ino, LK_EXCLUSIVE, &nvp); @@ -1085,13 +1010,13 @@ ext2_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) static int ext2_sbupdate(struct ext2mount *mp, int waitfor) { - struct ext2_sb_info *fs = mp->um_e2fs; - struct ext2_super_block *es = fs->s_es; + struct m_ext2fs *fs = mp->um_e2fs; + struct ext2fs *es = fs->e2fs; struct buf *bp; int error = 0; bp = getblk(mp->um_devvp, SBLOCK, SBSIZE, 0, 0, 0); - bcopy((caddr_t)es, bp->b_data, (u_int)sizeof(struct ext2_super_block)); + bcopy((caddr_t)es, bp->b_data, (u_int)sizeof(struct ext2fs)); if (waitfor == MNT_WAIT) error = bwrite(bp); else @@ -1104,7 +1029,31 @@ ext2_sbupdate(struct ext2mount *mp, int waitfor) */ return (error); } +int +ext2_cgupdate(struct ext2mount *mp, int waitfor) +{ + struct m_ext2fs *fs = mp->um_e2fs; + struct buf *bp; + int i, error = 0, allerror = 0; + + allerror = ext2_sbupdate(mp, waitfor); + for (i = 0; i < fs->e2fs_gdbcount; i++) { + bp = getblk(mp->um_devvp, fsbtodb(fs, + fs->e2fs->e2fs_first_dblock + + 1 /* superblock */ + i), fs->e2fs_bsize, 0, 0, 0); + e2fs_cgsave(&fs->e2fs_gd[ + i * fs->e2fs_bsize / sizeof(struct ext2_gd)], + (struct ext2_gd *)bp->b_data, fs->e2fs_bsize); + if (waitfor == MNT_WAIT) + error = bwrite(bp); + else + bawrite(bp); + } + if (!allerror && error) + allerror = error; + return (allerror); +} /* * Return the root of a filesystem. */ diff --git a/sys/gnu/fs/ext2fs/ext2_vnops.c b/sys/fs/ext2fs/ext2_vnops.c index 6b44b9b45475..6b0d37140771 100644 --- a/sys/gnu/fs/ext2fs/ext2_vnops.c +++ b/sys/fs/ext2fs/ext2_vnops.c @@ -74,14 +74,15 @@ #include <sys/signalvar.h> #include <ufs/ufs/dir.h> -#include <gnu/fs/ext2fs/inode.h> -#include <gnu/fs/ext2fs/ext2_mount.h> -#include <gnu/fs/ext2fs/ext2_fs_sb.h> -#include <gnu/fs/ext2fs/fs.h> -#include <gnu/fs/ext2fs/ext2_extern.h> -#include <gnu/fs/ext2fs/ext2_fs.h> +#include <fs/ext2fs/inode.h> +#include <fs/ext2fs/ext2_mount.h> +#include <fs/ext2fs/fs.h> +#include <fs/ext2fs/ext2_extern.h> +#include <fs/ext2fs/ext2fs.h> +#include <fs/ext2fs/ext2_dir.h> static int ext2_makeinode(int mode, struct vnode *, struct vnode **, struct componentname *); +static void ext2_itimes_locked(struct vnode *); static vop_access_t ext2_access; static int ext2_chmod(struct vnode *, int, struct ucred *, struct thread *); @@ -160,7 +161,7 @@ struct vop_vector ext2_fifoops = { .vop_vptofh = ext2_vptofh, }; -#include <gnu/fs/ext2fs/ext2_readwrite.c> +#include <fs/ext2fs/ext2_readwrite.c> /* * A virgin directory (no blushing please). @@ -177,13 +178,14 @@ static struct dirtemplate omastertemplate = { 0, DIRBLKSIZ - 12, 2, EXT2_FT_UNKNOWN, ".." }; -void -ext2_itimes(vp) - struct vnode *vp; +static void +ext2_itimes_locked(struct vnode *vp) { struct inode *ip; struct timespec ts; + ASSERT_VI_LOCKED(vp, __func__); + ip = VTOI(vp); if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) == 0) return; @@ -210,6 +212,15 @@ ext2_itimes(vp) ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE); } +void +ext2_itimes(struct vnode *vp) +{ + + VI_LOCK(vp); + ext2_itimes_locked(vp); + VI_UNLOCK(vp); +} + /* * Create a regular file */ @@ -275,7 +286,7 @@ ext2_close(ap) VI_LOCK(vp); if (vp->v_usecount > 1) - ext2_itimes(vp); + ext2_itimes_locked(vp); VI_UNLOCK(vp); return (0); } @@ -316,7 +327,7 @@ ext2_access(ap) } /* If immutable bit set, nobody gets to write it. */ - if ((accmode & VWRITE) && (ip->i_flags & (IMMUTABLE | SF_SNAPSHOT))) + if ((accmode & VWRITE) && (ip->i_flags & (SF_IMMUTABLE | SF_SNAPSHOT))) return (EPERM); error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid, @@ -391,12 +402,11 @@ ext2_setattr(ap) return (EINVAL); } if (vap->va_flags != VNOVAL) { - /* Disallow flags not supported by ext2fs. */ - if (vap->va_flags & ~(SF_APPEND | SF_IMMUTABLE | UF_NODUMP)) - return (EOPNOTSUPP); - if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); + /* Disallow flags not supported by ext2fs. */ + if(vap->va_flags & ~(SF_APPEND | SF_IMMUTABLE | UF_NODUMP)) + return(EOPNOTSUPP); /* * Callers may only modify the file flags on objects they * have VADMIN rights for. @@ -420,11 +430,9 @@ ext2_setattr(ap) ip->i_flags = vap->va_flags; } else { if (ip->i_flags - & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND) || - (vap->va_flags & UF_SETTABLE) != vap->va_flags) + & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) return (EPERM); ip->i_flags &= SF_SETTABLE; - ip->i_flags |= (vap->va_flags & UF_SETTABLE); } ip->i_flag |= IN_CHANGE; if (vap->va_flags & (IMMUTABLE | APPEND)) @@ -610,7 +618,6 @@ ext2_fsync(ap) /* * Flush all dirty buffers associated with a vnode. */ - ext2_discard_prealloc(VTOI(ap->a_vp)); vop_stdfsync(ap); @@ -743,7 +750,27 @@ out: /* * Rename system call. - * See comments in sys/ufs/ufs/ufs_vnops.c + * rename("foo", "bar"); + * is essentially + * unlink("bar"); + * link("foo", "bar"); + * unlink("foo"); + * but ``atomically''. Can't do full commit without saving state in the + * inode on disk which isn't feasible at this time. Best we can do is + * always guarantee the target exists. + * + * Basic algorithm is: + * + * 1) Bump link count on source while we're linking it to the + * target. This also ensure the inode won't be deleted out + * from underneath us while we work (it may be truncated by + * a concurrent `trunc' or `open' for creation). + * 2) Link source to destination. If destination already exists, + * delete it first. + * 3) Unlink source reference to inode if still around. If a + * directory was moved and the parent of the destination + * is different from the source, patch the ".." entry in the + * directory. */ static int ext2_rename(ap) @@ -1189,7 +1216,7 @@ ext2_mkdir(ap) /* Initialize directory with "." and ".." from static template. */ if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs, - EXT2_FEATURE_INCOMPAT_FILETYPE)) + EXT2F_INCOMPAT_FTYPE)) dtp = &mastertemplate; else dtp = &omastertemplate; @@ -1200,7 +1227,7 @@ ext2_mkdir(ap) * so let's just redefine it - for this function only */ #undef DIRBLKSIZ -#define DIRBLKSIZ VTOI(dvp)->i_e2fs->s_blocksize +#define DIRBLKSIZ VTOI(dvp)->i_e2fs->e2fs_bsize dirtemplate.dotdot_reclen = DIRBLKSIZ - 12; error = vn_rdwr(UIO_WRITE, tvp, (caddr_t)&dirtemplate, sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE, @@ -1454,7 +1481,7 @@ ext2fifo_close(ap) VI_LOCK(vp); if (vp->v_usecount > 1) - ext2_itimes(vp); + ext2_itimes_locked(vp); VI_UNLOCK(vp); return (fifo_specops.vop_close(ap)); } diff --git a/sys/fs/ext2fs/ext2fs.h b/sys/fs/ext2fs/ext2fs.h new file mode 100755 index 000000000000..2efc57fa92f2 --- /dev/null +++ b/sys/fs/ext2fs/ext2fs.h @@ -0,0 +1,329 @@ +/*- + * modified for EXT2FS support in Lites 1.1 + * + * Aug 1995, Godmar Back (gback@cs.utah.edu) + * University of Utah, Department of Computer Science + * + * $FreeBSD$ + */ +/*- + * Copyright (c) 2009 Aditya Sarawgi + * 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 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 AUTHOR 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. + * + * + */ + +#ifndef _FS_EXT2FS_EXT2_FS_H +#define _FS_EXT2FS_EXT2_FS_H + +#include <sys/types.h> + +/* + * Special inode numbers + */ +#define EXT2_BAD_INO 1 /* Bad blocks inode */ +#define EXT2_ROOT_INO 2 /* Root 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 E2FS_REV0_FIRST_INO 11 + +/* + * The second extended file system magic number + */ +#define E2FS_MAGIC 0xEF53 + +#if defined(_KERNEL) +/* + * FreeBSD passes the pointer to the in-core struct with relevant + * fields to EXT2_SB macro when accessing superblock fields. + */ +#define EXT2_SB(sb) (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 + +/* + * Maximal count of links to a file + */ +#define EXT2_LINK_MAX 32000 + +/* + * 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 (uint32_t)) + +/* + * 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 + +/* + * Super block for an ext2fs file system. + */ +struct ext2fs { + u_int32_t e2fs_icount; /* Inode count */ + u_int32_t e2fs_bcount; /* blocks count */ + u_int32_t e2fs_rbcount; /* reserved blocks count */ + u_int32_t e2fs_fbcount; /* free blocks count */ + u_int32_t e2fs_ficount; /* free inodes count */ + u_int32_t e2fs_first_dblock; /* first data block */ + u_int32_t e2fs_log_bsize; /* block size = 1024*(2^e2fs_log_bsize) */ + u_int32_t e2fs_log_fsize; /* fragment size */ + u_int32_t e2fs_bpg; /* blocks per group */ + u_int32_t e2fs_fpg; /* frags per group */ + u_int32_t e2fs_ipg; /* inodes per group */ + u_int32_t e2fs_mtime; /* mount time */ + u_int32_t e2fs_wtime; /* write time */ + u_int16_t e2fs_mnt_count; /* mount count */ + u_int16_t e2fs_max_mnt_count; /* max mount count */ + u_int16_t e2fs_magic; /* magic number */ + u_int16_t e2fs_state; /* file system state */ + u_int16_t e2fs_beh; /* behavior on errors */ + u_int16_t e2fs_minrev; /* minor revision level */ + u_int32_t e2fs_lastfsck; /* time of last fsck */ + u_int32_t e2fs_fsckintv; /* max time between fscks */ + u_int32_t e2fs_creator; /* creator OS */ + u_int32_t e2fs_rev; /* revision level */ + u_int16_t e2fs_ruid; /* default uid for reserved blocks */ + u_int16_t e2fs_rgid; /* default gid for reserved blocks */ + /* EXT2_DYNAMIC_REV superblocks */ + u_int32_t e2fs_first_ino; /* first non-reserved inode */ + u_int16_t e2fs_inode_size; /* size of inode structure */ + u_int16_t e2fs_block_group_nr; /* block grp number of this sblk*/ + u_int32_t e2fs_features_compat; /* compatible feature set */ + u_int32_t e2fs_features_incompat; /* incompatible feature set */ + u_int32_t e2fs_features_rocompat; /* RO-compatible feature set */ + u_int8_t e2fs_uuid[16]; /* 128-bit uuid for volume */ + char e2fs_vname[16]; /* volume name */ + char e2fs_fsmnt[64]; /* name mounted on */ + u_int32_t e2fs_algo; /* For comcate for dir */ + u_int16_t e2fs_reserved_ngdb; /* # of reserved gd blocks for resize */ + u_int32_t reserved2[204]; +}; + + +/* 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) + +/* + * In-Memory Superblock + */ + +struct m_ext2fs { + struct ext2fs * e2fs; + char e2fs_fsmnt[MAXMNTLEN];/* name mounted on */ + char e2fs_ronly; /* mounted read-only flag */ + char e2fs_fmod; /* super block modified flag */ + uint32_t e2fs_bsize; /* Block size */ + uint32_t e2fs_bshift; /* calc of logical block no */ + int32_t e2fs_bmask; /* calc of block offset */ + int32_t e2fs_bpg; /* Number of blocks per group */ + int64_t e2fs_qbmask; /* = s_blocksize -1 */ + uint32_t e2fs_fsbtodb; /* Shift to get disk block */ + uint32_t e2fs_ipg; /* Number of inodes per group */ + uint32_t e2fs_ipb; /* Number of inodes per block */ + uint32_t e2fs_itpg; /* Number of inode table per group */ + uint32_t e2fs_fsize; /* Size of fragments per block */ + uint32_t e2fs_fpb; /* Number of fragments per block */ + uint32_t e2fs_fpg; /* Number of fragments per group */ + uint32_t e2fs_dbpg; /* Number of descriptor blocks per group */ + uint32_t e2fs_descpb; /* Number of group descriptors per block */ + uint32_t e2fs_gdbcount; /* Number of group descriptors */ + uint32_t e2fs_gcount; /* Number of groups */ + uint32_t e2fs_first_inode;/* First inode on fs */ + int32_t e2fs_isize; /* Size of inode */ + uint32_t e2fs_mount_opt; + uint32_t e2fs_blocksize_bits; + uint32_t e2fs_total_dir; /* Total number of directories */ + uint8_t *e2fs_contigdirs; + char e2fs_wasvalid; /* valid at mount time */ + off_t e2fs_maxfilesize; + struct ext2_gd *e2fs_gd; /* Group Descriptors */ +}; + +/* + * The second extended file system version + */ +#define E2FS_DATE "95/08/09" +#define E2FS_VERSION "0.5b" + +/* + * Revision levels + */ +#define E2FS_REV0 0 /* The good old (original) format */ +#define E2FS_REV1 1 /* V2 format w/ dynamic inode sizes */ + +#define E2FS_CURRENT_REV E2FS_REV0 +#define E2FS_MAX_SUPP_REV E2FS_REV1 + +#define E2FS_REV0_INODE_SIZE 128 + +/* + * compatible/incompatible features + */ +#define EXT2F_COMPAT_PREALLOC 0x0001 +#define EXT2F_COMPAT_RESIZE 0x0010 + +#define EXT2F_ROCOMPAT_SPARSESUPER 0x0001 +#define EXT2F_ROCOMPAT_LARGEFILE 0x0002 +#define EXT2F_ROCOMPAT_BTREE_DIR 0x0004 + +#define EXT2F_INCOMPAT_COMP 0x0001 +#define EXT2F_INCOMPAT_FTYPE 0x0002 + +/* + * Features supported in this implementation + * + * We support the following REV1 features: + * - EXT2F_ROCOMPAT_SPARSESUPER + * - EXT2F_ROCOMPAT_LARGEFILE + * - EXT2F_INCOMPAT_FTYPE + */ +#define EXT2F_COMPAT_SUPP 0x0000 +#define EXT2F_ROCOMPAT_SUPP (EXT2F_ROCOMPAT_SPARSESUPER \ + | EXT2F_ROCOMPAT_LARGEFILE) +#define EXT2F_INCOMPAT_SUPP EXT2F_INCOMPAT_FTYPE + +/* + * Feature set definitions + */ +#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \ + ( EXT2_SB(sb)->e2fs->e2fs_features_compat & htole32(mask) ) +#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \ + ( EXT2_SB(sb)->e2fs->e2fs_features_rocompat & htole32(mask) ) +#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \ + ( EXT2_SB(sb)->e2fs->e2fs_features_incompat & htole32(mask) ) + +/* + * Definitions of behavior on errors + */ +#define E2FS_BEH_CONTINUE 1 /* continue operation */ +#define E2FS_BEH_READONLY 2 /* remount fs read only */ +#define E2FS_BEH_PANIC 3 /* cause panic */ +#define E2FS_BEH_DEFAULT E2FS_BEH_CONTINUE + +/* + * OS identification + */ +#define E2FS_OS_LINUX 0 +#define E2FS_OS_HURD 1 +#define E2FS_OS_MASIX 2 +#define E2FS_OS_FREEBSD 3 +#define E2FS_OS_LITES 4 + +/* + * File clean flags + */ +#define E2FS_ISCLEAN 0x0001 /* Unmounted cleanly */ +#define E2FS_ERRORS 0x0002 /* Errors detected */ + +/* ext2 file system block group descriptor */ + +struct ext2_gd { + u_int32_t ext2bgd_b_bitmap; /* blocks bitmap block */ + u_int32_t ext2bgd_i_bitmap; /* inodes bitmap block */ + u_int32_t ext2bgd_i_tables; /* inodes table block */ + u_int16_t ext2bgd_nbfree; /* number of free blocks */ + u_int16_t ext2bgd_nifree; /* number of free inodes */ + u_int16_t ext2bgd_ndirs; /* number of directories */ + u_int16_t reserved; + u_int32_t reserved2[3]; +}; + +/* EXT2FS metadatas are stored in little-endian byte order. These macros + * helps reading these metadatas + */ + +#define e2fs_cgload(old, new, size) memcpy((new), (old), (size)); +#define e2fs_cgsave(old, new, size) memcpy((new), (old), (size)); +/* + * 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) +# define EXT2_BLOCK_SIZE(s) ((s)->e2fs_bsize) +#else +# define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->e2fs_log_bsize) +#endif +#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (uint32_t)) +#if defined(_KERNEL) +# define EXT2_BLOCK_SIZE_BITS(s) ((s)->e2fs_blocksize_bits) +#else +# define EXT2_BLOCK_SIZE_BITS(s) ((s)->e2fs_log_bsize + 10) +#endif +#if defined(_KERNEL) +#define EXT2_ADDR_PER_BLOCK_BITS(s) (EXT2_SB(s)->s_addr_per_block_bits) +#define EXT2_INODE_SIZE(s) (EXT2_SB(s)->e2fs_isize) +#define EXT2_FIRST_INO(s) (EXT2_SB(s)->e2fs_first_inode) +#else +#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == E2FS_REV0) ? \ + E2FS_REV0 : (s)->s_inode_size) +#define EXT2_FIRST_INO(s) (((s)->s_rev_level == E2FS_REV0) ? \ + E2FS_REV0 : (s)->e2fs_first_ino) +#endif + +/* + * 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 +#if defined(_KERNEL) +# define EXT2_FRAG_SIZE(s) (EXT2_SB(s)->e2fs_fsize) +# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_SB(s)->e2fs_fpb) +#else +# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->e2fs_log_fsize) +# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s)) +#endif + +/* + * Macro-instructions used to manage group descriptors + */ +#if defined(_KERNEL) +# define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->e2fs_bpg) +# define EXT2_DESC_PER_BLOCK(s) (EXT2_SB(s)->e2fs_descpb) +# define EXT2_DESC_PER_BLOCK_BITS(s) (EXT2_SB(s)->s_desc_per_block_bits) +#else +# define EXT2_BLOCKS_PER_GROUP(s) ((s)->e2fs_bpg) +# define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_gd)) + +#endif + +#endif /* _LINUX_EXT2_FS_H */ diff --git a/sys/gnu/fs/ext2fs/fs.h b/sys/fs/ext2fs/fs.h index d9e70008a484..54c6b4408db5 100644 --- a/sys/gnu/fs/ext2fs/fs.h +++ b/sys/fs/ext2fs/fs.h @@ -57,45 +57,55 @@ /* * 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. + * the super block for this name. */ -#define MAXMNTLEN 512 +#define MAXMNTLEN 512 /* - * Macros for access to superblock array structures + * Grigoriy Orlov <gluk@ptci.ru> has done some extensive work to fine + * tune the layout preferences for directories within a filesystem. + * His algorithm can be tuned by adjusting the following parameters + * which tell the system the average file size and the average number + * of files per directory. These defaults are well selected for typical + * filesystems, but may need to be tuned for odd cases like filesystems + * being used for squid caches or news spools. + * AVFPDIR is the expected number of files per directory. AVGDIRSIZE is + * obtained by multiplying AVFPDIR and AVFILESIZ which is assumed to be + * 16384. */ +#define AFPDIR 64 +#define AVGDIRSIZE 1048576 + /* - * Convert cylinder group to base address of its global summary info. + * Macros for access to superblock array structures */ -#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)) +#define fsbtodb(fs, b) ((b) << ((fs)->e2fs_fsbtodb)) +#define dbtofsb(fs, b) ((b) >> ((fs)->e2fs_fsbtodb)) /* get group containing inode */ -#define ino_to_cg(fs, x) (((x) - 1) / EXT2_INODES_PER_GROUP(fs)) +#define ino_to_cg(fs, x) (((x) - 1) / (fs->e2fs_ipg)) /* 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) +#define ino_to_fsba(fs, x) \ + ((fs)->e2fs_gd[ino_to_cg((fs), (x))].ext2bgd_i_tables + \ + (((x) - 1) % (fs)->e2fs->e2fs_ipg) / (fs)->e2fs_ipb) /* get offset for inode in block */ -#define ino_to_fsbo(fs, x) ((x-1) % EXT2_INODES_PER_BLOCK(fs)) +#define ino_to_fsbo(fs, x) ((x-1) % (fs->e2fs_ipb)) /* * 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) / \ +#define dtog(fs, d) (((d) - fs->e2fs->e2fs_first_dblock) / \ EXT2_BLOCKS_PER_GROUP(fs)) -#define dtogd(fs, d) (((d) - fs->s_es->s_first_data_block) % \ +#define dtogd(fs, d) (((d) - fs->e2fs->e2fs_first_dblock) % \ EXT2_BLOCKS_PER_GROUP(fs)) /* @@ -104,32 +114,32 @@ * modulos and multiplications. */ #define blkoff(fs, loc) /* calculates (loc % fs->fs_bsize) */ \ - ((loc) & (fs)->s_qbmask) + ((loc) & (fs)->e2fs_qbmask) #define lblktosize(fs, blk) /* calculates (blk * fs->fs_bsize) */ \ - ((blk) << (fs->s_bshift)) + ((blk) << (fs->e2fs_bshift)) #define lblkno(fs, loc) /* calculates (loc / fs->fs_bsize) */ \ - ((loc) >> (fs->s_bshift)) + ((loc) >> (fs->e2fs_bshift)) /* no fragments -> logical block number equal # of frags */ #define numfrags(fs, loc) /* calculates (loc / fs->fs_fsize) */ \ - ((loc) >> (fs->s_bshift)) + ((loc) >> (fs->e2fs_bshift)) #define fragroundup(fs, size) /* calculates roundup(size, fs->fs_fsize) */ \ - roundup(size, fs->s_frag_size) + roundup(size, fs->e2fs_fsize) /* 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) +#define blksize(fs, ip, lbn) ((fs)->e2fs_fsize) /* * INOPB is the number of inodes in a secondary storage block. */ -#define INOPB(fs) EXT2_INODES_PER_BLOCK(fs) +#define INOPB(fs) (fs->e2fs_ipb) /* * NINDIR is the number of indirects in a file system block. @@ -139,32 +149,4 @@ 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) -#define unlock_super(devvp) VOP_UNLOCK(devvp, 0) -/* - * Historically, ext2fs kept it's metadata buffers on the LOCKED queue. Now, - * we change the lock owner to kern so that we may use it from contexts other - * than the one that originally locked it. When we are finished with the - * buffer, we release it, writing it first if it was dirty. - */ -#define LCK_BUF(bp) { \ - (bp)->b_flags |= B_PERSISTENT; \ - BUF_KERNPROC(bp); \ -} - -#define ULCK_BUF(bp) { \ - long flags; \ - flags = (bp)->b_flags; \ - (bp)->b_flags &= ~(B_DIRTY | B_PERSISTENT); \ - if (flags & B_DIRTY) \ - bwrite(bp); \ - else \ - brelse(bp); \ -} diff --git a/sys/gnu/fs/ext2fs/inode.h b/sys/fs/ext2fs/inode.h index 75d9b1b2cbaf..f352cdc161ad 100644 --- a/sys/gnu/fs/ext2fs/inode.h +++ b/sys/fs/ext2fs/inode.h @@ -35,8 +35,8 @@ * $FreeBSD$ */ -#ifndef _SYS_GNU_EXT2FS_INODE_H_ -#define _SYS_GNU_EXT2FS_INODE_H_ +#ifndef _FS_EXT2FS_INODE_H_ +#define _FS_EXT2FS_INODE_H_ #include <sys/lock.h> #include <sys/queue.h> @@ -63,10 +63,11 @@ struct inode { struct vnode *i_vnode;/* Vnode associated with this inode. */ struct vnode *i_devvp;/* Vnode for block I/O. */ + struct ext2mount *i_ump; u_int32_t i_flag; /* flags, see below */ ino_t i_number; /* The identity of the inode. */ - struct ext2_sb_info *i_e2fs; /* EXT2FS */ + struct m_ext2fs *i_e2fs; /* EXT2FS */ u_quad_t i_modrev; /* Revision level for NFS lease. */ /* * Side effects; used during directory lookup. @@ -75,8 +76,6 @@ struct inode { 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; @@ -142,7 +141,8 @@ struct inode { #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. */ - +#define IN_LAZYACCESS 0x0100 /* Process IN_ACCESS after the + suspension finished */ #ifdef _KERNEL /* * Structure used to pass around logical block paths generated by @@ -167,4 +167,4 @@ struct ufid { }; #endif /* _KERNEL */ -#endif /* !_SYS_GNU_EXT2FS_INODE_H_ */ +#endif /* !_FS_EXT2FS_INODE_H_ */ diff --git a/sys/gnu/fs/ext2fs/COPYRIGHT.INFO b/sys/gnu/fs/ext2fs/COPYRIGHT.INFO deleted file mode 100644 index 699f519c02a8..000000000000 --- a/sys/gnu/fs/ext2fs/COPYRIGHT.INFO +++ /dev/null @@ -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 - diff --git a/sys/gnu/fs/ext2fs/ext2_alloc.c b/sys/gnu/fs/ext2fs/ext2_alloc.c deleted file mode 100644 index 190a47264e57..000000000000 --- a/sys/gnu/fs/ext2fs/ext2_alloc.c +++ /dev/null @@ -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/fs/ext2fs/inode.h> -#include <gnu/fs/ext2fs/ext2_mount.h> -#include <gnu/fs/ext2fs/ext2_fs.h> -#include <gnu/fs/ext2fs/ext2_fs_sb.h> -#include <gnu/fs/ext2fs/fs.h> -#include <gnu/fs/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; -#ifdef 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; -#ifdef 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 { -#ifdef 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; -#ifdef 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); -} diff --git a/sys/gnu/fs/ext2fs/ext2_bitops.h b/sys/gnu/fs/ext2fs/ext2_bitops.h deleted file mode 100644 index c01150fea761..000000000000 --- a/sys/gnu/fs/ext2fs/ext2_bitops.h +++ /dev/null @@ -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 & ~31U) - 1); - p++; - ofs = (ofs + 31U) & ~31U; - } - while(ofs < sz && *p == ~0U) { - 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_ */ diff --git a/sys/gnu/fs/ext2fs/ext2_fs.h b/sys/gnu/fs/ext2fs/ext2_fs.h deleted file mode 100644 index 8a4081e5f915..000000000000 --- a/sys/gnu/fs/ext2fs/ext2_fs.h +++ /dev/null @@ -1,556 +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 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#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 - -#define cpu_to_le32(x) htole32(x) - -/* - * 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 inode numbers - */ -#define EXT2_BAD_INO 1 /* Bad blocks inode */ -#define EXT2_ROOT_INO 2 /* Root 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 - -#ifdef __KERNEL__ -#include <linux/ext2_fs_sb.h> -static inline struct ext2_sb_info *EXT2_SB(struct super_block *sb) -{ - return sb->s_fs_info; -} -#elif defined(_KERNEL) -/* - * FreeBSD passes the pointer to the in-core struct with relevant - * fields to EXT2_SB macro when accessing superblock fields. - */ -#define EXT2_SB(sb) (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 - -/* - * Maximal count of links to a file - */ -#define EXT2_LINK_MAX 32000 - -/* - * 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(_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_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32)) -#if defined(__KERNEL__) || defined(_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 -#if defined(__KERNEL__) || defined(_KERNEL) -#define EXT2_ADDR_PER_BLOCK_BITS(s) (EXT2_SB(s)->s_addr_per_block_bits) -#define EXT2_INODE_SIZE(s) (EXT2_SB(s)->s_inode_size) -#define EXT2_FIRST_INO(s) (EXT2_SB(s)->s_first_ino) -#define EXT2_INODES_PER_BLOCK(s) ((s)->s_inodes_per_block) -#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 - -/* - * 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 -#if defined(__KERNEL__) || defined(_KERNEL) -# define EXT2_FRAG_SIZE(s) (EXT2_SB(s)->s_frag_size) -# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_SB(s)->s_frags_per_block) -#else -# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size) -# 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 - */ -#if defined(__KERNEL__) || defined(_KERNEL) -# define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->s_blocks_per_group) -# define EXT2_DESC_PER_BLOCK(s) (EXT2_SB(s)->s_desc_per_block) -# define EXT2_INODES_PER_GROUP(s) (EXT2_SB(s)->s_inodes_per_group) -# define EXT2_DESC_PER_BLOCK_BITS(s) (EXT2_SB(s)->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) (EXT2_SB(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 */ -}; - -/* - * 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_es->s_feature_compat & cpu_to_le32(mask) ) -#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \ - ( EXT2_SB(sb)->s_es->s_feature_ro_compat & cpu_to_le32(mask) ) -#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \ - ( EXT2_SB(sb)->s_es->s_feature_incompat & cpu_to_le32(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 */ diff --git a/sys/gnu/fs/ext2fs/ext2_fs_sb.h b/sys/gnu/fs/ext2fs/ext2_fs_sb.h deleted file mode 100644 index 2e3d78f1bc05..000000000000 --- a/sys/gnu/fs/ext2fs/ext2_fs_sb.h +++ /dev/null @@ -1,100 +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 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#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_gdb_count; /* Number of group descriptor blocks */ - 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]; - unsigned long s_mount_opt; -#ifdef notyet - uid_t s_resuid; - gid_t s_resgid; -#endif - unsigned short s_inode_size; - unsigned int s_first_ino; - 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 */ diff --git a/sys/gnu/fs/ext2fs/ext2_linux_balloc.c b/sys/gnu/fs/ext2fs/ext2_linux_balloc.c deleted file mode 100644 index 2c9a6dabf205..000000000000 --- a/sys/gnu/fs/ext2fs/ext2_linux_balloc.c +++ /dev/null @@ -1,624 +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 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License.. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* - * 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/fs/ext2fs/inode.h> -#include <gnu/fs/ext2fs/ext2_mount.h> -#include <gnu/fs/ext2fs/ext2_extern.h> -#include <gnu/fs/ext2fs/ext2_fs.h> -#include <gnu/fs/ext2fs/ext2_fs_sb.h> -#include <gnu/fs/ext2fs/fs.h> - -#ifdef __i386__ -#include <gnu/fs/ext2fs/i386-bitops.h> -#else -#include <gnu/fs/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); -} diff --git a/sys/gnu/fs/ext2fs/ext2_linux_ialloc.c b/sys/gnu/fs/ext2fs/ext2_linux_ialloc.c deleted file mode 100644 index b3263b46ec9d..000000000000 --- a/sys/gnu/fs/ext2fs/ext2_linux_ialloc.c +++ /dev/null @@ -1,526 +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 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* - * 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/fs/ext2fs/inode.h> -#include <gnu/fs/ext2fs/ext2_mount.h> -#include <gnu/fs/ext2fs/ext2_extern.h> -#include <gnu/fs/ext2fs/ext2_fs.h> -#include <gnu/fs/ext2fs/ext2_fs_sb.h> -#include <gnu/fs/ext2fs/fs.h> -#include <sys/stat.h> - -#ifdef __i386__ -#include <gnu/fs/ext2fs/i386-bitops.h> -#else -#include <gnu/fs/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(sb) || - 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)); -} - -#ifdef 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(sb) || 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 diff --git a/sys/gnu/fs/ext2fs/i386-bitops.h b/sys/gnu/fs/ext2fs/i386-bitops.h deleted file mode 100644 index 001c51db7fb9..000000000000 --- a/sys/gnu/fs/ext2fs/i386-bitops.h +++ /dev/null @@ -1,175 +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 - */ -/*- - * Copyright 1992, Linus Torvalds. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -#ifndef _SYS_GNU_EXT2FS_I386_BITOPS_H_ -#define _SYS_GNU_EXT2FS_I386_BITOPS_H_ - -/* - * 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_ */ diff --git a/sys/gnu/fs/reiserfs/reiserfs_fs.h b/sys/gnu/fs/reiserfs/reiserfs_fs.h index 3c41563ab0af..5ad021ba4b5e 100644 --- a/sys/gnu/fs/reiserfs/reiserfs_fs.h +++ b/sys/gnu/fs/reiserfs/reiserfs_fs.h @@ -728,15 +728,16 @@ struct stat_data_v1 { * We want common flags to have the same values as in ext2, * so chattr(1) will work without problems */ -#include <gnu/fs/ext2fs/ext2_fs.h> -#define REISERFS_IMMUTABLE_FL EXT2_IMMUTABLE_FL -#define REISERFS_APPEND_FL EXT2_APPEND_FL -#define REISERFS_SYNC_FL EXT2_SYNC_FL -#define REISERFS_NOATIME_FL EXT2_NOATIME_FL -#define REISERFS_NODUMP_FL EXT2_NODUMP_FL -#define REISERFS_SECRM_FL EXT2_SECRM_FL -#define REISERFS_UNRM_FL EXT2_UNRM_FL -#define REISERFS_COMPR_FL EXT2_COMPR_FL +#include <fs/ext2fs/ext2fs.h> +#include <fs/ext2fs/ext2_dinode.h> +#define REISERFS_IMMUTABLE_FL EXT2_IMMUTABLE +#define REISERFS_APPEND_FL EXT2_APPEND +#define REISERFS_SYNC_FL EXT2_SYNC +#define REISERFS_NOATIME_FL EXT2_NOATIME +#define REISERFS_NODUMP_FL EXT2_NODUMP +#define REISERFS_SECRM_FL EXT2_SECRM +#define REISERFS_UNRM_FL EXT2_UNRM +#define REISERFS_COMPR_FL EXT2_COMPR #define REISERFS_NOTAIL_FL EXT2_NOTAIL_FL /* diff --git a/sys/modules/ext2fs/Makefile b/sys/modules/ext2fs/Makefile index 1ce8ab87aa28..d9ab969d4dad 100644 --- a/sys/modules/ext2fs/Makefile +++ b/sys/modules/ext2fs/Makefile @@ -1,10 +1,10 @@ # $FreeBSD$ -.PATH: ${.CURDIR}/../../gnu/fs/ext2fs +.PATH: ${.CURDIR}/../../fs/ext2fs KMOD= ext2fs SRCS= opt_ddb.h opt_quota.h opt_suiddir.h vnode_if.h \ ext2_alloc.c ext2_balloc.c ext2_bmap.c ext2_inode.c \ - ext2_inode_cnv.c ext2_linux_balloc.c ext2_linux_ialloc.c \ - ext2_lookup.c ext2_subr.c ext2_vfsops.c ext2_vnops.c + ext2_inode_cnv.c ext2_lookup.c ext2_subr.c ext2_vfsops.c \ + ext2_vnops.c .include <bsd.kmod.mk> |