summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/conf/files2
-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
-rw-r--r--sys/gnu/fs/ext2fs/ext2_alloc.c26
-rw-r--r--sys/gnu/fs/ext2fs/ext2_balloc.c9
-rw-r--r--sys/gnu/fs/ext2fs/ext2_extern.h29
-rw-r--r--sys/gnu/fs/ext2fs/ext2_fs.h23
-rw-r--r--sys/gnu/fs/ext2fs/ext2_inode.c118
-rw-r--r--sys/gnu/fs/ext2fs/ext2_inode_cnv.c151
-rw-r--r--sys/gnu/fs/ext2fs/ext2_linux_balloc.c45
-rw-r--r--sys/gnu/fs/ext2fs/ext2_linux_ialloc.c22
-rw-r--r--sys/gnu/fs/ext2fs/ext2_lookup.c49
-rw-r--r--sys/gnu/fs/ext2fs/ext2_readwrite.c4
-rw-r--r--sys/gnu/fs/ext2fs/ext2_subr.c6
-rw-r--r--sys/gnu/fs/ext2fs/ext2_vfsops.c193
-rw-r--r--sys/gnu/fs/ext2fs/ext2_vnops.c1114
-rw-r--r--sys/gnu/fs/ext2fs/fs.h2
-rw-r--r--sys/modules/ext2fs/Makefile6
30 files changed, 2689 insertions, 901 deletions
diff --git a/sys/conf/files b/sys/conf/files
index e7f520a..2fb96e8 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -732,6 +732,8 @@ geom/geom_sunlabel.c optional geom
gnu/ext2fs/ext2_alloc.c optional ext2fs \
warning "kernel contains GPL contaminated ext2fs file system"
gnu/ext2fs/ext2_balloc.c optional ext2fs
+gnu/ext2fs/ext2_bmap.c optional ext2fs
+gnu/ext2fs/ext2_ihash.c optional ext2fs
gnu/ext2fs/ext2_inode.c optional ext2fs
gnu/ext2fs/ext2_inode_cnv.c optional ext2fs
gnu/ext2fs/ext2_linux_balloc.c optional ext2fs
diff --git a/sys/gnu/ext2fs/ext2_alloc.c b/sys/gnu/ext2fs/ext2_alloc.c
index b9c40d3..585c5cd 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 275849f..252a297 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 8df829b..505fefd 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 b5e9f4a..2943593 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 2f0aed4..207778c 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 3e8e0ff..d64e549 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 fc72311..6320440 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 01ae55b..64d96b2 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 2c1de41..14b78b5 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 2772f7b..73f900c 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 69eecf1..587ed05 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 54c4305..b9afe91 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 180ac3d..ba7b714 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 785f267..50fb711 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)
diff --git a/sys/gnu/fs/ext2fs/ext2_alloc.c b/sys/gnu/fs/ext2fs/ext2_alloc.c
index b9c40d3..585c5cd 100644
--- a/sys/gnu/fs/ext2fs/ext2_alloc.c
+++ b/sys/gnu/fs/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/fs/ext2fs/ext2_balloc.c b/sys/gnu/fs/ext2fs/ext2_balloc.c
index 275849f..252a297 100644
--- a/sys/gnu/fs/ext2fs/ext2_balloc.c
+++ b/sys/gnu/fs/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/fs/ext2fs/ext2_extern.h b/sys/gnu/fs/ext2fs/ext2_extern.h
index 8df829b..505fefd 100644
--- a/sys/gnu/fs/ext2fs/ext2_extern.h
+++ b/sys/gnu/fs/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/fs/ext2fs/ext2_fs.h b/sys/gnu/fs/ext2fs/ext2_fs.h
index b5e9f4a..2943593 100644
--- a/sys/gnu/fs/ext2fs/ext2_fs.h
+++ b/sys/gnu/fs/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/fs/ext2fs/ext2_inode.c b/sys/gnu/fs/ext2fs/ext2_inode.c
index 2f0aed4..207778c 100644
--- a/sys/gnu/fs/ext2fs/ext2_inode.c
+++ b/sys/gnu/fs/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/fs/ext2fs/ext2_inode_cnv.c b/sys/gnu/fs/ext2fs/ext2_inode_cnv.c
index 3e8e0ff..d64e549 100644
--- a/sys/gnu/fs/ext2fs/ext2_inode_cnv.c
+++ b/sys/gnu/fs/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/fs/ext2fs/ext2_linux_balloc.c b/sys/gnu/fs/ext2fs/ext2_linux_balloc.c
index fc72311..6320440 100644
--- a/sys/gnu/fs/ext2fs/ext2_linux_balloc.c
+++ b/sys/gnu/fs/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/fs/ext2fs/ext2_linux_ialloc.c b/sys/gnu/fs/ext2fs/ext2_linux_ialloc.c
index 01ae55b..64d96b2 100644
--- a/sys/gnu/fs/ext2fs/ext2_linux_ialloc.c
+++ b/sys/gnu/fs/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/fs/ext2fs/ext2_lookup.c b/sys/gnu/fs/ext2fs/ext2_lookup.c
index 2c1de41..14b78b5 100644
--- a/sys/gnu/fs/ext2fs/ext2_lookup.c
+++ b/sys/gnu/fs/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/fs/ext2fs/ext2_readwrite.c b/sys/gnu/fs/ext2fs/ext2_readwrite.c
index 2772f7b..73f900c 100644
--- a/sys/gnu/fs/ext2fs/ext2_readwrite.c
+++ b/sys/gnu/fs/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/fs/ext2fs/ext2_subr.c b/sys/gnu/fs/ext2fs/ext2_subr.c
index 69eecf1..587ed05 100644
--- a/sys/gnu/fs/ext2fs/ext2_subr.c
+++ b/sys/gnu/fs/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/fs/ext2fs/ext2_vfsops.c b/sys/gnu/fs/ext2fs/ext2_vfsops.c
index 54c4305..b9afe91 100644
--- a/sys/gnu/fs/ext2fs/ext2_vfsops.c
+++ b/sys/gnu/fs/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/fs/ext2fs/ext2_vnops.c b/sys/gnu/fs/ext2fs/ext2_vnops.c
index 180ac3d..ba7b714 100644
--- a/sys/gnu/fs/ext2fs/ext2_vnops.c
+++ b/sys/gnu/fs/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/fs/ext2fs/fs.h b/sys/gnu/fs/ext2fs/fs.h
index 785f267..50fb711 100644
--- a/sys/gnu/fs/ext2fs/fs.h
+++ b/sys/gnu/fs/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)
diff --git a/sys/modules/ext2fs/Makefile b/sys/modules/ext2fs/Makefile
index 9de1d6c..b746452 100644
--- a/sys/modules/ext2fs/Makefile
+++ b/sys/modules/ext2fs/Makefile
@@ -3,8 +3,8 @@
.PATH: ${.CURDIR}/../../gnu/ext2fs
KMOD= ext2fs
SRCS= opt_ddb.h opt_quota.h opt_suiddir.h vnode_if.h \
- ext2_alloc.c ext2_balloc.c ext2_inode.c ext2_inode_cnv.c \
- ext2_linux_balloc.c ext2_linux_ialloc.c ext2_lookup.c ext2_subr.c \
- ext2_vfsops.c ext2_vnops.c
+ ext2_alloc.c ext2_balloc.c ext2_bmap.c ext2_ihash.c ext2_inode.c \
+ ext2_inode_cnv.c ext2_linux_balloc.c ext2_linux_ialloc.c \
+ ext2_lookup.c ext2_subr.c ext2_vfsops.c ext2_vnops.c
.include <bsd.kmod.mk>
OpenPOWER on IntegriCloud