summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/conf/files21
-rw-r--r--sys/fs/ext2fs/ext2_alloc.c973
-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-xsys/fs/ext2fs/ext2_dinode.h78
-rwxr-xr-xsys/fs/ext2fs/ext2_dir.h81
-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-xsys/fs/ext2fs/ext2fs.h329
-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.INFO35
-rw-r--r--sys/gnu/fs/ext2fs/ext2_alloc.c535
-rw-r--r--sys/gnu/fs/ext2fs/ext2_bitops.h114
-rw-r--r--sys/gnu/fs/ext2fs/ext2_fs.h556
-rw-r--r--sys/gnu/fs/ext2fs/ext2_fs_sb.h100
-rw-r--r--sys/gnu/fs/ext2fs/ext2_linux_balloc.c624
-rw-r--r--sys/gnu/fs/ext2fs/ext2_linux_ialloc.c526
-rw-r--r--sys/gnu/fs/ext2fs/i386-bitops.h175
-rw-r--r--sys/gnu/fs/reiserfs/reiserfs_fs.h19
-rw-r--r--sys/modules/ext2fs/Makefile6
28 files changed, 2155 insertions, 3393 deletions
diff --git a/sys/conf/files b/sys/conf/files
index 71a8e53..7be1676 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 0000000..1095100
--- /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 e46414c..124ac32 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 85cfbf9..c742188 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 0000000..3e45060
--- /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 0000000..0676268
--- /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 24c8f45..60905cb 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 0a62c30..2cf60a7 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 412a47cc..b042a5a 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 6ab41e5..56963b2 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 6be0c7d..6bc051c 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 e533392..9c9749a 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 5617842..dcb1b7c 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 20c44ef..7690bb8 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 6b44b9b..6b0d371 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 0000000..2efc57f
--- /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 d9e7000..54c6b44 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 75d9b1b..f352cdc1 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 699f519..0000000
--- 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 190a472..0000000
--- 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 c01150f..0000000
--- 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 8a4081e..0000000
--- 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 2e3d78f..0000000
--- 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 2c9a6da..0000000
--- 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 b3263b4..0000000
--- 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 001c51d..0000000
--- 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 3c41563..5ad021b 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 1ce8ab8..d9ab969 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>
OpenPOWER on IntegriCloud