summaryrefslogtreecommitdiffstats
path: root/sys/gnu/fs
diff options
context:
space:
mode:
authorlulf <lulf@FreeBSD.org>2010-01-14 14:30:54 +0000
committerlulf <lulf@FreeBSD.org>2010-01-14 14:30:54 +0000
commit8ab7715033ec4b66ff6203f772f2a4b430e2b6e6 (patch)
treefef80ad74c782758cf935f5ae7b6be070319042e /sys/gnu/fs
parentcee9e919b513999007f8f66c6581fa31174b4fb9 (diff)
downloadFreeBSD-src-8ab7715033ec4b66ff6203f772f2a4b430e2b6e6.zip
FreeBSD-src-8ab7715033ec4b66ff6203f772f2a4b430e2b6e6.tar.gz
Bring in the ext2fs work done by Aditya Sarawgi during and after Google Summer
of Code 2009: - BSDL block and inode allocation policies for ext2fs. This involves the use FFS1 style block and inode allocation for ext2fs. Preallocation was removed since it was GPL'd. - Make ext2fs MPSAFE by introducing locks to per-mount datastructures. - Fixes for kern/122047 PR. - Various small bugfixes. - Move out of gnu/ directory. Sponsored by: Google Inc. Submitted by: Aditya Sarawgi <sarawgi.aditya AT SPAMFREE gmail DOT com>
Diffstat (limited to 'sys/gnu/fs')
-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_balloc.c310
-rw-r--r--sys/gnu/fs/ext2fs/ext2_bitops.h114
-rw-r--r--sys/gnu/fs/ext2fs/ext2_bmap.c335
-rw-r--r--sys/gnu/fs/ext2fs/ext2_extern.h104
-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_inode.c528
-rw-r--r--sys/gnu/fs/ext2fs/ext2_inode_cnv.c137
-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/ext2_lookup.c1082
-rw-r--r--sys/gnu/fs/ext2fs/ext2_mount.h73
-rw-r--r--sys/gnu/fs/ext2fs/ext2_readwrite.c304
-rw-r--r--sys/gnu/fs/ext2fs/ext2_subr.c120
-rw-r--r--sys/gnu/fs/ext2fs/ext2_vfsops.c1122
-rw-r--r--sys/gnu/fs/ext2fs/ext2_vnops.c1649
-rw-r--r--sys/gnu/fs/ext2fs/fs.h170
-rw-r--r--sys/gnu/fs/ext2fs/i386-bitops.h175
-rw-r--r--sys/gnu/fs/ext2fs/inode.h170
-rw-r--r--sys/gnu/fs/reiserfs/reiserfs_fs.h19
22 files changed, 10 insertions, 8778 deletions
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_balloc.c b/sys/gnu/fs/ext2fs/ext2_balloc.c
deleted file mode 100644
index e46414c..0000000
--- a/sys/gnu/fs/ext2fs/ext2_balloc.c
+++ /dev/null
@@ -1,310 +0,0 @@
-/*-
- * modified for Lites 1.1
- *
- * Aug 1995, Godmar Back (gback@cs.utah.edu)
- * University of Utah, Department of Computer Science
- */
-/*-
- * Copyright (c) 1982, 1986, 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)ffs_balloc.c 8.4 (Berkeley) 9/23/93
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-#include <sys/lock.h>
-#include <sys/ucred.h>
-#include <sys/vnode.h>
-
-#include <gnu/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>
-
-/*
- * Balloc defines the structure of file system storage
- * by allocating the physical blocks on a device given
- * the inode and the logical block number in a file.
- */
-int
-ext2_balloc(ip, bn, size, cred, bpp, flags)
- struct inode *ip;
- int32_t bn;
- int size;
- struct ucred *cred;
- struct buf **bpp;
- int flags;
-{
- struct ext2_sb_info *fs;
- int32_t nb;
- struct buf *bp, *nbp;
- struct vnode *vp = ITOV(ip);
- struct indir indirs[NIADDR + 2];
- int32_t newb, lbn, *bap, pref;
- int osize, nsize, num, i, error;
-/*
-ext2_debug("ext2_balloc called (%d, %d, %d)\n",
- ip->i_number, (int)bn, (int)size);
-*/
- *bpp = NULL;
- if (bn < 0)
- return (EFBIG);
- fs = ip->i_e2fs;
- lbn = bn;
-
- /*
- * check if this is a sequential block allocation.
- * If so, increment next_alloc fields to allow ext2_blkpref
- * to make a good guess
- */
- if (lbn == ip->i_next_alloc_block + 1) {
- ip->i_next_alloc_block++;
- ip->i_next_alloc_goal++;
- }
-
- /*
- * The first NDADDR blocks are direct blocks
- */
- if (bn < NDADDR) {
- nb = ip->i_db[bn];
- /* no new block is to be allocated, and no need to expand
- the file */
- if (nb != 0 && ip->i_size >= (bn + 1) * fs->s_blocksize) {
- error = bread(vp, bn, fs->s_blocksize, NOCRED, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- bp->b_blkno = fsbtodb(fs, nb);
- *bpp = bp;
- return (0);
- }
- if (nb != 0) {
- /*
- * Consider need to reallocate a fragment.
- */
- osize = fragroundup(fs, blkoff(fs, ip->i_size));
- nsize = fragroundup(fs, size);
- if (nsize <= osize) {
- error = bread(vp, bn, osize, NOCRED, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- bp->b_blkno = fsbtodb(fs, nb);
- } else {
- /* Godmar thinks: this shouldn't happen w/o fragments */
- printf("nsize %d(%d) > osize %d(%d) nb %d\n",
- (int)nsize, (int)size, (int)osize,
- (int)ip->i_size, (int)nb);
- panic(
- "ext2_balloc: Something is terribly wrong");
-/*
- * please note there haven't been any changes from here on -
- * FFS seems to work.
- */
- }
- } else {
- if (ip->i_size < (bn + 1) * fs->s_blocksize)
- nsize = fragroundup(fs, size);
- else
- nsize = fs->s_blocksize;
- error = ext2_alloc(ip, bn,
- ext2_blkpref(ip, bn, (int)bn, &ip->i_db[0], 0),
- nsize, cred, &newb);
- if (error)
- return (error);
- bp = getblk(vp, bn, nsize, 0, 0, 0);
- bp->b_blkno = fsbtodb(fs, newb);
- if (flags & B_CLRBUF)
- vfs_bio_clrbuf(bp);
- }
- ip->i_db[bn] = dbtofsb(fs, bp->b_blkno);
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
- *bpp = bp;
- return (0);
- }
- /*
- * Determine the number of levels of indirection.
- */
- pref = 0;
- if ((error = ext2_getlbns(vp, bn, indirs, &num)) != 0)
- return(error);
-#ifdef DIAGNOSTIC
- if (num < 1)
- panic ("ext2_balloc: ext2_getlbns returned indirect block");
-#endif
- /*
- * Fetch the first indirect block allocating if necessary.
- */
- --num;
- nb = ip->i_ib[indirs[0].in_off];
- if (nb == 0) {
-#if 0
- pref = ext2_blkpref(ip, lbn, 0, (int32_t *)0, 0);
-#else
- /* see the comment by ext2_blkpref. What we do here is
- to pretend that it'd be good for a block holding indirect
- pointers to be allocated near its predecessor in terms
- of indirection, or the last direct block.
- We shamelessly exploit the fact that i_ib immediately
- follows i_db.
- Godmar thinks it make sense to allocate i_ib[0] immediately
- after i_db[11], but it's not utterly clear whether this also
- applies to i_ib[1] and i_ib[0]
- */
-
- pref = ext2_blkpref(ip, lbn, indirs[0].in_off +
- EXT2_NDIR_BLOCKS, &ip->i_db[0], 0);
-#endif
- if ((error = ext2_alloc(ip, lbn, pref, (int)fs->s_blocksize,
- cred, &newb)) != 0)
- return (error);
- nb = newb;
- bp = getblk(vp, indirs[1].in_lbn, fs->s_blocksize, 0, 0, 0);
- bp->b_blkno = fsbtodb(fs, newb);
- vfs_bio_clrbuf(bp);
- /*
- * Write synchronously so that indirect blocks
- * never point at garbage.
- */
- if ((error = bwrite(bp)) != 0) {
- ext2_blkfree(ip, nb, fs->s_blocksize);
- return (error);
- }
- ip->i_ib[indirs[0].in_off] = newb;
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
- }
- /*
- * Fetch through the indirect blocks, allocating as necessary.
- */
- for (i = 1;;) {
- error = bread(vp,
- indirs[i].in_lbn, (int)fs->s_blocksize, NOCRED, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- bap = (int32_t *)bp->b_data;
- nb = bap[indirs[i].in_off];
- if (i == num)
- break;
- i += 1;
- if (nb != 0) {
- brelse(bp);
- continue;
- }
- if (pref == 0)
-#if 1
- /* see the comment above and by ext2_blkpref
- * I think this implements Linux policy, but
- * does it really make sense to allocate to
- * block containing pointers together ?
- * Also, will it ever succeed ?
- */
- pref = ext2_blkpref(ip, lbn, indirs[i].in_off, bap,
- bp->b_lblkno);
-#else
- pref = ext2_blkpref(ip, lbn, 0, (int32_t *)0, 0);
-#endif
- if ((error =
- ext2_alloc(ip, lbn, pref, (int)fs->s_blocksize, cred, &newb)) != 0) {
- brelse(bp);
- return (error);
- }
- nb = newb;
- nbp = getblk(vp, indirs[i].in_lbn, fs->s_blocksize, 0, 0, 0);
- nbp->b_blkno = fsbtodb(fs, nb);
- vfs_bio_clrbuf(nbp);
- /*
- * Write synchronously so that indirect blocks
- * never point at garbage.
- */
- if ((error = bwrite(nbp)) != 0) {
- ext2_blkfree(ip, nb, fs->s_blocksize);
- brelse(bp);
- return (error);
- }
- bap[indirs[i - 1].in_off] = nb;
- /*
- * If required, write synchronously, otherwise use
- * delayed write.
- */
- if (flags & B_SYNC) {
- bwrite(bp);
- } else {
- bdwrite(bp);
- }
- }
- /*
- * Get the data block, allocating if necessary.
- */
- if (nb == 0) {
- pref = ext2_blkpref(ip, lbn, indirs[i].in_off, &bap[0],
- bp->b_lblkno);
- if ((error = ext2_alloc(ip,
- lbn, pref, (int)fs->s_blocksize, cred, &newb)) != 0) {
- brelse(bp);
- return (error);
- }
- nb = newb;
- nbp = getblk(vp, lbn, fs->s_blocksize, 0, 0, 0);
- nbp->b_blkno = fsbtodb(fs, nb);
- if (flags & B_CLRBUF)
- vfs_bio_clrbuf(nbp);
- bap[indirs[i].in_off] = nb;
- /*
- * If required, write synchronously, otherwise use
- * delayed write.
- */
- if (flags & B_SYNC) {
- bwrite(bp);
- } else {
- bdwrite(bp);
- }
- *bpp = nbp;
- return (0);
- }
- brelse(bp);
- if (flags & B_CLRBUF) {
- error = bread(vp, lbn, (int)fs->s_blocksize, NOCRED, &nbp);
- if (error) {
- brelse(nbp);
- return (error);
- }
- } else {
- nbp = getblk(vp, lbn, fs->s_blocksize, 0, 0, 0);
- nbp->b_blkno = fsbtodb(fs, nb);
- }
- *bpp = nbp;
- return (0);
-}
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_bmap.c b/sys/gnu/fs/ext2fs/ext2_bmap.c
deleted file mode 100644
index 85cfbf9..0000000
--- a/sys/gnu/fs/ext2fs/ext2_bmap.c
+++ /dev/null
@@ -1,335 +0,0 @@
-/*-
- * Copyright (c) 1989, 1991, 1993
- * The Regents of the University of California. All rights reserved.
- * (c) UNIX System Laboratories, Inc.
- * All or some portions of this file are derived from material licensed
- * to the University of California by American Telephone and Telegraph
- * Co. or Unix System Laboratories, Inc. and are reproduced herein with
- * the permission of UNIX System Laboratories, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)ufs_bmap.c 8.7 (Berkeley) 3/21/95
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-#include <sys/proc.h>
-#include <sys/vnode.h>
-#include <sys/mount.h>
-#include <sys/resourcevar.h>
-#include <sys/stat.h>
-
-#include <gnu/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>
-
-/*
- * Bmap converts a the logical block number of a file to its physical block
- * number on the disk. The conversion is done by using the logical block
- * number to index into the array of block pointers described by the dinode.
- */
-int
-ext2_bmap(ap)
- struct vop_bmap_args /* {
- struct vnode *a_vp;
- daddr_t a_bn;
- struct bufobj **a_bop;
- daddr_t *a_bnp;
- int *a_runp;
- int *a_runb;
- } */ *ap;
-{
- int32_t blkno;
- int error;
-
- /*
- * Check for underlying vnode requests and ensure that logical
- * to physical mapping is requested.
- */
- if (ap->a_bop != NULL)
- *ap->a_bop = &VTOI(ap->a_vp)->i_devvp->v_bufobj;
- if (ap->a_bnp == NULL)
- return (0);
-
- error = ext2_bmaparray(ap->a_vp, ap->a_bn, &blkno,
- ap->a_runp, ap->a_runb);
- *ap->a_bnp = blkno;
- return (error);
-}
-
-/*
- * Indirect blocks are now on the vnode for the file. They are given negative
- * logical block numbers. Indirect blocks are addressed by the negative
- * address of the first data block to which they point. Double indirect blocks
- * are addressed by one less than the address of the first indirect block to
- * which they point. Triple indirect blocks are addressed by one less than
- * the address of the first double indirect block to which they point.
- *
- * ufs_bmaparray does the bmap conversion, and if requested returns the
- * array of logical blocks which must be traversed to get to a block.
- * Each entry contains the offset into that block that gets you to the
- * next block and the disk address of the block (if it is assigned).
- */
-
-int
-ext2_bmaparray(vp, bn, bnp, runp, runb)
- struct vnode *vp;
- int32_t bn;
- int32_t *bnp;
- int *runp;
- int *runb;
-{
- struct inode *ip;
- struct buf *bp;
- struct ext2mount *ump;
- struct mount *mp;
- struct vnode *devvp;
- struct indir a[NIADDR+1], *ap;
- int32_t daddr;
- long metalbn;
- int error, num, maxrun = 0, bsize;
- int *nump;
-
- ap = NULL;
- ip = VTOI(vp);
- mp = vp->v_mount;
- ump = VFSTOEXT2(mp);
- devvp = ump->um_devvp;
-
- bsize = EXT2_BLOCK_SIZE(ump->um_e2fs);
-
- if (runp) {
- maxrun = mp->mnt_iosize_max / bsize - 1;
- *runp = 0;
- }
-
- if (runb) {
- *runb = 0;
- }
-
-
- ap = a;
- nump = &num;
- error = ext2_getlbns(vp, bn, ap, nump);
- if (error)
- return (error);
-
- num = *nump;
- if (num == 0) {
- *bnp = blkptrtodb(ump, ip->i_db[bn]);
- if (*bnp == 0) {
- *bnp = -1;
- } else if (runp) {
- int32_t bnb = bn;
- for (++bn; bn < NDADDR && *runp < maxrun &&
- is_sequential(ump, ip->i_db[bn - 1], ip->i_db[bn]);
- ++bn, ++*runp);
- bn = bnb;
- if (runb && (bn > 0)) {
- for (--bn; (bn >= 0) && (*runb < maxrun) &&
- is_sequential(ump, ip->i_db[bn],
- ip->i_db[bn+1]);
- --bn, ++*runb);
- }
- }
- return (0);
- }
-
-
- /* Get disk address out of indirect block array */
- daddr = ip->i_ib[ap->in_off];
-
- for (bp = NULL, ++ap; --num; ++ap) {
- /*
- * Exit the loop if there is no disk address assigned yet and
- * the indirect block isn't in the cache, or if we were
- * looking for an indirect block and we've found it.
- */
-
- metalbn = ap->in_lbn;
- if ((daddr == 0 && !incore(&vp->v_bufobj, metalbn)) || metalbn == bn)
- break;
- /*
- * If we get here, we've either got the block in the cache
- * or we have a disk address for it, go fetch it.
- */
- if (bp)
- bqrelse(bp);
-
- ap->in_exists = 1;
- bp = getblk(vp, metalbn, bsize, 0, 0, 0);
- if ((bp->b_flags & B_CACHE) == 0) {
-#ifdef DIAGNOSTIC
- if (!daddr)
- panic("ufs_bmaparray: indirect block not in cache");
-#endif
- bp->b_blkno = blkptrtodb(ump, daddr);
- bp->b_iocmd = BIO_READ;
- bp->b_flags &= ~B_INVAL;
- bp->b_ioflags &= ~BIO_ERROR;
- vfs_busy_pages(bp, 0);
- bp->b_iooffset = dbtob(bp->b_blkno);
- bstrategy(bp);
- curthread->td_ru.ru_inblock++;
- error = bufwait(bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- }
-
- daddr = ((int32_t *)bp->b_data)[ap->in_off];
- if (num == 1 && daddr && runp) {
- for (bn = ap->in_off + 1;
- bn < MNINDIR(ump) && *runp < maxrun &&
- is_sequential(ump,
- ((int32_t *)bp->b_data)[bn - 1],
- ((int32_t *)bp->b_data)[bn]);
- ++bn, ++*runp);
- bn = ap->in_off;
- if (runb && bn) {
- for(--bn; bn >= 0 && *runb < maxrun &&
- is_sequential(ump, ((int32_t *)bp->b_data)[bn],
- ((int32_t *)bp->b_data)[bn+1]);
- --bn, ++*runb);
- }
- }
- }
- if (bp)
- bqrelse(bp);
-
- /*
- * Since this is FFS independent code, we are out of scope for the
- * definitions of BLK_NOCOPY and BLK_SNAP, but we do know that they
- * will fall in the range 1..um_seqinc, so we use that test and
- * return a request for a zeroed out buffer if attempts are made
- * to read a BLK_NOCOPY or BLK_SNAP block.
- */
- if ((ip->i_flags & SF_SNAPSHOT) && daddr > 0 && daddr < ump->um_seqinc){
- *bnp = -1;
- return (0);
- }
- *bnp = blkptrtodb(ump, daddr);
- if (*bnp == 0) {
- *bnp = -1;
- }
- return (0);
-}
-
-/*
- * Create an array of logical block number/offset pairs which represent the
- * path of indirect blocks required to access a data block. The first "pair"
- * contains the logical block number of the appropriate single, double or
- * triple indirect block and the offset into the inode indirect block array.
- * Note, the logical block number of the inode single/double/triple indirect
- * block appears twice in the array, once with the offset into the i_ib and
- * once with the offset into the page itself.
- */
-int
-ext2_getlbns(vp, bn, ap, nump)
- struct vnode *vp;
- int32_t bn;
- struct indir *ap;
- int *nump;
-{
- long blockcnt, metalbn, realbn;
- struct ext2mount *ump;
- int i, numlevels, off;
- int64_t qblockcnt;
-
- ump = VFSTOEXT2(vp->v_mount);
- if (nump)
- *nump = 0;
- numlevels = 0;
- realbn = bn;
- if ((long)bn < 0)
- bn = -(long)bn;
-
- /* The first NDADDR blocks are direct blocks. */
- if (bn < NDADDR)
- return (0);
-
- /*
- * Determine the number of levels of indirection. After this loop
- * is done, blockcnt indicates the number of data blocks possible
- * at the previous level of indirection, and NIADDR - i is the number
- * of levels of indirection needed to locate the requested block.
- */
- for (blockcnt = 1, i = NIADDR, bn -= NDADDR;; i--, bn -= blockcnt) {
- if (i == 0)
- return (EFBIG);
- /*
- * Use int64_t's here to avoid overflow for triple indirect
- * blocks when longs have 32 bits and the block size is more
- * than 4K.
- */
- qblockcnt = (int64_t)blockcnt * MNINDIR(ump);
- if (bn < qblockcnt)
- break;
- blockcnt = qblockcnt;
- }
-
- /* Calculate the address of the first meta-block. */
- if (realbn >= 0)
- metalbn = -(realbn - bn + NIADDR - i);
- else
- metalbn = -(-realbn - bn + NIADDR - i);
-
- /*
- * At each iteration, off is the offset into the bap array which is
- * an array of disk addresses at the current level of indirection.
- * The logical block number and the offset in that block are stored
- * into the argument array.
- */
- ap->in_lbn = metalbn;
- ap->in_off = off = NIADDR - i;
- ap->in_exists = 0;
- ap++;
- for (++numlevels; i <= NIADDR; i++) {
- /* If searching for a meta-data block, quit when found. */
- if (metalbn == realbn)
- break;
-
- off = (bn / blockcnt) % MNINDIR(ump);
-
- ++numlevels;
- ap->in_lbn = metalbn;
- ap->in_off = off;
- ap->in_exists = 0;
- ++ap;
-
- metalbn -= -1 + off * blockcnt;
- blockcnt /= MNINDIR(ump);
- }
- if (nump)
- *nump = numlevels;
- return (0);
-}
diff --git a/sys/gnu/fs/ext2fs/ext2_extern.h b/sys/gnu/fs/ext2fs/ext2_extern.h
deleted file mode 100644
index 24c8f45..0000000
--- a/sys/gnu/fs/ext2fs/ext2_extern.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*-
- * modified for EXT2FS support in Lites 1.1
- *
- * Aug 1995, Godmar Back (gback@cs.utah.edu)
- * University of Utah, Department of Computer Science
- */
-/*-
- * Copyright (c) 1991, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)ffs_extern.h 8.3 (Berkeley) 4/16/94
- * $FreeBSD$
- */
-
-#ifndef _SYS_GNU_EXT2FS_EXT2_EXTERN_H_
-#define _SYS_GNU_EXT2FS_EXT2_EXTERN_H_
-
-struct ext2_inode;
-struct indir;
-struct inode;
-struct mount;
-struct vfsconf;
-struct vnode;
-
-int ext2_alloc(struct inode *,
- int32_t, int32_t, int, struct ucred *, int32_t *);
-int ext2_balloc(struct inode *,
- int32_t, int, struct ucred *, struct buf **, int);
-int ext2_blkatoff(struct vnode *, off_t, char **, struct buf **);
-void ext2_blkfree(struct inode *, int32_t, long);
-int32_t ext2_blkpref(struct inode *, int32_t, int, int32_t *, int32_t);
-int ext2_bmap(struct vop_bmap_args *);
-int ext2_bmaparray(struct vnode *, int32_t, int32_t *, int *, int *);
-void ext2_dirbad(struct inode *ip, doff_t offset, char *how);
-void ext2_ei2i(struct ext2_inode *, struct inode *);
-int ext2_getlbns(struct vnode *, int32_t, struct indir *, int *);
-void ext2_i2ei(struct inode *, struct ext2_inode *);
-void ext2_itimes(struct vnode *vp);
-int ext2_reallocblks(struct vop_reallocblks_args *);
-int ext2_reclaim(struct vop_reclaim_args *);
-void ext2_setblock(struct ext2_sb_info *, u_char *, int32_t);
-int ext2_truncate(struct vnode *, off_t, int, struct ucred *, struct thread *);
-int ext2_update(struct vnode *, int);
-int ext2_valloc(struct vnode *, int, struct ucred *, struct vnode **);
-int ext2_vfree(struct vnode *, ino_t, int);
-int ext2_vinit(struct mount *, struct vop_vector *, struct vnode **vpp);
-int ext2_lookup(struct vop_cachedlookup_args *);
-int ext2_readdir(struct vop_readdir_args *);
-void ext2_print_inode(struct inode *);
-int ext2_direnter(struct inode *,
- struct vnode *, struct componentname *);
-int ext2_dirremove(struct vnode *, struct componentname *);
-int ext2_dirrewrite(struct inode *,
- struct inode *, struct componentname *);
-int ext2_dirempty(struct inode *, ino_t, struct ucred *);
-int ext2_checkpath(struct inode *, struct inode *, struct ucred *);
-struct ext2_group_desc * get_group_desc(struct mount * ,
- unsigned int , struct buf ** );
-int ext2_group_sparse(int group);
-void ext2_discard_prealloc(struct inode *);
-int ext2_inactive(struct vop_inactive_args *);
-int ext2_new_block(struct mount * mp, unsigned long goal,
- u_int32_t *prealloc_count, u_int32_t *prealloc_block);
-ino_t ext2_new_inode(const struct inode * dir, int mode);
-unsigned long ext2_count_free(struct buf *map, unsigned int numchars);
-void ext2_free_blocks(struct mount *mp, unsigned long block,
- unsigned long count);
-void ext2_free_inode(struct inode * inode);
-void mark_buffer_dirty(struct buf *bh);
-
-/* Flags to low-level allocation routines. */
-#define B_CLRBUF 0x01 /* Request allocated buffer be cleared. */
-#define B_SYNC 0x02 /* Do all allocations synchronously. */
-#define B_METAONLY 0x04 /* Return indirect block buffer. */
-#define B_NOWAIT 0x08 /* do not sleep to await lock */
-
-extern struct vop_vector ext2_vnodeops;
-extern struct vop_vector ext2_fifoops;
-
-#endif /* !_SYS_GNU_EXT2FS_EXT2_EXTERN_H_ */
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_inode.c b/sys/gnu/fs/ext2fs/ext2_inode.c
deleted file mode 100644
index 0a62c30..0000000
--- a/sys/gnu/fs/ext2fs/ext2_inode.c
+++ /dev/null
@@ -1,528 +0,0 @@
-/*-
- * modified for Lites 1.1
- *
- * Aug 1995, Godmar Back (gback@cs.utah.edu)
- * University of Utah, Department of Computer Science
- */
-/*-
- * Copyright (c) 1982, 1986, 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)ffs_inode.c 8.5 (Berkeley) 12/30/93
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/mount.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-#include <sys/vnode.h>
-#include <sys/malloc.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-
-#include <gnu/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 int ext2_indirtrunc(struct inode *, int32_t, int32_t, int32_t, int,
- long *);
-
-/*
- * Update the access, modified, and inode change times as specified by the
- * IN_ACCESS, IN_UPDATE, and IN_CHANGE flags respectively. Write the inode
- * to disk if the IN_MODIFIED flag is set (it may be set initially, or by
- * the timestamp update). The IN_LAZYMOD flag is set to force a write
- * later if not now. If we write now, then clear both IN_MODIFIED and
- * IN_LAZYMOD to reflect the presumably successful write, and if waitfor is
- * set, then wait for the write to complete.
- */
-int
-ext2_update(vp, waitfor)
- struct vnode *vp;
- int waitfor;
-{
- struct ext2_sb_info *fs;
- struct buf *bp;
- struct inode *ip;
- int error;
-
- ext2_itimes(vp);
- ip = VTOI(vp);
- if ((ip->i_flag & IN_MODIFIED) == 0)
- return (0);
- ip->i_flag &= ~(IN_LAZYMOD | IN_MODIFIED);
- if (vp->v_mount->mnt_flag & MNT_RDONLY)
- return (0);
- fs = ip->i_e2fs;
- if ((error = bread(ip->i_devvp,
- fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
- (int)fs->s_blocksize, NOCRED, &bp)) != 0) {
- brelse(bp);
- return (error);
- }
- ext2_i2ei(ip, (struct ext2_inode *)((char *)bp->b_data +
- EXT2_INODE_SIZE(fs) * ino_to_fsbo(fs, ip->i_number)));
- if (waitfor && (vp->v_mount->mnt_kern_flag & MNTK_ASYNC) == 0)
- return (bwrite(bp));
- else {
- bdwrite(bp);
- return (0);
- }
-}
-
-#define SINGLE 0 /* index of single indirect block */
-#define DOUBLE 1 /* index of double indirect block */
-#define TRIPLE 2 /* index of triple indirect block */
-/*
- * Truncate the inode oip to at most length size, freeing the
- * disk blocks.
- */
-int
-ext2_truncate(vp, length, flags, cred, td)
- struct vnode *vp;
- off_t length;
- int flags;
- struct ucred *cred;
- struct thread *td;
-{
- struct vnode *ovp = vp;
- int32_t lastblock;
- struct inode *oip;
- int32_t bn, lbn, lastiblock[NIADDR], indir_lbn[NIADDR];
- int32_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR];
- struct ext2_sb_info *fs;
- struct buf *bp;
- int offset, size, level;
- long count, nblocks, blocksreleased = 0;
- int aflags, error, i, allerror;
- off_t osize;
-/*
-printf("ext2_truncate called %d to %d\n", VTOI(ovp)->i_number, length);
-*/ /*
- * negative file sizes will totally break the code below and
- * are not meaningful anyways.
- */
- if (length < 0)
- return EFBIG;
-
- oip = VTOI(ovp);
- if (ovp->v_type == VLNK &&
- oip->i_size < ovp->v_mount->mnt_maxsymlinklen) {
-#ifdef DIAGNOSTIC
- if (length != 0)
- panic("ext2_truncate: partial truncate of symlink");
-#endif
- bzero((char *)&oip->i_shortlink, (u_int)oip->i_size);
- oip->i_size = 0;
- oip->i_flag |= IN_CHANGE | IN_UPDATE;
- return (ext2_update(ovp, 1));
- }
- if (oip->i_size == length) {
- oip->i_flag |= IN_CHANGE | IN_UPDATE;
- return (ext2_update(ovp, 0));
- }
- fs = oip->i_e2fs;
- osize = oip->i_size;
- ext2_discard_prealloc(oip);
- /*
- * Lengthen the size of the file. We must ensure that the
- * last byte of the file is allocated. Since the smallest
- * value of oszie is 0, length will be at least 1.
- */
- if (osize < length) {
- if (length > oip->i_e2fs->fs_maxfilesize)
- return (EFBIG);
- offset = blkoff(fs, length - 1);
- lbn = lblkno(fs, length - 1);
- aflags = B_CLRBUF;
- if (flags & IO_SYNC)
- aflags |= B_SYNC;
- vnode_pager_setsize(ovp, length);
- if ((error = ext2_balloc(oip, lbn, offset + 1, cred, &bp,
- aflags)) != 0)
- return (error);
- oip->i_size = length;
- if (aflags & IO_SYNC)
- bwrite(bp);
- else
- bawrite(bp);
- oip->i_flag |= IN_CHANGE | IN_UPDATE;
- return (ext2_update(ovp, 1));
- }
- /*
- * Shorten the size of the file. If the file is not being
- * truncated to a block boundry, the contents of the
- * partial block following the end of the file must be
- * zero'ed in case it ever become accessible again because
- * of subsequent file growth.
- */
- /* I don't understand the comment above */
- offset = blkoff(fs, length);
- if (offset == 0) {
- oip->i_size = length;
- } else {
- lbn = lblkno(fs, length);
- aflags = B_CLRBUF;
- if (flags & IO_SYNC)
- aflags |= B_SYNC;
- if ((error = ext2_balloc(oip, lbn, offset, cred, &bp,
- aflags)) != 0)
- return (error);
- oip->i_size = length;
- size = blksize(fs, oip, lbn);
- bzero((char *)bp->b_data + offset, (u_int)(size - offset));
- allocbuf(bp, size);
- if (aflags & IO_SYNC)
- bwrite(bp);
- else
- bawrite(bp);
- }
- /*
- * Calculate index into inode's block list of
- * last direct and indirect blocks (if any)
- * which we want to keep. Lastblock is -1 when
- * the file is truncated to 0.
- */
- lastblock = lblkno(fs, length + fs->s_blocksize - 1) - 1;
- lastiblock[SINGLE] = lastblock - NDADDR;
- lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR(fs);
- lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR(fs) * NINDIR(fs);
- nblocks = btodb(fs->s_blocksize);
- /*
- * Update file and block pointers on disk before we start freeing
- * blocks. If we crash before free'ing blocks below, the blocks
- * will be returned to the free list. lastiblock values are also
- * normalized to -1 for calls to ext2_indirtrunc below.
- */
- bcopy((caddr_t)&oip->i_db[0], (caddr_t)oldblks, sizeof oldblks);
- for (level = TRIPLE; level >= SINGLE; level--)
- if (lastiblock[level] < 0) {
- oip->i_ib[level] = 0;
- lastiblock[level] = -1;
- }
- for (i = NDADDR - 1; i > lastblock; i--)
- oip->i_db[i] = 0;
- oip->i_flag |= IN_CHANGE | IN_UPDATE;
- allerror = ext2_update(ovp, 1);
-
- /*
- * Having written the new inode to disk, save its new configuration
- * and put back the old block pointers long enough to process them.
- * Note that we save the new block configuration so we can check it
- * when we are done.
- */
- bcopy((caddr_t)&oip->i_db[0], (caddr_t)newblks, sizeof newblks);
- bcopy((caddr_t)oldblks, (caddr_t)&oip->i_db[0], sizeof oldblks);
- oip->i_size = osize;
- error = vtruncbuf(ovp, cred, td, length, (int)fs->s_blocksize);
- if (error && (allerror == 0))
- allerror = error;
-
- /*
- * Indirect blocks first.
- */
- indir_lbn[SINGLE] = -NDADDR;
- indir_lbn[DOUBLE] = indir_lbn[SINGLE] - NINDIR(fs) - 1;
- indir_lbn[TRIPLE] = indir_lbn[DOUBLE] - NINDIR(fs) * NINDIR(fs) - 1;
- for (level = TRIPLE; level >= SINGLE; level--) {
- bn = oip->i_ib[level];
- if (bn != 0) {
- error = ext2_indirtrunc(oip, indir_lbn[level],
- fsbtodb(fs, bn), lastiblock[level], level, &count);
- if (error)
- allerror = error;
- blocksreleased += count;
- if (lastiblock[level] < 0) {
- oip->i_ib[level] = 0;
- ext2_blkfree(oip, bn, fs->s_frag_size);
- blocksreleased += nblocks;
- }
- }
- if (lastiblock[level] >= 0)
- goto done;
- }
-
- /*
- * All whole direct blocks or frags.
- */
- for (i = NDADDR - 1; i > lastblock; i--) {
- long bsize;
-
- bn = oip->i_db[i];
- if (bn == 0)
- continue;
- oip->i_db[i] = 0;
- bsize = blksize(fs, oip, i);
- ext2_blkfree(oip, bn, bsize);
- blocksreleased += btodb(bsize);
- }
- if (lastblock < 0)
- goto done;
-
- /*
- * Finally, look for a change in size of the
- * last direct block; release any frags.
- */
- bn = oip->i_db[lastblock];
- if (bn != 0) {
- long oldspace, newspace;
-
- /*
- * Calculate amount of space we're giving
- * back as old block size minus new block size.
- */
- oldspace = blksize(fs, oip, lastblock);
- oip->i_size = length;
- newspace = blksize(fs, oip, lastblock);
- if (newspace == 0)
- panic("itrunc: newspace");
- if (oldspace - newspace > 0) {
- /*
- * Block number of space to be free'd is
- * the old block # plus the number of frags
- * required for the storage we're keeping.
- */
- bn += numfrags(fs, newspace);
- ext2_blkfree(oip, bn, oldspace - newspace);
- blocksreleased += btodb(oldspace - newspace);
- }
- }
-done:
-#ifdef DIAGNOSTIC
- for (level = SINGLE; level <= TRIPLE; level++)
- if (newblks[NDADDR + level] != oip->i_ib[level])
- panic("itrunc1");
- for (i = 0; i < NDADDR; i++)
- if (newblks[i] != oip->i_db[i])
- panic("itrunc2");
- VI_LOCK(ovp);
- if (length == 0 && (ovp->v_bufobj.bo_dirty.bv_cnt != 0 ||
- ovp->v_bufobj.bo_clean.bv_cnt != 0))
- panic("itrunc3");
- VI_UNLOCK(ovp);
-#endif /* DIAGNOSTIC */
- /*
- * Put back the real size.
- */
- oip->i_size = length;
- oip->i_blocks -= blocksreleased;
- if (oip->i_blocks < 0) /* sanity */
- oip->i_blocks = 0;
- oip->i_flag |= IN_CHANGE;
- vnode_pager_setsize(ovp, length);
- return (allerror);
-}
-
-/*
- * Release blocks associated with the inode ip and stored in the indirect
- * block bn. Blocks are free'd in LIFO order up to (but not including)
- * lastbn. If level is greater than SINGLE, the block is an indirect block
- * and recursive calls to indirtrunc must be used to cleanse other indirect
- * blocks.
- *
- * NB: triple indirect blocks are untested.
- */
-
-static int
-ext2_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
- struct inode *ip;
- int32_t lbn, lastbn;
- int32_t dbn;
- int level;
- long *countp;
-{
- struct buf *bp;
- struct ext2_sb_info *fs = ip->i_e2fs;
- struct vnode *vp;
- int32_t *bap, *copy, nb, nlbn, last;
- long blkcount, factor;
- int i, nblocks, blocksreleased = 0;
- int error = 0, allerror = 0;
-
- /*
- * Calculate index in current block of last
- * block to be kept. -1 indicates the entire
- * block so we need not calculate the index.
- */
- factor = 1;
- for (i = SINGLE; i < level; i++)
- factor *= NINDIR(fs);
- last = lastbn;
- if (lastbn > 0)
- last /= factor;
- nblocks = btodb(fs->s_blocksize);
- /*
- * Get buffer of block pointers, zero those entries corresponding
- * to blocks to be free'd, and update on disk copy first. Since
- * double(triple) indirect before single(double) indirect, calls
- * to bmap on these blocks will fail. However, we already have
- * the on disk address, so we have to set the b_blkno field
- * explicitly instead of letting bread do everything for us.
- */
- vp = ITOV(ip);
- bp = getblk(vp, lbn, (int)fs->s_blocksize, 0, 0, 0);
- if (bp->b_flags & (B_DONE | B_DELWRI)) {
- } else {
- bp->b_iocmd = BIO_READ;
- if (bp->b_bcount > bp->b_bufsize)
- panic("ext2_indirtrunc: bad buffer size");
- bp->b_blkno = dbn;
- vfs_busy_pages(bp, 0);
- bp->b_iooffset = dbtob(bp->b_blkno);
- bstrategy(bp);
- error = bufwait(bp);
- }
- if (error) {
- brelse(bp);
- *countp = 0;
- return (error);
- }
-
- bap = (int32_t *)bp->b_data;
- copy = malloc(fs->s_blocksize, M_TEMP, M_WAITOK);
- bcopy((caddr_t)bap, (caddr_t)copy, (u_int)fs->s_blocksize);
- bzero((caddr_t)&bap[last + 1],
- (u_int)(NINDIR(fs) - (last + 1)) * sizeof (int32_t));
- if (last == -1)
- bp->b_flags |= B_INVAL;
- error = bwrite(bp);
- if (error)
- allerror = error;
- bap = copy;
-
- /*
- * Recursively free totally unused blocks.
- */
- for (i = NINDIR(fs) - 1, nlbn = lbn + 1 - i * factor; i > last;
- i--, nlbn += factor) {
- nb = bap[i];
- if (nb == 0)
- continue;
- if (level > SINGLE) {
- if ((error = ext2_indirtrunc(ip, nlbn,
- fsbtodb(fs, nb), (int32_t)-1, level - 1, &blkcount)) != 0)
- allerror = error;
- blocksreleased += blkcount;
- }
- ext2_blkfree(ip, nb, fs->s_blocksize);
- blocksreleased += nblocks;
- }
-
- /*
- * Recursively free last partial block.
- */
- if (level > SINGLE && lastbn >= 0) {
- last = lastbn % factor;
- nb = bap[i];
- if (nb != 0) {
- if ((error = ext2_indirtrunc(ip, nlbn, fsbtodb(fs, nb),
- last, level - 1, &blkcount)) != 0)
- allerror = error;
- blocksreleased += blkcount;
- }
- }
- free(copy, M_TEMP);
- *countp = blocksreleased;
- return (allerror);
-}
-
-/*
- * discard preallocated blocks
- */
-int
-ext2_inactive(ap)
- struct vop_inactive_args /* {
- struct vnode *a_vp;
- struct thread *a_td;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
- struct inode *ip = VTOI(vp);
- struct thread *td = ap->a_td;
- int mode, error = 0;
-
- ext2_discard_prealloc(ip);
- if (prtactive && vrefcnt(vp) != 0)
- vprint("ext2_inactive: pushing active", vp);
-
- /*
- * Ignore inodes related to stale file handles.
- */
- if (ip->i_mode == 0)
- goto out;
- if (ip->i_nlink <= 0) {
- error = ext2_truncate(vp, (off_t)0, 0, NOCRED, td);
- ip->i_rdev = 0;
- mode = ip->i_mode;
- ip->i_mode = 0;
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
- ext2_vfree(vp, ip->i_number, mode);
- }
- if (ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE))
- ext2_update(vp, 0);
-out:
- /*
- * If we are done with the inode, reclaim it
- * so that it can be reused immediately.
- */
- if (ip->i_mode == 0)
- vrecycle(vp, td);
- return (error);
-}
-
-/*
- * Reclaim an inode so that it can be used for other purposes.
- */
-int
-ext2_reclaim(ap)
- struct vop_reclaim_args /* {
- struct vnode *a_vp;
- struct thread *a_td;
- } */ *ap;
-{
- struct inode *ip;
- struct vnode *vp = ap->a_vp;
-
- if (prtactive && vrefcnt(vp) != 0)
- vprint("ufs_reclaim: pushing active", vp);
- ip = VTOI(vp);
- if (ip->i_flag & IN_LAZYMOD) {
- ip->i_flag |= IN_MODIFIED;
- ext2_update(vp, 0);
- }
- vfs_hash_remove(vp);
- free(vp->v_data, M_EXT2NODE);
- vp->v_data = 0;
- vnode_destroy_vobject(vp);
- return (0);
-}
diff --git a/sys/gnu/fs/ext2fs/ext2_inode_cnv.c b/sys/gnu/fs/ext2fs/ext2_inode_cnv.c
deleted file mode 100644
index 412a47cc..0000000
--- a/sys/gnu/fs/ext2fs/ext2_inode_cnv.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*-
- * Copyright (c) 1995 The University of Utah and
- * the Computer Systems Laboratory at the University of Utah (CSL).
- * All rights reserved.
- *
- * Permission to use, copy, modify and distribute this software is hereby
- * granted provided that (1) source code retains these copyright, permission,
- * and disclaimer notices, and (2) redistributions including binaries
- * reproduce the notices in supporting documentation, and (3) all advertising
- * materials mentioning features or use of this software display the following
- * acknowledgement: ``This product includes software developed by the
- * Computer Systems Laboratory at the University of Utah.''
- *
- * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
- * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
- * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * CSL requests users of this software to return to csl-dist@cs.utah.edu any
- * improvements that they make and grant CSL redistribution rights.
- *
- * Utah $Hdr$
- * $FreeBSD$
- */
-
-/*
- * routines to convert on disk ext2 inodes into inodes and back
- */
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/lock.h>
-#include <sys/stat.h>
-#include <sys/vnode.h>
-
-#include <gnu/fs/ext2fs/inode.h>
-#include <gnu/fs/ext2fs/ext2_fs.h>
-#include <gnu/fs/ext2fs/ext2_extern.h>
-
-void
-ext2_print_inode( in )
- struct inode *in;
-{
- int i;
-
- printf( "Inode: %5d", in->i_number);
- printf( /* "Inode: %5d" */
- " Type: %10s Mode: 0x%o Flags: 0x%x Version: %d\n",
- "n/a", in->i_mode, in->i_flags, in->i_gen);
- printf( "User: %5lu Group: %5lu Size: %lu\n",
- (unsigned long)in->i_uid, (unsigned long)in->i_gid,
- (unsigned long)in->i_size);
- printf( "Links: %3d Blockcount: %d\n",
- in->i_nlink, in->i_blocks);
- printf( "ctime: 0x%x", in->i_ctime);
- printf( "atime: 0x%x", in->i_atime);
- printf( "mtime: 0x%x", in->i_mtime);
- printf( "BLOCKS: ");
- for(i=0; i < (in->i_blocks <= 24 ? ((in->i_blocks+1)/2): 12); i++)
- printf("%d ", in->i_db[i]);
- printf("\n");
-}
-
-/*
- * raw ext2 inode to inode
- */
-void
-ext2_ei2i(ei, ip)
- struct ext2_inode *ei;
- struct inode *ip;
-{
- int i;
-
- ip->i_nlink = ei->i_links_count;
- /* Godmar thinks - if the link count is zero, then the inode is
- unused - according to ext2 standards. Ufs marks this fact
- by setting i_mode to zero - why ?
- I can see that this might lead to problems in an undelete.
- */
- ip->i_mode = ei->i_links_count ? ei->i_mode : 0;
- ip->i_size = ei->i_size;
- if (S_ISREG(ip->i_mode))
- ip->i_size |= ((u_int64_t)ei->i_size_high) << 32;
- ip->i_atime = ei->i_atime;
- ip->i_mtime = ei->i_mtime;
- ip->i_ctime = ei->i_ctime;
- ip->i_flags = 0;
- ip->i_flags |= (ei->i_flags & EXT2_APPEND_FL) ? 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;
- /* XXX use memcpy */
- for(i = 0; i < NDADDR; i++)
- ip->i_db[i] = ei->i_block[i];
- for(i = 0; i < NIADDR; i++)
- ip->i_ib[i] = ei->i_block[EXT2_NDIR_BLOCKS + i];
-}
-
-/*
- * inode to raw ext2 inode
- */
-void
-ext2_i2ei(ip, ei)
- struct inode *ip;
- struct ext2_inode *ei;
-{
- int i;
-
- ei->i_mode = ip->i_mode;
- ei->i_links_count = ip->i_nlink;
- /*
- Godmar thinks: if dtime is nonzero, ext2 says this inode
- has been deleted, this would correspond to a zero link count
- */
- ei->i_dtime = ei->i_links_count ? 0 : ip->i_mtime;
- ei->i_size = ip->i_size;
- if (S_ISREG(ip->i_mode))
- ei->i_size_high = ip->i_size >> 32;
- ei->i_atime = ip->i_atime;
- ei->i_mtime = ip->i_mtime;
- ei->i_ctime = ip->i_ctime;
- ei->i_flags = ip->i_flags;
- ei->i_flags = 0;
- ei->i_flags |= (ip->i_flags & 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;
- /* XXX use memcpy */
- for(i = 0; i < NDADDR; i++)
- ei->i_block[i] = ip->i_db[i];
- for(i = 0; i < NIADDR; i++)
- ei->i_block[EXT2_NDIR_BLOCKS + i] = ip->i_ib[i];
-}
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/ext2_lookup.c b/sys/gnu/fs/ext2fs/ext2_lookup.c
deleted file mode 100644
index 6ab41e5..0000000
--- a/sys/gnu/fs/ext2fs/ext2_lookup.c
+++ /dev/null
@@ -1,1082 +0,0 @@
-/*-
- * modified for Lites 1.1
- *
- * Aug 1995, Godmar Back (gback@cs.utah.edu)
- * University of Utah, Department of Computer Science
- */
-/*-
- * Copyright (c) 1989, 1993
- * The Regents of the University of California. All rights reserved.
- * (c) UNIX System Laboratories, Inc.
- * All or some portions of this file are derived from material licensed
- * to the University of California by American Telephone and Telegraph
- * Co. or Unix System Laboratories, Inc. and are reproduced herein with
- * the permission of UNIX System Laboratories, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)ufs_lookup.c 8.6 (Berkeley) 4/1/94
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/namei.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-#include <sys/endian.h>
-#include <sys/mount.h>
-#include <sys/vnode.h>
-#include <sys/malloc.h>
-#include <sys/dirent.h>
-#include <sys/sysctl.h>
-
-#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>
-
-#ifdef DIAGNOSTIC
-static int dirchk = 1;
-#else
-static int dirchk = 0;
-#endif
-
-static SYSCTL_NODE(_vfs, OID_AUTO, e2fs, CTLFLAG_RD, 0, "EXT2FS filesystem");
-SYSCTL_INT(_vfs_e2fs, OID_AUTO, dircheck, CTLFLAG_RW, &dirchk, 0, "");
-
-/*
- DIRBLKSIZE in ffs is DEV_BSIZE (in most cases 512)
- while it is the native blocksize in ext2fs - thus, a #define
- is no longer appropriate
-*/
-#undef DIRBLKSIZ
-
-static u_char ext2_ft_to_dt[] = {
- DT_UNKNOWN, /* EXT2_FT_UNKNOWN */
- DT_REG, /* EXT2_FT_REG_FILE */
- DT_DIR, /* EXT2_FT_DIR */
- DT_CHR, /* EXT2_FT_CHRDEV */
- DT_BLK, /* EXT2_FT_BLKDEV */
- DT_FIFO, /* EXT2_FT_FIFO */
- DT_SOCK, /* EXT2_FT_SOCK */
- DT_LNK, /* EXT2_FT_SYMLINK */
-};
-#define FTTODT(ft) \
- ((ft) > sizeof(ext2_ft_to_dt) / sizeof(ext2_ft_to_dt[0]) ? \
- DT_UNKNOWN : ext2_ft_to_dt[(ft)])
-
-static u_char dt_to_ext2_ft[] = {
- EXT2_FT_UNKNOWN, /* DT_UNKNOWN */
- EXT2_FT_FIFO, /* DT_FIFO */
- EXT2_FT_CHRDEV, /* DT_CHR */
- EXT2_FT_UNKNOWN, /* unused */
- EXT2_FT_DIR, /* DT_DIR */
- EXT2_FT_UNKNOWN, /* unused */
- EXT2_FT_BLKDEV, /* DT_BLK */
- EXT2_FT_UNKNOWN, /* unused */
- EXT2_FT_REG_FILE, /* DT_REG */
- EXT2_FT_UNKNOWN, /* unused */
- EXT2_FT_SYMLINK, /* DT_LNK */
- EXT2_FT_UNKNOWN, /* unused */
- EXT2_FT_SOCK, /* DT_SOCK */
- EXT2_FT_UNKNOWN, /* unused */
- EXT2_FT_UNKNOWN, /* DT_WHT */
-};
-#define DTTOFT(dt) \
- ((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,
- int entryoffsetinblock);
-
-/*
- * Vnode op for reading directories.
- *
- * The routine below assumes that the on-disk format of a directory
- * is the same as that defined by <sys/dirent.h>. If the on-disk
- * format changes, then it will be necessary to do a conversion
- * from the on-disk format that read returns to the format defined
- * by <sys/dirent.h>.
- */
-/*
- * this is exactly what we do here - the problem is that the conversion
- * will blow up some entries by four bytes, so it can't be done in place.
- * This is too bad. Right now the conversion is done entry by entry, the
- * converted entry is sent via uiomove.
- *
- * XXX allocate a buffer, convert as many entries as possible, then send
- * the whole buffer to uiomove
- */
-int
-ext2_readdir(ap)
- struct vop_readdir_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- struct ucred *a_cred;
- } */ *ap;
-{
- struct uio *uio = ap->a_uio;
- int count, error;
-
- struct ext2_dir_entry_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 readcnt;
- off_t startoffset = uio->uio_offset;
-
- count = uio->uio_resid;
- /*
- * Avoid complications for partial directory entries by adjusting
- * the i/o to end at a block boundary. Don't give up (like ufs
- * does) if the initial adjustment gives a negative count, since
- * many callers don't supply a large enough buffer. The correct
- * size is a little larger than DIRBLKSIZ to allow for expansion
- * of directory entries, but some callers just use 512.
- */
- 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;
- auio.uio_resid = count;
- auio.uio_segflg = UIO_SYSSPACE;
- aiov.iov_len = count;
- dirbuf = malloc(count, M_TEMP, M_WAITOK);
- aiov.iov_base = dirbuf;
- 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];
- ncookies = 0;
- bzero(&dstdp, offsetof(struct dirent, d_name));
- for (dp = (struct ext2_dir_entry_2 *)dirbuf;
- !error && uio->uio_resid > 0 && dp < edp; ) {
- /*-
- * "New" ext2fs directory entries differ in 3 ways
- * from ufs on-disk ones:
- * - the name is not necessarily NUL-terminated.
- * - the file type field always exists and always
- * follows the name length field.
- * - the file type is encoded in a different way.
- *
- * "Old" ext2fs directory entries need no special
- * conversions, since they are binary compatible
- * with "new" entries having a file type of 0 (i.e.,
- * EXT2_FT_UNKNOWN). Splitting the old name length
- * field didn't make a mess like it did in ufs,
- * 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_reclen = GENERIC_DIRSIZ(&dstdp);
- bcopy(dp->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(dstdp.d_reclen <= uio->uio_resid) {
- /* advance dp */
- dp = (struct ext2_dir_entry_2 *)
- ((char *)dp + dp->rec_len);
- error =
- uiomove(&dstdp, dstdp.d_reclen, uio);
- if (!error)
- ncookies++;
- } else
- break;
- } else {
- error = EIO;
- break;
- }
- }
- /* we need to correct uio_offset */
- uio->uio_offset = startoffset + (caddr_t)dp - dirbuf;
-
- if (!error && ap->a_ncookies != NULL) {
- u_long *cookiep, *cookies, *ecookies;
- off_t off;
-
- if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
- panic("ext2_readdir: unexpected uio from NFS server");
- cookies = malloc(ncookies * sizeof(u_long), M_TEMP,
- M_WAITOK);
- off = startoffset;
- for (dp = (struct ext2_dir_entry_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;
- *cookiep++ = (u_long) off;
- }
- *ap->a_ncookies = ncookies;
- *ap->a_cookies = cookies;
- }
- }
- free(dirbuf, M_TEMP);
- if (ap->a_eofflag)
- *ap->a_eofflag = VTOI(ap->a_vp)->i_size <= uio->uio_offset;
- return (error);
-}
-
-/*
- * Convert a component of a pathname into a pointer to a locked inode.
- * This is a very central and rather complicated routine.
- * If the file system is not maintained in a strict tree hierarchy,
- * this can result in a deadlock situation (see comments in code below).
- *
- * The cnp->cn_nameiop argument is LOOKUP, CREATE, RENAME, or DELETE depending
- * on whether the name is to be looked up, created, renamed, or deleted.
- * When CREATE, RENAME, or DELETE is specified, information usable in
- * creating, renaming, or deleting a directory entry may be calculated.
- * If flag has LOCKPARENT or'ed into it and the target of the pathname
- * exists, lookup returns both the target and its parent directory locked.
- * When creating or renaming and LOCKPARENT is specified, the target may
- * not be ".". When deleting and LOCKPARENT is specified, the target may
- * be "."., but the caller must check to ensure it does an vrele and vput
- * instead of two vputs.
- *
- * Overall outline of ext2_lookup:
- *
- * search for name in directory, to found or notfound
- * notfound:
- * if creating, return locked directory, leaving info on available slots
- * else return error
- * found:
- * if at end of path and deleting, return information to allow delete
- * if at end of path and rewriting (RENAME and LOCKPARENT), lock target
- * inode and return info to allow rewrite
- * if not at end, add name to cache; if at end and neither creating
- * nor deleting, add name to cache
- */
-int
-ext2_lookup(ap)
- struct vop_cachedlookup_args /* {
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- } */ *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 */
- 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 */
- int slotfreespace; /* amount of space free in slot */
- int slotneeded; /* size of the entry we're seeking */
- int numdirpasses; /* strategy for directory search */
- doff_t endsearch; /* offset to end directory search */
- doff_t prevoff; /* prev entry dp->i_offset */
- struct vnode *pdp; /* saved dp during symlink work */
- struct vnode *tdp; /* returned by VFS_VGET */
- doff_t enduseful; /* pointer past last used dir slot */
- u_long bmask; /* block offset mask */
- int namlen, error;
- struct vnode **vpp = ap->a_vpp;
- struct componentname *cnp = ap->a_cnp;
- struct ucred *cred = cnp->cn_cred;
- int flags = cnp->cn_flags;
- int nameiop = cnp->cn_nameiop;
- ino_t saved_ino;
-
- int DIRBLKSIZ = VTOI(ap->a_dvp)->i_e2fs->s_blocksize;
-
- bp = NULL;
- slotoffset = -1;
- *vpp = NULL;
- vdp = ap->a_dvp;
- dp = VTOI(vdp);
- /*
- * We now have a segment name to search for, and a directory to search.
- */
-
- /*
- * Suppress search for slots unless creating
- * file and at end of pathname, in which case
- * we watch for a place to put the new file in
- * case it doesn't already exist.
- */
- slotstatus = FOUND;
- slotfreespace = slotsize = slotneeded = 0;
- if ((nameiop == CREATE || nameiop == RENAME) &&
- (flags & ISLASTCN)) {
- slotstatus = NONE;
- slotneeded = EXT2_DIR_REC_LEN(cnp->cn_namelen);
- /* was
- slotneeded = (sizeof(struct direct) - MAXNAMLEN +
- cnp->cn_namelen + 3) &~ 3; */
- }
-
- /*
- * If there is cached information on a previous search of
- * this directory, pick up where we last left off.
- * We cache only lookups as these are the most common
- * and have the greatest payoff. Caching CREATE has little
- * benefit as it usually must search the entire directory
- * to determine that the entry does not exist. Caching the
- * location of the last DELETE or RENAME has not reduced
- * profiling time and hence has been removed in the interest
- * 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) {
- entryoffsetinblock = 0;
- dp->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,
- &bp)))
- return (error);
- numdirpasses = 2;
- nchstats.ncs_2passes++;
- }
- prevoff = dp->i_offset;
- endsearch = roundup(dp->i_size, DIRBLKSIZ);
- enduseful = 0;
-
-searchloop:
- while (dp->i_offset < endsearch) {
- /*
- * If necessary, get the next directory block.
- */
- if ((dp->i_offset & bmask) == 0) {
- if (bp != NULL)
- brelse(bp);
- if ((error =
- ext2_blkatoff(vdp, (off_t)dp->i_offset, NULL,
- &bp)) != 0)
- return (error);
- entryoffsetinblock = 0;
- }
- /*
- * If still looking for a slot, and at a DIRBLKSIZE
- * boundary, have to start looking for free space again.
- */
- if (slotstatus == NONE &&
- (entryoffsetinblock & (DIRBLKSIZ - 1)) == 0) {
- slotoffset = -1;
- slotfreespace = 0;
- }
- /*
- * Get pointer to next entry.
- * Full validation checks are slow, so we only check
- * enough to insure forward progress through the
- * directory. Complete checks can be run by setting
- * "vfs.e2fs.dirchk" to be true.
- */
- ep = (struct ext2_dir_entry_2 *)
- ((char *)bp->b_data + entryoffsetinblock);
- if (ep->rec_len == 0 ||
- (dirchk && ext2_dirbadentry(vdp, ep, entryoffsetinblock))) {
- int i;
- ext2_dirbad(dp, dp->i_offset, "mangled entry");
- i = DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1));
- dp->i_offset += i;
- entryoffsetinblock += i;
- continue;
- }
-
- /*
- * If an appropriate sized slot has not yet been found,
- * check to see if one is available. Also accumulate space
- * in the current block so that we can determine if
- * compaction is viable.
- */
- if (slotstatus != FOUND) {
- int size = ep->rec_len;
-
- if (ep->inode != 0)
- size -= EXT2_DIR_REC_LEN(ep->name_len);
- if (size > 0) {
- if (size >= slotneeded) {
- slotstatus = FOUND;
- slotoffset = dp->i_offset;
- slotsize = ep->rec_len;
- } else if (slotstatus == NONE) {
- slotfreespace += size;
- if (slotoffset == -1)
- slotoffset = dp->i_offset;
- if (slotfreespace >= slotneeded) {
- slotstatus = COMPACT;
- slotsize = dp->i_offset +
- ep->rec_len - slotoffset;
- }
- }
- }
- }
-
- /*
- * Check for a name match.
- */
- if (ep->inode) {
- namlen = ep->name_len;
- if (namlen == cnp->cn_namelen &&
- !bcmp(cnp->cn_nameptr, ep->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;
- goto found;
- }
- }
- prevoff = dp->i_offset;
- dp->i_offset += ep->rec_len;
- entryoffsetinblock += ep->rec_len;
- if (ep->inode)
- enduseful = dp->i_offset;
- }
-/* notfound: */
- /*
- * If we started in the middle of the directory and failed
- * to find our target, we must check the beginning as well.
- */
- if (numdirpasses == 2) {
- numdirpasses--;
- dp->i_offset = 0;
- endsearch = dp->i_diroff;
- goto searchloop;
- }
- if (bp != NULL)
- brelse(bp);
- /*
- * If creating, and at end of pathname and current
- * directory has not been removed, then can consider
- * allowing file to be created.
- */
- if ((nameiop == CREATE || nameiop == RENAME) &&
- (flags & ISLASTCN) && dp->i_nlink != 0) {
- /*
- * Access for write is interpreted as allowing
- * creation of files in the directory.
- */
- if ((error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread)) != 0)
- return (error);
- /*
- * Return an indication of where the new directory
- * entry should be put. If we didn't find a slot,
- * then set dp->i_count to 0 indicating
- * that the new slot belongs at the end of the
- * directory. If we found a slot, then the new entry
- * can be put in the range from dp->i_offset to
- * dp->i_offset + dp->i_count.
- */
- if (slotstatus == NONE) {
- dp->i_offset = roundup(dp->i_size, DIRBLKSIZ);
- dp->i_count = 0;
- enduseful = dp->i_offset;
- } else {
- dp->i_offset = slotoffset;
- dp->i_count = slotsize;
- if (enduseful < slotoffset + slotsize)
- enduseful = slotoffset + slotsize;
- }
- dp->i_endoff = roundup(enduseful, DIRBLKSIZ);
- dp->i_flag |= IN_CHANGE | IN_UPDATE;
- /*
- * We return with the directory locked, so that
- * the parameters we set up above will still be
- * valid if we actually decide to do a direnter().
- * We return ni_vp == NULL to indicate that the entry
- * does not currently exist; we leave a pointer to
- * the (locked) directory inode in ndp->ni_dvp.
- * The pathname buffer is saved so that the name
- * can be obtained later.
- *
- * NB - if the directory is unlocked, then this
- * information cannot be used.
- */
- cnp->cn_flags |= SAVENAME;
- return (EJUSTRETURN);
- }
- /*
- * Insert name into cache (as non-existent) if appropriate.
- */
- if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE)
- cache_enter(vdp, *vpp, cnp);
- return (ENOENT);
-
-found:
- if (numdirpasses == 2)
- nchstats.ncs_pass2++;
- /*
- * Check that directory length properly reflects presence
- * of this entry.
- */
- if (entryoffsetinblock + EXT2_DIR_REC_LEN(ep->name_len)
- > dp->i_size) {
- ext2_dirbad(dp, dp->i_offset, "i_size too small");
- dp->i_size = entryoffsetinblock+EXT2_DIR_REC_LEN(ep->name_len);
- dp->i_flag |= IN_CHANGE | IN_UPDATE;
- }
- brelse(bp);
-
- /*
- * Found component in pathname.
- * If the final component of path name, save information
- * in the cache as to where the entry was found.
- */
- if ((flags & ISLASTCN) && nameiop == LOOKUP)
- dp->i_diroff = dp->i_offset &~ (DIRBLKSIZ - 1);
-
- /*
- * If deleting, and at end of pathname, return
- * parameters which can be used to remove file.
- */
- if (nameiop == DELETE && (flags & ISLASTCN)) {
- /*
- * Write access to directory required to delete files.
- */
- if ((error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread)) != 0)
- return (error);
- /*
- * Return pointer to current entry in dp->i_offset,
- * and distance past previous entry (if there
- * is a previous entry in this block) in dp->i_count.
- * Save directory inode pointer in ndp->ni_dvp for dirremove().
- */
- if ((dp->i_offset & (DIRBLKSIZ - 1)) == 0)
- dp->i_count = 0;
- else
- dp->i_count = dp->i_offset - prevoff;
- if (dp->i_number == dp->i_ino) {
- VREF(vdp);
- *vpp = vdp;
- return (0);
- }
- if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, LK_EXCLUSIVE,
- &tdp)) != 0)
- return (error);
- /*
- * If directory is "sticky", then user must own
- * the directory, or the file in it, else she
- * may not delete it (unless she's root). This
- * implements append-only directories.
- */
- if ((dp->i_mode & ISVTX) &&
- cred->cr_uid != 0 &&
- cred->cr_uid != dp->i_uid &&
- VTOI(tdp)->i_uid != cred->cr_uid) {
- vput(tdp);
- return (EPERM);
- }
- *vpp = tdp;
- return (0);
- }
-
- /*
- * If rewriting (RENAME), return the inode and the
- * information required to rewrite the present directory
- * Must get inode of directory entry to verify it's a
- * regular file, or empty directory.
- */
- if (nameiop == RENAME && (flags & ISLASTCN)) {
- if ((error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread)) != 0)
- return (error);
- /*
- * Careful about locking second inode.
- * This can only occur if the target is ".".
- */
- if (dp->i_number == dp->i_ino)
- return (EISDIR);
- if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, LK_EXCLUSIVE,
- &tdp)) != 0)
- return (error);
- *vpp = tdp;
- cnp->cn_flags |= SAVENAME;
- return (0);
- }
-
- /*
- * Step through the translation in the name. We do not `vput' the
- * directory because we may need it again if a symbolic link
- * is relative to the current directory. Instead we save it
- * unlocked as "pdp". We must get the target inode before unlocking
- * the directory to insure that the inode will not be removed
- * before we get it. We prevent deadlock by always fetching
- * inodes from the root, moving down the directory tree. Thus
- * when following backward pointers ".." we must unlock the
- * parent directory before getting the requested directory.
- * There is a potential race condition here if both the current
- * and parent directories are removed before the VFS_VGET for the
- * inode associated with ".." returns. We hope that this occurs
- * infrequently since we cannot avoid this race condition without
- * implementing a sophisticated deadlock detection algorithm.
- * Note also that this simple deadlock detection scheme will not
- * work if the file system has any hard links other than ".."
- * that point backwards in the directory structure.
- */
- pdp = vdp;
- if (flags & ISDOTDOT) {
- saved_ino = dp->i_ino;
- 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);
- if (error != 0)
- return (error);
- *vpp = tdp;
- } else if (dp->i_number == dp->i_ino) {
- VREF(vdp); /* we want ourself, ie "." */
- *vpp = vdp;
- } else {
- if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, LK_EXCLUSIVE,
- &tdp)) != 0)
- return (error);
- *vpp = tdp;
- }
-
- /*
- * Insert name into cache if appropriate.
- */
- if (cnp->cn_flags & MAKEENTRY)
- cache_enter(vdp, *vpp, cnp);
- return (0);
-}
-
-void
-ext2_dirbad(ip, offset, how)
- struct inode *ip;
- doff_t offset;
- char *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");
-}
-
-/*
- * Do consistency checking on a directory entry:
- * record length must be multiple of 4
- * entry must fit in rest of its DIRBLKSIZ block
- * record must be large enough to contain entry
- * name is not longer than MAXNAMLEN
- * name must be as long as advertised, and null terminated
- */
-/*
- * changed so that it confirms to ext2_check_dir_entry
- */
-static int
-ext2_dirbadentry(dp, de, entryoffsetinblock)
- struct vnode *dp;
- struct ext2_dir_entry_2 *de;
- int entryoffsetinblock;
-{
- int DIRBLKSIZ = VTOI(dp)->i_e2fs->s_blocksize;
-
- char * error_msg = NULL;
-
- if (de->rec_len < EXT2_DIR_REC_LEN(1))
- error_msg = "rec_len is smaller than minimal";
- else if (de->rec_len % 4 != 0)
- error_msg = "rec_len % 4 != 0";
- else if (de->rec_len < EXT2_DIR_REC_LEN(de->name_len))
- error_msg = "reclen is too small for name_len";
- else if (entryoffsetinblock + de->rec_len > DIRBLKSIZ)
- error_msg = "directory entry across blocks";
- /* else LATER
- if (de->inode > dir->i_sb->u.ext2_sb.s_es->s_inodes_count)
- error_msg = "inode out of bounds";
- */
-
- 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);
- }
- return error_msg == NULL ? 0 : 1;
-}
-
-/*
- * Write a directory entry after a call to namei, using the parameters
- * that it left in nameidata. The argument ip is the inode which the new
- * directory entry will refer to. Dvp is a pointer to the directory to
- * be written, which was left locked by namei. Remaining parameters
- * (dp->i_offset, dp->i_count) indicate how the space for the new
- * entry is to be obtained.
- */
-int
-ext2_direnter(ip, dvp, cnp)
- struct inode *ip;
- struct vnode *dvp;
- struct componentname *cnp;
-{
- struct ext2_dir_entry_2 *ep, *nep;
- struct inode *dp;
- struct buf *bp;
- struct ext2_dir_entry_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;
-
-
-#ifdef DIAGNOSTIC
- if ((cnp->cn_flags & SAVENAME) == 0)
- panic("direnter: missing name");
-#endif
- dp = VTOI(dvp);
- newdir.inode = ip->i_number;
- newdir.name_len = cnp->cn_namelen;
- if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs,
- EXT2_FEATURE_INCOMPAT_FILETYPE))
- newdir.file_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);
- if (dp->i_count == 0) {
- /*
- * If dp->i_count is 0, then namei could find no
- * space in the directory. Here, dp->i_offset will
- * be on a directory block boundary and we will write the
- * new entry into a fresh block.
- */
- if (dp->i_offset & (DIRBLKSIZ - 1))
- panic("ext2_direnter: newblk");
- auio.uio_offset = dp->i_offset;
- newdir.rec_len = DIRBLKSIZ;
- auio.uio_resid = newentrysize;
- aiov.iov_len = newentrysize;
- aiov.iov_base = (caddr_t)&newdir;
- auio.uio_iov = &aiov;
- auio.uio_iovcnt = 1;
- auio.uio_rw = UIO_WRITE;
- auio.uio_segflg = UIO_SYSSPACE;
- auio.uio_td = (struct thread *)0;
- error = VOP_WRITE(dvp, &auio, IO_SYNC, cnp->cn_cred);
- if (DIRBLKSIZ >
- VFSTOEXT2(dvp->v_mount)->um_mountp->mnt_stat.f_bsize)
- /* XXX should grow with balloc() */
- panic("ext2_direnter: frag size");
- else if (!error) {
- dp->i_size = roundup(dp->i_size, DIRBLKSIZ);
- dp->i_flag |= IN_CHANGE;
- }
- return (error);
- }
-
- /*
- * If dp->i_count is non-zero, then namei found space
- * for the new entry in the range dp->i_offset to
- * dp->i_offset + dp->i_count in the directory.
- * To use this space, we may have to compact the entries located
- * there, by copying them together towards the beginning of the
- * block, leaving the free space in one usable chunk at the end.
- */
-
- /*
- * Increase size of directory if entry eats into new space.
- * This should never push the size past a new multiple of
- * DIRBLKSIZE.
- *
- * N.B. - THIS IS AN ARTIFACT OF 4.2 AND SHOULD NEVER HAPPEN.
- */
- if (dp->i_offset + dp->i_count > dp->i_size)
- dp->i_size = dp->i_offset + dp->i_count;
- /*
- * Get the block containing the space for the new directory entry.
- */
- if ((error = ext2_blkatoff(dvp, (off_t)dp->i_offset, &dirbuf,
- &bp)) != 0)
- return (error);
- /*
- * Find space for the new entry. In the simple case, the entry at
- * offset base will have the space. If it does not, then namei
- * arranged that compacting the region dp->i_offset to
- * 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) {
- /* trim the existing slot */
- ep->rec_len = dsize;
- ep = (struct ext2_dir_entry_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;
- 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 (spacefree + dsize < newentrysize)
- panic("ext2_direnter: compact1");
- newdir.rec_len = 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);
- }
- bcopy((caddr_t)&newdir, (caddr_t)ep, (u_int)newentrysize);
- error = bwrite(bp);
- dp->i_flag |= IN_CHANGE | IN_UPDATE;
- if (!error && dp->i_endoff && dp->i_endoff < dp->i_size)
- error = ext2_truncate(dvp, (off_t)dp->i_endoff, IO_SYNC,
- cnp->cn_cred, cnp->cn_thread);
- return (error);
-}
-
-/*
- * Remove a directory entry after a call to namei, using
- * the parameters which it left in nameidata. The entry
- * dp->i_offset contains the offset into the directory of the
- * entry to be eliminated. The dp->i_count field contains the
- * size of the previous record in the directory. If this
- * is 0, the first entry is being deleted, so we need only
- * zero the inode number to mark the entry as free. If the
- * entry is not the first in the directory, we must reclaim
- * the space of the now empty record by adding the record size
- * to the size of the previous entry.
- */
-int
-ext2_dirremove(dvp, cnp)
- struct vnode *dvp;
- struct componentname *cnp;
-{
- struct inode *dp;
- struct ext2_dir_entry_2 *ep;
- struct buf *bp;
- int error;
-
- dp = VTOI(dvp);
- if (dp->i_count == 0) {
- /*
- * First entry in block: set d_ino to zero.
- */
- if ((error =
- ext2_blkatoff(dvp, (off_t)dp->i_offset, (char **)&ep,
- &bp)) != 0)
- return (error);
- ep->inode = 0;
- error = bwrite(bp);
- dp->i_flag |= IN_CHANGE | IN_UPDATE;
- return (error);
- }
- /*
- * Collapse new free space into previous entry.
- */
- 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;
- error = bwrite(bp);
- dp->i_flag |= IN_CHANGE | IN_UPDATE;
- return (error);
-}
-
-/*
- * Rewrite an existing directory entry to point at the inode
- * supplied. The parameters describing the directory entry are
- * set up by a call to namei.
- */
-int
-ext2_dirrewrite(dp, ip, cnp)
- struct inode *dp, *ip;
- struct componentname *cnp;
-{
- struct buf *bp;
- struct ext2_dir_entry_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;
- if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs,
- EXT2_FEATURE_INCOMPAT_FILETYPE))
- ep->file_type = DTTOFT(IFTODT(ip->i_mode));
- else
- ep->file_type = EXT2_FT_UNKNOWN;
- error = bwrite(bp);
- dp->i_flag |= IN_CHANGE | IN_UPDATE;
- return (error);
-}
-
-/*
- * Check if a directory is empty or not.
- * Inode supplied must be locked.
- *
- * Using a struct dirtemplate here is not precisely
- * what we want, but better than using a struct direct.
- *
- * NB: does not handle corrupted directories.
- */
-int
-ext2_dirempty(ip, parentino, cred)
- struct inode *ip;
- ino_t parentino;
- struct ucred *cred;
-{
- off_t off;
- struct dirtemplate dbuf;
- struct ext2_dir_entry_2 *dp = (struct ext2_dir_entry_2 *)&dbuf;
- int error, count, namlen;
-#define MINDIRSIZ (sizeof (struct dirtemplate) / 2)
-
- for (off = 0; off < ip->i_size; off += dp->rec_len) {
- error = vn_rdwr(UIO_READ, ITOV(ip), (caddr_t)dp, MINDIRSIZ,
- off, UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK, cred,
- NOCRED, &count, (struct thread *)0);
- /*
- * Since we read MINDIRSIZ, residual must
- * be 0 unless we're at end of file.
- */
- if (error || count != 0)
- return (0);
- /* avoid infinite loops */
- if (dp->rec_len == 0)
- return (0);
- /* skip empty entries */
- if (dp->inode == 0)
- continue;
- /* accept only "." and ".." */
- namlen = dp->name_len;
- if (namlen > 2)
- return (0);
- if (dp->name[0] != '.')
- return (0);
- /*
- * At this point namlen must be 1 or 2.
- * 1 implies ".", 2 implies ".." if second
- * char is also "."
- */
- if (namlen == 1)
- continue;
- if (dp->name[1] == '.' && dp->inode == parentino)
- continue;
- return (0);
- }
- return (1);
-}
-
-/*
- * Check if source directory is in the path of the target directory.
- * Target is supplied locked, source is unlocked.
- * The target is always vput before returning.
- */
-int
-ext2_checkpath(source, target, cred)
- struct inode *source, *target;
- struct ucred *cred;
-{
- struct vnode *vp;
- int error, rootino, namlen;
- struct dirtemplate dirbuf;
-
- vp = ITOV(target);
- if (target->i_number == source->i_number) {
- error = EEXIST;
- goto out;
- }
- rootino = ROOTINO;
- error = 0;
- if (target->i_number == rootino)
- goto out;
-
- for (;;) {
- if (vp->v_type != VDIR) {
- error = ENOTDIR;
- break;
- }
- error = vn_rdwr(UIO_READ, vp, (caddr_t)&dirbuf,
- sizeof (struct dirtemplate), (off_t)0, UIO_SYSSPACE,
- IO_NODELOCKED | IO_NOMACCHECK, cred, NOCRED, NULL,
- NULL);
- if (error != 0)
- break;
- namlen = dirbuf.dotdot_type; /* like ufs little-endian */
- if (namlen != 2 ||
- dirbuf.dotdot_name[0] != '.' ||
- dirbuf.dotdot_name[1] != '.') {
- error = ENOTDIR;
- break;
- }
- if (dirbuf.dotdot_ino == source->i_number) {
- error = EINVAL;
- break;
- }
- if (dirbuf.dotdot_ino == rootino)
- break;
- vput(vp);
- if ((error = VFS_VGET(vp->v_mount, dirbuf.dotdot_ino,
- LK_EXCLUSIVE, &vp)) != 0) {
- vp = NULL;
- break;
- }
- }
-
-out:
- if (error == ENOTDIR)
- printf("checkpath: .. not a directory\n");
- if (vp != NULL)
- vput(vp);
- return (error);
-}
diff --git a/sys/gnu/fs/ext2fs/ext2_mount.h b/sys/gnu/fs/ext2fs/ext2_mount.h
deleted file mode 100644
index 6be0c7d..0000000
--- a/sys/gnu/fs/ext2fs/ext2_mount.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*-
- * Copyright (c) 1982, 1986, 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)ufsmount.h 8.6 (Berkeley) 3/30/95
- * $FreeBSD$
- */
-
-#ifndef _SYS_GNU_EXT2FS_EXT2_MOUNT_H_
-#define _SYS_GNU_EXT2FS_EXT2_MOUNT_H_
-
-#ifdef _KERNEL
-
-#ifdef MALLOC_DECLARE
-MALLOC_DECLARE(M_EXT2NODE);
-#endif
-
-struct vnode;
-
-/* This structure describes the ext2fs specific mount structure data. */
-struct ext2mount {
- struct mount *um_mountp; /* filesystem vfs structure */
- struct cdev *um_dev; /* device mounted */
- struct vnode *um_devvp; /* block device mounted vnode */
-
- struct ext2_sb_info *um_e2fs; /* EXT2FS */
-#define em_e2fsb um_e2fs->s_es
-
- u_long um_nindir; /* indirect ptrs per block */
- u_long um_bptrtodb; /* indir ptr to disk block */
- u_long um_seqinc; /* inc between seq blocks */
-
- struct g_consumer *um_cp;
- struct bufobj *um_bo;
-};
-
-/* Convert mount ptr to ext2fsmount ptr. */
-#define VFSTOEXT2(mp) ((struct ext2mount *)((mp)->mnt_data))
-
-/*
- * Macros to access file system parameters in the ufsmount structure.
- * Used by ufs_bmap.
- */
-#define MNINDIR(ump) ((ump)->um_nindir)
-#define blkptrtodb(ump, b) ((b) << (ump)->um_bptrtodb)
-#define is_sequential(ump, a, b) ((b) == (a) + ump->um_seqinc)
-#endif /* _KERNEL */
-
-#endif
diff --git a/sys/gnu/fs/ext2fs/ext2_readwrite.c b/sys/gnu/fs/ext2fs/ext2_readwrite.c
deleted file mode 100644
index e533392..0000000
--- a/sys/gnu/fs/ext2fs/ext2_readwrite.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/*-
- * modified for Lites 1.1
- *
- * Aug 1995, Godmar Back (gback@cs.utah.edu)
- * University of Utah, Department of Computer Science
- */
-/*-
- * Copyright (c) 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)ufs_readwrite.c 8.7 (Berkeley) 1/21/94
- * $FreeBSD$
- */
-
-#define BLKSIZE(a, b, c) blksize(a, b, c)
-#define FS struct ext2_sb_info
-#define I_FS i_e2fs
-#define READ ext2_read
-#define READ_S "ext2_read"
-#define WRITE ext2_write
-#define WRITE_S "ext2_write"
-
-/*
- * Vnode op for reading.
- */
-/* ARGSUSED */
-static int
-READ(ap)
- struct vop_read_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
-{
- struct vnode *vp;
- struct inode *ip;
- struct uio *uio;
- FS *fs;
- struct buf *bp;
- daddr_t lbn, nextlbn;
- off_t bytesinfile;
- long size, xfersize, blkoffset;
- int error, orig_resid;
- int seqcount = ap->a_ioflag >> IO_SEQSHIFT;
- u_short mode;
-
- vp = ap->a_vp;
- ip = VTOI(vp);
- mode = ip->i_mode;
- uio = ap->a_uio;
-
-#ifdef DIAGNOSTIC
- if (uio->uio_rw != UIO_READ)
- panic("%s: mode", READ_S);
-
- if (vp->v_type == VLNK) {
- if ((int)ip->i_size < vp->v_mount->mnt_maxsymlinklen)
- panic("%s: short symlink", READ_S);
- } else if (vp->v_type != VREG && vp->v_type != VDIR)
- panic("%s: type %d", READ_S, vp->v_type);
-#endif
- fs = ip->I_FS;
- if ((uoff_t)uio->uio_offset > fs->fs_maxfilesize)
- return (EFBIG);
-
- orig_resid = uio->uio_resid;
- for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) {
- if ((bytesinfile = ip->i_size - uio->uio_offset) <= 0)
- break;
- lbn = lblkno(fs, uio->uio_offset);
- nextlbn = lbn + 1;
- size = BLKSIZE(fs, ip, lbn);
- blkoffset = blkoff(fs, uio->uio_offset);
-
- xfersize = fs->s_frag_size - blkoffset;
- if (uio->uio_resid < xfersize)
- xfersize = uio->uio_resid;
- if (bytesinfile < xfersize)
- xfersize = bytesinfile;
-
- if (lblktosize(fs, nextlbn) >= ip->i_size)
- error = bread(vp, lbn, size, NOCRED, &bp);
- else if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0)
- error = cluster_read(vp,
- ip->i_size, lbn, size, NOCRED,
- uio->uio_resid, (ap->a_ioflag >> IO_SEQSHIFT), &bp);
- else if (seqcount > 1) {
- int nextsize = BLKSIZE(fs, ip, nextlbn);
- error = breadn(vp, lbn,
- size, &nextlbn, &nextsize, 1, NOCRED, &bp);
- } else
- error = bread(vp, lbn, size, NOCRED, &bp);
- if (error) {
- brelse(bp);
- bp = NULL;
- break;
- }
-
- /*
- * We should only get non-zero b_resid when an I/O error
- * has occurred, which should cause us to break above.
- * However, if the short read did not cause an error,
- * then we want to ensure that we do not uiomove bad
- * or uninitialized data.
- */
- size -= bp->b_resid;
- if (size < xfersize) {
- if (size == 0)
- break;
- xfersize = size;
- }
- error =
- uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio);
- if (error)
- break;
-
- bqrelse(bp);
- }
- if (bp != NULL)
- bqrelse(bp);
- if (orig_resid > 0 && (error == 0 || uio->uio_resid != orig_resid) &&
- (vp->v_mount->mnt_flag & MNT_NOATIME) == 0)
- ip->i_flag |= IN_ACCESS;
- return (error);
-}
-
-/*
- * Vnode op for writing.
- */
-static int
-WRITE(ap)
- struct vop_write_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
-{
- struct vnode *vp;
- struct uio *uio;
- struct inode *ip;
- FS *fs;
- struct buf *bp;
- struct thread *td;
- daddr_t lbn;
- off_t osize;
- int seqcount;
- int blkoffset, error, flags, ioflag, resid, size, xfersize;
-
- ioflag = ap->a_ioflag;
- seqcount = ap->a_ioflag >> IO_SEQSHIFT;
- uio = ap->a_uio;
- vp = ap->a_vp;
- ip = VTOI(vp);
-
-#ifdef DIAGNOSTIC
- if (uio->uio_rw != UIO_WRITE)
- panic("%s: mode", WRITE_S);
-#endif
-
- switch (vp->v_type) {
- case VREG:
- if (ioflag & IO_APPEND)
- uio->uio_offset = ip->i_size;
- if ((ip->i_flags & APPEND) && uio->uio_offset != ip->i_size)
- return (EPERM);
- /* FALLTHROUGH */
- case VLNK:
- break;
- case VDIR:
- if ((ioflag & IO_SYNC) == 0)
- panic("%s: nonsync dir write", WRITE_S);
- break;
- default:
- panic("%s: type", WRITE_S);
- }
-
- fs = ip->I_FS;
- if (uio->uio_offset < 0 ||
- (uoff_t)uio->uio_offset + uio->uio_resid > fs->fs_maxfilesize)
- return (EFBIG);
- /*
- * Maybe this should be above the vnode op call, but so long as
- * file servers have no limits, I don't think it matters.
- */
- td = uio->uio_td;
- if (vp->v_type == VREG && td != NULL) {
- PROC_LOCK(td->td_proc);
- if (uio->uio_offset + uio->uio_resid >
- lim_cur(td->td_proc, RLIMIT_FSIZE)) {
- psignal(td->td_proc, SIGXFSZ);
- PROC_UNLOCK(td->td_proc);
- return (EFBIG);
- }
- PROC_UNLOCK(td->td_proc);
- }
-
- resid = uio->uio_resid;
- osize = ip->i_size;
- flags = ioflag & IO_SYNC ? B_SYNC : 0;
-
- for (error = 0; uio->uio_resid > 0;) {
- lbn = lblkno(fs, uio->uio_offset);
- blkoffset = blkoff(fs, uio->uio_offset);
- xfersize = fs->s_frag_size - blkoffset;
- if (uio->uio_resid < xfersize)
- xfersize = uio->uio_resid;
-
- if (uio->uio_offset + xfersize > ip->i_size)
- vnode_pager_setsize(vp, uio->uio_offset + xfersize);
-
- /*
- * Avoid a data-consistency race between write() and mmap()
- * by ensuring that newly allocated blocks are zerod. The
- * race can occur even in the case where the write covers
- * the entire block.
- */
- flags |= B_CLRBUF;
-#if 0
- if (fs->s_frag_size > xfersize)
- flags |= B_CLRBUF;
- else
- flags &= ~B_CLRBUF;
-#endif
-
- error = ext2_balloc(ip,
- lbn, blkoffset + xfersize, ap->a_cred, &bp, flags);
- if (error)
- break;
-
- if (uio->uio_offset + xfersize > ip->i_size) {
- ip->i_size = uio->uio_offset + xfersize;
- }
-
- size = BLKSIZE(fs, ip, lbn) - bp->b_resid;
- if (size < xfersize)
- xfersize = size;
-
- error =
- uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio);
- if ((ioflag & IO_VMIO) &&
- (LIST_FIRST(&bp->b_dep) == NULL)) /* in ext2fs? */
- bp->b_flags |= B_RELBUF;
-
- if (ioflag & IO_SYNC) {
- (void)bwrite(bp);
- } else if (xfersize + blkoffset == fs->s_frag_size) {
- if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERW) == 0) {
- bp->b_flags |= B_CLUSTEROK;
- cluster_write(vp, bp, ip->i_size, seqcount);
- } else {
- bawrite(bp);
- }
- } else {
- bp->b_flags |= B_CLUSTEROK;
- bdwrite(bp);
- }
- if (error || xfersize == 0)
- break;
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
- }
- /*
- * If we successfully wrote any data, and we are not the superuser
- * we clear the setuid and setgid bits as a precaution against
- * tampering.
- */
- if (resid > uio->uio_resid && ap->a_cred && ap->a_cred->cr_uid != 0)
- ip->i_mode &= ~(ISUID | ISGID);
- if (error) {
- if (ioflag & IO_UNIT) {
- (void)ext2_truncate(vp, osize,
- ioflag & IO_SYNC, ap->a_cred, uio->uio_td);
- uio->uio_offset -= resid - uio->uio_resid;
- uio->uio_resid = resid;
- }
- } else if (resid > uio->uio_resid && (ioflag & IO_SYNC))
- error = ext2_update(vp, 1);
- return (error);
-}
diff --git a/sys/gnu/fs/ext2fs/ext2_subr.c b/sys/gnu/fs/ext2fs/ext2_subr.c
deleted file mode 100644
index 5617842..0000000
--- a/sys/gnu/fs/ext2fs/ext2_subr.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*-
- * modified for Lites 1.1
- *
- * Aug 1995, Godmar Back (gback@cs.utah.edu)
- * University of Utah, Department of Computer Science
- */
-/*-
- * Copyright (c) 1982, 1986, 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)ffs_subr.c 8.2 (Berkeley) 9/21/93
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-
-#include <sys/proc.h>
-#include <sys/systm.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-#include <sys/lock.h>
-#include <sys/ucred.h>
-#include <sys/vnode.h>
-
-#include <gnu/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>
-
-#ifdef KDB
-void ext2_checkoverlap(struct buf *, struct inode *);
-#endif
-
-/*
- * Return buffer with the contents of block "offset" from the beginning of
- * directory "ip". If "res" is non-zero, fill it in with a pointer to the
- * remaining space in the directory.
- */
-int
-ext2_blkatoff(vp, offset, res, bpp)
- struct vnode *vp;
- off_t offset;
- char **res;
- struct buf **bpp;
-{
- struct inode *ip;
- struct ext2_sb_info *fs;
- struct buf *bp;
- int32_t lbn;
- int bsize, error;
-
- ip = VTOI(vp);
- fs = ip->i_e2fs;
- lbn = lblkno(fs, offset);
- bsize = blksize(fs, ip, lbn);
-
- *bpp = NULL;
- if ((error = bread(vp, lbn, bsize, NOCRED, &bp)) != 0) {
- brelse(bp);
- return (error);
- }
- if (res)
- *res = (char *)bp->b_data + blkoff(fs, offset);
- *bpp = bp;
- return (0);
-}
-
-#ifdef KDB
-void
-ext2_checkoverlap(bp, ip)
- struct buf *bp;
- struct inode *ip;
-{
- struct buf *ebp, *ep;
- int32_t start, last;
- struct vnode *vp;
-
- ebp = &buf[nbuf];
- start = bp->b_blkno;
- last = start + btodb(bp->b_bcount) - 1;
- for (ep = buf; ep < ebp; ep++) {
- if (ep == bp || (ep->b_flags & B_INVAL))
- continue;
- vp = ip->i_devvp;
- /* look for overlap */
- if (ep->b_bcount == 0 || ep->b_blkno > last ||
- ep->b_blkno + btodb(ep->b_bcount) <= start)
- continue;
- vprint("Disk overlap", vp);
- (void)printf("\tstart %d, end %d overlap start %lld, end %ld\n",
- start, last, (long long)ep->b_blkno,
- (long)(ep->b_blkno + btodb(ep->b_bcount) - 1));
- panic("Disk buffer overlap");
- }
-}
-#endif /* KDB */
diff --git a/sys/gnu/fs/ext2fs/ext2_vfsops.c b/sys/gnu/fs/ext2fs/ext2_vfsops.c
deleted file mode 100644
index 20c44ef..0000000
--- a/sys/gnu/fs/ext2fs/ext2_vfsops.c
+++ /dev/null
@@ -1,1122 +0,0 @@
-/*-
- * modified for EXT2FS support in Lites 1.1
- *
- * Aug 1995, Godmar Back (gback@cs.utah.edu)
- * University of Utah, Department of Computer Science
- */
-/*-
- * Copyright (c) 1989, 1991, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)ffs_vfsops.c 8.8 (Berkeley) 4/18/94
- * $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>
-#include <sys/priv.h>
-#include <sys/proc.h>
-#include <sys/kernel.h>
-#include <sys/vnode.h>
-#include <sys/mount.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-#include <sys/conf.h>
-#include <sys/fcntl.h>
-#include <sys/malloc.h>
-#include <sys/stat.h>
-#include <sys/mutex.h>
-
-#include <geom/geom.h>
-#include <geom/geom_vfs.h>
-
-#include <gnu/fs/ext2fs/ext2_mount.h>
-#include <gnu/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>
-
-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 vfs_unmount_t ext2_unmount;
-static vfs_root_t ext2_root;
-static vfs_statfs_t ext2_statfs;
-static vfs_sync_t ext2_sync;
-static vfs_vget_t ext2_vget;
-static vfs_fhtovp_t ext2_fhtovp;
-static vfs_mount_t ext2_mount;
-
-MALLOC_DEFINE(M_EXT2NODE, "ext2_node", "EXT2 vnode private part");
-static MALLOC_DEFINE(M_EXT2MNT, "ext2_mount", "EXT2 mount structure");
-
-static struct vfsops ext2fs_vfsops = {
- .vfs_fhtovp = ext2_fhtovp,
- .vfs_mount = ext2_mount,
- .vfs_root = ext2_root, /* root inode via vget */
- .vfs_statfs = ext2_statfs,
- .vfs_sync = ext2_sync,
- .vfs_unmount = ext2_unmount,
- .vfs_vget = ext2_vget,
-};
-
-VFS_SET(ext2fs_vfsops, ext2fs, 0);
-
-static int ext2_check_sb_compat(struct ext2_super_block *es, struct cdev *dev,
- int ronly);
-static int compute_sb_data(struct vnode * devvp,
- struct ext2_super_block * es, struct ext2_sb_info * fs);
-
-static const char *ext2_opts[] = { "from", "export", "acls", "noexec",
- "noatime", "union", "suiddir", "multilabel", "nosymfollow",
- "noclusterr", "noclusterw", "force", NULL };
-
-/*
- * VFS Operations.
- *
- * mount system call
- */
-static int
-ext2_mount(struct mount *mp)
-{
- struct vfsoptlist *opts;
- struct vnode *devvp;
- struct thread *td;
- struct ext2mount *ump = 0;
- struct ext2_sb_info *fs;
- struct nameidata nd, *ndp = &nd;
- accmode_t accmode;
- char *path, *fspec;
- int error, flags, len;
-
- td = curthread;
- opts = mp->mnt_optnew;
-
- if (vfs_filteropt(opts, ext2_opts))
- return (EINVAL);
-
- vfs_getopt(opts, "fspath", (void **)&path, NULL);
- /* Double-check the length of path.. */
- if (strlen(path) >= MAXMNTLEN - 1)
- return (ENAMETOOLONG);
-
- fspec = NULL;
- error = vfs_getopt(opts, "from", (void **)&fspec, &len);
- if (!error && fspec[len - 1] != '\0')
- return (EINVAL);
-
- /*
- * If updating, check whether changing from read-only to
- * read/write; if there is no device name, that's all we do.
- */
- if (mp->mnt_flag & MNT_UPDATE) {
- ump = VFSTOEXT2(mp);
- fs = ump->um_e2fs;
- error = 0;
- if (fs->s_rd_only == 0 &&
- vfs_flagopt(opts, "ro", NULL, 0)) {
- error = VFS_SYNC(mp, MNT_WAIT);
- if (error)
- return (error);
- 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;
- ext2_sbupdate(ump, MNT_WAIT);
- }
- fs->s_rd_only = 1;
- vfs_flagopt(opts, "ro", &mp->mnt_flag, MNT_RDONLY);
- DROP_GIANT();
- g_topology_lock();
- g_access(ump->um_cp, 0, -1, 0);
- g_topology_unlock();
- PICKUP_GIANT();
- }
- if (!error && (mp->mnt_flag & MNT_RELOAD))
- error = ext2_reload(mp, td);
- 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))
- return (EPERM);
-
- /*
- * If upgrade to read-write by non-root, then verify
- * that user has necessary permissions on the device.
- */
- vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
- error = VOP_ACCESS(devvp, VREAD | VWRITE,
- td->td_ucred, td);
- if (error)
- error = priv_check(td, PRIV_VFS_MOUNT_PERM);
- if (error) {
- VOP_UNLOCK(devvp, 0);
- return (error);
- }
- VOP_UNLOCK(devvp, 0);
- DROP_GIANT();
- g_topology_lock();
- error = g_access(ump->um_cp, 0, 1, 0);
- g_topology_unlock();
- PICKUP_GIANT();
- if (error)
- return (error);
-
- if ((fs->s_es->s_state & EXT2_VALID_FS) == 0 ||
- (fs->s_es->s_state & EXT2_ERROR_FS)) {
- if (mp->mnt_flag & MNT_FORCE) {
- printf(
-"WARNING: %s was not properly dismounted\n", fs->fs_fsmnt);
- } else {
- printf(
-"WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n",
- fs->fs_fsmnt);
- return (EPERM);
- }
- }
- fs->s_es->s_state &= ~EXT2_VALID_FS;
- ext2_sbupdate(ump, MNT_WAIT);
- fs->s_rd_only = 0;
- MNT_ILOCK(mp);
- mp->mnt_flag &= ~MNT_RDONLY;
- MNT_IUNLOCK(mp);
- }
- if (vfs_flagopt(opts, "export", NULL, 0)) {
- /* Process export requests in vfs_mount.c. */
- return (error);
- }
- }
-
- /*
- * Not an update, or updating the name: look up the name
- * and verify that it refers to a sensible disk device.
- */
- if (fspec == NULL)
- return (EINVAL);
- NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspec, td);
- if ((error = namei(ndp)) != 0)
- return (error);
- NDFREE(ndp, NDF_ONLY_PNBUF);
- devvp = ndp->ni_vp;
-
- if (!vn_isdisk(devvp, &error)) {
- vput(devvp);
- return (error);
- }
-
- /*
- * If mount by non-root, then verify that user has necessary
- * permissions on the device.
- *
- * XXXRW: VOP_ACCESS() enough?
- */
- accmode = VREAD;
- if ((mp->mnt_flag & MNT_RDONLY) == 0)
- accmode |= VWRITE;
- error = VOP_ACCESS(devvp, accmode, td->td_ucred, td);
- if (error)
- error = priv_check(td, PRIV_VFS_MOUNT_PERM);
- if (error) {
- vput(devvp);
- return (error);
- }
-
- if ((mp->mnt_flag & MNT_UPDATE) == 0) {
- error = ext2_mountfs(devvp, mp);
- } else {
- if (devvp != ump->um_devvp) {
- vput(devvp);
- return (EINVAL); /* needs translation */
- } else
- vput(devvp);
- }
- if (error) {
- vrele(devvp);
- return (error);
- }
- ump = VFSTOEXT2(mp);
- fs = ump->um_e2fs;
-
- /*
- * 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';
- 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)
-{
- 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) {
- printf("ext2fs: %s: wrong magic number %#x (expected %#x)\n",
- devtoname(dev), es->s_magic, EXT2_SUPER_MAGIC);
- return (1);
- }
- if (es->s_rev_level > EXT2_GOOD_OLD_REV) {
- if (es->s_feature_incompat & ~EXT2_FEATURE_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)) {
- printf("WARNING: R/W mount of %s denied due to "
- "unsupported optional features\n", devtoname(dev));
- return (1);
- }
- }
- return (0);
-}
-
-/*
- * This computes the fields of the ext2_sb_info structure from the
- * 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)
-{
- int db_count, error;
- int i, j;
- int logic_sb_block = 1; /* XXX for now */
-
- 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;
- } else {
- fs->s_first_ino = es->s_first_ino;
- fs->s_inode_size = es->s_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) {
- printf("EXT2-fs: invalid inode size %d\n",
- fs->s_inode_size);
- 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);
- /* s_resuid / s_resgid ? */
- fs->s_groups_count = (es->s_blocks_count - es->s_first_data_block +
- EXT2_BLOCKS_PER_GROUP(fs) - 1) / EXT2_BLOCKS_PER_GROUP(fs);
- db_count = (fs->s_groups_count + 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 *),
- M_EXT2MNT, M_WAITOK);
-
- /*
- * Adjust logic_sb_block.
- * Godmar thinks: if the blocksize is greater than 1024, then
- * the superblock is logically part of block zero.
- */
- if(fs->s_blocksize > 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);
- }
- 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);
- }
- 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->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;
- else
- fs->fs_maxfilesize = 0x7fffffffffffffff;
- return (0);
-}
-
-/*
- * Reload all incore data for a filesystem (used after running fsck on
- * the root filesystem and finding things to fix). The filesystem must
- * be mounted read-only.
- *
- * Things to do to update the mount:
- * 1) invalidate all cached meta-data.
- * 2) re-read superblock from disk.
- * 3) re-read summary information from disk.
- * 4) invalidate all inactive vnodes.
- * 5) invalidate all cached file data.
- * 6) re-read inode data for all active vnodes.
- */
-static int
-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;
- int error;
-
- if ((mp->mnt_flag & MNT_RDONLY) == 0)
- return (EINVAL);
- /*
- * Step 1: invalidate all cached meta-data.
- */
- devvp = VFSTOEXT2(mp)->um_devvp;
- vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
- if (vinvalbuf(devvp, 0, 0, 0) != 0)
- panic("ext2_reload: dirty1");
- VOP_UNLOCK(devvp, 0);
-
- /*
- * Step 2: re-read superblock from disk.
- * constants have been adjusted for ext2
- */
- if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0)
- return (error);
- es = (struct ext2_super_block *)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));
-
- if((error = compute_sb_data(devvp, es, fs)) != 0) {
- brelse(bp);
- return (error);
- }
-#ifdef UNKLAR
- if (fs->fs_sbsize < SBSIZE)
- bp->b_flags |= B_INVAL;
-#endif
- brelse(bp);
-
-loop:
- MNT_ILOCK(mp);
- MNT_VNODE_FOREACH(vp, mp, mvp) {
- VI_LOCK(vp);
- if (vp->v_iflag & VI_DOOMED) {
- VI_UNLOCK(vp);
- continue;
- }
- MNT_IUNLOCK(mp);
- /*
- * Step 4: invalidate all cached file data.
- */
- if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
- MNT_VNODE_FOREACH_ABORT(mp, mvp);
- goto loop;
- }
- if (vinvalbuf(vp, 0, 0, 0))
- panic("ext2_reload: dirty2");
-
- /*
- * Step 5: re-read inode data for all active vnodes.
- */
- ip = VTOI(vp);
- error = bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
- (int)fs->s_blocksize, 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_INODE_SIZE(fs) * ino_to_fsbo(fs, ip->i_number)), ip);
- brelse(bp);
- VOP_UNLOCK(vp, 0);
- vrele(vp);
- MNT_ILOCK(mp);
- }
- MNT_IUNLOCK(mp);
- return (0);
-}
-
-/*
- * Common code for mount and mountroot.
- */
-static int
-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 cdev *dev = devvp->v_rdev;
- struct g_consumer *cp;
- struct bufobj *bo;
- int error;
- int ronly;
-
- ronly = vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0);
- /* XXX: use VOP_ACESS to check FS perms */
- DROP_GIANT();
- g_topology_lock();
- error = g_vfs_open(devvp, &cp, "ext2fs", ronly ? 0 : 1);
- g_topology_unlock();
- PICKUP_GIANT();
- VOP_UNLOCK(devvp, 0);
- if (error)
- return (error);
-
- /* XXX: should we check for some sectorsize or 512 instead? */
- if (((SBSIZE % cp->provider->sectorsize) != 0) ||
- (SBSIZE < cp->provider->sectorsize)) {
- DROP_GIANT();
- g_topology_lock();
- g_vfs_close(cp);
- g_topology_unlock();
- PICKUP_GIANT();
- return (EINVAL);
- }
-
- bo = &devvp->v_bufobj;
- bo->bo_private = cp;
- bo->bo_ops = g_vfs_bufops;
- if (devvp->v_rdev->si_iosize_max != 0)
- mp->mnt_iosize_max = devvp->v_rdev->si_iosize_max;
- if (mp->mnt_iosize_max > MAXPHYS)
- mp->mnt_iosize_max = MAXPHYS;
-
- bp = NULL;
- ump = NULL;
- if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0)
- goto out;
- es = (struct ext2_super_block *)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 (ronly || (mp->mnt_flag & MNT_FORCE)) {
- printf(
-"WARNING: Filesystem was not properly dismounted\n");
- } else {
- printf(
-"WARNING: R/W mount denied. Filesystem is not clean - run fsck\n");
- error = EPERM;
- goto out;
- }
- }
- ump = malloc(sizeof *ump, M_EXT2MNT, M_WAITOK);
- bzero((caddr_t)ump, sizeof *ump);
-
- /*
- * I don't know whether this is the right strategy. Note that
- * 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),
- M_EXT2MNT, M_WAITOK);
- ump->um_e2fs->s_es = malloc(sizeof(struct ext2_super_block),
- 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)))
- 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 */
-
- /*
- * 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;
- if (ronly == 0) {
- fs->s_dirt = 1; /* mark it modified */
- fs->s_es->s_state &= ~EXT2_VALID_FS; /* set fs invalid */
- }
- mp->mnt_data = ump;
- mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
- mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
- mp->mnt_maxsymlinklen = EXT2_MAXSYMLINKLEN;
- MNT_ILOCK(mp);
- mp->mnt_flag |= MNT_LOCAL;
- MNT_IUNLOCK(mp);
- ump->um_mountp = mp;
- ump->um_dev = dev;
- ump->um_devvp = devvp;
- ump->um_bo = &devvp->v_bufobj;
- ump->um_cp = cp;
-
- /*
- * Setting those two parameters allowed us to use
- * 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_seqinc = EXT2_FRAGS_PER_BLOCK(fs);
- if (ronly == 0)
- ext2_sbupdate(ump, MNT_WAIT);
- return (0);
-out:
- if (bp)
- brelse(bp);
- if (cp != NULL) {
- DROP_GIANT();
- g_topology_lock();
- g_vfs_close(cp);
- g_topology_unlock();
- PICKUP_GIANT();
- }
- if (ump) {
- free(ump->um_e2fs->s_es, M_EXT2MNT);
- free(ump->um_e2fs, M_EXT2MNT);
- free(ump, M_EXT2MNT);
- mp->mnt_data = NULL;
- }
- return (error);
-}
-
-/*
- * Unmount system call.
- */
-static int
-ext2_unmount(struct mount *mp, int mntflags)
-{
- struct ext2mount *ump;
- struct ext2_sb_info *fs;
- int error, flags, ronly, i;
-
- flags = 0;
- if (mntflags & MNT_FORCE) {
- if (mp->mnt_flag & MNT_ROOTFS)
- return (EINVAL);
- flags |= FORCECLOSE;
- }
- if ((error = ext2_flushfiles(mp, flags, curthread)) != 0)
- 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);
- }
-
- /* 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, M_EXT2MNT);
- free(ump, M_EXT2MNT);
- mp->mnt_data = NULL;
- MNT_ILOCK(mp);
- mp->mnt_flag &= ~MNT_LOCAL;
- MNT_IUNLOCK(mp);
- return (error);
-}
-
-/*
- * Flush out all the files in a filesystem.
- */
-static int
-ext2_flushfiles(struct mount *mp, int flags, struct thread *td)
-{
- int error;
-
- error = vflush(mp, 0, flags, td);
- return (error);
-}
-
-/*
- * Get file system statistics.
- * taken from ext2/super.c ext2_statfs.
- */
-static 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;
-
- ump = VFSTOEXT2(mp);
- fs = ump->um_e2fs;
- es = fs->s_es;
-
- if (es->s_magic != EXT2_SUPER_MAGIC)
- panic("ext2_statfs - magic number spoiled");
-
- /*
- * 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);
-
- 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;
- return (0);
-}
-
-/*
- * Go through the disk queues to initiate sandbagged IO;
- * go through the inodes to write those that have been modified;
- * initiate the writing of the super block if it has been modified.
- *
- * Note: we are always called with the filesystem marked `MPBUSY'.
- */
-static int
-ext2_sync(struct mount *mp, int waitfor)
-{
- struct vnode *mvp, *vp;
- struct thread *td;
- struct inode *ip;
- struct ext2mount *ump = VFSTOEXT2(mp);
- struct ext2_sb_info *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);
- panic("ext2_sync: rofs mod");
- }
-
- /*
- * Write back each (modified) inode.
- */
- MNT_ILOCK(mp);
-loop:
- MNT_VNODE_FOREACH(vp, mp, mvp) {
- VI_LOCK(vp);
- if (vp->v_type == VNON || (vp->v_iflag & VI_DOOMED)) {
- VI_UNLOCK(vp);
- continue;
- }
- MNT_IUNLOCK(mp);
- ip = VTOI(vp);
- if ((ip->i_flag &
- (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
- (vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
- waitfor == MNT_LAZY)) {
- VI_UNLOCK(vp);
- MNT_ILOCK(mp);
- continue;
- }
- error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, td);
- if (error) {
- MNT_ILOCK(mp);
- if (error == ENOENT) {
- MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp);
- goto loop;
- }
- continue;
- }
- if ((error = VOP_FSYNC(vp, waitfor, td)) != 0)
- allerror = error;
- VOP_UNLOCK(vp, 0);
- vrele(vp);
- MNT_ILOCK(mp);
- }
- MNT_IUNLOCK(mp);
-
- /*
- * Force stale file system control information to be flushed.
- */
- if (waitfor != MNT_LAZY) {
- vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
- if ((error = VOP_FSYNC(ump->um_devvp, waitfor, td)) != 0)
- allerror = error;
- VOP_UNLOCK(ump->um_devvp, 0);
- }
-
- /*
- * 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)
- allerror = error;
- }
- return (allerror);
-}
-
-/*
- * Look up an EXT2FS dinode number to find its incore vnode, otherwise read it
- * in from disk. If it is in core, wait for the lock bit to clear, then
- * return the inode locked. Detection and handling of mount points must be
- * done by the calling routine.
- */
-static int
-ext2_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
-{
- struct ext2_sb_info *fs;
- struct inode *ip;
- struct ext2mount *ump;
- struct buf *bp;
- struct vnode *vp;
- struct cdev *dev;
- struct thread *td;
- int i, error;
- int used_blocks;
-
- td = curthread;
- error = vfs_hash_get(mp, ino, flags, td, vpp, NULL, NULL);
- if (error || *vpp != NULL)
- return (error);
-
- ump = VFSTOEXT2(mp);
- dev = ump->um_dev;
-
- /*
- * If this malloc() is performed after the getnewvnode()
- * it might block, leaving a vnode with a NULL v_data to be
- * found by ext2_sync() if a sync happens to fire right then,
- * which will cause a panic because ext2_sync() blindly
- * dereferences vp->v_data (as well it should).
- */
- ip = malloc(sizeof(struct inode), M_EXT2NODE, M_WAITOK | M_ZERO);
-
- /* Allocate a new vnode/inode. */
- if ((error = getnewvnode("ext2fs", mp, &ext2_vnodeops, &vp)) != 0) {
- *vpp = NULL;
- free(ip, M_EXT2NODE);
- return (error);
- }
- vp->v_data = ip;
- ip->i_vnode = vp;
- ip->i_e2fs = fs = ump->um_e2fs;
- ip->i_number = ino;
-
- lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL);
- error = insmntque(vp, mp);
- if (error != 0) {
- free(ip, M_EXT2NODE);
- *vpp = NULL;
- return (error);
- }
- error = vfs_hash_insert(vp, ino, flags, td, vpp, NULL, NULL);
- if (error || *vpp != NULL)
- return (error);
-
- /* 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) {
- /*
- * 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);
- *vpp = NULL;
- return (error);
- }
- /* convert ext2 inode to dinode */
- ext2_ei2i((struct ext2_inode *) ((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;
- ip->i_next_alloc_goal = 0;
- ip->i_prealloc_count = 0;
- ip->i_prealloc_block = 0;
-
- /*
- * Now we want to make sure that block pointers for unused
- * blocks are zeroed out - ext2_balloc depends on this
- * 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;
- for(i = used_blocks; i < EXT2_NDIR_BLOCKS; i++)
- ip->i_db[i] = 0;
- }
-/*
- ext2_print_inode(ip);
-*/
- brelse(bp);
-
- /*
- * Initialize the vnode from the inode, check for aliases.
- * Note that the underlying vnode may have changed.
- */
- if ((error = ext2_vinit(mp, &ext2_fifoops, &vp)) != 0) {
- vput(vp);
- *vpp = NULL;
- return (error);
- }
-
- /*
- * Finish inode initialization now that aliasing has been resolved.
- */
- ip->i_devvp = ump->um_devvp;
-
- /*
- * Set up a generation number for this inode if it does not
- * already have one. This should only happen on old filesystems.
- */
- if (ip->i_gen == 0) {
- ip->i_gen = random() / 2 + 1;
- if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
- ip->i_flag |= IN_MODIFIED;
- }
- *vpp = vp;
- return (0);
-}
-
-/*
- * File handle to vnode
- *
- * Have to be really careful about stale file handles:
- * - check that the inode number is valid
- * - call ext2_vget() to get the locked inode
- * - check for an unallocated inode (i_mode == 0)
- * - check that the given client host has export rights and return
- * those rights via. exflagsp and credanonp
- */
-static int
-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;
- 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)
- return (ESTALE);
-
- error = VFS_VGET(mp, ufhp->ufid_ino, LK_EXCLUSIVE, &nvp);
- if (error) {
- *vpp = NULLVP;
- return (error);
- }
- ip = VTOI(nvp);
- if (ip->i_mode == 0 ||
- ip->i_gen != ufhp->ufid_gen || ip->i_nlink <= 0) {
- vput(nvp);
- *vpp = NULLVP;
- return (ESTALE);
- }
- *vpp = nvp;
- vnode_create_vobject(*vpp, 0, curthread);
- return (0);
-}
-
-/*
- * Write a superblock and associated information back to disk.
- */
-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 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));
- if (waitfor == MNT_WAIT)
- error = bwrite(bp);
- else
- bawrite(bp);
-
- /*
- * The buffers for group descriptors, inode bitmaps and block bitmaps
- * are not busy at this point and are (hopefully) written by the
- * usual sync mechanism. No need to write them here.
- */
- return (error);
-}
-
-/*
- * Return the root of a filesystem.
- */
-static int
-ext2_root(struct mount *mp, int flags, struct vnode **vpp)
-{
- struct vnode *nvp;
- int error;
-
- error = VFS_VGET(mp, (ino_t)ROOTINO, LK_EXCLUSIVE, &nvp);
- if (error)
- return (error);
- *vpp = nvp;
- return (0);
-}
diff --git a/sys/gnu/fs/ext2fs/ext2_vnops.c b/sys/gnu/fs/ext2fs/ext2_vnops.c
deleted file mode 100644
index 6b44b9b..0000000
--- a/sys/gnu/fs/ext2fs/ext2_vnops.c
+++ /dev/null
@@ -1,1649 +0,0 @@
-/*-
- * modified for EXT2FS support in Lites 1.1
- *
- * Aug 1995, Godmar Back (gback@cs.utah.edu)
- * University of Utah, Department of Computer Science
- */
-/*-
- * Copyright (c) 1982, 1986, 1989, 1993
- * The Regents of the University of California. All rights reserved.
- * (c) UNIX System Laboratories, Inc.
- * All or some portions of this file are derived from material licensed
- * to the University of California by American Telephone and Telegraph
- * Co. or Unix System Laboratories, Inc. and are reproduced herein with
- * the permission of UNIX System Laboratories, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)ufs_vnops.c 8.7 (Berkeley) 2/3/94
- * @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95
- * $FreeBSD$
- */
-
-#include "opt_suiddir.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/resourcevar.h>
-#include <sys/kernel.h>
-#include <sys/fcntl.h>
-#include <sys/stat.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-#include <sys/endian.h>
-#include <sys/priv.h>
-#include <sys/proc.h>
-#include <sys/mount.h>
-#include <sys/unistd.h>
-#include <sys/time.h>
-#include <sys/vnode.h>
-#include <sys/namei.h>
-#include <sys/lockf.h>
-#include <sys/event.h>
-#include <sys/conf.h>
-#include <sys/file.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-#include <vm/vnode_pager.h>
-
-#include <fs/fifofs/fifo.h>
-
-#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>
-
-static int ext2_makeinode(int mode, struct vnode *, struct vnode **, struct componentname *);
-
-static vop_access_t ext2_access;
-static int ext2_chmod(struct vnode *, int, struct ucred *, struct thread *);
-static int ext2_chown(struct vnode *, uid_t, gid_t, struct ucred *,
- struct thread *);
-static vop_close_t ext2_close;
-static vop_create_t ext2_create;
-static vop_fsync_t ext2_fsync;
-static vop_getattr_t ext2_getattr;
-static vop_link_t ext2_link;
-static vop_mkdir_t ext2_mkdir;
-static vop_mknod_t ext2_mknod;
-static vop_open_t ext2_open;
-static vop_pathconf_t ext2_pathconf;
-static vop_print_t ext2_print;
-static vop_read_t ext2_read;
-static vop_readlink_t ext2_readlink;
-static vop_remove_t ext2_remove;
-static vop_rename_t ext2_rename;
-static vop_rmdir_t ext2_rmdir;
-static vop_setattr_t ext2_setattr;
-static vop_strategy_t ext2_strategy;
-static vop_symlink_t ext2_symlink;
-static vop_write_t ext2_write;
-static vop_vptofh_t ext2_vptofh;
-static vop_close_t ext2fifo_close;
-static vop_kqfilter_t ext2fifo_kqfilter;
-
-/* Global vfs data structures for ext2. */
-struct vop_vector ext2_vnodeops = {
- .vop_default = &default_vnodeops,
- .vop_access = ext2_access,
- .vop_bmap = ext2_bmap,
- .vop_cachedlookup = ext2_lookup,
- .vop_close = ext2_close,
- .vop_create = ext2_create,
- .vop_fsync = ext2_fsync,
- .vop_getattr = ext2_getattr,
- .vop_inactive = ext2_inactive,
- .vop_link = ext2_link,
- .vop_lookup = vfs_cache_lookup,
- .vop_mkdir = ext2_mkdir,
- .vop_mknod = ext2_mknod,
- .vop_open = ext2_open,
- .vop_pathconf = ext2_pathconf,
- .vop_poll = vop_stdpoll,
- .vop_print = ext2_print,
- .vop_read = ext2_read,
- .vop_readdir = ext2_readdir,
- .vop_readlink = ext2_readlink,
- .vop_reallocblks = ext2_reallocblks,
- .vop_reclaim = ext2_reclaim,
- .vop_remove = ext2_remove,
- .vop_rename = ext2_rename,
- .vop_rmdir = ext2_rmdir,
- .vop_setattr = ext2_setattr,
- .vop_strategy = ext2_strategy,
- .vop_symlink = ext2_symlink,
- .vop_write = ext2_write,
- .vop_vptofh = ext2_vptofh,
-};
-
-struct vop_vector ext2_fifoops = {
- .vop_default = &fifo_specops,
- .vop_access = ext2_access,
- .vop_close = ext2fifo_close,
- .vop_fsync = ext2_fsync,
- .vop_getattr = ext2_getattr,
- .vop_inactive = ext2_inactive,
- .vop_kqfilter = ext2fifo_kqfilter,
- .vop_print = ext2_print,
- .vop_read = VOP_PANIC,
- .vop_reclaim = ext2_reclaim,
- .vop_setattr = ext2_setattr,
- .vop_write = VOP_PANIC,
- .vop_vptofh = ext2_vptofh,
-};
-
-#include <gnu/fs/ext2fs/ext2_readwrite.c>
-
-/*
- * A virgin directory (no blushing please).
- * Note that the type and namlen fields are reversed relative to ext2.
- * Also, we don't use `struct odirtemplate', since it would just cause
- * endianness problems.
- */
-static struct dirtemplate mastertemplate = {
- 0, 12, 1, EXT2_FT_DIR, ".",
- 0, DIRBLKSIZ - 12, 2, EXT2_FT_DIR, ".."
-};
-static struct dirtemplate omastertemplate = {
- 0, 12, 1, EXT2_FT_UNKNOWN, ".",
- 0, DIRBLKSIZ - 12, 2, EXT2_FT_UNKNOWN, ".."
-};
-
-void
-ext2_itimes(vp)
- struct vnode *vp;
-{
- struct inode *ip;
- struct timespec ts;
-
- ip = VTOI(vp);
- if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) == 0)
- return;
- if ((vp->v_type == VBLK || vp->v_type == VCHR))
- ip->i_flag |= IN_LAZYMOD;
- else
- ip->i_flag |= IN_MODIFIED;
- if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
- vfs_timestamp(&ts);
- if (ip->i_flag & IN_ACCESS) {
- ip->i_atime = ts.tv_sec;
- ip->i_atimensec = ts.tv_nsec;
- }
- if (ip->i_flag & IN_UPDATE) {
- ip->i_mtime = ts.tv_sec;
- ip->i_mtimensec = ts.tv_nsec;
- ip->i_modrev++;
- }
- if (ip->i_flag & IN_CHANGE) {
- ip->i_ctime = ts.tv_sec;
- ip->i_ctimensec = ts.tv_nsec;
- }
- }
- ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE);
-}
-
-/*
- * Create a regular file
- */
-static int
-ext2_create(ap)
- struct vop_create_args /* {
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- } */ *ap;
-{
- int error;
-
- error =
- ext2_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
- ap->a_dvp, ap->a_vpp, ap->a_cnp);
- if (error)
- return (error);
- return (0);
-}
-
-static int
-ext2_open(ap)
- struct vop_open_args /* {
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
-{
-
- if (ap->a_vp->v_type == VBLK || ap->a_vp->v_type == VCHR)
- return (EOPNOTSUPP);
-
- /*
- * Files marked append-only must be opened for appending.
- */
- if ((VTOI(ap->a_vp)->i_flags & APPEND) &&
- (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE)
- return (EPERM);
-
- vnode_create_vobject(ap->a_vp, VTOI(ap->a_vp)->i_size, ap->a_td);
-
- return (0);
-}
-
-/*
- * Close called.
- *
- * Update the times on the inode.
- */
-static int
-ext2_close(ap)
- struct vop_close_args /* {
- struct vnode *a_vp;
- int a_fflag;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
-
- VI_LOCK(vp);
- if (vp->v_usecount > 1)
- ext2_itimes(vp);
- VI_UNLOCK(vp);
- return (0);
-}
-
-static int
-ext2_access(ap)
- struct vop_access_args /* {
- struct vnode *a_vp;
- accmode_t a_accmode;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
- struct inode *ip = VTOI(vp);
- accmode_t accmode = ap->a_accmode;
- int error;
-
- if (vp->v_type == VBLK || vp->v_type == VCHR)
- return (EOPNOTSUPP);
-
- /*
- * Disallow write attempts on read-only file systems;
- * unless the file is a socket, fifo, or a block or
- * character device resident on the file system.
- */
- if (accmode & VWRITE) {
- switch (vp->v_type) {
- case VDIR:
- case VLNK:
- case VREG:
- if (vp->v_mount->mnt_flag & MNT_RDONLY)
- return (EROFS);
- break;
- default:
- break;
- }
- }
-
- /* If immutable bit set, nobody gets to write it. */
- if ((accmode & VWRITE) && (ip->i_flags & (IMMUTABLE | SF_SNAPSHOT)))
- return (EPERM);
-
- error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid,
- ap->a_accmode, ap->a_cred, NULL);
- return (error);
-}
-
-static int
-ext2_getattr(ap)
- struct vop_getattr_args /* {
- struct vnode *a_vp;
- struct vattr *a_vap;
- struct ucred *a_cred;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
- struct inode *ip = VTOI(vp);
- struct vattr *vap = ap->a_vap;
-
- ext2_itimes(vp);
- /*
- * Copy from inode table
- */
- vap->va_fsid = dev2udev(ip->i_devvp->v_rdev);
- vap->va_fileid = ip->i_number;
- vap->va_mode = ip->i_mode & ~IFMT;
- vap->va_nlink = ip->i_nlink;
- vap->va_uid = ip->i_uid;
- vap->va_gid = ip->i_gid;
- vap->va_rdev = ip->i_rdev;
- vap->va_size = ip->i_size;
- vap->va_atime.tv_sec = ip->i_atime;
- vap->va_atime.tv_nsec = ip->i_atimensec;
- vap->va_mtime.tv_sec = ip->i_mtime;
- vap->va_mtime.tv_nsec = ip->i_mtimensec;
- vap->va_ctime.tv_sec = ip->i_ctime;
- vap->va_ctime.tv_nsec = ip->i_ctimensec;
- vap->va_flags = ip->i_flags;
- vap->va_gen = ip->i_gen;
- vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
- vap->va_bytes = dbtob((u_quad_t)ip->i_blocks);
- vap->va_type = IFTOVT(ip->i_mode);
- vap->va_filerev = ip->i_modrev;
- return (0);
-}
-
-/*
- * Set attribute vnode op. called from several syscalls
- */
-static int
-ext2_setattr(ap)
- struct vop_setattr_args /* {
- struct vnode *a_vp;
- struct vattr *a_vap;
- struct ucred *a_cred;
- } */ *ap;
-{
- struct vattr *vap = ap->a_vap;
- struct vnode *vp = ap->a_vp;
- struct inode *ip = VTOI(vp);
- struct ucred *cred = ap->a_cred;
- struct thread *td = curthread;
- int error;
-
- /*
- * Check for unsettable attributes.
- */
- if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
- (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
- (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
- ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
- 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);
- /*
- * Callers may only modify the file flags on objects they
- * have VADMIN rights for.
- */
- if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
- return (error);
- /*
- * Unprivileged processes and privileged processes in
- * jail() are not permitted to unset system flags, or
- * modify flags if any system flags are set.
- * Privileged non-jail processes may not modify system flags
- * if securelevel > 0 and any existing system flags are set.
- */
- if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0)) {
- if (ip->i_flags
- & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) {
- error = securelevel_gt(cred, 0);
- if (error)
- return (error);
- }
- 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)
- 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))
- return (0);
- }
- if (ip->i_flags & (IMMUTABLE | APPEND))
- return (EPERM);
- /*
- * Go through the fields and update iff not VNOVAL.
- */
- if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
- if (vp->v_mount->mnt_flag & MNT_RDONLY)
- return (EROFS);
- if ((error = ext2_chown(vp, vap->va_uid, vap->va_gid, cred,
- td)) != 0)
- return (error);
- }
- if (vap->va_size != VNOVAL) {
- /*
- * Disallow write attempts on read-only file systems;
- * unless the file is a socket, fifo, or a block or
- * character device resident on the file system.
- */
- switch (vp->v_type) {
- case VDIR:
- return (EISDIR);
- case VLNK:
- case VREG:
- if (vp->v_mount->mnt_flag & MNT_RDONLY)
- return (EROFS);
- break;
- default:
- break;
- }
- if ((error = ext2_truncate(vp, vap->va_size, 0, cred, td)) != 0)
- return (error);
- }
- if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
- if (vp->v_mount->mnt_flag & MNT_RDONLY)
- return (EROFS);
- /*
- * From utimes(2):
- * If times is NULL, ... The caller must be the owner of
- * the file, have permission to write the file, or be the
- * super-user.
- * If times is non-NULL, ... The caller must be the owner of
- * the file or be the super-user.
- */
- if ((error = VOP_ACCESS(vp, VADMIN, cred, td)) &&
- ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
- (error = VOP_ACCESS(vp, VWRITE, cred, td))))
- return (error);
- if (vap->va_atime.tv_sec != VNOVAL)
- ip->i_flag |= IN_ACCESS;
- if (vap->va_mtime.tv_sec != VNOVAL)
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
- ext2_itimes(vp);
- if (vap->va_atime.tv_sec != VNOVAL) {
- ip->i_atime = vap->va_atime.tv_sec;
- ip->i_atimensec = vap->va_atime.tv_nsec;
- }
- if (vap->va_mtime.tv_sec != VNOVAL) {
- ip->i_mtime = vap->va_mtime.tv_sec;
- ip->i_mtimensec = vap->va_mtime.tv_nsec;
- }
- error = ext2_update(vp, 0);
- if (error)
- return (error);
- }
- error = 0;
- if (vap->va_mode != (mode_t)VNOVAL) {
- if (vp->v_mount->mnt_flag & MNT_RDONLY)
- return (EROFS);
- error = ext2_chmod(vp, (int)vap->va_mode, cred, td);
- }
- return (error);
-}
-
-/*
- * Change the mode on a file.
- * Inode must be locked before calling.
- */
-static int
-ext2_chmod(vp, mode, cred, td)
- struct vnode *vp;
- int mode;
- struct ucred *cred;
- struct thread *td;
-{
- struct inode *ip = VTOI(vp);
- int error;
-
- /*
- * To modify the permissions on a file, must possess VADMIN
- * for that file.
- */
- if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
- return (error);
- /*
- * Privileged processes may set the sticky bit on non-directories,
- * as well as set the setgid bit on a file with a group that the
- * process is not a member of.
- */
- if (vp->v_type != VDIR && (mode & S_ISTXT)) {
- error = priv_check_cred(cred, PRIV_VFS_STICKYFILE, 0);
- if (error)
- return (EFTYPE);
- }
- if (!groupmember(ip->i_gid, cred) && (mode & ISGID)) {
- error = priv_check_cred(cred, PRIV_VFS_SETGID, 0);
- if (error)
- return (error);
- }
- ip->i_mode &= ~ALLPERMS;
- ip->i_mode |= (mode & ALLPERMS);
- ip->i_flag |= IN_CHANGE;
- return (0);
-}
-
-/*
- * Perform chown operation on inode ip;
- * inode must be locked prior to call.
- */
-static int
-ext2_chown(vp, uid, gid, cred, td)
- struct vnode *vp;
- uid_t uid;
- gid_t gid;
- struct ucred *cred;
- struct thread *td;
-{
- struct inode *ip = VTOI(vp);
- uid_t ouid;
- gid_t ogid;
- int error = 0;
-
- if (uid == (uid_t)VNOVAL)
- uid = ip->i_uid;
- if (gid == (gid_t)VNOVAL)
- gid = ip->i_gid;
- /*
- * To modify the ownership of a file, must possess VADMIN
- * for that file.
- */
- if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
- return (error);
- /*
- * To change the owner of a file, or change the group of a file
- * to a group of which we are not a member, the caller must
- * have privilege.
- */
- if (uid != ip->i_uid || (gid != ip->i_gid &&
- !groupmember(gid, cred))) {
- error = priv_check_cred(cred, PRIV_VFS_CHOWN, 0);
- if (error)
- return (error);
- }
- ogid = ip->i_gid;
- ouid = ip->i_uid;
- ip->i_gid = gid;
- ip->i_uid = uid;
- ip->i_flag |= IN_CHANGE;
- if ((ip->i_mode & (ISUID | ISGID)) && (ouid != uid || ogid != gid)) {
- if (priv_check_cred(cred, PRIV_VFS_RETAINSUGID, 0) != 0)
- ip->i_mode &= ~(ISUID | ISGID);
- }
- return (0);
-}
-
-/*
- * Synch an open file.
- */
-/* ARGSUSED */
-static int
-ext2_fsync(ap)
- struct vop_fsync_args /* {
- struct vnode *a_vp;
- struct ucred *a_cred;
- int a_waitfor;
- struct thread *a_td;
- } */ *ap;
-{
- /*
- * Flush all dirty buffers associated with a vnode.
- */
- ext2_discard_prealloc(VTOI(ap->a_vp));
-
- vop_stdfsync(ap);
-
- return (ext2_update(ap->a_vp, ap->a_waitfor == MNT_WAIT));
-}
-
-/*
- * Mknod vnode call
- */
-/* ARGSUSED */
-static int
-ext2_mknod(ap)
- struct vop_mknod_args /* {
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- } */ *ap;
-{
- struct vattr *vap = ap->a_vap;
- struct vnode **vpp = ap->a_vpp;
- struct inode *ip;
- ino_t ino;
- int error;
-
- error = ext2_makeinode(MAKEIMODE(vap->va_type, vap->va_mode),
- ap->a_dvp, vpp, ap->a_cnp);
- if (error)
- return (error);
- ip = VTOI(*vpp);
- ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
- if (vap->va_rdev != VNOVAL) {
- /*
- * Want to be able to use this to make badblock
- * inodes, so don't truncate the dev number.
- */
- ip->i_rdev = vap->va_rdev;
- }
- /*
- * Remove inode, then reload it through VFS_VGET so it is
- * checked to see if it is an alias of an existing entry in
- * the inode cache. XXX I don't believe this is necessary now.
- */
- (*vpp)->v_type = VNON;
- ino = ip->i_number; /* Save this before vgone() invalidates ip. */
- vgone(*vpp);
- vput(*vpp);
- error = VFS_VGET(ap->a_dvp->v_mount, ino, LK_EXCLUSIVE, vpp);
- if (error) {
- *vpp = NULL;
- return (error);
- }
- return (0);
-}
-
-static int
-ext2_remove(ap)
- struct vop_remove_args /* {
- struct vnode *a_dvp;
- struct vnode *a_vp;
- struct componentname *a_cnp;
- } */ *ap;
-{
- struct inode *ip;
- struct vnode *vp = ap->a_vp;
- struct vnode *dvp = ap->a_dvp;
- int error;
-
- ip = VTOI(vp);
- if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
- (VTOI(dvp)->i_flags & APPEND)) {
- error = EPERM;
- goto out;
- }
- error = ext2_dirremove(dvp, ap->a_cnp);
- if (error == 0) {
- ip->i_nlink--;
- ip->i_flag |= IN_CHANGE;
- }
-out:
- return (error);
-}
-
-/*
- * link vnode call
- */
-static int
-ext2_link(ap)
- struct vop_link_args /* {
- struct vnode *a_tdvp;
- struct vnode *a_vp;
- struct componentname *a_cnp;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
- struct vnode *tdvp = ap->a_tdvp;
- struct componentname *cnp = ap->a_cnp;
- struct inode *ip;
- int error;
-
-#ifdef DIAGNOSTIC
- if ((cnp->cn_flags & HASBUF) == 0)
- panic("ext2_link: no name");
-#endif
- if (tdvp->v_mount != vp->v_mount) {
- error = EXDEV;
- goto out;
- }
- ip = VTOI(vp);
- if ((nlink_t)ip->i_nlink >= LINK_MAX) {
- error = EMLINK;
- goto out;
- }
- if (ip->i_flags & (IMMUTABLE | APPEND)) {
- error = EPERM;
- goto out;
- }
- ip->i_nlink++;
- ip->i_flag |= IN_CHANGE;
- error = ext2_update(vp, 1);
- if (!error)
- error = ext2_direnter(ip, tdvp, cnp);
- if (error) {
- ip->i_nlink--;
- ip->i_flag |= IN_CHANGE;
- }
-out:
- return (error);
-}
-
-/*
- * Rename system call.
- * See comments in sys/ufs/ufs/ufs_vnops.c
- */
-static int
-ext2_rename(ap)
- struct vop_rename_args /* {
- struct vnode *a_fdvp;
- struct vnode *a_fvp;
- struct componentname *a_fcnp;
- struct vnode *a_tdvp;
- struct vnode *a_tvp;
- struct componentname *a_tcnp;
- } */ *ap;
-{
- struct vnode *tvp = ap->a_tvp;
- struct vnode *tdvp = ap->a_tdvp;
- struct vnode *fvp = ap->a_fvp;
- struct vnode *fdvp = ap->a_fdvp;
- struct componentname *tcnp = ap->a_tcnp;
- struct componentname *fcnp = ap->a_fcnp;
- struct inode *ip, *xp, *dp;
- struct dirtemplate dirbuf;
- int doingdirectory = 0, oldparent = 0, newparent = 0;
- int error = 0;
- u_char namlen;
-
-#ifdef DIAGNOSTIC
- if ((tcnp->cn_flags & HASBUF) == 0 ||
- (fcnp->cn_flags & HASBUF) == 0)
- panic("ext2_rename: no name");
-#endif
- /*
- * Check for cross-device rename.
- */
- if ((fvp->v_mount != tdvp->v_mount) ||
- (tvp && (fvp->v_mount != tvp->v_mount))) {
- error = EXDEV;
-abortit:
- if (tdvp == tvp)
- vrele(tdvp);
- else
- vput(tdvp);
- if (tvp)
- vput(tvp);
- vrele(fdvp);
- vrele(fvp);
- return (error);
- }
-
- if (tvp && ((VTOI(tvp)->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
- (VTOI(tdvp)->i_flags & APPEND))) {
- error = EPERM;
- goto abortit;
- }
-
- /*
- * Renaming a file to itself has no effect. The upper layers should
- * not call us in that case. Temporarily just warn if they do.
- */
- if (fvp == tvp) {
- printf("ext2_rename: fvp == tvp (can't happen)\n");
- error = 0;
- goto abortit;
- }
-
- if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0)
- goto abortit;
- dp = VTOI(fdvp);
- ip = VTOI(fvp);
- if (ip->i_nlink >= LINK_MAX) {
- VOP_UNLOCK(fvp, 0);
- error = EMLINK;
- goto abortit;
- }
- if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND))
- || (dp->i_flags & APPEND)) {
- VOP_UNLOCK(fvp, 0);
- error = EPERM;
- goto abortit;
- }
- if ((ip->i_mode & IFMT) == IFDIR) {
- /*
- * Avoid ".", "..", and aliases of "." for obvious reasons.
- */
- if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
- dp == ip || (fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT ||
- (ip->i_flag & IN_RENAME)) {
- VOP_UNLOCK(fvp, 0);
- error = EINVAL;
- goto abortit;
- }
- ip->i_flag |= IN_RENAME;
- oldparent = dp->i_number;
- doingdirectory++;
- }
- vrele(fdvp);
-
- /*
- * When the target exists, both the directory
- * and target vnodes are returned locked.
- */
- dp = VTOI(tdvp);
- xp = NULL;
- if (tvp)
- xp = VTOI(tvp);
-
- /*
- * 1) Bump link count while we're moving stuff
- * around. If we crash somewhere before
- * completing our work, the link count
- * may be wrong, but correctable.
- */
- ip->i_nlink++;
- ip->i_flag |= IN_CHANGE;
- if ((error = ext2_update(fvp, 1)) != 0) {
- VOP_UNLOCK(fvp, 0);
- goto bad;
- }
-
- /*
- * If ".." must be changed (ie the directory gets a new
- * parent) then the source directory must not be in the
- * directory heirarchy above the target, as this would
- * orphan everything below the source directory. Also
- * the user must have write permission in the source so
- * as to be able to change "..". We must repeat the call
- * to namei, as the parent directory is unlocked by the
- * call to checkpath().
- */
- error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_thread);
- VOP_UNLOCK(fvp, 0);
- if (oldparent != dp->i_number)
- newparent = dp->i_number;
- if (doingdirectory && newparent) {
- if (error) /* write access check above */
- goto bad;
- if (xp != NULL)
- vput(tvp);
- error = ext2_checkpath(ip, dp, tcnp->cn_cred);
- if (error)
- goto out;
- VREF(tdvp);
- error = relookup(tdvp, &tvp, tcnp);
- if (error)
- goto out;
- vrele(tdvp);
- dp = VTOI(tdvp);
- xp = NULL;
- if (tvp)
- xp = VTOI(tvp);
- }
- /*
- * 2) If target doesn't exist, link the target
- * to the source and unlink the source.
- * Otherwise, rewrite the target directory
- * entry to reference the source inode and
- * expunge the original entry's existence.
- */
- if (xp == NULL) {
- if (dp->i_devvp != ip->i_devvp)
- panic("ext2_rename: EXDEV");
- /*
- * Account for ".." in new directory.
- * When source and destination have the same
- * parent we don't fool with the link count.
- */
- if (doingdirectory && newparent) {
- if ((nlink_t)dp->i_nlink >= LINK_MAX) {
- error = EMLINK;
- goto bad;
- }
- dp->i_nlink++;
- dp->i_flag |= IN_CHANGE;
- error = ext2_update(tdvp, 1);
- if (error)
- goto bad;
- }
- error = ext2_direnter(ip, tdvp, tcnp);
- if (error) {
- if (doingdirectory && newparent) {
- dp->i_nlink--;
- dp->i_flag |= IN_CHANGE;
- (void)ext2_update(tdvp, 1);
- }
- goto bad;
- }
- vput(tdvp);
- } else {
- if (xp->i_devvp != dp->i_devvp || xp->i_devvp != ip->i_devvp)
- panic("ext2_rename: EXDEV");
- /*
- * Short circuit rename(foo, foo).
- */
- if (xp->i_number == ip->i_number)
- panic("ext2_rename: same file");
- /*
- * If the parent directory is "sticky", then the user must
- * own the parent directory, or the destination of the rename,
- * otherwise the destination may not be changed (except by
- * root). This implements append-only directories.
- */
- if ((dp->i_mode & S_ISTXT) && tcnp->cn_cred->cr_uid != 0 &&
- tcnp->cn_cred->cr_uid != dp->i_uid &&
- xp->i_uid != tcnp->cn_cred->cr_uid) {
- error = EPERM;
- goto bad;
- }
- /*
- * Target must be empty if a directory and have no links
- * to it. Also, ensure source and target are compatible
- * (both directories, or both not directories).
- */
- if ((xp->i_mode&IFMT) == IFDIR) {
- if (! ext2_dirempty(xp, dp->i_number, tcnp->cn_cred) ||
- xp->i_nlink > 2) {
- error = ENOTEMPTY;
- goto bad;
- }
- if (!doingdirectory) {
- error = ENOTDIR;
- goto bad;
- }
- cache_purge(tdvp);
- } else if (doingdirectory) {
- error = EISDIR;
- goto bad;
- }
- error = ext2_dirrewrite(dp, ip, tcnp);
- if (error)
- goto bad;
- /*
- * If the target directory is in the same
- * directory as the source directory,
- * decrement the link count on the parent
- * of the target directory.
- */
- if (doingdirectory && !newparent) {
- dp->i_nlink--;
- dp->i_flag |= IN_CHANGE;
- }
- vput(tdvp);
- /*
- * Adjust the link count of the target to
- * reflect the dirrewrite above. If this is
- * a directory it is empty and there are
- * no links to it, so we can squash the inode and
- * any space associated with it. We disallowed
- * renaming over top of a directory with links to
- * it above, as the remaining link would point to
- * a directory without "." or ".." entries.
- */
- xp->i_nlink--;
- if (doingdirectory) {
- if (--xp->i_nlink != 0)
- panic("ext2_rename: linked directory");
- error = ext2_truncate(tvp, (off_t)0, IO_SYNC,
- tcnp->cn_cred, tcnp->cn_thread);
- }
- xp->i_flag |= IN_CHANGE;
- vput(tvp);
- xp = NULL;
- }
-
- /*
- * 3) Unlink the source.
- */
- fcnp->cn_flags &= ~MODMASK;
- fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
- VREF(fdvp);
- error = relookup(fdvp, &fvp, fcnp);
- if (error == 0)
- vrele(fdvp);
- if (fvp != NULL) {
- xp = VTOI(fvp);
- dp = VTOI(fdvp);
- } else {
- /*
- * From name has disappeared.
- */
- if (doingdirectory)
- panic("ext2_rename: lost dir entry");
- vrele(ap->a_fvp);
- return (0);
- }
- /*
- * Ensure that the directory entry still exists and has not
- * changed while the new name has been entered. If the source is
- * a file then the entry may have been unlinked or renamed. In
- * either case there is no further work to be done. If the source
- * is a directory then it cannot have been rmdir'ed; its link
- * count of three would cause a rmdir to fail with ENOTEMPTY.
- * The IN_RENAME flag ensures that it cannot be moved by another
- * rename.
- */
- if (xp != ip) {
- if (doingdirectory)
- panic("ext2_rename: lost dir entry");
- } else {
- /*
- * If the source is a directory with a
- * new parent, the link count of the old
- * parent directory must be decremented
- * and ".." set to point to the new parent.
- */
- if (doingdirectory && newparent) {
- dp->i_nlink--;
- dp->i_flag |= IN_CHANGE;
- error = vn_rdwr(UIO_READ, fvp, (caddr_t)&dirbuf,
- sizeof (struct dirtemplate), (off_t)0,
- UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK,
- tcnp->cn_cred, NOCRED, NULL, NULL);
- if (error == 0) {
- /* Like ufs little-endian: */
- namlen = dirbuf.dotdot_type;
- if (namlen != 2 ||
- dirbuf.dotdot_name[0] != '.' ||
- dirbuf.dotdot_name[1] != '.') {
- ext2_dirbad(xp, (doff_t)12,
- "rename: mangled dir");
- } else {
- dirbuf.dotdot_ino = newparent;
- (void) vn_rdwr(UIO_WRITE, fvp,
- (caddr_t)&dirbuf,
- sizeof (struct dirtemplate),
- (off_t)0, UIO_SYSSPACE,
- IO_NODELOCKED | IO_SYNC |
- IO_NOMACCHECK, tcnp->cn_cred,
- NOCRED, NULL, NULL);
- cache_purge(fdvp);
- }
- }
- }
- error = ext2_dirremove(fdvp, fcnp);
- if (!error) {
- xp->i_nlink--;
- xp->i_flag |= IN_CHANGE;
- }
- xp->i_flag &= ~IN_RENAME;
- }
- if (dp)
- vput(fdvp);
- if (xp)
- vput(fvp);
- vrele(ap->a_fvp);
- return (error);
-
-bad:
- if (xp)
- vput(ITOV(xp));
- vput(ITOV(dp));
-out:
- if (doingdirectory)
- ip->i_flag &= ~IN_RENAME;
- if (vn_lock(fvp, LK_EXCLUSIVE) == 0) {
- ip->i_nlink--;
- ip->i_flag |= IN_CHANGE;
- ip->i_flag &= ~IN_RENAME;
- vput(fvp);
- } else
- vrele(fvp);
- return (error);
-}
-
-/*
- * Mkdir system call
- */
-static int
-ext2_mkdir(ap)
- struct vop_mkdir_args /* {
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- } */ *ap;
-{
- struct vnode *dvp = ap->a_dvp;
- struct vattr *vap = ap->a_vap;
- struct componentname *cnp = ap->a_cnp;
- struct inode *ip, *dp;
- struct vnode *tvp;
- struct dirtemplate dirtemplate, *dtp;
- int error, dmode;
-
-#ifdef DIAGNOSTIC
- if ((cnp->cn_flags & HASBUF) == 0)
- panic("ext2_mkdir: no name");
-#endif
- dp = VTOI(dvp);
- if ((nlink_t)dp->i_nlink >= LINK_MAX) {
- error = EMLINK;
- goto out;
- }
- dmode = vap->va_mode & 0777;
- dmode |= IFDIR;
- /*
- * Must simulate part of ext2_makeinode here to acquire the inode,
- * but not have it entered in the parent directory. The entry is
- * made later after writing "." and ".." entries.
- */
- error = ext2_valloc(dvp, dmode, cnp->cn_cred, &tvp);
- if (error)
- goto out;
- ip = VTOI(tvp);
- ip->i_gid = dp->i_gid;
-#ifdef SUIDDIR
- {
- /*
- * if we are hacking owners here, (only do this where told to)
- * and we are not giving it TOO root, (would subvert quotas)
- * then go ahead and give it to the other user.
- * The new directory also inherits the SUID bit.
- * If user's UID and dir UID are the same,
- * 'give it away' so that the SUID is still forced on.
- */
- if ( (dvp->v_mount->mnt_flag & MNT_SUIDDIR) &&
- (dp->i_mode & ISUID) && dp->i_uid) {
- dmode |= ISUID;
- ip->i_uid = dp->i_uid;
- } else {
- ip->i_uid = cnp->cn_cred->cr_uid;
- }
- }
-#else
- ip->i_uid = cnp->cn_cred->cr_uid;
-#endif
- ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
- ip->i_mode = dmode;
- tvp->v_type = VDIR; /* Rest init'd in getnewvnode(). */
- ip->i_nlink = 2;
- if (cnp->cn_flags & ISWHITEOUT)
- ip->i_flags |= UF_OPAQUE;
- error = ext2_update(tvp, 1);
-
- /*
- * Bump link count in parent directory
- * to reflect work done below. Should
- * be done before reference is created
- * so reparation is possible if we crash.
- */
- dp->i_nlink++;
- dp->i_flag |= IN_CHANGE;
- error = ext2_update(dvp, 1);
- if (error)
- goto bad;
-
- /* Initialize directory with "." and ".." from static template. */
- if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs,
- EXT2_FEATURE_INCOMPAT_FILETYPE))
- dtp = &mastertemplate;
- else
- dtp = &omastertemplate;
- dirtemplate = *dtp;
- dirtemplate.dot_ino = ip->i_number;
- dirtemplate.dotdot_ino = dp->i_number;
- /* note that in ext2 DIRBLKSIZ == blocksize, not DEV_BSIZE
- * so let's just redefine it - for this function only
- */
-#undef DIRBLKSIZ
-#define DIRBLKSIZ VTOI(dvp)->i_e2fs->s_blocksize
- dirtemplate.dotdot_reclen = DIRBLKSIZ - 12;
- error = vn_rdwr(UIO_WRITE, tvp, (caddr_t)&dirtemplate,
- sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE,
- IO_NODELOCKED | IO_SYNC | IO_NOMACCHECK, cnp->cn_cred, NOCRED,
- NULL, NULL);
- if (error) {
- dp->i_nlink--;
- dp->i_flag |= IN_CHANGE;
- goto bad;
- }
- if (DIRBLKSIZ > VFSTOEXT2(dvp->v_mount)->um_mountp->mnt_stat.f_bsize)
- /* XXX should grow with balloc() */
- panic("ext2_mkdir: blksize");
- else {
- ip->i_size = DIRBLKSIZ;
- ip->i_flag |= IN_CHANGE;
- }
-
- /* Directory set up, now install its entry in the parent directory. */
- error = ext2_direnter(ip, dvp, cnp);
- if (error) {
- dp->i_nlink--;
- dp->i_flag |= IN_CHANGE;
- }
-bad:
- /*
- * No need to do an explicit VOP_TRUNCATE here, vrele will do this
- * for us because we set the link count to 0.
- */
- if (error) {
- ip->i_nlink = 0;
- ip->i_flag |= IN_CHANGE;
- vput(tvp);
- } else
- *ap->a_vpp = tvp;
-out:
- return (error);
-#undef DIRBLKSIZ
-#define DIRBLKSIZ DEV_BSIZE
-}
-
-/*
- * Rmdir system call.
- */
-static int
-ext2_rmdir(ap)
- struct vop_rmdir_args /* {
- struct vnode *a_dvp;
- struct vnode *a_vp;
- struct componentname *a_cnp;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
- struct vnode *dvp = ap->a_dvp;
- struct componentname *cnp = ap->a_cnp;
- struct inode *ip, *dp;
- int error;
-
- ip = VTOI(vp);
- dp = VTOI(dvp);
-
- /*
- * Verify the directory is empty (and valid).
- * (Rmdir ".." won't be valid since
- * ".." will contain a reference to
- * the current directory and thus be
- * non-empty.)
- */
- error = 0;
- if (ip->i_nlink != 2 || !ext2_dirempty(ip, dp->i_number, cnp->cn_cred)) {
- error = ENOTEMPTY;
- goto out;
- }
- if ((dp->i_flags & APPEND)
- || (ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND))) {
- error = EPERM;
- goto out;
- }
- /*
- * Delete reference to directory before purging
- * inode. If we crash in between, the directory
- * will be reattached to lost+found,
- */
- error = ext2_dirremove(dvp, cnp);
- if (error)
- goto out;
- dp->i_nlink--;
- dp->i_flag |= IN_CHANGE;
- cache_purge(dvp);
- VOP_UNLOCK(dvp, 0);
- /*
- * Truncate inode. The only stuff left
- * in the directory is "." and "..". The
- * "." reference is inconsequential since
- * we're quashing it. The ".." reference
- * has already been adjusted above. We've
- * removed the "." reference and the reference
- * in the parent directory, but there may be
- * other hard links so decrement by 2 and
- * worry about them later.
- */
- ip->i_nlink -= 2;
- error = ext2_truncate(vp, (off_t)0, IO_SYNC, cnp->cn_cred,
- cnp->cn_thread);
- cache_purge(ITOV(ip));
- vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
-out:
- return (error);
-}
-
-/*
- * symlink -- make a symbolic link
- */
-static int
-ext2_symlink(ap)
- struct vop_symlink_args /* {
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- char *a_target;
- } */ *ap;
-{
- struct vnode *vp, **vpp = ap->a_vpp;
- struct inode *ip;
- int len, error;
-
- error = ext2_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp,
- vpp, ap->a_cnp);
- if (error)
- return (error);
- vp = *vpp;
- len = strlen(ap->a_target);
- if (len < vp->v_mount->mnt_maxsymlinklen) {
- ip = VTOI(vp);
- bcopy(ap->a_target, (char *)ip->i_shortlink, len);
- ip->i_size = len;
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
- } else
- error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0,
- UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK,
- ap->a_cnp->cn_cred, NOCRED, NULL, NULL);
- if (error)
- vput(vp);
- return (error);
-}
-
-/*
- * Return target name of a symbolic link
- */
-static int
-ext2_readlink(ap)
- struct vop_readlink_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- struct ucred *a_cred;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
- struct inode *ip = VTOI(vp);
- int isize;
-
- isize = ip->i_size;
- if (isize < vp->v_mount->mnt_maxsymlinklen) {
- uiomove((char *)ip->i_shortlink, isize, ap->a_uio);
- return (0);
- }
- return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
-}
-
-/*
- * Calculate the logical to physical mapping if not done already,
- * then call the device strategy routine.
- *
- * In order to be able to swap to a file, the ext2_bmaparray() operation may not
- * deadlock on memory. See ext2_bmap() for details.
- */
-static int
-ext2_strategy(ap)
- struct vop_strategy_args /* {
- struct vnode *a_vp;
- struct buf *a_bp;
- } */ *ap;
-{
- struct buf *bp = ap->a_bp;
- struct vnode *vp = ap->a_vp;
- struct inode *ip;
- struct bufobj *bo;
- int32_t blkno;
- int error;
-
- ip = VTOI(vp);
- if (vp->v_type == VBLK || vp->v_type == VCHR)
- panic("ext2_strategy: spec");
- if (bp->b_blkno == bp->b_lblkno) {
- error = ext2_bmaparray(vp, bp->b_lblkno, &blkno, NULL, NULL);
- bp->b_blkno = blkno;
- if (error) {
- bp->b_error = error;
- bp->b_ioflags |= BIO_ERROR;
- bufdone(bp);
- return (0);
- }
- if ((long)bp->b_blkno == -1)
- vfs_bio_clrbuf(bp);
- }
- if ((long)bp->b_blkno == -1) {
- bufdone(bp);
- return (0);
- }
- bp->b_iooffset = dbtob(bp->b_blkno);
- bo = VFSTOEXT2(vp->v_mount)->um_bo;
- BO_STRATEGY(bo, bp);
- return (0);
-}
-
-/*
- * Print out the contents of an inode.
- */
-static int
-ext2_print(ap)
- struct vop_print_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
- struct inode *ip = VTOI(vp);
-
- vn_printf(ip->i_devvp, "\tino %lu", (u_long)ip->i_number);
- if (vp->v_type == VFIFO)
- fifo_printinfo(vp);
- printf("\n");
- return (0);
-}
-
-/*
- * Close wrapper for fifos.
- *
- * Update the times on the inode then do device close.
- */
-static int
-ext2fifo_close(ap)
- struct vop_close_args /* {
- struct vnode *a_vp;
- int a_fflag;
- struct ucred *a_cred;
- struct thread *a_td;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
-
- VI_LOCK(vp);
- if (vp->v_usecount > 1)
- ext2_itimes(vp);
- VI_UNLOCK(vp);
- return (fifo_specops.vop_close(ap));
-}
-
-/*
- * Kqfilter wrapper for fifos.
- *
- * Fall through to ext2 kqfilter routines if needed
- */
-static int
-ext2fifo_kqfilter(ap)
- struct vop_kqfilter_args *ap;
-{
- int error;
-
- error = fifo_specops.vop_kqfilter(ap);
- if (error)
- error = vfs_kqfilter(ap);
- return (error);
-}
-
-/*
- * Return POSIX pathconf information applicable to ext2 filesystems.
- */
-static int
-ext2_pathconf(ap)
- struct vop_pathconf_args /* {
- struct vnode *a_vp;
- int a_name;
- int *a_retval;
- } */ *ap;
-{
-
- switch (ap->a_name) {
- case _PC_LINK_MAX:
- *ap->a_retval = LINK_MAX;
- return (0);
- case _PC_NAME_MAX:
- *ap->a_retval = NAME_MAX;
- return (0);
- case _PC_PATH_MAX:
- *ap->a_retval = PATH_MAX;
- return (0);
- case _PC_PIPE_BUF:
- *ap->a_retval = PIPE_BUF;
- return (0);
- case _PC_CHOWN_RESTRICTED:
- *ap->a_retval = 1;
- return (0);
- case _PC_NO_TRUNC:
- *ap->a_retval = 1;
- return (0);
- default:
- return (EINVAL);
- }
- /* NOTREACHED */
-}
-
-/*
- * Vnode pointer to File handle
- */
-/* ARGSUSED */
-static int
-ext2_vptofh(ap)
- struct vop_vptofh_args /* {
- struct vnode *a_vp;
- struct fid *a_fhp;
- } */ *ap;
-{
- struct inode *ip;
- struct ufid *ufhp;
-
- ip = VTOI(ap->a_vp);
- ufhp = (struct ufid *)ap->a_fhp;
- ufhp->ufid_len = sizeof(struct ufid);
- ufhp->ufid_ino = ip->i_number;
- ufhp->ufid_gen = ip->i_gen;
- return (0);
-}
-
-/*
- * Initialize the vnode associated with a new inode, handle aliased
- * vnodes.
- */
-int
-ext2_vinit(mntp, fifoops, vpp)
- struct mount *mntp;
- struct vop_vector *fifoops;
- struct vnode **vpp;
-{
- struct inode *ip;
- struct vnode *vp;
-
- vp = *vpp;
- ip = VTOI(vp);
- vp->v_type = IFTOVT(ip->i_mode);
- if (vp->v_type == VFIFO)
- vp->v_op = fifoops;
-
- if (ip->i_number == ROOTINO)
- vp->v_vflag |= VV_ROOT;
- ip->i_modrev = init_va_filerev();
- *vpp = vp;
- return (0);
-}
-
-/*
- * Allocate a new inode.
- */
-static int
-ext2_makeinode(mode, dvp, vpp, cnp)
- int mode;
- struct vnode *dvp;
- struct vnode **vpp;
- struct componentname *cnp;
-{
- struct inode *ip, *pdir;
- struct vnode *tvp;
- int error;
-
- pdir = VTOI(dvp);
-#ifdef DIAGNOSTIC
- if ((cnp->cn_flags & HASBUF) == 0)
- panic("ext2_makeinode: no name");
-#endif
- *vpp = NULL;
- if ((mode & IFMT) == 0)
- mode |= IFREG;
-
- error = ext2_valloc(dvp, mode, cnp->cn_cred, &tvp);
- if (error) {
- return (error);
- }
- ip = VTOI(tvp);
- ip->i_gid = pdir->i_gid;
-#ifdef SUIDDIR
- {
- /*
- * if we are
- * not the owner of the directory,
- * and we are hacking owners here, (only do this where told to)
- * and we are not giving it TOO root, (would subvert quotas)
- * then go ahead and give it to the other user.
- * Note that this drops off the execute bits for security.
- */
- if ( (dvp->v_mount->mnt_flag & MNT_SUIDDIR) &&
- (pdir->i_mode & ISUID) &&
- (pdir->i_uid != cnp->cn_cred->cr_uid) && pdir->i_uid) {
- ip->i_uid = pdir->i_uid;
- mode &= ~07111;
- } else {
- ip->i_uid = cnp->cn_cred->cr_uid;
- }
- }
-#else
- ip->i_uid = cnp->cn_cred->cr_uid;
-#endif
- ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
- ip->i_mode = mode;
- tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */
- ip->i_nlink = 1;
- if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred)) {
- if (priv_check_cred(cnp->cn_cred, PRIV_VFS_RETAINSUGID, 0))
- ip->i_mode &= ~ISGID;
- }
-
- if (cnp->cn_flags & ISWHITEOUT)
- ip->i_flags |= UF_OPAQUE;
-
- /*
- * Make sure inode goes to disk before directory entry.
- */
- error = ext2_update(tvp, 1);
- if (error)
- goto bad;
- error = ext2_direnter(ip, dvp, cnp);
- if (error)
- goto bad;
-
- *vpp = tvp;
- return (0);
-
-bad:
- /*
- * Write error occurred trying to update the inode
- * or the directory so must deallocate the inode.
- */
- ip->i_nlink = 0;
- ip->i_flag |= IN_CHANGE;
- vput(tvp);
- return (error);
-}
diff --git a/sys/gnu/fs/ext2fs/fs.h b/sys/gnu/fs/ext2fs/fs.h
deleted file mode 100644
index d9e7000..0000000
--- a/sys/gnu/fs/ext2fs/fs.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/*-
- * modified for EXT2FS support in Lites 1.1
- *
- * Aug 1995, Godmar Back (gback@cs.utah.edu)
- * University of Utah, Department of Computer Science
- */
-/*-
- * Copyright (c) 1982, 1986, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)fs.h 8.7 (Berkeley) 4/19/94
- * $FreeBSD$
- */
-
-/*
- * Each disk drive contains some number of file systems.
- * A file system consists of a number of cylinder groups.
- * Each cylinder group has inodes and data.
- *
- * A file system is described by its super-block, which in turn
- * describes the cylinder groups. The super-block is critical
- * data and is replicated in each cylinder group to protect against
- * catastrophic loss. This is done at `newfs' time and the critical
- * super-block data does not change, so the copies need not be
- * referenced further unless disaster strikes.
- *
- * The first boot and super blocks are given in absolute disk addresses.
- * The byte-offset forms are preferred, as they don't imply a sector size.
- */
-#define SBSIZE 1024
-#define SBLOCK 2
-
-/*
- * The path name on which the file system is mounted is maintained
- * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in
- * the super block for this name.
- */
-#define MAXMNTLEN 512
-
-/*
- * Macros for access to superblock array structures
- */
-
-/*
- * Convert cylinder group to base address of its global summary info.
- */
-#define fs_cs(fs, cgindx) (((struct ext2_group_desc *) \
- (fs->s_group_desc[cgindx / EXT2_DESC_PER_BLOCK(fs)]->b_data)) \
- [cgindx % EXT2_DESC_PER_BLOCK(fs)])
-
-/*
- * Turn file system block numbers into disk block addresses.
- * This maps file system blocks to device size blocks.
- */
-#define fsbtodb(fs, b) ((b) << ((fs)->s_fsbtodb))
-#define dbtofsb(fs, b) ((b) >> ((fs)->s_fsbtodb))
-
-/* get group containing inode */
-#define ino_to_cg(fs, x) (((x) - 1) / EXT2_INODES_PER_GROUP(fs))
-
-/* get block containing inode from its number x */
-#define ino_to_fsba(fs, x) fs_cs(fs, ino_to_cg(fs, x)).bg_inode_table + \
- (((x)-1) % EXT2_INODES_PER_GROUP(fs))/EXT2_INODES_PER_BLOCK(fs)
-
-/* get offset for inode in block */
-#define ino_to_fsbo(fs, x) ((x-1) % EXT2_INODES_PER_BLOCK(fs))
-
-/*
- * Give cylinder group number for a file system block.
- * Give cylinder group block number for a file system block.
- */
-#define dtog(fs, d) (((d) - fs->s_es->s_first_data_block) / \
- EXT2_BLOCKS_PER_GROUP(fs))
-#define dtogd(fs, d) (((d) - fs->s_es->s_first_data_block) % \
- EXT2_BLOCKS_PER_GROUP(fs))
-
-/*
- * The following macros optimize certain frequently calculated
- * quantities by using shifts and masks in place of divisions
- * modulos and multiplications.
- */
-#define blkoff(fs, loc) /* calculates (loc % fs->fs_bsize) */ \
- ((loc) & (fs)->s_qbmask)
-
-#define lblktosize(fs, blk) /* calculates (blk * fs->fs_bsize) */ \
- ((blk) << (fs->s_bshift))
-
-#define lblkno(fs, loc) /* calculates (loc / fs->fs_bsize) */ \
- ((loc) >> (fs->s_bshift))
-
-/* no fragments -> logical block number equal # of frags */
-#define numfrags(fs, loc) /* calculates (loc / fs->fs_fsize) */ \
- ((loc) >> (fs->s_bshift))
-
-#define fragroundup(fs, size) /* calculates roundup(size, fs->fs_fsize) */ \
- roundup(size, fs->s_frag_size)
- /* was (((size) + (fs)->fs_qfmask) & (fs)->fs_fmask) */
-
-/*
- * Determining the size of a file block in the file system.
- * easy w/o fragments
- */
-#define blksize(fs, ip, lbn) ((fs)->s_frag_size)
-
-/*
- * INOPB is the number of inodes in a secondary storage block.
- */
-#define INOPB(fs) EXT2_INODES_PER_BLOCK(fs)
-
-/*
- * NINDIR is the number of indirects in a file system block.
- */
-#define NINDIR(fs) (EXT2_ADDR_PER_BLOCK(fs))
-
-extern int inside[], around[];
-extern u_char *fragtbl[];
-
-/* a few remarks about superblock locking/unlocking
- * Linux provides special routines for doing so
- * I haven't figured out yet what BSD does
- * I think I'll try a VOP_LOCK/VOP_UNLOCK on the device vnode
- */
-#define DEVVP(inode) (VFSTOEXT2(ITOV(inode)->v_mount)->um_devvp)
-#define lock_super(devvp) vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY)
-#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/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/ext2fs/inode.h b/sys/gnu/fs/ext2fs/inode.h
deleted file mode 100644
index 75d9b1b..0000000
--- a/sys/gnu/fs/ext2fs/inode.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/*-
- * Copyright (c) 1982, 1989, 1993
- * The Regents of the University of California. All rights reserved.
- * (c) UNIX System Laboratories, Inc.
- * All or some portions of this file are derived from material licensed
- * to the University of California by American Telephone and Telegraph
- * Co. or Unix System Laboratories, Inc. and are reproduced herein with
- * the permission of UNIX System Laboratories, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)inode.h 8.9 (Berkeley) 5/14/95
- * $FreeBSD$
- */
-
-#ifndef _SYS_GNU_EXT2FS_INODE_H_
-#define _SYS_GNU_EXT2FS_INODE_H_
-
-#include <sys/lock.h>
-#include <sys/queue.h>
-
-#define ROOTINO ((ino_t)2)
-
-#define NDADDR 12 /* Direct addresses in inode. */
-#define NIADDR 3 /* Indirect addresses in inode. */
-
-/*
- * This must agree with the definition in <ufs/ufs/dir.h>.
- */
-#define doff_t int32_t
-
-/*
- * The inode is used to describe each active (or recently active) file in the
- * EXT2FS filesystem. It is composed of two types of information. The first
- * part is the information that is needed only while the file is active (such
- * as the identity of the file and linkage to speed its lookup). The second
- * part is the permanent meta-data associated with the file which is read in
- * from the permanent dinode from long term storage when the file becomes
- * active, and is put back when the file is no longer being used.
- */
-struct inode {
- struct vnode *i_vnode;/* Vnode associated with this inode. */
- struct vnode *i_devvp;/* Vnode for block I/O. */
- u_int32_t i_flag; /* flags, see below */
- ino_t i_number; /* The identity of the inode. */
-
- struct ext2_sb_info *i_e2fs; /* EXT2FS */
- u_quad_t i_modrev; /* Revision level for NFS lease. */
- /*
- * Side effects; used during directory lookup.
- */
- int32_t i_count; /* Size of free slot in directory. */
- doff_t i_endoff; /* End of useful stuff in directory. */
- doff_t i_diroff; /* Offset in dir, where we found last entry. */
- doff_t i_offset; /* Offset of free space in directory. */
- ino_t i_ino; /* Inode number of found directory. */
- u_int32_t i_reclen; /* Size of found directory entry. */
-
- u_int32_t i_block_group;
- u_int32_t i_next_alloc_block;
- u_int32_t i_next_alloc_goal;
- u_int32_t i_prealloc_block;
- u_int32_t i_prealloc_count;
-
- /* Fields from struct dinode in UFS. */
- u_int16_t i_mode; /* IFMT, permissions; see below. */
- int16_t i_nlink; /* File link count. */
- u_int64_t i_size; /* File byte count. */
- int32_t i_atime; /* Last access time. */
- int32_t i_atimensec; /* Last access time. */
- int32_t i_mtime; /* Last modified time. */
- int32_t i_mtimensec; /* Last modified time. */
- int32_t i_ctime; /* Last inode change time. */
- int32_t i_ctimensec; /* Last inode change time. */
- int32_t i_db[NDADDR]; /* Direct disk blocks. */
- int32_t i_ib[NIADDR]; /* Indirect disk blocks. */
- u_int32_t i_flags; /* Status flags (chflags). */
- int32_t i_blocks; /* Blocks actually held. */
- int32_t i_gen; /* Generation number. */
- u_int32_t i_uid; /* File owner. */
- u_int32_t i_gid; /* File group. */
-};
-
-/*
- * The di_db fields may be overlaid with other information for
- * file types that do not have associated disk storage. Block
- * and character devices overlay the first data block with their
- * dev_t value. Short symbolic links place their path in the
- * di_db area.
- */
-#define i_shortlink i_db
-#define i_rdev i_db[0]
-#define MAXSYMLINKLEN ((NDADDR + NIADDR) * sizeof(int32_t))
-
-/* File permissions. */
-#define IEXEC 0000100 /* Executable. */
-#define IWRITE 0000200 /* Writeable. */
-#define IREAD 0000400 /* Readable. */
-#define ISVTX 0001000 /* Sticky bit. */
-#define ISGID 0002000 /* Set-gid. */
-#define ISUID 0004000 /* Set-uid. */
-
-/* File types. */
-#define IFMT 0170000 /* Mask of file type. */
-#define IFIFO 0010000 /* Named pipe (fifo). */
-#define IFCHR 0020000 /* Character device. */
-#define IFDIR 0040000 /* Directory file. */
-#define IFBLK 0060000 /* Block device. */
-#define IFREG 0100000 /* Regular file. */
-#define IFLNK 0120000 /* Symbolic link. */
-#define IFSOCK 0140000 /* UNIX domain socket. */
-#define IFWHT 0160000 /* Whiteout. */
-
-/* These flags are kept in i_flag. */
-#define IN_ACCESS 0x0001 /* Access time update request. */
-#define IN_CHANGE 0x0002 /* Inode change time update request. */
-#define IN_UPDATE 0x0004 /* Modification time update request. */
-#define IN_MODIFIED 0x0008 /* Inode has been modified. */
-#define IN_RENAME 0x0010 /* Inode is being renamed. */
-#define IN_HASHED 0x0020 /* Inode is on hash list */
-#define IN_LAZYMOD 0x0040 /* Modified, but don't write yet. */
-#define IN_SPACECOUNTED 0x0080 /* Blocks to be freed in free count. */
-
-#ifdef _KERNEL
-/*
- * Structure used to pass around logical block paths generated by
- * ext2_getlbns and used by truncate and bmap code.
- */
-struct indir {
- int32_t in_lbn; /* Logical block number. */
- int in_off; /* Offset in buffer. */
- int in_exists; /* Flag if the block exists. */
-};
-
-/* Convert between inode pointers and vnode pointers. */
-#define VTOI(vp) ((struct inode *)(vp)->v_data)
-#define ITOV(ip) ((ip)->i_vnode)
-
-/* This overlays the fid structure (see mount.h). */
-struct ufid {
- u_int16_t ufid_len; /* Length of structure. */
- u_int16_t ufid_pad; /* Force 32-bit alignment. */
- ino_t ufid_ino; /* File number (ino). */
- int32_t ufid_gen; /* Generation number. */
-};
-#endif /* _KERNEL */
-
-#endif /* !_SYS_GNU_EXT2FS_INODE_H_ */
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
/*
OpenPOWER on IntegriCloud