summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorjasoni <jasoni@cvs.openbsd.org>2000-04-26 23:24:43 +0000
committerjasoni <jasoni@cvs.openbsd.org>2000-04-26 23:24:43 +0000
commitb8e2981f69abb136dfacb9e792372f456732e939 (patch)
tree6cf55356a1d0549dd7bd890f16470ed65af9fd6f /sys
parentf101b0a4deb6828e7d91b49b0c42e87659eb834d (diff)
Support for ext2fs rev. 1 (from NetBSD)
Diffstat (limited to 'sys')
-rw-r--r--sys/ufs/ext2fs/ext2fs.h145
-rw-r--r--sys/ufs/ext2fs/ext2fs_alloc.c16
-rw-r--r--sys/ufs/ext2fs/ext2fs_dinode.h16
-rw-r--r--sys/ufs/ext2fs/ext2fs_dir.h50
-rw-r--r--sys/ufs/ext2fs/ext2fs_extern.h5
-rw-r--r--sys/ufs/ext2fs/ext2fs_inode.c4
-rw-r--r--sys/ufs/ext2fs/ext2fs_lookup.c18
-rw-r--r--sys/ufs/ext2fs/ext2fs_vfsops.c262
-rw-r--r--sys/ufs/ext2fs/ext2fs_vnops.c153
9 files changed, 437 insertions, 232 deletions
diff --git a/sys/ufs/ext2fs/ext2fs.h b/sys/ufs/ext2fs/ext2fs.h
index e1d7b8c4842..a5d683b137d 100644
--- a/sys/ufs/ext2fs/ext2fs.h
+++ b/sys/ufs/ext2fs/ext2fs.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ext2fs.h,v 1.3 1997/06/12 21:09:30 downsj Exp $ */
+/* $OpenBSD: ext2fs.h,v 1.4 2000/04/26 23:24:39 jasoni Exp $ */
/* $NetBSD: ext2fs.h,v 1.1 1997/06/11 09:33:37 bouyer Exp $ */
/*
@@ -100,32 +100,46 @@
* Super block for an ext2fs file system.
*/
struct ext2fs {
- u_int32_t e2fs_icount; /* Inode count */
- u_int32_t e2fs_bcount; /* blocks count */
- u_int32_t e2fs_rbcount; /* reserved blocks count */
- u_int32_t e2fs_fbcount; /* free blocks count */
- u_int32_t e2fs_ficount; /* free inodes count */
+ u_int32_t e2fs_icount; /* Inode count */
+ u_int32_t e2fs_bcount; /* blocks count */
+ u_int32_t e2fs_rbcount; /* reserved blocks count */
+ u_int32_t e2fs_fbcount; /* free blocks count */
+ u_int32_t e2fs_ficount; /* free inodes count */
u_int32_t e2fs_first_dblock; /* first data block */
- u_int32_t e2fs_log_bsize; /* block size = 1024*(2^e2fs_log_bsize) */
- u_int32_t e2fs_fsize; /* fragment size */
- u_int32_t e2fs_bpg; /* blocks per group */
- u_int32_t e2fs_fpg; /* frags per group */
- u_int32_t e2fs_ipg; /* inodes per group */
- u_int32_t e2fs_mtime; /* mount time */
- u_int32_t e2fs_wtime; /* write time */
- u_int16_t e2fs_mnt_count; /* mount count */
+ u_int32_t e2fs_log_bsize; /* block size = 1024*(2^e2fs_log_bsize) */
+ u_int32_t e2fs_fsize; /* fragment size */
+ u_int32_t e2fs_bpg; /* blocks per group */
+ u_int32_t e2fs_fpg; /* frags per group */
+ u_int32_t e2fs_ipg; /* inodes per group */
+ u_int32_t e2fs_mtime; /* mount time */
+ u_int32_t e2fs_wtime; /* write time */
+ u_int16_t e2fs_mnt_count; /* mount count */
u_int16_t e2fs_max_mnt_count; /* max mount count */
- u_int16_t e2fs_magic; /* magic number */
- u_int16_t e2fs_state; /* file system state */
- u_int16_t e2fs_beh; /* behavior on errors */
- u_int16_t reserved;
- u_int32_t e2fs_lastfsck; /* time of last fsck */
- u_int32_t e2fs_fsckintv; /* max time between fscks */
- u_int32_t e2fs_creator; /* creator OS */
- u_int32_t e2fs_rev; /* revision level */
- u_int16_t e2fs_ruid; /* default uid for reserved blocks */
- u_int16_t e2fs_rgid; /* default gid for reserved blocks */
- u_int32_t reserved2[235];
+ u_int16_t e2fs_magic; /* magic number */
+ u_int16_t e2fs_state; /* file system state */
+ u_int16_t e2fs_beh; /* behavior on errors */
+ u_int16_t e2fs_minrev; /* minor revision level */
+ u_int32_t e2fs_lastfsck; /* time of last fsck */
+ u_int32_t e2fs_fsckintv; /* max time between fscks */
+ u_int32_t e2fs_creator; /* creator OS */
+ u_int32_t e2fs_rev; /* revision level */
+ u_int16_t e2fs_ruid; /* default uid for reserved blocks */
+ u_int16_t e2fs_rgid; /* default gid for reserved blocks */
+ /* EXT2_DYNAMIC_REV superblocks */
+ u_int32_t e2fs_first_ino; /* first non-reserved inode */
+ u_int16_t e2fs_inode_size; /* size of inode structure */
+ u_int16_t e2fs_block_group_nr; /* block grp number of this sblk*/
+ u_int32_t e2fs_features_compat; /* compatible feature set */
+ u_int32_t e2fs_features_incompat; /* incompatible feature set */
+ u_int32_t e2fs_features_rocompat; /* RO-compatible feature set */
+ u_int8_t e2fs_uuid[16]; /* 128-bit uuid for volume */
+ char e2fs_vname[16]; /* volume name */
+ char e2fs_fsmnt[64]; /* name mounted on */
+ u_int32_t e2fs_algo; /* For compression */
+ u_int8_t e2fs_prealloc; /* # of blocks to preallocate */
+ u_int8_t e2fs_dir_prealloc; /* # of blocks to preallocate for dir */
+ u_int16_t pad1;
+ u_int32_t reserved2[204];
};
@@ -133,18 +147,18 @@ struct ext2fs {
struct m_ext2fs {
struct ext2fs e2fs;
u_char e2fs_fsmnt[MAXMNTLEN]; /* name mounted on */
- int8_t e2fs_ronly; /* mounted read-only flag */
- int8_t e2fs_fmod; /* super block modified flag */
- int32_t e2fs_bsize; /* block size */
- int32_t e2fs_bshift; /* ``lblkno'' calc of logical blkno */
- int32_t e2fs_bmask; /* ``blkoff'' calc of blk offsets */
- int64_t e2fs_qbmask; /* ~fs_bmask - for use with quad size */
- int32_t e2fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */
- int32_t e2fs_ncg; /* number of cylinder groups */
- int32_t e2fs_ngdb; /* number of group descriptor block */
- int32_t e2fs_ipb; /* number of inodes per block */
- int32_t e2fs_itpg; /* number of inode table per group */
- struct ext2_gd *e2fs_gd; /* group descripors */
+ int8_t e2fs_ronly; /* mounted read-only flag */
+ int8_t e2fs_fmod; /* super block modified flag */
+ int32_t e2fs_bsize; /* block size */
+ int32_t e2fs_bshift; /* ``lblkno'' calc of logical blkno */
+ int32_t e2fs_bmask; /* ``blkoff'' calc of blk offsets */
+ int64_t e2fs_qbmask; /* ~fs_bmask - for use with quad size */
+ int32_t e2fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */
+ int32_t e2fs_ncg; /* number of cylinder groups */
+ int32_t e2fs_ngdb; /* number of group descriptor block */
+ int32_t e2fs_ipb; /* number of inodes per block */
+ int32_t e2fs_itpg; /* number of inode table per group */
+ struct ext2_gd *e2fs_gd; /* group descripors */
};
@@ -153,7 +167,23 @@ struct m_ext2fs {
* Filesystem identification
*/
#define E2FS_MAGIC 0xef53 /* the ext2fs magic number */
-#define E2FS_REV 0 /* revision level */
+#define E2FS_REV0 0 /* revision level */
+#define E2FS_REV1 1 /* revision level */
+
+/* compatible/imcompatible features */
+#define EXT2F_COMPAT_PREALLOC 0x0001
+
+#define EXT2F_ROCOMPAT_SPARSESUPER 0x0001
+#define EXT2F_ROCOMPAT_LARGEFILE 0x0002
+#define EXT2F_ROCOMPAT_BTREE_DIR 0x0004
+
+#define EXT2F_INCOMPAT_COMP 0x0001
+#define EXT2F_INCOMPAT_FTYPE 0x0002
+
+/* features supported in this implementation */
+#define EXT2F_COMPAT_SUPP 0x0000
+#define EXT2F_ROCOMPAT_SUPP EXT2F_ROCOMPAT_SPARSESUPER
+#define EXT2F_INCOMPAT_SUPP EXT2F_INCOMPAT_FTYPE
/*
* OS identification
@@ -166,7 +196,7 @@ struct m_ext2fs {
* Filesystem clean flags
*/
#define E2FS_ISCLEAN 0x01
-#define E2FS_ERRORS 0x02
+#define E2FS_ERRORS 0x02
/* ext2 file system block group descriptor */
@@ -179,10 +209,45 @@ struct ext2_gd {
u_int16_t ext2bgd_ndirs; /* number of directories */
u_int16_t reserved;
u_int32_t reserved2[3];
-
};
/*
+ * If the EXT2F_ROCOMPAT_SPARSESUPER flag is set, the cylinder group has a
+ * copy of the super and cylinder group descriptors blocks only if it's
+ * a power of 3, 5 or 7
+ */
+
+static __inline__ int cg_has_sb __P((int)) __attribute__((__unused__));
+static __inline int
+cg_has_sb(i)
+ int i;
+{
+ int a3 ,a5 , a7;
+
+ if (i == 0 || i == 1)
+ return 1;
+ for (a3 = 3, a5 = 5, a7 = 7;
+ a3 <= i || a5 <= i || a7 <= i;
+ a3 *= 3, a5 *= 5, a7 *= 7)
+ if (i == a3 || i == a5 || i == a7)
+ return 1;
+ return 0;
+}
+
+/*
+ * EXT2FS metadatas are stored in little-endian byte order. These macros
+ * should aide in support for big-endian machines.
+ */
+#define h2fs16(x) (x)
+#define h2fs32(x) (x)
+#define fs2h16(x) (x)
+#define fs2h32(x) (x)
+#define e2fs_sbload(old, new) bcopy((old), (new), SBSIZE);
+#define e2fs_cgload(old, new, size) bcopy((old), (new), (size));
+#define e2fs_sbsave(old, new) bcopy((old), (new), SBSIZE);
+#define e2fs_cgsave(old, new, size) bcopy((old), (new), (size));
+
+/*
* Turn file system block numbers into disk block addresses.
* This maps file system blocks to device size blocks.
*/
diff --git a/sys/ufs/ext2fs/ext2fs_alloc.c b/sys/ufs/ext2fs/ext2fs_alloc.c
index 90897f7fd09..77d761a4c3f 100644
--- a/sys/ufs/ext2fs/ext2fs_alloc.c
+++ b/sys/ufs/ext2fs/ext2fs_alloc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ext2fs_alloc.c,v 1.4 1999/01/11 05:12:35 millert Exp $ */
+/* $OpenBSD: ext2fs_alloc.c,v 1.5 2000/04/26 23:24:40 jasoni Exp $ */
/* $NetBSD: ext2fs_alloc.c,v 1.1 1997/06/11 09:33:41 bouyer Exp $ */
/*
@@ -264,7 +264,7 @@ ext2fs_blkpref(ip, lbn, indx, bap)
if (bap) {
for (i = indx; i >= 0 ; i--) {
if (bap[i]) {
- return bap[i] + 1;
+ return fs2h32(bap[i]) + 1;
}
}
}
@@ -352,7 +352,8 @@ ext2fs_alloccg(ip, cg, bpref, size)
fs = ip->i_e2fs;
if (fs->e2fs_gd[cg].ext2bgd_nbfree == 0)
return (NULL);
- error = bread(ip->i_devvp, fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap),
+ error = bread(ip->i_devvp, fsbtodb(fs,
+ fs->e2fs_gd[cg].ext2bgd_b_bitmap),
(int)fs->e2fs_bsize, NOCRED, &bp);
if (error) {
brelse(bp);
@@ -440,7 +441,8 @@ ext2fs_nodealloccg(ip, cg, ipref, mode)
fs = ip->i_e2fs;
if (fs->e2fs_gd[cg].ext2bgd_nifree == 0)
return (NULL);
- error = bread(ip->i_devvp, fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_i_bitmap),
+ error = bread(ip->i_devvp, fsbtodb(fs,
+ fs->e2fs_gd[cg].ext2bgd_i_bitmap),
(int)fs->e2fs_bsize, NOCRED, &bp);
if (error) {
brelse(bp);
@@ -512,7 +514,8 @@ ext2fs_blkfree(ip, bno)
ext2fs_fserr(fs, ip->i_e2fs_uid, "bad block");
return;
}
- error = bread(ip->i_devvp, fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap),
+ error = bread(ip->i_devvp, fsbtodb(fs,
+ fs->e2fs_gd[cg].ext2bgd_b_bitmap),
(int)fs->e2fs_bsize, NOCRED, &bp);
if (error) {
brelse(bp);
@@ -560,7 +563,8 @@ ext2fs_vfree(v)
panic("ifree: range: dev = 0x%x, ino = %d, fs = %s",
pip->i_dev, ino, fs->e2fs_fsmnt);
cg = ino_to_cg(fs, ino);
- error = bread(pip->i_devvp, fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_i_bitmap),
+ error = bread(pip->i_devvp,
+ fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_i_bitmap),
(int)fs->e2fs_bsize, NOCRED, &bp);
if (error) {
brelse(bp);
diff --git a/sys/ufs/ext2fs/ext2fs_dinode.h b/sys/ufs/ext2fs/ext2fs_dinode.h
index 5215322d30f..fe5c280f497 100644
--- a/sys/ufs/ext2fs/ext2fs_dinode.h
+++ b/sys/ufs/ext2fs/ext2fs_dinode.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ext2fs_dinode.h,v 1.3 1997/06/12 21:09:32 downsj Exp $ */
+/* $OpenBSD: ext2fs_dinode.h,v 1.4 2000/04/26 23:24:40 jasoni Exp $ */
/* $NetBSD: ext2fs_dinode.h,v 1.1 1997/06/11 09:33:48 bouyer Exp $ */
/*
@@ -117,10 +117,13 @@ struct ext2fs_dinode {
#define EXT2_UNRM 0x00000002 /* Undelete */
#define EXT2_COMPR 0x00000004 /* Compress file */
#define EXT2_SYNC 0x00000008 /* Synchronous updates */
-#define EXT2_IMMUTABLE 0x00000010 /* Immutable file */
+#define EXT2_IMMUTABLE 0x00000010 /* Immutable file */
#define EXT2_APPEND 0x00000020 /* writes to file may only append */
#define EXT2_NODUMP 0x00000040 /* do not dump file */
+/* Size of on-disk inode. */
+#define EXT2_DINODE_SIZE (sizeof(struct ext2fs_dinode)) /* 128 */
+
/*
* The e2di_blocks fields may be overlaid with other information for
* file types that do not have associated disk storage. Block
@@ -130,4 +133,11 @@ struct ext2fs_dinode {
*/
#define e2di_rdev e2di_blocks[0]
-#define e2di_shortlink e2di_blocks
+#define e2di_shortlink e2di_blocks
+
+/*
+ * e2fs needs byte swapping on big-endian systems. Use macros here to
+ * aide in big-endian support.
+ */
+#define e2fs_iload(old, new) bcopy((old),(new),sizeof(struct ext2fs_dinode))
+#define e2fs_isave(old, new) bcopy((old),(new),sizeof(struct ext2fs_dinode))
diff --git a/sys/ufs/ext2fs/ext2fs_dir.h b/sys/ufs/ext2fs/ext2fs_dir.h
index c959023414b..ae73124ee95 100644
--- a/sys/ufs/ext2fs/ext2fs_dir.h
+++ b/sys/ufs/ext2fs/ext2fs_dir.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ext2fs_dir.h,v 1.3 1997/06/12 21:09:32 downsj Exp $ */
+/* $OpenBSD: ext2fs_dir.h,v 1.4 2000/04/26 23:24:40 jasoni Exp $ */
/* $NetBSD: ext2fs_dir.h,v 1.1 1997/06/11 09:33:50 bouyer Exp $ */
/*
@@ -83,10 +83,50 @@
struct ext2fs_direct {
u_int32_t e2d_ino; /* inode number of entry */
u_int16_t e2d_reclen; /* length of this record */
- u_int16_t e2d_namlen; /* length of string in d_name */
+ u_int8_t e2d_namlen; /* length of string in d_name */
+ u_int8_t e2d_type; /* file type */
char e2d_name[EXT2FS_MAXNAMLEN];/* name with length <= EXT2FS_MAXNAMLEN */
};
+/* Ext2 directory file types (not the same as FFS. Sigh. */
+#define EXT2_FT_UNKNOWN 0
+#define EXT2_FT_REG_FILE 1
+#define EXT2_FT_DIR 2
+#define EXT2_FT_CHRDEV 3
+#define EXT2_FT_BLKDEV 4
+#define EXT2_FT_FIFO 5
+#define EXT2_FT_SOCK 6
+#define EXT2_FT_SYMLINK 7
+#define EXT2_FT_MAX 8
+
+#define E2IFTODT(mode) (((mode) & 0170000) >> 12)
+
+static __inline__ u_int8_t inot2ext2dt __P((u_int16_t))
+ __attribute__((__unused__));
+static __inline__ u_int8_t
+inot2ext2dt(type)
+ u_int16_t type;
+{
+ switch(type) {
+ case E2IFTODT(EXT2_IFIFO):
+ return EXT2_FT_FIFO;
+ case E2IFTODT(EXT2_IFCHR):
+ return EXT2_FT_CHRDEV;
+ case E2IFTODT(EXT2_IFDIR):
+ return EXT2_FT_DIR;
+ case E2IFTODT(EXT2_IFBLK):
+ return EXT2_FT_BLKDEV;
+ case E2IFTODT(EXT2_IFREG):
+ return EXT2_FT_REG_FILE;
+ case E2IFTODT(EXT2_IFLNK):
+ return EXT2_FT_SYMLINK;
+ case E2IFTODT(EXT2_IFSOCK):
+ return EXT2_FT_SOCK;
+ default:
+ return 0;
+ }
+}
+
/*
* The EXT2FS_DIRSIZ macro gives the minimum record length which will hold
* the directory entryfor a name len "len" (without the terminating null byte).
@@ -104,11 +144,13 @@ struct ext2fs_direct {
struct ext2fs_dirtemplate {
u_int32_t dot_ino;
int16_t dot_reclen;
- u_int16_t dot_namlen;
+ u_int8_t dot_namlen;
+ u_int8_t dot_type;
char dot_name[4]; /* must be multiple of 4 */
u_int32_t dotdot_ino;
int16_t dotdot_reclen;
- u_int16_t dotdot_namlen;
+ u_int8_t dotdot_namlen;
+ u_int8_t dotdot_type;
char dotdot_name[4]; /* ditto */
};
diff --git a/sys/ufs/ext2fs/ext2fs_extern.h b/sys/ufs/ext2fs/ext2fs_extern.h
index 7310611b52b..386399dba4e 100644
--- a/sys/ufs/ext2fs/ext2fs_extern.h
+++ b/sys/ufs/ext2fs/ext2fs_extern.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ext2fs_extern.h,v 1.6 2000/02/07 04:57:18 assar Exp $ */
+/* $OpenBSD: ext2fs_extern.h,v 1.7 2000/04/26 23:24:40 jasoni Exp $ */
/* $NetBSD: ext2fs_extern.h,v 1.1 1997/06/11 09:33:55 bouyer Exp $ */
/*-
@@ -55,6 +55,8 @@ struct vfsconf;
struct mbuf;
struct componentname;
+extern struct pool ext2fs_inode_pool; /* memory pool for inodes */
+
__BEGIN_DECLS
/* ext2fs_alloc.c */
@@ -142,6 +144,7 @@ int ext2fs_makeinode __P((int, struct vnode *, struct vnode **,
struct componentname *cnp));
int ext2fs_fsync __P((void *));
int ext2fs_reclaim __P((void *));
+
__END_DECLS
#define IS_EXT2_VNODE(vp) (vp->v_tag == VT_EXT2FS)
diff --git a/sys/ufs/ext2fs/ext2fs_inode.c b/sys/ufs/ext2fs/ext2fs_inode.c
index 9813965c3f4..d97a1290e96 100644
--- a/sys/ufs/ext2fs/ext2fs_inode.c
+++ b/sys/ufs/ext2fs/ext2fs_inode.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ext2fs_inode.c,v 1.7 1999/08/17 14:20:46 art Exp $ */
+/* $OpenBSD: ext2fs_inode.c,v 1.8 2000/04/26 23:24:41 jasoni Exp $ */
/* $NetBSD: ext2fs_inode.c,v 1.1 1997/06/11 09:33:56 bouyer Exp $ */
/*
@@ -61,7 +61,7 @@
#include <ufs/ext2fs/ext2fs_extern.h>
static int ext2fs_indirtrunc __P((struct inode *, daddr_t, daddr_t,
- daddr_t, int, long *));
+ daddr_t, int, long *));
int
ext2fs_init(vfsp)
diff --git a/sys/ufs/ext2fs/ext2fs_lookup.c b/sys/ufs/ext2fs/ext2fs_lookup.c
index e05806462f4..11bc88989f9 100644
--- a/sys/ufs/ext2fs/ext2fs_lookup.c
+++ b/sys/ufs/ext2fs/ext2fs_lookup.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ext2fs_lookup.c,v 1.6 1999/01/11 05:12:37 millert Exp $ */
+/* $OpenBSD: ext2fs_lookup.c,v 1.7 2000/04/26 23:24:41 jasoni Exp $ */
/* $NetBSD: ext2fs_lookup.c,v 1.1 1997/06/11 09:33:59 bouyer Exp $ */
/*
@@ -797,8 +797,14 @@ ext2fs_direnter(ip, dvp, cnp)
panic("direnter: missing name");
#endif
dp = VTOI(dvp);
- newdir.e2d_ino = ip->i_number;
+ newdir.e2d_ino = h2fs32(ip->i_number);
newdir.e2d_namlen = cnp->cn_namelen;
+ if (ip->i_e2fs->e2fs.e2fs_rev > E2FS_REV0 &&
+ (ip->i_e2fs->e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE)) {
+ newdir.e2d_type = inot2ext2dt(IFTODT(ip->i_ffs_mode));
+ } else {
+ newdir.e2d_type = 0;
+ };
bcopy(cnp->cn_nameptr, newdir.e2d_name, (unsigned)cnp->cn_namelen + 1);
newentrysize = EXT2FS_DIRSIZ(newdir.e2d_namlen);
if (dp->i_count == 0) {
@@ -968,7 +974,13 @@ ext2fs_dirrewrite(dp, ip, cnp)
error = VOP_BLKATOFF(vdp, (off_t)dp->i_offset, (char **)&ep, &bp);
if (error != 0)
return (error);
- ep->e2d_ino = ip->i_number;
+ ep->e2d_ino = h2fs32(ip->i_number);
+ if (ip->i_e2fs->e2fs.e2fs_rev > E2FS_REV0 &&
+ (ip->i_e2fs->e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE)) {
+ ep->e2d_type = inot2ext2dt(IFTODT(ip->i_ffs_mode));
+ } else {
+ ep->e2d_type = 0;
+ }
error = VOP_BWRITE(bp);
dp->i_flag |= IN_CHANGE | IN_UPDATE;
return (error);
diff --git a/sys/ufs/ext2fs/ext2fs_vfsops.c b/sys/ufs/ext2fs/ext2fs_vfsops.c
index 2b6ba93d951..27aa5357325 100644
--- a/sys/ufs/ext2fs/ext2fs_vfsops.c
+++ b/sys/ufs/ext2fs/ext2fs_vfsops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ext2fs_vfsops.c,v 1.11 2000/02/07 04:57:18 assar Exp $ */
+/* $OpenBSD: ext2fs_vfsops.c,v 1.12 2000/04/26 23:24:41 jasoni Exp $ */
/* $NetBSD: ext2fs_vfsops.c,v 1.1 1997/06/11 09:34:07 bouyer Exp $ */
/*
@@ -54,6 +54,8 @@
#include <sys/ioctl.h>
#include <sys/errno.h>
#include <sys/malloc.h>
+#include <sys/pool.h>
+#include <sys/lock.h>
#include <miscfs/specfs/specdev.h>
@@ -66,7 +68,21 @@
#include <ufs/ext2fs/ext2fs.h>
#include <ufs/ext2fs/ext2fs_extern.h>
+extern struct lock ufs_hashlock;
+
int ext2fs_sbupdate __P((struct ufsmount *, int));
+static int ext2fs_checksb __P((struct ext2fs *, int));
+
+extern struct vnodeopv_desc ext2fs_vnodeop_opv_desc;
+extern struct vnodeopv_desc ext2fs_specop_opv_desc;
+extern struct vnodeopv_desc ext2fs_fifoop_opv_desc;
+
+struct vnodeopv_desc *ext2fs_vnodeopv_descs[] = {
+ &ext2fs_vnodeop_opv_desc,
+ &ext2fs_specop_opv_desc,
+ &ext2fs_fifoop_opv_desc,
+ NULL,
+};
struct vfsops ext2fs_vfsops = {
ext2fs_mount,
@@ -84,6 +100,8 @@ struct vfsops ext2fs_vfsops = {
ufs_check_export
};
+struct pool ext2fs_inode_pool;
+
extern u_long ext2gennumber;
/*
@@ -109,12 +127,16 @@ ext2fs_mountroot()
if (bdevvp(swapdev, &swapdev_vp) || bdevvp(rootdev, &rootvp))
panic("ext2fs_mountroot: can't setup bdevvp's");
- if ((error = vfs_rootmountalloc("ext2fs", "root_device", &mp)) != 0)
+ if ((error = vfs_rootmountalloc("ext2fs", "root_device", &mp)) != 0) {
+ vrele(rootvp);
return (error);
+ }
+
if ((error = ext2fs_mountfs(rootvp, mp, p)) != 0) {
mp->mnt_vfc->vfc_refcount--;
vfs_unbusy(mp, p);
free(mp, M_MOUNT);
+ vrele(rootvp);
return (error);
}
simple_lock(&mountlist_slock);
@@ -122,9 +144,15 @@ ext2fs_mountroot()
simple_unlock(&mountlist_slock);
ump = VFSTOUFS(mp);
fs = ump->um_e2fs;
- (void) copystr(mp->mnt_stat.f_mntonname, fs->e2fs_fsmnt, MNAMELEN -1, 0);
+ bzero(fs->e2fs_fsmnt, sizeof(fs->e2fs_fsmnt));
+ (void) copystr(mp->mnt_stat.f_mntonname, fs->e2fs_fsmnt,
+ sizeof(fs->e2fs_fsmnt) - 1, 0);
+ if (fs->e2fs.e2fs_rev > E2FS_REV0) {
+ bzero(fs->e2fs.e2fs_fsmnt, sizeof(fs->e2fs.e2fs_fsmnt));
+ (void) copystr(mp->mnt_stat.f_mntonname, fs->e2fs.e2fs_fsmnt,
+ sizeof(fs->e2fs.e2fs_fsmnt) - 1, 0);
+ }
(void)ext2fs_statfs(mp, &mp->mnt_stat, p);
-
vfs_unbusy(mp, p);
inittodr(fs->e2fs.e2fs_wtime);
return (0);
@@ -203,7 +231,6 @@ ext2fs_mount(mp, path, data, ndp, p)
else
fs->e2fs.e2fs_state = E2FS_ERRORS;
fs->e2fs_fmod = 1;
- (void) ext2fs_sbupdate(ump, MNT_WAIT);
}
if (args.fspec == 0) {
/*
@@ -259,9 +286,14 @@ ext2fs_mount(mp, path, data, ndp, p)
}
ump = VFSTOUFS(mp);
fs = ump->um_e2fs;
- (void) copyinstr(path, fs->e2fs_fsmnt, sizeof(fs->e2fs_fsmnt) - 1, &size);
- bcopy(&args, &mp->mnt_stat.mount_info.ufs_args, sizeof(args));
+ (void) copyinstr(path, fs->e2fs_fsmnt, sizeof(fs->e2fs_fsmnt) - 1,
+ &size);
bzero(fs->e2fs_fsmnt + size, sizeof(fs->e2fs_fsmnt) - size);
+ if (fs->e2fs.e2fs_rev > E2FS_REV0) {
+ (void) copystr(mp->mnt_stat.f_mntonname, fs->e2fs.e2fs_fsmnt,
+ sizeof(fs->e2fs.e2fs_fsmnt) - 1, &size);
+ bzero(fs->e2fs.e2fs_fsmnt, sizeof(fs->e2fs.e2fs_fsmnt) - size);
+ }
bcopy(fs->e2fs_fsmnt, mp->mnt_stat.f_mntonname, MNAMELEN);
(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
&size);
@@ -304,6 +336,7 @@ ext2fs_reload(mountp, cred, p)
struct ext2fs *newfs;
struct partinfo dpart;
int i, size, error;
+ caddr_t cp;
if ((mountp->mnt_flag & MNT_RDONLY) == 0)
return (EINVAL);
@@ -311,10 +344,7 @@ ext2fs_reload(mountp, cred, p)
* Step 1: invalidate all cached meta-data.
*/
devvp = VFSTOUFS(mountp)->um_devvp;
- vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
- error = vinvalbuf(devvp, 0, cred, p, 0, 0);
- VOP_UNLOCK(devvp, 0, p);
- if (error)
+ if (vinvalbuf(devvp, 0, cred, p, 0, 0))
panic("ext2fs_reload: dirty1");
/*
@@ -324,37 +354,26 @@ ext2fs_reload(mountp, cred, p)
size = DEV_BSIZE;
else
size = dpart.disklab->d_secsize;
- error = bread(devvp, (daddr_t)(SBOFF / size), SBSIZE, NOCRED, &bp);
- if (error)
- return (error);
- newfs = (struct ext2fs *)bp->b_data;
- if (newfs->e2fs_magic != E2FS_MAGIC || newfs->e2fs_rev != E2FS_REV) {
-#ifdef DIAGNOSTIC
- printf("Wrong magic number: %x (expected %x for ext2 fs)",
- newfs->e2fs_magic, E2FS_MAGIC);
- printf("or wrong revision number: %x (expected %x for ext2 fs)",
- newfs->e2fs_rev, E2FS_REV);
-#endif
+ error = bread(devvp, (ufs_daddr_t)(SBOFF / size), SBSIZE, NOCRED, &bp);
+ if (error) {
brelse(bp);
- return (EIO); /* XXX needs translation */
+ return (error);
}
- if (newfs->e2fs_log_bsize > 2) { /* block size = 1024|2048|4096 */
-#ifdef DIAGNOSTIC
- printf("wrong block size: %d (expected <=2 for ext2 fs)\n",
- newfs->e2fs_log_bsize);
-#endif
+ newfs = (struct ext2fs *)bp->b_data;
+ error = ext2fs_checksb(newfs, (mountp->mnt_flag & MNT_RDONLY) != 0);
+ if (error) {
brelse(bp);
- return (EIO); /* XXX needs translation */
+ return (error);
}
-
fs = VFSTOUFS(mountp)->um_e2fs;
/*
* copy in new superblock, and compute in-memory values
*/
- bcopy(newfs, &fs->e2fs, SBSIZE);
- fs->e2fs_ncg = howmany(fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock,
- fs->e2fs.e2fs_bpg);
+ e2fs_sbload(newfs, &fs->e2fs);
+ fs->e2fs_ncg =
+ howmany(fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock,
+ fs->e2fs.e2fs_bpg);
/* XXX assume hw bsize = 512 */
fs->e2fs_fsbtodb = fs->e2fs.e2fs_log_bsize + 1;
fs->e2fs_bsize = 1024 << fs->e2fs.e2fs_log_bsize;
@@ -363,7 +382,7 @@ ext2fs_reload(mountp, cred, p)
fs->e2fs_bmask = ~fs->e2fs_qbmask;
fs->e2fs_ngdb = howmany(fs->e2fs_ncg,
fs->e2fs_bsize / sizeof(struct ext2_gd));
- fs->e2fs_ipb = fs->e2fs_bsize / sizeof(struct ext2fs_dinode);
+ fs->e2fs_ipb = fs->e2fs_bsize / EXT2_DINODE_SIZE;
fs->e2fs_itpg = fs->e2fs.e2fs_ipg/fs->e2fs_ipb;
/*
@@ -371,13 +390,16 @@ ext2fs_reload(mountp, cred, p)
*/
for (i=0; i < fs->e2fs_ngdb; i++) {
- error = bread(devvp , fsbtodb(fs, ((fs->e2fs_bsize>1024)?0:1)+i+1),
- fs->e2fs_bsize, NOCRED, &bp);
- if (error)
+ error = bread(devvp ,
+ fsbtodb(fs, ((fs->e2fs_bsize>1024)? 0 : 1) + i + 1),
+ fs->e2fs_bsize, NOCRED, &bp);
+ if (error) {
+ brelse(bp);
return (error);
- bcopy(bp->b_data,
- &fs->e2fs_gd[i* fs->e2fs_bsize / sizeof(struct ext2_gd)],
- fs->e2fs_bsize);
+ }
+ e2fs_cgload((struct ext2_gd*)bp->b_data,
+ &fs->e2fs_gd[i* fs->e2fs_bsize / sizeof(struct ext2_gd)],
+ fs->e2fs_bsize);
brelse(bp);
}
@@ -415,10 +437,9 @@ loop:
vput(vp);
return (error);
}
- bcopy((struct ext2fs_dinode *)bp->b_data +
- ino_to_fsbo(fs, ip->i_number),
- &ip->i_din.e2fs_din, sizeof(struct ext2fs_dinode));
- ip->i_effnlink = ip->i_e2fs_nlink;
+ cp = (caddr_t)bp->b_data +
+ (ino_to_fsbo(fs, ip->i_number) * EXT2_DINODE_SIZE);
+ e2fs_iload((struct ext2fs_dinode *)cp, &ip->i_din.e2fs_din);
brelse(bp);
vput(vp);
simple_lock(&mntvnode_slock);
@@ -458,10 +479,7 @@ ext2fs_mountfs(devvp, mp, p)
return (error);
if (vcount(devvp) > 1 && devvp != rootvp)
return (EBUSY);
- vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
- error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0);
- VOP_UNLOCK(devvp, 0, p);
- if (error)
+ if ((error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0)) != 0)
return (error);
ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
@@ -478,36 +496,20 @@ ext2fs_mountfs(devvp, mp, p)
#ifdef DEBUG_EXT2
printf("sb size: %d ino size %d\n", sizeof(struct ext2fs),
- sizeof(struct ext2fs_dinode));
+ EXT2_DINODE_SIZE);
#endif
error = bread(devvp, (SBOFF / DEV_BSIZE), SBSIZE, cred, &bp);
if (error)
goto out;
fs = (struct ext2fs *)bp->b_data;
- if (fs->e2fs_magic != E2FS_MAGIC || fs->e2fs_rev != E2FS_REV) {
-#ifdef DIAGNOSTIC
- printf("Wrong magic number: %x (expected %x for ext2 fs)",
- fs->e2fs_magic, E2FS_MAGIC);
- printf(" or wrong revision number: %x (expected %x for ext2 fs)\n",
- fs->e2fs_rev, E2FS_REV);
-#endif
- error = EFTYPE;
- goto out;
- }
-
- if (fs->e2fs_log_bsize > 2) { /* block size = 1024|2048|4096 */
-#ifdef DIAGNOSTIC
- printf("wrong block size: %d (expected <2 for ext2 fs)\n",
- fs->e2fs_log_bsize);
-#endif
- error = EFTYPE;
+ error = ext2fs_checksb(fs, ronly);
+ if (error)
goto out;
- }
-
ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
- bzero((caddr_t)ump, sizeof *ump);
+ memset((caddr_t)ump, 0, sizeof *ump);
ump->um_e2fs = malloc(sizeof(struct m_ext2fs), M_UFSMNT, M_WAITOK);
- bcopy(bp->b_data, ump->um_e2fs, SBSIZE);
+ memset((caddr_t)ump->um_e2fs, 0, sizeof(struct m_ext2fs));
+ e2fs_sbload((struct ext2fs*)bp->b_data, &ump->um_e2fs->e2fs);
brelse(bp);
bp = NULL;
m_fs = ump->um_e2fs;
@@ -532,21 +534,23 @@ ext2fs_mountfs(devvp, mp, p)
m_fs->e2fs_bmask = ~m_fs->e2fs_qbmask;
m_fs->e2fs_ngdb = howmany(m_fs->e2fs_ncg,
m_fs->e2fs_bsize / sizeof(struct ext2_gd));
- m_fs->e2fs_ipb = m_fs->e2fs_bsize / sizeof(struct ext2fs_dinode);
+ m_fs->e2fs_ipb = m_fs->e2fs_bsize / EXT2_DINODE_SIZE;
m_fs->e2fs_itpg = m_fs->e2fs.e2fs_ipg/m_fs->e2fs_ipb;
m_fs->e2fs_gd = malloc(m_fs->e2fs_ngdb * m_fs->e2fs_bsize,
M_UFSMNT, M_WAITOK);
for (i=0; i < m_fs->e2fs_ngdb; i++) {
- error = bread(devvp , fsbtodb(m_fs, ((m_fs->e2fs_bsize>1024)?0:1)+i+1),
- m_fs->e2fs_bsize, NOCRED, &bp);
+ error = bread(devvp ,
+ fsbtodb(m_fs, ((m_fs->e2fs_bsize>1024)? 0 : 1) + i + 1),
+ m_fs->e2fs_bsize, NOCRED, &bp);
if (error) {
free(m_fs->e2fs_gd, M_UFSMNT);
goto out;
}
- bcopy(bp->b_data,
- &m_fs->e2fs_gd[i* m_fs->e2fs_bsize / sizeof(struct ext2_gd)],
- m_fs->e2fs_bsize);
+ e2fs_cgload((struct ext2_gd*)bp->b_data,
+ &m_fs->e2fs_gd[
+ i * m_fs->e2fs_bsize / sizeof(struct ext2_gd)],
+ m_fs->e2fs_bsize);
brelse(bp);
bp = NULL;
}
@@ -555,6 +559,7 @@ ext2fs_mountfs(devvp, mp, p)
mp->mnt_stat.f_fsid.val[0] = (long)dev;
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
mp->mnt_maxsymlinklen = EXT2_MAXSYMLINKLEN;
+ mp->mnt_flag |= MNT_LOCAL;
ump->um_mountp = mp;
ump->um_dev = dev;
ump->um_devvp = devvp;
@@ -564,10 +569,11 @@ ext2fs_mountfs(devvp, mp, p)
devvp->v_specmountpoint = mp;
return (0);
out:
- devvp->v_specmountpoint = NULL;
if (bp)
brelse(bp);
+ vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
+ VOP_UNLOCK(devvp, 0, p);
if (ump) {
free(ump->um_e2fs, M_UFSMNT);
free(ump, M_UFSMNT);
@@ -603,14 +609,17 @@ ext2fs_unmount(mp, mntflags, p)
(void) ext2fs_sbupdate(ump, MNT_WAIT);
}
- ump->um_devvp->v_specmountpoint = NULL;
+ if (ump->um_devvp->v_type != VBAD)
+ ump->um_devvp->v_specmountpoint = NULL;
+ vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
error = VOP_CLOSE(ump->um_devvp, fs->e2fs_ronly ? FREAD : FREAD|FWRITE,
NOCRED, p);
- vrele(ump->um_devvp);
+ vput(ump->um_devvp);
free(fs->e2fs_gd, M_UFSMNT);
free(fs, M_UFSMNT);
free(ump, M_UFSMNT);
mp->mnt_data = (qaddr_t)0;
+ mp->mnt_flag &= ~MNT_LOCAL;
return (error);
}
@@ -653,6 +662,7 @@ ext2fs_statfs(mp, sbp, p)
register struct ufsmount *ump;
register struct m_ext2fs *fs;
u_int32_t overhead, overhead_per_group;
+ int i, ngroups;
ump = VFSTOUFS(mp);
fs = ump->um_e2fs;
@@ -662,14 +672,21 @@ ext2fs_statfs(mp, sbp, p)
/*
* Compute the overhead (FS structures)
*/
- overhead_per_group = 1 /* super block */ +
- fs->e2fs_ngdb +
- 1 /* block bitmap */ +
- 1 /* inode bitmap */ +
- fs->e2fs_itpg;
+ overhead_per_group = 1 /* block bitmap */ +
+ 1 /* inode bitmap */ +
+ fs->e2fs_itpg;
overhead = fs->e2fs.e2fs_first_dblock +
fs->e2fs_ncg * overhead_per_group;
-
+ if (fs->e2fs.e2fs_rev > E2FS_REV0 &&
+ fs->e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_SPARSESUPER) {
+ for (i = 0, ngroups = 0; i < fs->e2fs_ncg; i++) {
+ if (cg_has_sb(i))
+ ngroups++;
+ }
+ } else {
+ ngroups = fs->e2fs_ncg;
+ }
+ overhead += ngroups * (1 + fs->e2fs_ngdb);
sbp->f_bsize = fs->e2fs_bsize;
sbp->f_iosize = fs->e2fs_bsize;
@@ -681,8 +698,6 @@ ext2fs_statfs(mp, sbp, p)
if (sbp != &mp->mnt_stat) {
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
- bcopy(&mp->mnt_stat.mount_info.ufs_args,
- &sbp->mount_info.ufs_args, sizeof(struct ufs_args));
}
strncpy(sbp->f_fstypename, mp->mnt_vfc->vfc_name, MFSNAMELEN);
return (0);
@@ -709,30 +724,23 @@ ext2fs_sync(mp, waitfor, cred, p)
int error, allerror = 0;
fs = ump->um_e2fs;
- /*
- * Write back modified superblock.
- * Consistency check that the superblock
- * is still in the buffer cache.
- */
- if (fs->e2fs_fmod != 0 && fs->e2fs_ronly != 0) { /* XXX */
+ if (fs->e2fs_ronly != 0) { /* XXX */
printf("fs = %s\n", fs->e2fs_fsmnt);
panic("update: rofs mod");
}
+
/*
* Write back each (modified) inode.
*/
simple_lock(&mntvnode_slock);
loop:
- for (vp = mp->mnt_vnodelist.lh_first;
- vp != NULL;
- vp = nvp) {
+ for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
/*
* If the vnode that we are about to sync is no longer
* associated with this mount point, start over.
*/
if (vp->v_mount != mp)
goto loop;
-
simple_lock(&vp->v_interlock);
nvp = vp->v_mntvnodes.le_next;
ip = VTOI(vp);
@@ -753,8 +761,7 @@ loop:
}
if ((error = VOP_FSYNC(vp, cred, waitfor, p)) != 0)
allerror = error;
- VOP_UNLOCK(vp, 0, p);
- vrele(vp);
+ vput(vp);
simple_lock(&mntvnode_slock);
}
simple_unlock(&mntvnode_slock);
@@ -772,9 +779,12 @@ loop:
/*
* Write back modified superblock.
*/
-
- if (fs->e2fs_fmod != 0 && (error = ext2fs_sbupdate(ump, waitfor)) != 0)
- allerror = error;
+ if (fs->e2fs_fmod != 0) {
+ fs->e2fs_fmod = 0;
+ fs->e2fs.e2fs_wtime = time.tv_sec;
+ if ((error = ext2fs_cgupdate(ump, waitfor)))
+ allerror = error;
+ }
return (allerror);
}
@@ -1002,16 +1012,56 @@ ext2fs_cgupdate(mp, waitfor)
allerror = ext2fs_sbupdate(mp, waitfor);
for (i = 0; i < fs->e2fs_ngdb; i++) {
bp = getblk(mp->um_devvp, fsbtodb(fs, ((fs->e2fs_bsize>1024)?0:1)+i+1),
- fs->e2fs_bsize, 0, 0);
- bcopy(&fs->e2fs_gd[i* fs->e2fs_bsize / sizeof(struct ext2_gd)],
- bp->b_data, fs->e2fs_bsize);
+ fs->e2fs_bsize, 0, 0);
+ e2fs_cgsave(&fs->e2fs_gd[i* fs->e2fs_bsize / sizeof(struct ext2_gd)], (struct ext2_gd*)bp->b_data, fs->e2fs_bsize);
if (waitfor == MNT_WAIT)
error = bwrite(bp);
else
bawrite(bp);
}
-
+
if (!allerror && error)
allerror = error;
return (allerror);
}
+
+static int
+ext2fs_checksb(fs, ronly)
+ struct ext2fs *fs;
+ int ronly;
+{
+ if (fs2h16(fs->e2fs_magic) != E2FS_MAGIC) {
+ return (EIO); /* XXX needs translation */
+ }
+ if (fs2h32(fs->e2fs_rev) > E2FS_REV1) {
+#ifdef DIAGNOSTIC
+ printf("Ext2 fs: unsupported revision number: %x\n",
+ fs2h32(fs->e2fs_rev));
+#endif
+ return (EIO); /* XXX needs translation */
+ }
+ if (fs2h32(fs->e2fs_log_bsize) > 2) { /* block size = 1024|2048|4096 */
+#ifdef DIAGNOSTIC
+ printf("Ext2 fs: bad block size: %d (expected <=2 for ext2 fs)\n",
+ fs2h32(fs->e2fs_log_bsize));
+#endif
+ return (EIO); /* XXX needs translation */
+ }
+ if (fs2h32(fs->e2fs_rev) > E2FS_REV0) {
+ if (fs2h32(fs->e2fs_first_ino) != EXT2_FIRSTINO ||
+ fs2h16(fs->e2fs_inode_size) != EXT2_DINODE_SIZE) {
+ printf("Ext2 fs: unsupported inode size\n");
+ return (EINVAL); /* XXX needs translation */
+ }
+ if (fs2h32(fs->e2fs_features_incompat) &
+ ~EXT2F_INCOMPAT_SUPP) {
+ printf("Ext2 fs: unsupported optionnal feature\n");
+ return (EINVAL); /* XXX needs translation */
+ }
+ if (!ronly && fs2h32(fs->e2fs_features_rocompat) &
+ ~EXT2F_ROCOMPAT_SUPP) {
+ return (EROFS); /* XXX needs translation */
+ }
+ }
+ return (0);
+}
diff --git a/sys/ufs/ext2fs/ext2fs_vnops.c b/sys/ufs/ext2fs/ext2fs_vnops.c
index 8348a54b15d..57218f04e65 100644
--- a/sys/ufs/ext2fs/ext2fs_vnops.c
+++ b/sys/ufs/ext2fs/ext2fs_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ext2fs_vnops.c,v 1.10 1999/02/26 16:35:33 millert Exp $ */
+/* $OpenBSD: ext2fs_vnops.c,v 1.11 2000/04/26 23:24:42 jasoni Exp $ */
/* $NetBSD: ext2fs_vnops.c,v 1.1 1997/06/11 09:34:09 bouyer Exp $ */
/*
@@ -57,10 +57,13 @@
#include <sys/vnode.h>
#include <sys/lockf.h>
#include <sys/malloc.h>
+#include <sys/pool.h>
#include <sys/signalvar.h>
#include <vm/vm.h>
+#include <uvm/uvm_extern.h>
+
#include <miscfs/fifofs/fifo.h>
#include <miscfs/specfs/specdev.h>
@@ -109,9 +112,9 @@ ext2fs_create(v)
struct componentname *a_cnp;
struct vattr *a_vap;
} */ *ap = v;
- return
- ext2fs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
- ap->a_dvp, ap->a_vpp, ap->a_cnp);
+ return ext2fs_makeinode(MAKEIMODE(ap->a_vap->va_type,
+ ap->a_vap->va_mode),
+ ap->a_dvp, ap->a_vpp, ap->a_cnp);
}
/*
@@ -144,7 +147,7 @@ ext2fs_mknod(v)
* Want to be able to use this to make badblock
* inodes, so don't truncate the dev number.
*/
- ip->i_din.e2fs_din.e2di_rdev = vap->va_rdev;
+ ip->i_din.e2fs_din.e2di_rdev = h2fs32(vap->va_rdev);
}
/*
* Remove inode so that it will be reloaded by VFS_VGET and
@@ -198,13 +201,6 @@ ext2fs_access(v)
register struct inode *ip = VTOI(vp);
mode_t mode = ap->a_mode;
-#ifdef DIAGNOSTIC
- if (!VOP_ISLOCKED(vp)) {
- vprint("ext2fs_access: not locked", vp);
- panic("ext2fs_access: not locked");
- }
-#endif
-
/* If immutable bit set, nobody gets to write it. */
if ((mode & VWRITE) && (ip->i_e2fs_flags & EXT2_IMMUTABLE))
return (EPERM);
@@ -238,7 +234,7 @@ ext2fs_getattr(v)
vap->va_nlink = ip->i_e2fs_nlink;
vap->va_uid = ip->i_e2fs_uid;
vap->va_gid = ip->i_e2fs_gid;
- vap->va_rdev = (dev_t)ip->i_din.e2fs_din.e2di_rdev;
+ vap->va_rdev = (dev_t)fs2h32(ip->i_din.e2fs_din.e2di_rdev);
vap->va_size = ip->i_e2fs_size;
vap->va_atime.tv_sec = ip->i_e2fs_atime;
vap->va_atime.tv_nsec = 0;
@@ -261,7 +257,7 @@ ext2fs_getattr(v)
vap->va_blocksize = MAXBSIZE;
else
vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
- vap->va_bytes = dbtob(ip->i_e2fs_nblock);
+ vap->va_bytes = dbtob((u_quad_t)ip->i_e2fs_nblock);
vap->va_type = vp->v_type;
vap->va_filerev = ip->i_modrev;
return (0);
@@ -297,24 +293,28 @@ ext2fs_setattr(v)
return (EINVAL);
}
if (vap->va_flags != VNOVAL) {
+ if (vp->v_mount->mnt_flag & MNT_RDONLY)
+ return (EROFS);
if (cred->cr_uid != ip->i_e2fs_uid &&
(error = suser(cred, &p->p_acflag)))
return (error);
#ifdef EXT2FS_SYSTEM_FLAGS
if (cred->cr_uid == 0) {
- if ((ip->i_e2fs_flags & (EXT2_APPEND | EXT2_IMMUTABLE)) &&
- securelevel > 0)
+ if ((ip->i_e2fs_flags &
+ (EXT2_APPEND | EXT2_IMMUTABLE)) && securelevel > 0)
return (EPERM);
ip->i_e2fs_flags &= ~(EXT2_APPEND | EXT2_IMMUTABLE);
- ip->i_e2fs_flags |= (vap->va_flags & SF_APPEND) ? EXT2_APPEND : 0 |
- (vap->va_flags & SF_IMMUTABLE) ? EXT2_IMMUTABLE: 0;
+ ip->i_e2fs_flags |=
+ (vap->va_flags & SF_APPEND) ? EXT2_APPEND : 0 |
+ (vap->va_flags & SF_IMMUTABLE) ? EXT2_IMMUTABLE: 0;
} else {
return (EPERM);
}
#else
ip->i_e2fs_flags &= ~(EXT2_APPEND | EXT2_IMMUTABLE);
- ip->i_e2fs_flags |= (vap->va_flags & UF_APPEND) ? EXT2_APPEND : 0 |
- (vap->va_flags & UF_IMMUTABLE) ? EXT2_IMMUTABLE: 0;
+ ip->i_e2fs_flags |=
+ (vap->va_flags & UF_APPEND) ? EXT2_APPEND : 0 |
+ (vap->va_flags & UF_IMMUTABLE) ? EXT2_IMMUTABLE: 0;
#endif
ip->i_flag |= IN_CHANGE;
if (vap->va_flags & (IMMUTABLE | APPEND))
@@ -326,19 +326,36 @@ ext2fs_setattr(v)
* 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);
error = ext2fs_chown(vp, vap->va_uid, vap->va_gid, cred, p);
if (error)
return (error);
}
if (vap->va_size != VNOVAL) {
- if (vp->v_type == VDIR)
+ /*
+ * 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);
+ default:
+ break;
+ }
error = VOP_TRUNCATE(vp, vap->va_size, 0, cred, p);
if (error)
return (error);
}
ip = VTOI(vp);
if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
+ if (vp->v_mount->mnt_flag & MNT_RDONLY)
+ return (EROFS);
if (cred->cr_uid != ip->i_e2fs_uid &&
(error = suser(cred, &p->p_acflag)) &&
((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
@@ -354,8 +371,11 @@ ext2fs_setattr(v)
return (error);
}
error = 0;
- if (vap->va_mode != (mode_t)VNOVAL)
+ if (vap->va_mode != (mode_t)VNOVAL) {
+ if (vp->v_mount->mnt_flag & MNT_RDONLY)
+ return (EROFS);
error = ext2fs_chmod(vp, (int)vap->va_mode, cred, p);
+ }
return (error);
}
@@ -387,7 +407,7 @@ ext2fs_chmod(vp, mode, cred, p)
ip->i_flag |= IN_CHANGE;
if ((vp->v_flag & VTEXT) && (ip->i_e2fs_mode & S_ISTXT) == 0)
#if defined(UVM)
- uvm_vnp_uncache(vp);
+ (void) uvm_vnp_uncache(vp);
#else
(void) vnode_pager_uncache(vp);
#endif
@@ -454,8 +474,8 @@ ext2fs_remove(v)
ip = VTOI(vp);
if (vp->v_type == VDIR ||
- (ip->i_e2fs_flags & (EXT2_IMMUTABLE | EXT2_APPEND)) ||
- (VTOI(dvp)->i_e2fs_flags & EXT2_APPEND)) {
+ (ip->i_e2fs_flags & (EXT2_IMMUTABLE | EXT2_APPEND)) ||
+ (VTOI(dvp)->i_e2fs_flags & EXT2_APPEND)) {
error = EPERM;
goto out;
}
@@ -490,7 +510,6 @@ ext2fs_link(v)
register struct componentname *cnp = ap->a_cnp;
struct proc *p = cnp->cn_proc;
register struct inode *ip;
- struct timespec ts;
int error;
#ifdef DIAGNOSTIC
@@ -507,7 +526,7 @@ ext2fs_link(v)
error = EXDEV;
goto out2;
}
- if (dvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p))) {
+ if (dvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE, p))) {
VOP_ABORTOP(dvp, cnp);
goto out2;
}
@@ -524,8 +543,7 @@ ext2fs_link(v)
}
ip->i_e2fs_nlink++;
ip->i_flag |= IN_CHANGE;
- TIMEVAL_TO_TIMESPEC(&time, &ts);
- error = VOP_UPDATE(vp, &ts, &ts, 1);
+ error = VOP_UPDATE(vp, NULL, NULL, 1);
if (!error)
error = ext2fs_direnter(ip, dvp, cnp);
if (error) {
@@ -586,7 +604,7 @@ ext2fs_rename(v)
register struct inode *ip, *xp, *dp;
struct proc *p = fcnp->cn_proc;
struct ext2fs_dirtemplate dirbuf;
- struct timespec ts;
+ //struct timespec ts;
int doingdirectory = 0, oldparent = 0, newparent = 0;
int error = 0;
u_char namlen;
@@ -646,7 +664,7 @@ abortit:
(void) relookup(fdvp, &fvp, fcnp);
return (VOP_REMOVE(fdvp, fvp, fcnp));
}
- if ((error = vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, p)) != 0)
+ if ((error = vn_lock(fvp, LK_EXCLUSIVE, p)) != 0)
goto abortit;
dp = VTOI(fdvp);
ip = VTOI(fvp);
@@ -662,14 +680,15 @@ abortit:
goto abortit;
}
if ((ip->i_e2fs_mode & IFMT) == IFDIR) {
- error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc);
- if (!error && tvp)
- error = VOP_ACCESS(tvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc);
- if (error) {
- VOP_UNLOCK(fvp, 0, p);
- error = EACCES;
- goto abortit;
- }
+ error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc);
+ if (!error && tvp)
+ error = VOP_ACCESS(tvp, VWRITE, tcnp->cn_cred,
+ tcnp->cn_proc);
+ if (error) {
+ VOP_UNLOCK(fvp, 0, p);
+ error = EACCES;
+ goto abortit;
+ }
/*
* Avoid ".", "..", and aliases of "." for obvious reasons.
*/
@@ -705,8 +724,7 @@ abortit:
*/
ip->i_e2fs_nlink++;
ip->i_flag |= IN_CHANGE;
- TIMEVAL_TO_TIMESPEC(&time, &ts);
- if ((error = VOP_UPDATE(fvp, &ts, &ts, 1)) != 0) {
+ if ((error = VOP_UPDATE(fvp, NULL, NULL, 1)) != 0) {
VOP_UNLOCK(fvp, 0, p);
goto bad;
}
@@ -764,7 +782,7 @@ abortit:
}
dp->i_e2fs_nlink++;
dp->i_flag |= IN_CHANGE;
- if ((error = VOP_UPDATE(tdvp, &ts, &ts, 1)) != 0)
+ if ((error = VOP_UPDATE(tdvp, NULL, NULL, 1)) != 0)
goto bad;
}
error = ext2fs_direnter(ip, tdvp, tcnp);
@@ -772,7 +790,7 @@ abortit:
if (doingdirectory && newparent) {
dp->i_e2fs_nlink--;
dp->i_flag |= IN_CHANGE;
- (void)VOP_UPDATE(tdvp, &ts, &ts, 1);
+ (void)VOP_UPDATE(tdvp, NULL, NULL, 1);
}
goto bad;
}
@@ -899,7 +917,7 @@ abortit:
error = vn_rdwr(UIO_READ, fvp, (caddr_t)&dirbuf,
sizeof (struct ext2fs_dirtemplate), (off_t)0,
UIO_SYSSPACE, IO_NODELOCKED,
- tcnp->cn_cred, NULL, (struct proc *)0);
+ tcnp->cn_cred, (size_t *)0, (struct proc *)0);
if (error == 0) {
namlen = dirbuf.dotdot_namlen;
if (namlen != 2 ||
@@ -908,13 +926,13 @@ abortit:
ufs_dirbad(xp, (doff_t)12,
"ext2fs_rename: mangled dir");
} else {
- dirbuf.dotdot_ino = newparent;
+ dirbuf.dotdot_ino = h2fs32(newparent);
(void) vn_rdwr(UIO_WRITE, fvp,
(caddr_t)&dirbuf,
sizeof (struct dirtemplate),
(off_t)0, UIO_SYSSPACE,
IO_NODELOCKED|IO_SYNC,
- tcnp->cn_cred, NULL,
+ tcnp->cn_cred, (size_t *)0,
(struct proc *)0);
cache_purge(fdvp);
}
@@ -941,7 +959,7 @@ bad:
out:
if (doingdirectory)
ip->i_flag &= ~IN_RENAME;
- if (vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, p) == 0) {
+ if (vn_lock(fvp, LK_EXCLUSIVE, p) == 0) {
ip->i_e2fs_nlink--;
ip->i_flag |= IN_CHANGE;
vput(fvp);
@@ -951,14 +969,6 @@ out:
}
/*
- * A virgin directory (no blushing please).
- */
-static struct ext2fs_dirtemplate mastertemplate = {
- 0, 12, 1, ".",
- 0, - 12, 2, ".." /* XXX -12 should be e2fs_bsize-12 */
-};
-
-/*
* Mkdir system call
*/
int
@@ -976,8 +986,7 @@ ext2fs_mkdir(v)
register struct componentname *cnp = ap->a_cnp;
register struct inode *ip, *dp;
struct vnode *tvp;
- struct ext2fs_dirtemplate dirtemplate, *dtp;
- struct timespec ts;
+ struct ext2fs_dirtemplate dirtemplate;
int error, dmode;
#ifdef DIAGNOSTIC
@@ -1005,8 +1014,7 @@ ext2fs_mkdir(v)
ip->i_e2fs_mode = dmode;
tvp->v_type = VDIR; /* Rest init'd in getnewvnode(). */
ip->i_e2fs_nlink = 2;
- TIMEVAL_TO_TIMESPEC(&time, &ts);
- error = VOP_UPDATE(tvp, &ts, &ts, 1);
+ error = VOP_UPDATE(tvp, NULL, NULL, 1);
/*
* Bump link count in parent directory
@@ -1016,19 +1024,30 @@ ext2fs_mkdir(v)
*/
dp->i_e2fs_nlink++;
dp->i_flag |= IN_CHANGE;
- if ((error = VOP_UPDATE(dvp, &ts, &ts, 1)) != 0)
+ if ((error = VOP_UPDATE(dvp, NULL, NULL, 1)) != 0)
goto bad;
/* Initialize directory with "." and ".." from static template. */
- dtp = &mastertemplate;
- dirtemplate = *dtp;
- dirtemplate.dot_ino = ip->i_number;
- dirtemplate.dotdot_ino = dp->i_number;
- /* Correct reclen of second entry */
- dirtemplate.dotdot_reclen = VTOI(dvp)->i_e2fs->e2fs_bsize - 12;
+ bzero(&dirtemplate, sizeof(dirtemplate));
+ dirtemplate.dot_ino = h2fs32(ip->i_number);
+ dirtemplate.dot_reclen = h2fs16(12);
+ dirtemplate.dot_namlen = 1;
+ if (ip->i_e2fs->e2fs.e2fs_rev > E2FS_REV0 &&
+ (ip->i_e2fs->e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE)) {
+ dirtemplate.dot_type = EXT2_FT_DIR;
+ }
+ dirtemplate.dot_name[0] = '.';
+ dirtemplate.dotdot_ino = h2fs32(dp->i_number);
+ dirtemplate.dotdot_reclen = h2fs16(VTOI(dvp)->i_e2fs->e2fs_bsize - 12);
+ dirtemplate.dotdot_namlen = 2;
+ if (ip->i_e2fs->e2fs.e2fs_rev > E2FS_REV0 &&
+ (ip->i_e2fs->e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE)) {
+ dirtemplate.dotdot_type = EXT2_FT_DIR;
+ }
+ dirtemplate.dotdot_name[0] = dirtemplate.dotdot_name[1] = '.';
error = vn_rdwr(UIO_WRITE, tvp, (caddr_t)&dirtemplate,
sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE,
- IO_NODELOCKED|IO_SYNC, cnp->cn_cred, NULL, (struct proc *)0);
+ IO_NODELOCKED|IO_SYNC, cnp->cn_cred, (size_t *)0, (struct proc *)0);
if (error) {
dp->i_e2fs_nlink--;
dp->i_flag |= IN_CHANGE;