aboutsummaryrefslogtreecommitdiff
path: root/sys/gnu/ext2fs
diff options
context:
space:
mode:
authorIan Dowse <iedowse@FreeBSD.org>2002-05-16 19:08:03 +0000
committerIan Dowse <iedowse@FreeBSD.org>2002-05-16 19:08:03 +0000
commit9504abaad76b5fa631ac0eb7a59d107332189fbd (patch)
tree90aeb827be217019fb5a2b0c03ee96df99127d25 /sys/gnu/ext2fs
parentd99142426b33e21bc9344fa772e582fad9380164 (diff)
downloadsrc-9504abaad76b5fa631ac0eb7a59d107332189fbd.tar.gz
src-9504abaad76b5fa631ac0eb7a59d107332189fbd.zip
Complete the separation of ext2fs from ufs by copying the remaining
shared code and converting all ufs references. Originally it may have made sense to share common features between the two filesystems, but recently it has only caused problems, the UFS2 work being the final straw. All UFS_* indirect calls are now direct calls to ext2_* functions, and ext2fs-specific mount and inode structures have been introduced.
Notes
Notes: svn path=/head/; revision=96749
Diffstat (limited to 'sys/gnu/ext2fs')
-rw-r--r--sys/gnu/ext2fs/ext2_alloc.c26
-rw-r--r--sys/gnu/ext2fs/ext2_balloc.c9
-rw-r--r--sys/gnu/ext2fs/ext2_extern.h29
-rw-r--r--sys/gnu/ext2fs/ext2_fs.h23
-rw-r--r--sys/gnu/ext2fs/ext2_inode.c118
-rw-r--r--sys/gnu/ext2fs/ext2_inode_cnv.c151
-rw-r--r--sys/gnu/ext2fs/ext2_linux_balloc.c45
-rw-r--r--sys/gnu/ext2fs/ext2_linux_ialloc.c22
-rw-r--r--sys/gnu/ext2fs/ext2_lookup.c49
-rw-r--r--sys/gnu/ext2fs/ext2_readwrite.c4
-rw-r--r--sys/gnu/ext2fs/ext2_subr.c6
-rw-r--r--sys/gnu/ext2fs/ext2_vfsops.c193
-rw-r--r--sys/gnu/ext2fs/ext2_vnops.c1114
-rw-r--r--sys/gnu/ext2fs/fs.h2
14 files changed, 1342 insertions, 449 deletions
diff --git a/sys/gnu/ext2fs/ext2_alloc.c b/sys/gnu/ext2fs/ext2_alloc.c
index b9c40d37b9e1..585c5cdb4632 100644
--- a/sys/gnu/ext2fs/ext2_alloc.c
+++ b/sys/gnu/ext2fs/ext2_alloc.c
@@ -40,8 +40,6 @@
* $FreeBSD$
*/
-#include "opt_quota.h"
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
@@ -50,11 +48,8 @@
#include <sys/mount.h>
#include <sys/syslog.h>
-#include <ufs/ufs/extattr.h>
-#include <ufs/ufs/quota.h>
-#include <ufs/ufs/inode.h>
-#include <ufs/ufs/ufsmount.h>
-
+#include <gnu/ext2fs/inode.h>
+#include <gnu/ext2fs/ext2_mount.h>
#include <gnu/ext2fs/ext2_fs.h>
#include <gnu/ext2fs/ext2_fs_sb.h>
#include <gnu/ext2fs/fs.h>
@@ -108,9 +103,6 @@ ext2_alloc(ip, lbn, bpref, size, cred, bnp)
{
register struct ext2_sb_info *fs;
daddr_t bno;
-#if QUOTA
- int error;
-#endif
*bnp = 0;
fs = ip->i_e2fs;
@@ -128,10 +120,6 @@ ext2_alloc(ip, lbn, bpref, size, cred, bnp)
if (cred->cr_uid != 0 &&
fs->s_es->s_free_blocks_count < fs->s_es->s_r_blocks_count)
goto nospace;
-#if QUOTA
- if ((error = chkdq(ip, (long)btodb(size), cred, 0)) != 0)
- return (error);
-#endif
if (bpref >= fs->s_es->s_blocks_count)
bpref = 0;
/* call the Linux code */
@@ -179,12 +167,6 @@ ext2_alloc(ip, lbn, bpref, size, cred, bnp)
*bnp = bno;
return (0);
}
-#if QUOTA
- /*
- * Restore user's disk quota because allocation failed.
- */
- (void) chkdq(ip, (long)-btodb(size), cred, FORCE);
-#endif
nospace:
ext2_fserr(fs, cred->cr_uid, "file system full");
uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt);
@@ -342,7 +324,7 @@ return ENOSPC;
} else {
ip->i_flag |= IN_CHANGE | IN_UPDATE;
if (!doasyncfree)
- UFS_UPDATE(vp, 1);
+ ext2_update(vp, 1);
}
if (ssize < len)
if (doasyncfree)
@@ -401,7 +383,7 @@ ext2_valloc(pvp, mode, cred, vpp)
goto noinodes;
error = VFS_VGET(pvp->v_mount, ino, LK_EXCLUSIVE, vpp);
if (error) {
- UFS_VFREE(pvp, ino, mode);
+ ext2_vfree(pvp, ino, mode);
return (error);
}
ip = VTOI(*vpp);
diff --git a/sys/gnu/ext2fs/ext2_balloc.c b/sys/gnu/ext2fs/ext2_balloc.c
index 275849fcec52..252a29792527 100644
--- a/sys/gnu/ext2fs/ext2_balloc.c
+++ b/sys/gnu/ext2fs/ext2_balloc.c
@@ -48,10 +48,7 @@
#include <sys/ucred.h>
#include <sys/vnode.h>
-#include <ufs/ufs/quota.h>
-#include <ufs/ufs/inode.h>
-#include <ufs/ufs/ufs_extern.h>
-
+#include <gnu/ext2fs/inode.h>
#include <gnu/ext2fs/ext2_fs.h>
#include <gnu/ext2fs/ext2_fs_sb.h>
#include <gnu/ext2fs/fs.h>
@@ -164,11 +161,11 @@ ext2_debug("ext2_balloc called (%d, %d, %d)\n",
* Determine the number of levels of indirection.
*/
pref = 0;
- if ((error = ufs_getlbns(vp, bn, indirs, &num)) != 0)
+ if ((error = ext2_getlbns(vp, bn, indirs, &num)) != 0)
return(error);
#if DIAGNOSTIC
if (num < 1)
- panic ("ext2_balloc: ufs_getlbns returned indirect block");
+ panic ("ext2_balloc: ext2_getlbns returned indirect block");
#endif
/*
* Fetch the first indirect block allocating if necessary.
diff --git a/sys/gnu/ext2fs/ext2_extern.h b/sys/gnu/ext2fs/ext2_extern.h
index 8df829b369a7..505fefd97c56 100644
--- a/sys/gnu/ext2fs/ext2_extern.h
+++ b/sys/gnu/ext2fs/ext2_extern.h
@@ -43,8 +43,8 @@
#ifndef _SYS_GNU_EXT2FS_EXT2_EXTERN_H_
#define _SYS_GNU_EXT2FS_EXT2_EXTERN_H_
-struct dinode;
struct ext2_inode;
+struct indir;
struct inode;
struct mount;
struct vfsconf;
@@ -58,7 +58,18 @@ int ext2_blkatoff(struct vnode *, off_t, char **, struct buf **);
void ext2_blkfree(struct inode *, daddr_t, long);
daddr_t ext2_blkpref(struct inode *, daddr_t, int, daddr_t *, daddr_t);
int ext2_bmap(struct vop_bmap_args *);
-int ext2_init(struct vfsconf *);
+int ext2_bmaparray(struct vnode *, daddr_t, daddr_t *, int *, int *);
+void ext2_dirbad(struct inode *ip, doff_t offset, char *how);
+void ext2_ei2i(struct ext2_inode *, struct inode *);
+int ext2_getlbns(struct vnode *, daddr_t, struct indir *, int *);
+void ext2_i2ei(struct inode *, struct ext2_inode *);
+int ext2_ihashget(dev_t, ino_t, int, struct vnode **);
+void ext2_ihashinit(void);
+void ext2_ihashins(struct inode *);
+struct vnode *
+ ext2_ihashlookup(dev_t, ino_t);
+void ext2_ihashrem(struct inode *);
+void ext2_itimes(struct vnode *vp);
int ext2_reallocblks(struct vop_reallocblks_args *);
int ext2_reclaim(struct vop_reclaim_args *);
void ext2_setblock(struct ext2_sb_info *, u_char *, daddr_t);
@@ -66,9 +77,9 @@ int ext2_truncate(struct vnode *, off_t, int, struct ucred *, struct thread *);
int ext2_update(struct vnode *, int);
int ext2_valloc(struct vnode *, int, struct ucred *, struct vnode **);
int ext2_vfree(struct vnode *, ino_t, int);
+int ext2_vinit(struct mount *, vop_t **, vop_t **, struct vnode **vpp);
int ext2_lookup(struct vop_cachedlookup_args *);
int ext2_readdir(struct vop_readdir_args *);
-void ext2_print_dinode(struct dinode *);
void ext2_print_inode(struct inode *);
int ext2_direnter(struct inode *,
struct vnode *, struct componentname *);
@@ -89,15 +100,13 @@ unsigned long ext2_count_free(struct buf *map, unsigned int numchars);
void ext2_free_blocks(struct mount *mp, unsigned long block,
unsigned long count);
void ext2_free_inode(struct inode * inode);
-void ext2_ei2di(struct ext2_inode *ei, struct dinode *di);
-void ext2_di2ei(struct dinode *di, struct ext2_inode *ei);
void mark_buffer_dirty(struct buf *bh);
-/*
- * This macro allows the ufs code to distinguish between an EXT2 and a
- * non-ext2(FFS/LFS) vnode.
- */
-#define IS_EXT2_VNODE(vp) (vp->v_mount->mnt_stat.f_type == MOUNT_EXT2FS)
+/* Flags to low-level allocation routines. */
+#define B_CLRBUF 0x01 /* Request allocated buffer be cleared. */
+#define B_SYNC 0x02 /* Do all allocations synchronously. */
+#define B_METAONLY 0x04 /* Return indirect block buffer. */
+#define B_NOWAIT 0x08 /* do not sleep to await lock */
extern vop_t **ext2_vnodeop_p;
extern vop_t **ext2_specop_p;
diff --git a/sys/gnu/ext2fs/ext2_fs.h b/sys/gnu/ext2fs/ext2_fs.h
index b5e9f4a92573..29435937181b 100644
--- a/sys/gnu/ext2fs/ext2_fs.h
+++ b/sys/gnu/ext2fs/ext2_fs.h
@@ -38,19 +38,6 @@
#define umode_t mode_t
#define loff_t off_t
-/* the Linux implementation of EXT2 stores some information about
- * an inode in a ext2_inode_info structure which is part of the incore
- * inode in Linux
- * I decided to use the "spare" fields instead - we'll see how this
- * works out
- */
-
-#define i_block_group i_spare[0]
-#define i_next_alloc_block i_spare[1]
-#define i_next_alloc_goal i_spare[2]
-#define i_prealloc_block i_din.di_spare[0]
-#define i_prealloc_count i_din.di_spare[1]
-
/*
* The second extended filesystem constants/structures
*/
@@ -264,14 +251,6 @@ struct ext2_group_desc
#define EXT2_IOC_SETVERSION _IOW('v', 2, long)
/*
- * Only declare `struct ext2_inode' if <ufs/ufs/inode.h> hasn't made things
- * difficult by #defining i_mode and other struct members. The details of
- * the struct are only needed in ext2_inode_cnv.c where the ext2fs on-disk
- * inode is converted to a ufs in-core inode.
- */
-#ifndef i_mode
-
-/*
* Structure of an inode on the disk
*/
struct ext2_inode {
@@ -351,8 +330,6 @@ struct ext2_inode {
#define i_reserved2 osd2.masix2.m_i_reserved2
#endif
-#endif /* i_mode */
-
/*
* File system states
*/
diff --git a/sys/gnu/ext2fs/ext2_inode.c b/sys/gnu/ext2fs/ext2_inode.c
index 2f0aed472f09..207778c84f88 100644
--- a/sys/gnu/ext2fs/ext2_inode.c
+++ b/sys/gnu/ext2fs/ext2_inode.c
@@ -40,8 +40,6 @@
* $FreeBSD$
*/
-#include "opt_quota.h"
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mount.h>
@@ -53,12 +51,8 @@
#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/ufsmount.h>
-#include <ufs/ufs/ufs_extern.h>
-
+#include <gnu/ext2fs/inode.h>
+#include <gnu/ext2fs/ext2_mount.h>
#include <gnu/ext2fs/ext2_fs.h>
#include <gnu/ext2fs/ext2_fs_sb.h>
#include <gnu/ext2fs/fs.h>
@@ -67,12 +61,6 @@
static int ext2_indirtrunc(struct inode *, daddr_t, daddr_t, daddr_t, int,
long *);
-int
-ext2_init(struct vfsconf *vfsp)
-{
- return (ufs_init(vfsp));
-}
-
/*
* Update the access, modified, and inode change times as specified by the
* IN_ACCESS, IN_UPDATE, and IN_CHANGE flags respectively. Write the inode
@@ -92,7 +80,7 @@ ext2_update(vp, waitfor)
struct inode *ip;
int error;
- ufs_itimes(vp);
+ ext2_itimes(vp);
ip = VTOI(vp);
if ((ip->i_flag & IN_MODIFIED) == 0)
return (0);
@@ -106,8 +94,8 @@ ext2_update(vp, waitfor)
brelse(bp);
return (error);
}
- ext2_di2ei( &ip->i_din, (struct ext2_inode *) ((char *)bp->b_data + EXT2_INODE_SIZE *
- ino_to_fsbo(fs, ip->i_number)));
+ ext2_i2ei(ip, (struct ext2_inode *)((char *)bp->b_data +
+ EXT2_INODE_SIZE * ino_to_fsbo(fs, ip->i_number)));
/*
if (waitfor && (vp->v_mount->mnt_flag & MNT_ASYNC) == 0)
return (bwrite(bp));
@@ -166,16 +154,12 @@ printf("ext2_truncate called %d to %d\n", VTOI(ovp)->i_number, length);
bzero((char *)&oip->i_shortlink, (u_int)oip->i_size);
oip->i_size = 0;
oip->i_flag |= IN_CHANGE | IN_UPDATE;
- return (UFS_UPDATE(ovp, 1));
+ return (ext2_update(ovp, 1));
}
if (oip->i_size == length) {
oip->i_flag |= IN_CHANGE | IN_UPDATE;
- return (UFS_UPDATE(ovp, 0));
+ return (ext2_update(ovp, 0));
}
-#if QUOTA
- if ((error = getinoquota(oip)) != 0)
- return (error);
-#endif
fs = oip->i_e2fs;
osize = oip->i_size;
ext2_discard_prealloc(oip);
@@ -200,7 +184,7 @@ printf("ext2_truncate called %d to %d\n", VTOI(ovp)->i_number, length);
else
bawrite(bp);
oip->i_flag |= IN_CHANGE | IN_UPDATE;
- return (UFS_UPDATE(ovp, 1));
+ return (ext2_update(ovp, 1));
}
/*
* Shorten the size of the file. If the file is not being
@@ -256,7 +240,7 @@ printf("ext2_truncate called %d to %d\n", VTOI(ovp)->i_number, length);
for (i = NDADDR - 1; i > lastblock; i--)
oip->i_db[i] = 0;
oip->i_flag |= IN_CHANGE | IN_UPDATE;
- allerror = UFS_UPDATE(ovp, 1);
+ allerror = ext2_update(ovp, 1);
/*
* Having written the new inode to disk, save its new configuration
@@ -361,9 +345,6 @@ done:
oip->i_blocks = 0;
oip->i_flag |= IN_CHANGE;
vnode_pager_setsize(ovp, length);
-#if QUOTA
- (void) chkdq(oip, -blocksreleased, NOCRED, 0);
-#endif
return (allerror);
}
@@ -488,9 +469,86 @@ int
ext2_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct thread *a_td;
} */ *ap;
{
- ext2_discard_prealloc(VTOI(ap->a_vp));
- return ufs_inactive(ap);
+ struct vnode *vp = ap->a_vp;
+ struct inode *ip = VTOI(vp);
+ struct thread *td = ap->a_td;
+ int mode, error = 0;
+
+ ext2_discard_prealloc(ip);
+ if (prtactive && vp->v_usecount != 0)
+ vprint("ext2_inactive: pushing active", vp);
+
+ /*
+ * Ignore inodes related to stale file handles.
+ */
+ if (ip->i_mode == 0)
+ goto out;
+ if (ip->i_nlink <= 0) {
+ (void) vn_write_suspend_wait(vp, NULL, V_WAIT);
+ error = ext2_truncate(vp, (off_t)0, 0, NOCRED, td);
+ ip->i_rdev = 0;
+ mode = ip->i_mode;
+ ip->i_mode = 0;
+ ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ ext2_vfree(vp, ip->i_number, mode);
+ }
+ if (ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) {
+ if ((ip->i_flag & (IN_CHANGE | IN_UPDATE | IN_MODIFIED)) == 0 &&
+ vn_write_suspend_wait(vp, NULL, V_NOWAIT)) {
+ ip->i_flag &= ~IN_ACCESS;
+ } else {
+ (void) vn_write_suspend_wait(vp, NULL, V_WAIT);
+ ext2_update(vp, 0);
+ }
+ }
+out:
+ VOP_UNLOCK(vp, 0, td);
+ /*
+ * If we are done with the inode, reclaim it
+ * so that it can be reused immediately.
+ */
+ if (ip->i_mode == 0)
+ vrecycle(vp, NULL, td);
+ return (error);
}
+/*
+ * Reclaim an inode so that it can be used for other purposes.
+ */
+int
+ext2_reclaim(ap)
+ struct vop_reclaim_args /* {
+ struct vnode *a_vp;
+ struct thread *a_td;
+ } */ *ap;
+{
+ struct inode *ip;
+ struct vnode *vp = ap->a_vp;
+
+ if (prtactive && vp->v_usecount != 0)
+ vprint("ufs_reclaim: pushing active", vp);
+ ip = VTOI(vp);
+ if (ip->i_flag & IN_LAZYMOD) {
+ ip->i_flag |= IN_MODIFIED;
+ ext2_update(vp, 0);
+ }
+ /*
+ * Remove the inode from its hash chain.
+ */
+ ext2_ihashrem(ip);
+ /*
+ * Purge old data structures associated with the inode.
+ */
+ cache_purge(vp);
+ if (ip->i_devvp) {
+ vrele(ip->i_devvp);
+ ip->i_devvp = 0;
+ }
+ lockdestroy(&vp->v_lock);
+ FREE(vp->v_data, M_EXT2NODE);
+ vp->v_data = 0;
+ return (0);
+}
diff --git a/sys/gnu/ext2fs/ext2_inode_cnv.c b/sys/gnu/ext2fs/ext2_inode_cnv.c
index 3e8e0ff73445..d64e5498776b 100644
--- a/sys/gnu/ext2fs/ext2_inode_cnv.c
+++ b/sys/gnu/ext2fs/ext2_inode_cnv.c
@@ -23,7 +23,7 @@
*/
/*
- * routines to convert on disk ext2 inodes in dinodes and back
+ * routines to convert on disk ext2 inodes into inodes and back
*/
#include <sys/param.h>
#include <sys/systm.h>
@@ -31,130 +31,101 @@
#include <sys/stat.h>
#include <sys/vnode.h>
-#include <ufs/ufs/quota.h>
-#include <ufs/ufs/inode.h>
-
-/*
- * Undo the definitions in <ufs/ufs/inode.h> that would destroy the include
- * of <gnu/ext2fs/ext2_fs.h>.
- */
-#undef i_atime
-#undef i_blocks
-#undef i_ctime
-#undef i_db
-#undef i_flags
-#undef i_gen
-#undef i_gid
-#undef i_ib
-#undef i_mode
-#undef i_mtime
-#undef i_nlink
-#undef i_rdev
-#undef i_shortlink
-#undef i_size
-#undef i_uid
-
+#include <gnu/ext2fs/inode.h>
#include <gnu/ext2fs/ext2_fs.h>
#include <gnu/ext2fs/ext2_extern.h>
void
-ext2_print_dinode( di )
- struct dinode *di;
+ext2_print_inode( in )
+ struct inode *in;
{
int i;
+
+ printf( "Inode: %5d", in->i_number);
printf( /* "Inode: %5d" */
" Type: %10s Mode: 0x%o Flags: 0x%x Version: %d\n",
- "n/a", di->di_mode, di->di_flags, di->di_gen);
+ "n/a", in->i_mode, in->i_flags, in->i_gen);
printf( "User: %5lu Group: %5lu Size: %lu\n",
- (unsigned long)di->di_uid, (unsigned long)di->di_gid,
- (unsigned long)di->di_size);
+ (unsigned long)in->i_uid, (unsigned long)in->i_gid,
+ (unsigned long)in->i_size);
printf( "Links: %3d Blockcount: %d\n",
- di->di_nlink, di->di_blocks);
- printf( "ctime: 0x%x", di->di_ctime);
- printf( "atime: 0x%x", di->di_atime);
- printf( "mtime: 0x%x", di->di_mtime);
+ in->i_nlink, in->i_blocks);
+ printf( "ctime: 0x%x", in->i_ctime);
+ printf( "atime: 0x%x", in->i_atime);
+ printf( "mtime: 0x%x", in->i_mtime);
printf( "BLOCKS: ");
- for(i=0; i < (di->di_blocks <= 24 ? ((di->di_blocks+1)/2): 12); i++)
- printf("%d ", di->di_db[i]);
+ for(i=0; i < (in->i_blocks <= 24 ? ((in->i_blocks+1)/2): 12); i++)
+ printf("%d ", in->i_db[i]);
printf("\n");
}
-void
-ext2_print_inode( in )
- struct inode *in;
-{
- printf( "Inode: %5d", in->i_number);
- ext2_print_dinode(&in->i_din);
-}
-
/*
- * raw ext2 inode to dinode
+ * raw ext2 inode to inode
*/
void
-ext2_ei2di(ei, di)
- struct ext2_inode *ei;
- struct dinode *di;
+ext2_ei2i(ei, ip)
+ struct ext2_inode *ei;
+ struct inode *ip;
{
- int i;
+ int i;
- di->di_nlink = ei->i_links_count;
+ ip->i_nlink = ei->i_links_count;
/* Godmar thinks - if the link count is zero, then the inode is
unused - according to ext2 standards. Ufs marks this fact
by setting i_mode to zero - why ?
I can see that this might lead to problems in an undelete.
*/
- di->di_mode = ei->i_links_count ? ei->i_mode : 0;
- di->di_size = ei->i_size;
- di->di_atime = ei->i_atime;
- di->di_mtime = ei->i_mtime;
- di->di_ctime = ei->i_ctime;
- di->di_flags = 0;
- di->di_flags |= (ei->i_flags & EXT2_APPEND_FL) ? APPEND : 0;
- di->di_flags |= (ei->i_flags & EXT2_IMMUTABLE_FL) ? IMMUTABLE : 0;
- di->di_blocks = ei->i_blocks;
- di->di_gen = ei->i_generation;
- di->di_uid = ei->i_uid;
- di->di_gid = ei->i_gid;
+ ip->i_mode = ei->i_links_count ? ei->i_mode : 0;
+ ip->i_size = ei->i_size;
+ ip->i_atime = ei->i_atime;
+ ip->i_mtime = ei->i_mtime;
+ ip->i_ctime = ei->i_ctime;
+ ip->i_flags = 0;
+ ip->i_flags |= (ei->i_flags & EXT2_APPEND_FL) ? APPEND : 0;
+ ip->i_flags |= (ei->i_flags & EXT2_IMMUTABLE_FL) ? IMMUTABLE : 0;
+ ip->i_blocks = ei->i_blocks;
+ ip->i_gen = ei->i_generation;
+ ip->i_uid = ei->i_uid;
+ ip->i_gid = ei->i_gid;
/* XXX use memcpy */
- for(i = 0; i < NDADDR; i++)
- di->di_db[i] = ei->i_block[i];
- for(i = 0; i < NIADDR; i++)
- di->di_ib[i] = ei->i_block[EXT2_NDIR_BLOCKS + i];
+ for(i = 0; i < NDADDR; i++)
+ ip->i_db[i] = ei->i_block[i];
+ for(i = 0; i < NIADDR; i++)
+ ip->i_ib[i] = ei->i_block[EXT2_NDIR_BLOCKS + i];
}
/*
- * dinode to raw ext2 inode
+ * inode to raw ext2 inode
*/
void
-ext2_di2ei(di, ei)
- struct dinode *di;
- struct ext2_inode *ei;
+ext2_i2ei(ip, ei)
+ struct inode *ip;
+ struct ext2_inode *ei;
{
- int i;
+ int i;
- ei->i_mode = di->di_mode;
- ei->i_links_count = di->di_nlink;
+ ei->i_mode = ip->i_mode;
+ ei->i_links_count = ip->i_nlink;
/*
Godmar thinks: if dtime is nonzero, ext2 says this inode
has been deleted, this would correspond to a zero link count
*/
- ei->i_dtime = ei->i_links_count ? 0 : di->di_mtime;
- ei->i_size = di->di_size;
- ei->i_atime = di->di_atime;
- ei->i_mtime = di->di_mtime;
- ei->i_ctime = di->di_ctime;
- ei->i_flags = di->di_flags;
- ei->i_flags = 0;
- ei->i_flags |= (di->di_flags & APPEND) ? EXT2_APPEND_FL: 0;
- ei->i_flags |= (di->di_flags & IMMUTABLE)
- ? EXT2_IMMUTABLE_FL: 0;
- ei->i_blocks = di->di_blocks;
- ei->i_generation = di->di_gen;
- ei->i_uid = di->di_uid;
- ei->i_gid = di->di_gid;
+ ei->i_dtime = ei->i_links_count ? 0 : ip->i_mtime;
+ ei->i_size = ip->i_size;
+ ei->i_atime = ip->i_atime;
+ ei->i_mtime = ip->i_mtime;
+ ei->i_ctime = ip->i_ctime;
+ ei->i_flags = ip->i_flags;
+ ei->i_flags = 0;
+ ei->i_flags |= (ip->i_flags & APPEND) ? EXT2_APPEND_FL: 0;
+ ei->i_flags |= (ip->i_flags & IMMUTABLE) ? EXT2_IMMUTABLE_FL: 0;
+ ei->i_blocks = ip->i_blocks;
+ ei->i_generation = ip->i_gen;
+ ei->i_uid = ip->i_uid;
+ ei->i_gid = ip->i_gid;
/* XXX use memcpy */
- for(i = 0; i < NDADDR; i++)
- ei->i_block[i] = di->di_db[i];
- for(i = 0; i < NIADDR; i++)
- ei->i_block[EXT2_NDIR_BLOCKS + i] = di->di_ib[i];
+ for(i = 0; i < NDADDR; i++)
+ ei->i_block[i] = ip->i_db[i];
+ for(i = 0; i < NIADDR; i++)
+ ei->i_block[EXT2_NDIR_BLOCKS + i] = ip->i_ib[i];
}
diff --git a/sys/gnu/ext2fs/ext2_linux_balloc.c b/sys/gnu/ext2fs/ext2_linux_balloc.c
index fc723114dfa6..632044009643 100644
--- a/sys/gnu/ext2fs/ext2_linux_balloc.c
+++ b/sys/gnu/ext2fs/ext2_linux_balloc.c
@@ -35,9 +35,8 @@
#include <sys/mount.h>
#include <sys/vnode.h>
-#include <ufs/ufs/extattr.h>
-#include <ufs/ufs/quota.h>
-#include <ufs/ufs/ufsmount.h>
+#include <gnu/ext2fs/inode.h>
+#include <gnu/ext2fs/ext2_mount.h>
#include <gnu/ext2fs/ext2_extern.h>
#include <gnu/ext2fs/ext2_fs.h>
#include <gnu/ext2fs/ext2_fs_sb.h>
@@ -61,13 +60,13 @@ static void read_block_bitmap (struct mount * mp,
unsigned int block_group,
unsigned long bitmap_nr)
{
- struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
+ struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs;
struct ext2_group_desc * gdp;
struct buffer_head * bh;
int error;
gdp = get_group_desc (mp, block_group, NULL);
- if ((error = bread (VFSTOUFS(mp)->um_devvp,
+ if ((error = bread (VFSTOEXT2(mp)->um_devvp,
fsbtodb(sb, gdp->bg_block_bitmap),sb->s_blocksize, NOCRED, &bh)) != 0)
panic ( "read_block_bitmap: "
"Cannot read block bitmap - "
@@ -93,7 +92,7 @@ static int load__block_bitmap (struct mount * mp,
unsigned int block_group)
{
int i, j;
- struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
+ struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs;
unsigned long block_bitmap_number;
struct buffer_head * block_bitmap;
@@ -152,7 +151,7 @@ static int load__block_bitmap (struct mount * mp,
static __inline int load_block_bitmap (struct mount * mp,
unsigned int block_group)
{
- struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
+ struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs;
if (sb->s_loaded_block_bitmaps > 0 &&
sb->s_block_bitmap_number[0] == block_group)
return 0;
@@ -168,7 +167,7 @@ static __inline int load_block_bitmap (struct mount * mp,
void ext2_free_blocks (struct mount * mp, unsigned long block,
unsigned long count)
{
- struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
+ struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs;
struct buffer_head * bh;
struct buffer_head * bh2;
unsigned long block_group;
@@ -182,13 +181,13 @@ void ext2_free_blocks (struct mount * mp, unsigned long block,
printf ("ext2_free_blocks: nonexistent device");
return;
}
- lock_super (VFSTOUFS(mp)->um_devvp);
+ lock_super (VFSTOEXT2(mp)->um_devvp);
if (block < es->s_first_data_block ||
(block + count) > es->s_blocks_count) {
printf ( "ext2_free_blocks: "
"Freeing blocks not in datazone - "
"block = %lu, count = %lu", block, count);
- unlock_super (VFSTOUFS(mp)->um_devvp);
+ unlock_super (VFSTOEXT2(mp)->um_devvp);
return;
}
@@ -238,7 +237,7 @@ void ext2_free_blocks (struct mount * mp, unsigned long block,
}
****/
sb->s_dirt = 1;
- unlock_super (VFSTOUFS(mp)->um_devvp);
+ unlock_super (VFSTOEXT2(mp)->um_devvp);
return;
}
@@ -253,7 +252,7 @@ int ext2_new_block (struct mount * mp, unsigned long goal,
u_int32_t * prealloc_count,
u_int32_t * prealloc_block)
{
- struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
+ struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs;
struct buffer_head * bh;
struct buffer_head * bh2;
char * p, * r;
@@ -269,7 +268,7 @@ int ext2_new_block (struct mount * mp, unsigned long goal,
printf ("ext2_new_block: nonexistent device");
return 0;
}
- lock_super (VFSTOUFS(mp)->um_devvp);
+ lock_super (VFSTOEXT2(mp)->um_devvp);
ext2_debug ("goal=%lu.\n", goal);
@@ -356,7 +355,7 @@ repeat:
break;
}
if (k >= sb->s_groups_count) {
- unlock_super (VFSTOUFS(mp)->um_devvp);
+ unlock_super (VFSTOEXT2(mp)->um_devvp);
return 0;
}
bitmap_nr = load_block_bitmap (mp, i);
@@ -372,7 +371,7 @@ repeat:
if (j >= EXT2_BLOCKS_PER_GROUP(sb)) {
printf ( "ext2_new_block: "
"Free blocks count corrupted for block group %d", i);
- unlock_super (VFSTOUFS(mp)->um_devvp);
+ unlock_super (VFSTOEXT2(mp)->um_devvp);
return 0;
}
@@ -439,7 +438,7 @@ got_block:
printf ( "ext2_new_block: "
"block >= blocks count - "
"block_group = %d, block=%d", i, j);
- unlock_super (VFSTOUFS(mp)->um_devvp);
+ unlock_super (VFSTOEXT2(mp)->um_devvp);
return 0;
}
@@ -450,14 +449,14 @@ got_block:
mark_buffer_dirty(bh2);
es->s_free_blocks_count--;
sb->s_dirt = 1;
- unlock_super (VFSTOUFS(mp)->um_devvp);
+ unlock_super (VFSTOEXT2(mp)->um_devvp);
return j;
}
#ifdef unused
static unsigned long ext2_count_free_blocks (struct mount * mp)
{
- struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
+ struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs;
#ifdef EXT2FS_DEBUG
struct ext2_super_block * es;
unsigned long desc_count, bitmap_count, x;
@@ -465,7 +464,7 @@ static unsigned long ext2_count_free_blocks (struct mount * mp)
struct ext2_group_desc * gdp;
int i;
- lock_super (VFSTOUFS(mp)->um_devvp);
+ lock_super (VFSTOEXT2(mp)->um_devvp);
es = sb->s_es;
desc_count = 0;
bitmap_count = 0;
@@ -482,7 +481,7 @@ static unsigned long ext2_count_free_blocks (struct mount * mp)
}
ext2_debug( "stored = %lu, computed = %lu, %lu\n",
es->s_free_blocks_count, desc_count, bitmap_count);
- unlock_super (VFSTOUFS(mp)->um_devvp);
+ unlock_super (VFSTOEXT2(mp)->um_devvp);
return bitmap_count;
#else
return sb->s_es->s_free_blocks_count;
@@ -520,7 +519,7 @@ int ext2_group_sparse(int group)
#ifdef unused
static void ext2_check_blocks_bitmap (struct mount * mp)
{
- struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
+ struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs;
struct buffer_head * bh;
struct ext2_super_block * es;
unsigned long desc_count, bitmap_count, x;
@@ -529,7 +528,7 @@ static void ext2_check_blocks_bitmap (struct mount * mp)
struct ext2_group_desc * gdp;
int i, j;
- lock_super (VFSTOUFS(mp)->um_devvp);
+ lock_super (VFSTOEXT2(mp)->um_devvp);
es = sb->s_es;
desc_count = 0;
bitmap_count = 0;
@@ -586,7 +585,7 @@ static void ext2_check_blocks_bitmap (struct mount * mp)
"Wrong free blocks count in super block, "
"stored = %lu, counted = %lu",
(unsigned long) es->s_free_blocks_count, bitmap_count);
- unlock_super (VFSTOUFS(mp)->um_devvp);
+ unlock_super (VFSTOEXT2(mp)->um_devvp);
}
#endif /* unused */
diff --git a/sys/gnu/ext2fs/ext2_linux_ialloc.c b/sys/gnu/ext2fs/ext2_linux_ialloc.c
index 01ae55b078dc..64d96b21104c 100644
--- a/sys/gnu/ext2fs/ext2_linux_ialloc.c
+++ b/sys/gnu/ext2fs/ext2_linux_ialloc.c
@@ -36,10 +36,8 @@
#include <sys/mount.h>
#include <sys/vnode.h>
-#include <ufs/ufs/extattr.h>
-#include <ufs/ufs/quota.h>
-#include <ufs/ufs/inode.h>
-#include <ufs/ufs/ufsmount.h>
+#include <gnu/ext2fs/inode.h>
+#include <gnu/ext2fs/ext2_mount.h>
#include <gnu/ext2fs/ext2_extern.h>
#include <gnu/ext2fs/ext2_fs.h>
#include <gnu/ext2fs/ext2_fs_sb.h>
@@ -69,7 +67,7 @@ struct ext2_group_desc * get_group_desc (struct mount * mp,
unsigned int block_group,
struct buffer_head ** bh)
{
- struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
+ struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs;
unsigned long group_desc;
unsigned long desc;
struct ext2_group_desc * gdp;
@@ -98,13 +96,13 @@ static void read_inode_bitmap (struct mount * mp,
unsigned long block_group,
unsigned int bitmap_nr)
{
- struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
+ struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs;
struct ext2_group_desc * gdp;
struct buffer_head * bh;
int error;
gdp = get_group_desc (mp, block_group, NULL);
- if ((error = bread (VFSTOUFS(mp)->um_devvp,
+ if ((error = bread (VFSTOEXT2(mp)->um_devvp,
fsbtodb(sb, gdp->bg_inode_bitmap),
sb->s_blocksize,
NOCRED, &bh)) != 0)
@@ -131,7 +129,7 @@ static void read_inode_bitmap (struct mount * mp,
static int load_inode_bitmap (struct mount * mp,
unsigned int block_group)
{
- struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
+ struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs;
int i, j;
unsigned long inode_bitmap_number;
struct buffer_head * inode_bitmap;
@@ -447,14 +445,14 @@ repeat:
static unsigned long ext2_count_free_inodes (struct mount * mp)
{
#ifdef EXT2FS_DEBUG
- struct ext2_sb_info *sb = VFSTOUFS(mp)->um_e2fs;
+ struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs;
struct ext2_super_block * es;
unsigned long desc_count, bitmap_count, x;
int bitmap_nr;
struct ext2_group_desc * gdp;
int i;
- lock_super (VFSTOUFS(mp)->um_devvp);
+ lock_super (VFSTOEXT2(mp)->um_devvp);
es = sb->s_es;
desc_count = 0;
bitmap_count = 0;
@@ -471,10 +469,10 @@ static unsigned long ext2_count_free_inodes (struct mount * mp)
}
ext2_debug("stored = %lu, computed = %lu, %lu\n",
es->s_free_inodes_count, desc_count, bitmap_count);
- unlock_super (VFSTOUFS(mp)->um_devvp);
+ unlock_super (VFSTOEXT2(mp)->um_devvp);
return desc_count;
#else
- return VFSTOUFS(mp)->um_e2fsb->s_free_inodes_count;
+ return VFSTOEXT2(mp)->um_e2fsb->s_free_inodes_count;
#endif
}
#endif /* unused */
diff --git a/sys/gnu/ext2fs/ext2_lookup.c b/sys/gnu/ext2fs/ext2_lookup.c
index 2c1de41414f4..14b78b58a7cf 100644
--- a/sys/gnu/ext2fs/ext2_lookup.c
+++ b/sys/gnu/ext2fs/ext2_lookup.c
@@ -55,13 +55,10 @@
#include <sys/malloc.h>
#include <sys/dirent.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 <gnu/ext2fs/inode.h>
+#include <gnu/ext2fs/ext2_mount.h>
#include <gnu/ext2fs/ext2_extern.h>
#include <gnu/ext2fs/ext2_fs.h>
#include <gnu/ext2fs/ext2_fs_sb.h>
@@ -364,7 +361,7 @@ ext2_lookup(ap)
* profiling time and hence has been removed in the interest
* of simplicity.
*/
- bmask = VFSTOUFS(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1;
+ bmask = VFSTOEXT2(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1;
if (nameiop != LOOKUP || dp->i_diroff == 0 ||
dp->i_diroff > dp->i_size) {
entryoffsetinblock = 0;
@@ -373,7 +370,8 @@ ext2_lookup(ap)
} else {
dp->i_offset = dp->i_diroff;
if ((entryoffsetinblock = dp->i_offset & bmask) &&
- (error = UFS_BLKATOFF(vdp, (off_t)dp->i_offset, NULL, &bp)))
+ (error = ext2_blkatoff(vdp, (off_t)dp->i_offset, NULL,
+ &bp)))
return (error);
numdirpasses = 2;
nchstats.ncs_2passes++;
@@ -391,7 +389,8 @@ searchloop:
if (bp != NULL)
brelse(bp);
if ((error =
- UFS_BLKATOFF(vdp, (off_t)dp->i_offset, NULL, &bp)) != 0)
+ ext2_blkatoff(vdp, (off_t)dp->i_offset, NULL,
+ &bp)) != 0)
return (error);
entryoffsetinblock = 0;
}
@@ -416,7 +415,7 @@ searchloop:
if (ep->rec_len == 0 ||
(dirchk && ext2_dirbadentry(vdp, ep, entryoffsetinblock))) {
int i;
- ufs_dirbad(dp, dp->i_offset, "mangled entry");
+ ext2_dirbad(dp, dp->i_offset, "mangled entry");
i = DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1));
dp->i_offset += i;
entryoffsetinblock += i;
@@ -558,7 +557,7 @@ found:
*/
if (entryoffsetinblock + EXT2_DIR_REC_LEN(ep->name_len)
> dp->i_size) {
- ufs_dirbad(dp, dp->i_offset, "i_size too small");
+ ext2_dirbad(dp, dp->i_offset, "i_size too small");
dp->i_size = entryoffsetinblock+EXT2_DIR_REC_LEN(ep->name_len);
dp->i_flag |= IN_CHANGE | IN_UPDATE;
}
@@ -700,6 +699,21 @@ found:
return (0);
}
+void
+ext2_dirbad(ip, offset, how)
+ struct inode *ip;
+ doff_t offset;
+ char *how;
+{
+ struct mount *mp;
+
+ mp = ITOV(ip)->v_mount;
+ (void)printf("%s: bad dir ino %lu at offset %ld: %s\n",
+ mp->mnt_stat.f_mntonname, (u_long)ip->i_number, (long)offset, how);
+ if ((mp->mnt_flag & MNT_RDONLY) == 0)
+ panic("ext2_dirbad: bad dir");
+}
+
/*
* Do consistency checking on a directory entry:
* record length must be multiple of 4
@@ -804,7 +818,7 @@ ext2_direnter(ip, dvp, cnp)
auio.uio_td = (struct thread *)0;
error = VOP_WRITE(dvp, &auio, IO_SYNC, cnp->cn_cred);
if (DIRBLKSIZ >
- VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_bsize)
+ VFSTOEXT2(dvp->v_mount)->um_mountp->mnt_stat.f_bsize)
/* XXX should grow with balloc() */
panic("ext2_direnter: frag size");
else if (!error) {
@@ -835,7 +849,8 @@ ext2_direnter(ip, dvp, cnp)
/*
* Get the block containing the space for the new directory entry.
*/
- if ((error = UFS_BLKATOFF(dvp, (off_t)dp->i_offset, &dirbuf, &bp)) != 0)
+ if ((error = ext2_blkatoff(dvp, (off_t)dp->i_offset, &dirbuf,
+ &bp)) != 0)
return (error);
/*
* Find space for the new entry. In the simple case, the entry at
@@ -881,7 +896,7 @@ ext2_direnter(ip, dvp, cnp)
error = BUF_WRITE(bp);
dp->i_flag |= IN_CHANGE | IN_UPDATE;
if (!error && dp->i_endoff && dp->i_endoff < dp->i_size)
- error = UFS_TRUNCATE(dvp, (off_t)dp->i_endoff, IO_SYNC,
+ error = ext2_truncate(dvp, (off_t)dp->i_endoff, IO_SYNC,
cnp->cn_cred, cnp->cn_thread);
return (error);
}
@@ -914,7 +929,8 @@ ext2_dirremove(dvp, cnp)
* First entry in block: set d_ino to zero.
*/
if ((error =
- UFS_BLKATOFF(dvp, (off_t)dp->i_offset, (char **)&ep, &bp)) != 0)
+ ext2_blkatoff(dvp, (off_t)dp->i_offset, (char **)&ep,
+ &bp)) != 0)
return (error);
ep->inode = 0;
error = BUF_WRITE(bp);
@@ -924,7 +940,7 @@ ext2_dirremove(dvp, cnp)
/*
* Collapse new free space into previous entry.
*/
- if ((error = UFS_BLKATOFF(dvp, (off_t)(dp->i_offset - dp->i_count),
+ if ((error = ext2_blkatoff(dvp, (off_t)(dp->i_offset - dp->i_count),
(char **)&ep, &bp)) != 0)
return (error);
ep->rec_len += dp->i_reclen;
@@ -948,7 +964,8 @@ ext2_dirrewrite(dp, ip, cnp)
struct vnode *vdp = ITOV(dp);
int error;
- if ((error = UFS_BLKATOFF(vdp, (off_t)dp->i_offset, (char **)&ep, &bp)) != 0)
+ if ((error = ext2_blkatoff(vdp, (off_t)dp->i_offset, (char **)&ep,
+ &bp)) != 0)
return (error);
ep->inode = ip->i_number;
if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs->s_es,
diff --git a/sys/gnu/ext2fs/ext2_readwrite.c b/sys/gnu/ext2fs/ext2_readwrite.c
index 2772f7b2306e..73f900cd3230 100644
--- a/sys/gnu/ext2fs/ext2_readwrite.c
+++ b/sys/gnu/ext2fs/ext2_readwrite.c
@@ -301,12 +301,12 @@ WRITE(ap)
ip->i_mode &= ~(ISUID | ISGID);
if (error) {
if (ioflag & IO_UNIT) {
- (void)UFS_TRUNCATE(vp, osize,
+ (void)ext2_truncate(vp, osize,
ioflag & IO_SYNC, ap->a_cred, uio->uio_td);
uio->uio_offset -= resid - uio->uio_resid;
uio->uio_resid = resid;
}
} else if (resid > uio->uio_resid && (ioflag & IO_SYNC))
- error = UFS_UPDATE(vp, 1);
+ error = ext2_update(vp, 1);
return (error);
}
diff --git a/sys/gnu/ext2fs/ext2_subr.c b/sys/gnu/ext2fs/ext2_subr.c
index 69eecf1e236b..587ed0520f6d 100644
--- a/sys/gnu/ext2fs/ext2_subr.c
+++ b/sys/gnu/ext2fs/ext2_subr.c
@@ -50,9 +50,7 @@
#include <sys/ucred.h>
#include <sys/vnode.h>
-#include <ufs/ufs/quota.h>
-#include <ufs/ufs/inode.h>
-
+#include <gnu/ext2fs/inode.h>
#include <gnu/ext2fs/ext2_extern.h>
#include <gnu/ext2fs/ext2_fs_sb.h>
#include <gnu/ext2fs/fs.h>
@@ -121,7 +119,7 @@ ext2_checkoverlap(bp, ip)
continue;
vprint("Disk overlap", vp);
(void)printf("\tstart %d, end %d overlap start %lld, end %ld\n",
- start, last, ep->b_blkno,
+ start, last, (long long)ep->b_blkno,
(long)(ep->b_blkno + btodb(ep->b_bcount) - 1));
panic("Disk buffer overlap");
}
diff --git a/sys/gnu/ext2fs/ext2_vfsops.c b/sys/gnu/ext2fs/ext2_vfsops.c
index 54c43058cb3d..b9afe91a1f7f 100644
--- a/sys/gnu/ext2fs/ext2_vfsops.c
+++ b/sys/gnu/ext2fs/ext2_vfsops.c
@@ -40,8 +40,6 @@
* $FreeBSD$
*/
-#include "opt_quota.h"
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/namei.h>
@@ -57,12 +55,8 @@
#include <sys/stat.h>
#include <sys/mutex.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 <gnu/ext2fs/ext2_mount.h>
+#include <gnu/ext2fs/inode.h>
#include <gnu/ext2fs/fs.h>
#include <gnu/ext2fs/ext2_extern.h>
@@ -71,26 +65,29 @@
static int ext2_fhtovp(struct mount *, struct fid *, struct vnode **);
static int ext2_flushfiles(struct mount *mp, int flags, struct thread *td);
+static int ext2_init(struct vfsconf *);
static int ext2_mount(struct mount *,
char *, caddr_t, struct nameidata *, struct thread *);
static int ext2_mountfs(struct vnode *, struct mount *, struct thread *);
static int ext2_reload(struct mount *mountp, struct ucred *cred,
struct thread *td);
-static int ext2_sbupdate(struct ufsmount *, int);
+static int ext2_root(struct mount *, struct vnode **vpp);
+static int ext2_sbupdate(struct ext2mount *, int);
static int ext2_statfs(struct mount *, struct statfs *, struct thread *);
static int ext2_sync(struct mount *, int, struct ucred *, struct thread *);
static int ext2_unmount(struct mount *, int, struct thread *);
static int ext2_vget(struct mount *, ino_t, int, struct vnode **);
static int ext2_vptofh(struct vnode *, struct fid *);
-static MALLOC_DEFINE(M_EXT2NODE, "EXT2 node", "EXT2 vnode private part");
+MALLOC_DEFINE(M_EXT2NODE, "EXT2 node", "EXT2 vnode private part");
+static MALLOC_DEFINE(M_EXT2MNT, "EXT2 mount", "EXT2 mount structure");
static struct vfsops ext2fs_vfsops = {
ext2_mount,
- ufs_start, /* empty function */
+ vfs_stdstart,
ext2_unmount,
- ufs_root, /* root inode via vget */
- ufs_quotactl, /* does operations associated with quotas */
+ ext2_root, /* root inode via vget */
+ vfs_stdquotactl,
ext2_statfs,
ext2_sync,
ext2_vget,
@@ -129,7 +126,7 @@ ext2_mountroot()
register struct ext2_sb_info *fs;
register struct mount *mp;
struct thread *td = curthread;
- struct ufsmount *ump;
+ struct ext2mount *ump;
u_int size;
int error;
@@ -155,7 +152,7 @@ ext2_mountroot()
TAILQ_INSERT_HEAD(&mountlist, mp, mnt_list);
mp->mnt_flag |= MNT_ROOTFS;
mp->mnt_vnodecovered = NULLVP;
- ump = VFSTOUFS(mp);
+ ump = VFSTOEXT2(mp);
fs = ump->um_e2fs;
bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt));
fs->fs_fsmnt[0] = '/';
@@ -180,13 +177,13 @@ static int
ext2_mount(mp, path, data, ndp, td)
register struct mount *mp;
char *path;
- caddr_t data; /* this is actually a (struct ufs_args *) */
+ caddr_t data; /* this is actually a (struct ext2_args *) */
struct nameidata *ndp;
struct thread *td;
{
struct vnode *devvp;
- struct ufs_args args;
- struct ufsmount *ump = 0;
+ struct ext2_args args;
+ struct ext2mount *ump = 0;
register struct ext2_sb_info *fs;
size_t size;
int error, flags;
@@ -195,7 +192,7 @@ ext2_mount(mp, path, data, ndp, td)
/* Double-check the length of path.. */
if (strlen(path) >= MAXMNTLEN - 1)
return (ENAMETOOLONG);
- error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args));
+ error = copyin(data, (caddr_t)&args, sizeof (struct ext2_args));
if (error != 0)
return (error);
/*
@@ -203,7 +200,7 @@ ext2_mount(mp, path, data, ndp, td)
* read/write; if there is no device name, that's all we do.
*/
if (mp->mnt_flag & MNT_UPDATE) {
- ump = VFSTOUFS(mp);
+ ump = VFSTOEXT2(mp);
fs = ump->um_e2fs;
error = 0;
if (fs->s_rd_only == 0 && (mp->mnt_flag & MNT_RDONLY)) {
@@ -310,7 +307,7 @@ ext2_mount(mp, path, data, ndp, td)
vrele(devvp);
return (error);
}
- ump = VFSTOUFS(mp);
+ ump = VFSTOEXT2(mp);
fs = ump->um_e2fs;
/*
* Note that this strncpy() is ok because of a check at the start
@@ -466,7 +463,7 @@ static int compute_sb_data(devvp, es, fs)
V(s_db_per_group)
fs->s_group_desc = bsd_malloc(db_count * sizeof (struct buf *),
- M_UFSMNT, M_WAITOK);
+ M_EXT2MNT, M_WAITOK);
/* adjust logic_sb_block */
if(fs->s_blocksize > SBSIZE)
@@ -481,7 +478,7 @@ static int compute_sb_data(devvp, es, fs)
if(error) {
for (j = 0; j < i; j++)
brelse(fs->s_group_desc[j]);
- bsd_free(fs->s_group_desc, M_UFSMNT);
+ bsd_free(fs->s_group_desc, M_EXT2MNT);
printf("EXT2-fs: unable to read group descriptors (%d)\n", error);
return EIO;
}
@@ -491,7 +488,7 @@ static int compute_sb_data(devvp, es, fs)
if(!ext2_check_descriptors(fs)) {
for (j = 0; j < db_count; j++)
ULCK_BUF(fs->s_group_desc[j])
- bsd_free(fs->s_group_desc, M_UFSMNT);
+ bsd_free(fs->s_group_desc, M_EXT2MNT);
printf("EXT2-fs: (ext2_check_descriptors failure) "
"unable to read group descriptors\n");
return EIO;
@@ -539,7 +536,7 @@ ext2_reload(mountp, cred, td)
/*
* Step 1: invalidate all cached meta-data.
*/
- devvp = VFSTOUFS(mountp)->um_devvp;
+ devvp = VFSTOEXT2(mountp)->um_devvp;
if (vinvalbuf(devvp, 0, cred, td, 0, 0))
panic("ext2_reload: dirty1");
/*
@@ -553,7 +550,7 @@ ext2_reload(mountp, cred, td)
brelse(bp);
return (EIO); /* XXX needs translation */
}
- fs = VFSTOUFS(mountp)->um_e2fs;
+ fs = VFSTOEXT2(mountp)->um_e2fs;
bcopy(bp->b_data, fs->s_es, sizeof(struct ext2_super_block));
if((error = compute_sb_data(devvp, es, fs)) != 0) {
@@ -600,9 +597,8 @@ loop:
vput(vp);
return (error);
}
- ext2_ei2di((struct ext2_inode *) ((char *)bp->b_data +
- EXT2_INODE_SIZE * ino_to_fsbo(fs, ip->i_number)),
- &ip->i_din);
+ ext2_ei2i((struct ext2_inode *) ((char *)bp->b_data +
+ EXT2_INODE_SIZE * ino_to_fsbo(fs, ip->i_number)), ip);
brelse(bp);
vput(vp);
mtx_lock(&mntvnode_mtx);
@@ -620,12 +616,12 @@ ext2_mountfs(devvp, mp, td)
struct mount *mp;
struct thread *td;
{
- register struct ufsmount *ump;
+ register struct ext2mount *ump;
struct buf *bp;
register struct ext2_sb_info *fs;
struct ext2_super_block * es;
dev_t dev = devvp->v_rdev;
- int error, i;
+ int error;
int ronly;
/*
@@ -677,22 +673,16 @@ ext2_mountfs(devvp, mp, td)
goto out;
}
}
- ump = bsd_malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
+ ump = bsd_malloc(sizeof *ump, M_EXT2MNT, M_WAITOK);
bzero((caddr_t)ump, sizeof *ump);
- ump->um_malloctype = M_EXT2NODE;
- ump->um_blkatoff = ext2_blkatoff;
- ump->um_truncate = ext2_truncate;
- ump->um_update = ext2_update;
- ump->um_valloc = ext2_valloc;
- ump->um_vfree = ext2_vfree;
/* I don't know whether this is the right strategy. Note that
we dynamically allocate both a ext2_sb_info and a ext2_super_block
while Linux keeps the super block in a locked buffer
*/
ump->um_e2fs = bsd_malloc(sizeof(struct ext2_sb_info),
- M_UFSMNT, M_WAITOK);
+ M_EXT2MNT, M_WAITOK);
ump->um_e2fs->s_es = bsd_malloc(sizeof(struct ext2_super_block),
- M_UFSMNT, M_WAITOK);
+ M_EXT2MNT, M_WAITOK);
bcopy(es, ump->um_e2fs->s_es, (u_int)sizeof(struct ext2_super_block));
if ((error = compute_sb_data(devvp, ump->um_e2fs->s_es, ump->um_e2fs)))
goto out;
@@ -720,14 +710,12 @@ ext2_mountfs(devvp, mp, td)
ump->um_mountp = mp;
ump->um_dev = dev;
ump->um_devvp = devvp;
- /* setting those two parameters allows us to use
+ /* setting those two parameters allowed us to use
ufs_bmap w/o changse !
*/
ump->um_nindir = EXT2_ADDR_PER_BLOCK(fs);
ump->um_bptrtodb = fs->s_es->s_log_block_size + 1;
ump->um_seqinc = EXT2_FRAGS_PER_BLOCK(fs);
- for (i = 0; i < MAXQUOTAS; i++)
- ump->um_quotas[i] = NULLVP;
devvp->v_rdev->si_mountpoint = mp;
if (ronly == 0)
ext2_sbupdate(ump, MNT_WAIT);
@@ -737,9 +725,9 @@ out:
brelse(bp);
(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, td);
if (ump) {
- bsd_free(ump->um_e2fs->s_es, M_UFSMNT);
- bsd_free(ump->um_e2fs, M_UFSMNT);
- bsd_free(ump, M_UFSMNT);
+ bsd_free(ump->um_e2fs->s_es, M_EXT2MNT);
+ bsd_free(ump->um_e2fs, M_EXT2MNT);
+ bsd_free(ump, M_EXT2MNT);
mp->mnt_data = (qaddr_t)0;
}
return (error);
@@ -754,7 +742,7 @@ ext2_unmount(mp, mntflags, td)
int mntflags;
struct thread *td;
{
- register struct ufsmount *ump;
+ register struct ext2mount *ump;
register struct ext2_sb_info *fs;
int error, flags, ronly, i;
@@ -766,7 +754,7 @@ ext2_unmount(mp, mntflags, td)
}
if ((error = ext2_flushfiles(mp, flags, td)) != 0)
return (error);
- ump = VFSTOUFS(mp);
+ ump = VFSTOEXT2(mp);
fs = ump->um_e2fs;
ronly = fs->s_rd_only;
if (ronly == 0) {
@@ -778,7 +766,7 @@ ext2_unmount(mp, mntflags, td)
/* release buffers containing group descriptors */
for(i = 0; i < fs->s_db_per_group; i++)
ULCK_BUF(fs->s_group_desc[i])
- bsd_free(fs->s_group_desc, M_UFSMNT);
+ bsd_free(fs->s_group_desc, M_EXT2MNT);
/* release cached inode/block bitmaps */
for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++)
@@ -793,9 +781,9 @@ ext2_unmount(mp, mntflags, td)
error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE,
NOCRED, td);
vrele(ump->um_devvp);
- bsd_free(fs->s_es, M_UFSMNT);
- bsd_free(fs, M_UFSMNT);
- bsd_free(ump, M_UFSMNT);
+ bsd_free(fs->s_es, M_EXT2MNT);
+ bsd_free(fs, M_EXT2MNT);
+ bsd_free(ump, M_EXT2MNT);
mp->mnt_data = (qaddr_t)0;
mp->mnt_flag &= ~MNT_LOCAL;
return (error);
@@ -810,28 +798,8 @@ ext2_flushfiles(mp, flags, td)
int flags;
struct thread *td;
{
- register struct ufsmount *ump;
int error;
-#if QUOTA
- int i;
-#endif
- ump = VFSTOUFS(mp);
-#if QUOTA
- if (mp->mnt_flag & MNT_QUOTA) {
- if ((error = vflush(mp, 0, SKIPSYSTEM|flags)) != 0)
- return (error);
- for (i = 0; i < MAXQUOTAS; i++) {
- if (ump->um_quotas[i] == NULLVP)
- continue;
- quotaoff(td, mp, i);
- }
- /*
- * Here we fall through to vflush again to ensure
- * that we have gotten rid of all the system vnodes.
- */
- }
-#endif
error = vflush(mp, 0, flags);
return (error);
}
@@ -847,12 +815,12 @@ ext2_statfs(mp, sbp, td)
struct thread *td;
{
unsigned long overhead;
- register struct ufsmount *ump;
+ register struct ext2mount *ump;
register struct ext2_sb_info *fs;
register struct ext2_super_block *es;
int i, nsb;
- ump = VFSTOUFS(mp);
+ ump = VFSTOEXT2(mp);
fs = ump->um_e2fs;
es = fs->s_es;
@@ -908,7 +876,7 @@ ext2_sync(mp, waitfor, cred, td)
{
struct vnode *nvp, *vp;
struct inode *ip;
- struct ufsmount *ump = VFSTOUFS(mp);
+ struct ext2mount *ump = VFSTOEXT2(mp);
struct ext2_sb_info *fs;
int error, allerror = 0;
@@ -964,9 +932,6 @@ loop:
allerror = error;
VOP_UNLOCK(ump->um_devvp, 0, td);
}
-#if QUOTA
- qsync(mp);
-#endif
/*
* Write back modified superblock.
*/
@@ -994,17 +959,17 @@ ext2_vget(mp, ino, flags, vpp)
{
register struct ext2_sb_info *fs;
register struct inode *ip;
- struct ufsmount *ump;
+ struct ext2mount *ump;
struct buf *bp;
struct vnode *vp;
dev_t dev;
int i, error;
int used_blocks;
- ump = VFSTOUFS(mp);
+ ump = VFSTOEXT2(mp);
dev = ump->um_dev;
restart:
- if ((error = ufs_ihashget(dev, ino, flags, vpp)) != 0)
+ if ((error = ext2_ihashget(dev, ino, flags, vpp)) != 0)
return (error);
if (*vpp != NULL)
return (0);
@@ -1048,17 +1013,13 @@ restart:
ip->i_e2fs = fs = ump->um_e2fs;
ip->i_dev = dev;
ip->i_number = ino;
-#if QUOTA
- 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);
+ ext2_ihashins(ip);
if (ext2fs_inode_hash_lock < 0)
wakeup(&ext2fs_inode_hash_lock);
@@ -1082,8 +1043,8 @@ printf("ext2_vget(%d) dbn= %d ", ino, fsbtodb(fs, ino_to_fsba(fs, ino)));
return (error);
}
/* convert ext2 inode to dinode */
- ext2_ei2di((struct ext2_inode *) ((char *)bp->b_data + EXT2_INODE_SIZE *
- ino_to_fsbo(fs, ino)), &ip->i_din);
+ ext2_ei2i((struct ext2_inode *) ((char *)bp->b_data + EXT2_INODE_SIZE *
+ ino_to_fsbo(fs, ino)), ip);
ip->i_block_group = ino_to_cg(fs, ino);
ip->i_next_alloc_block = 0;
ip->i_next_alloc_goal = 0;
@@ -1107,7 +1068,7 @@ printf("ext2_vget(%d) dbn= %d ", ino, fsbtodb(fs, ino_to_fsba(fs, ino)));
* Initialize the vnode from the inode, check for aliases.
* Note that the underlying vnode may have changed.
*/
- if ((error = ufs_vinit(mp, ext2_specop_p, ext2_fifoop_p, &vp)) != 0) {
+ if ((error = ext2_vinit(mp, ext2_specop_p, ext2_fifoop_p, &vp)) != 0) {
vput(vp);
*vpp = NULL;
return (error);
@@ -1146,15 +1107,32 @@ ext2_fhtovp(mp, fhp, vpp)
struct fid *fhp;
struct vnode **vpp;
{
+ struct inode *ip;
register struct ufid *ufhp;
+ struct vnode *nvp;
struct ext2_sb_info *fs;
+ int error;
ufhp = (struct ufid *)fhp;
- fs = VFSTOUFS(mp)->um_e2fs;
+ fs = VFSTOEXT2(mp)->um_e2fs;
if (ufhp->ufid_ino < ROOTINO ||
ufhp->ufid_ino >= fs->s_groups_count * fs->s_es->s_inodes_per_group)
return (ESTALE);
- return (ufs_fhtovp(mp, ufhp, vpp));
+
+ error = VFS_VGET(mp, ufhp->ufid_ino, LK_EXCLUSIVE, &nvp);
+ if (error) {
+ *vpp = NULLVP;
+ return (error);
+ }
+ ip = VTOI(nvp);
+ if (ip->i_mode == 0 ||
+ ip->i_gen != ufhp->ufid_gen || ip->i_nlink <= 0) {
+ vput(nvp);
+ *vpp = NULLVP;
+ return (ESTALE);
+ }
+ *vpp = nvp;
+ return (0);
}
/*
@@ -1182,7 +1160,7 @@ ext2_vptofh(vp, fhp)
*/
static int
ext2_sbupdate(mp, waitfor)
- struct ufsmount *mp;
+ struct ext2mount *mp;
int waitfor;
{
register struct ext2_sb_info *fs = mp->um_e2fs;
@@ -1207,3 +1185,34 @@ printf("\nupdating superblock, waitfor=%s\n", waitfor == MNT_WAIT ? "yes":"no");
return (error);
}
+
+/*
+ * Return the root of a filesystem.
+ */
+static int
+ext2_root(mp, vpp)
+ struct mount *mp;
+ struct vnode **vpp;
+{
+ struct vnode *nvp;
+ int error;
+
+ error = VFS_VGET(mp, (ino_t)ROOTINO, LK_EXCLUSIVE, &nvp);
+ if (error)
+ return (error);
+ *vpp = nvp;
+ return (0);
+}
+
+static int
+ext2_init(struct vfsconf *vfsp)
+{
+ static int done;
+
+ if (done)
+ return (0);
+ done = 1;
+ ext2_ihashinit();
+
+ return (0);
+}
diff --git a/sys/gnu/ext2fs/ext2_vnops.c b/sys/gnu/ext2fs/ext2_vnops.c
index 180ac3db063a..ba7b714cdaf9 100644
--- a/sys/gnu/ext2fs/ext2_vnops.c
+++ b/sys/gnu/ext2fs/ext2_vnops.c
@@ -46,34 +46,38 @@
* $FreeBSD$
*/
-#include "opt_quota.h"
#include "opt_suiddir.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/resourcevar.h>
#include <sys/kernel.h>
+#include <sys/fcntl.h>
#include <sys/stat.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/proc.h>
#include <sys/mount.h>
+#include <sys/unistd.h>
#include <sys/time.h>
#include <sys/vnode.h>
#include <sys/namei.h>
+#include <sys/lockf.h>
+#include <sys/event.h>
+#include <sys/conf.h>
+#include <sys/file.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
#include <vm/vnode_pager.h>
+#include <fs/fifofs/fifo.h>
+
#include <sys/signalvar.h>
#include <ufs/ufs/dir.h>
-#include <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 <gnu/ext2fs/inode.h>
+#include <gnu/ext2fs/ext2_mount.h>
#include <gnu/ext2fs/ext2_fs_sb.h>
#include <gnu/ext2fs/fs.h>
#include <gnu/ext2fs/ext2_extern.h>
@@ -81,38 +85,81 @@
static int ext2_makeinode(int mode, struct vnode *, struct vnode **, struct componentname *);
+static int ext2_access(struct vop_access_args *);
+static int ext2_advlock(struct vop_advlock_args *);
+static int ext2_chmod(struct vnode *, int, struct ucred *, struct thread *);
+static int ext2_chown(struct vnode *, uid_t, gid_t, struct ucred *,
+ struct thread *);
+static int ext2_close(struct vop_close_args *);
+static int ext2_create(struct vop_create_args *);
static int ext2_fsync(struct vop_fsync_args *);
+static int ext2_getattr(struct vop_getattr_args *);
+static int ext2_kqfilter(struct vop_kqfilter_args *ap);
+static int ext2_link(struct vop_link_args *);
+static int ext2_mkdir(struct vop_mkdir_args *);
+static int ext2_mknod(struct vop_mknod_args *);
+static int ext2_open(struct vop_open_args *);
+static int ext2_pathconf(struct vop_pathconf_args *);
+static int ext2_print(struct vop_print_args *);
static int ext2_read(struct vop_read_args *);
-static int ext2_write(struct vop_write_args *);
+static int ext2_readlink(struct vop_readlink_args *);
static int ext2_remove(struct vop_remove_args *);
-static int ext2_link(struct vop_link_args *);
static int ext2_rename(struct vop_rename_args *);
-static int ext2_mkdir(struct vop_mkdir_args *);
static int ext2_rmdir(struct vop_rmdir_args *);
-static int ext2_create(struct vop_create_args *);
-static int ext2_mknod(struct vop_mknod_args *);
+static int ext2_setattr(struct vop_setattr_args *);
+static int ext2_strategy(struct vop_strategy_args *);
static int ext2_symlink(struct vop_symlink_args *);
+static int ext2_write(struct vop_write_args *);
+static int ext2fifo_close(struct vop_close_args *);
+static int ext2fifo_kqfilter(struct vop_kqfilter_args *);
+static int ext2fifo_read(struct vop_read_args *);
+static int ext2fifo_write(struct vop_write_args *);
+static int ext2spec_close(struct vop_close_args *);
+static int ext2spec_read(struct vop_read_args *);
+static int ext2spec_write(struct vop_write_args *);
+static int filt_ext2read(struct knote *kn, long hint);
+static int filt_ext2write(struct knote *kn, long hint);
+static int filt_ext2vnode(struct knote *kn, long hint);
+static void filt_ext2detach(struct knote *kn);
-/* Global vfs data structures for ufs. */
+/* Global vfs data structures for ext2. */
vop_t **ext2_vnodeop_p;
static struct vnodeopv_entry_desc ext2_vnodeop_entries[] = {
- { &vop_default_desc, (vop_t *) ufs_vnoperate },
+ { &vop_default_desc, (vop_t *) vop_defaultop },
+ { &vop_access_desc, (vop_t *) ext2_access },
+ { &vop_advlock_desc, (vop_t *) ext2_advlock },
+ { &vop_bmap_desc, (vop_t *) ext2_bmap },
{ &vop_cachedlookup_desc, (vop_t *) ext2_lookup },
+ { &vop_close_desc, (vop_t *) ext2_close },
+ { &vop_create_desc, (vop_t *) ext2_create },
{ &vop_fsync_desc, (vop_t *) ext2_fsync },
+ { &vop_getattr_desc, (vop_t *) ext2_getattr },
+ { &vop_getwritemount_desc, (vop_t *) vop_stdgetwritemount },
{ &vop_inactive_desc, (vop_t *) ext2_inactive },
+ { &vop_islocked_desc, (vop_t *) vop_stdislocked },
+ { &vop_link_desc, (vop_t *) ext2_link },
+ { &vop_lock_desc, (vop_t *) vop_stdlock },
{ &vop_lookup_desc, (vop_t *) vfs_cache_lookup },
+ { &vop_mkdir_desc, (vop_t *) ext2_mkdir },
+ { &vop_mknod_desc, (vop_t *) ext2_mknod },
+ { &vop_open_desc, (vop_t *) ext2_open },
+ { &vop_pathconf_desc, (vop_t *) ext2_pathconf },
+ { &vop_poll_desc, (vop_t *) vop_stdpoll },
+ { &vop_kqfilter_desc, (vop_t *) ext2_kqfilter },
+ { &vop_print_desc, (vop_t *) ext2_print },
{ &vop_read_desc, (vop_t *) ext2_read },
{ &vop_readdir_desc, (vop_t *) ext2_readdir },
+ { &vop_readlink_desc, (vop_t *) ext2_readlink },
{ &vop_reallocblks_desc, (vop_t *) ext2_reallocblks },
- { &vop_write_desc, (vop_t *) ext2_write },
+ { &vop_reclaim_desc, (vop_t *) ext2_reclaim },
{ &vop_remove_desc, (vop_t *) ext2_remove },
- { &vop_link_desc, (vop_t *) ext2_link },
{ &vop_rename_desc, (vop_t *) ext2_rename },
- { &vop_mkdir_desc, (vop_t *) ext2_mkdir },
{ &vop_rmdir_desc, (vop_t *) ext2_rmdir },
- { &vop_create_desc, (vop_t *) ext2_create },
- { &vop_mknod_desc, (vop_t *) ext2_mknod },
+ { &vop_setattr_desc, (vop_t *) ext2_setattr },
+ { &vop_strategy_desc, (vop_t *) ext2_strategy },
{ &vop_symlink_desc, (vop_t *) ext2_symlink },
+ { &vop_unlock_desc, (vop_t *) vop_stdunlock },
+ { &vop_write_desc, (vop_t *) ext2_write },
{ NULL, NULL }
};
static struct vnodeopv_desc ext2fs_vnodeop_opv_desc =
@@ -120,9 +167,20 @@ static struct vnodeopv_desc ext2fs_vnodeop_opv_desc =
vop_t **ext2_specop_p;
static struct vnodeopv_entry_desc ext2_specop_entries[] = {
- { &vop_default_desc, (vop_t *) ufs_vnoperatespec },
+ { &vop_default_desc, (vop_t *) spec_vnoperate },
+ { &vop_access_desc, (vop_t *) ext2_access },
+ { &vop_close_desc, (vop_t *) ext2spec_close },
{ &vop_fsync_desc, (vop_t *) ext2_fsync },
+ { &vop_getattr_desc, (vop_t *) ext2_getattr },
{ &vop_inactive_desc, (vop_t *) ext2_inactive },
+ { &vop_islocked_desc, (vop_t *) vop_stdislocked },
+ { &vop_lock_desc, (vop_t *) vop_stdlock },
+ { &vop_print_desc, (vop_t *) ext2_print },
+ { &vop_read_desc, (vop_t *) ext2spec_read },
+ { &vop_reclaim_desc, (vop_t *) ext2_reclaim },
+ { &vop_setattr_desc, (vop_t *) ext2_setattr },
+ { &vop_unlock_desc, (vop_t *) vop_stdunlock },
+ { &vop_write_desc, (vop_t *) ext2spec_write },
{ NULL, NULL }
};
static struct vnodeopv_desc ext2fs_specop_opv_desc =
@@ -130,9 +188,21 @@ static struct vnodeopv_desc ext2fs_specop_opv_desc =
vop_t **ext2_fifoop_p;
static struct vnodeopv_entry_desc ext2_fifoop_entries[] = {
- { &vop_default_desc, (vop_t *) ufs_vnoperatefifo },
+ { &vop_default_desc, (vop_t *) fifo_vnoperate },
+ { &vop_access_desc, (vop_t *) ext2_access },
+ { &vop_close_desc, (vop_t *) ext2fifo_close },
{ &vop_fsync_desc, (vop_t *) ext2_fsync },
+ { &vop_getattr_desc, (vop_t *) ext2_getattr },
{ &vop_inactive_desc, (vop_t *) ext2_inactive },
+ { &vop_islocked_desc, (vop_t *) vop_stdislocked },
+ { &vop_kqfilter_desc, (vop_t *) ext2fifo_kqfilter },
+ { &vop_lock_desc, (vop_t *) vop_stdlock },
+ { &vop_print_desc, (vop_t *) ext2_print },
+ { &vop_read_desc, (vop_t *) ext2fifo_read },
+ { &vop_reclaim_desc, (vop_t *) ext2_reclaim },
+ { &vop_setattr_desc, (vop_t *) ext2_setattr },
+ { &vop_unlock_desc, (vop_t *) vop_stdunlock },
+ { &vop_write_desc, (vop_t *) ext2fifo_write },
{ NULL, NULL }
};
static struct vnodeopv_desc ext2fs_fifoop_opv_desc =
@@ -144,9 +214,26 @@ static struct vnodeopv_desc ext2fs_fifoop_opv_desc =
#include <gnu/ext2fs/ext2_readwrite.c>
+union _qcvt {
+ int64_t qcvt;
+ int32_t val[2];
+};
+#define SETHIGH(q, h) { \
+ union _qcvt tmp; \
+ tmp.qcvt = (q); \
+ tmp.val[_QUAD_HIGHWORD] = (h); \
+ (q) = tmp.qcvt; \
+}
+#define SETLOW(q, l) { \
+ union _qcvt tmp; \
+ tmp.qcvt = (q); \
+ tmp.val[_QUAD_LOWWORD] = (l); \
+ (q) = tmp.qcvt; \
+}
+
/*
* A virgin directory (no blushing please).
- * Note that the type and namlen fields are reversed relative to ufs.
+ * Note that the type and namlen fields are reversed relative to ext2.
* Also, we don't use `struct odirtemplate', since it would just cause
* endianness problems.
*/
@@ -159,6 +246,39 @@ static struct dirtemplate omastertemplate = {
0, DIRBLKSIZ - 12, 2, EXT2_FT_UNKNOWN, ".."
};
+void
+ext2_itimes(vp)
+ struct vnode *vp;
+{
+ struct inode *ip;
+ struct timespec ts;
+
+ ip = VTOI(vp);
+ if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) == 0)
+ return;
+ if ((vp->v_type == VBLK || vp->v_type == VCHR))
+ ip->i_flag |= IN_LAZYMOD;
+ else
+ ip->i_flag |= IN_MODIFIED;
+ if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
+ vfs_timestamp(&ts);
+ if (ip->i_flag & IN_ACCESS) {
+ ip->i_atime = ts.tv_sec;
+ ip->i_atimensec = ts.tv_nsec;
+ }
+ if (ip->i_flag & IN_UPDATE) {
+ ip->i_mtime = ts.tv_sec;
+ ip->i_mtimensec = ts.tv_nsec;
+ ip->i_modrev++;
+ }
+ if (ip->i_flag & IN_CHANGE) {
+ ip->i_ctime = ts.tv_sec;
+ ip->i_ctimensec = ts.tv_nsec;
+ }
+ }
+ ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE);
+}
+
/*
* Create a regular file
*/
@@ -182,6 +302,375 @@ ext2_create(ap)
}
/*
+ * Open called.
+ *
+ * Nothing to do.
+ */
+int
+ext2_open(ap)
+ struct vop_open_args /* {
+ struct vnode *a_vp;
+ int a_mode;
+ struct ucred *a_cred;
+ struct thread *a_td;
+ } */ *ap;
+{
+
+ /*
+ * Files marked append-only must be opened for appending.
+ */
+ if ((VTOI(ap->a_vp)->i_flags & APPEND) &&
+ (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE)
+ return (EPERM);
+ return (0);
+}
+
+/*
+ * Close called.
+ *
+ * Update the times on the inode.
+ */
+static int
+ext2_close(ap)
+ struct vop_close_args /* {
+ struct vnode *a_vp;
+ int a_fflag;
+ struct ucred *a_cred;
+ struct thread *a_td;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+ struct mount *mp;
+
+ mtx_lock(&vp->v_interlock);
+ if (vp->v_usecount > 1) {
+ ext2_itimes(vp);
+ mtx_unlock(&vp->v_interlock);
+ } else {
+ mtx_unlock(&vp->v_interlock);
+ /*
+ * If we are closing the last reference to an unlinked
+ * file, then it will be freed by the inactive routine.
+ * Because the freeing causes a the filesystem to be
+ * modified, it must be held up during periods when the
+ * filesystem is suspended.
+ *
+ * XXX - EAGAIN is returned to prevent vn_close from
+ * repeating the vrele operation.
+ */
+ if (vp->v_type == VREG && VTOI(vp)->i_nlink == 0) {
+ (void) vn_start_write(vp, &mp, V_WAIT);
+ vrele(vp);
+ vn_finished_write(mp);
+ return (EAGAIN);
+ }
+ }
+ return (0);
+}
+
+static int
+ext2_access(ap)
+ struct vop_access_args /* {
+ struct vnode *a_vp;
+ int a_mode;
+ struct ucred *a_cred;
+ struct thread *a_td;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+ struct inode *ip = VTOI(vp);
+ mode_t mode = ap->a_mode;
+ int error;
+
+ /*
+ * Disallow write attempts on read-only file systems;
+ * unless the file is a socket, fifo, or a block or
+ * character device resident on the file system.
+ */
+ if (mode & VWRITE) {
+ switch (vp->v_type) {
+ case VDIR:
+ case VLNK:
+ case VREG:
+ if (vp->v_mount->mnt_flag & MNT_RDONLY)
+ return (EROFS);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* If immutable bit set, nobody gets to write it. */
+ if ((mode & VWRITE) && (ip->i_flags & (IMMUTABLE | SF_SNAPSHOT)))
+ return (EPERM);
+
+ error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid,
+ ap->a_mode, ap->a_cred, NULL);
+ return (error);
+}
+
+static int
+ext2_getattr(ap)
+ struct vop_getattr_args /* {
+ struct vnode *a_vp;
+ struct vattr *a_vap;
+ struct ucred *a_cred;
+ struct thread *a_td;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+ struct inode *ip = VTOI(vp);
+ struct vattr *vap = ap->a_vap;
+
+ ext2_itimes(vp);
+ /*
+ * Copy from inode table
+ */
+ vap->va_fsid = dev2udev(ip->i_dev);
+ vap->va_fileid = ip->i_number;
+ vap->va_mode = ip->i_mode & ~IFMT;
+ vap->va_nlink = ip->i_nlink;
+ vap->va_uid = ip->i_uid;
+ vap->va_gid = ip->i_gid;
+ vap->va_rdev = ip->i_rdev;
+ vap->va_size = ip->i_size;
+ vap->va_atime.tv_sec = ip->i_atime;
+ vap->va_atime.tv_nsec = ip->i_atimensec;
+ vap->va_mtime.tv_sec = ip->i_mtime;
+ vap->va_mtime.tv_nsec = ip->i_mtimensec;
+ vap->va_ctime.tv_sec = ip->i_ctime;
+ vap->va_ctime.tv_nsec = ip->i_ctimensec;
+ vap->va_flags = ip->i_flags;
+ vap->va_gen = ip->i_gen;
+ vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
+ vap->va_bytes = dbtob((u_quad_t)ip->i_blocks);
+ vap->va_type = IFTOVT(ip->i_mode);
+ vap->va_filerev = ip->i_modrev;
+ return (0);
+}
+
+/*
+ * Set attribute vnode op. called from several syscalls
+ */
+int
+ext2_setattr(ap)
+ struct vop_setattr_args /* {
+ struct vnode *a_vp;
+ struct vattr *a_vap;
+ struct ucred *a_cred;
+ struct thread *a_td;
+ } */ *ap;
+{
+ struct vattr *vap = ap->a_vap;
+ struct vnode *vp = ap->a_vp;
+ struct inode *ip = VTOI(vp);
+ struct ucred *cred = ap->a_cred;
+ struct thread *td = ap->a_td;
+ int error;
+
+ /*
+ * Check for unsettable attributes.
+ */
+ if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
+ (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
+ (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
+ ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
+ return (EINVAL);
+ }
+ if (vap->va_flags != VNOVAL) {
+ if (vp->v_mount->mnt_flag & MNT_RDONLY)
+ return (EROFS);
+ /*
+ * Callers may only modify the file flags on objects they
+ * have VADMIN rights for.
+ */
+ if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
+ return (error);
+ /*
+ * Unprivileged processes and privileged processes in
+ * jail() are not permitted to unset system flags, or
+ * modify flags if any system flags are set.
+ * Privileged non-jail processes may not modify system flags
+ * if securelevel > 0 and any existing system flags are set.
+ */
+ if (!suser_cred(cred, PRISON_ROOT)) {
+ if (ip->i_flags
+ & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) {
+ error = securelevel_gt(cred, 0);
+ if (error)
+ return (error);
+ }
+ ip->i_flags = vap->va_flags;
+ } else {
+ if (ip->i_flags
+ & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND) ||
+ (vap->va_flags & UF_SETTABLE) != vap->va_flags)
+ return (EPERM);
+ ip->i_flags &= SF_SETTABLE;
+ ip->i_flags |= (vap->va_flags & UF_SETTABLE);
+ }
+ ip->i_flag |= IN_CHANGE;
+ if (vap->va_flags & (IMMUTABLE | APPEND))
+ return (0);
+ }
+ if (ip->i_flags & (IMMUTABLE | APPEND))
+ return (EPERM);
+ /*
+ * Go through the fields and update iff not VNOVAL.
+ */
+ if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
+ if (vp->v_mount->mnt_flag & MNT_RDONLY)
+ return (EROFS);
+ if ((error = ext2_chown(vp, vap->va_uid, vap->va_gid, cred,
+ td)) != 0)
+ return (error);
+ }
+ if (vap->va_size != VNOVAL) {
+ /*
+ * Disallow write attempts on read-only file systems;
+ * unless the file is a socket, fifo, or a block or
+ * character device resident on the file system.
+ */
+ switch (vp->v_type) {
+ case VDIR:
+ return (EISDIR);
+ case VLNK:
+ case VREG:
+ if (vp->v_mount->mnt_flag & MNT_RDONLY)
+ return (EROFS);
+ break;
+ default:
+ break;
+ }
+ if ((error = ext2_truncate(vp, vap->va_size, 0, cred, td)) != 0)
+ return (error);
+ }
+ if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
+ if (vp->v_mount->mnt_flag & MNT_RDONLY)
+ return (EROFS);
+ /*
+ * From utimes(2):
+ * If times is NULL, ... The caller must be the owner of
+ * the file, have permission to write the file, or be the
+ * super-user.
+ * If times is non-NULL, ... The caller must be the owner of
+ * the file or be the super-user.
+ */
+ if ((error = VOP_ACCESS(vp, VADMIN, cred, td)) &&
+ ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
+ (error = VOP_ACCESS(vp, VWRITE, cred, td))))
+ return (error);
+ if (vap->va_atime.tv_sec != VNOVAL)
+ ip->i_flag |= IN_ACCESS;
+ if (vap->va_mtime.tv_sec != VNOVAL)
+ ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ ext2_itimes(vp);
+ if (vap->va_atime.tv_sec != VNOVAL) {
+ ip->i_atime = vap->va_atime.tv_sec;
+ ip->i_atimensec = vap->va_atime.tv_nsec;
+ }
+ if (vap->va_mtime.tv_sec != VNOVAL) {
+ ip->i_mtime = vap->va_mtime.tv_sec;
+ ip->i_mtimensec = vap->va_mtime.tv_nsec;
+ }
+ error = ext2_update(vp, 0);
+ if (error)
+ return (error);
+ }
+ error = 0;
+ if (vap->va_mode != (mode_t)VNOVAL) {
+ if (vp->v_mount->mnt_flag & MNT_RDONLY)
+ return (EROFS);
+ error = ext2_chmod(vp, (int)vap->va_mode, cred, td);
+ }
+ VN_KNOTE(vp, NOTE_ATTRIB);
+ return (error);
+}
+
+/*
+ * Change the mode on a file.
+ * Inode must be locked before calling.
+ */
+static int
+ext2_chmod(vp, mode, cred, td)
+ struct vnode *vp;
+ int mode;
+ struct ucred *cred;
+ struct thread *td;
+{
+ struct inode *ip = VTOI(vp);
+ int error;
+
+ /*
+ * To modify the permissions on a file, must possess VADMIN
+ * for that file.
+ */
+ if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
+ return (error);
+ /*
+ * Privileged processes may set the sticky bit on non-directories,
+ * as well as set the setgid bit on a file with a group that the
+ * process is not a member of.
+ */
+ if (suser_cred(cred, PRISON_ROOT)) {
+ if (vp->v_type != VDIR && (mode & S_ISTXT))
+ return (EFTYPE);
+ if (!groupmember(ip->i_gid, cred) && (mode & ISGID))
+ return (EPERM);
+ }
+ ip->i_mode &= ~ALLPERMS;
+ ip->i_mode |= (mode & ALLPERMS);
+ ip->i_flag |= IN_CHANGE;
+ return (0);
+}
+
+/*
+ * Perform chown operation on inode ip;
+ * inode must be locked prior to call.
+ */
+static int
+ext2_chown(vp, uid, gid, cred, td)
+ struct vnode *vp;
+ uid_t uid;
+ gid_t gid;
+ struct ucred *cred;
+ struct thread *td;
+{
+ struct inode *ip = VTOI(vp);
+ uid_t ouid;
+ gid_t ogid;
+ int error = 0;
+
+ if (uid == (uid_t)VNOVAL)
+ uid = ip->i_uid;
+ if (gid == (gid_t)VNOVAL)
+ gid = ip->i_gid;
+ /*
+ * To modify the ownership of a file, must possess VADMIN
+ * for that file.
+ */
+ if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
+ return (error);
+ /*
+ * To change the owner of a file, or change the group of a file
+ * to a group of which we are not a member, the caller must
+ * have privilege.
+ */
+ if ((uid != ip->i_uid ||
+ (gid != ip->i_gid && !groupmember(gid, cred))) &&
+ (error = suser_cred(cred, PRISON_ROOT)))
+ return (error);
+ ogid = ip->i_gid;
+ ouid = ip->i_uid;
+ ip->i_gid = gid;
+ ip->i_uid = uid;
+ ip->i_flag |= IN_CHANGE;
+ if (suser_cred(cred, PRISON_ROOT) && (ouid != uid || ogid != gid))
+ ip->i_mode &= ~(ISUID | ISGID);
+ return (0);
+}
+
+/*
* Synch an open file.
*/
/* ARGSUSED */
@@ -241,7 +730,7 @@ loop:
#endif
}
splx(s);
- return (UFS_UPDATE(ap->a_vp, ap->a_waitfor == MNT_WAIT));
+ return (ext2_update(ap->a_vp, ap->a_waitfor == MNT_WAIT));
}
/*
@@ -341,7 +830,7 @@ ext2_link(ap)
#ifdef DIAGNOSTIC
if ((cnp->cn_flags & HASBUF) == 0)
- panic("ufs_link: no name");
+ panic("ext2_link: no name");
#endif
if (tdvp->v_mount != vp->v_mount) {
error = EXDEV;
@@ -361,7 +850,7 @@ ext2_link(ap)
}
ip->i_nlink++;
ip->i_flag |= IN_CHANGE;
- error = UFS_UPDATE(vp, 1);
+ error = ext2_update(vp, 1);
if (!error)
error = ext2_direnter(ip, tdvp, cnp);
if (error) {
@@ -406,7 +895,7 @@ ext2_rename(ap)
#ifdef DIAGNOSTIC
if ((tcnp->cn_flags & HASBUF) == 0 ||
(fcnp->cn_flags & HASBUF) == 0)
- panic("ufs_rename: no name");
+ panic("ext2_rename: no name");
#endif
/*
* Check for cross-device rename.
@@ -447,7 +936,7 @@ abortit:
* completed before the lookup.
*/
#ifdef UFS_RENAME_DEBUG
- printf("ufs_rename: fvp == tvp for directories\n");
+ printf("ext2_rename: fvp == tvp for directories\n");
#endif
error = ENOENT;
goto abortit;
@@ -474,7 +963,7 @@ abortit:
vrele(fdvp);
if (fvp == NULL) {
#ifdef UFS_RENAME_DEBUG
- printf("ufs_rename: from name disappeared\n");
+ printf("ext2_rename: from name disappeared\n");
#endif
return (ENOENT);
}
@@ -536,7 +1025,7 @@ abortit:
*/
ip->i_nlink++;
ip->i_flag |= IN_CHANGE;
- if ((error = UFS_UPDATE(fvp, 1)) != 0) {
+ if ((error = ext2_update(fvp, 1)) != 0) {
VOP_UNLOCK(fvp, 0, td);
goto bad;
}
@@ -582,7 +1071,7 @@ abortit:
*/
if (xp == NULL) {
if (dp->i_dev != ip->i_dev)
- panic("ufs_rename: EXDEV");
+ panic("ext2_rename: EXDEV");
/*
* Account for ".." in new directory.
* When source and destination have the same
@@ -595,7 +1084,7 @@ abortit:
}
dp->i_nlink++;
dp->i_flag |= IN_CHANGE;
- error = UFS_UPDATE(tdvp, 1);
+ error = ext2_update(tdvp, 1);
if (error)
goto bad;
}
@@ -604,19 +1093,19 @@ abortit:
if (doingdirectory && newparent) {
dp->i_nlink--;
dp->i_flag |= IN_CHANGE;
- (void)UFS_UPDATE(tdvp, 1);
+ (void)ext2_update(tdvp, 1);
}
goto bad;
}
vput(tdvp);
} else {
if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev)
- panic("ufs_rename: EXDEV");
+ panic("ext2_rename: EXDEV");
/*
* Short circuit rename(foo, foo).
*/
if (xp->i_number == ip->i_number)
- panic("ufs_rename: same file");
+ panic("ext2_rename: same file");
/*
* If the parent directory is "sticky", then the user must
* own the parent directory, or the destination of the rename,
@@ -676,8 +1165,8 @@ abortit:
xp->i_nlink--;
if (doingdirectory) {
if (--xp->i_nlink != 0)
- panic("ufs_rename: linked directory");
- error = UFS_TRUNCATE(tvp, (off_t)0, IO_SYNC,
+ panic("ext2_rename: linked directory");
+ error = ext2_truncate(tvp, (off_t)0, IO_SYNC,
tcnp->cn_cred, tcnp->cn_thread);
}
xp->i_flag |= IN_CHANGE;
@@ -702,7 +1191,7 @@ abortit:
* From name has disappeared.
*/
if (doingdirectory)
- panic("ufs_rename: lost dir entry");
+ panic("ext2_rename: lost dir entry");
vrele(ap->a_fvp);
return (0);
}
@@ -718,7 +1207,7 @@ abortit:
*/
if (xp != ip) {
if (doingdirectory)
- panic("ufs_rename: lost dir entry");
+ panic("ext2_rename: lost dir entry");
} else {
/*
* If the source is a directory with a
@@ -739,7 +1228,7 @@ abortit:
if (namlen != 2 ||
dirbuf.dotdot_name[0] != '.' ||
dirbuf.dotdot_name[1] != '.') {
- ufs_dirbad(xp, (doff_t)12,
+ ext2_dirbad(xp, (doff_t)12,
"rename: mangled dir");
} else {
dirbuf.dotdot_ino = newparent;
@@ -807,7 +1296,7 @@ ext2_mkdir(ap)
#ifdef DIAGNOSTIC
if ((cnp->cn_flags & HASBUF) == 0)
- panic("ufs_mkdir: no name");
+ panic("ext2_mkdir: no name");
#endif
dp = VTOI(dvp);
if ((nlink_t)dp->i_nlink >= LINK_MAX) {
@@ -821,17 +1310,13 @@ ext2_mkdir(ap)
* but not have it entered in the parent directory. The entry is
* made later after writing "." and ".." entries.
*/
- error = UFS_VALLOC(dvp, dmode, cnp->cn_cred, &tvp);
+ error = ext2_valloc(dvp, dmode, cnp->cn_cred, &tvp);
if (error)
goto out;
ip = VTOI(tvp);
ip->i_gid = dp->i_gid;
#ifdef SUIDDIR
{
-#ifdef QUOTA
- struct ucred ucred, *ucp;
- ucp = cnp->cn_cred;
-#endif
/*
* if we are hacking owners here, (only do this where told to)
* and we are not giving it TOO root, (would subvert quotas)
@@ -844,44 +1329,12 @@ ext2_mkdir(ap)
(dp->i_mode & ISUID) && dp->i_uid) {
dmode |= ISUID;
ip->i_uid = dp->i_uid;
-#ifdef QUOTA
- if (dp->i_uid != cnp->cn_cred->cr_uid) {
- /*
- * make sure the correct user gets charged
- * for the space.
- * Make a dummy credential for the victim.
- * XXX This seems to never be accessed out of
- * our context so a stack variable is ok.
- */
- ucred.cr_ref = 1;
- ucred.cr_uid = ip->i_uid;
- ucred.cr_ngroups = 1;
- ucred.cr_groups[0] = dp->i_gid;
- ucp = &ucred;
- }
-#endif
} else {
ip->i_uid = cnp->cn_cred->cr_uid;
}
-#ifdef QUOTA
- if ((error = getinoquota(ip)) ||
- (error = chkiq(ip, 1, ucp, 0))) {
- UFS_VFREE(tvp, ip->i_number, dmode);
- vput(tvp);
- return (error);
- }
-#endif
}
#else
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, dmode);
- vput(tvp);
- return (error);
- }
-#endif
#endif
ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
ip->i_mode = dmode;
@@ -889,7 +1342,7 @@ ext2_mkdir(ap)
ip->i_nlink = 2;
if (cnp->cn_flags & ISWHITEOUT)
ip->i_flags |= UF_OPAQUE;
- error = UFS_UPDATE(tvp, 1);
+ error = ext2_update(tvp, 1);
/*
* Bump link count in parent directory
@@ -899,7 +1352,7 @@ ext2_mkdir(ap)
*/
dp->i_nlink++;
dp->i_flag |= IN_CHANGE;
- error = UFS_UPDATE(dvp, 1);
+ error = ext2_update(dvp, 1);
if (error)
goto bad;
@@ -926,8 +1379,9 @@ ext2_mkdir(ap)
dp->i_flag |= IN_CHANGE;
goto bad;
}
- if (DIRBLKSIZ > VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_bsize)
- panic("ufs_mkdir: blksize"); /* XXX should grow with balloc() */
+ if (DIRBLKSIZ > VFSTOEXT2(dvp->v_mount)->um_mountp->mnt_stat.f_bsize)
+ /* XXX should grow with balloc() */
+ panic("ext2_mkdir: blksize");
else {
ip->i_size = DIRBLKSIZ;
ip->i_flag |= IN_CHANGE;
@@ -1018,7 +1472,7 @@ ext2_rmdir(ap)
* worry about them later.
*/
ip->i_nlink -= 2;
- error = UFS_TRUNCATE(vp, (off_t)0, IO_SYNC, cnp->cn_cred, td);
+ error = ext2_truncate(vp, (off_t)0, IO_SYNC, cnp->cn_cred, td);
cache_purge(ITOV(ip));
vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
out:
@@ -1063,6 +1517,362 @@ ext2_symlink(ap)
}
/*
+ * Return target name of a symbolic link
+ */
+static int
+ext2_readlink(ap)
+ struct vop_readlink_args /* {
+ struct vnode *a_vp;
+ struct uio *a_uio;
+ struct ucred *a_cred;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+ struct inode *ip = VTOI(vp);
+ int isize;
+
+ isize = ip->i_size;
+ if (isize < vp->v_mount->mnt_maxsymlinklen) {
+ uiomove((char *)ip->i_shortlink, isize, ap->a_uio);
+ return (0);
+ }
+ return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
+}
+
+/*
+ * Calculate the logical to physical mapping if not done already,
+ * then call the device strategy routine.
+ *
+ * In order to be able to swap to a file, the ext2_bmaparray() operation may not
+ * deadlock on memory. See ext2_bmap() for details.
+ */
+int
+ext2_strategy(ap)
+ struct vop_strategy_args /* {
+ struct vnode *a_vp;
+ struct buf *a_bp;
+ } */ *ap;
+{
+ struct buf *bp = ap->a_bp;
+ struct vnode *vp = ap->a_vp;
+ struct inode *ip;
+ daddr_t blkno;
+ int error;
+
+ ip = VTOI(vp);
+ if (vp->v_type == VBLK || vp->v_type == VCHR)
+ panic("ext2_strategy: spec");
+ if (bp->b_blkno == bp->b_lblkno) {
+ error = ext2_bmaparray(vp, bp->b_lblkno, &blkno, NULL, NULL);
+ bp->b_blkno = blkno;
+ if (error) {
+ bp->b_error = error;
+ bp->b_ioflags |= BIO_ERROR;
+ bufdone(bp);
+ return (error);
+ }
+ if ((long)bp->b_blkno == -1)
+ vfs_bio_clrbuf(bp);
+ }
+ if ((long)bp->b_blkno == -1) {
+ bufdone(bp);
+ return (0);
+ }
+ vp = ip->i_devvp;
+ bp->b_dev = vp->v_rdev;
+ VOP_STRATEGY(vp, bp);
+ return (0);
+}
+
+/*
+ * Print out the contents of an inode.
+ */
+int
+ext2_print(ap)
+ struct vop_print_args /* {
+ struct vnode *a_vp;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+ struct inode *ip = VTOI(vp);
+
+ printf("tag VT_UFS, ino %lu, on dev %s (%d, %d)",
+ (u_long)ip->i_number, devtoname(ip->i_dev), major(ip->i_dev),
+ minor(ip->i_dev));
+ if (vp->v_type == VFIFO)
+ fifo_printinfo(vp);
+ lockmgr_printinfo(&vp->v_lock);
+ printf("\n");
+ return (0);
+}
+
+/*
+ * Read wrapper for special devices.
+ */
+int
+ext2spec_read(ap)
+ struct vop_read_args /* {
+ struct vnode *a_vp;
+ struct uio *a_uio;
+ int a_ioflag;
+ struct ucred *a_cred;
+ } */ *ap;
+{
+ int error, resid;
+ struct inode *ip;
+ struct uio *uio;
+
+ uio = ap->a_uio;
+ resid = uio->uio_resid;
+ error = VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap);
+ /*
+ * The inode may have been revoked during the call, so it must not
+ * be accessed blindly here or in the other wrapper functions.
+ */
+ ip = VTOI(ap->a_vp);
+ if (ip != NULL && (uio->uio_resid != resid || (error == 0 && resid != 0)))
+ ip->i_flag |= IN_ACCESS;
+ return (error);
+}
+
+/*
+ * Write wrapper for special devices.
+ */
+int
+ext2spec_write(ap)
+ struct vop_write_args /* {
+ struct vnode *a_vp;
+ struct uio *a_uio;
+ int a_ioflag;
+ struct ucred *a_cred;
+ } */ *ap;
+{
+ int error, resid;
+ struct inode *ip;
+ struct uio *uio;
+
+ uio = ap->a_uio;
+ resid = uio->uio_resid;
+ error = VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap);
+ ip = VTOI(ap->a_vp);
+ if (ip != NULL && (uio->uio_resid != resid || (error == 0 && resid != 0)))
+ VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE;
+ return (error);
+}
+
+/*
+ * Close wrapper for special devices.
+ *
+ * Update the times on the inode then do device close.
+ */
+int
+ext2spec_close(ap)
+ struct vop_close_args /* {
+ struct vnode *a_vp;
+ int a_fflag;
+ struct ucred *a_cred;
+ struct thread *a_td;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+
+ mtx_lock(&vp->v_interlock);
+ if (vp->v_usecount > 1)
+ ext2_itimes(vp);
+ mtx_unlock(&vp->v_interlock);
+ return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap));
+}
+
+/*
+ * Read wrapper for fifos.
+ */
+int
+ext2fifo_read(ap)
+ struct vop_read_args /* {
+ struct vnode *a_vp;
+ struct uio *a_uio;
+ int a_ioflag;
+ struct ucred *a_cred;
+ } */ *ap;
+{
+ int error, resid;
+ struct inode *ip;
+ struct uio *uio;
+
+ uio = ap->a_uio;
+ resid = uio->uio_resid;
+ error = VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap);
+ ip = VTOI(ap->a_vp);
+ if ((ap->a_vp->v_mount->mnt_flag & MNT_NOATIME) == 0 && ip != NULL &&
+ (uio->uio_resid != resid || (error == 0 && resid != 0)))
+ VTOI(ap->a_vp)->i_flag |= IN_ACCESS;
+ return (error);
+}
+
+/*
+ * Write wrapper for fifos.
+ */
+int
+ext2fifo_write(ap)
+ struct vop_write_args /* {
+ struct vnode *a_vp;
+ struct uio *a_uio;
+ int a_ioflag;
+ struct ucred *a_cred;
+ } */ *ap;
+{
+ int error, resid;
+ struct inode *ip;
+ struct uio *uio;
+
+ uio = ap->a_uio;
+ resid = uio->uio_resid;
+ error = VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap);
+ ip = VTOI(ap->a_vp);
+ if (ip != NULL && (uio->uio_resid != resid || (error == 0 && resid != 0)))
+ VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE;
+ return (error);
+}
+
+/*
+ * Close wrapper for fifos.
+ *
+ * Update the times on the inode then do device close.
+ */
+int
+ext2fifo_close(ap)
+ struct vop_close_args /* {
+ struct vnode *a_vp;
+ int a_fflag;
+ struct ucred *a_cred;
+ struct thread *a_td;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+
+ mtx_lock(&vp->v_interlock);
+ if (vp->v_usecount > 1)
+ ext2_itimes(vp);
+ mtx_unlock(&vp->v_interlock);
+ return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap));
+}
+
+/*
+ * Kqfilter wrapper for fifos.
+ *
+ * Fall through to ext2 kqfilter routines if needed
+ */
+int
+ext2fifo_kqfilter(ap)
+ struct vop_kqfilter_args *ap;
+{
+ int error;
+
+ error = VOCALL(fifo_vnodeop_p, VOFFSET(vop_kqfilter), ap);
+ if (error)
+ error = ext2_kqfilter(ap);
+ return (error);
+}
+
+/*
+ * Return POSIX pathconf information applicable to ext2 filesystems.
+ */
+int
+ext2_pathconf(ap)
+ struct vop_pathconf_args /* {
+ struct vnode *a_vp;
+ int a_name;
+ int *a_retval;
+ } */ *ap;
+{
+
+ switch (ap->a_name) {
+ case _PC_LINK_MAX:
+ *ap->a_retval = LINK_MAX;
+ return (0);
+ case _PC_NAME_MAX:
+ *ap->a_retval = NAME_MAX;
+ return (0);
+ case _PC_PATH_MAX:
+ *ap->a_retval = PATH_MAX;
+ return (0);
+ case _PC_PIPE_BUF:
+ *ap->a_retval = PIPE_BUF;
+ return (0);
+ case _PC_CHOWN_RESTRICTED:
+ *ap->a_retval = 1;
+ return (0);
+ case _PC_NO_TRUNC:
+ *ap->a_retval = 1;
+ return (0);
+ default:
+ return (EINVAL);
+ }
+ /* NOTREACHED */
+}
+
+/*
+ * Advisory record locking support
+ */
+static int
+ext2_advlock(ap)
+ struct vop_advlock_args /* {
+ struct vnode *a_vp;
+ caddr_t a_id;
+ int a_op;
+ struct flock *a_fl;
+ int a_flags;
+ } */ *ap;
+{
+ struct inode *ip = VTOI(ap->a_vp);
+
+ return (lf_advlock(ap, &(ip->i_lockf), ip->i_size));
+}
+
+/*
+ * Initialize the vnode associated with a new inode, handle aliased
+ * vnodes.
+ */
+int
+ext2_vinit(mntp, specops, fifoops, vpp)
+ struct mount *mntp;
+ vop_t **specops;
+ vop_t **fifoops;
+ struct vnode **vpp;
+{
+ struct inode *ip;
+ struct vnode *vp;
+ struct timeval tv;
+
+ vp = *vpp;
+ ip = VTOI(vp);
+ switch(vp->v_type = IFTOVT(ip->i_mode)) {
+ case VCHR:
+ case VBLK:
+ vp->v_op = specops;
+ vp = addaliasu(vp, ip->i_rdev);
+ ip->i_vnode = vp;
+ break;
+ case VFIFO:
+ vp->v_op = fifoops;
+ break;
+ default:
+ break;
+
+ }
+ if (ip->i_number == ROOTINO)
+ vp->v_flag |= VROOT;
+ /*
+ * Initialize modrev times
+ */
+ getmicrouptime(&tv);
+ SETHIGH(ip->i_modrev, tv.tv_sec);
+ SETLOW(ip->i_modrev, tv.tv_usec * 4294);
+ *vpp = vp;
+ return (0);
+}
+
+/*
* Allocate a new inode.
*/
static int
@@ -1085,7 +1895,7 @@ ext2_makeinode(mode, dvp, vpp, cnp)
if ((mode & IFMT) == 0)
mode |= IFREG;
- error = UFS_VALLOC(dvp, mode, cnp->cn_cred, &tvp);
+ error = ext2_valloc(dvp, mode, cnp->cn_cred, &tvp);
if (error) {
return (error);
}
@@ -1093,10 +1903,6 @@ ext2_makeinode(mode, dvp, vpp, cnp)
ip->i_gid = pdir->i_gid;
#ifdef SUIDDIR
{
-#ifdef QUOTA
- struct ucred ucred, *ucp;
- ucp = cnp->cn_cred;
-#endif
/*
* if we are
* not the owner of the directory,
@@ -1110,43 +1916,12 @@ ext2_makeinode(mode, dvp, vpp, cnp)
(pdir->i_uid != cnp->cn_cred->cr_uid) && pdir->i_uid) {
ip->i_uid = pdir->i_uid;
mode &= ~07111;
-#ifdef QUOTA
- /*
- * make sure the correct user gets charged
- * for the space.
- * Quickly knock up a dummy credential for the victim.
- * XXX This seems to never be accessed out of our
- * context so a stack variable is ok.
- */
- ucred.cr_ref = 1;
- ucred.cr_uid = ip->i_uid;
- ucred.cr_ngroups = 1;
- ucred.cr_groups[0] = pdir->i_gid;
- ucp = &ucred;
-#endif
} else {
ip->i_uid = cnp->cn_cred->cr_uid;
}
-
-#ifdef QUOTA
- if ((error = getinoquota(ip)) ||
- (error = chkiq(ip, 1, ucp, 0))) {
- UFS_VFREE(tvp, ip->i_number, mode);
- vput(tvp);
- return (error);
- }
-#endif
}
#else
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
#endif
ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
ip->i_mode = mode;
@@ -1162,7 +1937,7 @@ ext2_makeinode(mode, dvp, vpp, cnp)
/*
* Make sure inode goes to disk before directory entry.
*/
- error = UFS_UPDATE(tvp, 1);
+ error = ext2_update(tvp, 1);
if (error)
goto bad;
error = ext2_direnter(ip, dvp, cnp);
@@ -1182,3 +1957,106 @@ bad:
vput(tvp);
return (error);
}
+
+static struct filterops ext2read_filtops =
+ { 1, NULL, filt_ext2detach, filt_ext2read };
+static struct filterops ext2write_filtops =
+ { 1, NULL, filt_ext2detach, filt_ext2write };
+static struct filterops ext2vnode_filtops =
+ { 1, NULL, filt_ext2detach, filt_ext2vnode };
+
+static int
+ext2_kqfilter(ap)
+ struct vop_kqfilter_args /* {
+ struct vnode *a_vp;
+ struct knote *a_kn;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+ struct knote *kn = ap->a_kn;
+
+ switch (kn->kn_filter) {
+ case EVFILT_READ:
+ kn->kn_fop = &ext2read_filtops;
+ break;
+ case EVFILT_WRITE:
+ kn->kn_fop = &ext2write_filtops;
+ break;
+ case EVFILT_VNODE:
+ kn->kn_fop = &ext2vnode_filtops;
+ break;
+ default:
+ return (1);
+ }
+
+ kn->kn_hook = (caddr_t)vp;
+
+ if (vp->v_pollinfo == NULL)
+ v_addpollinfo(vp);
+ mtx_lock(&vp->v_pollinfo->vpi_lock);
+ SLIST_INSERT_HEAD(&vp->v_pollinfo->vpi_selinfo.si_note, kn, kn_selnext);
+ mtx_unlock(&vp->v_pollinfo->vpi_lock);
+
+ return (0);
+}
+
+static void
+filt_ext2detach(struct knote *kn)
+{
+ struct vnode *vp = (struct vnode *)kn->kn_hook;
+
+ KASSERT(vp->v_pollinfo != NULL, ("Mising v_pollinfo"));
+ mtx_lock(&vp->v_pollinfo->vpi_lock);
+ SLIST_REMOVE(&vp->v_pollinfo->vpi_selinfo.si_note,
+ kn, knote, kn_selnext);
+ mtx_unlock(&vp->v_pollinfo->vpi_lock);
+}
+
+/*ARGSUSED*/
+static int
+filt_ext2read(struct knote *kn, long hint)
+{
+ struct vnode *vp = (struct vnode *)kn->kn_hook;
+ struct inode *ip = VTOI(vp);
+
+ /*
+ * filesystem is gone, so set the EOF flag and schedule
+ * the knote for deletion.
+ */
+ if (hint == NOTE_REVOKE) {
+ kn->kn_flags |= (EV_EOF | EV_ONESHOT);
+ return (1);
+ }
+
+ kn->kn_data = ip->i_size - kn->kn_fp->f_offset;
+ return (kn->kn_data != 0);
+}
+
+/*ARGSUSED*/
+static int
+filt_ext2write(struct knote *kn, long hint)
+{
+
+ /*
+ * filesystem is gone, so set the EOF flag and schedule
+ * the knote for deletion.
+ */
+ if (hint == NOTE_REVOKE)
+ kn->kn_flags |= (EV_EOF | EV_ONESHOT);
+
+ kn->kn_data = 0;
+ return (1);
+}
+
+static int
+filt_ext2vnode(struct knote *kn, long hint)
+{
+
+ if (kn->kn_sfflags & hint)
+ kn->kn_fflags |= hint;
+ if (hint == NOTE_REVOKE) {
+ kn->kn_flags |= EV_EOF;
+ return (1);
+ }
+ return (kn->kn_fflags != 0);
+}
diff --git a/sys/gnu/ext2fs/fs.h b/sys/gnu/ext2fs/fs.h
index 785f267f8ac3..50fb711f371f 100644
--- a/sys/gnu/ext2fs/fs.h
+++ b/sys/gnu/ext2fs/fs.h
@@ -148,7 +148,7 @@ extern u_char *fragtbl[];
* I haven't figured out yet what BSD does
* I think I'll try a VOP_LOCK/VOP_UNLOCK on the device vnode
*/
-#define DEVVP(inode) (VFSTOUFS(ITOV(inode)->v_mount)->um_devvp)
+#define DEVVP(inode) (VFSTOEXT2(ITOV(inode)->v_mount)->um_devvp)
#define lock_super(devvp) vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, curthread)
#define unlock_super(devvp) VOP_UNLOCK(devvp, 0, curthread)