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:
parent
8b1febe499
commit
2bab796d96
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>
|
@ -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 */
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user