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