Remove IFS from 5.0-CURRENT. This facilitates introducing UFS2 as

IFS had its fingers deep in the belly of the UFS/FFS split.  IFS
will be reimplemented by the maintainer at a later date.

Requested by:	adrian (maintainer)
This commit is contained in:
Robert Watson 2002-05-19 00:11:08 +00:00
parent 8b1febe499
commit 2bab796d96
9 changed files with 0 additions and 1375 deletions

View File

@ -592,9 +592,6 @@ options UNIONFS #Union filesystem
# options NODEVFS #disable devices filesystem
# The xFS_ROOT options REQUIRE the associated ``options xFS''
options NFS_ROOT #NFS usable as root device
# This code enables IFS, an FFS which exports inodes as the namespace.
# You can find details in src/sys/ufs/ifs/README .
options IFS
# Soft updates is a technique for improving filesystem speed and
# making abrupt shutdown less risky.

View File

@ -1299,49 +1299,25 @@ posix4/ksched.c optional _kposix_priority_scheduling
posix4/p1003_1b.c standard
posix4/posix4_mib.c standard
ufs/ffs/ffs_alloc.c optional ffs
ufs/ffs/ffs_alloc.c optional ifs
ufs/ffs/ffs_balloc.c optional ffs
ufs/ffs/ffs_balloc.c optional ifs
ufs/ffs/ffs_inode.c optional ffs
ufs/ffs/ffs_inode.c optional ifs
ufs/ffs/ffs_snapshot.c optional ffs
ufs/ffs/ffs_snapshot.c optional ifs
ufs/ffs/ffs_softdep.c optional softupdates ffs
ufs/ffs/ffs_softdep.c optional softupdates ifs
ufs/ffs/ffs_softdep_stub.c optional ffs
ufs/ffs/ffs_softdep_stub.c optional ifs
ufs/ffs/ffs_subr.c optional ffs
ufs/ffs/ffs_subr.c optional ifs
ufs/ffs/ffs_tables.c optional ffs
ufs/ffs/ffs_tables.c optional ifs
ufs/ffs/ffs_vfsops.c optional ffs
ufs/ffs/ffs_vfsops.c optional ifs
ufs/ffs/ffs_vnops.c optional ffs
ufs/ffs/ffs_vnops.c optional ifs
ufs/ufs/ufs_acl.c optional ffs
ufs/ufs/ufs_acl.c optional ifs
ufs/ufs/ufs_bmap.c optional ffs
ufs/ufs/ufs_bmap.c optional ifs
ufs/ufs/ufs_dirhash.c optional ffs
ufs/ufs/ufs_dirhash.c optional ifs
ufs/ufs/ufs_extattr.c optional ffs
ufs/ufs/ufs_extattr.c optional ifs
ufs/ufs/ufs_ihash.c optional ffs
ufs/ufs/ufs_ihash.c optional ifs
ufs/ufs/ufs_inode.c optional ffs
ufs/ufs/ufs_inode.c optional ifs
ufs/ufs/ufs_lookup.c optional ffs
ufs/ufs/ufs_lookup.c optional ifs
ufs/ufs/ufs_quota.c optional ffs
ufs/ufs/ufs_quota.c optional ifs
ufs/ufs/ufs_vfsops.c optional ffs
ufs/ufs/ufs_vfsops.c optional ifs
ufs/ufs/ufs_vnops.c optional ffs
ufs/ufs/ufs_vnops.c optional ifs
ufs/ifs/ifs_lookup.c optional ifs
ufs/ifs/ifs_vfsops.c optional ifs
ufs/ifs/ifs_vnops.c optional ifs
ufs/ifs/ifs_subr.c optional ifs
vm/default_pager.c standard
vm/device_pager.c standard
vm/phys_pager.c standard

View File

@ -134,7 +134,6 @@ UDF opt_dontuse.h
# Broken - ffs_snapshot() dependency from ufs_lookup() :-(
FFS opt_ffs_broken_fixme.h
IFS opt_ffs_broken_fixme.h
# These static filesystems has one slightly bogus static dependency in
# sys/i386/i386/autoconf.c. If any of these filesystems are

View File

@ -1,109 +0,0 @@
$FreeBSD$
ifs- inode filesystem
--
ifs is the beginning of a little experiment - to remove the namespace
from ffs. FFS is a good generic filesystem, however in high volume
activities today (eg web, mail, cache, news) one thing causes a rather
huge resource drain - the namespace.
Having to maintain the directory structures means wasting a lot of
disk IO and/or memory. Since most applications these days have their
own database containing object->ufs namespace mappings, we can effectively
bypass namespace together and talk instead to just inodes.
This is a big big hack(1), but its also a start. It should speed up news
servers and cache servers quite a bit - since the time spent in open()
and unlink() is drastically reduced - however, it is nowhere near
optimal. We'll cover that shortly.
(1) not hack as evil and ugly, hack as in non-optimal solution. The
optimal solution hasn't quite presented itself yet. :-)
How it works:
--
Basically ifs is a copy of ffs, overriding some vfs/vnops. (Yes, hack.)
I didn't see the need in duplicating all of sys/ufs/ffs to get this
off the ground.
File creation is done through a special file - 'newfile' . When newfile
is called, the system allocates and returns an inode. Note that newfile
is done in a cloning fashion:
fd = open("newfile", O_CREAT|O_RDWR, 0644);
fstat(fd, &st);
printf("new file is %d\n", (int)st.st_ino);
Once you have created a file, you can open() and unlink() it by its returned
inode number retrieved from the stat call, ie:
fd = open("5", O_RDWR);
The creation permissions depend entirely if you have write access to the
root directory of the filesystem.
Why its nowhere near optimal
--
When doing file allocation in FFS, it tries to reduce the disk seeks by
allocating new files inside the cylinder group of the parent directory, if
possible. In this scheme, we've had to drop that. Files are allocated
sequentially, filling up cylinder groups as we go along. Its not very optimal,
more research will have to be done into how cylinder group locality can be
bought back into this. (It entirely depends upon the benefits here..)
Allowing create by inode number requires quite a bit of code rewrite, and in
the test applications here I didn't need it. Maybe in the next phase I might
look at allowing create by inode number, feedback, please.
SOFTUPDATES will *NOT* work here - especially in unlink() where I've just
taken a large axe to it. I've tried to keep as much of the softupdates call
stubs in as much as possible, but I haven't looked at the softupdates code.
My reasoning was that because there's no directory metadata anymore,
softupdates isn't as important. Besides, fsck's are so damn quick ..
Extras
--
I've taken the liberty of applying a large axe to bits of fsck - stripping out
namespace checks. As far as I can *TELL*, its close, however, I'd like it if
someone fsck clued poked me back on what I missed.
There's also a modified copy of mount that will mount a fs type 'ifs'. Again,
its just the normal mount with s/"ufs"/"ifs"/g, async/noatime/etc mount
options work just as normal.
I haven't supplied an ifs 'newfs' - use FFS newfs to create a blank drive.
That creates the root directory, which you still do DEFINITELY need.
However, ifs updates on the drive will not update directory entries in '.'.
There is a 1:1 mapping between the inode numbers in open()/stat() and the
inodes on disk. You don't get access to inodes 0-2. They don't show up
in a readdir. I'll work on making 2 avaliable, but since the current ufs/ffs
code assumes things are locked against the root inode which is 2 ..
You can find these utilities in src/sbin/mount_ifs and src/sbin/fsck_ifs .
Yes, this means that you can tie in ifs partitions in your bootup
sequence.
TODO:
--
* Implement cookies for NFS
(Realise that this is a huge hack which uses the existing UFS/FFS code.
Therefore its nowhere near as optimal as it could be, and things aren't
as easy to add as one might think. Especially 'fake' files. :-)
--
Adrian Chadd
<adrianFreeBSD.org>

View File

@ -1,82 +0,0 @@
/*-
* Copyright (c) 1991, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 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_extern.h 8.6 (Berkeley) 3/30/95
* $FreeBSD$
*/
#ifndef _UFS_IFS_EXTERN_H
#define _UFS_IFS_EXTERN_H
/*
* Sysctl values for the fast filesystem.
*/
#define IFS_REALLOCBLKS 3 /* block reallocation enabled */
#define IFS_ASYNCFREE 4 /* asynchronous block freeing enabled */
#define IFS_MAXID 5 /* number of valid ffs ids */
/* Return vals from ifs_isinodealloc */
#define IFS_INODE_ISALLOC 1
#define IFS_INODE_NOALLOC 0
#define IFS_INODE_EMPTYCG -1
#define IFS_NAMES { \
{ 0, 0 }, \
{ 0, 0 }, \
{ 0, 0 }, \
{ "doreallocblks", CTLTYPE_INT }, \
{ "doasyncfree", CTLTYPE_INT }, \
}
struct buf;
struct fid;
struct fs;
struct inode;
struct malloc_type;
struct mount;
struct sockaddr;
struct statfs;
struct ucred;
struct vnode;
struct vop_balloc_args;
struct vop_fsync_args;
struct vop_reallocblks_args;
extern vop_t **ifs_vnodeop_p;
extern vop_t **ifs_specop_p;
extern vop_t **ifs_fifoop_p;
int ifs_lookup(struct vop_lookup_args *);
int ifs_isinodealloc(struct inode *, ufs_daddr_t);
#endif /* !_UFS_IFS_EXTERN_H */

View File

@ -1,253 +0,0 @@
/*
* Copyright (c) 1999, 2000
* Adrian Chadd <adrian@FreeBSD.org>
*
* 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.
*
* @(#)ufs_lookup.c 8.15 (Berkeley) 6/16/95
* $FreeBSD$
*/
#include <machine/limits.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/namei.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <sys/vnode.h>
#include <sys/sysctl.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
#include <ufs/ufs/extattr.h>
#include <ufs/ufs/quota.h>
#include <ufs/ufs/inode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ufs/ufsmount.h>
#include <ufs/ufs/ufs_extern.h>
#include <ufs/ffs/fs.h>
#include <ufs/ifs/ifs_extern.h>
/* true if old FS format...*/
#define OFSFMT(vp) ((vp)->v_mount->mnt_maxsymlinklen <= 0)
/* Define if you want my debug printfs inside ifs_lookup() */
#undef DEBUG_IFS_LOOKUP
#ifdef DEBUG_IFS_LOOKUP
static char *
getnameiopstr(int nameiop)
{
switch (nameiop) {
case LOOKUP:
return "LOOKUP";
break;
case CREATE:
return "CREATE";
break;
case DELETE:
return "DELETE";
break;
case RENAME:
return "RENAME";
break;
default:
return "unknown";
break;
}
}
#endif
/*
* Convert a path to an inode.
*
* This is HIGHLY simplified - we just take the path fragment given to us,
* attempt to convert it to an inode, and return the inode if we can.
* No permission checking is done here, that is done further up in the
* VFS call layers.
*/
int
ifs_lookup(ap)
struct vop_lookup_args /* {
struct vnode *a_dvp;
struct vnode **a_vpp;
struct componentname *a_cnp;
} */ *ap;
{
struct vnode *vdp; /* vnode for directory being searched */
struct inode *dp; /* inode for directory being searched */
struct vnode *pdp; /* saved dp during symlink work */
struct vnode *tdp; /* returned by VFS_VGET */
struct vnode **vpp = ap->a_vpp;
struct componentname *cnp = ap->a_cnp;
struct ucred *cred = cnp->cn_cred;
struct mount *mp = ap->a_dvp->v_mount;
struct fs *fs = VFSTOUFS(mp)->um_fs;
int flags = cnp->cn_flags;
int nameiop = cnp->cn_nameiop;
int error, lockparent, wantparent;
struct thread *td = cnp->cn_thread;
ufs_daddr_t inodenum;
char *endp;
*vpp = NULL;
lockparent = flags & LOCKPARENT;
wantparent = flags & (LOCKPARENT|WANTPARENT);
vdp = ap->a_dvp;
dp = VTOI(vdp);
pdp = vdp;
/*
* Firstly, we are NOT dealing with RENAME, at all
*/
if (nameiop == RENAME) {
*vpp = NULL;
#ifdef DEBUG_IFS_LOOKUP
printf("ifs_lookup(): Denying RENAME nameiop\n");
#endif
return (EPERM);
}
/* Deal with the '.' directory */
/* VOP_UNLOCK(vdp, 0, td); */
if (cnp->cn_namelen == 1 && *(cnp->cn_nameptr) == '.') {
/* We don't unlock the parent dir since the're the same */
*vpp = vdp;
VREF(vdp);
/* vn_lock(vdp, LK_SHARED | LK_RETRY, td); */
return (0);
}
/*
* 'newfile' is considered something special .. read below why
* we're returning NULL
*/
if ((cnp->cn_namelen) == 7 && (strncmp(cnp->cn_nameptr, "newfile", 7) == 0)) {
if (nameiop == CREATE) {
/* Check for write permissions in . */
error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread);
if (error)
return (error);
*vpp = NULL;
if (!lockparent || !(flags & ISLASTCN))
VOP_UNLOCK(pdp, 0, td);
cnp->cn_flags |= SAVENAME;
return (EJUSTRETURN);
} else {
*vpp = NULL;
#ifdef DEBUG_IFS_LOOKUP
printf("ifs_lookup(): Denying !CREATE on 'newfile'\n");
#endif
return (EPERM);
}
}
/* Grab the hex inode number */
inodenum = strtouq(cnp->cn_nameptr, &endp, 0);
/* Sanity Check */
if (endp != (cnp->cn_nameptr + cnp->cn_namelen)) {
*vpp = NULL;
return (ENOENT);
}
/*
* error check here - inodes 0-2 are considered 'special' even here
* so we will hide it from the user.
*/
if (inodenum <= 2) {
#ifdef DEBUG_IFS_LOOKUP
printf("ifs_lookup(): Access to disk inode '%d' denied\n",
(int)inodenum);
#endif
return EPERM;
}
/* Check we haven't overflowed the number of inodes in the fs */
if (inodenum > (fs->fs_ncg * fs->fs_ipg)) {
#ifdef DEBUG_IFS_LOOKUP
printf("ifs_lookup(): disk inode '%d' is outside the disk\n"),
(int)inodenum);
#endif
return EINVAL;
}
/*
* The next bit of code grabs the inode, checks to see whether
* we're allowed to do our nameiop on it. The only one we need
* to check here is CREATE - only allow create on an inode
* that exists.
*
* Comment for VFS-newbies:
* read vn_open() - you'll learn that if you return a name here,
* it assumes you don't need to call VOP_CREATE. Bad juju as
* you now have a vnode that isn't tagged with the right type,
* and it'll panic in the VOP_READ/VOP_WRITE routines..
*/
/*
* If we get here and its a CREATE, then return EPERM if the inode
* doesn't exist.
*/
if ((nameiop == CREATE) &&
(ifs_isinodealloc(VTOI(vdp), inodenum) != IFS_INODE_ISALLOC)) {
#ifdef DEBUG_IFS_LOOKUP
printf("ifs_lookup(): CREATE on inode %d which doesn't exist\n",
(int)inodenum);
#endif
return EPERM;
#ifdef DEBUG_IFS_LOOKUP
} else if (nameiop == CREATE) {
/* It does exist, allow CREATE */
printf("ifs_lookup(): CREATE on inode %d which exists\n",
(int)inodenum);
}
#else
}
#endif
/*
* Make sure that the inode exists if we're trying to delete or
* modify
*/
if ((nameiop == LOOKUP || nameiop == DELETE) &&
ifs_isinodealloc(VTOI(vdp), inodenum) != IFS_INODE_ISALLOC) {
/* it doesn't exist */
#ifdef DEBUG_IFS_LOOKUP
printf("ifs_lookup(): Inode %d isn't allocated\n", inodenum);
#endif
return ENOENT;
}
/* Now, we can get the vnode */
error = VFS_VGET(vdp->v_mount, (long)inodenum, LK_EXCLUSIVE, &tdp);
if (error)
return (error);
if (!lockparent || !(flags & ISLASTCN))
VOP_UNLOCK(pdp, 0, td);
*vpp = tdp;
return (0);
}

View File

@ -1,118 +0,0 @@
/*
* Copyright (c) 1999, 2000
* Adrian Chadd <adrian@FreeBSD.org>
*
* 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_vnops.c 8.15 (Berkeley) 5/14/95
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/resourcevar.h>
#include <sys/signalvar.h>
#include <sys/kernel.h>
#include <sys/stat.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/mount.h>
#include <sys/vnode.h>
#include <sys/conf.h>
#include <sys/namei.h>
#include <sys/malloc.h>
#include <sys/dirent.h>
#include <machine/limits.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <vm/vm_object.h>
#include <vm/vm_extern.h>
#include <ufs/ufs/dir.h>
#include <ufs/ufs/quota.h>
#include <ufs/ufs/inode.h>
#include <ufs/ufs/ufs_extern.h>
#include <ufs/ffs/fs.h>
#include <ufs/ffs/ffs_extern.h>
#include <ufs/ifs/ifs_extern.h>
/*
* Check whether the given inode number is free.
*
* This routine is a chunk of ffs_nodealloccg - we aren't
* allocating here. We also check whether there will be
* any other inodes in the cylinder group, and if not,
* we return -1.
*/
int
ifs_isinodealloc(struct inode *ip, ufs_daddr_t ino)
{
struct fs *fs;
struct cg *cgp;
struct buf *bp;
int error;
int cg;
int retval = 0;
/* Grab the filesystem info and cylinder group */
fs = ip->i_fs;
cg = ino_to_cg(fs, ino);
/* Read in the cylinder group inode allocation bitmap .. */
error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)),
(int)fs->fs_cgsize, NOCRED, &bp);
if (error) {
retval = IFS_INODE_NOALLOC;
goto end;
}
cgp = (struct cg *)bp->b_data;
if (!cg_chkmagic(cgp)) {
retval = IFS_INODE_NOALLOC;
goto end;
}
ino %= fs->fs_ipg;
/*
* Check whether we have any inodes in this cg, or whether the
* inode is allocated
*/
if (!isclr(cg_inosused(cgp), ino))
retval = IFS_INODE_ISALLOC; /* it is allocated */
else if (cgp->cg_niblk == cgp->cg_cs.cs_nifree)
retval = IFS_INODE_EMPTYCG; /* empty cg */
else
retval = IFS_INODE_NOALLOC; /* its not allocated */
end:
/* Close the buffer and return */
brelse(bp);
return (retval);
}

View File

@ -1,316 +0,0 @@
/*
* Copyright (c) 1999, 2000
* Adrian Chadd <adrian@FreeBSD.org>
*
* 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_vfsops.c 8.31 (Berkeley) 5/20/95
* $FreeBSD$
*/
#include "opt_ffs.h"
#include "opt_quota.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/namei.h>
#include <sys/kernel.h>
#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/conf.h>
#include <sys/fcntl.h>
#include <sys/disklabel.h>
#include <sys/malloc.h>
#include <ufs/ufs/extattr.h>
#include <ufs/ufs/quota.h>
#include <ufs/ufs/ufsmount.h>
#include <ufs/ufs/inode.h>
#include <ufs/ufs/ufs_extern.h>
#include <ufs/ffs/fs.h>
#include <ufs/ffs/ffs_extern.h>
#include <ufs/ifs/ifs_extern.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
static MALLOC_DEFINE(M_IFSNODE, "IFS node", "IFS vnode private part");
static int ifs_init (struct vfsconf *);
static int ifs_mount (struct mount *, char *, caddr_t,
struct nameidata *, struct thread *);
extern int ifs_vget (struct mount *, ino_t, int, struct vnode **);
static struct vfsops ifs_vfsops = {
ifs_mount,
ufs_start,
ffs_unmount,
ufs_root,
ufs_quotactl,
ffs_statfs,
ffs_sync,
ifs_vget,
ffs_fhtovp,
vfs_stdcheckexp,
ffs_vptofh,
ifs_init,
vfs_stduninit,
vfs_stdextattrctl,
};
VFS_SET(ifs_vfsops, ifs, 0);
/*
* ifs_mount
*
* A simple wrapper around ffs_mount - IFS filesystems right now can't
* deal with softupdates so we make sure the user isn't trying to use it.
*/
static int
ifs_mount(mp, path, data, ndp, td)
struct mount *mp;
char *path;
caddr_t data;
struct nameidata *ndp;
struct thread *td;
{
/* Clear the softdep flag */
mp->mnt_flag &= ~MNT_SOFTDEP;
return (ffs_mount(mp, path, data, ndp, td));
}
/*
* Look up a IFS dinode number to find its incore vnode, otherwise read it
* in from disk. If it is in core, wait for the lock bit to clear, then
* return the inode locked. Detection and handling of mount points must be
* done by the calling routine.
*/
static int ifs_inode_hash_lock;
/*
* ifs_inode_hash_lock is a variable to manage mutual exclusion
* of vnode allocation and intertion to the hash, especially to
* avoid holding more than one vnodes for the same inode in the
* hash table. ifs_inode_hash_lock must hence be tested-and-set
* or cleared atomically, accomplished by ifs_inode_hash_mtx.
*
* As vnode allocation may block during MALLOC() and zone
* allocation, we should also do msleep() to give away the CPU
* if anyone else is allocating a vnode. lockmgr is not suitable
* here because someone else may insert to the hash table the
* vnode we are trying to allocate during our sleep, in which
* case the hash table needs to be examined once again after
* waking up.
*/
static struct mtx ifs_inode_hash_mtx;
/*
* Initialize the filesystem; just use ufs_init.
*/
static int
ifs_init(vfsp)
struct vfsconf *vfsp;
{
mtx_init(&ifs_inode_hash_mtx, "ifsvgt", NULL, MTX_DEF);
return (ufs_init(vfsp));
}
int
ifs_vget(mp, ino, flags, vpp)
struct mount *mp;
ino_t ino;
int flags;
struct vnode **vpp;
{
struct fs *fs;
struct inode *ip;
struct ufsmount *ump;
struct buf *bp;
struct vnode *vp;
dev_t dev;
int error, want_wakeup;
ump = VFSTOUFS(mp);
dev = ump->um_dev;
restart:
if ((error = ufs_ihashget(dev, ino, flags, vpp)) != 0)
return (error);
if (*vpp != NULL)
return (0);
/*
* Lock out the creation of new entries in the FFS hash table in
* case getnewvnode() or MALLOC() blocks, otherwise a duplicate
* may occur!
*/
mtx_lock(&ifs_inode_hash_mtx);
if (ifs_inode_hash_lock) {
while (ifs_inode_hash_lock) {
ifs_inode_hash_lock = -1;
msleep(&ifs_inode_hash_lock, &ifs_inode_hash_mtx, PVM, "ifsvgt", 0);
}
mtx_unlock(&ifs_inode_hash_mtx);
goto restart;
}
ifs_inode_hash_lock = 1;
mtx_unlock(&ifs_inode_hash_mtx);
/*
* If this MALLOC() is performed after the getnewvnode()
* it might block, leaving a vnode with a NULL v_data to be
* found by ffs_sync() if a sync happens to fire right then,
* which will cause a panic because ffs_sync() blindly
* dereferences vp->v_data (as well it should).
*/
MALLOC(ip, struct inode *, sizeof(struct inode),
ump->um_malloctype, M_WAITOK);
/* Allocate a new vnode/inode. */
error = getnewvnode(VT_UFS, mp, ifs_vnodeop_p, &vp);
if (error) {
/*
* Do not wake up processes while holding the mutex,
* otherwise the processes waken up immediately hit
* themselves into the mutex.
*/
mtx_lock(&ifs_inode_hash_mtx);
want_wakeup = ifs_inode_hash_lock < 0;
ifs_inode_hash_lock = 0;
mtx_unlock(&ifs_inode_hash_mtx);
if (want_wakeup)
wakeup(&ifs_inode_hash_lock);
*vpp = NULL;
FREE(ip, ump->um_malloctype);
return (error);
}
bzero((caddr_t)ip, sizeof(struct inode));
/*
* IFS supports lock sharing in the stack of vnodes
*/
vp->v_vnlock = &vp->v_lock;
lockinit(vp->v_vnlock, PINOD, "inode", VLKTIMEOUT, LK_CANRECURSE);
vp->v_data = ip;
ip->i_vnode = vp;
ip->i_fs = fs = ump->um_fs;
ip->i_dev = dev;
ip->i_number = ino;
#ifdef QUOTA
{
int i;
for (i = 0; i < MAXQUOTAS; i++)
ip->i_dquot[i] = NODQUOT;
}
#endif
/*
* Put it onto its hash chain and lock it so that other requests for
* this inode will block if they arrive while we are sleeping waiting
* for old data structures to be purged or for the contents of the
* disk portion of this inode to be read.
*/
ufs_ihashins(ip);
/*
* Do not wake up processes while holding the mutex,
* otherwise the processes waken up immediately hit
* themselves into the mutex.
*/
mtx_lock(&ifs_inode_hash_mtx);
want_wakeup = ifs_inode_hash_lock < 0;
ifs_inode_hash_lock = 0;
mtx_unlock(&ifs_inode_hash_mtx);
if (want_wakeup)
wakeup(&ifs_inode_hash_lock);
/* Read in the disk contents for the inode, copy into the inode. */
error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
(int)fs->fs_bsize, NOCRED, &bp);
if (error) {
/*
* The inode does not contain anything useful, so it would
* be misleading to leave it on its hash chain. With mode
* still zero, it will be unlinked and returned to the free
* list by vput().
*/
brelse(bp);
vput(vp);
*vpp = NULL;
return (error);
}
ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino));
if (DOINGSOFTDEP(vp))
softdep_load_inodeblock(ip);
else
ip->i_effnlink = ip->i_nlink;
bqrelse(bp);
/*
* Initialize the vnode from the inode, check for aliases.
* Note that the underlying vnode may have changed.
*/
error = ufs_vinit(mp, ifs_specop_p, ifs_fifoop_p, &vp);
if (error) {
vput(vp);
*vpp = NULL;
return (error);
}
/*
* Finish inode initialization now that aliasing has been resolved.
*/
ip->i_devvp = ump->um_devvp;
VREF(ip->i_devvp);
/*
* Set up a generation number for this inode if it does not
* already have one. This should only happen on old filesystems.
*/
if (ip->i_gen == 0) {
ip->i_gen = random() / 2 + 1;
if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
ip->i_flag |= IN_MODIFIED;
}
/*
* Ensure that uid and gid are correct. This is a temporary
* fix until fsck has been changed to do the update.
*/
if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
ip->i_uid = ip->i_din.di_ouid; /* XXX */
ip->i_gid = ip->i_din.di_ogid; /* XXX */
} /* XXX */
*vpp = vp;
return (0);
}

View File

@ -1,469 +0,0 @@
/*
* Copyright (c) 1999, 2000
* Adrian Chadd <adrian@FreeBSD.org>
*
* 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_vnops.c 8.15 (Berkeley) 5/14/95
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/resourcevar.h>
#include <sys/signalvar.h>
#include <sys/kernel.h>
#include <sys/stat.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/proc.h>
#include <sys/mount.h>
#include <sys/vnode.h>
#include <sys/conf.h>
#include <sys/poll.h>
#include <sys/namei.h>
#include <sys/malloc.h>
#include <sys/dirent.h>
#include <machine/limits.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <vm/vm_object.h>
#include <vm/vm_extern.h>
#include <vm/uma.h>
#include <ufs/ufs/extattr.h>
#include <ufs/ufs/quota.h>
#include <ufs/ufs/inode.h>
#include <ufs/ufs/ufsmount.h>
#include <ufs/ufs/ufs_extern.h>
#include <ufs/ufs/dir.h>
#include <ufs/ffs/fs.h>
#include <ufs/ffs/ffs_extern.h>
#include <ufs/ifs/ifs_extern.h>
/* IFS debugging */
#undef DEBUG_IFS_READDIR
/* Declare our trampling into the FFS code */
extern int ffs_fsync (struct vop_fsync_args *);
static int ffs_getpages(struct vop_getpages_args *);
static int ffs_read(struct vop_read_args *);
static int ffs_write(struct vop_write_args *);
static int ifs_noop(struct vop_generic_args *);
static int ifs_getattr(struct vop_getattr_args *);
static int ifs_create(struct vop_create_args *);
static int ifs_makeinode(int mode, struct vnode *, struct vnode **,
struct componentname *);
static int ifs_remove(struct vop_remove_args *);
static int ifs_readdir(struct vop_readdir_args *);
static int ifs_dirremove(struct vnode *, struct inode *, int, int);
/* Global vfs data structures for ifs. */
vop_t **ifs_vnodeop_p;
static struct vnodeopv_entry_desc ifs_vnodeop_entries[] = {
{ &vop_default_desc, (vop_t *) ufs_vnoperate },
{ &vop_fsync_desc, (vop_t *) ffs_fsync },
{ &vop_getpages_desc, (vop_t *) ffs_getpages },
{ &vop_read_desc, (vop_t *) ffs_read },
{ &vop_reallocblks_desc, (vop_t *) ffs_reallocblks },
{ &vop_write_desc, (vop_t *) ffs_write },
{ &vop_lookup_desc, (vop_t *) ifs_lookup },
{ &vop_getattr_desc, (vop_t *) ifs_getattr },
{ &vop_create_desc, (vop_t *) ifs_create },
{ &vop_remove_desc, (vop_t *) ifs_remove },
{ &vop_readdir_desc, (vop_t *) ifs_readdir },
/* NULL operations for ifs */
{ &vop_cachedlookup_desc, (vop_t *) ifs_noop },
{ &vop_mkdir_desc, (vop_t *) ifs_noop },
{ &vop_mknod_desc, (vop_t *) ifs_noop },
{ &vop_readlink_desc, (vop_t *) ifs_noop },
{ &vop_rename_desc, (vop_t *) ifs_noop },
{ &vop_rmdir_desc, (vop_t *) ifs_noop },
{ &vop_symlink_desc, (vop_t *) ifs_noop },
{ &vop_link_desc, (vop_t *) ifs_noop },
{ &vop_whiteout_desc, (vop_t *) ifs_noop },
{ NULL, NULL }
};
static struct vnodeopv_desc ifs_vnodeop_opv_desc =
{ &ifs_vnodeop_p, ifs_vnodeop_entries };
vop_t **ifs_specop_p;
static struct vnodeopv_entry_desc ifs_specop_entries[] = {
{ &vop_default_desc, (vop_t *) ufs_vnoperatespec },
{ &vop_fsync_desc, (vop_t *) ffs_fsync },
{ NULL, NULL }
};
static struct vnodeopv_desc ifs_specop_opv_desc =
{ &ifs_specop_p, ifs_specop_entries };
vop_t **ifs_fifoop_p;
static struct vnodeopv_entry_desc ifs_fifoop_entries[] = {
{ &vop_default_desc, (vop_t *) ufs_vnoperatefifo },
{ &vop_fsync_desc, (vop_t *) ffs_fsync },
{ NULL, NULL }
};
static struct vnodeopv_desc ifs_fifoop_opv_desc =
{ &ifs_fifoop_p, ifs_fifoop_entries };
VNODEOP_SET(ifs_vnodeop_opv_desc);
VNODEOP_SET(ifs_specop_opv_desc);
VNODEOP_SET(ifs_fifoop_opv_desc);
#include <ufs/ufs/ufs_readwrite.c>
static int
ifs_noop(ap)
struct vop_generic_args *ap;
{
return EOPNOTSUPP;
}
/* ARGSUSED */
static int
ifs_getattr(ap)
struct vop_getattr_args /* {
struct vnode *a_vp;
struct vattr *a_vap;
struct ucred *a_cred;
struct proc *a_p;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
struct inode *ip = VTOI(vp);
struct vattr *vap = ap->a_vap;
ufs_itimes(vp);
/*
* Copy from inode table
*/
vap->va_fsid = dev2udev(ip->i_dev);
vap->va_fileid = ip->i_number;
vap->va_mode = ip->i_mode & ~IFMT;
vap->va_nlink = ip->i_effnlink;
vap->va_uid = ip->i_uid;
vap->va_gid = ip->i_gid;
vap->va_rdev = ip->i_rdev;
vap->va_size = ip->i_din.di_size;
vap->va_atime.tv_sec = ip->i_atime;
vap->va_atime.tv_nsec = ip->i_atimensec;
vap->va_mtime.tv_sec = ip->i_mtime;
vap->va_mtime.tv_nsec = ip->i_mtimensec;
vap->va_ctime.tv_sec = ip->i_ctime;
vap->va_ctime.tv_nsec = ip->i_ctimensec;
vap->va_flags = ip->i_flags;
vap->va_gen = ip->i_gen;
vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
vap->va_bytes = dbtob((u_quad_t)ip->i_blocks);
vap->va_type = IFTOVT(ip->i_mode);
vap->va_filerev = ip->i_modrev;
return (0);
}
/*
* Create a regular file
*/
int
ifs_create(ap)
struct vop_create_args /* {
struct vnode *a_dvp;
struct vnode **a_vpp;
struct componentname *a_cnp;
struct vattr *a_vap;
} */ *ap;
{
int error;
error =
ifs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
ap->a_dvp, ap->a_vpp, ap->a_cnp);
if (error)
return (error);
VN_KNOTE(ap->a_dvp, NOTE_WRITE);
return (0);
}
/*
* Allocate a new inode.
*/
int
ifs_makeinode(mode, dvp, vpp, cnp)
int mode;
struct vnode *dvp;
struct vnode **vpp;
struct componentname *cnp;
{
struct inode *ip, *pdir;
struct vnode *tvp;
int error;
pdir = VTOI(dvp);
#ifdef DIAGNOSTIC
if ((cnp->cn_flags & HASBUF) == 0)
panic("ifs_makeinode: no name");
#endif
*vpp = NULL;
if ((mode & IFMT) == 0)
mode |= IFREG;
error = UFS_VALLOC(dvp, mode, cnp->cn_cred, &tvp);
if (error) {
uma_zfree(namei_zone, cnp->cn_pnbuf);
return (error);
}
ip = VTOI(tvp);
ip->i_gid = pdir->i_gid;
ip->i_uid = cnp->cn_cred->cr_uid;
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, cnp->cn_cred, 0))) {
UFS_VFREE(tvp, ip->i_number, mode);
vput(tvp);
return (error);
}
#endif
ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
ip->i_mode = mode;
tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */
ip->i_effnlink = 1;
ip->i_nlink = 1;
if (DOINGSOFTDEP(tvp))
softdep_change_linkcnt(ip);
if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) &&
suser_cred(cnp->cn_cred, 0))
ip->i_mode &= ~ISGID;
if (cnp->cn_flags & ISWHITEOUT)
ip->i_flags |= UF_OPAQUE;
/*
* Make sure inode goes to disk before directory entry.
*/
error = UFS_UPDATE(tvp, !(DOINGSOFTDEP(tvp) | DOINGASYNC(tvp)));
if (error)
goto bad;
*vpp = tvp;
return (0);
bad:
/*
* Write error occurred trying to update the inode
* or the directory so must deallocate the inode.
*/
ip->i_effnlink = 0;
ip->i_nlink = 0;
ip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(tvp))
softdep_change_linkcnt(ip);
vput(tvp);
return (error);
}
int
ifs_remove(ap)
struct vop_remove_args /* {
struct vnode *a_dvp;
struct vnode *a_vp;
struct componentname *a_cnp;
} */ *ap;
{
struct inode *ip;
struct vnode *vp = ap->a_vp;
struct vnode *dvp = ap->a_dvp;
int error;
ip = VTOI(vp);
if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
(VTOI(dvp)->i_flags & APPEND))
return (EPERM);
error = ifs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0);
if (error == 0) {
VN_KNOTE(vp, NOTE_DELETE);
VN_KNOTE(dvp, NOTE_WRITE);
}
return (error);
}
/*
* highly cutdown ufs_dirremove, since we're not updating
* any directory entries. :-)
*/
static int
ifs_dirremove(struct vnode *dvp, struct inode *ip, int flags, int isrmdir)
{
int error;
if (ip) {
ip->i_effnlink--;
ip->i_flag |= IN_CHANGE;
ip->i_nlink--;
error = 0;
} else
error = ENOENT;
return (error);
}
/*
* ifs_readdir
*
* Do the directory listing, representing the allocated inodes
* making up this filesystem.
*
*/
static int
ifs_readdir(ap)
struct vop_readdir_args /* {
struct vnode *a_vp;
struct uio *a_uio;
struct ucred *a_cred;
int *a_eofflag;
int *ncookies;
u_long **a_cookies;
} */ *ap;
{
int inodenum;
struct dirent *dent, *lastdp = NULL;
struct dirent *tmpdp;
char *dirbuf;
struct inode *ip = VTOI(ap->a_vp); /* To get the mount info later */
struct mount *mp = ap->a_vp->v_mount;
struct fs *fs = VFSTOUFS(mp)->um_fs;
int maxnuminode = fs->fs_ncg * fs->fs_ipg;
int error = 0;
int count;
int dircount = 0;
int copylen = 0;
char iret;
/*
* Get the offset, which represents the inode we're going to
* start from
*/
inodenum = ap->a_uio->uio_offset;
#ifdef DEBUG_IFS_READDIR
printf("ifs_readdir: starting with inode %d\n", inodenum);
#endif
if (inodenum < 0)
return EINVAL;
/*
* Next, get the buffer size, round it down to a dirent, and
* figure out how many allocated inodes we need to match
*/
count = ap->a_uio->uio_resid;
/*
* Next, create a dirbuf to fill with directory entries
*/
MALLOC(tmpdp, struct dirent *, sizeof (struct dirent), M_TEMP, M_WAITOK);
MALLOC(dirbuf, char *, count, M_TEMP, M_WAITOK);
dent = (struct dirent *)dirbuf;
/* now, keep reading until we run out of inodes */
while (inodenum <= maxnuminode) {
/* Get bitmap info and see if we bother with this cg */
iret = ifs_isinodealloc(ip, inodenum);
if (iret == IFS_INODE_EMPTYCG) {
/* Skip this CG */
/* Next cg please */
inodenum -= inodenum % fs->fs_ipg;
inodenum += fs->fs_ipg;
continue;
}
/* Allocated and not special? */
if ((inodenum > 2) && iret == IFS_INODE_ISALLOC) {
/* Create a new entry */
sprintf(tmpdp->d_name, "%d", inodenum);
tmpdp->d_fileno = inodenum;
tmpdp->d_type = DT_REG;
tmpdp->d_namlen = strlen(tmpdp->d_name);
tmpdp->d_reclen = DIRECTSIZ(tmpdp->d_namlen);
/* Make sure we have enough space for this entry */
if (tmpdp->d_reclen > count)
break;
/* Copy it to the given buffer */
bcopy(tmpdp, dent, tmpdp->d_reclen);
/* Decrement the count */
count -= dent->d_reclen;
copylen += dent->d_reclen;
lastdp = dent;
/* Increment the offset pointer */
dent = (struct dirent *)((char *)dent + dent->d_reclen);
dircount++;
}
/* Increment the inode number we are checking */
inodenum++;
}
/* End */
#ifdef DEBUG_IFS_READDIR
printf("ifs_readdir: copied %d directories\n", dircount);
#endif
/*
* Get the last dent updated, and make the record d_reclen last the whole
* buffer.
*/
if (lastdp != NULL) {
/* Update the length of the last entry */
lastdp->d_reclen += count;
}
/* Copy the data out */
#ifdef DEBUG_IFS_READDIR
printf("ifs_readdir: copied %d bytes\n", copylen);
#endif
error = uiomove(dirbuf, copylen, ap->a_uio);
/* Free memory we've used */
FREE(dirbuf, M_TEMP);
FREE(tmpdp, M_TEMP);
/* Set uio_offset to the last inode number */
ap->a_uio->uio_offset = inodenum;
/* Handle EOF/eofflag */
if ((inodenum >= maxnuminode) && (ap->a_eofflag != NULL)) {
*ap->a_eofflag = 1;
#ifdef DEBUG_IFS_READDIR
printf("ifs_readdir: setting EOF flag\n");
#endif
}
#ifdef DEBUG_IFS_READDIR
printf("ifs_readdir: new offset: %d\n", inodenum);
#endif
return error;
}