Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/ufs/ext2fs Add support for large files (>2GB).
details: https://anonhg.NetBSD.org/src/rev/4a1a4b929118
branches: trunk
changeset: 573788:4a1a4b929118
user: ws <ws%NetBSD.org@localhost>
date: Wed Feb 09 23:02:10 2005 +0000
description:
Add support for large files (>2GB).
Like Linux, automagically convert old filesystem to use this,
if they are already at revision 1.
For revision 0, just punt (unlike Linux; makes me a bit too nervous.)
There should be an option to fsck_ext2fs to upgrade revision 0 to revision 1.
Reviewd by Manuel (bouyer@).
diffstat:
sys/ufs/ext2fs/ext2fs.h | 5 +-
sys/ufs/ext2fs/ext2fs_balloc.c | 20 ++++++++---
sys/ufs/ext2fs/ext2fs_extern.h | 4 +-
sys/ufs/ext2fs/ext2fs_inode.c | 65 +++++++++++++++++++++++++++++++-------
sys/ufs/ext2fs/ext2fs_lookup.c | 30 +++++++++++------
sys/ufs/ext2fs/ext2fs_readwrite.c | 30 +++++++++--------
sys/ufs/ext2fs/ext2fs_vfsops.c | 9 +++--
sys/ufs/ext2fs/ext2fs_vnops.c | 20 ++++++++---
8 files changed, 127 insertions(+), 56 deletions(-)
diffs (truncated from 535 to 300 lines):
diff -r 46d32a74f741 -r 4a1a4b929118 sys/ufs/ext2fs/ext2fs.h
--- a/sys/ufs/ext2fs/ext2fs.h Wed Feb 09 22:55:45 2005 +0000
+++ b/sys/ufs/ext2fs/ext2fs.h Wed Feb 09 23:02:10 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ext2fs.h,v 1.15 2004/03/22 19:23:08 bouyer Exp $ */
+/* $NetBSD: ext2fs.h,v 1.16 2005/02/09 23:02:10 ws Exp $ */
/*
* Copyright (c) 1982, 1986, 1993
@@ -213,7 +213,8 @@
/* features supported in this implementation */
#define EXT2F_COMPAT_SUPP 0x0000
-#define EXT2F_ROCOMPAT_SUPP EXT2F_ROCOMPAT_SPARSESUPER
+#define EXT2F_ROCOMPAT_SUPP (EXT2F_ROCOMPAT_SPARSESUPER \
+ | EXT2F_ROCOMPAT_LARGEFILE)
#define EXT2F_INCOMPAT_SUPP EXT2F_INCOMPAT_FTYPE
/*
diff -r 46d32a74f741 -r 4a1a4b929118 sys/ufs/ext2fs/ext2fs_balloc.c
--- a/sys/ufs/ext2fs/ext2fs_balloc.c Wed Feb 09 22:55:45 2005 +0000
+++ b/sys/ufs/ext2fs/ext2fs_balloc.c Wed Feb 09 23:02:10 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ext2fs_balloc.c,v 1.22 2004/03/22 19:23:08 bouyer Exp $ */
+/* $NetBSD: ext2fs_balloc.c,v 1.23 2005/02/09 23:02:10 ws Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@@ -65,7 +65,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_balloc.c,v 1.22 2004/03/22 19:23:08 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_balloc.c,v 1.23 2005/02/09 23:02:10 ws Exp $");
#if defined(_KERNEL_OPT)
#include "opt_uvmhist.h"
@@ -392,10 +392,18 @@
* EOF be up-to-date before each call.
*/
- if (ip->i_e2fs_size < off + bsize) {
- UVMHIST_LOG(ubchist, "old 0x%x new 0x%x",
- ip->i_e2fs_size, off + bsize,0,0);
- ip->i_e2fs_size = off + bsize;
+ if (ext2fs_size(ip) < off + bsize) {
+ UVMHIST_LOG(ubchist, "old 0x%lx%8lx new 0x%lx%8lx",
+ /* Note that arguments are always cast to u_long. */
+ ext2fs_size(ip) >> 32,
+ ext2fs_size(ip) & 0xffffffff,
+ (off + bsize) >> 32,
+ (off + bsize) & 0xffffffff);
+ error = ext2fs_setsize(ip, off + bsize);
+ if (error) {
+ UVMHIST_LOG(ubcist, "error %d", error, 0,0,0);
+ return error;
+ }
}
off += bsize;
diff -r 46d32a74f741 -r 4a1a4b929118 sys/ufs/ext2fs/ext2fs_extern.h
--- a/sys/ufs/ext2fs/ext2fs_extern.h Wed Feb 09 22:55:45 2005 +0000
+++ b/sys/ufs/ext2fs/ext2fs_extern.h Wed Feb 09 23:02:10 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ext2fs_extern.h,v 1.24 2004/05/20 06:34:32 atatat Exp $ */
+/* $NetBSD: ext2fs_extern.h,v 1.25 2005/02/09 23:02:10 ws Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@@ -109,6 +109,8 @@
int ext2fs_bmap __P((void *));
/* ext2fs_inode.c */
+u_int64_t ext2fs_size(struct inode *);
+int ext2fs_setsize(struct inode *, u_int64_t);
int ext2fs_update __P((void *));
int ext2fs_truncate __P((void *));
int ext2fs_inactive __P((void *));
diff -r 46d32a74f741 -r 4a1a4b929118 sys/ufs/ext2fs/ext2fs_inode.c
--- a/sys/ufs/ext2fs/ext2fs_inode.c Wed Feb 09 22:55:45 2005 +0000
+++ b/sys/ufs/ext2fs/ext2fs_inode.c Wed Feb 09 23:02:10 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ext2fs_inode.c,v 1.43 2004/08/15 07:19:56 mycroft Exp $ */
+/* $NetBSD: ext2fs_inode.c,v 1.44 2005/02/09 23:02:10 ws Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@@ -65,7 +65,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_inode.c,v 1.43 2004/08/15 07:19:56 mycroft Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_inode.c,v 1.44 2005/02/09 23:02:10 ws Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -92,6 +92,47 @@
daddr_t, int, long *));
/*
+ * Get the size of an inode.
+ */
+u_int64_t
+ext2fs_size(struct inode *ip)
+{
+ u_int64_t size = ip->i_e2fs_size;
+
+ if ((ip->i_e2fs_mode & IFMT) == IFREG)
+ size |= (u_int64_t)ip->i_e2fs_dacl << 32;
+ return size;
+}
+
+int
+ext2fs_setsize(struct inode *ip, u_int64_t size)
+{
+ if ((ip->i_e2fs_mode & IFMT) == IFREG ||
+ ip->i_e2fs_mode == 0) {
+ ip->i_e2fs_dacl = size >> 32;
+ if (size >= 0x80000000U) {
+ struct m_ext2fs *fs = ip->i_e2fs;
+
+ if (fs->e2fs.e2fs_rev <= E2FS_REV0) {
+ /* Linux automagically upgrades to REV1 here! */
+ return EFBIG;
+ }
+ if (!(fs->e2fs.e2fs_features_rocompat
+ & EXT2F_ROCOMPAT_LARGEFILE)) {
+ fs->e2fs.e2fs_features_rocompat |=
+ EXT2F_ROCOMPAT_LARGEFILE;
+ fs->e2fs_fmod = 1;
+ }
+ }
+ } else if (size >= 0x80000000U)
+ return EFBIG;
+
+ ip->i_e2fs_size = size;
+
+ return 0;
+}
+
+/*
* Last reference to an inode. If necessary, write or delete it.
*/
int
@@ -118,7 +159,7 @@
error = 0;
if (ip->i_e2fs_nlink == 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
vn_start_write(vp, &mp, V_WAIT | V_LOWER);
- if (ip->i_e2fs_size != 0) {
+ if (ext2fs_size(ip) != 0) {
error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED, NULL);
}
TIMEVAL_TO_TIMESPEC(&time, &ts);
@@ -245,16 +286,16 @@
return (EINVAL);
if (ovp->v_type == VLNK &&
- (oip->i_e2fs_size < ump->um_maxsymlinklen ||
+ (ext2fs_size(oip) < ump->um_maxsymlinklen ||
(ump->um_maxsymlinklen == 0 && oip->i_e2fs_nblock == 0))) {
KDASSERT(length == 0);
memset((char *)&oip->i_din.e2fs_din->e2di_shortlink, 0,
- (u_int)oip->i_e2fs_size);
- oip->i_e2fs_size = 0;
+ (u_int)ext2fs_size(oip));
+ (void)ext2fs_setsize(oip, 0);
oip->i_flag |= IN_CHANGE | IN_UPDATE;
return (VOP_UPDATE(ovp, NULL, NULL, 0));
}
- if (oip->i_e2fs_size == length) {
+ if (ext2fs_size(oip) == length) {
oip->i_flag |= IN_CHANGE | IN_UPDATE;
return (VOP_UPDATE(ovp, NULL, NULL, 0));
}
@@ -262,7 +303,7 @@
if (length > ump->um_maxfilesize)
return (EFBIG);
- osize = oip->i_e2fs_size;
+ osize = ext2fs_size(oip);
ioflag = ap->a_flags;
/*
@@ -280,7 +321,7 @@
}
uvm_vnp_setsize(ovp, length);
oip->i_flag |= IN_CHANGE | IN_UPDATE;
- KASSERT(ovp->v_size == oip->i_size);
+ KASSERT(error || ovp->v_size == oip->i_size);
return (VOP_UPDATE(ovp, NULL, NULL, 0));
}
/*
@@ -297,7 +338,7 @@
/* XXXUBC we should handle more than just VREG */
uvm_vnp_zerorange(ovp, length, size - offset);
}
- oip->i_e2fs_size = length;
+ (void)ext2fs_setsize(oip, length);
uvm_vnp_setsize(ovp, length);
/*
* Calculate index into inode's block list of
@@ -347,7 +388,7 @@
memcpy((caddr_t)newblks, (caddr_t)&oip->i_e2fs_blocks[0], sizeof newblks);
memcpy((caddr_t)&oip->i_e2fs_blocks[0], (caddr_t)oldblks, sizeof oldblks);
- oip->i_e2fs_size = osize;
+ (void)ext2fs_setsize(oip, osize);
error = vtruncbuf(ovp, lastblock + 1, 0, 0);
if (error && !allerror)
allerror = error;
@@ -407,7 +448,7 @@
/*
* Put back the real size.
*/
- oip->i_e2fs_size = length;
+ (void)ext2fs_setsize(oip, length);
oip->i_e2fs_nblock -= blocksreleased;
oip->i_flag |= IN_CHANGE;
KASSERT(ovp->v_type != VREG || ovp->v_size == oip->i_size);
diff -r 46d32a74f741 -r 4a1a4b929118 sys/ufs/ext2fs/ext2fs_lookup.c
--- a/sys/ufs/ext2fs/ext2fs_lookup.c Wed Feb 09 22:55:45 2005 +0000
+++ b/sys/ufs/ext2fs/ext2fs_lookup.c Wed Feb 09 23:02:10 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ext2fs_lookup.c,v 1.30 2004/09/17 14:11:27 skrll Exp $ */
+/* $NetBSD: ext2fs_lookup.c,v 1.31 2005/02/09 23:02:10 ws Exp $ */
/*
* Modified for NetBSD 1.2E
@@ -48,7 +48,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_lookup.c,v 1.30 2004/09/17 14:11:27 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_lookup.c,v 1.31 2005/02/09 23:02:10 ws Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -209,7 +209,7 @@
uio->uio_offset = off;
}
FREE(dirbuf, M_TEMP);
- *ap->a_eofflag = VTOI(ap->a_vp)->i_e2fs_size <= uio->uio_offset;
+ *ap->a_eofflag = ext2fs_size(VTOI(ap->a_vp)) <= uio->uio_offset;
if (ap->a_ncookies) {
if (error) {
free(*ap->a_cookies, M_TEMP);
@@ -347,7 +347,7 @@
*/
bmask = vdp->v_mount->mnt_stat.f_iosize - 1;
if (nameiop != LOOKUP || dp->i_diroff == 0 ||
- dp->i_diroff >= dp->i_e2fs_size) {
+ dp->i_diroff >= ext2fs_size(dp)) {
entryoffsetinblock = 0;
dp->i_offset = 0;
numdirpasses = 1;
@@ -360,7 +360,7 @@
nchstats.ncs_2passes++;
}
prevoff = dp->i_offset;
- endsearch = roundup(dp->i_e2fs_size, dirblksiz);
+ endsearch = roundup(ext2fs_size(dp), dirblksiz);
enduseful = 0;
searchloop:
@@ -500,7 +500,7 @@
* dp->i_offset + dp->i_count.
*/
if (slotstatus == NONE) {
- dp->i_offset = roundup(dp->i_e2fs_size, dirblksiz);
+ dp->i_offset = roundup(ext2fs_size(dp), dirblksiz);
dp->i_count = 0;
enduseful = dp->i_offset;
} else if (nameiop == DELETE) {
@@ -553,9 +553,14 @@
* Check that directory length properly reflects presence
* of this entry.
*/
- if (dp->i_offset + EXT2FS_DIRSIZ(ep->e2d_namlen) > dp->i_e2fs_size) {
+ if (dp->i_offset + EXT2FS_DIRSIZ(ep->e2d_namlen) > ext2fs_size(dp)) {
ufs_dirbad(dp, dp->i_offset, "i_size too small");
- dp->i_e2fs_size = dp->i_offset + EXT2FS_DIRSIZ(ep->e2d_namlen);
+ error = ext2fs_setsize(dp,
+ dp->i_offset + EXT2FS_DIRSIZ(ep->e2d_namlen));
+ if (error) {
+ brelse(bp);
+ return (error);
+ }
dp->i_flag |= IN_CHANGE | IN_UPDATE;
}
brelse(bp);
@@ -827,7 +832,10 @@
/* XXX should grow with balloc() */
panic("ext2fs_direnter: frag size");
else if (!error) {
- dp->i_e2fs_size = roundup(dp->i_e2fs_size, dirblksiz);
+ error = ext2fs_setsize(dp,
+ roundup(ext2fs_size(dp), dirblksiz));
+ if (error)
+ return (error);
dp->i_flag |= IN_CHANGE;
Home |
Main Index |
Thread Index |
Old Index