diff options
author | lulf <lulf@FreeBSD.org> | 2010-01-14 14:30:54 +0000 |
---|---|---|
committer | lulf <lulf@FreeBSD.org> | 2010-01-14 14:30:54 +0000 |
commit | 8ab7715033ec4b66ff6203f772f2a4b430e2b6e6 (patch) | |
tree | fef80ad74c782758cf935f5ae7b6be070319042e /sys/gnu | |
parent | cee9e919b513999007f8f66c6581fa31174b4fb9 (diff) | |
download | FreeBSD-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')
-rw-r--r-- | sys/gnu/fs/ext2fs/COPYRIGHT.INFO | 35 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_alloc.c | 535 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_balloc.c | 310 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_bitops.h | 114 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_bmap.c | 335 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_extern.h | 104 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_fs.h | 556 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_fs_sb.h | 100 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_inode.c | 528 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_inode_cnv.c | 137 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_linux_balloc.c | 624 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_linux_ialloc.c | 526 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_lookup.c | 1082 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_mount.h | 73 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_readwrite.c | 304 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_subr.c | 120 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_vfsops.c | 1122 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_vnops.c | 1649 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/fs.h | 170 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/i386-bitops.h | 175 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/inode.h | 170 | ||||
-rw-r--r-- | sys/gnu/fs/reiserfs/reiserfs_fs.h | 19 |
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 = # - 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 /* |