summaryrefslogtreecommitdiff
path: root/ufs
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2013-09-17 19:20:42 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2013-09-17 19:20:42 +0200
commit84cf9c0f312637b670cc87224ff7e7c4da659e36 (patch)
tree5e7f0f1f6c7579d1275bb5cf1856ce52767ac8b3 /ufs
parent3e6aab0243da094f1ca05b80eb3e5a9adb8ea519 (diff)
Remove UFS support
It has been unused/untested/unmaintained for a decade now, and its 4-clause BSD licence poses problem. * configure.ac (default_static): Remove ufs. * Makefile (prog-subdirs): Remove ufs, ufs-fsck and ufs-utils. * NEWS, TODO: doc/hurd.texi, doc/navigating: Remove UFS notes. * ufs: Remove directory * ufs-fsck: Remove directory * ufs-utils: Remove directory * bsdfsck: Remove directory
Diffstat (limited to 'ufs')
-rw-r--r--ufs/Makefile32
-rw-r--r--ufs/alloc.c1703
-rw-r--r--ufs/bmap.c120
-rw-r--r--ufs/consts.c33
-rw-r--r--ufs/dinode.h137
-rw-r--r--ufs/dir.c988
-rw-r--r--ufs/dir.h163
-rw-r--r--ufs/fs.h509
-rw-r--r--ufs/hyper.c414
-rw-r--r--ufs/inode.c705
-rw-r--r--ufs/main.c210
-rw-r--r--ufs/pager.c838
-rw-r--r--ufs/pokeloc.c85
-rw-r--r--ufs/sizes.c736
-rw-r--r--ufs/subr.c264
-rw-r--r--ufs/tables.c138
-rw-r--r--ufs/ufs.h310
-rw-r--r--ufs/xinl.c2
18 files changed, 0 insertions, 7387 deletions
diff --git a/ufs/Makefile b/ufs/Makefile
deleted file mode 100644
index b66a6259..00000000
--- a/ufs/Makefile
+++ /dev/null
@@ -1,32 +0,0 @@
-# Makefile for ufs
-#
-# Copyright (C) 1994,95,96,99,2000,02,12 Free Software Foundation, Inc.
-#
-# 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, or (at
-# your option) any later version.
-#
-# 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.
-
-dir := ufs
-makemode := server
-
-target = ufs
-SRCS = alloc.c consts.c dir.c hyper.c inode.c main.c pager.c \
- sizes.c subr.c tables.c bmap.c pokeloc.c xinl.c
-
-OBJS = $(SRCS:.c=.o)
-HURDLIBS = diskfs iohelp fshelp store pager ports ihash shouldbeinlibc
-OTHERLIBS = -lpthread
-
-include ../Makeconf
-
-ufs.static: $(boot-store-types:%=../libstore/libstore_%.a)
diff --git a/ufs/alloc.c b/ufs/alloc.c
deleted file mode 100644
index 9056a8b7..00000000
--- a/ufs/alloc.c
+++ /dev/null
@@ -1,1703 +0,0 @@
-/* Disk allocation routines
- Copyright (C) 1993,94,95,96,98,2002 Free Software Foundation, Inc.
-
-This file is part of the GNU Hurd.
-
-The GNU Hurd 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, or (at your option)
-any later version.
-
-The GNU Hurd 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 the GNU Hurd; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* Modified from UCB by Michael I. Bushnell. */
-/*
- * 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 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
- */
-
-#include "ufs.h"
-#include <stdio.h>
-#include <string.h>
-
-
-/* These don't work *at all* here; don't even try setting them. */
-#undef DIAGNOSTIC
-#undef QUOTA
-
-extern u_long nextgennumber;
-
-pthread_spinlock_t alloclock = PTHREAD_SPINLOCK_INITIALIZER;
-
-/* Forward declarations */
-static u_long ffs_hashalloc (struct node *, int, long, int,
- u_long (*)(struct node *, int, daddr_t, int));
-static u_long ffs_alloccg (struct node *, int, daddr_t, int);
-static daddr_t ffs_fragextend (struct node *, int, long, int, int);
-static ino_t ffs_dirpref (struct fs *);
-static u_long ffs_nodealloccg (struct node *, int, daddr_t, int);
-static daddr_t ffs_alloccgblk (struct fs *, struct cg *, daddr_t);
-static daddr_t ffs_mapsearch (struct fs *, struct cg *, daddr_t, int);
-static void ffs_clusteracct (struct fs *, struct cg *, daddr_t, int);
-
-/* Sync all allocation information and nod eNP if diskfs_synchronous. */
-inline void
-alloc_sync (struct node *np)
-{
- if (diskfs_synchronous)
- {
- if (np)
- diskfs_node_update (np, 1);
- copy_sblock ();
- diskfs_set_hypermetadata (1, 0);
- sync_disk (1);
- }
-}
-
-/* Byteswap everything in CGP. */
-void
-swab_cg (struct cg *cg)
-{
- int i, j;
-
- if (swab_long (cg->cg_magic) == CG_MAGIC
- || cg->cg_magic == CG_MAGIC)
- {
- cg->cg_magic = swab_long (cg->cg_magic);
- cg->cg_time = swab_long (cg->cg_time);
- cg->cg_cgx = swab_long (cg->cg_cgx);
- cg->cg_ncyl = swab_short (cg->cg_ncyl);
- cg->cg_niblk = swab_short (cg->cg_niblk);
- cg->cg_cs.cs_ndir = swab_long (cg->cg_cs.cs_ndir);
- cg->cg_cs.cs_nbfree = swab_long (cg->cg_cs.cs_nbfree);
- cg->cg_cs.cs_nifree = swab_long (cg->cg_cs.cs_nifree);
- cg->cg_cs.cs_nffree = swab_long (cg->cg_cs.cs_nffree);
- cg->cg_rotor = swab_long (cg->cg_rotor);
- cg->cg_irotor = swab_long (cg->cg_irotor);
- for (i = 0; i < MAXFRAG; i++)
- cg->cg_frsum[i] = swab_long (cg->cg_frsum[i]);
- cg->cg_btotoff = swab_long (cg->cg_btotoff);
- cg->cg_boff = swab_long (cg->cg_boff);
- cg->cg_iusedoff = swab_long (cg->cg_iusedoff);
- cg->cg_freeoff = swab_long (cg->cg_freeoff);
- cg->cg_nextfreeoff = swab_long (cg->cg_nextfreeoff);
- cg->cg_clustersumoff = swab_long (cg->cg_clustersumoff);
- cg->cg_clusteroff = swab_long (cg->cg_clusteroff);
- cg->cg_nclusterblks = swab_long (cg->cg_nclusterblks);
-
- /* blktot map */
- for (i = 0; i < cg->cg_ncyl; i++)
- cg_blktot(cg)[i] = swab_long (cg_blktot(cg)[i]);
-
- /* blks map */
- for (i = 0; i < cg->cg_ncyl; i++)
- for (j = 0; j < sblock->fs_nrpos; j++)
- cg_blks(sblock, cg, i)[j] = swab_short (cg_blks (sblock, cg, i)[j]);
-
- for (i = 0; i < sblock->fs_contigsumsize; i++)
- cg_clustersum(cg)[i] = swab_long (cg_clustersum(cg)[i]);
-
- /* inosused, blksfree, and cg_clustersfree are char arrays */
- }
- else
- {
- /* Old format cylinder group... */
- struct ocg *ocg = (struct ocg *) cg;
-
- if (swab_long (ocg->cg_magic) != CG_MAGIC
- && ocg->cg_magic != CG_MAGIC)
- return;
-
- ocg->cg_time = swab_long (ocg->cg_time);
- ocg->cg_cgx = swab_long (ocg->cg_cgx);
- ocg->cg_ncyl = swab_short (ocg->cg_ncyl);
- ocg->cg_niblk = swab_short (ocg->cg_niblk);
- ocg->cg_ndblk = swab_long (ocg->cg_ndblk);
- ocg->cg_cs.cs_ndir = swab_long (ocg->cg_cs.cs_ndir);
- ocg->cg_cs.cs_nbfree = swab_long (ocg->cg_cs.cs_nbfree);
- ocg->cg_cs.cs_nifree = swab_long (ocg->cg_cs.cs_nifree);
- ocg->cg_cs.cs_nffree = swab_long (ocg->cg_cs.cs_nffree);
- ocg->cg_rotor = swab_long (ocg->cg_rotor);
- ocg->cg_frotor = swab_long (ocg->cg_frotor);
- ocg->cg_irotor = swab_long (ocg->cg_irotor);
- for (i = 0; i < 8; i++)
- ocg->cg_frsum[i] = swab_long (ocg->cg_frsum[i]);
- for (i = 0; i < 32; i++)
- ocg->cg_btot[i] = swab_long (ocg->cg_btot[i]);
- for (i = 0; i < 32; i++)
- for (j = 0; j < 8; j++)
- ocg->cg_b[i][j] = swab_short (ocg->cg_b[i][j]);
- ocg->cg_magic = swab_long (ocg->cg_magic);
- }
-}
-
-
-/* Read cylinder group indexed CG. Set *CGPP to point at it.
- Return 1 if caller should call release_cgp when we're done with it;
- otherwise zero. */
-int
-read_cg (int cg, struct cg **cgpp)
-{
- struct cg *diskcg = cg_locate (cg);
-
- if (swab_disk)
- {
- *cgpp = malloc (sblock->fs_cgsize);
- bcopy (diskcg, *cgpp, sblock->fs_cgsize);
- swab_cg (*cgpp);
- return 1;
- }
- else
- {
- *cgpp = diskcg;
- return 0;
- }
-}
-
-/* Caller of read_cg is done with cg; write it back to disk (swapping it
- along the way) and free the memory allocated in read_cg. */
-void
-release_cg (struct cg *cgp)
-{
- int cgx = cgp->cg_cgx;
- swab_cg (cgp);
- bcopy (cgp, cg_locate (cgx), sblock->fs_cgsize);
- free (cgp);
-}
-
-
-/*
- * Allocate a block in the file system.
- *
- * The size of the requested block is given, which must be some
- * multiple of fs_fsize and <= fs_bsize.
- * A preference may be optionally specified. If a preference is given
- * the following hierarchy is used to allocate a block:
- * 1) allocate the requested block.
- * 2) allocate a rotationally optimal block in the same cylinder.
- * 3) allocate a block in the same cylinder group.
- * 4) quadradically rehash into other cylinder groups, until an
- * available block is located.
- * If no block preference is given the following hierarchy is used
- * to allocate a block:
- * 1) allocate a block in the cylinder group that contains the
- * inode for the file.
- * 2) quadradically rehash into other cylinder groups, until an
- * available block is located.
- */
-error_t
-ffs_alloc(register struct node *np,
- daddr_t lbn,
- daddr_t bpref,
- int size,
- daddr_t *bnp,
- struct protid *cred)
-{
- register struct fs *fs;
- daddr_t bno;
- int cg;
-
- *bnp = 0;
- fs = sblock;
-#ifdef DIAGNOSTIC
- if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0) {
- printf("dev = 0x%x, bsize = %d, size = %d, fs = %s\n",
- ip->i_dev, fs->fs_bsize, size, fs->fs_fsmnt);
- panic("ffs_alloc: bad size");
- }
- assert (cred);
-#endif /* DIAGNOSTIC */
- pthread_spin_lock (&alloclock);
- if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0)
- goto nospace;
- if (cred && !idvec_contains (cred->user->uids, 0)
- && freespace(fs, fs->fs_minfree) <= 0)
- goto nospace;
-#ifdef QUOTA
- if (error = chkdq(ip, (long)btodb(size), cred, 0))
- return (error);
-#endif
- if (bpref >= fs->fs_size)
- bpref = 0;
- if (bpref == 0)
- cg = ino_to_cg(fs, np->dn->number);
- else
- cg = dtog(fs, bpref);
- bno = (daddr_t)ffs_hashalloc(np, cg, (long)bpref, size,
- (u_long (*)())ffs_alloccg);
- if (bno > 0) {
- pthread_spin_unlock (&alloclock);
- np->dn_stat.st_blocks += btodb(size);
- np->dn_set_ctime = 1;
- np->dn_set_mtime = 1;
- *bnp = bno;
- alloc_sync (np);
- return (0);
- }
-#ifdef QUOTA
- /*
- * Restore user's disk quota because allocation failed.
- */
- (void) chkdq(ip, (long)-btodb(size), cred, FORCE);
-#endif
-nospace:
- pthread_spin_unlock (&alloclock);
- printf ("file system full");
-/* ffs_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 fragment to a bigger size
- *
- * The number and size of the old block is given, and a preference
- * and new size is also specified. The allocator attempts to extend
- * the original block. Failing that, the regular block allocator is
- * invoked to get an appropriate block.
- */
-error_t
-ffs_realloccg(register struct node *np,
- daddr_t lbprev,
- volatile daddr_t bpref,
- int osize,
- int nsize,
- daddr_t *pbn,
- struct protid *cred)
-{
- register struct fs *fs;
- int cg, error;
- volatile int request;
- daddr_t bprev, bno;
-
- *pbn = 0;
- fs = sblock;
-#ifdef DIAGNOSTIC
- if ((u_int)osize > fs->fs_bsize || fragoff(fs, osize) != 0 ||
- (u_int)nsize > fs->fs_bsize || fragoff(fs, nsize) != 0) {
- printf(
- "dev = 0x%x, bsize = %d, osize = %d, nsize = %d, fs = %s\n",
- ip->i_dev, fs->fs_bsize, osize, nsize, fs->fs_fsmnt);
- panic("ffs_realloccg: bad size");
- }
- if (cred == NOCRED)
- panic("ffs_realloccg: missing credential\n");
-#endif /* DIAGNOSTIC */
-
- pthread_spin_lock (&alloclock);
-
- if (!idvec_contains (cred->user->uids, 0)
- && freespace(fs, fs->fs_minfree) <= 0)
- goto nospace;
- error = diskfs_catch_exception ();
- if (error)
- return error;
- bprev = read_disk_entry ((dino (np->dn->number))->di_db[lbprev]);
- diskfs_end_catch_exception ();
- assert ("old block not allocated" && bprev);
-
-#if 0 /* Not needed in GNU Hurd ufs */
- /*
- * Allocate the extra space in the buffer.
- */
- if (error = bread(ITOV(ip), lbprev, osize, NOCRED, &bp)) {
- brelse(bp);
- return (error);
- }
-#ifdef QUOTA
- if (error = chkdq(ip, (long)btodb(nsize - osize), cred, 0)) {
- brelse(bp);
- return (error);
- }
-#endif
-#endif /* 0 */
-
- /*
- * Check for extension in the existing location.
- */
- cg = dtog(fs, bprev);
- bno = ffs_fragextend(np, cg, (long)bprev, osize, nsize);
- if (bno) {
- assert (bno == bprev);
- pthread_spin_unlock (&alloclock);
- np->dn_stat.st_blocks += btodb(nsize - osize);
- np->dn_set_ctime = 1;
- np->dn_set_mtime = 1;
- *pbn = bno;
-#if 0 /* Not done this way in GNU Hurd ufs. */
- allocbuf(bp, nsize);
- bp->b_flags |= B_DONE;
- bzero((char *)bp->b_data + osize, (u_int)nsize - osize);
- *bpp = bp;
-#endif
- alloc_sync (np);
- return (0);
- }
- /*
- * Allocate a new disk location.
- */
- if (bpref >= fs->fs_size)
- bpref = 0;
- switch ((int)fs->fs_optim) {
- case FS_OPTSPACE:
- /*
- * Allocate an exact sized fragment. Although this makes
- * best use of space, we will waste time relocating it if
- * the file continues to grow. If the fragmentation is
- * less than half of the minimum free reserve, we choose
- * to begin optimizing for time.
- */
- request = nsize;
- if (fs->fs_minfree < 5 ||
- fs->fs_cstotal.cs_nffree >
- fs->fs_dsize * fs->fs_minfree / (2 * 100))
- break;
- printf ("%s: optimization changed from SPACE to TIME\n",
- fs->fs_fsmnt);
- fs->fs_optim = FS_OPTTIME;
- break;
- case FS_OPTTIME:
- /*
- * At this point we have discovered a file that is trying to
- * grow a small fragment to a larger fragment. To save time,
- * we allocate a full sized block, then free the unused portion.
- * If the file continues to grow, the `ffs_fragextend' call
- * above will be able to grow it in place without further
- * copying. If aberrant programs cause disk fragmentation to
- * grow within 2% of the free reserve, we choose to begin
- * optimizing for space.
- */
- request = fs->fs_bsize;
- if (fs->fs_cstotal.cs_nffree <
- fs->fs_dsize * (fs->fs_minfree - 2) / 100)
- break;
- printf ("%s: optimization changed from TIME to SPACE\n",
- fs->fs_fsmnt);
- fs->fs_optim = FS_OPTSPACE;
- break;
- default:
- assert (0);
- /* NOTREACHED */
- }
- bno = (daddr_t)ffs_hashalloc(np, cg, (long)bpref, request,
- (u_long (*)())ffs_alloccg);
- if (bno > 0) {
-#if 0 /* Not necessary in GNU Hurd ufs */
- bp->b_blkno = fsbtodb(fs, bno);
- (void) vnode_pager_uncache(ITOV(ip));
-#endif
-/* Commented out here for Hurd; we don't want to free this until we've
- saved the old contents. Callers are responsible for freeing the
- block when they are done with it. */
-/* ffs_blkfree(np, bprev, (long)osize); */
- if (nsize < request)
- ffs_blkfree(np, bno + numfrags(fs, nsize),
- (long)(request - nsize));
- pthread_spin_unlock (&alloclock);
- np->dn_stat.st_blocks += btodb(nsize - osize);
- np->dn_set_mtime = 1;
- np->dn_set_ctime = 1;
- *pbn = bno;
-#if 0 /* Not done this way in GNU Hurd ufs */
- allocbuf(bp, nsize);
- bp->b_flags |= B_DONE;
- bzero((char *)bp->b_data + osize, (u_int)nsize - osize);
- *bpp = bp;
-#endif /* 0 */
- alloc_sync (np);
- return (0);
- }
-#ifdef QUOTA
- /*
- * Restore user's disk quota because allocation failed.
- */
- (void) chkdq(ip, (long)-btodb(nsize - osize), cred, FORCE);
-#endif
-#if 0 /* Not necesarry in GNU Hurd ufs */
- brelse(bp);
-#endif
-nospace:
- /*
- * no space available
- */
- pthread_spin_unlock (&alloclock);
- printf ("file system full");
-/* ffs_fserr(fs, cred->cr_uid, "file system full"); */
-/* uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); */
- return (ENOSPC);
-}
-
-#if 0 /* Not used (yet?) in GNU Hurd ufs */
-/*
- * 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.
- */
-#include <sys/sysctl.h>
-int doasyncfree = 1;
-struct ctldebug debug14 = { "doasyncfree", &doasyncfree };
-int
-ffs_reallocblks(ap)
- struct vop_reallocblks_args /* {
- struct vnode *a_vp;
- struct cluster_save *a_buflist;
- } */ *ap;
-{
- struct fs *fs;
- struct inode *ip;
- struct vnode *vp;
- struct buf *sbp, *ebp;
- daddr_t *bap, *sbap, *ebap;
- struct cluster_save *buflist;
- daddr_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_fs;
- if (fs->fs_contigsumsize <= 0)
- return (ENOSPC);
- 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("ffs_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->fs_bsize, NOCRED, &sbp)) {
- brelse(sbp);
- return (ENOSPC);
- }
- sbap = (daddr_t *)sbp->b_data;
- soff = idp->in_off;
- }
- /*
- * Find the preferred location for the cluster.
- */
- pref = ffs_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("ffs_reallocblk: start == end");
-#endif
- ssize = len - (idp->in_off + 1);
- if (bread(vp, idp->in_lbn, (int)fs->fs_bsize, NOCRED, &ebp))
- goto fail;
- ebap = (daddr_t *)ebp->b_data;
- }
- /*
- * Search the block map looking for an allocation of the desired size.
- */
- if ((newblk = (daddr_t)ffs_hashalloc(ip, dtog(fs, pref), (long)pref,
- len, (u_long (*)())ffs_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->fs_frag) {
- if (i == ssize)
- bap = ebap;
-#ifdef DIAGNOSTIC
- if (buflist->bs_children[i]->b_blkno != fsbtodb(fs, *bap))
- panic("ffs_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)
- VOP_UPDATE(vp, &time, &time, MNT_WAIT);
- }
- 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->fs_frag) {
- ffs_blkfree(ip, dbtofsb(fs, buflist->bs_children[i]->b_blkno),
- fs->fs_bsize);
- buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno);
- }
- return (0);
-
-fail:
- if (ssize < len)
- brelse(ebp);
- if (sbap != &ip->i_db[0])
- brelse(sbp);
- return (ENOSPC);
-}
-#endif /* 0 */
-
-/*
- * Allocate an inode in the file system.
- *
- * If allocating a directory, use ffs_dirpref to select the inode.
- * If allocating in a directory, the following hierarchy is followed:
- * 1) allocate the preferred inode.
- * 2) allocate an inode in the same cylinder group.
- * 3) quadradically rehash into other cylinder groups, until an
- * available inode is located.
- * If no inode preference is given the following hierarchy is used
- * to allocate an inode:
- * 1) allocate an inode in cylinder group 0.
- * 2) quadradically rehash into other cylinder groups, until an
- * available inode is located.
- */
-/* This is now the diskfs_alloc_node callback from the diskfs library
- (described in <hurd/diskfs.h>). It used to be ffs_valloc in BSD. */
-error_t
-diskfs_alloc_node (struct node *dir,
- mode_t mode,
- struct node **npp)
-{
- register struct fs *fs;
- struct node *np;
- ino_t ino, ipref;
- int cg, error;
- int sex;
-
- fs = sblock;
-
-
- pthread_spin_lock (&alloclock);
-
- if (fs->fs_cstotal.cs_nifree == 0)
- {
- pthread_spin_unlock (&alloclock);
- goto noinodes;
- }
-
- if (S_ISDIR (mode))
- ipref = ffs_dirpref(fs);
- else
- ipref = dir->dn->number;
-
- if (ipref >= fs->fs_ncg * fs->fs_ipg)
- ipref = 0;
- cg = ino_to_cg(fs, ipref);
- ino = (ino_t)ffs_hashalloc(dir, cg, (long)ipref,
- mode, ffs_nodealloccg);
- pthread_spin_unlock (&alloclock);
- if (ino == 0)
- goto noinodes;
- error = diskfs_cached_lookup (ino, &np);
- assert ("duplicate allocation" && !np->dn_stat.st_mode);
- assert (! (np->dn_stat.st_mode & S_IPTRANS));
- if (np->dn_stat.st_blocks) {
- printf("free inode %Ld had %Ld blocks\n",
- ino, np->dn_stat.st_blocks);
- np->dn_stat.st_blocks = 0;
- np->dn_set_ctime = 1;
- }
- np->dn_stat.st_flags = 0;
- /*
- * Set up a new generation number for this inode.
- */
- pthread_spin_lock (&gennumberlock);
- sex = diskfs_mtime->seconds;
- if (++nextgennumber < (u_long)sex)
- nextgennumber = sex;
- np->dn_stat.st_gen = nextgennumber;
- pthread_spin_unlock (&gennumberlock);
-
- *npp = np;
- alloc_sync (np);
- return (0);
-noinodes:
- printf ("out of inodes");
-/* ffs_fserr(fs, ap->a_cred->cr_uid, "out of inodes"); */
-/* uprintf("\n%s: create/symlink failed, no inodes free\n", fs->fs_fsmnt);*/
- return (ENOSPC);
-}
-
-/*
- * Find a cylinder to place a directory.
- *
- * The policy implemented by this algorithm is to select from
- * among those cylinder groups with above the average number of
- * free inodes, the one with the smallest number of directories.
- */
-static ino_t
-ffs_dirpref(register struct fs *fs)
-{
- int cg, minndir, mincg, avgifree;
-
- avgifree = fs->fs_cstotal.cs_nifree / fs->fs_ncg;
- minndir = fs->fs_ipg;
- mincg = 0;
- for (cg = 0; cg < fs->fs_ncg; cg++)
- if (csum[cg].cs_ndir < minndir &&
- csum[cg].cs_nifree >= avgifree) {
- mincg = cg;
- minndir = csum[cg].cs_ndir;
- }
- return ((ino_t)(fs->fs_ipg * mincg));
-}
-
-/*
- * Select the desired position for the next block in a file. The file is
- * logically divided into sections. The first section is composed of the
- * direct blocks. Each additional section contains fs_maxbpg blocks.
- *
- * If no blocks have been allocated in the first section, the policy is to
- * request a block in the same cylinder group as the inode that describes
- * the file. If no blocks have been allocated in any other section, the
- * policy is to place the section in a cylinder group with a greater than
- * average number of free blocks. An appropriate cylinder group is found
- * by using a rotor that sweeps the cylinder groups. When a new group of
- * blocks is needed, the sweep begins in the cylinder group following the
- * cylinder group from which the previous allocation was made. The sweep
- * continues until a cylinder group with greater than the average number
- * of free blocks is found. If the allocation is for the first block in an
- * indirect block, the information on the previous allocation is unavailable;
- * here a best guess is made based upon the logical block number being
- * allocated.
- *
- * If a section is already partially allocated, the policy is to
- * contiguously allocate fs_maxcontig blocks. The end of one of these
- * contiguous blocks and the beginning of the next is physically separated
- * so that the disk head will be in transit between them for at least
- * fs_rotdelay milliseconds. This is to allow time for the processor to
- * schedule another I/O transfer.
- */
-daddr_t
-ffs_blkpref(struct node *np,
- daddr_t lbn,
- int indx,
- daddr_t *bap)
-{
- register struct fs *fs;
- register int cg;
- int avgbfree, startcg;
- daddr_t nextblk;
-
- fs = sblock;
- pthread_spin_lock (&alloclock);
- if (indx % fs->fs_maxbpg == 0 || bap[indx - 1] == 0) {
- if (lbn < NDADDR) {
- cg = ino_to_cg(fs, np->dn->number);
- pthread_spin_unlock (&alloclock);
- return (fs->fs_fpg * cg + fs->fs_frag);
- }
- /*
- * Find a cylinder with greater than average number of
- * unused data blocks.
- */
- if (indx == 0 || bap[indx - 1] == 0)
- startcg =
- (ino_to_cg(fs, np->dn->number)
- + lbn / fs->fs_maxbpg);
- else
- startcg = dtog(fs,
- read_disk_entry (bap[indx - 1])) + 1;
- startcg %= fs->fs_ncg;
- avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg;
- for (cg = startcg; cg < fs->fs_ncg; cg++)
- if (csum[cg].cs_nbfree >= avgbfree) {
- fs->fs_cgrotor = cg;
- pthread_spin_unlock (&alloclock);
- return (fs->fs_fpg * cg + fs->fs_frag);
- }
- for (cg = 0; cg <= startcg; cg++)
- if (csum[cg].cs_nbfree >= avgbfree) {
- fs->fs_cgrotor = cg;
- pthread_spin_unlock (&alloclock);
- return (fs->fs_fpg * cg + fs->fs_frag);
- }
- pthread_spin_unlock (&alloclock);
- return 0;
- }
- pthread_spin_unlock (&alloclock);
- /*
- * One or more previous blocks have been laid out. If less
- * than fs_maxcontig previous blocks are contiguous, the
- * next block is requested contiguously, otherwise it is
- * requested rotationally delayed by fs_rotdelay milliseconds.
- */
- nextblk = read_disk_entry (bap[indx - 1]) + fs->fs_frag;
- if (indx < fs->fs_maxcontig
- || (read_disk_entry (bap[indx - fs->fs_maxcontig]) +
- blkstofrags(fs, fs->fs_maxcontig) != nextblk))
- {
- return (nextblk);
- }
- if (fs->fs_rotdelay != 0)
- /*
- * Here we convert ms of delay to frags as:
- * (frags) = (ms) * (rev/sec) * (sect/rev) /
- * ((sect/frag) * (ms/sec))
- * then round up to the next block.
- */
- nextblk += roundup(fs->fs_rotdelay * fs->fs_rps * fs->fs_nsect /
- (NSPF(fs) * 1000), fs->fs_frag);
- return (nextblk);
-}
-
-/*
- * Implement the cylinder overflow algorithm.
- *
- * The policy implemented by this algorithm is:
- * 1) allocate the block in its requested cylinder group.
- * 2) quadradically rehash on the cylinder group number.
- * 3) brute force search for a free block.
- */
-/*VARARGS5*/
-static u_long
-ffs_hashalloc(struct node *np,
- int cg,
- long pref,
- int size, /* size for data blocks, mode for inodes */
- u_long (*allocator)())
-{
- register struct fs *fs;
- long result;
- int i, icg = cg;
-
- fs = sblock;
- /*
- * 1: preferred cylinder group
- */
- result = (*allocator)(np, cg, pref, size);
- if (result)
- return (result);
- /*
- * 2: quadratic rehash
- */
- for (i = 1; i < fs->fs_ncg; i *= 2) {
- cg += i;
- if (cg >= fs->fs_ncg)
- cg -= fs->fs_ncg;
- result = (*allocator)(np, cg, 0, size);
- if (result)
- return (result);
- }
- /*
- * 3: brute force search
- * Note that we start at i == 2, since 0 was checked initially,
- * and 1 is always checked in the quadratic rehash.
- */
- cg = (icg + 2) % fs->fs_ncg;
- for (i = 2; i < fs->fs_ncg; i++) {
- result = (*allocator)(np, cg, 0, size);
- if (result)
- return (result);
- cg++;
- if (cg == fs->fs_ncg)
- cg = 0;
- }
- return 0;
-}
-
-/*
- * Determine whether a fragment can be extended.
- *
- * Check to see if the necessary fragments are available, and
- * if they are, allocate them.
- */
-static daddr_t
-ffs_fragextend(struct node *np,
- int cg,
- long bprev,
- int osize,
- int nsize)
-{
- register struct fs *fs;
- struct cg *cgp;
- long bno;
- int frags, bbase;
- int i;
- int releasecg;
-
- fs = sblock;
- if (csum[cg].cs_nffree < numfrags(fs, nsize - osize))
- return 0;
- frags = numfrags(fs, nsize);
- bbase = fragnum(fs, bprev);
- if (bbase > fragnum(fs, (bprev + frags - 1))) {
- /* cannot extend across a block boundary */
- return 0;
- }
-#if 0 /* Wrong for GNU Hurd ufs */
- error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)),
- (int)fs->fs_cgsize, NOCRED, &bp);
- if (error) {
- brelse(bp);
- return (NULL);
- }
- cgp = (struct cg *)bp->b_data;
-#else
- releasecg = read_cg (cg, &cgp);
-#endif
- if (!cg_chkmagic(cgp)) {
-/* brelse(bp); */
- if (releasecg)
- release_cg (cgp);
- return 0;
- }
- cgp->cg_time = diskfs_mtime->seconds;
- bno = dtogd(fs, bprev);
- for (i = numfrags(fs, osize); i < frags; i++)
- if (isclr(cg_blksfree(cgp), bno + i)) {
-/* brelse(bp); */
- if (releasecg)
- release_cg (cgp);
- return 0;
- }
- /*
- * the current fragment can be extended
- * deduct the count on fragment being extended into
- * increase the count on the remaining fragment (if any)
- * allocate the extended piece
- */
- for (i = frags; i < fs->fs_frag - bbase; i++)
- if (isclr(cg_blksfree(cgp), bno + i))
- break;
- cgp->cg_frsum[i - numfrags(fs, osize)]--;
- if (i != frags)
- cgp->cg_frsum[i - frags]++;
- for (i = numfrags(fs, osize); i < frags; i++) {
- clrbit(cg_blksfree(cgp), bno + i);
- cgp->cg_cs.cs_nffree--;
- fs->fs_cstotal.cs_nffree--;
- csum[cg].cs_nffree--;
- }
- if (releasecg)
- release_cg (cgp);
- record_poke (cgp, sblock->fs_cgsize);
- csum_dirty = 1;
- sblock_dirty = 1;
- fs->fs_fmod = 1;
-/* bdwrite(bp); */
- return (bprev);
-}
-
-/*
- * Determine whether a block can be allocated.
- *
- * Check to see if a block of the appropriate size is available,
- * and if it is, allocate it.
- */
-static u_long
-ffs_alloccg(struct node *np,
- int cg,
- daddr_t bpref,
- int size)
-{
- register struct fs *fs;
- struct cg *cgp;
- register int i;
- int bno, frags, allocsiz;
- int releasecg;
-
- fs = sblock;
- if (csum[cg].cs_nbfree == 0 && size == fs->fs_bsize)
- return 0;
-#if 0 /* Not this way in GNU Hurd ufs */
- error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)),
- (int)fs->fs_cgsize, NOCRED, &bp);
- if (error) {
- brelse(bp);
- return (NULL);
- }
- cgp = (struct cg *)bp->b_data;
-#else
- releasecg = read_cg (cg, &cgp);
-#endif
- if (!cg_chkmagic(cgp) ||
- (cgp->cg_cs.cs_nbfree == 0 && size == fs->fs_bsize)) {
-/* brelse(bp); */
- if (releasecg)
- release_cg (cgp);
- return 0;
- }
- cgp->cg_time = diskfs_mtime->seconds;
- if (size == fs->fs_bsize) {
- bno = ffs_alloccgblk(fs, cgp, bpref);
-/* bdwrite(bp); */
- if (releasecg)
- release_cg (cgp);
- return (bno);
- }
- /*
- * check to see if any fragments are already available
- * allocsiz is the size which will be allocated, hacking
- * it down to a smaller size if necessary
- */
- frags = numfrags(fs, size);
- for (allocsiz = frags; allocsiz < fs->fs_frag; allocsiz++)
- if (cgp->cg_frsum[allocsiz] != 0)
- break;
- if (allocsiz == fs->fs_frag) {
- /*
- * no fragments were available, so a block will be
- * allocated, and hacked up
- */
- if (cgp->cg_cs.cs_nbfree == 0) {
-/* brelse(bp); */
- if (releasecg)
- release_cg (cgp);
- return 0;
- }
- bno = ffs_alloccgblk(fs, cgp, bpref);
- bpref = dtogd(fs, bno);
- for (i = frags; i < fs->fs_frag; i++)
- setbit(cg_blksfree(cgp), bpref + i);
- i = fs->fs_frag - frags;
- cgp->cg_cs.cs_nffree += i;
- fs->fs_cstotal.cs_nffree += i;
- csum[cg].cs_nffree += i;
- fs->fs_fmod = 1;
- cgp->cg_frsum[i]++;
-
- if (releasecg)
- release_cg (cgp);
- record_poke (cgp, sblock->fs_cgsize);
- csum_dirty = 1;
- sblock_dirty = 1;
-/* bdwrite(bp); */
- return (bno);
- }
- bno = ffs_mapsearch(fs, cgp, bpref, allocsiz);
- if (bno < 0) {
-/* brelse(bp); */
- if (releasecg)
- release_cg (cgp);
- return 0;
- }
- for (i = 0; i < frags; i++)
- clrbit(cg_blksfree(cgp), bno + i);
- cgp->cg_cs.cs_nffree -= frags;
- fs->fs_cstotal.cs_nffree -= frags;
- csum[cg].cs_nffree -= frags;
- fs->fs_fmod = 1;
- cgp->cg_frsum[allocsiz]--;
- if (frags != allocsiz)
- cgp->cg_frsum[allocsiz - frags]++;
- if (releasecg)
- release_cg (cgp);
- record_poke (cgp, sblock->fs_cgsize);
- csum_dirty = 1;
- sblock_dirty = 1;
-/* bdwrite(bp); */
- return (cg * fs->fs_fpg + bno);
-}
-
-/*
- * Allocate a block in a cylinder group.
- *
- * This algorithm implements the following policy:
- * 1) allocate the requested block.
- * 2) allocate a rotationally optimal block in the same cylinder.
- * 3) allocate the next available block on the block rotor for the
- * specified cylinder group.
- * Note that this routine only allocates fs_bsize blocks; these
- * blocks may be fragmented by the routine that allocates them.
- */
-static daddr_t
-ffs_alloccgblk(register struct fs *fs,
- register struct cg *cgp,
- daddr_t bpref)
-{
- daddr_t bno, blkno;
- int cylno, pos, delta;
- short *cylbp;
- register int i;
-
- if (bpref == 0 || dtog(fs, bpref) != cgp->cg_cgx) {
- bpref = cgp->cg_rotor;
- goto norot;
- }
- bpref = blknum(fs, bpref);
- bpref = dtogd(fs, bpref);
- /*
- * if the requested block is available, use it
- */
- if (ffs_isblock(fs, cg_blksfree(cgp), fragstoblks(fs, bpref))) {
- bno = bpref;
- goto gotit;
- }
- /*
- * check for a block available on the same cylinder
- */
- cylno = cbtocylno(fs, bpref);
- if (cg_blktot(cgp)[cylno] == 0)
- goto norot;
- if (fs->fs_cpc == 0) {
- /*
- * Block layout information is not available.
- * Leaving bpref unchanged means we take the
- * next available free block following the one
- * we just allocated. Hopefully this will at
- * least hit a track cache on drives of unknown
- * geometry (e.g. SCSI).
- */
- goto norot;
- }
- /*
- * check the summary information to see if a block is
- * available in the requested cylinder starting at the
- * requested rotational position and proceeding around.
- */
- cylbp = cg_blks(fs, cgp, cylno);
- pos = cbtorpos(fs, bpref);
- for (i = pos; i < fs->fs_nrpos; i++)
- if (cylbp[i] > 0)
- break;
- if (i == fs->fs_nrpos)
- for (i = 0; i < pos; i++)
- if (cylbp[i] > 0)
- break;
- if (cylbp[i] > 0) {
- /*
- * found a rotational position, now find the actual
- * block. A panic if none is actually there.
- */
- pos = cylno % fs->fs_cpc;
- bno = (cylno - pos) * fs->fs_spc / NSPB(fs);
- assert (fs_postbl(fs, pos)[i] != -1);
- for (i = fs_postbl(fs, pos)[i];; ) {
- if (ffs_isblock(fs, cg_blksfree(cgp), bno + i)) {
- bno = blkstofrags(fs, (bno + i));
- goto gotit;
- }
- delta = fs_rotbl(fs)[i];
- if (delta <= 0 ||
- delta + i > fragstoblks(fs, fs->fs_fpg))
- break;
- i += delta;
- }
- printf("pos = %d, i = %d, fs = %s\n", pos, i, fs->fs_fsmnt);
- assert (0);
- }
-norot:
- /*
- * no blocks in the requested cylinder, so take next
- * available one in this cylinder group.
- */
- bno = ffs_mapsearch(fs, cgp, bpref, (int)fs->fs_frag);
- if (bno < 0)
- return 0;
- cgp->cg_rotor = bno;
-gotit:
- blkno = fragstoblks(fs, bno);
- ffs_clrblock(fs, cg_blksfree(cgp), (long)blkno);
- ffs_clusteracct(fs, cgp, blkno, -1);
- cgp->cg_cs.cs_nbfree--;
- fs->fs_cstotal.cs_nbfree--;
- csum[cgp->cg_cgx].cs_nbfree--;
- cylno = cbtocylno(fs, bno);
- cg_blks(fs, cgp, cylno)[cbtorpos(fs, bno)]--;
- cg_blktot(cgp)[cylno]--;
- fs->fs_fmod = 1;
- record_poke (cgp, sblock->fs_cgsize);
- csum_dirty = 1;
- sblock_dirty = 1;
- return (cgp->cg_cgx * fs->fs_fpg + bno);
-}
-
-#if 0 /* Not needed in GNU Hurd ufs (yet?) */
-/*
- * Determine whether a cluster can be allocated.
- *
- * We do not currently check for optimal rotational layout if there
- * are multiple choices in the same cylinder group. Instead we just
- * take the first one that we find following bpref.
- */
-static daddr_t
-ffs_clusteralloc(ip, cg, bpref, len)
- struct inode *ip;
- int cg;
- daddr_t bpref;
- int len;
-{
- register struct fs *fs;
- register struct cg *cgp;
- struct buf *bp;
- int i, run, bno, bit, map;
- u_char *mapp;
-
- fs = ip->i_fs;
- if (fs->fs_cs(fs, cg).cs_nbfree < len)
- return (NULL);
- if (bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize,
- NOCRED, &bp))
- goto fail;
- cgp = (struct cg *)bp->b_data;
- if (!cg_chkmagic(cgp))
- goto fail;
- /*
- * Check to see if a cluster of the needed size (or bigger) is
- * available in this cylinder group.
- */
- for (i = len; i <= fs->fs_contigsumsize; i++)
- if (cg_clustersum(cgp)[i] > 0)
- break;
- if (i > fs->fs_contigsumsize)
- goto fail;
- /*
- * Search the cluster map to find a big enough cluster.
- * We take the first one that we find, even if it is larger
- * than we need as we prefer to get one close to the previous
- * block allocation. We do not search before the current
- * preference point as we do not want to allocate a block
- * that is allocated before the previous one (as we will
- * then have to wait for another pass of the elevator
- * algorithm before it will be read). We prefer to fail and
- * be recalled to try an allocation in the next cylinder group.
- */
- if (dtog(fs, bpref) != cg)
- bpref = 0;
- else
- bpref = fragstoblks(fs, dtogd(fs, blknum(fs, bpref)));
- mapp = &cg_clustersfree(cgp)[bpref / NBBY];
- map = *mapp++;
- bit = 1 << (bpref % NBBY);
- for (run = 0, i = bpref; i < cgp->cg_nclusterblks; i++) {
- if ((map & bit) == 0) {
- run = 0;
- } else {
- run++;
- if (run == len)
- break;
- }
- if ((i & (NBBY - 1)) != (NBBY - 1)) {
- bit <<= 1;
- } else {
- map = *mapp++;
- bit = 1;
- }
- }
- if (i == cgp->cg_nclusterblks)
- goto fail;
- /*
- * Allocate the cluster that we have found.
- */
- bno = cg * fs->fs_fpg + blkstofrags(fs, i - run + 1);
- len = blkstofrags(fs, len);
- for (i = 0; i < len; i += fs->fs_frag)
- if (ffs_alloccgblk(fs, cgp, bno + i) != bno + i)
- panic("ffs_clusteralloc: lost block");
- brelse(bp);
- return (bno);
-
-fail:
- brelse(bp);
- return (0);
-}
-#endif
-
-/*
- * Determine whether an inode can be allocated.
- *
- * Check to see if an inode is available, and if it is,
- * allocate it using the following policy:
- * 1) allocate the requested inode.
- * 2) allocate the next available inode after the requested
- * inode in the specified cylinder group.
- */
-static u_long
-ffs_nodealloccg(struct node *np,
- int cg,
- daddr_t ipref,
- int mode)
-{
- register struct fs *fs;
- struct cg *cgp;
- int start, len, loc, map, i;
- int releasecg;
-
- fs = sblock;
- if (csum[cg].cs_nifree == 0)
- return 0;
-#if 0 /* Not this way in GNU Hurd ufs */
- error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)),
- (int)fs->fs_cgsize, NOCRED, &bp);
- if (error) {
- brelse(bp);
- return (NULL);
- }
- cgp = (struct cg *)bp->b_data;
-#else
- releasecg = read_cg (cg, &cgp);
-#endif
- if (!cg_chkmagic(cgp) || cgp->cg_cs.cs_nifree == 0) {
-/* brelse(bp); */
- if (releasecg)
- release_cg (cgp);
- return 0;
- }
- cgp->cg_time = diskfs_mtime->seconds;
- if (ipref) {
- ipref %= fs->fs_ipg;
- if (isclr(cg_inosused(cgp), ipref))
- goto gotit;
- }
- start = cgp->cg_irotor / NBBY;
- len = howmany(fs->fs_ipg - cgp->cg_irotor, NBBY);
- loc = skpc(0xff, len, &cg_inosused(cgp)[start]);
- if (loc == 0) {
- len = start + 1;
- start = 0;
- loc = skpc(0xff, len, &cg_inosused(cgp)[0]);
- assert (loc != 0);
- }
- i = start + len - loc;
- map = cg_inosused(cgp)[i];
- ipref = i * NBBY;
- for (i = 1; i < (1 << NBBY); i <<= 1, ipref++) {
- if ((map & i) == 0) {
- cgp->cg_irotor = ipref;
- goto gotit;
- }
- }
- assert (0);
- /* NOTREACHED */
-gotit:
- setbit(cg_inosused(cgp), ipref);
- cgp->cg_cs.cs_nifree--;
- fs->fs_cstotal.cs_nifree--;
- csum[cg].cs_nifree--;
- fs->fs_fmod = 1;
- if ((mode & IFMT) == IFDIR) {
- cgp->cg_cs.cs_ndir++;
- fs->fs_cstotal.cs_ndir++;
- csum[cg].cs_ndir++;
- }
- if (releasecg)
- release_cg (cgp);
- record_poke (cgp, sblock->fs_cgsize);
- csum_dirty = 1;
- sblock_dirty = 1;
-/* bdwrite(bp); */
- return (cg * fs->fs_ipg + ipref);
-}
-
-/*
- * Free a block or fragment.
- *
- * The specified block or fragment is placed back in the
- * free map. If a fragment is deallocated, a possible
- * block reassembly is checked.
- */
-void
-ffs_blkfree(register struct node *np,
- daddr_t bno,
- long size)
-{
- register struct fs *fs;
- struct cg *cgp;
- daddr_t blkno;
- int i, cg, blk, frags, bbase;
- int releasecg;
-
- fs = sblock;
- assert ((u_int)size <= fs->fs_bsize && !fragoff (fs, size));
- cg = dtog(fs, bno);
- if ((u_int)bno >= fs->fs_size) {
- printf("bad block %ld, ino %Ld\n", bno, np->dn->number);
-/* ffs_fserr(fs, ip->i_uid, "bad block"); */
- return;
- }
-#if 0 /* Not this way in GNU Hurd ufs */
- error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)),
- (int)fs->fs_cgsize, NOCRED, &bp);
- if (error) {
- brelse(bp);
- return;
- }
- cgp = (struct cg *)bp->b_data;
-#else
- releasecg = read_cg (cg, &cgp);
-#endif
- if (!cg_chkmagic(cgp)) {
-/* brelse(bp); */
- if (releasecg)
- release_cg (cgp);
- return;
- }
- cgp->cg_time = diskfs_mtime->seconds;
- bno = dtogd(fs, bno);
- if (size == fs->fs_bsize) {
- blkno = fragstoblks(fs, bno);
- assert (!ffs_isblock(fs, cg_blksfree (cgp), blkno));
- ffs_setblock(fs, cg_blksfree(cgp), blkno);
- ffs_clusteracct(fs, cgp, blkno, 1);
- cgp->cg_cs.cs_nbfree++;
- fs->fs_cstotal.cs_nbfree++;
- csum[cg].cs_nbfree++;
- i = cbtocylno(fs, bno);
- cg_blks(fs, cgp, i)[cbtorpos(fs, bno)]++;
- cg_blktot(cgp)[i]++;
- } else {
- bbase = bno - fragnum(fs, bno);
- /*
- * decrement the counts associated with the old frags
- */
- blk = blkmap(fs, cg_blksfree(cgp), bbase);
- ffs_fragacct(fs, blk, cgp->cg_frsum, -1);
- /*
- * deallocate the fragment
- */
- frags = numfrags(fs, size);
- for (i = 0; i < frags; i++) {
- assert (!isset (cg_blksfree(cgp), bno + i));
- setbit(cg_blksfree(cgp), bno + i);
- }
- cgp->cg_cs.cs_nffree += i;
- fs->fs_cstotal.cs_nffree += i;
- csum[cg].cs_nffree += i;
- /*
- * add back in counts associated with the new frags
- */
- blk = blkmap(fs, cg_blksfree(cgp), bbase);
- ffs_fragacct(fs, blk, cgp->cg_frsum, 1);
- /*
- * if a complete block has been reassembled, account for it
- */
- blkno = fragstoblks(fs, bbase);
- if (ffs_isblock(fs, cg_blksfree(cgp), blkno)) {
- cgp->cg_cs.cs_nffree -= fs->fs_frag;
- fs->fs_cstotal.cs_nffree -= fs->fs_frag;
- csum[cg].cs_nffree -= fs->fs_frag;
- ffs_clusteracct(fs, cgp, blkno, 1);
- cgp->cg_cs.cs_nbfree++;
- fs->fs_cstotal.cs_nbfree++;
- csum[cg].cs_nbfree++;
- i = cbtocylno(fs, bbase);
- cg_blks(fs, cgp, i)[cbtorpos(fs, bbase)]++;
- cg_blktot(cgp)[i]++;
- }
- }
- if (releasecg)
- release_cg (cgp);
- record_poke (cgp, sblock->fs_cgsize);
- csum_dirty = 1;
- sblock_dirty = 1;
- fs->fs_fmod = 1;
- alloc_sync (np);
-/* bdwrite(bp); */
-}
-
-/*
- * Free an inode.
- *
- * The specified inode is placed back in the free map.
- */
-/* Implement diskfs call back diskfs_free_node (described in
- <hurd/diskfs.h>. This was called ffs_vfree in BSD. */
-void
-diskfs_free_node (struct node *np, mode_t mode)
-{
- register struct fs *fs;
- struct cg *cgp;
- ino_t ino = np->dn->number;
- int cg;
- int releasecg;
-
- fs = sblock;
- assert (ino < fs->fs_ipg * fs->fs_ncg);
- cg = ino_to_cg(fs, ino);
-#if 0 /* Not this way in GNU Hurd ufs */
- error = bread(pip->i_devvp, fsbtodb(fs, cgtod(fs, cg)),
- (int)fs->fs_cgsize, NOCRED, &bp);
- if (error) {
- brelse(bp);
- return (0);
- }
- cgp = (struct cg *)bp->b_data;
-#else
- releasecg = read_cg (cg, &cgp);
-#endif
- if (!cg_chkmagic(cgp)) {
-/* brelse(bp); */
- if (releasecg)
- release_cg (cgp);
- return;
- }
- cgp->cg_time = diskfs_mtime->seconds;
- ino %= fs->fs_ipg;
- if (isclr(cg_inosused(cgp), ino)) {
-/* printf("dev = 0x%x, ino = %Ld, fs = %s\n",
- pip->i_dev, ino, fs->fs_fsmnt); */
- assert (diskfs_readonly);
- }
- clrbit(cg_inosused(cgp), ino);
- if (ino < cgp->cg_irotor)
- cgp->cg_irotor = ino;
- cgp->cg_cs.cs_nifree++;
- fs->fs_cstotal.cs_nifree++;
- csum[cg].cs_nifree++;
- if ((mode & IFMT) == IFDIR) {
- cgp->cg_cs.cs_ndir--;
- fs->fs_cstotal.cs_ndir--;
- csum[cg].cs_ndir--;
- }
- if (releasecg)
- release_cg (cgp);
- record_poke (cgp, sblock->fs_cgsize);
- csum_dirty = 1;
- sblock_dirty = 1;
- fs->fs_fmod = 1;
- alloc_sync (np);
-/* bdwrite(bp); */
-}
-
-/*
- * Find a block of the specified size in the specified cylinder group.
- *
- * It is a panic if a request is made to find a block if none are
- * available.
- */
-static daddr_t
-ffs_mapsearch(register struct fs *fs,
- register struct cg *cgp,
- daddr_t bpref,
- int allocsiz)
-{
- daddr_t bno;
- int start, len, loc, i;
- int blk, field, subfield, pos;
-
- /*
- * find the fragment by searching through the free block
- * map for an appropriate bit pattern
- */
- if (bpref)
- start = dtogd(fs, bpref) / NBBY;
- else
- start = cgp->cg_frotor / NBBY;
- len = howmany(fs->fs_fpg, NBBY) - start;
- loc = scanc((u_int)len, (u_char *)&cg_blksfree(cgp)[start],
- (u_char *)fragtbl[fs->fs_frag],
- (u_char)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY))));
- if (loc == 0) {
- len = start + 1;
- start = 0;
- loc = scanc((u_int)len, (u_char *)&cg_blksfree(cgp)[0],
- (u_char *)fragtbl[fs->fs_frag],
- (u_char)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY))));
- assert (loc);
-
- }
- bno = (start + len - loc) * NBBY;
- cgp->cg_frotor = bno;
- /*
- * found the byte in the map
- * sift through the bits to find the selected frag
- */
- for (i = bno + NBBY; bno < i; bno += fs->fs_frag) {
- blk = blkmap(fs, cg_blksfree(cgp), bno);
- blk <<= 1;
- field = around[allocsiz];
- subfield = inside[allocsiz];
- for (pos = 0; pos <= fs->fs_frag - allocsiz; pos++) {
- if ((blk & field) == subfield)
- return (bno + pos);
- field <<= 1;
- subfield <<= 1;
- }
- }
- assert (0);
- return (-1);
-}
-
-/*
- * Update the cluster map because of an allocation or free.
- *
- * Cnt == 1 means free; cnt == -1 means allocating.
- */
-static void
-ffs_clusteracct(struct fs *fs,
- struct cg *cgp,
- daddr_t blkno,
- int cnt)
-{
- long *sump;
- u_char *freemapp, *mapp;
- int i, start, end, forw, back, map, bit;
-
- if (fs->fs_contigsumsize <= 0)
- return;
- freemapp = cg_clustersfree(cgp);
- sump = cg_clustersum(cgp);
- /*
- * Allocate or clear the actual block.
- */
- if (cnt > 0)
- setbit(freemapp, blkno);
- else
- clrbit(freemapp, blkno);
- /*
- * Find the size of the cluster going forward.
- */
- start = blkno + 1;
- end = start + fs->fs_contigsumsize;
- if (end >= cgp->cg_nclusterblks)
- end = cgp->cg_nclusterblks;
- mapp = &freemapp[start / NBBY];
- map = *mapp++;
- bit = 1 << (start % NBBY);
- for (i = start; i < end; i++) {
- if ((map & bit) == 0)
- break;
- if ((i & (NBBY - 1)) != (NBBY - 1)) {
- bit <<= 1;
- } else {
- map = *mapp++;
- bit = 1;
- }
- }
- forw = i - start;
- /*
- * Find the size of the cluster going backward.
- */
- start = blkno - 1;
- end = start - fs->fs_contigsumsize;
- if (end < 0)
- end = -1;
- mapp = &freemapp[start / NBBY];
- map = *mapp--;
- bit = 1 << (start % NBBY);
- for (i = start; i > end; i--) {
- if ((map & bit) == 0)
- break;
- if ((i & (NBBY - 1)) != 0) {
- bit >>= 1;
- } else {
- map = *mapp--;
- bit = 1 << (NBBY - 1);
- }
- }
- back = start - i;
- /*
- * Account for old cluster and the possibly new forward and
- * back clusters.
- */
- i = back + forw + 1;
- if (i > fs->fs_contigsumsize)
- i = fs->fs_contigsumsize;
- sump[i] += cnt;
- if (back > 0)
- sump[back] -= cnt;
- if (forw > 0)
- sump[forw] -= cnt;
-}
-
-#if 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
-ffs_fserr(fs, uid, cp)
- struct fs *fs;
- u_int uid;
- char *cp;
-{
-
- log(LOG_ERR, "uid %d on %s: %s\n", uid, fs->fs_fsmnt, cp);
-}
-#endif
diff --git a/ufs/bmap.c b/ufs/bmap.c
deleted file mode 100644
index 1a138f39..00000000
--- a/ufs/bmap.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/* Interpretation of indirect block structure
- Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
- Written by Michael I. Bushnell.
-
- This file is part of the GNU Hurd.
-
- The GNU Hurd 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, or (at
- your option) any later version.
-
- The GNU Hurd 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 "ufs.h"
-
-/* For logical block number LBN of file NP, look it the block address,
- giving the "path" of indirect blocks to the file, starting
- with the least indirect. Fill *INDIRS with information for
- the block. */
-error_t
-fetch_indir_spec (struct node *np, volatile daddr_t lbn,
- struct iblock_spec *indirs)
-{
- struct dinode *di = dino (np->dn->number);
- error_t err;
- daddr_t *siblock;
-
- err = diskfs_catch_exception ();
- if (err)
- return err;
-
- indirs[0].offset = -2;
- indirs[1].offset = -2;
- indirs[2].offset = -2;
- indirs[3].offset = -2;
-
- if (lbn < NDADDR)
- {
- if (lbn >= 0)
- {
- indirs[0].bno = read_disk_entry (di->di_db[lbn]);
- indirs[0].offset = -1;
- }
-
- diskfs_end_catch_exception ();
- return 0;
- }
-
- lbn -= NDADDR;
-
- indirs[0].offset = lbn % NINDIR (sblock);
-
- if (lbn / NINDIR (sblock))
- {
- /* We will use the double indirect block */
- int ibn;
- daddr_t *diblock;
-
- ibn = lbn / NINDIR (sblock) - 1;
-
- indirs[1].offset = ibn % NINDIR (sblock);
-
- /* We don't support triple indirect blocks, but this
- is where we'd do it. */
- assert (!(ibn / NINDIR (sblock)));
-
- indirs[2].offset = -1;
- indirs[2].bno = read_disk_entry (di->di_ib[INDIR_DOUBLE]);
-
- if (indirs[2].bno)
- {
- diblock = indir_block (indirs[2].bno);
- indirs[1].bno = read_disk_entry (diblock[indirs[1].offset]);
- }
- else
- indirs[1].bno = 0;
- }
- else
- {
- indirs[1].offset = -1;
- indirs[1].bno = read_disk_entry (di->di_ib[INDIR_SINGLE]);
- }
-
- if (indirs[1].bno)
- {
- siblock = indir_block (indirs[1].bno);
- indirs[0].bno = read_disk_entry (siblock[indirs[0].offset]);
- }
- else
- indirs[0].bno = 0;
-
- diskfs_end_catch_exception ();
- return 0;
-}
-
-
-/* Mark indirect block BNO as dirty on node NP's list. NP must
- be locked. */
-void
-mark_indir_dirty (struct node *np, daddr_t bno)
-{
- struct dirty_indir *d;
-
- for (d = np->dn->dirty; d; d = d->next)
- if (d->bno == bno)
- return;
-
- d = malloc (sizeof (struct dirty_indir));
- d->bno = bno;
- d->next = np->dn->dirty;
- np->dn->dirty = d;
-}
-
diff --git a/ufs/consts.c b/ufs/consts.c
deleted file mode 100644
index 69221233..00000000
--- a/ufs/consts.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Various constants wanted by the diskfs library
- Copyright (C) 1994, 1995, 1996, 1999 Free Software Foundation
-
- 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, or (at
- your option) any later version.
-
- 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 "ufs.h"
-#include "dir.h"
-#include <version.h>
-
-int diskfs_link_max = LINK_MAX;
-int diskfs_name_max = MAXNAMLEN;
-int diskfs_maxsymlinks = 8;
-int diskfs_shortcut_symlink = 1;
-int diskfs_shortcut_chrdev = 1;
-int diskfs_shortcut_blkdev = 1;
-int diskfs_shortcut_fifo = 1;
-int diskfs_shortcut_ifsock = 1;
-char *diskfs_server_name = "ufs";
-char *diskfs_server_version = HURD_VERSION;
-char *diskfs_extra_version = "GNU Hurd";
-int diskfs_synchronous = 0;
diff --git a/ufs/dinode.h b/ufs/dinode.h
deleted file mode 100644
index 00be0d94..00000000
--- a/ufs/dinode.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- Copyright (C) 1994 Free Software Foundation
-
- 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, or (at
- your option) any later version.
-
- 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. */
-
-/*
- * 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 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.
- *
- * @(#)dinode.h 8.3 (Berkeley) 1/21/94
- */
-
-/*
- * The root inode is the root of the file system. Inode 0 can't be used for
- * normal purposes and historically bad blocks were linked to inode 1, thus
- * the root inode is 2. (Inode 1 is no longer used for this purpose, however
- * numerous dump tapes make this assumption, so we are stuck with it).
- */
-#define ROOTINO ((ino_t)2)
-
-/*
- * A dinode contains all the meta-data associated with a UFS file.
- * This structure defines the on-disk format of a dinode.
- */
-
-#define NDADDR 12 /* Direct addresses in inode. */
-#define NIADDR 3 /* Indirect addresses in inode. */
-
-/* Maximum value of di_nlink field. */
-#define LINK_MAX 32767
-
-/* Indexes into di_ib */
-#define INDIR_SINGLE 0
-#define INDIR_DOUBLE 1
-#define INDIR_TRIPLE 2 /* NOT SUPPORTED */
-
-struct dinode {
- u_short di_model; /* 0: IFMT and permissions. */
- short di_nlink; /* 2: File link count. */
- union
- {
- u_long diu_author; /* 4: File author */
- u_short diu_oldids[2]; /* Old format uid and gid */
- } di_u;
- u_quad_t di_size; /* 8: File byte count. */
- struct timespec di_atime; /* 16: Last access time. */
- struct timespec di_mtime; /* 24: Last modified time. */
- struct timespec di_ctime; /* 32: Last inode change time. */
- daddr_t di_db[NDADDR]; /* 40: Direct disk blocks. */
- daddr_t di_ib[NIADDR]; /* 88: Indirect disk blocks. */
- u_long di_flags; /* 100: Status flags (chflags). */
- long di_blocks; /* 104: Blocks actually held. */
- long di_gen; /* 108: Generation number. */
- u_long di_uid; /* 112: File owner. */
- u_long di_gid; /* 116: File group. */
- u_short di_modeh; /* 120: Mode high bits */
- u_short di_spare; /* 122: unused */
- long di_trans; /* 124: filesystem translator */
-};
-
-#define di_author di_u.diu_author /* GNU extension */
-#define di_ouid di_u.diu_oldids[0]
-#define di_ogid di_u.diu_oldids[1]
-
-/*
- * 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 di_rdev di_db[0]
-#define di_shortlink di_db
-#define MAXSYMLINKLEN ((NDADDR + NIADDR) * sizeof(daddr_t))
-
-/* File modes. */
-#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. */
diff --git a/ufs/dir.c b/ufs/dir.c
deleted file mode 100644
index c3bd424e..00000000
--- a/ufs/dir.c
+++ /dev/null
@@ -1,988 +0,0 @@
-/* Directory management routines
-
- Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2007
- Free Software Foundation, Inc.
-
- 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, or (at
- your option) any later version.
-
- 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 "ufs.h"
-#include "dir.h"
-
-#include <string.h>
-#include <stdio.h>
-#include <dirent.h>
-
-#undef d_ino
-
-enum slot_status
-{
- /* This means we haven't yet found room for a new entry. */
- LOOKING,
-
- /* This means that the specified entry is free and should be used. */
- TAKE,
-
- /* This means that the specified entry has enough room at the end
- to hold the new entry. */
- SHRINK,
-
- /* This means that there is enough space in the block, but not in
- any one single entry, so they all have to be shifted to make
- room. */
- COMPRESS,
-
- /* This means that the directory will have to be grown to hold the
- entry. */
- EXTEND,
-
- /* For removal and rename, this means that this is the location
- of the entry found. */
- HERE_TIS,
-};
-
-struct dirstat
-{
- /* Type of followp operation expected */
- enum lookup_type type;
-
- /* One of the statuses above */
- enum slot_status stat;
-
- /* Mapped address and length of directory */
- vm_address_t mapbuf;
- vm_size_t mapextent;
-
- /* Index of this directory block. */
- int idx;
-
- /* For stat COMPRESS, this is the address (inside mapbuf)
- of the first direct in the directory block to be compressed. */
- /* For stat HERE_TIS, SHRINK, and TAKE, this is the entry referenced. */
- struct directory_entry *entry;
-
- /* For stat HERE_TIS, type REMOVE, this is the address of the immediately
- previous direct in this directory block, or zero if this is the first. */
- struct directory_entry *preventry;
-
- /* For stat COMPRESS, this is the number of bytes needed to be copied
- in order to undertake the compression. */
- size_t nbytes;
-};
-
-const size_t diskfs_dirstat_size = sizeof (struct dirstat);
-
-/* Initialize DS such that diskfs_drop_dirstat will ignore it. */
-void
-diskfs_null_dirstat (struct dirstat *ds)
-{
- ds->type = LOOKUP;
-}
-
-static error_t
-dirscanblock (vm_address_t blockoff, struct node *dp, int idx,
- const char *name, int namelen, enum lookup_type type,
- struct dirstat *ds, ino_t *inum);
-
-/* Implement the diskfs_lookup from the diskfs library. See
- <hurd/diskfs.h> for the interface specification. */
-error_t
-diskfs_lookup_hard (struct node *dp, const char *name, enum lookup_type type,
- struct node **npp, struct dirstat *ds, struct protid *cred)
-{
- error_t err;
- ino_t inum;
- int namelen;
- int spec_dotdot;
- struct node *np = 0;
- int retry_dotdot = 0;
- memory_object_t memobj;
- vm_prot_t prot =
- (type == LOOKUP) ? VM_PROT_READ : (VM_PROT_READ | VM_PROT_WRITE);
- vm_address_t buf = 0;
- vm_size_t buflen = 0;
- int blockaddr;
- int idx, lastidx;
- int looped;
-
- if ((type == REMOVE) || (type == RENAME))
- assert (npp);
-
- if (npp)
- *npp = 0;
-
- spec_dotdot = type & SPEC_DOTDOT;
- type &= ~SPEC_DOTDOT;
-
- namelen = strlen (name);
-
- if (namelen > MAXNAMLEN)
- {
- if (ds)
- diskfs_null_dirstat (ds);
- return ENAMETOOLONG;
- }
-
- try_again:
- if (ds)
- {
- ds->type = LOOKUP;
- ds->mapbuf = 0;
- ds->mapextent = 0;
- }
- if (buf)
- {
- munmap ((caddr_t) buf, buflen);
- buf = 0;
- }
- if (ds && (type == CREATE || type == RENAME))
- ds->stat = LOOKING;
-
- /* Map in the directory contents. */
- memobj = diskfs_get_filemap (dp, prot);
-
- if (memobj == MACH_PORT_NULL)
- return errno;
-
- buf = 0;
- /* We allow extra space in case we have to do an EXTEND. */
- buflen = round_page (dp->dn_stat.st_size + DIRBLKSIZ);
- err = vm_map (mach_task_self (),
- &buf, buflen, 0, 1, memobj, 0, 0, prot, prot, 0);
- mach_port_deallocate (mach_task_self (), memobj);
-
- inum = 0;
-
- diskfs_set_node_atime (dp);
-
- /* Start the lookup at DP->dn->dir_idx. */
- idx = dp->dn->dir_idx;
- if (idx * DIRBLKSIZ > dp->dn_stat.st_size)
- idx = 0; /* just in case */
- blockaddr = buf + idx * DIRBLKSIZ;
- looped = (idx == 0);
- lastidx = idx;
- if (lastidx == 0)
- lastidx = dp->dn_stat.st_size / DIRBLKSIZ;
-
- while (!looped || idx < lastidx)
- {
- err = dirscanblock (blockaddr, dp, idx, name, namelen, type, ds, &inum);
- if (!err)
- {
- dp->dn->dir_idx = idx;
- break;
- }
- if (err != ENOENT)
- {
- munmap ((caddr_t) buf, buflen);
- return err;
- }
-
- blockaddr += DIRBLKSIZ;
- idx++;
- if (blockaddr - buf >= dp->dn_stat.st_size && !looped)
- {
- /* We've gotten to the end; start back at the beginning */
- looped = 1;
- blockaddr = buf;
- idx = 0;
- }
- }
-
- diskfs_set_node_atime (dp);
- if (diskfs_synchronous)
- diskfs_node_update (dp, 1);
-
- /* If err is set here, it's ENOENT, and we don't want to
- think about that as an error yet. */
- err = 0;
-
- if (inum && npp)
- {
- if (namelen != 2 || name[0] != '.' || name[1] != '.')
- {
- if (inum == dp->dn->number)
- {
- np = dp;
- diskfs_nref (np);
- }
- else
- {
- err = diskfs_cached_lookup (inum, &np);
- if (err)
- goto out;
- }
- }
-
- /* We are looking up .. */
- /* Check to see if this is the root of the filesystem. */
- else if (dp->dn->number == 2)
- {
- err = EAGAIN;
- goto out;
- }
-
- /* We can't just do diskfs_cached_lookup, because we would then deadlock.
- So we do this. Ick. */
- else if (retry_dotdot)
- {
- /* Check to see that we got the same answer as last time. */
- if (inum != retry_dotdot)
- {
- /* Drop what we *thought* was .. (but isn't any more) and
- try *again*. */
- diskfs_nput (np);
- pthread_mutex_unlock (&dp->lock);
- err = diskfs_cached_lookup (inum, &np);
- pthread_mutex_lock (&dp->lock);
- if (err)
- goto out;
- retry_dotdot = inum;
- goto try_again;
- }
- /* Otherwise, we got it fine and np is already set properly. */
- }
- else if (!spec_dotdot)
- {
- /* Lock them in the proper order, and then
- repeat the directory scan to see if this is still
- right. */
- pthread_mutex_unlock (&dp->lock);
- err = diskfs_cached_lookup (inum, &np);
- pthread_mutex_lock (&dp->lock);
- if (err)
- goto out;
- retry_dotdot = inum;
- goto try_again;
- }
-
- /* Here below are the spec dotdot cases. */
- else if (type == RENAME || type == REMOVE)
- np = ifind (inum);
-
- else if (type == LOOKUP)
- {
- diskfs_nput (dp);
- err = diskfs_cached_lookup (inum, &np);
- if (err)
- goto out;
- }
- else
- assert (0);
- }
-
- if ((type == CREATE || type == RENAME) && !inum && ds && ds->stat == LOOKING)
- {
- /* We didn't find any room, so mark ds to extend the dir */
- ds->type = CREATE;
- ds->stat = EXTEND;
- ds->idx = dp->dn_stat.st_size / DIRBLKSIZ;
- }
-
- /* Return to the user; if we can't, release the reference
- (and lock) we acquired above. */
- out:
- /* Deallocate or save the mapping. */
- if ((err && err != ENOENT)
- || !ds
- || ds->type == LOOKUP)
- {
- munmap ((caddr_t) buf, buflen);
- if (ds)
- ds->type = LOOKUP; /* set to be ignored by drop_dirstat */
- }
- else
- {
- ds->mapbuf = buf;
- ds->mapextent = buflen;
- }
-
- if (np)
- {
- assert (npp);
- if (err)
- {
- if (!spec_dotdot)
- {
- /* Normal case */
- if (np == dp)
- diskfs_nrele (np);
- else
- diskfs_nput (np);
- }
- else if (type == RENAME || type == REMOVE)
- /* We just did ifind to get np; that allocates
- no new references, so we don't have anything to do */
- ;
- else if (type == LOOKUP)
- /* We did diskfs_cached_lookup */
- diskfs_nput (np);
- }
- else
- *npp = np;
- }
-
- return err ? : inum ? 0 : ENOENT;
-}
-
-/* Scan block at address BLKADDR (of node DP; block index IDX), for
- name NAME of length NAMELEN. Args TYPE, DS are as for
- diskfs_lookup. If found, set *INUM to the inode number, else
- return ENOENT. */
-static error_t
-dirscanblock (vm_address_t blockaddr, struct node *dp, int idx,
- const char *name, int namelen, enum lookup_type type,
- struct dirstat *ds, ino_t *inum)
-{
- int nfree = 0;
- int needed = 0;
- vm_address_t currentoff, prevoff;
- struct directory_entry *entry = 0;
- int nentries = 0;
- size_t nbytes = 0;
- int looking = 0;
- int countcopies = 0;
- int consider_compress = 0;
-
- if (ds && (ds->stat == LOOKING
- || ds->stat == COMPRESS))
- {
- looking = 1;
- countcopies = 1;
- needed = DIRSIZ (namelen);
- }
-
- for (currentoff = blockaddr, prevoff = 0;
- currentoff < blockaddr + DIRBLKSIZ;
- prevoff = currentoff, currentoff += read_disk_entry (entry->d_reclen))
- {
- entry = (struct directory_entry *)currentoff;
-
- if (!entry->d_reclen
- || read_disk_entry (entry->d_reclen) % 4
- || DIRECT_NAMLEN (entry) > MAXNAMLEN
- || (currentoff + read_disk_entry (entry->d_reclen)
- > blockaddr + DIRBLKSIZ)
- || entry->d_name[DIRECT_NAMLEN (entry)]
- || DIRSIZ (DIRECT_NAMLEN (entry)) > read_disk_entry (entry->d_reclen)
- || memchr (entry->d_name, '\0', DIRECT_NAMLEN (entry)))
- {
- fprintf (stderr, "Bad directory entry: inode: %Ld offset: %zd\n",
- dp->dn->number, currentoff - blockaddr + idx * DIRBLKSIZ);
- return ENOENT;
- }
-
- if (looking || countcopies)
- {
- int thisfree;
-
- /* Count how much free space this entry has in it. */
- if (entry->d_ino == 0)
- thisfree = read_disk_entry (entry->d_reclen);
- else
- thisfree = (read_disk_entry (entry->d_reclen)
- - DIRSIZ (DIRECT_NAMLEN (entry)));
-
- /* If this isn't at the front of the block, then it will
- have to be copied if we do a compression; count the
- number of bytes there too. */
- if (countcopies && currentoff != blockaddr)
- nbytes += DIRSIZ (DIRECT_NAMLEN (entry));
-
- if (ds->stat == COMPRESS && nbytes > ds->nbytes)
- /* The previously found compress is better than
- this one, so don't bother counting any more. */
- countcopies = 0;
-
- if (thisfree >= needed)
- {
- ds->type = CREATE;
- ds->stat = read_disk_entry (entry->d_ino) == 0 ? TAKE : SHRINK;
- ds->entry = entry;
- ds->idx = idx;
- looking = countcopies = 0;
- }
- else
- {
- nfree += thisfree;
- if (nfree >= needed)
- consider_compress = 1;
- }
- }
-
- if (entry->d_ino)
- nentries++;
-
- if (DIRECT_NAMLEN (entry) == namelen
- && entry->d_name[0] == name[0]
- && entry->d_ino
- && !bcmp (entry->d_name, name, namelen))
- break;
- }
-
- if (consider_compress
- && (ds->type == LOOKING
- || (ds->type == COMPRESS && ds->nbytes > nbytes)))
- {
- ds->type = CREATE;
- ds->stat = COMPRESS;
- ds->entry = (struct directory_entry *) blockaddr;
- ds->idx = idx;
- ds->nbytes = nbytes;
- }
-
- if (currentoff >= blockaddr + DIRBLKSIZ)
- {
- int i;
- /* The name is not in this block. */
-
- /* Because we scanned the entire block, we should write
- down how many entries there were. */
- if (!dp->dn->dirents)
- {
- dp->dn->dirents = malloc ((dp->dn_stat.st_size / DIRBLKSIZ)
- * sizeof (int));
- for (i = 0; i < dp->dn_stat.st_size/DIRBLKSIZ; i++)
- dp->dn->dirents[i] = -1;
- }
- /* Make sure the count is correct if there is one now. */
- assert (dp->dn->dirents[idx] == -1
- || dp->dn->dirents[idx] == nentries);
- dp->dn->dirents[idx] = nentries;
-
- return ENOENT;
- }
-
- /* We have found the required name. */
-
- if (ds && type == CREATE)
- ds->type = LOOKUP; /* it's invalid now */
- else if (ds && (type == REMOVE || type == RENAME))
- {
- ds->type = type;
- ds->stat = HERE_TIS;
- ds->entry = entry;
- ds->idx = idx;
- ds->preventry = (struct directory_entry *) prevoff;
- }
-
- *inum = read_disk_entry (entry->d_ino);
- return 0;
-}
-
-/* Following a lookup call for CREATE, this adds a node to a directory.
- DP is the directory to be modified; NAME is the name to be entered;
- NP is the node being linked in; DS is the cached information returned
- by lookup; CRED describes the user making the call. This call may
- only be made if the directory has been held locked continuously since
- the preceding lookup call, and only if that call returned ENOENT. */
-error_t
-diskfs_direnter_hard(struct node *dp,
- const char *name,
- struct node *np,
- struct dirstat *ds,
- struct protid *cred)
-{
- struct directory_entry *new;
- int namelen = strlen (name);
- int needed = DIRSIZ (namelen);
- int oldneeded;
- vm_address_t fromoff, tooff;
- int totfreed;
- error_t err;
- size_t oldsize = 0;
-
- assert (ds->type == CREATE);
-
- dp->dn_set_mtime = 1;
-
- switch (ds->stat)
- {
- case TAKE:
- /* We are supposed to consume this slot. */
- assert (ds->entry->d_ino == 0
- && read_disk_entry (ds->entry->d_reclen) >= needed);
-
- write_disk_entry (ds->entry->d_ino, np->dn->number);
- DIRECT_NAMLEN (ds->entry) = namelen;
- if (direct_symlink_extension)
- ds->entry->d_type = IFTODT (np->dn_stat.st_mode);
- bcopy (name, ds->entry->d_name, namelen + 1);
-
- break;
-
- case SHRINK:
- /* We are supposed to take the extra space at the end
- of this slot. */
- oldneeded = DIRSIZ (DIRECT_NAMLEN (ds->entry));
- assert (read_disk_entry (ds->entry->d_reclen) - oldneeded >= needed);
-
- new = (struct directory_entry *) ((vm_address_t) ds->entry + oldneeded);
-
- write_disk_entry (new->d_ino, np->dn->number);
- write_disk_entry (new->d_reclen,
- read_disk_entry (ds->entry->d_reclen) - oldneeded);
- DIRECT_NAMLEN (new) = namelen;
- if (direct_symlink_extension)
- new->d_type = IFTODT (np->dn_stat.st_mode);
- bcopy (name, new->d_name, namelen + 1);
-
- write_disk_entry (ds->entry->d_reclen, oldneeded);
-
- break;
-
- case COMPRESS:
- /* We are supposed to move all the entries to the
- front of the block, giving each the minimum
- necessary room. This should free up enough space
- for the new entry. */
- fromoff = tooff = (vm_address_t) ds->entry;
-
- while (fromoff < (vm_address_t) ds->entry + DIRBLKSIZ)
- {
- struct directory_entry *from = (struct directory_entry *)fromoff;
- struct directory_entry *to = (struct directory_entry *) tooff;
- int fromreclen = read_disk_entry (from->d_reclen);
-
- if (from->d_ino != 0)
- {
- assert (fromoff >= tooff);
-
- bcopy (from, to, fromreclen);
- write_disk_entry (to->d_reclen, DIRSIZ (DIRECT_NAMLEN (to)));
-
- tooff += read_disk_entry (to->d_reclen);
- }
- fromoff += fromreclen;
- }
-
- totfreed = (vm_address_t) ds->entry + DIRBLKSIZ - tooff;
- assert (totfreed >= needed);
-
- new = (struct directory_entry *) tooff;
- write_disk_entry (new->d_ino, np->dn->number);
- write_disk_entry (new->d_reclen, totfreed);
- DIRECT_NAMLEN (new) = namelen;
- if (direct_symlink_extension)
- new->d_type = IFTODT (np->dn_stat.st_mode);
- bcopy (name, new->d_name, namelen + 1);
- break;
-
- case EXTEND:
- /* Extend the file. */
- assert (needed <= DIRBLKSIZ);
-
- oldsize = dp->dn_stat.st_size;
- if ((off_t)(oldsize + DIRBLKSIZ) != dp->dn_stat.st_size + DIRBLKSIZ)
- {
- /* We can't possibly map the whole directory in. */
- munmap ((caddr_t) ds->mapbuf, ds->mapextent);
- return EOVERFLOW;
- }
- while (oldsize + DIRBLKSIZ > dp->allocsize)
- {
- err = diskfs_grow (dp, oldsize + DIRBLKSIZ, cred);
- if (err)
- {
- munmap ((caddr_t) ds->mapbuf, ds->mapextent);
- return err;
- }
- }
-
- new = (struct directory_entry *) (ds->mapbuf + oldsize);
-
- dp->dn_stat.st_size = oldsize + DIRBLKSIZ;
- dp->dn_set_ctime = 1;
-
- write_disk_entry (new->d_ino, np->dn->number);
- write_disk_entry (new->d_reclen, DIRBLKSIZ);
- DIRECT_NAMLEN (new) = namelen;
- if (direct_symlink_extension)
- new->d_type = IFTODT (np->dn_stat.st_mode);
- bcopy (name, new->d_name, namelen + 1);
- break;
-
- default:
- assert (0);
- }
-
- dp->dn_set_mtime = 1;
-
- munmap ((caddr_t) ds->mapbuf, ds->mapextent);
-
- if (ds->stat != EXTEND)
- {
- /* If we are keeping count of this block, then keep the count up
- to date. */
- if (dp->dn->dirents && dp->dn->dirents[ds->idx] != -1)
- dp->dn->dirents[ds->idx]++;
- }
- else
- {
- int i;
- /* It's cheap, so start a count here even if we aren't counting
- anything at all. */
- if (dp->dn->dirents)
- {
- dp->dn->dirents = realloc (dp->dn->dirents,
- (dp->dn_stat.st_size / DIRBLKSIZ
- * sizeof (int)));
- for (i = oldsize / DIRBLKSIZ;
- i < dp->dn_stat.st_size / DIRBLKSIZ;
- i++)
- dp->dn->dirents[i] = -1;
-
- dp->dn->dirents[ds->idx] = 1;
- }
- else
- {
- dp->dn->dirents = malloc (dp->dn_stat.st_size / DIRBLKSIZ
- * sizeof (int));
- for (i = 0; i < dp->dn_stat.st_size / DIRBLKSIZ; i++)
- dp->dn->dirents[i] = -1;
- dp->dn->dirents[ds->idx] = 1;
- }
- }
-
- diskfs_file_update (dp, 1);
-
- return 0;
-}
-
-/* Following a lookup call for REMOVE, this removes the link from the
- directory. DP is the directory being changed and DS is the cached
- information returned from lookup. This call is only valid if the
- directory has been locked continuously since the call to lookup, and
- only if that call succeeded. */
-error_t
-diskfs_dirremove_hard(struct node *dp,
- struct dirstat *ds)
-{
- assert (ds->type == REMOVE);
- assert (ds->stat == HERE_TIS);
-
- dp->dn_set_mtime = 1;
-
- if (ds->preventry == 0)
- ds->entry->d_ino = 0;
- else
- {
- assert ((vm_address_t) ds->entry - (vm_address_t) ds->preventry
- == read_disk_entry (ds->preventry->d_reclen));
- write_disk_entry (ds->preventry->d_reclen,
- (read_disk_entry (ds->preventry->d_reclen)
- + read_disk_entry (ds->entry->d_reclen)));
- }
-
- dp->dn_set_mtime = 1;
-
- munmap ((caddr_t) ds->mapbuf, ds->mapextent);
-
- /* If we are keeping count of this block, then keep the count up
- to date. */
- if (dp->dn->dirents && dp->dn->dirents[ds->idx] != -1)
- dp->dn->dirents[ds->idx]--;
-
- diskfs_file_update (dp, 1);
-
- return 0;
-}
-
-
-/* Following a lookup call for RENAME, this changes the inode number
- on a directory entry. DP is the directory being changed; NP is
- the new node being linked in; DP is the cached information returned
- by lookup. This call is only valid if the directory has been locked
- continuously since the call to lookup, and only if that call
- succeeded. */
-error_t
-diskfs_dirrewrite_hard(struct node *dp,
- struct node *np,
- struct dirstat *ds)
-{
- assert (ds->type == RENAME);
- assert (ds->stat == HERE_TIS);
-
- dp->dn_set_mtime = 1;
- write_disk_entry (ds->entry->d_ino, np->dn->number);
- if (direct_symlink_extension)
- ds->entry->d_type = IFTODT (np->dn_stat.st_mode);
- dp->dn_set_mtime = 1;
-
- munmap ((caddr_t) ds->mapbuf, ds->mapextent);
-
- diskfs_file_update (dp, 1);
-
- return 0;
-}
-
-/* Tell if DP is an empty directory (has only "." and ".." entries). */
-/* This routine must be called from inside a catch_exception (). */
-int
-diskfs_dirempty(struct node *dp,
- struct protid *cred)
-{
- struct directory_entry *entry;
- vm_address_t buf, curoff;
- memory_object_t memobj;
- error_t err;
-
- memobj = diskfs_get_filemap (dp, VM_PROT_READ);
-
- if (memobj == MACH_PORT_NULL)
- /* XXX should reflect error properly */
- return 0;
-
- buf = 0;
-
- err = vm_map (mach_task_self (), &buf, dp->dn_stat.st_size, 0,
- 1, memobj, 0, 0, VM_PROT_READ, VM_PROT_READ, 0);
- mach_port_deallocate (mach_task_self (), memobj);
- assert (!err);
-
- diskfs_set_node_atime (dp);
-
- for (curoff = buf;
- curoff < buf + dp->dn_stat.st_size;
- curoff += read_disk_entry (entry->d_reclen))
- {
- entry = (struct directory_entry *) curoff;
-
- if (entry->d_ino != 0
- && (DIRECT_NAMLEN (entry) > 2
- || entry->d_name[0] != '.'
- || (entry->d_name[1] != '.'
- && entry->d_name[1] != '\0')))
- {
- munmap ((caddr_t) buf, dp->dn_stat.st_size);
- diskfs_set_node_atime (dp);
- if (diskfs_synchronous)
- diskfs_node_update (dp, 1);
- return 0;
- }
- }
- diskfs_set_node_atime (dp);
- if (diskfs_synchronous)
- diskfs_node_update (dp, 1);
- munmap ((caddr_t) buf, dp->dn_stat.st_size);
- return 1;
-}
-
-/* Make DS an invalid dirstat. */
-error_t
-diskfs_drop_dirstat (struct node *dp, struct dirstat *ds)
-{
- if (ds->type != LOOKUP)
- {
- assert (ds->mapbuf);
- munmap ((caddr_t) ds->mapbuf, ds->mapextent);
- ds->type = LOOKUP;
- }
- return 0;
-}
-
-
-/* Count the entries in directory block NB for directory DP and
- write the answer down in its dirents array. As a side affect
- fill BUF with the block. */
-static error_t
-count_dirents (struct node *dp, int nb, char *buf)
-{
- size_t amt;
- char *offinblk;
- struct directory_entry *entry;
- int count = 0;
- error_t err;
-
- assert (dp->dn->dirents);
- assert ((nb + 1) * DIRBLKSIZ <= dp->dn_stat.st_size);
-
- err = diskfs_node_rdwr (dp, buf, nb * DIRBLKSIZ, DIRBLKSIZ, 0, 0, &amt);
- if (err)
- return err;
- assert (amt == DIRBLKSIZ);
-
- for (offinblk = buf;
- offinblk < buf + DIRBLKSIZ;
- offinblk += read_disk_entry (entry->d_reclen))
- {
- entry = (struct directory_entry *) offinblk;
- if (entry->d_ino)
- count++;
- }
-
- assert (dp->dn->dirents[nb] == -1 || dp->dn->dirents[nb] == count);
- dp->dn->dirents[nb] = count;
- return 0;
-}
-
-/* Implement the disikfs_get_directs callback as described in
- <hurd/diskfs.h>. */
-error_t
-diskfs_get_directs (struct node *dp,
- int entry,
- int nentries,
- char **data,
- size_t *datacnt,
- vm_size_t bufsiz,
- int *amt)
-{
- int blkno;
- int nblks;
- int curentry;
- char buf[DIRBLKSIZ];
- char *bufp;
- int bufvalid;
- error_t err;
- int i;
- char *datap;
- struct directory_entry *entryp;
- int allocsize;
- size_t checklen;
- struct dirent *userp;
-
- nblks = dp->dn_stat.st_size/DIRBLKSIZ;
-
- if (!dp->dn->dirents)
- {
- dp->dn->dirents = malloc (nblks * sizeof (int));
- for (i = 0; i < nblks; i++)
- dp->dn->dirents[i] = -1;
- }
-
- /* Scan through the entries to find ENTRY. If we encounter
- a -1 in the process then stop to fill it. When we run
- off the end, ENTRY is too big. */
- curentry = 0;
- bufvalid = 0;
- for (blkno = 0; blkno < nblks; blkno++)
- {
- if (dp->dn->dirents[blkno] == -1)
- {
- err = count_dirents (dp, blkno, buf);
- if (err)
- return err;
- bufvalid = 1;
- }
-
- if (curentry + dp->dn->dirents[blkno] > entry)
- /* ENTRY starts in this block. */
- break;
-
- curentry += dp->dn->dirents[blkno];
-
- bufvalid = 0;
- }
-
- if (blkno == nblks)
- {
- /* We reached the end of the directory without seeing ENTRY.
- This is treated as an EOF condition, meaning we return
- success with empty results. */
- *datacnt = 0;
- *amt = 0;
- return 0;
- }
-
- /* Allocate enough space to hold the maximum we might return */
- if (!bufsiz || bufsiz > dp->dn_stat.st_size)
- allocsize = round_page (dp->dn_stat.st_size);
- else
- allocsize = round_page (bufsiz);
-
- if (allocsize > *datacnt)
- *data = mmap (0, allocsize, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
-
- /* Set bufp appropriately */
- bufp = buf;
- if (curentry != entry)
- {
- /* Look through the block to find out where to start,
- setting bufp appropriately. */
- if (!bufvalid)
- {
- err = diskfs_node_rdwr (dp, buf, blkno * DIRBLKSIZ, DIRBLKSIZ,
- 0, 0, &checklen);
- if (err)
- return err;
- assert (checklen == DIRBLKSIZ);
- bufvalid = 1;
- }
- for (i = 0, bufp = buf;
- i < entry - curentry && bufp - buf < DIRBLKSIZ;
- (bufp
- += read_disk_entry (((struct directory_entry *)bufp)->d_reclen)),
- i++)
- ;
- /* Make sure we didn't run off the end. */
- assert (bufp - buf < DIRBLKSIZ);
- }
-
- i = 0;
- datap = *data;
-
- /* Copy the entries, one at a time. */
- while (((nentries == -1) || (i < nentries))
- && (!bufsiz || (datap - *data < bufsiz) )
- && blkno < nblks)
- {
- if (!bufvalid)
- {
- err = diskfs_node_rdwr (dp, buf, blkno * DIRBLKSIZ, DIRBLKSIZ,
- 0, 0, &checklen);
- if (err)
- return err;
- assert (checklen == DIRBLKSIZ);
- bufvalid = 1;
- bufp = buf;
- }
-
- entryp = (struct directory_entry *)bufp;
-
- if (entryp->d_ino)
- {
- userp = (struct dirent *) datap;
-
- userp->d_fileno = read_disk_entry (entryp->d_ino);
- userp->d_reclen = DIRSIZ (DIRECT_NAMLEN (entryp));
- userp->d_namlen = DIRECT_NAMLEN (entryp);
- bcopy (entryp->d_name, userp->d_name, DIRECT_NAMLEN (entryp) + 1);
- userp->d_type = DT_UNKNOWN; /* until fixed */
- i++;
- datap += DIRSIZ (DIRECT_NAMLEN (entryp));
- }
-
- bufp += read_disk_entry (entryp->d_reclen);
- if (bufp - buf == DIRBLKSIZ)
- {
- blkno++;
- bufvalid = 0;
- }
- }
-
- /* We've copied all we can. If we allocated our own array
- but didn't fill all of it, then free whatever memory we didn't use. */
- if (allocsize > *datacnt)
- {
- if (round_page (datap - *data) < allocsize)
- munmap (*data + round_page (datap - *data),
- allocsize - round_page (datap - *data));
- }
-
- /* Set variables for return */
- *datacnt = datap - *data;
- *amt = i;
- return 0;
-}
diff --git a/ufs/dir.h b/ufs/dir.h
deleted file mode 100644
index 5730ef44..00000000
--- a/ufs/dir.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/* Modified from BSD by Michael I. Bushnell for GNU Hurd ufs server. */
-/*
- * 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 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.
- *
- * @(#)dir.h 8.2 (Berkeley) 1/21/94
- */
-
-#ifndef _DIR_H_
-#define _DIR_H_
-
-#include <endian.h>
-
-/*
- * A directory consists of some number of blocks of DIRBLKSIZ
- * bytes, where DIRBLKSIZ is chosen such that it can be transferred
- * to disk in a single atomic operation (e.g. 512 bytes on most machines).
- *
- * Each DIRBLKSIZ byte block contains some number of directory entry
- * structures, which are of variable length. Each directory entry has
- * a struct direct at the front of it, containing its inode number,
- * the length of the entry, and the length of the name contained in
- * the entry. These are followed by the name padded to a 4 byte boundary
- * with null bytes. All names are guaranteed null terminated.
- * The maximum length of a name in a directory is MAXNAMLEN.
- *
- * The macro DIRSIZ(fmt, dp) gives the amount of space required to represent
- * a directory entry. Free space in a directory is represented by
- * entries which have dp->d_reclen > DIRSIZ(fmt, dp). All DIRBLKSIZ bytes
- * in a directory block are claimed by the directory entries. This
- * usually results in the last entry in a directory having a large
- * dp->d_reclen. When entries are deleted from a directory, the
- * space is returned to the previous entry in the same directory
- * block by increasing its dp->d_reclen. If the first entry of
- * a directory block is free, then its dp->d_ino is set to 0.
- * Entries other than the first in a directory do not normally have
- * dp->d_ino set to 0.
- */
-#define DIRBLKSIZ DEV_BSIZE
-#undef MAXNAMLEN
-#define MAXNAMLEN 255
-
-/* Don't call this struct DIRECT because the library defines that
- (sometimes) in a possible different way. */
-
-struct directory_entry {
- u_long d_ino; /* inode number of entry */
- u_short d_reclen; /* length of this record */
- u_char d_type; /* file type, see below */
- u_char d_namlen; /* length of string in d_name */
- char d_name[MAXNAMLEN + 1]; /* name with length <= MAXNAMLEN */
-};
-
-/* Return the type from a struct directory_entry, paying attention to whether
- this filesystem supports the type extension */
-#define DIRECT_TYPE(dp) (direct_symlink_extension ? (dp)->d_type : DT_UNKNOWN)
-
-/* Return the namlen from a struct direct, paying attention to whether
- this filesystem supports the type extension */
-#if (BYTE_ORDER == LITTLE_ENDIAN)
-#define DIRECT_NAMLEN(dp) (*(direct_symlink_extension || swab_disk \
- ? &(dp)->d_namlen \
- : &(dp)->d_type))
-#else
-#define DIRECT_NAMLEN(dp) (*(!direct_symlink_extension && swab_disk \
- ? &(dp)->d_type \
- : &(dp)->d_namlen))
-#endif
-
-/*
- * The DIRSIZ macro gives the minimum record length which will hold
- * the directory entry. This requires the amount of space in struct direct
- * without the d_name field, plus enough space for the name with a terminating
- * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
- */
-/* In BSD this macro takes a struct direct. Modified by MIB here to
- take the namelen (as computed by strlen). */
-#define DIRSIZ(namelen) \
- ((sizeof (struct directory_entry) - (MAXNAMLEN+1)) + (((namelen)+1 + 3) &~ 3))
-
-#if 0 /* This is the BSD definition */
-#if (BYTE_ORDER == LITTLE_ENDIAN)
-#define DIRSIZ(oldfmt, dp) \
- ((oldfmt) ? \
- ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_type+1 + 3) &~ 3)) : \
- ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)))
-#else
-#define DIRSIZ(oldfmt, dp) \
- ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
-#endif
-#endif /* 0 */
-
-#define OLDDIRFMT 1
-#define NEWDIRFMT 0
-
-#if 0 /* Not used in GNU */
-/*
- * Template for manipulating directories.
- * Should use struct direct's, but the name field
- * is MAXNAMLEN - 1, and this just won't do.
- */
-struct dirtemplate {
- u_long dot_ino;
- short dot_reclen;
- u_char dot_type;
- u_char dot_namlen;
- char dot_name[4]; /* must be multiple of 4 */
- u_long dotdot_ino;
- short dotdot_reclen;
- u_char dotdot_type;
- u_char dotdot_namlen;
- char dotdot_name[4]; /* ditto */
-};
-
-/*
- * This is the old format of directories, sanz type element.
- */
-struct odirtemplate {
- u_long dot_ino;
- short dot_reclen;
- u_short dot_namlen;
- char dot_name[4]; /* must be multiple of 4 */
- u_long dotdot_ino;
- short dotdot_reclen;
- u_short dotdot_namlen;
- char dotdot_name[4]; /* ditto */
-};
-#endif /* 0 */
-
-#endif /* !_DIR_H_ */
diff --git a/ufs/fs.h b/ufs/fs.h
deleted file mode 100644
index a2a3cc9b..00000000
--- a/ufs/fs.h
+++ /dev/null
@@ -1,509 +0,0 @@
-/*
- * 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 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
- */
-
-/*
- * 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.
- *
- * For file system fs, the offsets of the various blocks of interest
- * are given in the super block as:
- * [fs->fs_sblkno] Super-block
- * [fs->fs_cblkno] Cylinder group block
- * [fs->fs_iblkno] Inode blocks
- * [fs->fs_dblkno] Data blocks
- * The beginning of cylinder group cg in fs, is given by
- * the ``cgbase(fs, cg)'' macro.
- *
- * 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 BBSIZE 8192
-#define SBSIZE 8192
-#define BBOFF ((off_t)(0))
-#define SBOFF ((off_t)(BBOFF + BBSIZE))
-#define BBLOCK ((daddr_t)(0))
-#define SBLOCK ((daddr_t)(BBLOCK + BBSIZE / DEV_BSIZE))
-
-/*
- * Addresses stored in inodes are capable of addressing fragments
- * of `blocks'. File system blocks of at most size MAXBSIZE can
- * be optionally broken into 2, 4, or 8 pieces, each of which is
- * addressible; these pieces may be DEV_BSIZE, or some multiple of
- * a DEV_BSIZE unit.
- *
- * Large files consist of exclusively large data blocks. To avoid
- * undue wasted disk space, the last data block of a small file may be
- * allocated as only as many fragments of a large block as are
- * necessary. The file system format retains only a single pointer
- * to such a fragment, which is a piece of a single large block that
- * has been divided. The size of such a fragment is determinable from
- * information in the inode, using the ``blksize(fs, ip, lbn)'' macro.
- *
- * The file system records space availability at the fragment level;
- * to determine block availability, aligned fragments are examined.
- */
-
-/*
- * The file system is made out of blocks of at most MAXBSIZE units, with
- * smaller units (fragments) only in the last direct block. MAXBSIZE
- * primarily determines the size of buffers in the buffer pool. It may be
- * made larger without any effect on existing file systems; however making
- * it smaller make make some file systems unmountable.
- */
-#define MAXBSIZE MAXPHYS
-#define MAXFRAG 8
-
-/*
- * MINBSIZE is the smallest allowable block size.
- * In order to insure that it is possible to create files of size
- * 2^32 with only two levels of indirection, MINBSIZE is set to 4096.
- * MINBSIZE must be big enough to hold a cylinder group block,
- * thus changes to (struct cg) must keep its size within MINBSIZE.
- * Note that super blocks are always of size SBSIZE,
- * and that both SBSIZE and MAXBSIZE must be >= MINBSIZE.
- */
-#define MINBSIZE 4096
-
-/*
- * The path name on which the file system is mounted is maintained
- * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in
- * the super block for this name.
- * The limit on the amount of summary information per file system
- * is defined by MAXCSBUFS. It is currently parameterized for a
- * maximum of two million cylinders.
- */
-#define MAXMNTLEN 512
-#define MAXCSBUFS 32
-
-/*
- * A summary of contiguous blocks of various sizes is maintained
- * in each cylinder group. Normally this is set by the initial
- * value of fs_maxcontig. To conserve space, a maximum summary size
- * is set by FS_MAXCONTIG.
- */
-#define FS_MAXCONTIG 16
-
-/*
- * MINFREE gives the minimum acceptable percentage of file system
- * blocks which may be free. If the freelist drops below this level
- * only the superuser may continue to allocate blocks. This may
- * be set to 0 if no reserve of free blocks is deemed necessary,
- * however throughput drops by fifty percent if the file system
- * is run at between 95% and 100% full; thus the minimum default
- * value of fs_minfree is 5%. However, to get good clustering
- * performance, 10% is a better choice. hence we use 10% as our
- * default value. With 10% free space, fragmentation is not a
- * problem, so we choose to optimize for time.
- */
-#define MINFREE 5
-#define DEFAULTOPT FS_OPTTIME
-
-/*
- * Per cylinder group information; summarized in blocks allocated
- * from first cylinder group data blocks. These blocks have to be
- * read in from fs_csaddr (size fs_cssize) in addition to the
- * super block.
- *
- * N.B. sizeof(struct csum) must be a power of two in order for
- * the ``fs_cs'' macro to work (see below).
- */
-struct csum {
- long cs_ndir; /* number of directories */
- long cs_nbfree; /* number of free blocks */
- long cs_nifree; /* number of free inodes */
- long cs_nffree; /* number of free frags */
-};
-
-/*
- * Super block for a file system.
- */
-struct fs {
- struct fs *fs_link; /* linked list of file systems */
- struct fs *fs_rlink; /* used for incore super blocks */
- daddr_t fs_sblkno; /* addr of super-block in filesys */
- daddr_t fs_cblkno; /* offset of cyl-block in filesys */
- daddr_t fs_iblkno; /* offset of inode-blocks in filesys */
- daddr_t fs_dblkno; /* offset of first data after cg */
- long fs_cgoffset; /* cylinder group offset in cylinder */
- long fs_cgmask; /* used to calc mod fs_ntrak */
- time_t fs_time; /* last time written */
- long fs_size; /* number of blocks in fs */
- long fs_dsize; /* number of data blocks in fs */
- long fs_ncg; /* number of cylinder groups */
- long fs_bsize; /* size of basic blocks in fs */
- long fs_fsize; /* size of frag blocks in fs */
- long fs_frag; /* number of frags in a block in fs */
-/* these are configuration parameters */
- long fs_minfree; /* minimum percentage of free blocks */
- long fs_rotdelay; /* num of ms for optimal next block */
- long fs_rps; /* disk revolutions per second */
-/* these fields can be computed from the others */
- long fs_bmask; /* ``blkoff'' calc of blk offsets */
- long fs_fmask; /* ``fragoff'' calc of frag offsets */
- long fs_bshift; /* ``lblkno'' calc of logical blkno */
- long fs_fshift; /* ``numfrags'' calc number of frags */
-/* these are configuration parameters */
- long fs_maxcontig; /* max number of contiguous blks */
- long fs_maxbpg; /* max number of blks per cyl group */
-/* these fields can be computed from the others */
- long fs_fragshift; /* block to frag shift */
- long fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */
- long fs_sbsize; /* actual size of super block */
- long fs_csmask; /* csum block offset */
- long fs_csshift; /* csum block number */
- long fs_nindir; /* value of NINDIR */
- long fs_inopb; /* value of INOPB */
- long fs_nspf; /* value of NSPF */
-/* yet another configuration parameter */
- long fs_optim; /* optimization preference, see below */
-/* these fields are derived from the hardware */
- long fs_npsect; /* # sectors/track including spares */
- long fs_interleave; /* hardware sector interleave */
- long fs_trackskew; /* sector 0 skew, per track */
- long fs_headswitch; /* head switch time, usec */
- long fs_trkseek; /* track-to-track seek, usec */
-/* sizes determined by number of cylinder groups and their sizes */
- daddr_t fs_csaddr; /* blk addr of cyl grp summary area */
- long fs_cssize; /* size of cyl grp summary area */
- long fs_cgsize; /* cylinder group size */
-/* these fields are derived from the hardware */
- long fs_ntrak; /* tracks per cylinder */
- long fs_nsect; /* sectors per track */
- long fs_spc; /* sectors per cylinder */
-/* this comes from the disk driver partitioning */
- long fs_ncyl; /* cylinders in file system */
-/* these fields can be computed from the others */
- long fs_cpg; /* cylinders per group */
- long fs_ipg; /* inodes per group */
- long fs_fpg; /* blocks per group * fs_frag */
-/* this data must be re-computed after crashes */
- struct csum fs_cstotal; /* cylinder summary information */
-/* these fields are cleared at mount time */
- char fs_fmod; /* super block modified flag */
- char fs_clean; /* file system is clean flag */
- char fs_ronly; /* mounted read-only flag */
- char fs_flags; /* currently unused flag */
- char fs_fsmnt[MAXMNTLEN]; /* name mounted on */
-/* these fields retain the current block allocation info */
- long fs_cgrotor; /* last cg searched */
- struct csum *fs_csp[MAXCSBUFS];/* list of fs_cs info buffers */
- long fs_cpc; /* cyl per cycle in postbl */
- short fs_opostbl[16][8]; /* old rotation block list head */
- long fs_sparecon[50]; /* reserved for future constants */
- long fs_contigsumsize; /* size of cluster summary array */
- long fs_maxsymlinklen; /* max length of an internal symlink */
- long fs_inodefmt; /* format of on-disk inodes */
- u_quad_t fs_maxfilesize; /* maximum representable file size */
- quad_t fs_qbmask; /* ~fs_bmask - for use with quad size */
- quad_t fs_qfmask; /* ~fs_fmask - for use with quad size */
- long fs_state; /* validate fs_clean field */
- long fs_postblformat; /* format of positional layout tables */
- long fs_nrpos; /* number of rotational positions */
- long fs_postbloff; /* (short) rotation block list head */
- long fs_rotbloff; /* (u_char) blocks for each rotation */
- long fs_magic; /* magic number */
- u_char fs_space[1]; /* list of blocks for each rotation */
-/* actually longer */
-};
-/*
- * Filesystem idetification
- */
-#define FS_MAGIC 0x011954 /* the fast filesystem magic number */
-#define FS_OKAY 0x7c269d38 /* superblock checksum */
-#define FS_42INODEFMT -1 /* 4.2BSD inode format */
-#define FS_44INODEFMT 2 /* 4.4BSD inode format */
-/*
- * Preference for optimization.
- */
-#define FS_OPTTIME 0 /* minimize allocation time */
-#define FS_OPTSPACE 1 /* minimize disk fragmentation */
-
-/*
- * Rotational layout table format types
- */
-#define FS_42POSTBLFMT -1 /* 4.2BSD rotational table format */
-#define FS_DYNAMICPOSTBLFMT 1 /* dynamic rotational table format */
-/*
- * Macros for access to superblock array structures
- */
-#define fs_postbl(fs, cylno) \
- (((fs)->fs_postblformat == FS_42POSTBLFMT) \
- ? ((fs)->fs_opostbl[cylno]) \
- : ((short *)((char *)(fs) + (fs)->fs_postbloff) + (cylno) * (fs)->fs_nrpos))
-#define fs_rotbl(fs) \
- (((fs)->fs_postblformat == FS_42POSTBLFMT) \
- ? ((fs)->fs_space) \
- : ((u_char *)((char *)(fs) + (fs)->fs_rotbloff)))
-
-/*
- * The size of a cylinder group is calculated by CGSIZE. The maximum size
- * is limited by the fact that cylinder groups are at most one block.
- * Its size is derived from the size of the maps maintained in the
- * cylinder group and the (struct cg) size.
- */
-#define CGSIZE(fs) \
- /* base cg */ (sizeof(struct cg) + sizeof(long) + \
- /* blktot size */ (fs)->fs_cpg * sizeof(long) + \
- /* blks size */ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof(short) + \
- /* inode map */ howmany((fs)->fs_ipg, NBBY) + \
- /* block map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY) +\
- /* if present */ ((fs)->fs_contigsumsize <= 0 ? 0 : \
- /* cluster sum */ (fs)->fs_contigsumsize * sizeof(long) + \
- /* cluster map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPB(fs), NBBY)))
-
-#if 0 /* Wrong for GNU Hurd ufs; we don't use fs_csp at all. */
-/*
- * Convert cylinder group to base address of its global summary info.
- *
- * N.B. This macro assumes that sizeof(struct csum) is a power of two.
- */
-#define fs_cs(fs, indx) \
- fs_csp[(indx) >> (fs)->fs_csshift][(indx) & ~(fs)->fs_csmask]
-#else
-/* Global variable csum is declared in ufs.h; use it instead
- of fs_cs stuff. */
-#define fs_cs(fs, indx) this will generate a syntax error.
-#endif
-
-/*
- * Cylinder group block for a file system.
- */
-#define CG_MAGIC 0x090255
-struct cg {
- struct cg *cg_link; /* linked list of cyl groups */
- long cg_magic; /* magic number */
- time_t cg_time; /* time last written */
- long cg_cgx; /* we are the cgx'th cylinder group */
- short cg_ncyl; /* number of cyl's this cg */
- short cg_niblk; /* number of inode blocks this cg */
- long cg_ndblk; /* number of data blocks this cg */
- struct csum cg_cs; /* cylinder summary information */
- long cg_rotor; /* position of last used block */
- long cg_frotor; /* position of last used frag */
- long cg_irotor; /* position of last used inode */
- long cg_frsum[MAXFRAG]; /* counts of available frags */
- long cg_btotoff; /* (long) block totals per cylinder */
- long cg_boff; /* (short) free block positions */
- long cg_iusedoff; /* (char) used inode map */
- long cg_freeoff; /* (u_char) free block map */
- long cg_nextfreeoff; /* (u_char) next available space */
- long cg_clustersumoff; /* (long) counts of avail clusters */
- long cg_clusteroff; /* (char) free cluster map */
- long cg_nclusterblks; /* number of clusters this cg */
- long cg_sparecon[13]; /* reserved for future use */
- u_char cg_space[1]; /* space for cylinder group maps */
-/* actually longer */
-};
-/*
- * Macros for access to cylinder group array structures
- */
-#define cg_blktot(cgp) \
- (((cgp)->cg_magic != CG_MAGIC) \
- ? (((struct ocg *)(cgp))->cg_btot) \
- : ((long *)((char *)(cgp) + (cgp)->cg_btotoff)))
-#define cg_blks(fs, cgp, cylno) \
- (((cgp)->cg_magic != CG_MAGIC) \
- ? (((struct ocg *)(cgp))->cg_b[cylno]) \
- : ((short *)((char *)(cgp) + (cgp)->cg_boff) + (cylno) * (fs)->fs_nrpos))
-#define cg_inosused(cgp) \
- (((cgp)->cg_magic != CG_MAGIC) \
- ? (((struct ocg *)(cgp))->cg_iused) \
- : ((char *)((char *)(cgp) + (cgp)->cg_iusedoff)))
-#define cg_blksfree(cgp) \
- (((cgp)->cg_magic != CG_MAGIC) \
- ? (((struct ocg *)(cgp))->cg_free) \
- : ((u_char *)((char *)(cgp) + (cgp)->cg_freeoff)))
-#define cg_chkmagic(cgp) \
- ((cgp)->cg_magic == CG_MAGIC || ((struct ocg *)(cgp))->cg_magic == CG_MAGIC)
-#define cg_clustersfree(cgp) \
- ((u_char *)((char *)(cgp) + (cgp)->cg_clusteroff))
-#define cg_clustersum(cgp) \
- ((long *)((char *)(cgp) + (cgp)->cg_clustersumoff))
-
-/*
- * The following structure is defined
- * for compatibility with old file systems.
- */
-struct ocg {
- struct ocg *cg_link; /* linked list of cyl groups */
- struct ocg *cg_rlink; /* used for incore cyl groups */
- time_t cg_time; /* time last written */
- long cg_cgx; /* we are the cgx'th cylinder group */
- short cg_ncyl; /* number of cyl's this cg */
- short cg_niblk; /* number of inode blocks this cg */
- long cg_ndblk; /* number of data blocks this cg */
- struct csum cg_cs; /* cylinder summary information */
- long cg_rotor; /* position of last used block */
- long cg_frotor; /* position of last used frag */
- long cg_irotor; /* position of last used inode */
- long cg_frsum[8]; /* counts of available frags */
- long cg_btot[32]; /* block totals per cylinder */
- short cg_b[32][8]; /* positions of free blocks */
- char cg_iused[256]; /* used inode map */
- long cg_magic; /* magic number */
- u_char cg_free[1]; /* free block map */
-/* actually longer */
-};
-
-/*
- * Turn file system block numbers into disk block addresses.
- * This maps file system blocks to device size blocks.
- */
-#define fsbtodb(fs, b) ((b) << (fs)->fs_fsbtodb)
-#define dbtofsb(fs, b) ((b) >> (fs)->fs_fsbtodb)
-
-/*
- * Cylinder group macros to locate things in cylinder groups.
- * They calc file system addresses of cylinder group data structures.
- */
-#define cgbase(fs, c) ((daddr_t)((fs)->fs_fpg * (c)))
-#define cgdmin(fs, c) (cgstart(fs, c) + (fs)->fs_dblkno) /* 1st data */
-#define cgimin(fs, c) (cgstart(fs, c) + (fs)->fs_iblkno) /* inode blk */
-#define cgsblock(fs, c) (cgstart(fs, c) + (fs)->fs_sblkno) /* super blk */
-#define cgtod(fs, c) (cgstart(fs, c) + (fs)->fs_cblkno) /* cg block */
-#define cgstart(fs, c) \
- (cgbase(fs, c) + (fs)->fs_cgoffset * ((c) & ~((fs)->fs_cgmask)))
-
-/*
- * Macros for handling inode numbers:
- * inode number to file system block offset.
- * inode number to cylinder group number.
- * inode number to file system block address.
- */
-#define ino_to_cg(fs, x) ((x) / (fs)->fs_ipg)
-#define ino_to_fsba(fs, x) \
- ((daddr_t)(cgimin(fs, ino_to_cg(fs, x)) + \
- (blkstofrags((fs), (((x) % (fs)->fs_ipg) / INOPB(fs))))))
-#define ino_to_fsbo(fs, x) ((x) % INOPB(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)->fs_fpg)
-#define dtogd(fs, d) ((d) % (fs)->fs_fpg)
-
-/*
- * Extract the bits for a block from a map.
- * Compute the cylinder and rotational position of a cyl block addr.
- */
-#define blkmap(fs, map, loc) \
- (((map)[(loc) / NBBY] >> ((loc) % NBBY)) & (0xff >> (NBBY - (fs)->fs_frag)))
-#define cbtocylno(fs, bno) \
- ((bno) * NSPF(fs) / (fs)->fs_spc)
-#define cbtorpos(fs, bno) \
- (((bno) * NSPF(fs) % (fs)->fs_spc / (fs)->fs_nsect * (fs)->fs_trackskew + \
- (bno) * NSPF(fs) % (fs)->fs_spc % (fs)->fs_nsect * (fs)->fs_interleave) % \
- (fs)->fs_nsect * (fs)->fs_nrpos / (fs)->fs_npsect)
-
-/*
- * 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)->fs_qbmask)
-#define fragoff(fs, loc) /* calculates (loc % fs->fs_fsize) */ \
- ((loc) & (fs)->fs_qfmask)
-#define lblktosize(fs, blk) /* calculates (blk * fs->fs_bsize) */ \
- ((blk) << (fs)->fs_bshift)
-#define lblkno(fs, loc) /* calculates (loc / fs->fs_bsize) */ \
- ((loc) >> (fs)->fs_bshift)
-#define numfrags(fs, loc) /* calculates (loc / fs->fs_fsize) */ \
- ((loc) >> (fs)->fs_fshift)
-#define blkroundup(fs, size) /* calculates roundup(size, fs->fs_bsize) */ \
- (((size) + (fs)->fs_qbmask) & (fs)->fs_bmask)
-#define fragroundup(fs, size) /* calculates roundup(size, fs->fs_fsize) */ \
- (((size) + (fs)->fs_qfmask) & (fs)->fs_fmask)
-#define fragstoblks(fs, frags) /* calculates (frags / fs->fs_frag) */ \
- ((frags) >> (fs)->fs_fragshift)
-#define blkstofrags(fs, blks) /* calculates (blks * fs->fs_frag) */ \
- ((blks) << (fs)->fs_fragshift)
-#define fragnum(fs, fsb) /* calculates (fsb % fs->fs_frag) */ \
- ((fsb) & ((fs)->fs_frag - 1))
-#define blknum(fs, fsb) /* calculates rounddown(fsb, fs->fs_frag) */ \
- ((fsb) &~ ((fs)->fs_frag - 1))
-
-/*
- * Determine the number of available frags given a
- * percentage to hold in reserve
- */
-#define freespace(fs, percentreserved) \
- (blkstofrags((fs), (fs)->fs_cstotal.cs_nbfree) + \
- (fs)->fs_cstotal.cs_nffree - ((fs)->fs_dsize * (percentreserved) / 100))
-
-/*
- * Determining the size of a file block in the file system.
- */
-/* Changed from BSD to use allocsize instead of i_size. */
-#define blksize(fs, np, lbn) \
- (((lbn) >= NDADDR || (np)->allocsize >= ((lbn) + 1) << (fs)->fs_bshift) \
- ? (fs)->fs_bsize \
- : (fragroundup(fs, blkoff(fs, (np)->allocsize))))
-
-#if 0 /* Don't use this */
-#define dblksize(fs, dip, lbn) \
- (((lbn) >= NDADDR || (dip)->di_size >= ((lbn) + 1) << (fs)->fs_bshift) \
- ? (fs)->fs_bsize \
- : (fragroundup(fs, blkoff(fs, (dip)->di_size))))
-#endif
-
-/*
- * Number of disk sectors per block; assumes DEV_BSIZE byte sector size.
- */
-#define NSPB(fs) ((fs)->fs_nspf << (fs)->fs_fragshift)
-#define NSPF(fs) ((fs)->fs_nspf)
-
-/*
- * INOPB is the number of inodes in a secondary storage block.
- */
-#define INOPB(fs) ((fs)->fs_inopb)
-#define INOPF(fs) ((fs)->fs_inopb >> (fs)->fs_fragshift)
-
-/*
- * NINDIR is the number of indirects in a file system block.
- */
-#define NINDIR(fs) ((fs)->fs_nindir)
-
-extern int inside[], around[];
-extern u_char *fragtbl[];
diff --git a/ufs/hyper.c b/ufs/hyper.c
deleted file mode 100644
index 95013895..00000000
--- a/ufs/hyper.c
+++ /dev/null
@@ -1,414 +0,0 @@
-/* Fetching and storing the hypermetadata (superblock and cg summary info).
- Copyright (C) 1994, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
-
- 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, or (at
- your option) any later version.
-
- 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 "ufs.h"
-#include <string.h>
-#include <stdio.h>
-#include <error.h>
-#include <hurd/store.h>
-
-static int ufs_clean; /* fs clean before we started writing? */
-
-static int oldformat;
-
-void *zeroblock;
-
-struct fs *sblock;
-struct csum *csum;
-
-void
-swab_sblock (struct fs *sblock)
-{
- int i, j;
-
- sblock->fs_sblkno = swab_long (sblock->fs_sblkno);
- sblock->fs_cblkno = swab_long (sblock->fs_cblkno);
- sblock->fs_iblkno = swab_long (sblock->fs_iblkno);
- sblock->fs_dblkno = swab_long (sblock->fs_dblkno);
- sblock->fs_cgoffset = swab_long (sblock->fs_cgoffset);
- sblock->fs_cgmask = swab_long (sblock->fs_cgmask);
- sblock->fs_time = swab_long (sblock->fs_time);
- sblock->fs_size = swab_long (sblock->fs_size);
- sblock->fs_dsize = swab_long (sblock->fs_dsize);
- sblock->fs_ncg = swab_long (sblock->fs_ncg);
- sblock->fs_bsize = swab_long (sblock->fs_bsize);
- sblock->fs_fsize = swab_long (sblock->fs_fsize);
- sblock->fs_frag = swab_long (sblock->fs_frag);
- sblock->fs_minfree = swab_long (sblock->fs_minfree);
- sblock->fs_rotdelay = swab_long (sblock->fs_rotdelay);
- sblock->fs_rps = swab_long (sblock->fs_rps);
- sblock->fs_bmask = swab_long (sblock->fs_bmask);
- sblock->fs_fmask = swab_long (sblock->fs_fmask);
- sblock->fs_bshift = swab_long (sblock->fs_bshift);
- sblock->fs_fshift = swab_long (sblock->fs_fshift);
- sblock->fs_maxcontig = swab_long (sblock->fs_maxcontig);
- sblock->fs_maxbpg = swab_long (sblock->fs_maxbpg);
- sblock->fs_fragshift = swab_long (sblock->fs_fragshift);
- sblock->fs_fsbtodb = swab_long (sblock->fs_fsbtodb);
- sblock->fs_sbsize = swab_long (sblock->fs_sbsize);
- sblock->fs_csmask = swab_long (sblock->fs_csmask);
- sblock->fs_csshift = swab_long (sblock->fs_csshift);
- sblock->fs_nindir = swab_long (sblock->fs_nindir);
- sblock->fs_inopb = swab_long (sblock->fs_inopb);
- sblock->fs_nspf = swab_long (sblock->fs_nspf);
- sblock->fs_optim = swab_long (sblock->fs_optim);
- sblock->fs_npsect = swab_long (sblock->fs_npsect);
- sblock->fs_interleave = swab_long (sblock->fs_interleave);
- sblock->fs_trackskew = swab_long (sblock->fs_trackskew);
- sblock->fs_headswitch = swab_long (sblock->fs_headswitch);
- sblock->fs_trkseek = swab_long (sblock->fs_trkseek);
- sblock->fs_csaddr = swab_long (sblock->fs_csaddr);
- sblock->fs_cssize = swab_long (sblock->fs_cssize);
- sblock->fs_cgsize = swab_long (sblock->fs_cgsize);
- sblock->fs_ntrak = swab_long (sblock->fs_ntrak);
- sblock->fs_nsect = swab_long (sblock->fs_nsect);
- sblock->fs_spc = swab_long (sblock->fs_spc);
- sblock->fs_ncyl = swab_long (sblock->fs_ncyl);
- sblock->fs_cpg = swab_long (sblock->fs_cpg);
- sblock->fs_ipg = swab_long (sblock->fs_ipg);
- sblock->fs_fpg = swab_long (sblock->fs_fpg);
- sblock->fs_cstotal.cs_ndir = swab_long (sblock->fs_cstotal.cs_ndir);
- sblock->fs_cstotal.cs_nbfree = swab_long (sblock->fs_cstotal.cs_nbfree);
- sblock->fs_cstotal.cs_nifree = swab_long (sblock->fs_cstotal.cs_nifree);
- sblock->fs_cstotal.cs_nffree = swab_long (sblock->fs_cstotal.cs_nffree);
- /* fs_fmod, fs_clean, fs_ronly, fs_flags, fs_fsmnt are all char */
- sblock->fs_cgrotor = swab_long (sblock->fs_cgrotor);
- sblock->fs_cpc = swab_long (sblock->fs_cpc);
- sblock->fs_contigsumsize = swab_long (sblock->fs_contigsumsize);
- sblock->fs_maxsymlinklen = swab_long (sblock->fs_maxsymlinklen);
- sblock->fs_inodefmt = swab_long (sblock->fs_inodefmt);
- sblock->fs_maxfilesize = swab_long_long (sblock->fs_maxfilesize);
- sblock->fs_qbmask = swab_long_long (sblock->fs_qbmask);
- sblock->fs_state = swab_long (sblock->fs_state);
- sblock->fs_postblformat = swab_long (sblock->fs_postblformat);
- sblock->fs_nrpos = swab_long (sblock->fs_nrpos);
- sblock->fs_postbloff = swab_long (sblock->fs_postbloff);
- sblock->fs_rotbloff = swab_long (sblock->fs_rotbloff);
- sblock->fs_magic = swab_long (sblock->fs_magic);
-
- /* Tables */
- if (sblock->fs_postblformat == FS_42POSTBLFMT)
- for (i = 0; i < 16; i++)
- for (j = 0; j < 8; j++)
- sblock->fs_opostbl[i][j] = swab_short (sblock->fs_opostbl[i][j]);
- else
- for (i = 0; i < sblock->fs_cpc; i++)
- for (j = 0; j < sblock->fs_nrpos; j++)
- fs_postbl(sblock, j)[i]
- = swab_short (fs_postbl (sblock, j)[i]);
-
- /* The rot table is all chars */
-}
-
-void
-swab_csums (struct csum *csum)
-{
- int i;
-
- for (i = 0; i < sblock->fs_ncg; i++)
- {
- csum[i].cs_ndir = swab_long (csum[i].cs_ndir);
- csum[i].cs_nbfree = swab_long (csum[i].cs_nbfree);
- csum[i].cs_nifree = swab_long (csum[i].cs_nifree);
- csum[i].cs_nffree = swab_long (csum[i].cs_nffree);
- }
-}
-
-void
-get_hypermetadata (void)
-{
- error_t err;
-
- if (!sblock)
- sblock = malloc (SBSIZE);
-
- /* Free previous values. */
- if (zeroblock)
- munmap ((caddr_t) zeroblock, sblock->fs_bsize);
- if (csum)
- free (csum);
-
- err = diskfs_catch_exception ();
- assert_perror (err);
- bcopy (disk_image + SBOFF, sblock, SBSIZE);
- diskfs_end_catch_exception ();
-
- if ((swab_long (sblock->fs_magic)) == FS_MAGIC)
- {
- swab_disk = 1;
- swab_sblock (sblock);
- }
- else
- swab_disk = 0;
-
- if (sblock->fs_magic != FS_MAGIC)
- {
- fprintf (stderr, "Bad magic number %#lx (should be %#x)\n",
- sblock->fs_magic, FS_MAGIC);
- exit (1);
- }
- if (sblock->fs_bsize > 8192)
- {
- fprintf (stderr, "Block size %ld is too big (max is 8192 bytes)\n",
- sblock->fs_bsize);
- exit (1);
- }
- if (sblock->fs_bsize < sizeof (struct fs))
- {
- fprintf (stderr, "Block size %ld is too small (min is %Zd bytes)\n",
- sblock->fs_bsize, sizeof (struct fs));
- exit (1);
- }
-
- if (sblock->fs_maxsymlinklen > (long)MAXSYMLINKLEN)
- {
- fprintf (stderr, "Max shortcut symlinklen %ld is too big (max is %ld)\n",
- sblock->fs_maxsymlinklen, (long)MAXSYMLINKLEN);
- exit (1);
- }
-
- assert ((__vm_page_size % DEV_BSIZE) == 0);
- assert ((sblock->fs_bsize % DEV_BSIZE) == 0);
- assert (__vm_page_size <= sblock->fs_bsize);
-
- /* Examine the clean bit and force read-only if unclean. */
- ufs_clean = sblock->fs_clean;
- if (! ufs_clean)
- {
- error (0, 0,
- "%s: warning: FILESYSTEM NOT UNMOUNTED CLEANLY; PLEASE fsck",
- diskfs_disk_name);
- if (! diskfs_readonly)
- {
- diskfs_readonly = 1;
- error (0, 0,
- "%s: MOUNTED READ-ONLY; MUST USE `fsysopts --writable'",
- diskfs_disk_name);
- }
- }
-
- /* If this is an old filesystem, then we have some more
- work to do; some crucial constants might not be set; we
- are therefore forced to set them here. */
-
- if (sblock->fs_npsect < sblock->fs_nsect)
- sblock->fs_npsect = sblock->fs_nsect;
-
- if (sblock->fs_interleave < 1)
- sblock->fs_interleave = 1;
-
- if (sblock->fs_postblformat == FS_42POSTBLFMT)
- sblock->fs_nrpos = 8;
-
- if (sblock->fs_inodefmt < FS_44INODEFMT)
- {
- quad_t sizepb = sblock->fs_bsize;
- int i;
-
- oldformat = 1;
- sblock->fs_maxfilesize = sblock->fs_bsize * NDADDR - 1;
- for (i = 0; i < NIADDR; i++)
- {
- sizepb *= NINDIR (sblock);
- sblock->fs_maxfilesize += sizepb;
- }
- sblock->fs_qbmask = ~sblock->fs_bmask;
- sblock->fs_qfmask = ~sblock->fs_fmask;
- }
-
- /* Find out if we support the 4.4 symlink/dirtype extension */
- if (sblock->fs_maxsymlinklen > 0)
- direct_symlink_extension = 1;
- else
- direct_symlink_extension = 0;
-
- csum = malloc (fsaddr (sblock, howmany (sblock->fs_cssize,
- sblock->fs_fsize)));
-
- assert (!diskfs_catch_exception ());
- bcopy (disk_image + fsaddr (sblock, sblock->fs_csaddr),
- csum,
- fsaddr (sblock, howmany (sblock->fs_cssize, sblock->fs_fsize)));
- diskfs_end_catch_exception ();
-
- if (swab_disk)
- swab_csums (csum);
-
- if (store->size < sblock->fs_size * sblock->fs_fsize)
- {
- fprintf (stderr,
- "Disk size (%Ld) less than necessary "
- "(superblock says we need %ld)\n",
- store->size, sblock->fs_size * sblock->fs_fsize);
- exit (1);
- }
-
- zeroblock = mmap (0, sblock->fs_bsize, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
-
- /* If the filesystem has new features in it, don't pay attention to
- the user's request not to use them. */
- if ((sblock->fs_inodefmt == FS_44INODEFMT
- || direct_symlink_extension)
- && compat_mode == COMPAT_BSD42)
- {
- compat_mode = COMPAT_BSD44;
- error (0, 0,
- "4.2 compat mode requested on 4.4 fs--switched to 4.4 mode");
- }
-}
-
-/* Write the csum data. This isn't backed by a pager because it is
- taken from ordinary data blocks and might not be an even number
- of pages; in that case writing it through the pager would nuke whatever
- pages came after it on the disk and were backed by file pagers. */
-error_t
-diskfs_set_hypermetadata (int wait, int clean)
-{
- error_t err;
-
- pthread_spin_lock (&alloclock);
-
- if (csum_dirty)
- {
- /* Copy into a page-aligned buffer to avoid bugs in kernel device
- code. */
- void *buf = 0;
- size_t read = 0;
- size_t bufsize = round_page (fragroundup (sblock, sblock->fs_cssize));
-
- err = store_read (store,
- fsbtodb (sblock, sblock->fs_csaddr)
- << log2_dev_blocks_per_dev_bsize,
- bufsize, &buf, &read);
- if (err)
- return err;
- else if (read != bufsize)
- err = EIO;
- else
- {
- size_t wrote;
- bcopy (csum, buf, sblock->fs_cssize);
- if (swab_disk)
- swab_csums ((struct csum *)buf);
- err = store_write (store,
- fsbtodb (sblock, sblock->fs_csaddr)
- << log2_dev_blocks_per_dev_bsize,
- buf, bufsize, &wrote);
- if (!err && wrote != bufsize)
- err = EIO;
- }
-
- munmap (buf, read);
-
- if (err)
- {
- pthread_spin_unlock (&alloclock);
- return err;
- }
-
- csum_dirty = 0;
- }
-
- if (clean && ufs_clean && !sblock->fs_clean)
- {
- /* The filesystem is clean, so set the clean flag. */
- sblock->fs_clean = 1;
- sblock_dirty = 1;
- }
- else if (!clean && sblock->fs_clean)
- {
- /* Clear the clean flag */
- sblock->fs_clean = 0;
- sblock_dirty = 1;
- wait = 1; /* must be synchronous */
- }
-
- pthread_spin_unlock (&alloclock);
-
- /* Update the superblock if necessary (clean bit was just set). */
- copy_sblock ();
-
- sync_disk (wait);
- return 0;
-}
-
-/* Copy the sblock into the disk */
-void
-copy_sblock ()
-{
- error_t err;
-
- err = diskfs_catch_exception ();
- assert_perror (err);
-
- pthread_spin_lock (&alloclock);
-
- if (sblock_dirty)
- {
- assert (! diskfs_readonly);
-
- if (sblock->fs_postblformat == FS_42POSTBLFMT
- || oldformat
- || swab_disk)
- {
- char sblockcopy[SBSIZE];
- struct fs *sbcopy = (struct fs *)sblockcopy;
- bcopy (sblock, sblockcopy, SBSIZE);
- if (sblock->fs_postblformat == FS_42POSTBLFMT)
- sbcopy->fs_nrpos = -1;
- if (oldformat)
- {
- sbcopy->fs_maxfilesize = -1;
- sbcopy->fs_qbmask = -1;
- sbcopy->fs_qfmask = -1;
- }
- if (swab_disk)
- swab_sblock (sbcopy);
- bcopy (sbcopy, disk_image + SBOFF, SBSIZE);
- }
- else
- bcopy (sblock, disk_image + SBOFF, SBSIZE);
- record_poke (disk_image + SBOFF, SBSIZE);
- sblock_dirty = 0;
- }
-
- pthread_spin_unlock (&alloclock);
-
- diskfs_end_catch_exception ();
-}
-
-void
-diskfs_readonly_changed (int readonly)
-{
- (*(readonly ? store_set_flags : store_clear_flags)) (store, STORE_READONLY);
-
- mprotect (disk_image, store->size, PROT_READ | (readonly ? 0 : PROT_WRITE));
-
- if (readonly)
- {
- /* We know we are sync'd now. The superblock is marked as dirty
- because we cleared the clean flag immediately after sync'ing.
- But now we want to leave it marked clean and not touch it further. */
- sblock_dirty = 0;
- return;
- }
-
- strcpy (sblock->fs_fsmnt, "Hurd /"); /* XXX */
-
- if (!sblock->fs_clean)
- error (0, 0, "WARNING: UNCLEANED FILESYSTEM NOW WRITABLE");
-}
diff --git a/ufs/inode.c b/ufs/inode.c
deleted file mode 100644
index 066eb1e5..00000000
--- a/ufs/inode.c
+++ /dev/null
@@ -1,705 +0,0 @@
-/* Inode management routines
-
- Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2007
- Free Software Foundation, Inc.
-
- 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, or (at
- your option) any later version.
-
- 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 "ufs.h"
-#include <string.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <netinet/in.h>
-#include <fcntl.h>
-#include <hurd/store.h>
-
-#define INOHSZ 512
-#if ((INOHSZ&(INOHSZ-1)) == 0)
-#define INOHASH(ino) ((ino)&(INOHSZ-1))
-#else
-#define INOHASH(ino) (((unsigned)(ino))%INOHSZ)
-#endif
-
-static struct node *nodehash[INOHSZ];
-static error_t read_disknode (struct node *np);
-
-pthread_spinlock_t gennumberlock = PTHREAD_SPINLOCK_INITIALIZER;
-
-/* Initialize the inode hash table. */
-void
-inode_init ()
-{
- int n;
- for (n = 0; n < INOHSZ; n++)
- nodehash[n] = 0;
-}
-
-/* Fetch inode INUM, set *NPP to the node structure;
- gain one user reference and lock the node. */
-error_t
-diskfs_cached_lookup (ino_t inum, struct node **npp)
-{
- struct disknode *dn;
- struct node *np;
- error_t err;
-
- pthread_spin_lock (&diskfs_node_refcnt_lock);
- for (np = nodehash[INOHASH(inum)]; np; np = np->dn->hnext)
- {
- if (np->dn->number != inum)
- continue;
-
- np->references++;
- pthread_spin_unlock (&diskfs_node_refcnt_lock);
- pthread_mutex_lock (&np->lock);
- *npp = np;
- return 0;
- }
-
- dn = malloc (sizeof (struct disknode));
-
- dn->number = inum;
- dn->dirents = 0;
- dn->dir_idx = 0;
-
- pthread_rwlock_init (&dn->allocptrlock, NULL);
- pthread_mutex_init (&dn->waitlock, NULL);
- pthread_cond_init (&dn->waitcond, NULL);
- dn->dirty = 0;
- dn->fileinfo = 0;
-
- np = diskfs_make_node (dn);
- np->cache_id = inum;
-
- pthread_mutex_lock (&np->lock);
- dn->hnext = nodehash[INOHASH(inum)];
- if (dn->hnext)
- dn->hnext->dn->hprevp = &dn->hnext;
- dn->hprevp = &nodehash[INOHASH(inum)];
- nodehash[INOHASH(inum)] = np;
- pthread_spin_unlock (&diskfs_node_refcnt_lock);
-
- err = read_disknode (np);
-
- if (!diskfs_check_readonly () && !np->dn_stat.st_gen)
- {
- pthread_spin_lock (&gennumberlock);
- if (++nextgennumber < diskfs_mtime->seconds)
- nextgennumber = diskfs_mtime->seconds;
- np->dn_stat.st_gen = nextgennumber;
- pthread_spin_unlock (&gennumberlock);
- np->dn_set_ctime = 1;
- }
-
- if (err)
- return err;
- else
- {
- *npp = np;
- return 0;
- }
-}
-
-/* Lookup node INUM (which must have a reference already) and return it
- without allocating any new references. */
-struct node *
-ifind (ino_t inum)
-{
- struct node *np;
-
- pthread_spin_lock (&diskfs_node_refcnt_lock);
- for (np = nodehash[INOHASH(inum)]; np; np = np->dn->hnext)
- {
- if (np->dn->number != inum)
- continue;
-
- assert (np->references);
- pthread_spin_unlock (&diskfs_node_refcnt_lock);
- return np;
- }
- assert (0);
-}
-
-/* The last reference to a node has gone away; drop
- it from the hash table and clean all state in the dn structure. */
-void
-diskfs_node_norefs (struct node *np)
-{
- *np->dn->hprevp = np->dn->hnext;
- if (np->dn->hnext)
- np->dn->hnext->dn->hprevp = np->dn->hprevp;
- if (np->dn->dirents)
- free (np->dn->dirents);
- assert (!np->dn->fileinfo);
- free (np->dn);
- free (np);
-}
-
-/* The last hard reference to a node has gone away; arrange to have
- all the weak references dropped that can be. */
-void
-diskfs_try_dropping_softrefs (struct node *np)
-{
- drop_pager_softrefs (np);
-}
-
-/* The last hard reference to a node has gone away. */
-void
-diskfs_lost_hardrefs (struct node *np)
-{
-#ifdef notanymore
- struct port_info *pi;
- struct pager *p;
-
- /* Check and see if there is a pager which has only
- one reference (ours). If so, then drop that reference,
- breaking the cycle. The complexity in this routine
- is all due to this cycle. */
-
- if (np->dn->fileinfo)
- {
- pthread_spin_lock (&_libports_portrefcntlock);
- pi = (struct port_info *) np->dn->fileinfo->p;
- if (pi->refcnt == 1)
- {
-
- /* The only way to get a new reference to the pager
- in this state is to call diskfs_get_filemap; this
- can't happen as long as we hold NP locked. So
- we can safely unlock _libports_portrefcntlock for
- the following call. */
- pthread_spin_unlock (&_libports_portrefcntlock);
-
- /* Right now the node is locked with no hard refs;
- this is an anomalous situation. Before messing with
- the reference count on the file pager, we have to
- give ourselves a reference back so that we are really
- allowed to hold the lock. Then we can do the
- unreference. */
- p = np->dn->fileinfo->p;
- np->dn->fileinfo = 0;
- diskfs_nref (np);
- pager_unreference (p);
-
- assert (np->references == 1 && np->light_references == 0);
-
- /* This will do the real deallocate. Whew. */
- diskfs_nput (np);
- }
- else
- pthread_spin_unlock (&_libports_portrefcntlock);
- }
-#endif
-}
-
-/* A new hard reference to a node has been created; it's now OK to
- have unused weak references. */
-void
-diskfs_new_hardrefs (struct node *np)
-{
- allow_pager_softrefs (np);
-}
-
-/* Read stat information out of the dinode. */
-static error_t
-read_disknode (struct node *np)
-{
- struct stat *st = &np->dn_stat;
- struct dinode *di = dino (np->dn->number);
- error_t err;
-
- err = diskfs_catch_exception ();
- if (err)
- return err;
-
- st->st_fstype = FSTYPE_UFS;
- st->st_fsid = getpid (); /* This call is very cheap. */
- st->st_ino = np->dn->number;
- st->st_gen = read_disk_entry (di->di_gen);
- st->st_rdev = read_disk_entry(di->di_rdev);
- st->st_mode = (((read_disk_entry (di->di_model)
- | (read_disk_entry (di->di_modeh) << 16))
- & ~S_ITRANS)
- | (di->di_trans ? S_IPTRANS : 0));
- st->st_nlink = read_disk_entry (di->di_nlink);
- st->st_size = read_disk_entry (di->di_size);
- st->st_atim.tv_sec = read_disk_entry (di->di_atime.tv_sec);
- st->st_atim.tv_nsec = read_disk_entry (di->di_atime.tv_nsec);
- st->st_mtim.tv_sec = read_disk_entry (di->di_mtime.tv_sec);
- st->st_mtim.tv_nsec = read_disk_entry (di->di_mtime.tv_nsec);
- st->st_ctim.tv_sec = read_disk_entry (di->di_ctime.tv_sec);
- st->st_ctim.tv_nsec = read_disk_entry (di->di_ctime.tv_nsec);
- st->st_blksize = sblock->fs_bsize;
- st->st_blocks = read_disk_entry (di->di_blocks);
- st->st_flags = read_disk_entry (di->di_flags);
-
- if (sblock->fs_inodefmt < FS_44INODEFMT)
- {
- st->st_uid = read_disk_entry (di->di_ouid);
- st->st_gid = read_disk_entry (di->di_ogid);
- st->st_author = st->st_uid;
- np->author_tracks_uid = 1;
- }
- else
- {
- st->st_uid = read_disk_entry (di->di_uid);
- st->st_gid = read_disk_entry (di->di_gid);
- st->st_author = read_disk_entry (di->di_author);
- if (st->st_author == -1)
- st->st_author = st->st_uid;
- }
-
- diskfs_end_catch_exception ();
- if (!S_ISBLK (st->st_mode) && !S_ISCHR (st->st_mode))
- st->st_rdev = 0;
-
- if (S_ISLNK (st->st_mode)
- && direct_symlink_extension
- && st->st_size < sblock->fs_maxsymlinklen)
- np->allocsize = 0;
- else
- {
- if (lblkno (sblock, np->dn_stat.st_size) < NDADDR)
- np->allocsize = fragroundup (sblock, st->st_size);
- else
- np->allocsize = blkroundup (sblock, st->st_size);
- }
-
- return 0;
-}
-
-error_t diskfs_node_reload (struct node *node)
-{
- if (node->dn->dirents)
- {
- free (node->dn->dirents);
- node->dn->dirents = 0;
- }
- flush_node_pager (node);
- read_disknode (node);
- return 0;
-}
-
-/* Return 0 if NP's author can be changed to AUTHOR; otherwise return an
- error code. */
-error_t
-diskfs_validate_author_change (struct node *np, uid_t author)
-{
- if (compat_mode == COMPAT_GNU)
- return 0;
- else
- /* For non-hurd filesystems, the author & owner are the same. */
- return (author == np->dn_stat.st_uid) ? 0 : EINVAL;
-}
-
-static void
-write_node (struct node *np)
-{
- struct stat *st = &np->dn_stat;
- struct dinode *di = dino (np->dn->number);
- error_t err;
-
- if (np->dn_stat_dirty)
- {
- assert (!diskfs_readonly);
-
- err = diskfs_catch_exception ();
- if (err)
- return;
-
- write_disk_entry (di->di_gen, st->st_gen);
-
- if (S_ISBLK (st->st_mode) || S_ISCHR (st->st_mode))
- write_disk_entry (di->di_rdev, st->st_rdev);
-
- /* We happen to know that the stat mode bits are the same
- as the ufs mode bits. */
-
- if (compat_mode == COMPAT_GNU)
- {
- mode_t mode = st->st_mode & ~S_ITRANS;
- write_disk_entry (di->di_model, mode & 0xffff);
- write_disk_entry (di->di_modeh, (mode >> 16) & 0xffff);
- }
- else
- {
- write_disk_entry (di->di_model, st->st_mode & 0xffff & ~S_ITRANS);
- di->di_modeh = 0;
- }
-
- if (compat_mode != COMPAT_BSD42)
- {
- write_disk_entry (di->di_uid, st->st_uid);
- write_disk_entry (di->di_gid, st->st_gid);
- }
-
- if (sblock->fs_inodefmt < FS_44INODEFMT)
- {
- write_disk_entry (di->di_ouid, st->st_uid & 0xffff);
- write_disk_entry (di->di_ogid, st->st_gid & 0xffff);
- }
- else if (compat_mode == COMPAT_GNU)
- write_disk_entry (di->di_author, st->st_author);
-
- write_disk_entry (di->di_nlink, st->st_nlink);
- write_disk_entry (di->di_size, st->st_size);
- write_disk_entry (di->di_atime.tv_sec, st->st_atim.tv_sec);
- write_disk_entry (di->di_atime.tv_nsec, st->st_atim.tv_nsec);
- write_disk_entry (di->di_mtime.tv_sec, st->st_mtim.tv_sec);
- write_disk_entry (di->di_mtime.tv_nsec, st->st_mtim.tv_nsec);
- write_disk_entry (di->di_ctime.tv_sec, st->st_ctim.tv_sec);
- write_disk_entry (di->di_ctime.tv_nsec, st->st_ctim.tv_nsec);
- write_disk_entry (di->di_blocks, st->st_blocks);
- write_disk_entry (di->di_flags, st->st_flags);
-
- diskfs_end_catch_exception ();
- np->dn_stat_dirty = 0;
- record_poke (di, sizeof (struct dinode));
- }
-}
-
-/* See if we should create a symlink by writing it directly into
- the block pointer array. Returning EINVAL tells diskfs to do it
- the usual way. */
-static error_t
-create_symlink_hook (struct node *np, const char *target)
-{
- int len = strlen (target);
- error_t err;
- struct dinode *di;
-
- if (!direct_symlink_extension)
- return EINVAL;
-
- assert (compat_mode != COMPAT_BSD42);
-
- if (len >= sblock->fs_maxsymlinklen)
- return EINVAL;
-
- err = diskfs_catch_exception ();
- if (err)
- return err;
-
- di = dino (np->dn->number);
- bcopy (target, di->di_shortlink, len);
- np->dn_stat.st_size = len;
- np->dn_set_ctime = 1;
- np->dn_set_mtime = 1;
- record_poke (di, sizeof (struct dinode));
-
- diskfs_end_catch_exception ();
- return 0;
-}
-error_t (*diskfs_create_symlink_hook)(struct node *, const char *)
- = create_symlink_hook;
-
-/* Check if this symlink is stored directly in the block pointer array.
- Returning EINVAL tells diskfs to do it the usual way. */
-static error_t
-read_symlink_hook (struct node *np,
- char *buf)
-{
- error_t err;
-
- if (!direct_symlink_extension
- || np->dn_stat.st_size >= sblock->fs_maxsymlinklen)
- return EINVAL;
-
- err = diskfs_catch_exception ();
- if (err)
- return err;
-
- bcopy ((dino (np->dn->number))->di_shortlink, buf, np->dn_stat.st_size);
-
- diskfs_set_node_atime (np);
-
- diskfs_end_catch_exception ();
- return 0;
-}
-error_t (*diskfs_read_symlink_hook)(struct node *, char *)
- = read_symlink_hook;
-
-error_t
-diskfs_node_iterate (error_t (*fun)(struct node *))
-{
- struct node *np;
- struct item {struct item *next; struct node *np;} *list = 0;
- struct item *i;
- error_t err;
- int n;
-
- /* Acquire a reference on all the nodes in the hash table
- and enter them into a list on the stack. */
- pthread_spin_lock (&diskfs_node_refcnt_lock);
- for (n = 0; n < INOHSZ; n++)
- for (np = nodehash[n]; np; np = np->dn->hnext)
- {
- np->references++;
- i = alloca (sizeof (struct item));
- i->next = list;
- i->np = np;
- list = i;
- }
- pthread_spin_unlock (&diskfs_node_refcnt_lock);
-
- err = 0;
- for (i = list; i; i = i->next)
- {
- if (!err)
- {
- pthread_mutex_lock (&i->np->lock);
- err = (*fun)(i->np);
- pthread_mutex_unlock (&i->np->lock);
- }
- diskfs_nrele (i->np);
- }
- return err;
-}
-
-/* Write all active disknodes into the dinode pager. */
-void
-write_all_disknodes ()
-{
- error_t
- helper (struct node *np)
- {
- diskfs_set_node_times (np);
- write_node (np);
- return 0;
- }
-
- diskfs_node_iterate (helper);
-}
-
-void
-diskfs_write_disknode (struct node *np, int wait)
-{
- write_node (np);
- if (wait)
- sync_dinode (np->dn->number, 1);
-}
-
-/* Implement the diskfs_set_statfs callback from the diskfs library;
- see <hurd/diskfs.h> for the interface description. */
-error_t
-diskfs_set_statfs (struct statfs *st)
-{
- st->f_type = FSTYPE_UFS;
- st->f_bsize = sblock->fs_fsize;
- st->f_blocks = sblock->fs_dsize;
- st->f_bfree = (sblock->fs_cstotal.cs_nbfree * sblock->fs_frag
- + sblock->fs_cstotal.cs_nffree);
- st->f_bavail = ((sblock->fs_dsize * (100 - sblock->fs_minfree) / 100)
- - (sblock->fs_dsize - st->f_bfree));
- if (st->f_bfree < ((sblock->fs_dsize * (100 - sblock->fs_minfree) / 100)))
- st->f_bavail = 0;
- st->f_files = sblock->fs_ncg * sblock->fs_ipg - 2; /* not 0 or 1 */
- st->f_ffree = sblock->fs_cstotal.cs_nifree;
- st->f_fsid = getpid ();
- st->f_namelen = 0;
- st->f_favail = st->f_ffree;
- st->f_frsize = sblock->fs_fsize;
- return 0;
-}
-
-/* Implement the diskfs_set_translator callback from the diskfs
- library; see <hurd/diskfs.h> for the interface description. */
-error_t
-diskfs_set_translator (struct node *np, const char *name, u_int namelen,
- struct protid *cred)
-{
- daddr_t blkno;
- error_t err;
- char buf[sblock->fs_bsize];
- struct dinode *di;
-
- if (compat_mode != COMPAT_GNU)
- return EOPNOTSUPP;
-
- if (namelen + sizeof (u_int) > sblock->fs_bsize)
- return ENAMETOOLONG;
-
- err = diskfs_catch_exception ();
- if (err)
- return err;
-
- di = dino (np->dn->number);
- blkno = read_disk_entry (di->di_trans);
-
- if (namelen && !blkno)
- {
- /* Allocate block for translator */
- err = ffs_alloc (np, 0, 0, sblock->fs_bsize, &blkno, cred);
- if (err)
- {
- diskfs_end_catch_exception ();
- return err;
- }
- write_disk_entry (di->di_trans, blkno);
- record_poke (di, sizeof (struct dinode));
- np->dn_set_ctime = 1;
- }
- else if (!namelen && blkno)
- {
- /* Clear block for translator going away. */
- ffs_blkfree (np, blkno, sblock->fs_bsize);
- di->di_trans = 0;
- record_poke (di, sizeof (struct dinode));
- np->dn_stat.st_blocks -= btodb (sblock->fs_bsize);
- np->dn_stat.st_mode &= ~S_IPTRANS;
- np->dn_set_ctime = 1;
- }
-
- if (namelen)
- {
- bcopy (&namelen, buf, sizeof (u_int));
- bcopy (name, buf + sizeof (u_int), namelen);
-
- bcopy (buf, disk_image + fsaddr (sblock, blkno), sblock->fs_bsize);
- sync_disk_blocks (blkno, sblock->fs_bsize, 1);
-
- np->dn_stat.st_mode |= S_IPTRANS;
- np->dn_set_ctime = 1;
- }
-
- diskfs_end_catch_exception ();
- return err;
-}
-
-/* Implement the diskfs_get_translator callback from the diskfs library.
- See <hurd/diskfs.h> for the interface description. */
-error_t
-diskfs_get_translator (struct node *np, char **namep, u_int *namelen)
-{
- error_t err;
- daddr_t blkno;
- u_int datalen;
- const void *transloc;
-
- err = diskfs_catch_exception ();
- if (err)
- return err;
-
- blkno = read_disk_entry ((dino (np->dn->number))->di_trans);
- assert (blkno);
- transloc = disk_image + fsaddr (sblock, blkno);
-
- datalen = *(u_int *)transloc;
- if (datalen > sblock->fs_bsize - sizeof (u_int))
- err = EFTYPE;
- else
- {
- *namep = malloc (datalen);
- if (*namep == NULL)
- err = ENOMEM;
- memcpy (*namep, transloc + sizeof (u_int), datalen);
- }
-
- diskfs_end_catch_exception ();
-
- *namelen = datalen;
- return 0;
-}
-
-/* Called when all hard ports have gone away. */
-void
-diskfs_shutdown_soft_ports ()
-{
- /* Should initiate termination of internally held pager ports
- (the only things that should be soft) XXX */
-}
-
-/* Return a description of the storage of the file. */
-/* In STORAGE_DATA are the following, in network byte order:
-
- Inode number (4 bytes)
- disk address of transator spec (4 bytes)
- disk address of inode structure (4 bytes)
- offset into inode block holding inode (4 bytes) */
-error_t
-diskfs_S_file_get_storage_info (struct protid *cred,
- mach_port_t **ports,
- mach_msg_type_name_t *ports_type,
- mach_msg_type_number_t *num_ports,
- int **ints, mach_msg_type_number_t *num_ints,
- off_t **offsets,
- mach_msg_type_number_t *num_offsets,
- char **data, mach_msg_type_number_t *data_len)
-{
- error_t err;
- struct node *np;
- struct store *file_store;
- struct store_run runs[NDADDR];
- size_t num_runs = 0;
-
- if (! cred)
- return EOPNOTSUPP;
-
- np = cred->po->np;
- pthread_mutex_lock (&np->lock);
-
- /* See if this file fits in the direct block pointers. If not, punt
- for now. (Reading indir blocks is a pain, and I'm postponing
- pain.) XXX */
- if (np->allocsize > NDADDR * sblock->fs_bsize)
- {
- pthread_mutex_unlock (&np->lock);
- return EINVAL;
- }
-
- err = diskfs_catch_exception ();
- if (! err)
- if (!direct_symlink_extension
- || np->dn_stat.st_size >= sblock->fs_maxsymlinklen
- || !S_ISLNK (np->dn_stat.st_mode))
- /* Copy the block pointers */
- {
- int i;
- struct store_run *run = runs;
- struct dinode *di = dino (np->dn->number);
-
- for (i = 0; i < NDADDR; i++)
- {
- store_offset_t start = fsbtodb (sblock, read_disk_entry (di->di_db[i]));
- store_offset_t length =
- (((i + 1) * sblock->fs_bsize > np->allocsize)
- ? np->allocsize - i * sblock->fs_bsize
- : sblock->fs_bsize);
- start <<= log2_dev_blocks_per_dev_bsize;
- length <<= log2_dev_blocks_per_dev_bsize;
- if (num_runs == 0 || run->start + run->length != start)
- *run++ = (struct store_run){ start, length };
- else
- run->length += length;
- }
- }
- diskfs_end_catch_exception ();
-
- pthread_mutex_unlock (&np->lock);
-
- if (! err)
- err = store_clone (store, &file_store);
- if (! err)
- {
- err = store_remap (file_store, runs, num_runs, &file_store);
- if (! err)
- err = store_return (file_store, ports, num_ports, ints, num_ints,
- offsets, num_offsets, data, data_len);
- store_free (file_store);
- }
- *ports_type = MACH_MSG_TYPE_COPY_SEND;
-
- return err;
-}
diff --git a/ufs/main.c b/ufs/main.c
deleted file mode 100644
index 9fc21f81..00000000
--- a/ufs/main.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- Copyright (C) 1994,95,96,97,98,99,2002 Free Software Foundation, Inc.
-
- 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, or (at
- your option) any later version.
-
- 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 "ufs.h"
-#include <stdarg.h>
-#include <stdio.h>
-#include <error.h>
-#include <device/device.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <argz.h>
-#include <argp.h>
-#include <hurd/store.h>
-
-struct node *diskfs_root_node;
-
-struct store *store = 0;
-struct store_parsed *store_parsed = 0;
-
-char *diskfs_disk_name = 0;
-
-/* Number of device blocks per DEV_BSIZE block. */
-unsigned log2_dev_blocks_per_dev_bsize = 0;
-
-/* Set diskfs_root_node to the root inode. */
-static void
-warp_root (void)
-{
- error_t err;
- err = diskfs_cached_lookup (2, &diskfs_root_node);
- assert (!err);
- pthread_mutex_unlock (&diskfs_root_node->lock);
-}
-
-/* XXX */
-pthread_mutex_t printf_lock = PTHREAD_MUTEX_INITIALIZER;
-int printf (const char *fmt, ...)
-{
- va_list arg;
- int done;
- va_start (arg, fmt);
- pthread_mutex_lock (&printf_lock);
- done = vprintf (fmt, arg);
- pthread_mutex_unlock (&printf_lock);
- va_end (arg);
- return done;
-}
-
-int diskfs_readonly;
-
-/* Ufs-specific options. XXX this should be moved so it can be done at
- runtime as well as startup. */
-static const struct argp_option
-options[] =
-{
- {"compat", 'C', "FMT", 0,
- "FMT may be GNU, 4.4, or 4.2, and determines which filesystem extensions"
- " are written onto the disk (default is GNU)"},
- {0}
-};
-
-/* Parse a ufs-specific command line option. */
-static error_t
-parse_opt (int key, char *arg, struct argp_state *state)
-{
- switch (key)
- {
- enum compat_mode mode;
-
- case 'C':
- if (strcasecmp (arg, "gnu") == 0)
- mode = COMPAT_GNU;
- else if (strcmp (arg, "4.4") == 0)
- mode = COMPAT_BSD44;
- else if (strcmp (arg, "4.2") == 0)
- {
- if (sblock
- && (sblock->fs_inodefmt == FS_44INODEFMT
- || direct_symlink_extension))
- {
- argp_failure (state, 0, 0,
- "4.2 compat mode requested on 4.4 fs");
- return EINVAL;
- }
- mode = COMPAT_BSD42;
- }
- else
- {
- argp_error (state, "%s: Unknown compatibility mode", arg);
- return EINVAL;
- }
-
- state->hook = (void *)mode; /* Save it for the end. */
- break;
-
- case ARGP_KEY_INIT:
- state->child_inputs[0] = state->input;
- state->hook = (void *)compat_mode; break;
- case ARGP_KEY_SUCCESS:
- compat_mode = (enum compat_mode)state->hook; break;
-
- default:
- return ARGP_ERR_UNKNOWN;
- }
- return 0;
-}
-
-/* Add our startup arguments to the standard diskfs set. */
-static const struct argp_child startup_children[] =
- {{&diskfs_store_startup_argp}, {0}};
-static struct argp startup_argp = {options, parse_opt, 0, 0, startup_children};
-
-/* Similarly at runtime. */
-static const struct argp_child runtime_children[] =
- {{&diskfs_std_runtime_argp}, {0}};
-static struct argp runtime_argp = {options, parse_opt, 0, 0, runtime_children};
-
-struct argp *diskfs_runtime_argp = (struct argp *)&runtime_argp;
-
-/* Override the standard diskfs routine so we can add our own output. */
-error_t
-diskfs_append_args (char **argz, size_t *argz_len)
-{
- error_t err;
-
- /* Get the standard things. */
- err = diskfs_append_std_options (argz, argz_len);
-
- if (!err && compat_mode != COMPAT_GNU)
- err = argz_add (argz, argz_len,
- ((compat_mode == COMPAT_BSD42)
- ? "--compat=4.2"
- : "--compat=4.4"));
-
- if (! err)
- err = store_parsed_append_args (store_parsed, argz, argz_len);
-
- return err;
-}
-
-int
-main (int argc, char **argv)
-{
- mach_port_t bootstrap;
-
- /* Initialize the diskfs library, parse arguments, and open the store.
- This starts the first diskfs thread for us. */
- store = diskfs_init_main (&startup_argp, argc, argv,
- &store_parsed, &bootstrap);
-
- if (store->block_size > DEV_BSIZE)
- error (4, 0, "%s: Bad device block size %zd (should be <= %d)",
- diskfs_disk_name, store->block_size, DEV_BSIZE);
- if (store->size < SBSIZE + SBOFF)
- error (5, 0, "%s: Disk too small (%Ld bytes)", diskfs_disk_name,
- store->size);
-
- log2_dev_blocks_per_dev_bsize = 0;
- while ((1 << log2_dev_blocks_per_dev_bsize) < DEV_BSIZE)
- log2_dev_blocks_per_dev_bsize++;
- log2_dev_blocks_per_dev_bsize -= store->log2_block_size;
-
- /* Map the entire disk. */
- create_disk_pager ();
-
- get_hypermetadata ();
-
- inode_init ();
-
- /* Find our root node. */
- warp_root ();
-
- /* Now that we are all set up to handle requests, and diskfs_root_node is
- set properly, it is safe to export our fsys control port to the
- outside world. */
- diskfs_startup_diskfs (bootstrap, 0);
-
- /* SET HOST NAME */
-
- /* And this thread is done with its work. */
- pthread_exit (NULL);
-
- return 0;
-}
-
-error_t
-diskfs_reload_global_state ()
-{
- flush_pokes ();
- pager_flush (diskfs_disk_pager, 1);
- get_hypermetadata ();
- return 0;
-}
diff --git a/ufs/pager.c b/ufs/pager.c
deleted file mode 100644
index 5d3e44ab..00000000
--- a/ufs/pager.c
+++ /dev/null
@@ -1,838 +0,0 @@
-/* Pager for ufs
- Copyright (C) 1994, 1995, 1996, 1997, 1999 Free Software Foundation
-
- 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, or (at
- your option) any later version.
-
- 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 "ufs.h"
-#include <strings.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <hurd/store.h>
-
-pthread_spinlock_t node2pagelock = PTHREAD_SPINLOCK_INITIALIZER;
-
-pthread_spinlock_t unlocked_pagein_lock = PTHREAD_SPINLOCK_INITIALIZER;
-
-#ifdef DONT_CACHE_MEMORY_OBJECTS
-#define MAY_CACHE 0
-#else
-#define MAY_CACHE 1
-#endif
-
-struct port_bucket *pager_bucket;
-
-/* Mapped image of the disk. */
-void *disk_image;
-
-/* Find the location on disk of page OFFSET in pager UPI. Return the
- disk address (in disk block) in *ADDR. If *NPLOCK is set on
- return, then release that mutex after I/O on the data has
- completed. Set DISKSIZE to be the amount of valid data on disk.
- (If this is an unallocated block, then set *ADDR to zero.)
- ISREAD is non-zero iff this is for a pagein. */
-static error_t
-find_address (struct user_pager_info *upi,
- vm_address_t offset,
- daddr_t *addr,
- int *disksize,
- pthread_rwlock_t **nplock,
- int isread)
-{
- error_t err;
- pthread_rwlock_t *lock;
-
- assert (upi->type == DISK || upi->type == FILE_DATA);
-
- if (upi->type == DISK)
- {
- *disksize = __vm_page_size;
- *addr = offset / DEV_BSIZE;
- *nplock = 0;
- return 0;
- }
- else
- {
- struct iblock_spec indirs[NIADDR + 1];
- struct node *np;
-
- np = upi->np;
-
- if (isread)
- {
- try_again:
-
- /* If we should allow an unlocked pagein, do so. (This
- still has a slight race; there could be a pageout in progress
- which is blocked on NP->np->allocptrlock itself. In that
- case the pagein that should proceed unimpeded is blocked
- in the pager library waiting for the pageout to complete.
- I think this is sufficiently rare to put it off for the time
- being.) */
-
- pthread_spin_lock (&unlocked_pagein_lock);
- if (offset >= upi->allow_unlocked_pagein
- && (offset + vm_page_size
- <= upi->allow_unlocked_pagein + upi->unlocked_pagein_length))
- {
- pthread_spin_unlock (&unlocked_pagein_lock);
- *nplock = 0;
- goto have_lock;
- }
- pthread_spin_unlock (&unlocked_pagein_lock);
-
- /* Block on the rwlock if necessary; but when we wake up,
- don't acquire it; check again from the top.
- This is mutated inline from rwlock.h. */
- lock = &np->dn->allocptrlock;
- /*
- TD - Why do we lock first?
- To prevent this nigh-impossible scenario:
- 1) trylock - writer has lock
- 2) switch back to writer before we lock waitlock
- 3) writer finishes: releases lock and broadcasts
- 4) we wait for a condition that will never get broadcast
- With this, either we get the lock, or we get the signal.
- */
- pthread_mutex_lock (&np->dn->waitlock);
- if (pthread_rwlock_tryrdlock (lock))
- {
- /*
- TD - we now don't block on the rwlock. Instead, we wait on a
- condition that will be signalled when the lock is unlocked,
- or when it is safe not to lock the page. We don't spin on an
- invariant, as spurius wakeups can do no harm.
- */
- pthread_cond_wait (&np->dn->waitcond, &np->dn->waitlock);
- pthread_mutex_unlock (&np->dn->waitlock);
- goto try_again;
- }
- pthread_mutex_unlock (&np->dn->waitlock);
- *nplock = lock;
- }
- else
- {
- pthread_rwlock_rdlock (&np->dn->allocptrlock);
- *nplock = &np->dn->allocptrlock;
- }
-
- have_lock:
-
- if (offset >= np->allocsize)
- {
- if (*nplock)
- pthread_rwlock_unlock (*nplock);
- if (isread)
- return EIO;
- else
- {
- *addr = 0;
- *disksize = 0;
- return 0;
- }
- }
-
- if (offset + __vm_page_size > np->allocsize)
- *disksize = np->allocsize - offset;
- else
- *disksize = __vm_page_size;
-
- err = fetch_indir_spec (np, lblkno (sblock, offset), indirs);
- if (err && *nplock)
- pthread_rwlock_unlock (*nplock);
- else
- {
- if (indirs[0].bno)
- *addr = (fsbtodb (sblock, indirs[0].bno)
- + blkoff (sblock, offset) / DEV_BSIZE);
- else
- *addr = 0;
- }
-
- return err;
- }
-}
-
-
-/* Implement the pager_read_page callback from the pager library. See
- <hurd/pager.h> for the interface description. */
-error_t
-pager_read_page (struct user_pager_info *pager,
- vm_offset_t page,
- vm_address_t *buf,
- int *writelock)
-{
- error_t err;
- pthread_rwlock_t *nplock;
- daddr_t addr;
- int disksize;
-
- err = find_address (pager, page, &addr, &disksize, &nplock, 1);
- if (err)
- return err;
-
- if (addr)
- {
- size_t read = 0;
- err = store_read (store, addr << log2_dev_blocks_per_dev_bsize,
- disksize, (void **)buf, &read);
- if (read != disksize)
- err = EIO;
- if (!err && disksize != __vm_page_size)
- bzero ((void *)(*buf + disksize), __vm_page_size - disksize);
- *writelock = 0;
- }
- else
- {
-#if 0
- printf ("Write-locked pagein Object %#x\tOffset %#x\n", pager, page);
- fflush (stdout);
-#endif
- *buf = (vm_address_t) mmap (0, vm_page_size, PROT_READ|PROT_WRITE,
- MAP_ANON, 0, 0);
- *writelock = 1;
- }
-
- if (nplock)
- pthread_rwlock_unlock (nplock);
-
- return err;
-}
-
-/* Implement the pager_write_page callback from the pager library. See
- <hurd/pager.h> for the interface description. */
-error_t
-pager_write_page (struct user_pager_info *pager,
- vm_offset_t page,
- vm_address_t buf)
-{
- daddr_t addr;
- int disksize;
- pthread_rwlock_t *nplock;
- error_t err;
-
- err = find_address (pager, page, &addr, &disksize, &nplock, 0);
- if (err)
- return err;
-
- if (addr)
- {
- size_t wrote;
- err = store_write (store, addr << log2_dev_blocks_per_dev_bsize,
- (void *)buf, disksize, &wrote);
- if (wrote != disksize)
- err = EIO;
- }
- else
- err = 0;
-
- if (nplock)
- pthread_rwlock_unlock (nplock);
-
- return err;
-}
-
-/* Implement the pager_unlock_page callback from the pager library. See
- <hurd/pager.h> for the interface description. */
-error_t
-pager_unlock_page (struct user_pager_info *pager,
- vm_offset_t address)
-{
- struct node *np;
- error_t err;
- struct iblock_spec indirs[NIADDR + 1];
- daddr_t bno;
- struct disknode *dn;
- struct dinode *di;
-
- /* Zero an sblock->fs_bsize piece of disk starting at BNO,
- synchronously. We do this on newly allocated indirect
- blocks before setting the pointer to them to ensure that an
- indirect block absolutely never points to garbage. */
- void zero_disk_block (int bno)
- {
- bzero (indir_block (bno), sblock->fs_bsize);
- sync_disk_blocks (bno, sblock->fs_bsize, 1);
- };
-
- /* Problem--where to get cred values for allocation here? */
-
-#if 0
- printf ("Unlock page request, Object %#x\tOffset %#x...", pager, address);
- fflush (stdout);
-#endif
-
- if (pager->type == DISK)
- return 0;
-
- np = pager->np;
- dn = np->dn;
- di = dino (dn->number);
-
- pthread_rwlock_wrlock (&dn->allocptrlock);
-
- /* If this is the last block, we don't let it get unlocked. */
- if (address + __vm_page_size
- > blkroundup (sblock, np->allocsize) - sblock->fs_bsize)
- {
- printf ("attempt to unlock at last block denied\n");
- fflush (stdout);
- pthread_rwlock_unlock (&dn->allocptrlock);
- /* Wake up any remaining sleeping readers. Wow, so much work.... */
- pthread_mutex_lock (&dn->waitlock);
- pthread_cond_broadcast (&dn->waitcond);
- pthread_mutex_unlock (&dn->waitlock);
- return EIO;
- }
-
- err = fetch_indir_spec (np, lblkno (sblock, address), indirs);
- if (err)
- {
- pthread_rwlock_unlock (&dn->allocptrlock);
- pthread_mutex_lock (&dn->waitlock);
- pthread_cond_broadcast (&dn->waitcond);
- pthread_mutex_unlock (&dn->waitlock);
- return EIO;
- }
-
- err = diskfs_catch_exception ();
- if (err)
- {
- pthread_rwlock_unlock (&dn->allocptrlock);
- pthread_mutex_lock (&dn->waitlock);
- pthread_cond_broadcast (&dn->waitcond);
- pthread_mutex_unlock (&dn->waitlock);
- return EIO;
- }
-
- /* See if we need a triple indirect block; fail if we do. */
- assert (indirs[0].offset == -1
- || indirs[1].offset == -1
- || indirs[2].offset == -1);
-
- /* Check to see if this block is allocated. */
- if (indirs[0].bno == 0)
- {
- size_t wrote;
-
- if (indirs[0].offset == -1)
- {
- err = ffs_alloc (np, lblkno (sblock, address),
- ffs_blkpref (np, lblkno (sblock, address),
- lblkno (sblock, address), di->di_db),
- sblock->fs_bsize, &bno, 0);
- if (err)
- goto out;
-
- assert (lblkno (sblock, address) < NDADDR);
- err = store_write (store,
- fsbtodb (sblock, bno)
- << log2_dev_blocks_per_dev_bsize,
- zeroblock, sblock->fs_bsize, &wrote);
- if (!err && wrote != sblock->fs_bsize)
- err = EIO;
- if (err)
- goto out;
-
- indirs[0].bno = bno;
- write_disk_entry (di->di_db[lblkno (sblock, address)], bno);
- record_poke (di, sizeof (struct dinode));
- }
- else
- {
- daddr_t *siblock;
-
- /* We need to set siblock to the single indirect block
- array; see if the single indirect block is allocated. */
- if (indirs[1].bno == 0)
- {
- if (indirs[1].offset == -1)
- {
- err = ffs_alloc (np, lblkno (sblock, address),
- ffs_blkpref (np, lblkno (sblock, address),
- INDIR_SINGLE, di->di_ib),
- sblock->fs_bsize, &bno, 0);
- if (err)
- goto out;
- zero_disk_block (bno);
- indirs[1].bno = bno;
- write_disk_entry (di->di_ib[INDIR_SINGLE], bno);
- record_poke (di, sizeof (struct dinode));
- }
- else
- {
- daddr_t *diblock;
-
- /* We need to set diblock to the double indirect
- block array; see if the double indirect block is
- allocated. */
- if (indirs[2].bno == 0)
- {
- /* This assert because triple indirection is
- not supported. */
- assert (indirs[2].offset == -1);
-
- err = ffs_alloc (np, lblkno (sblock, address),
- ffs_blkpref (np, lblkno (sblock,
- address),
- INDIR_DOUBLE, di->di_ib),
- sblock->fs_bsize, &bno, 0);
- if (err)
- goto out;
- zero_disk_block (bno);
- indirs[2].bno = bno;
- write_disk_entry (di->di_ib[INDIR_DOUBLE], bno);
- record_poke (di, sizeof (struct dinode));
- }
-
- diblock = indir_block (indirs[2].bno);
- mark_indir_dirty (np, indirs[2].bno);
-
- /* Now we can allocate the single indirect block */
-
- err = ffs_alloc (np, lblkno (sblock, address),
- ffs_blkpref (np, lblkno (sblock, address),
- indirs[1].offset, diblock),
- sblock->fs_bsize, &bno, 0);
- if (err)
- goto out;
- zero_disk_block (bno);
- indirs[1].bno = bno;
- write_disk_entry (diblock[indirs[1].offset], bno);
- record_poke (diblock, sblock->fs_bsize);
- }
- }
-
- siblock = indir_block (indirs[1].bno);
- mark_indir_dirty (np, indirs[1].bno);
-
- /* Now we can allocate the data block. */
-
- err = ffs_alloc (np, lblkno (sblock, address),
- ffs_blkpref (np, lblkno (sblock, address),
- indirs[0].offset, siblock),
- sblock->fs_bsize, &bno, 0);
- if (err)
- goto out;
-
- err = store_write (store,
- fsbtodb (sblock, bno)
- << log2_dev_blocks_per_dev_bsize,
- zeroblock, sblock->fs_bsize, &wrote);
- if (!err && wrote != sblock->fs_bsize)
- err = EIO;
- if (err)
- goto out;
-
- indirs[0].bno = bno;
- write_disk_entry (siblock[indirs[0].offset], bno);
- record_poke (siblock, sblock->fs_bsize);
- }
- }
-
- out:
- diskfs_end_catch_exception ();
- pthread_rwlock_unlock (&dn->allocptrlock);
- pthread_mutex_lock (&dn->waitlock);
- pthread_cond_broadcast (&dn->waitcond);
- pthread_mutex_unlock (&dn->waitlock);
- return err;
-}
-
-void
-pager_notify_evict (struct user_pager_info *pager,
- vm_offset_t page)
-{
- assert (!"unrequested notification on eviction");
-}
-
-/* Implement the pager_report_extent callback from the pager library. See
- <hurd/pager.h> for the interface description. */
-inline error_t
-pager_report_extent (struct user_pager_info *pager,
- vm_address_t *offset,
- vm_size_t *size)
-{
- assert (pager->type == DISK || pager->type == FILE_DATA);
-
- *offset = 0;
-
- if (pager->type == DISK)
- *size = store->size;
- else
- *size = pager->np->allocsize;
-
- return 0;
-}
-
-/* Implement the pager_clear_user_data callback from the pager library.
- See <hurd/pager.h> for the interface description. */
-void
-pager_clear_user_data (struct user_pager_info *upi)
-{
- /* XXX Do the right thing for the disk pager here too. */
- if (upi->type == FILE_DATA)
- {
- pthread_spin_lock (&node2pagelock);
- if (upi->np->dn->fileinfo == upi)
- upi->np->dn->fileinfo = 0;
- pthread_spin_unlock (&node2pagelock);
- diskfs_nrele_light (upi->np);
- }
- free (upi);
-}
-
-void
-pager_dropweak (struct user_pager_info *upi __attribute__ ((unused)))
-{
-}
-
-
-
-/* Create the DISK pager. */
-void
-create_disk_pager (void)
-{
- struct user_pager_info *upi = malloc (sizeof (struct user_pager_info));
-
- upi->type = DISK;
- upi->np = 0;
- pager_bucket = ports_create_bucket ();
- diskfs_start_disk_pager (upi, pager_bucket, MAY_CACHE, 0, store->size,
- &disk_image);
- upi->p = diskfs_disk_pager;
-}
-
-/* This syncs a single file (NP) to disk. Wait for all I/O to complete
- if WAIT is set. NP->lock must be held. */
-void
-diskfs_file_update (struct node *np,
- int wait)
-{
- struct dirty_indir *d, *tmp;
- struct user_pager_info *upi;
-
- pthread_spin_lock (&node2pagelock);
- upi = np->dn->fileinfo;
- if (upi)
- ports_port_ref (upi->p);
- pthread_spin_unlock (&node2pagelock);
-
- if (upi)
- {
- pager_sync (upi->p, wait);
- ports_port_deref (upi->p);
- }
-
- for (d = np->dn->dirty; d; d = tmp)
- {
- sync_disk_blocks (d->bno, sblock->fs_bsize, wait);
- tmp = d->next;
- free (d);
- }
- np->dn->dirty = 0;
-
- diskfs_node_update (np, wait);
-}
-
-/* Invalidate any pager data associated with NODE. */
-void
-flush_node_pager (struct node *node)
-{
- struct user_pager_info *upi;
- struct disknode *dn = node->dn;
- struct dirty_indir *dirty = dn->dirty;
-
- pthread_spin_lock (&node2pagelock);
- upi = dn->fileinfo;
- if (upi)
- ports_port_ref (upi->p);
- pthread_spin_unlock (&node2pagelock);
-
- if (upi)
- {
- pager_flush (upi->p, 1);
- ports_port_deref (upi->p);
- }
-
- dn->dirty = 0;
-
- while (dirty)
- {
- struct dirty_indir *next = dirty->next;
- free (dirty);
- dirty = next;
- }
-}
-
-/* Call this to create a FILE_DATA pager and return a send right.
- NP must be locked. PROT is the max protection desired. */
-mach_port_t
-diskfs_get_filemap (struct node *np, vm_prot_t prot)
-{
- struct user_pager_info *upi;
- mach_port_t right;
-
- assert (S_ISDIR (np->dn_stat.st_mode)
- || S_ISREG (np->dn_stat.st_mode)
- || (S_ISLNK (np->dn_stat.st_mode)
- && (!direct_symlink_extension
- || np->dn_stat.st_size >= sblock->fs_maxsymlinklen)));
-
- pthread_spin_lock (&node2pagelock);
- do
- if (!np->dn->fileinfo)
- {
- upi = malloc (sizeof (struct user_pager_info));
- upi->type = FILE_DATA;
- upi->np = np;
- upi->max_prot = prot;
- upi->allow_unlocked_pagein = 0;
- upi->unlocked_pagein_length = 0;
- diskfs_nref_light (np);
- upi->p = pager_create (upi, pager_bucket,
- MAY_CACHE, MEMORY_OBJECT_COPY_DELAY, 0);
- if (upi->p == 0)
- {
- diskfs_nrele_light (np);
- free (upi);
- pthread_spin_unlock (&node2pagelock);
- return MACH_PORT_NULL;
- }
- np->dn->fileinfo = upi;
- right = pager_get_port (np->dn->fileinfo->p);
- ports_port_deref (np->dn->fileinfo->p);
- }
- else
- {
- np->dn->fileinfo->max_prot |= prot;
-
- /* Because NP->dn->fileinfo->p is not a real reference,
- this might be nearly deallocated. If that's so, then
- the port right will be null. In that case, clear here
- and loop. The deallocation will complete separately. */
- right = pager_get_port (np->dn->fileinfo->p);
- if (right == MACH_PORT_NULL)
- np->dn->fileinfo = 0;
- }
- while (right == MACH_PORT_NULL);
-
- pthread_spin_unlock (&node2pagelock);
-
- mach_port_insert_right (mach_task_self (), right, right,
- MACH_MSG_TYPE_MAKE_SEND);
-
- return right;
-}
-
-/* Call this when we should turn off caching so that unused memory object
- ports get freed. */
-void
-drop_pager_softrefs (struct node *np)
-{
- struct user_pager_info *upi;
-
- pthread_spin_lock (&node2pagelock);
- upi = np->dn->fileinfo;
- if (upi)
- ports_port_ref (upi->p);
- pthread_spin_unlock (&node2pagelock);
-
- if (MAY_CACHE && upi)
- pager_change_attributes (upi->p, 0, MEMORY_OBJECT_COPY_DELAY, 0);
- if (upi)
- ports_port_deref (upi->p);
-}
-
-/* Call this when we should turn on caching because it's no longer
- important for unused memory object ports to get freed. */
-void
-allow_pager_softrefs (struct node *np)
-{
- struct user_pager_info *upi;
-
- pthread_spin_lock (&node2pagelock);
- upi = np->dn->fileinfo;
- if (upi)
- ports_port_ref (upi->p);
- pthread_spin_unlock (&node2pagelock);
-
- if (MAY_CACHE && upi)
- pager_change_attributes (upi->p, 1, MEMORY_OBJECT_COPY_DELAY, 0);
- if (upi)
- ports_port_deref (upi->p);
-}
-
-static void
-block_caching ()
-{
- error_t block_cache (void *arg)
- {
- struct pager *p = arg;
-
- pager_change_attributes (p, 0, MEMORY_OBJECT_COPY_DELAY, 1);
- return 0;
- }
-
- /* Loop through the pagers and turn off caching one by one,
- synchronously. That should cause termination of each pager. */
- ports_bucket_iterate (pager_bucket, block_cache);
-}
-
-static void
-enable_caching ()
-{
- error_t enable_cache (void *arg)
- {
- struct pager *p = arg;
- struct user_pager_info *upi = pager_get_upi (p);
-
- pager_change_attributes (p, 1, MEMORY_OBJECT_COPY_DELAY, 0);
-
- /* It's possible that we didn't have caching on before, because
- the user here is the only reference to the underlying node
- (actually, that's quite likely inside this particular
- routine), and if that node has no links. So dinkle the node
- ref counting scheme here, which will cause caching to be
- turned off, if that's really necessary. */
- if (upi->type == FILE_DATA)
- {
- diskfs_nref (upi->np);
- diskfs_nrele (upi->np);
- }
-
- return 0;
- }
-
- ports_bucket_iterate (pager_bucket, enable_cache);
-}
-
-/* Tell diskfs if there are pagers exported, and if none, then
- prevent any new ones from showing up. */
-int
-diskfs_pager_users ()
-{
- int npagers = ports_count_bucket (pager_bucket);
-
- if (npagers <= 1)
- return 0;
-
- if (MAY_CACHE)
- {
- block_caching ();
-
- /* Give it a second; the kernel doesn't actually shutdown
- immediately. XXX */
- sleep (1);
-
- npagers = ports_count_bucket (pager_bucket);
- if (npagers <= 1)
- return 0;
-
- /* Darn, there are actual honest users. Turn caching back on,
- and return failure. */
- enable_caching ();
- }
-
- ports_enable_bucket (pager_bucket);
-
- return 1;
-}
-
-/* Return the bitwise or of the maximum prot parameter (the second arg to
- diskfs_get_filemap) for all active user pagers. */
-vm_prot_t
-diskfs_max_user_pager_prot ()
-{
- vm_prot_t max_prot = 0;
- int npagers = ports_count_bucket (pager_bucket);
-
- if (npagers > 1)
- /* More than just the disk pager. */
- {
- error_t add_pager_max_prot (void *v_p)
- {
- struct pager *p = v_p;
- struct user_pager_info *upi = pager_get_upi (p);
- if (upi->type == FILE_DATA)
- max_prot |= upi->max_prot;
- /* Stop iterating if MAX_PROT is as filled as it's going to get. */
- return max_prot == (VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
- }
-
- block_caching (); /* Make any silly pagers go away. */
-
- /* Give it a second; the kernel doesn't actually shutdown
- immediately. XXX */
- sleep (1);
-
- ports_bucket_iterate (pager_bucket, add_pager_max_prot);
-
- enable_caching ();
- }
-
- ports_enable_bucket (pager_bucket);
-
- return max_prot;
-}
-
-/* Call this to find out the struct pager * corresponding to the
- FILE_DATA pager of inode IP. This should be used *only* as a subsequent
- argument to register_memory_fault_area, and will be deleted when
- the kernel interface is fixed. NP must be locked. */
-struct pager *
-diskfs_get_filemap_pager_struct (struct node *np)
-{
- /* This is safe because fileinfo can't be cleared; there must be
- an active mapping for this to be called. */
- return np->dn->fileinfo->p;
-}
-
-/* Shutdown all the pagers. */
-void
-diskfs_shutdown_pager ()
-{
- error_t shutdown_one (void *arg)
- {
- struct pager *p = arg;
- /* Don't ever shut down the disk pager. */
- if (p != diskfs_disk_pager)
- pager_shutdown (p);
- return 0;
- }
-
- copy_sblock ();
- write_all_disknodes ();
- ports_bucket_iterate (pager_bucket, shutdown_one);
- sync_disk (1);
-}
-
-/* Sync all the pagers. */
-void
-diskfs_sync_everything (int wait)
-{
- error_t sync_one (void *arg)
- {
- struct pager *p = arg;
- /* Make sure the disk pager is done last. */
- if (p != diskfs_disk_pager)
- pager_sync (p, wait);
- return 0;
- }
-
- copy_sblock ();
- write_all_disknodes ();
- ports_bucket_iterate (pager_bucket, sync_one);
- sync_disk (wait);
-}
diff --git a/ufs/pokeloc.c b/ufs/pokeloc.c
deleted file mode 100644
index e1d5ffcb..00000000
--- a/ufs/pokeloc.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Remember where we've written the disk to speed up sync
- Copyright (C) 1994, 1996 Free Software Foundation, Inc.
- Written by Michael I. Bushnell.
-
- This file is part of the GNU Hurd.
-
- The GNU Hurd 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, or (at
- your option) any later version.
-
- The GNU Hurd 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 "ufs.h"
-
-struct pokeloc
-{
- vm_offset_t offset;
- vm_size_t length;
- struct pokeloc *next;
-};
-
-struct pokeloc *pokelist;
-pthread_spinlock_t pokelistlock = PTHREAD_SPINLOCK_INITIALIZER;
-
-/* Remember that data here on the disk has been modified. */
-void
-record_poke (void *loc, vm_size_t length)
-{
- struct pokeloc *pl = malloc (sizeof (struct pokeloc));
- vm_offset_t offset;
-
- offset = loc - disk_image;
- pl->offset = trunc_page (offset);
- pl->length = round_page (offset + length) - pl->offset;
-
- pthread_spin_lock (&pokelistlock);
- pl->next = pokelist;
- pokelist = pl;
- pthread_spin_unlock (&pokelistlock);
-}
-
-/* Get rid of any outstanding pokes. */
-void
-flush_pokes ()
-{
- struct pokeloc *pl;
-
- pthread_spin_lock (&pokelistlock);
- pl = pokelist;
- pokelist = 0;
- pthread_spin_unlock (&pokelistlock);
-
- while (pl)
- {
- struct pokeloc *next = pl->next;
- free (pl);
- pl = next;
- }
-}
-
-/* Sync all the modified pieces of disk */
-void
-sync_disk (int wait)
-{
- struct pokeloc *pl, *tmp;
-
- pthread_spin_lock (&pokelistlock);
- for (pl = pokelist; pl; pl = tmp)
- {
- pager_sync_some (diskfs_disk_pager, pl->offset, pl->length, wait);
- tmp = pl->next;
- free (pl);
- }
- pokelist = 0;
- pthread_spin_unlock (&pokelistlock);
-}
-
diff --git a/ufs/sizes.c b/ufs/sizes.c
deleted file mode 100644
index e3d51b7d..00000000
--- a/ufs/sizes.c
+++ /dev/null
@@ -1,736 +0,0 @@
-/* File growth and truncation
- Copyright (C) 1993, 1994, 1995, 1996, 1997, 1999 Free Software Foundation
-
-This file is part of the GNU Hurd.
-
-The GNU Hurd 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, or (at your option)
-any later version.
-
-The GNU Hurd 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 the GNU Hurd; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* Written by Michael I. Bushnell. */
-
-#include "ufs.h"
-#include <string.h>
-
-#ifdef DONT_CACHE_MEMORY_OBJECTS
-#define MAY_CACHE 0
-#else
-#define MAY_CACHE 1
-#endif
-
-static int indir_release (struct node *np, daddr_t bno, int level);
-static void poke_pages (memory_object_t, vm_offset_t, vm_offset_t);
-
-/* Implement the diskfs_truncate callback; sse <hurd/diskfs.h> for the
- interface description. */
-error_t
-diskfs_truncate (struct node *np,
- off_t length)
-{
- int offset;
- struct dinode *di = dino (np->dn->number);
- volatile int blocksfreed = 0;
- error_t err;
- int i;
- struct iblock_spec indirs[NIADDR + 1];
- volatile daddr_t lbn;
- struct user_pager_info *upi;
-
- if (length >= np->dn_stat.st_size)
- return 0;
-
- diskfs_check_readonly ();
- assert (!diskfs_readonly);
-
- /* First check to see if this is a kludged symlink; if so
- this is special. */
- if (direct_symlink_extension && S_ISLNK (np->dn_stat.st_mode)
- && np->dn_stat.st_size < sblock->fs_maxsymlinklen)
- {
- error_t err;
-
- err = diskfs_catch_exception ();
- if (err)
- return err;
- bzero ((char *)di->di_shortlink + length, np->dn_stat.st_size - length);
- record_poke (di, sizeof (struct dinode));
- diskfs_end_catch_exception ();
- np->dn_stat.st_size = length;
- np->dn_set_ctime = np->dn_set_mtime = 1;
- diskfs_node_update (np, 1);
- return 0;
- }
-
- /* If the file is not being trucated to a block boundary,
- the zero the partial bit in the new last block. */
- offset = blkoff (sblock, length);
- if (offset)
- {
- int bsize; /* size of new last block */
- int savesize = np->allocsize;
-
- np->allocsize = length; /* temporary */
- bsize = blksize (sblock, np, lblkno (sblock, length));
- np->allocsize = savesize;
- diskfs_node_rdwr (np, zeroblock, length, bsize - offset, 1, 0, 0);
- diskfs_file_update (np, 1);
- }
-
- /* Now flush all the data past the new size from the kernel.
- Also force any delayed copies of this data to take place
- immediately. (We are implicitly changing the data to zeros
- and doing it without the kernel's immediate knowledge;
- accordingl we must help out the kernel thusly.) */
- pthread_spin_lock (&node2pagelock);
- upi = np->dn->fileinfo;
- if (upi)
- ports_port_ref (upi->p);
- pthread_spin_unlock (&node2pagelock);
-
- if (upi)
- {
- mach_port_t obj;
-
- pager_change_attributes (upi->p, MAY_CACHE,
- MEMORY_OBJECT_COPY_NONE, 1);
- obj = diskfs_get_filemap (np, VM_PROT_READ | VM_PROT_WRITE);
- if (obj != MACH_PORT_NULL)
- {
- /* XXX should cope with errors from diskfs_get_filemap */
- poke_pages (obj, round_page (length), round_page (np->allocsize));
- mach_port_deallocate (mach_task_self (), obj);
- pager_flush_some (upi->p, round_page (length),
- np->allocsize - length, 1);
- }
- ports_port_deref (upi->p);
- }
-
- pthread_rwlock_wrlock (&np->dn->allocptrlock);
-
- /* Update the size on disk; fsck will finish freeing blocks if necessary
- should we crash. */
- np->dn_stat.st_size = length;
- np->dn_set_mtime = 1;
- np->dn_set_ctime = 1;
- diskfs_node_update (np, 1);
-
- /* Find out the location information for the last block to
- be retained */
- lbn = lblkno (sblock, length - 1);
- err = fetch_indir_spec (np, lbn, indirs);
- /* err XXX */
-
- /* We don't support triple indirs */
- assert (indirs[3].offset == -2);
-
- err = diskfs_catch_exception ();
- /* err XXX */
-
- /* BSD carefully finds out how far to clear; it's vastly simpler
- to just clear everything after the new last block. */
-
- /* Free direct blocks */
- if (indirs[0].offset < 0)
- {
- /* ...mapped from the inode. */
- for (i = lbn + 1; i < NDADDR; i++)
- if (di->di_db[i])
- {
- long bsize = blksize (sblock, np, i);
- ffs_blkfree (np, read_disk_entry (di->di_db[i]), bsize);
- di->di_db[i] = 0;
- blocksfreed += btodb (bsize);
- }
- }
- else
- {
- /* ... or mapped from sindir */
- if (indirs[1].bno)
- {
- daddr_t *sindir = indir_block (indirs[1].bno);
- for (i = indirs[0].offset + 1; i < NINDIR (sblock); i++)
- if (sindir[i])
- {
- ffs_blkfree (np, read_disk_entry (sindir[i]),
- sblock->fs_bsize);
- sindir[i] = 0;
- blocksfreed += btodb (sblock->fs_bsize);
- }
- record_poke (sindir, sblock->fs_bsize);
- }
- }
-
- /* Free single indirect blocks */
- if (indirs[1].offset < 0)
- {
- /* ...mapped from the inode */
- if (di->di_ib[INDIR_SINGLE] && indirs[1].offset == -2)
- {
- blocksfreed += indir_release (np,
- read_disk_entry (di->di_ib
- [INDIR_SINGLE]),
- INDIR_SINGLE);
- di->di_ib[INDIR_SINGLE] = 0;
- }
- }
- else
- {
- /* ...or mapped from dindir */
- if (indirs[2].bno)
- {
- daddr_t *dindir = indir_block (indirs[2].bno);
- for (i = indirs[1].offset + 1; i < NINDIR (sblock); i++)
- if (dindir[i])
- {
- blocksfreed += indir_release (np,
- read_disk_entry (dindir[i]),
- INDIR_SINGLE);
- dindir[i] = 0;
- }
- record_poke (dindir, sblock->fs_bsize);
- }
- }
-
- /* Free double indirect block */
- assert (indirs[2].offset < 0); /* which must be mapped from the inode */
- if (indirs[2].offset == -2)
- {
- if (di->di_ib[INDIR_DOUBLE])
- {
- blocksfreed += indir_release (np,
- read_disk_entry (di->di_ib
- [INDIR_DOUBLE]),
- INDIR_DOUBLE);
- di->di_ib[INDIR_DOUBLE] = 0;
- }
- }
-
- /* Finally, check to see if the new last direct block is
- changing size; if so release any frags necessary. */
- if (lbn >= 0 && lbn < NDADDR && di->di_db[lbn])
- {
- long oldspace, newspace;
- daddr_t bn;
-
- bn = read_disk_entry (di->di_db[lbn]);
- oldspace = blksize (sblock, np, lbn);
- np->allocsize = fragroundup (sblock, length);
- newspace = blksize (sblock, np, lbn);
-
- assert (newspace);
-
- if (oldspace - newspace)
- {
- bn += numfrags (sblock, newspace);
- ffs_blkfree (np, bn, oldspace - newspace);
- blocksfreed += btodb (oldspace - newspace);
- }
- }
- else
- {
- if (lbn > NDADDR)
- np->allocsize = blkroundup (sblock, length);
- else
- np->allocsize = fragroundup (sblock, length);
- }
-
- record_poke (di, sizeof (struct dinode));
-
- np->dn_stat.st_blocks -= blocksfreed;
- np->dn_set_ctime = 1;
- diskfs_node_update (np, 1);
-
- pthread_rwlock_unlock (&np->dn->allocptrlock);
- /* Wake up any remaining sleeping readers.
- This sequence of three calls is now necessary whenever we acquire a write
- lock on allocptrlock. If we do not, we may leak some readers. */
- pthread_mutex_lock (&np->dn->waitlock);
- pthread_cond_broadcast (&np->dn->waitcond);
- pthread_mutex_unlock (&np->dn->waitlock);
-
- /* At this point the last block (as defined by np->allocsize)
- might not be allocated. We need to allocate it to maintain
- the rule that the last block of a file is always allocated. */
-
- if (np->allocsize && indirs[0].bno == 0)
- {
- /* The strategy is to reduce LBN until we get one that's allocated;
- then reduce allocsize accordingly, then call diskfs_grow. */
-
- do
- err = fetch_indir_spec (np, --lbn, indirs);
- /* err XXX */
- while (indirs[0].bno == 0 && lbn >= 0);
-
- assert ((lbn + 1) * sblock->fs_bsize < np->allocsize);
- np->allocsize = (lbn + 1) * sblock->fs_bsize;
-
- diskfs_grow (np, length, 0);
- }
-
- diskfs_end_catch_exception ();
-
- /* Now we can permit delayed copies again. */
- pthread_spin_lock (&node2pagelock);
- upi = np->dn->fileinfo;
- if (upi)
- ports_port_ref (upi->p);
- pthread_spin_unlock (&node2pagelock);
- if (upi)
- {
- pager_change_attributes (upi->p, MAY_CACHE,
- MEMORY_OBJECT_COPY_DELAY, 0);
- ports_port_deref (upi->p);
- }
-
- return err;
-}
-
-/* Free indirect block BNO of level LEVEL; recursing if necessary
- to free other indirect blocks. Return the number of disk
- blocks freed. */
-static int
-indir_release (struct node *np, daddr_t bno, int level)
-{
- int count = 0;
- daddr_t *addrs;
- int i;
- struct dirty_indir *d, *prev, *next;
-
- assert (bno);
-
- addrs = indir_block (bno);
- for (i = 0; i < NINDIR (sblock); i++)
- if (addrs[i])
- {
- if (level == INDIR_SINGLE)
- {
- ffs_blkfree (np, read_disk_entry (addrs[i]), sblock->fs_bsize);
- count += btodb (sblock->fs_bsize);
- }
- else
- count += indir_release (np, read_disk_entry (addrs[i]), level - 1);
- }
-
- /* Subtlety: this block is no longer necessary; the information
- the kernel has cached corresponding to ADDRS is now unimportant.
- Consider that if this block is allocated to a file, it will then
- be double cached and the kernel might decide to write out
- the disk_image version of the block. So we have to flush
- the block from the kernel's memory, making sure we do it
- synchronously--and BEFORE we attach it to the free list
- with ffs_blkfree. */
- pager_flush_some (diskfs_disk_pager, fsaddr (sblock, bno), sblock->fs_bsize, 1);
-
- /* We should also take this block off the inode's list of
- dirty indirect blocks if it's there. */
- prev = 0;
- d = np->dn->dirty;
- while (d)
- {
- next = d->next;
- if (d->bno == bno)
- {
- if (prev)
- prev->next = next;
- else
- np->dn->dirty = next;
- free (d);
- }
- else
- {
- prev = d;
- next = d->next;
- }
- d = next;
- }
-
- /* Free designated block */
- ffs_blkfree (np, bno, sblock->fs_bsize);
- count += btodb (sblock->fs_bsize);
-
- return count;
-}
-
-
-/* Offer data at BUF from START of LEN bytes of file NP. */
-void
-offer_data (struct node *np,
- off_t start,
- size_t len,
- vm_address_t buf)
-{
- vm_address_t addr;
-
- len = round_page (len);
-
- assert (start % vm_page_size == 0);
-
- assert (np->dn->fileinfo);
- for (addr = start; addr < start + len; addr += vm_page_size)
- pager_offer_page (np->dn->fileinfo->p, 1, 0, addr, buf + (addr - start));
-}
-
-/* Logical block LBN of node NP has been extended with ffs_realloccg.
- It used to be allocated at OLD_PBN and is now at NEW_PBN. The old
- size was OLD_SIZE; it is now NEW_SIZE bytes long. Arrange for the data
- on disk to be kept consistent, and free the old block if it has moved.
- Return one iff we've actually moved data around on disk. */
-int
-block_extended (struct node *np,
- daddr_t lbn,
- daddr_t old_pbn,
- daddr_t new_pbn,
- size_t old_size,
- size_t new_size)
-{
- /* Make sure that any pages of this block which just became allocated
- don't get paged in from disk. */
- if (round_page (old_size) < round_page (new_size))
- offer_data (np, lbn * sblock->fs_bsize + round_page (old_size),
- round_page (new_size) - round_page (old_size),
- (vm_address_t)zeroblock);
-
- if (old_pbn != new_pbn)
- {
- memory_object_t mapobj;
- error_t err;
- vm_address_t mapaddr;
- volatile int *pokeaddr;
-
- /* Map in this part of the file */
- mapobj = diskfs_get_filemap (np, VM_PROT_WRITE | VM_PROT_READ);
-
- /* XXX Should cope with errors from diskfs_get_filemap and back
- out the operation here. */
- assert (mapobj);
-
- err = vm_map (mach_task_self (), &mapaddr, round_page (old_size), 0, 1,
- mapobj, lbn * sblock->fs_bsize, 0,
- VM_PROT_READ|VM_PROT_WRITE, VM_PROT_READ|VM_PROT_WRITE, 0);
- assert_perror (err);
-
- /* Allow these pageins to occur even though we're holding the lock */
- pthread_spin_lock (&unlocked_pagein_lock);
- np->dn->fileinfo->allow_unlocked_pagein = lbn * sblock->fs_bsize;
- np->dn->fileinfo->unlocked_pagein_length = round_page (old_size);
- pthread_spin_unlock (&unlocked_pagein_lock);
-
- /* Make sure all waiting pageins see this change. */
- /* BDD - Is this sane? */
- /* TD - No... no it wasn't. But, it looked right. */
- /*
- This new code should, SHOULD, behave as the original code did.
- This will wake up all readers waiting on the lock. This code favors
- strongly writers, but, as of making this change, pthreads favors
- writers, and cthreads did favor writers.
- */
- pthread_mutex_lock (&np->dn->waitlock);
- pthread_cond_broadcast (&np->dn->waitcond);
- pthread_mutex_unlock (&np->dn->waitlock);
-
- /* Force the pages in core and make sure they are dirty */
- for (pokeaddr = (int *)mapaddr;
- pokeaddr < (int *) (mapaddr + round_page (old_size));
- pokeaddr += vm_page_size / sizeof (*pokeaddr))
- *pokeaddr = *pokeaddr;
-
- /* Turn off the special pagein permission */
- pthread_spin_lock (&unlocked_pagein_lock);
- np->dn->fileinfo->allow_unlocked_pagein = 0;
- np->dn->fileinfo->unlocked_pagein_length = 0;
- pthread_spin_unlock (&unlocked_pagein_lock);
-
- /* Undo mapping */
- mach_port_deallocate (mach_task_self (), mapobj);
- munmap ((caddr_t) mapaddr, round_page (old_size));
-
- /* Now it's OK to free the old block */
- ffs_blkfree (np, old_pbn, old_size);
-
- /* Tell caller that we've moved data */
- return 1;
- }
- else
- return 0;
-}
-
-
-/* Implement the diskfs_grow callback; see <hurd/diskfs.h> for the
- interface description. */
-error_t
-diskfs_grow (struct node *np,
- off_t end,
- struct protid *cred)
-{
- daddr_t lbn, olbn;
- int size, osize;
- error_t err;
- struct dinode *di = dino (np->dn->number);
- mach_port_t pagerpt;
- int need_sync = 0;
-
- /* Zero an sblock->fs_bsize piece of disk starting at BNO,
- synchronously. We do this on newly allocated indirect
- blocks before setting the pointer to them to ensure that an
- indirect block absolutely never points to garbage. */
- void zero_disk_block (int bno)
- {
- bzero (indir_block (bno), sblock->fs_bsize);
- sync_disk_blocks (bno, sblock->fs_bsize, 1);
- };
-
- /* Check to see if we don't actually have to do anything */
- if (end <= np->allocsize)
- return 0;
-
- diskfs_check_readonly ();
- assert (!diskfs_readonly);
-
- /* This reference will ensure that NP->dn->fileinfo stays allocated. */
- pagerpt = diskfs_get_filemap (np, VM_PROT_WRITE|VM_PROT_READ);
-
- if (pagerpt == MACH_PORT_NULL)
- return errno;
-
- /* The new last block of the file. */
- lbn = lblkno (sblock, end - 1);
-
- /* This is the size of that block if it is in the NDADDR array. */
- size = fragroundup (sblock, blkoff (sblock, end));
- if (size == 0)
- size = sblock->fs_bsize;
-
- pthread_rwlock_wrlock (&np->dn->allocptrlock);
-
- /* The old last block of the file. */
- olbn = lblkno (sblock, np->allocsize - 1);
-
- /* This is the size of that block if it is in the NDADDR array. */
- osize = fragroundup (sblock, blkoff (sblock, np->allocsize));
- if (osize == 0)
- osize = sblock->fs_bsize;
-
- /* If this end point is a new block and the file currently
- has a fragment, then expand the fragment to a full block. */
- if (np->allocsize && olbn < NDADDR && olbn < lbn)
- {
- if (osize < sblock->fs_bsize)
- {
- daddr_t old_pbn, bno;
- err = ffs_realloccg (np, olbn,
- ffs_blkpref (np, lbn, lbn, di->di_db),
- osize, sblock->fs_bsize, &bno, cred);
- if (err)
- goto out;
-
- old_pbn = read_disk_entry (di->di_db[olbn]);
-
- need_sync = block_extended (np, olbn, old_pbn, bno,
- osize, sblock->fs_bsize);
-
- write_disk_entry (di->di_db[olbn], bno);
- record_poke (di, sizeof (struct dinode));
- np->dn_set_ctime = 1;
- }
- }
-
- if (lbn < NDADDR)
- {
- daddr_t bno, old_pbn = read_disk_entry (di->di_db[lbn]);
-
- if (old_pbn != 0)
- {
- /* The last block is already allocated. Therefore we
- must be expanding the fragment. Make sure that's really
- what we're up to. */
- assert (size > osize);
- assert (lbn == olbn);
-
- err = ffs_realloccg (np, lbn,
- ffs_blkpref (np, lbn, lbn, di->di_db),
- osize, size, &bno, cred);
- if (err)
- goto out;
-
- need_sync = block_extended (np, lbn, old_pbn, bno, osize, size);
-
- write_disk_entry (di->di_db[lbn], bno);
- record_poke (di, sizeof (struct dinode));
- np->dn_set_ctime = 1;
- }
- else
- {
- /* Allocate a new last block. */
- err = ffs_alloc (np, lbn,
- ffs_blkpref (np, lbn, lbn, di->di_db),
- size, &bno, cred);
- if (err)
- goto out;
-
-
- offer_data (np, lbn * sblock->fs_bsize, size,
- (vm_address_t)zeroblock);
- write_disk_entry (di->di_db[lbn], bno);
- record_poke (di, sizeof (struct dinode));
- np->dn_set_ctime = 1;
- }
- }
- else
- {
- struct iblock_spec indirs[NIADDR + 1];
- daddr_t *siblock;
- daddr_t bno;
-
- /* Count the number of levels of indirection. */
- err = fetch_indir_spec (np, lbn, indirs);
- if (err)
- goto out;
-
- /* Make sure we didn't miss the NDADDR case
- above somehow. */
- assert (indirs[0].offset != -1);
-
- /* See if we need a triple indirect block; fail if so. */
- assert (indirs[1].offset == -1 || indirs[2].offset == -1);
-
- /* Check to see if this block is allocated. If it is
- that's an error. */
- assert (indirs[0].bno == 0);
-
- /* We need to set SIBLOCK to the single indirect block
- array; see if the single indirect block is allocated. */
- if (indirs[1].bno == 0)
- {
- /* Allocate it. */
- if (indirs[1].offset == -1)
- {
- err = ffs_alloc (np, lbn,
- ffs_blkpref (np, lbn, INDIR_SINGLE, di->di_ib),
- sblock->fs_bsize, &bno, 0);
- if (err)
- goto out;
- zero_disk_block (bno);
- indirs[1].bno = bno;
- write_disk_entry (di->di_ib[INDIR_SINGLE], bno);
- record_poke (di, sizeof (struct dinode));
- }
- else
- {
- daddr_t *diblock;
-
- /* We need to set diblock to the double indirect block
- array; see if the double indirect block is allocated. */
- if (indirs[2].bno == 0)
- {
- /* This assert because triple indirection is not
- supported. */
- assert (indirs[2].offset == -1);
- err = ffs_alloc (np, lbn,
- ffs_blkpref (np, lbn,
- INDIR_DOUBLE, di->di_ib),
- sblock->fs_bsize, &bno, 0);
- if (err)
- goto out;
- zero_disk_block (bno);
- indirs[2].bno = bno;
- write_disk_entry (di->di_ib[INDIR_DOUBLE], bno);
- record_poke (di, sizeof (struct dinode));
- }
-
- diblock = indir_block (indirs[2].bno);
- mark_indir_dirty (np, indirs[2].bno);
-
- /* Now we can allocate the single indirect block */
- err = ffs_alloc (np, lbn,
- ffs_blkpref (np, lbn,
- indirs[1].offset, diblock),
- sblock->fs_bsize, &bno, 0);
- if (err)
- goto out;
- zero_disk_block (bno);
- indirs[1].bno = bno;
- write_disk_entry (diblock[indirs[1].offset], bno);
- record_poke (diblock, sblock->fs_bsize);
- }
- }
-
- siblock = indir_block (indirs[1].bno);
- mark_indir_dirty (np, indirs[1].bno);
-
- /* Now we can allocate the data block. */
- err = ffs_alloc (np, lbn,
- ffs_blkpref (np, lbn, indirs[0].offset, siblock),
- sblock->fs_bsize, &bno, 0);
- if (err)
- goto out;
- offer_data (np, lbn * sblock->fs_bsize, sblock->fs_bsize,
- (vm_address_t)zeroblock);
- indirs[0].bno = bno;
- write_disk_entry (siblock[indirs[0].offset], bno);
- record_poke (siblock, sblock->fs_bsize);
- }
-
- out:
- mach_port_deallocate (mach_task_self (), pagerpt);
- if (!err)
- {
- int newallocsize;
- if (lbn < NDADDR)
- newallocsize = lbn * sblock->fs_bsize + size;
- else
- newallocsize = (lbn + 1) * sblock->fs_bsize;
- assert (newallocsize > np->allocsize);
- np->allocsize = newallocsize;
- }
-
- pthread_rwlock_unlock (&np->dn->allocptrlock);
- pthread_mutex_lock (&np->dn->waitlock);
- pthread_cond_broadcast (&np->dn->waitcond);
- pthread_mutex_unlock (&np->dn->waitlock);
-
- if (need_sync)
- diskfs_file_update (np, 1);
-
- return err;
-}
-
-/* Write something to each page from START to END inclusive of memory
- object OBJ, but make sure the data doesns't actually change. */
-static void
-poke_pages (memory_object_t obj,
- vm_offset_t start,
- vm_offset_t end)
-{
- vm_address_t addr, poke;
- vm_size_t len;
- error_t err;
-
- while (start < end)
- {
- len = 8 * vm_page_size;
- if (len > end - start)
- len = end - start;
- addr = 0;
- err = vm_map (mach_task_self (), &addr, len, 0, 1, obj, start, 0,
- VM_PROT_WRITE|VM_PROT_READ, VM_PROT_READ|VM_PROT_WRITE, 0);
- if (!err)
- {
- for (poke = addr; poke < addr + len; poke += vm_page_size)
- *(volatile int *)poke = *(volatile int *)poke;
- munmap ((caddr_t) addr, len);
- }
- start += len;
- }
-}
-
diff --git a/ufs/subr.c b/ufs/subr.c
deleted file mode 100644
index 2b356ddc..00000000
--- a/ufs/subr.c
+++ /dev/null
@@ -1,264 +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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 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
- */
-
-#include "ufs.h"
-
-#if 0 /* Not needed in GNU Hurd ufs. */
-/*
- * 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
-ffs_blkatoff(ap)
- struct vop_blkatoff_args /* {
- struct vnode *a_vp;
- off_t a_offset;
- char **a_res;
- struct buf **a_bpp;
- } */ *ap;
-{
- struct inode *ip;
- register struct fs *fs;
- struct buf *bp;
- daddr_t lbn;
- int bsize, error;
-
- ip = VTOI(ap->a_vp);
- fs = ip->i_fs;
- lbn = lblkno(fs, ap->a_offset);
- bsize = blksize(fs, ip, lbn);
-
- *ap->a_bpp = NULL;
- if (error = bread(ap->a_vp, lbn, bsize, NOCRED, &bp)) {
- brelse(bp);
- return (error);
- }
- if (ap->a_res)
- *ap->a_res = (char *)bp->b_data + blkoff(fs, ap->a_offset);
- *ap->a_bpp = bp;
- return (0);
-}
-#endif /* 0 */
-
-/*
- * Update the frsum fields to reflect addition or deletion
- * of some frags.
- */
-void
-ffs_fragacct(fs, fragmap, fraglist, cnt)
- struct fs *fs;
- int fragmap;
- long fraglist[];
- int cnt;
-{
- int inblk;
- register int field, subfield;
- register int siz, pos;
-
- inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1;
- fragmap <<= 1;
- for (siz = 1; siz < fs->fs_frag; siz++) {
- if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
- continue;
- field = around[siz];
- subfield = inside[siz];
- for (pos = siz; pos <= fs->fs_frag; pos++) {
- if ((fragmap & field) == subfield) {
- fraglist[siz] += cnt;
- pos += siz;
- field <<= siz;
- subfield <<= siz;
- }
- field <<= 1;
- subfield <<= 1;
- }
- }
-}
-
-#if 0 /* Not needed in GNU Hurd ufs. */
-void
-ffs_checkoverlap(bp, ip)
- struct buf *bp;
- struct inode *ip;
-{
- register struct buf *ebp, *ep;
- register daddr_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) ||
- ep->b_vp == NULLVP)
- continue;
- if (VOP_BMAP(ep->b_vp, (daddr_t)0, &vp, (daddr_t)0, NULL))
- continue;
- if (vp != ip->i_devvp)
- continue;
- /* 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 %d, end %d\n",
- start, last, ep->b_blkno,
- ep->b_blkno + btodb(ep->b_bcount) - 1);
- panic("Disk buffer overlap");
- }
-}
-#endif /* 0 */
-
-/*
- * block operations
- *
- * check if a block is available
- */
-int
-ffs_isblock(fs, cp, h)
- struct fs *fs;
- unsigned char *cp;
- daddr_t h;
-{
- unsigned char mask;
-
- switch ((int)fs->fs_frag) {
- case 8:
- return (cp[h] == 0xff);
- case 4:
- mask = 0x0f << ((h & 0x1) << 2);
- return ((cp[h >> 1] & mask) == mask);
- case 2:
- mask = 0x03 << ((h & 0x3) << 1);
- return ((cp[h >> 2] & mask) == mask);
- case 1:
- mask = 0x01 << (h & 0x7);
- return ((cp[h >> 3] & mask) == mask);
- default:
- assert (0);
- }
-}
-
-/*
- * take a block out of the map
- */
-void
-ffs_clrblock(fs, cp, h)
- struct fs *fs;
- u_char *cp;
- daddr_t h;
-{
-
- switch ((int)fs->fs_frag) {
- case 8:
- cp[h] = 0;
- return;
- case 4:
- cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
- return;
- case 2:
- cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
- return;
- case 1:
- cp[h >> 3] &= ~(0x01 << (h & 0x7));
- return;
- default:
- assert (0);
- }
-}
-
-/*
- * put a block into the map
- */
-void
-ffs_setblock(fs, cp, h)
- struct fs *fs;
- unsigned char *cp;
- daddr_t h;
-{
-
- switch ((int)fs->fs_frag) {
-
- case 8:
- cp[h] = 0xff;
- return;
- case 4:
- cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
- return;
- case 2:
- cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
- return;
- case 1:
- cp[h >> 3] |= (0x01 << (h & 0x7));
- return;
- default:
- assert (0);
- }
-}
-
-/* Taken from 4.4 BSD sys/libkern/skpc.c:
- @(#)skpc.c 8.1 (Berkeley) 6/10/93
-*/
-int
-skpc(mask0, size, cp0)
- int mask0;
- int size;
- char *cp0;
-{
- register u_char *cp, *end, mask;
-
- mask = mask0;
- cp = (u_char *)cp0;
- for (end = &cp[size]; cp < end && *cp == mask; ++cp);
- return (end - cp);
-}
-
-/* Taken from 4.4 BSD sys/libkern/scanc.c:
- @(#)scanc.c 8.1 (Berkeley) 6/10/93
-*/
-int
-scanc(size, cp, table, mask0)
- u_int size;
- register u_char *cp, table[];
- int mask0;
-{
- register u_char *end;
- register u_char mask;
-
- mask = mask0;
- for (end = &cp[size]; cp < end && (table[*cp] & mask) == 0; ++cp);
- return (end - cp);
-}
diff --git a/ufs/tables.c b/ufs/tables.c
deleted file mode 100644
index d345b9e4..00000000
--- a/ufs/tables.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/* Modified from BSD for GNU Hurd ufs server by Michael I. Bushnell. */
-/*
- * 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 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_tables.c 8.1 (Berkeley) 6/11/93
- */
-
-#include <sys/types.h>
-#include "fs.h"
-
-/*
- * Bit patterns for identifying fragments in the block map
- * used as ((map & around) == inside)
- */
-int around[9] = {
- 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff
-};
-int inside[9] = {
- 0x0, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe
-};
-
-/*
- * Given a block map bit pattern, the frag tables tell whether a
- * particular size fragment is available.
- *
- * used as:
- * if ((1 << (size - 1)) & fragtbl[fs->fs_frag][map] {
- * at least one fragment of the indicated size is available
- * }
- *
- * These tables are used by the scanc instruction on the VAX to
- * quickly find an appropriate fragment.
- */
-u_char fragtbl124[256] = {
- 0x00, 0x16, 0x16, 0x2a, 0x16, 0x16, 0x26, 0x4e,
- 0x16, 0x16, 0x16, 0x3e, 0x2a, 0x3e, 0x4e, 0x8a,
- 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
- 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
- 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
- 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
- 0x2a, 0x3e, 0x3e, 0x2a, 0x3e, 0x3e, 0x2e, 0x6e,
- 0x3e, 0x3e, 0x3e, 0x3e, 0x2a, 0x3e, 0x6e, 0xaa,
- 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
- 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
- 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
- 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
- 0x26, 0x36, 0x36, 0x2e, 0x36, 0x36, 0x26, 0x6e,
- 0x36, 0x36, 0x36, 0x3e, 0x2e, 0x3e, 0x6e, 0xae,
- 0x4e, 0x5e, 0x5e, 0x6e, 0x5e, 0x5e, 0x6e, 0x4e,
- 0x5e, 0x5e, 0x5e, 0x7e, 0x6e, 0x7e, 0x4e, 0xce,
- 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
- 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
- 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
- 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
- 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e,
- 0x16, 0x16, 0x16, 0x3e, 0x3e, 0x3e, 0x5e, 0x9e,
- 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e,
- 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, 0xbe,
- 0x2a, 0x3e, 0x3e, 0x2a, 0x3e, 0x3e, 0x2e, 0x6e,
- 0x3e, 0x3e, 0x3e, 0x3e, 0x2a, 0x3e, 0x6e, 0xaa,
- 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e,
- 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x7e, 0xbe,
- 0x4e, 0x5e, 0x5e, 0x6e, 0x5e, 0x5e, 0x6e, 0x4e,
- 0x5e, 0x5e, 0x5e, 0x7e, 0x6e, 0x7e, 0x4e, 0xce,
- 0x8a, 0x9e, 0x9e, 0xaa, 0x9e, 0x9e, 0xae, 0xce,
- 0x9e, 0x9e, 0x9e, 0xbe, 0xaa, 0xbe, 0xce, 0x8a,
-};
-
-u_char fragtbl8[256] = {
- 0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x04,
- 0x01, 0x01, 0x01, 0x03, 0x02, 0x03, 0x04, 0x08,
- 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
- 0x02, 0x03, 0x03, 0x02, 0x04, 0x05, 0x08, 0x10,
- 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
- 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
- 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06,
- 0x04, 0x05, 0x05, 0x06, 0x08, 0x09, 0x10, 0x20,
- 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
- 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
- 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
- 0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11,
- 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06,
- 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0a,
- 0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04,
- 0x08, 0x09, 0x09, 0x0a, 0x10, 0x11, 0x20, 0x40,
- 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
- 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
- 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
- 0x03, 0x03, 0x03, 0x03, 0x05, 0x05, 0x09, 0x11,
- 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05,
- 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x05, 0x09,
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07,
- 0x05, 0x05, 0x05, 0x07, 0x09, 0x09, 0x11, 0x21,
- 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x06,
- 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x06, 0x0a,
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07,
- 0x02, 0x03, 0x03, 0x02, 0x06, 0x07, 0x0a, 0x12,
- 0x04, 0x05, 0x05, 0x06, 0x05, 0x05, 0x06, 0x04,
- 0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x04, 0x0c,
- 0x08, 0x09, 0x09, 0x0a, 0x09, 0x09, 0x0a, 0x0c,
- 0x10, 0x11, 0x11, 0x12, 0x20, 0x21, 0x40, 0x80,
-};
-
-/*
- * The actual fragtbl array.
- */
-u_char *fragtbl[MAXFRAG + 1] = {
- 0, fragtbl124, fragtbl124, 0, fragtbl124, 0, 0, 0, fragtbl8,
-};
diff --git a/ufs/ufs.h b/ufs/ufs.h
deleted file mode 100644
index 0a79f560..00000000
--- a/ufs/ufs.h
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- Copyright (C) 1994, 1995, 1996, 1997, 1999 Free Software Foundation
-
- 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, or (at
- your option) any later version.
-
- 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 <mach.h>
-#include <hurd.h>
-#include <sys/mman.h>
-#include <hurd/ports.h>
-#include <hurd/pager.h>
-#include <hurd/fshelp.h>
-#include <hurd/iohelp.h>
-#include <hurd/diskfs.h>
-#include <sys/mman.h>
-#include <assert.h>
-#include <pthread.h>
-#include <features.h>
-#include "fs.h"
-#include "dinode.h"
-
-#ifdef UFS_DEFINE_EI
-#define UFS_EI
-#else
-#define UFS_EI __extern_inline
-#endif
-
-/* Define this if memory objects should not be cached by the kernel.
- Normally, don't define it, but defining it causes a much greater rate
- of paging requests, which may be helpful in catching bugs. */
-
-/* #undef DONT_CACHE_MEMORY_OBJECTS */
-
-struct disknode
-{
- ino_t number;
-
- int dir_idx;
-
- /* For a directory, this array holds the number of directory entries in
- each DIRBLKSIZE piece of the directory. */
- int *dirents;
-
- /* Links on hash list. */
- struct node *hnext, **hprevp;
-
- pthread_rwlock_t allocptrlock;
- pthread_mutex_t waitlock;
- pthread_cond_t waitcond;
-
- struct dirty_indir *dirty;
-
- struct user_pager_info *fileinfo;
-};
-
-/* Identifies a particular block and where it's found
- when interpreting indirect block structure. */
-struct iblock_spec
-{
- /* Disk address of block */
- daddr_t bno;
-
- /* Offset in next block up; -1 if it's in the inode itself. */
- int offset;
-};
-
-/* Identifies an indirect block owned by this file which
- might be dirty. */
-struct dirty_indir
-{
- daddr_t bno; /* Disk address of block. */
- struct dirty_indir *next;
-};
-
-struct user_pager_info
-{
- struct node *np;
- enum pager_type
- {
- DISK,
- FILE_DATA,
- } type;
- struct pager *p;
- vm_prot_t max_prot;
-
- vm_offset_t allow_unlocked_pagein;
- vm_size_t unlocked_pagein_length;
-};
-
-#include <hurd/diskfs-pager.h>
-
-/* The physical media. */
-extern struct store *store;
-/* What the user specified. */
-extern struct store_parsed *store_parsed;
-
-/* Mapped image of the disk. */
-extern void *disk_image;
-
-extern void *zeroblock;
-
-extern struct fs *sblock;
-extern struct csum *csum;
-int sblock_dirty;
-int csum_dirty;
-
-pthread_spinlock_t node2pagelock;
-
-pthread_spinlock_t alloclock;
-
-pthread_spinlock_t gennumberlock;
-u_long nextgennumber;
-
-pthread_spinlock_t unlocked_pagein_lock;
-
-/* The compat_mode specifies whether or not we write
- extensions onto the disk. */
-enum compat_mode
-{
- COMPAT_GNU = 0,
- COMPAT_BSD42 = 1,
- COMPAT_BSD44 = 2,
-} compat_mode;
-
-/* If this is set, then this filesystem has two extensions:
- 1) directory entries include the type field.
- 2) symlink targets might be written directly in the di_db field
- of the dinode. */
-int direct_symlink_extension;
-
-/* If this is set, then the disk is byteswapped from native order. */
-int swab_disk;
-
-/* Number of device blocks per DEV_BSIZE block. */
-unsigned log2_dev_blocks_per_dev_bsize;
-
-/* Handy macros */
-#define DEV_BSIZE 512
-#define NBBY 8
-#define btodb(n) ((n) / DEV_BSIZE)
-#define howmany(x,y) (((x)+((y)-1))/(y))
-#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
-#define isclr(a, i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
-#define isset(a, i) ((a)[(i)/NBBY] & (1<<((i)%NBBY)))
-#define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY))
-#define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<(i)%NBBY))
-#define fsaddr(fs,n) (fsbtodb(fs,n)*DEV_BSIZE)
-
-
-/* Functions for looking inside disk_image */
-
-extern struct dinode * dino (ino_t inum);
-extern daddr_t * indir_block (daddr_t bno);
-extern struct cg * cg_locate (int ncg);
-extern void sync_disk_blocks (daddr_t blkno, size_t nbytes, int wait);
-extern void sync_dinode (int inum, int wait);
-extern short swab_short (short arg);
-extern long swab_long (long arg);
-extern long long swab_long_long (long long arg);
-
-#if defined(__USE_EXTERN_INLINES) || defined(UFS_DEFINE_EI)
-/* Convert an inode number to the dinode on disk. */
-UFS_EI struct dinode *
-dino (ino_t inum)
-{
- return (struct dinode *)
- (disk_image
- + fsaddr (sblock, ino_to_fsba (sblock, inum))
- + ino_to_fsbo (sblock, inum) * sizeof (struct dinode));
-}
-
-/* Convert a indirect block number to a daddr_t table. */
-UFS_EI daddr_t *
-indir_block (daddr_t bno)
-{
- return (daddr_t *) (disk_image + fsaddr (sblock, bno));
-}
-
-/* Convert a cg number to the cylinder group. */
-UFS_EI struct cg *
-cg_locate (int ncg)
-{
- return (struct cg *) (disk_image + fsaddr (sblock, cgtod (sblock, ncg)));
-}
-
-/* Sync part of the disk */
-UFS_EI void
-sync_disk_blocks (daddr_t blkno, size_t nbytes, int wait)
-{
- pager_sync_some (diskfs_disk_pager, fsaddr (sblock, blkno), nbytes, wait);
-}
-
-/* Sync an disk inode */
-UFS_EI void
-sync_dinode (int inum, int wait)
-{
- sync_disk_blocks (ino_to_fsba (sblock, inum), sblock->fs_fsize, wait);
-}
-
-
-/* Functions for byte swapping */
-UFS_EI short
-swab_short (short arg)
-{
- return (((arg & 0xff) << 8)
- | ((arg & 0xff00) >> 8));
-}
-
-UFS_EI long
-swab_long (long arg)
-{
- return (((long) swab_short (arg & 0xffff) << 16)
- | swab_short ((arg & 0xffff0000) >> 16));
-}
-
-UFS_EI long long
-swab_long_long (long long arg)
-{
- return (((long long) swab_long (arg & 0xffffffff) << 32)
- | swab_long ((arg & 0xffffffff00000000LL) >> 32));
-}
-#endif /* Use extern inlines. */
-
-/* Return ENTRY, after byteswapping it if necessary */
-#define read_disk_entry(entry) \
-({ \
- typeof (entry) ret; \
- if (!swab_disk || sizeof (entry) == 1) \
- ret = (entry); \
- else if (sizeof (entry) == 2) \
- ret = swab_short (entry); \
- else if (sizeof (entry) == 4) \
- ret = swab_long (entry); \
- else \
- abort (); \
- ret; \
-})
-
-/* Execute A = B, but byteswap it along the way if necessary */
-#define write_disk_entry(a,b) \
-({ \
- if (!swab_disk || sizeof (a) == 1) \
- ((a) = (b)); \
- else if (sizeof (a) == 2) \
- ((a) = (swab_short (b))); \
- else if (sizeof (a) == 4) \
- ((a) = (swab_long (b))); \
- else \
- abort (); \
-})
-
-
-
-
-
-/* From alloc.c: */
-error_t ffs_alloc (struct node *, daddr_t, daddr_t, int, daddr_t *,
- struct protid *);
-void ffs_blkfree(struct node *, daddr_t bno, long size);
-daddr_t ffs_blkpref (struct node *, daddr_t, int, daddr_t *);
-error_t ffs_realloccg(struct node *, daddr_t, daddr_t,
- int, int, daddr_t *, struct protid *);
-
-/* From bmap.c */
-error_t fetch_indir_spec (struct node *, daddr_t, struct iblock_spec *);
-void mark_indir_dirty (struct node *, daddr_t);
-
-/* From hyper.c: */
-void get_hypermetadata (void);
-void copy_sblock (void);
-
-/* From inode.c: */
-struct node *ifind (ino_t ino);
-void inode_init (void);
-void write_all_disknodes (void);
-
-/* From pager.c: */
-void create_disk_pager (void);
-void din_map (struct node *);
-void sin_map (struct node *);
-void sin_remap (struct node *, int);
-void sin_unmap (struct node *);
-void din_unmap (struct node *);
-void drop_pager_softrefs (struct node *);
-void allow_pager_softrefs (struct node *);
-void flush_node_pager (struct node *);
-
-/* From subr.c: */
-void ffs_fragacct (struct fs *, int, long [], int);
-int ffs_isblock(struct fs *, u_char *, daddr_t);
-void ffs_clrblock(struct fs *, u_char *, daddr_t);
-void ffs_setblock (struct fs *, u_char *, daddr_t);
-int skpc (int, int, char *);
-int scanc (u_int, u_char *, u_char [], int);
-
-/* From pokeloc.c: */
-void record_poke (void *, vm_size_t);
-void sync_disk (int);
-void flush_pokes ();
diff --git a/ufs/xinl.c b/ufs/xinl.c
deleted file mode 100644
index 7994a1f7..00000000
--- a/ufs/xinl.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define UFS_DEFINE_EI
-#include "ufs.h"