]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
Bump revision number of version 2 log support v2.1.0
authorSteve Lord <lord@sgi.com>
Tue, 18 Jun 2002 20:32:20 +0000 (20:32 +0000)
committerSteve Lord <lord@sgi.com>
Tue, 18 Jun 2002 20:32:20 +0000 (20:32 +0000)
16 files changed:
VERSION
db/sb.c
db/uuid.c
doc/CHANGES
include/libxfs.h
include/xfs_fs.h
include/xfs_log_priv.h
include/xfs_mount.h
include/xfs_sb.h
libxfs/rdwr.c
libxfs/xfs_mount.c
libxlog/xfs_log_recover.c
man/man8/mkfs.xfs.8
mkfs/xfs_mkfs.c
repair/agheader.c
repair/phase2.c

diff --git a/VERSION b/VERSION
index 307cbbb4ef22be908bbd52563dfb075dcf7591af..c82d8cc183fb07482b05b30e9af11817664d2527 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -2,6 +2,6 @@
 # This file is used by configure to get version information
 #
 PKG_MAJOR=2
-PKG_MINOR=0
-PKG_REVISION=6
+PKG_MINOR=1
+PKG_REVISION=0
 PKG_BUILD=0
diff --git a/db/sb.c b/db/sb.c
index fe54a27143fc63d1467c1a1988469ce2da38c62f..ea471d6dcc15ee282a7dc892feb91dbd500094d7 100644 (file)
--- a/db/sb.c
+++ b/db/sb.c
@@ -99,6 +99,7 @@ const field_t sb_flds[] = {
        { "unit", FLDT_UINT32D, OI(OFF(unit)), C1, 0, TYP_NONE },
        { "width", FLDT_UINT32D, OI(OFF(width)), C1, 0, TYP_NONE },
        { "dirblklog", FLDT_UINT8D, OI(OFF(dirblklog)), C1, 0, TYP_NONE },
+       { "logsunit", FLDT_UINT32D, OI(OFF(logsunit)), C1, 0, TYP_NONE },
        { NULL }
 };
 
index af7db34d0965ca4a42d6d64360ca0bc1f7108a7b..e26e1e1054857feb0880174fefba1ea33aa5d3f0 100644 (file)
--- a/db/uuid.c
+++ b/db/uuid.c
@@ -257,7 +257,8 @@ uuid_f(
                     XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart),
                     XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks),
                     &uu,
-                    XLOG_FMT)) {
+                   XFS_SB_VERSION_HASLOGV2(&mp->m_sb) ? 2 : 1,
+                    mp->m_sb.sb_logsunit, XLOG_FMT)) {
                         dbprintf("error clearing log\n");
                         return 0;
                     }
index eaad5d880dbc962204d7b6f81d747903a5481f3d..4e54705bd514c271fdbcab8529a6fa35b9c40e15 100644 (file)
@@ -1,4 +1,5 @@
-[cvs]
+xfsprogs-2.1.0 (14 Jun 2002)
+       - support for xfs version 2 log format.
        - Fix for xfs_repair mangling i8count for dir2_sf directories
        - Minor mkfs.xfs man page update for blocksize limits on Linux
 
index 0b0501868fc2671a757a8072e9823d3851aed181..430dcc1403b2293908a331858da6087e1f653b1b 100644 (file)
@@ -117,7 +117,8 @@ extern void libxfs_device_zero (dev_t, xfs_daddr_t, uint);
 extern void    libxfs_device_close (dev_t);
 
 /* check or write log footer: specify device, log size in blocks & uuid */
-extern int     libxfs_log_clear (dev_t, xfs_daddr_t, uint, uuid_t *, int);
+extern int     libxfs_log_clear (dev_t, xfs_daddr_t, uint, uuid_t *,
+                               int, int, int);
 
 /* 
  * Define a user-level mount structure with all we need
@@ -169,6 +170,7 @@ typedef struct xfs_mount {
        __uint64_t              m_maxicount;    /* maximum inode count */
        int                     m_dalign;       /* stripe unit */
        int                     m_swidth;       /* stripe width */
+       int                     m_lstripemask;  /* log stripe mask */
        int                     m_sinoalign;    /* stripe unit inode alignmnt */
        int                     m_dir_magicpct; /* 37% of the dir blocksize */
        __uint8_t               m_dirversion;   /* 1 or 2 */
index f0b852a77730d2199e1a3d9ffe1e6f9fb9b43db3..bea0c97b98ac4a425a2a24672923c57ddd5687e4 100644 (file)
@@ -161,6 +161,32 @@ typedef struct xfs_flock64 {
        __s32           l_pad[4];       /* reserve area                     */
 } xfs_flock64_t;
 
+/*
+ * Output for XFS_IOC_FSGEOMETRY_V1
+ */
+typedef struct xfs_fsop_geom_v1 {
+       __u32           blocksize;      /* filesystem (data) block size */
+       __u32           rtextsize;      /* realtime extent size         */
+       __u32           agblocks;       /* fsblocks in an AG            */
+       __u32           agcount;        /* number of allocation groups  */
+       __u32           logblocks;      /* fsblocks in the log          */
+       __u32           sectsize;       /* (data) sector size, bytes    */
+       __u32           inodesize;      /* inode size in bytes          */
+       __u32           imaxpct;        /* max allowed inode space(%)   */
+       __u64           datablocks;     /* fsblocks in data subvolume   */
+       __u64           rtblocks;       /* fsblocks in realtime subvol  */
+       __u64           rtextents;      /* rt extents in realtime subvol*/
+       __u64           logstart;       /* starting fsblock of the log  */
+       unsigned char   uuid[16];       /* unique id of the filesystem  */
+       __u32           sunit;          /* stripe unit, fsblocks        */
+       __u32           swidth;         /* stripe width, fsblocks       */
+       __s32           version;        /* structure version            */
+       __u32           flags;          /* superblock version flags     */
+       __u32           logsectsize;    /* log sector size, bytes       */
+       __u32           rtsectsize;     /* realtime sector size, bytes  */
+       __u32           dirblocksize;   /* directory block size, bytes  */
+} xfs_fsop_geom_v1_t;
+
 /*
  * Output for XFS_IOC_FSGEOMETRY
  */
@@ -185,6 +211,7 @@ typedef struct xfs_fsop_geom {
        __u32           logsectsize;    /* log sector size, bytes       */
        __u32           rtsectsize;     /* realtime sector size, bytes  */
        __u32           dirblocksize;   /* directory block size, bytes  */
+       __u32           logsunit;       /* log stripe unit, bytes */
 } xfs_fsop_geom_t;
 
 /* Output for XFS_FS_COUNTS */
@@ -211,6 +238,7 @@ typedef struct xfs_fsop_resblks {
 #define        XFS_FSOP_GEOM_FLAGS_SHARED      0x20    /* read-only shared     */
 #define        XFS_FSOP_GEOM_FLAGS_EXTFLG      0x40    /* special extent flag  */
 #define        XFS_FSOP_GEOM_FLAGS_DIRV2       0x80    /* directory version 2  */
+#define XFS_FSOP_GEOM_FLAGS_LOGV2      0x100   /* log format version 2 */
 
 
 /*
@@ -432,7 +460,7 @@ typedef struct xfs_handle {
 /*
  * ioctl commands that replace IRIX syssgi()'s
  */
-#define        XFS_IOC_FSGEOMETRY           _IOR ('X', 100, struct xfs_fsop_geom)
+#define        XFS_IOC_FSGEOMETRY_V1        _IOR ('X', 100, struct xfs_fsop_geom_v1)
 #define        XFS_IOC_FSBULKSTAT           _IOWR('X', 101, struct xfs_fsop_bulkreq)
 #define        XFS_IOC_FSBULKSTAT_SINGLE    _IOWR('X', 102, struct xfs_fsop_bulkreq)
 #define        XFS_IOC_FSINUMBERS           _IOWR('X', 103, struct xfs_fsop_bulkreq)
@@ -456,6 +484,7 @@ typedef struct xfs_handle {
 #define        XFS_IOC_FSSETDM_BY_HANDLE    _IOW ('X', 121, struct xfs_fsop_setdm_handlereq)
 #define        XFS_IOC_ATTRLIST_BY_HANDLE   _IOW ('X', 122, struct xfs_fsop_attrlist_handlereq)
 #define        XFS_IOC_ATTRMULTI_BY_HANDLE  _IOW ('X', 123, struct xfs_fsop_attrmulti_handlereq)
+#define        XFS_IOC_FSGEOMETRY           _IOR ('X', 124, struct xfs_fsop_geom)
 /*      XFS_IOC_GETFSUUID ---------- deprecated 140      */
 
 
index 4fbffc9386abf9f2f6db11dfca639e27b1cd95f1..01a890ec1931b6a2cfa9c5e3266aad585a4bbd6a 100644 (file)
@@ -54,10 +54,16 @@ struct xfs_mount;
 #define XLOG_MAX_ICLOGS                8
 #define XLOG_CALLBACK_SIZE     10
 #define XLOG_HEADER_MAGIC_NUM  0xFEEDbabe      /* Illegal cycle number */
+#define XLOG_VERSION_1         1
+#define XLOG_VERSION_2         2               /* Large IClogs, Log sunit */
+#define XLOG_VERSION_OKBITS    (XLOG_VERSION_1 | XLOG_VERSION_2)
 #define XLOG_RECORD_BSIZE      (16*1024)       /* eventually 32k */
-#define XLOG_MAX_RECORD_BSIZE  (32*1024)
+#define XLOG_BIG_RECORD_BSIZE  (32*1024)       /* 32k buffers */
+#define XLOG_MAX_RECORD_BSIZE  (256*1024)
+#define XLOG_HEADER_CYCLE_SIZE (32*1024)       /* cycle data in header */
 #define XLOG_RECORD_BSHIFT     14              /* 16384 == 1 << 14 */
-#define XLOG_MAX_RECORD_BSHIFT 15              /* 32k == 1 << 15 */
+#define XLOG_BIG_RECORD_BSHIFT 15              /* 32k == 1 << 15 */
+#define XLOG_MAX_RECORD_BSHIFT 18              /* 256k == 1 << 18 */
 #if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XLOG_BTOLRBB)
 int xlog_btolrbb(int b);
 #define XLOG_BTOLRBB(b)                xlog_btolrbb(b)
@@ -67,6 +73,10 @@ int xlog_btolrbb(int b);
 
 #define XLOG_HEADER_SIZE       512
 
+#define XLOG_TOTAL_REC_SHIFT(log) \
+       BTOBB(XLOG_MAX_ICLOGS << (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) ? \
+        XLOG_MAX_RECORD_BSHIFT : XLOG_BIG_RECORD_BSHIFT))
+   
 /*
  *  set lsns
  */
@@ -115,7 +125,7 @@ int xlog_btolrbb(int b);
 #define GET_CLIENT_ID(i,arch) \
     ((i) >> 24)
 #endif
-   
+
 #if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XLOG_GRANT_SUB_SPACE)
 void xlog_grant_sub_space(struct log *log, int bytes, int type);
 #define XLOG_GRANT_SUB_SPACE(log,bytes,type)   \
@@ -348,7 +358,7 @@ typedef struct xlog_ticket {
 
 typedef struct xlog_op_header {
        xlog_tid_t oh_tid;      /* transaction id of operation  :  4 b */
-       int        oh_len;      /* bytes in data region         :  2 b */
+       int        oh_len;      /* bytes in data region         :  4 b */
        __uint8_t  oh_clientid; /* who sent me this             :  1 b */
        __uint8_t  oh_flags;    /*                              :  1 b */
        ushort     oh_res2;     /* 32 bit align                 :  2 b */
@@ -382,12 +392,17 @@ typedef struct xlog_rec_header {
        uint      h_chksum;     /* may not be used; non-zero if used    :  4 */
        int       h_prev_block; /* block number to previous LR          :  4 */
        int       h_num_logops; /* number of log operations in this LR  :  4 */
-       uint      h_cycle_data[XLOG_MAX_RECORD_BSIZE / BBSIZE];
+       uint      h_cycle_data[XLOG_HEADER_CYCLE_SIZE / BBSIZE];        
         /* new fields */
         int       h_fmt;        /* format of log record                 :  4 */
         uuid_t    h_fs_uuid;    /* uuid of FS                           : 16 */
+       int       h_size;       /* iclog size                           :  4 */
 } xlog_rec_header_t;
 
+typedef struct xlog_rec_ext_header {
+       uint      xh_cycle;     /* write cycle of log                   : 4 */
+       uint      xh_cycle_data[XLOG_HEADER_CYCLE_SIZE / BBSIZE]; /*    : 256 */
+} xlog_rec_ext_header_t;
 #ifdef __KERNEL__
 /*
  * - A log record header is 512 bytes.  There is plenty of room to grow the
@@ -406,7 +421,6 @@ typedef struct xlog_rec_header {
  * - ic_state is the state of the iclog.
  */
 typedef struct xlog_iclog_fields {
-       struct tq_struct        ic_write_sched;
        sv_t                    ic_forcesema;
        struct xlog_in_core     *ic_next;
        struct xlog_in_core     *ic_prev;
@@ -423,14 +437,16 @@ typedef struct xlog_iclog_fields {
        int                     ic_roundoff;
        int                     ic_bwritecnt;
        ushort_t                ic_state;
+       char                    *ic_datap;      /* pointer to iclog data */
+       struct tq_struct        ic_write_sched;
 } xlog_iclog_fields_t;
 
 typedef struct xlog_in_core2 {
        union {
                xlog_rec_header_t hic_header;
+               xlog_rec_ext_header_t hic_xheader;
                char              hic_sector[XLOG_HEADER_SIZE];
        } ic_h;
-       __uint8_t                 hic_data[1];
 } xlog_in_core_2_t;
 
 typedef struct xlog_in_core {
@@ -456,8 +472,8 @@ typedef struct xlog_in_core {
 #define        ic_roundoff     hic_fields.ic_roundoff
 #define        ic_bwritecnt    hic_fields.ic_bwritecnt
 #define        ic_state        hic_fields.ic_state
+#define ic_datap       hic_fields.ic_datap
 #define ic_header      hic_data->ic_h.hic_header
-#define ic_data                hic_data->hic_data
 
 /*
  * The reservation head lsn is not made up of a cycle number and block number.
@@ -514,6 +530,8 @@ typedef struct log {
     uint               l_flags;
     uint               l_quotaoffs_flag;/* XFS_DQ_*, if QUOTAOFFs found */
     struct xfs_buf_cancel **l_buf_cancel_table;        
+    int                        l_iclog_hsize;  /* size of iclog header */
+    int                        l_iclog_heads;  /* number of iclog header sectors */
 } xlog_t;
 
 
index 31f2e37b0a7cfd0a0f85e754a20c10d8a2403804..bd731b55f89e76c073f352eab6c1785143eac9df 100644 (file)
@@ -278,6 +278,7 @@ typedef struct xfs_mount {
 #endif
        int                     m_dalign;       /* stripe unit */
        int                     m_swidth;       /* stripe width */
+       int                     m_lstripemask;  /* log stripe mask */
        int                     m_sinoalign;    /* stripe unit inode alignmnt */
        int                     m_attr_magicpct;/* 37% of the blocksize */
        int                     m_dir_magicpct; /* 37% of the dir blocksize */
index adc2b1a4b4e6fea269f7a847855caa0fb61efe16..3b3780590644aa989df24f089a7b4af6b4509bad 100644 (file)
@@ -56,6 +56,7 @@ struct xfs_mount;
 #define        XFS_SB_VERSION_ALIGNBIT         0x0080
 #define        XFS_SB_VERSION_DALIGNBIT        0x0100
 #define        XFS_SB_VERSION_SHAREDBIT        0x0200
+#define XFS_SB_VERSION_LOGV2BIT                0x0400
 #define        XFS_SB_VERSION_EXTFLGBIT        0x1000
 #define        XFS_SB_VERSION_DIRV2BIT         0x2000
 #define        XFS_SB_VERSION_OKSASHFBITS      \
@@ -67,7 +68,8 @@ struct xfs_mount;
         XFS_SB_VERSION_QUOTABIT | \
         XFS_SB_VERSION_ALIGNBIT | \
         XFS_SB_VERSION_DALIGNBIT | \
-        XFS_SB_VERSION_SHAREDBIT)
+        XFS_SB_VERSION_SHAREDBIT | \
+        XFS_SB_VERSION_LOGV2BIT)
 #define        XFS_SB_VERSION_OKSASHBITS       \
        (XFS_SB_VERSION_NUMBITS | \
         XFS_SB_VERSION_REALFBITS | \
@@ -76,13 +78,14 @@ struct xfs_mount;
        (XFS_SB_VERSION_NUMBITS | \
         XFS_SB_VERSION_OKREALFBITS | \
         XFS_SB_VERSION_OKSASHFBITS)
-#define        XFS_SB_VERSION_MKFS(ia,dia,extflag,dirv2)       \
-       (((ia) || (dia) || (extflag) || (dirv2)) ? \
+#define        XFS_SB_VERSION_MKFS(ia,dia,extflag,dirv2,na)    \
+       (((ia) || (dia) || (extflag) || (dirv2) || (na)) ? \
                (XFS_SB_VERSION_4 | \
                 ((ia) ? XFS_SB_VERSION_ALIGNBIT : 0) | \
                 ((dia) ? XFS_SB_VERSION_DALIGNBIT : 0) | \
                 ((extflag) ? XFS_SB_VERSION_EXTFLGBIT : 0) | \
-                ((dirv2) ? XFS_SB_VERSION_DIRV2BIT : 0)) : \
+                ((dirv2) ? XFS_SB_VERSION_DIRV2BIT : 0) | \
+                ((na) ? XFS_SB_VERSION_LOGV2BIT : 0)) : \
                XFS_SB_VERSION_1)
 
 typedef struct xfs_sb
@@ -137,7 +140,8 @@ typedef struct xfs_sb
        __uint32_t      sb_unit;        /* stripe or raid unit */
        __uint32_t      sb_width;       /* stripe or raid width */      
        __uint8_t       sb_dirblklog;   /* log2 of dir block size (fsbs) */
-        __uint8_t       sb_dummy[7];    /* padding */
+        __uint8_t       sb_dummy[3];    /* padding */
+       __uint32_t      sb_logsunit;    /* stripe unit size for the log */
 } xfs_sb_t;
 
 /*
@@ -155,7 +159,7 @@ typedef enum {
        XFS_SBS_IFREE, XFS_SBS_FDBLOCKS, XFS_SBS_FREXTENTS, XFS_SBS_UQUOTINO,
        XFS_SBS_GQUOTINO, XFS_SBS_QFLAGS, XFS_SBS_FLAGS, XFS_SBS_SHARED_VN,
        XFS_SBS_INOALIGNMT, XFS_SBS_UNIT, XFS_SBS_WIDTH, XFS_SBS_DIRBLKLOG,
-        XFS_SBS_DUMMY,
+        XFS_SBS_DUMMY, XFS_SBS_LOGSUNIT,
        XFS_SBS_FIELDCOUNT
 } xfs_sb_field_t;
 
@@ -400,6 +404,15 @@ int xfs_sb_version_hasdirv2(xfs_sb_t *sbp);
         ((sbp)->sb_versionnum & XFS_SB_VERSION_DIRV2BIT))
 #endif
 
+#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_HASLOGV2)
+int xfs_sb_version_haslogv2(xfs_sb_t *sbp);
+#define XFS_SB_VERSION_HASLOGV2(sbp)   xfs_sb_version_haslogv2(sbp)
+#else
+#define XFS_SB_VERSION_HASLOGV2(sbp)   \
+       ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
+       ((sbp)->sb_versionnum & XFS_SB_VERSION_LOGV2BIT))
+#endif
+
 #if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_HASEXTFLGBIT)
 int xfs_sb_version_hasextflgbit(xfs_sb_t *sbp);
 #define XFS_SB_VERSION_HASEXTFLGBIT(sbp)       xfs_sb_version_hasextflgbit(sbp)
index 797e217f08a34067a3721766c77c606e683f0580..10587aef2c2eeee2c94f1facb064ec8d39d918ab 100644 (file)
@@ -80,11 +80,14 @@ libxfs_log_clear(
         xfs_daddr_t start,
         uint        length,
         uuid_t      *fs_uuid, 
+       int         version,
+       int         sunit,
         int         fmt)
 {
        xfs_buf_t               *buf;
         xlog_rec_header_t       *head;
         xlog_op_header_t        *op;
+       int                     i, len;
         /* the data section must be 32 bit size aligned */
         struct {
             __uint16_t magic;
@@ -99,11 +102,15 @@ libxfs_log_clear(
         libxfs_device_zero(device, start, length);   
                    
         /* then write a log record header */
-        buf = libxfs_getbuf(device, start, 1);
+       if ((version == 2) && sunit)
+               len = BTOBB(sunit);
+       else
+               len = 1;
+        buf = libxfs_getbuf(device, start, len);
         if (!buf) 
             return -1;
         
-        memset(XFS_BUF_PTR(buf), 0, BBSIZE);
+        memset(XFS_BUF_PTR(buf), 0, BBSIZE * len);
        head = (xlog_rec_header_t *)XFS_BUF_PTR(buf);
         
         /* note that oh_tid actually contains the cycle number
@@ -113,18 +120,34 @@ libxfs_log_clear(
         
        INT_SET(head->h_magicno,        ARCH_CONVERT, XLOG_HEADER_MAGIC_NUM);
        INT_SET(head->h_cycle,          ARCH_CONVERT, 1);
-       INT_SET(head->h_version,        ARCH_CONVERT, 1);
-       INT_SET(head->h_len,            ARCH_CONVERT, 20);
+       INT_SET(head->h_version,        ARCH_CONVERT, version);
+       if (len != 1)
+               INT_SET(head->h_len,            ARCH_CONVERT, sunit - BBSIZE);
+       else
+               INT_SET(head->h_len,            ARCH_CONVERT, 20);
        INT_SET(head->h_chksum,         ARCH_CONVERT, 0);
        INT_SET(head->h_prev_block,     ARCH_CONVERT, -1);
        INT_SET(head->h_num_logops,     ARCH_CONVERT, 1);
        INT_SET(head->h_cycle_data[0],  ARCH_CONVERT, 0xb0c0d0d0);
        INT_SET(head->h_fmt,            ARCH_CONVERT, fmt);
+       INT_SET(head->h_size,           ARCH_CONVERT, XLOG_HEADER_CYCLE_SIZE);
         
         ASSIGN_ANY_LSN(head->h_lsn,         1, 0, ARCH_CONVERT);
         ASSIGN_ANY_LSN(head->h_tail_lsn,    1, 0, ARCH_CONVERT);
         
         memcpy(head->h_fs_uuid,  fs_uuid, sizeof(uuid_t));
+
+       if (len > 1) {
+               xfs_caddr_t     dp;
+               uint            cycle_lsn;
+
+               cycle_lsn = CYCLE_LSN_NOCONV(head->h_lsn, ARCH_CONVERT);
+               dp = XFS_BUF_PTR(buf) + BBSIZE;
+               for (i = 1; i < len; i++) {
+                       *(uint *)dp = cycle_lsn;
+                       dp += BBSIZE;
+               }
+       }
         
         if (libxfs_writebuf(buf, 0))
             return -1;
index 41e4a44f2742d8708cf87ae36c064ba3e4b447c3..07e28487e7cab55ef00217563145cca319711c91 100644 (file)
@@ -54,6 +54,16 @@ xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp)
        mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG;
        mp->m_blockwmask = mp->m_blockwsize - 1;
 
+
+       if (XFS_SB_VERSION_HASLOGV2(sbp)) {
+               if (sbp->sb_logsunit <= 1) {
+                       mp->m_lstripemask = 1;
+               } else {
+                       mp->m_lstripemask =
+                               1 << xfs_highbit32(sbp->sb_logsunit >> BBSHIFT);
+               }
+       }
+
        /*
         * Setup for attributes, in case they get created.
         * This value is for inodes getting attributes for the first time,
@@ -147,6 +157,7 @@ static struct {
     { offsetof(xfs_sb_t, sb_width),      0 },
     { offsetof(xfs_sb_t, sb_dirblklog),  0 },
     { offsetof(xfs_sb_t, sb_dummy),      1 },
+    { offsetof(xfs_sb_t, sb_logsunit),   0 },
     { sizeof(xfs_sb_t),                  0 }
 };
 
index f47f27d91bac59b7cae6e918adf6ed008537c827..b270b1f83db0c90c5c4e5f130f2ff0d72a7ed760 100644 (file)
@@ -156,6 +156,7 @@ xlog_find_verify_log_record(xlog_t  *log,
     int                        error       = 0;
     int                 smallmem    = 0;
     int                 num_blks    = *last_blk - start_blk;
+    int                        xhdrs;
 
     ASSERT(start_blk != 0 || *last_blk != start_blk);
 
@@ -215,8 +216,17 @@ xlog_find_verify_log_record(xlog_t *log,
      * reset last_blk.  Only when last_blk points in the middle of a log
      * record do we update last_blk.
      */
+    if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
+       int h_size = INT_GET(head->h_size, ARCH_CONVERT);
+       xhdrs = h_size / XLOG_HEADER_CYCLE_SIZE;
+       if (h_size % XLOG_HEADER_CYCLE_SIZE)
+               xhdrs++;
+    } else {
+       xhdrs = 1;
+    }
+
     if (*last_blk - i + extra_bblks 
-               != BTOBB(INT_GET(head->h_len, ARCH_CONVERT))+1)
+               != BTOBB(INT_GET(head->h_len, ARCH_CONVERT))+xhdrs)
            *last_blk = i;
 
 out:
@@ -354,7 +364,7 @@ xlog_find_head(xlog_t  *log,
      * in the in-core log.  The following number can be made tighter if
      * we actually look at the block size of the filesystem.
      */
-    num_scan_bblks = BTOBB(XLOG_MAX_ICLOGS<<XLOG_MAX_RECORD_BSHIFT);
+    num_scan_bblks = XLOG_TOTAL_REC_SHIFT(log);
     if (head_blk >= num_scan_bblks) {
        /*
         * We are guaranteed that the entire check can be performed
@@ -512,6 +522,7 @@ xlog_find_tail(xlog_t  *log,
        xfs_daddr_t             umount_data_blk;
        xfs_daddr_t             after_umount_blk;
        xfs_lsn_t               tail_lsn;
+       int                     hblks;
        
        found = error = 0;
 
@@ -605,10 +616,25 @@ xlog_find_tail(xlog_t  *log,
         * unmount record if there is one, so we pass the lsn of the
         * unmount record rather than the block after it.
         */
-       after_umount_blk = (i + 2) % log->l_logBBsize;
+       if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
+               int     h_size = INT_GET(rhead->h_size, ARCH_CONVERT);
+               int     h_version = INT_GET(rhead->h_version, ARCH_CONVERT);
+               if ((h_version && XLOG_VERSION_2) && 
+                   (h_size > XLOG_HEADER_CYCLE_SIZE)) {
+                       hblks = h_size / XLOG_HEADER_CYCLE_SIZE;
+                       if (h_size % XLOG_HEADER_CYCLE_SIZE)
+                               hblks++;
+               } else {
+                       hblks = 1;
+               }
+       } else {
+               hblks = 1;
+       }
+       after_umount_blk = (i + hblks +
+               (int)BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT))) % log->l_logBBsize;
        tail_lsn = log->l_tail_lsn;
        if (*head_blk == after_umount_blk && INT_GET(rhead->h_num_logops, ARCH_CONVERT) == 1) {
-               umount_data_blk = (i + 1) % log->l_logBBsize;
+               umount_data_blk = (i + hblks) % log->l_logBBsize;
                if ((error = xlog_bread(log, umount_data_blk, 1, bp))) {
                        goto bread_err;
                }
@@ -653,7 +679,6 @@ exit:
        return error;
 }      /* xlog_find_tail */
 
-
 /*
  * Is the log zeroed at all?
  *
@@ -722,7 +747,7 @@ xlog_find_zeroed(struct log *log,
         * we scan over the defined maximum blocks.  At this point, the maximum
         * is not chosen to mean anything special.   XXXmiken
         */
-       num_scan_bblks = BTOBB(XLOG_MAX_ICLOGS<<XLOG_MAX_RECORD_BSHIFT);
+       num_scan_bblks = XLOG_TOTAL_REC_SHIFT(log);
        ASSERT(num_scan_bblks <= INT_MAX);
         
        if (last_blk < num_scan_bblks)
@@ -766,17 +791,34 @@ xlog_unpack_data(xlog_rec_header_t *rhead,
                 xfs_caddr_t       dp,
                 xlog_t            *log)
 {
-       int i;
+       int i, j, k;
+       union ich {
+               xlog_rec_header_t       hic_header;
+               xlog_rec_ext_header_t   hic_xheader;
+               char                    hic_sector[XLOG_HEADER_SIZE];
+       } *xhdr;
+
 #if defined(DEBUG) && defined(XFS_LOUD_RECOVERY)
        uint *up = (uint *)dp;
        uint chksum = 0;
 #endif
 
-       for (i=0; i<BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT)); i++) {
-               /* these are both on-disk, so don't endian flip twice */
+       for (i=0; i < BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT)) &&
+                 i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) {
                *(uint *)dp = *(uint *)&rhead->h_cycle_data[i];
                dp += BBSIZE;
        }
+
+       if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
+               xhdr = (union ich*)rhead;
+               for ( ; i < BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT)); i++) {
+                       j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
+                       k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
+                       *(uint *)dp = xhdr[j].hic_xheader.xh_cycle_data[k];
+                       dp += BBSIZE;
+               }
+       }
+
 #if defined(DEBUG) && defined(XFS_LOUD_RECOVERY)
        /* divide length by 4 to get # words */
        for (i=0; i < INT_GET(rhead->h_len, ARCH_CONVERT) >> 2; i++) {
@@ -791,13 +833,16 @@ xlog_unpack_data(xlog_rec_header_t *rhead,
                            INT_GET(rhead->h_chksum, ARCH_CONVERT), chksum);
                    cmn_err(CE_DEBUG,
 "XFS: Disregard message if filesystem was created with non-DEBUG kernel");
+                   if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
+                           cmn_err(CE_DEBUG, 
+                               "XFS: LogR this is a LogV2 filesystem\n");
+                   }
                    log->l_flags |= XLOG_CHKSUM_MISMATCH;
            }
         }
 #endif /* DEBUG && XFS_LOUD_RECOVERY */
 }      /* xlog_unpack_data */
 
-
 STATIC xlog_recover_t *
 xlog_recover_find_tid(xlog_recover_t *q,
                      xlog_tid_t     tid)
@@ -1048,7 +1093,7 @@ xlog_recover_process_data(xlog_t      *log,
     if (xlog_header_check_recover(log->l_mp, rhead))
            return (XFS_ERROR(EIO));
     
-    while (dp < lp) {
+    while ((dp < lp) && num_logops) {
        ASSERT(dp + sizeof(xlog_op_header_t) <= lp);
        ohead = (xlog_op_header_t *)dp;
        dp += sizeof(xlog_op_header_t);
@@ -1130,38 +1175,87 @@ xlog_do_recovery_pass(xlog_t    *log,
     xfs_daddr_t                blk_no;
     xfs_caddr_t                bufaddr;
     xfs_buf_t          *hbp, *dbp;
-    int                        error;
+    int                        error, h_size;
     int                        bblks, split_bblks;
+    int                        hblks, split_hblks, wrapped_hblks;
     xlog_recover_t     *rhash[XLOG_RHASH_SIZE];
 
     error = 0;
-    hbp = xlog_get_bp(1,log->l_mp);
+
+
+    /*
+     * Read the header of the tail block and get the iclog buffer size from
+     * h_size.  Use this to tell how many sectors make up the log header.
+     */
+    if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
+       /*
+        * When using variable length iclogs, read first sector of iclog
+        * header and extract the header size from it.  Get a new hbp that
+        * is the correct size.
+        */
+       hbp = xlog_get_bp(1, log->l_mp);
+       if (!hbp)
+           return ENOMEM;
+       if ((error = xlog_bread(log, tail_blk, 1, hbp)))
+           goto bread_err1;
+       rhead = (xlog_rec_header_t *)XFS_BUF_PTR(hbp);
+       ASSERT(INT_GET(rhead->h_magicno, ARCH_CONVERT) ==
+                                               XLOG_HEADER_MAGIC_NUM);
+       if ((INT_GET(rhead->h_version, ARCH_CONVERT) & (~XLOG_VERSION_OKBITS)) != 0) {
+           xlog_warn("XFS: xlog_do_recovery_pass: unrecognised log version number.");
+           error = XFS_ERROR(EIO);
+           goto bread_err1;
+       }
+       h_size = INT_GET(rhead->h_size, ARCH_CONVERT);
+
+       if ((INT_GET(rhead->h_version, ARCH_CONVERT) & XLOG_VERSION_2) &&
+           (h_size > XLOG_HEADER_CYCLE_SIZE)) {
+           hblks = h_size / XLOG_HEADER_CYCLE_SIZE;
+           if (h_size % XLOG_HEADER_CYCLE_SIZE)
+               hblks++;
+           xlog_put_bp(hbp);
+           hbp = xlog_get_bp(hblks, log->l_mp);
+       } else {
+           hblks=1;
+       }
+    } else {
+       hblks=1;
+       hbp = xlog_get_bp(1, log->l_mp);
+       h_size = XLOG_BIG_RECORD_BSIZE;
+    }
+
     if (!hbp)
        return ENOMEM;
-    dbp = xlog_get_bp(BTOBB(XLOG_MAX_RECORD_BSIZE),log->l_mp);
+    dbp = xlog_get_bp(BTOBB(h_size),log->l_mp);
     if (!dbp) {
        xlog_put_bp(hbp);
        return ENOMEM;
     }
+
     bzero(rhash, sizeof(rhash));
     if (tail_blk <= head_blk) {
        for (blk_no = tail_blk; blk_no < head_blk; ) {
-           if ((error = xlog_bread(log, blk_no, 1, hbp)))
-               goto bread_err;
+           if ((error = xlog_bread(log, blk_no, hblks, hbp)))
+               goto bread_err2;
            rhead = (xlog_rec_header_t *)XFS_BUF_PTR(hbp);
            ASSERT(INT_GET(rhead->h_magicno, ARCH_CONVERT) == XLOG_HEADER_MAGIC_NUM);
            ASSERT(BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT) <= INT_MAX));
+           if ((INT_GET(rhead->h_version, ARCH_CONVERT) & (~XLOG_VERSION_OKBITS)) != 0) {
+               xlog_warn("XFS: xlog_do_recovery_pass: unrecognised log version number.");
+               error = XFS_ERROR(EIO);
+               goto bread_err2;
+           }
            bblks = (int) BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT));   /* blocks in data section */
            if (bblks > 0) {
-               if ((error = xlog_bread(log, blk_no+1, bblks, dbp)))
-                   goto bread_err;
+               if ((error = xlog_bread(log, blk_no+hblks, bblks, dbp)))
+                   goto bread_err2;
                xlog_unpack_data(rhead, XFS_BUF_PTR(dbp), log);
                if ((error = xlog_recover_process_data(log, rhash,
                                                      rhead, XFS_BUF_PTR(dbp),
                                                      pass)))
-                       goto bread_err;
+                       goto bread_err2;
            }
-           blk_no += (bblks+1);
+           blk_no += (bblks+hblks);
        }
     } else {
        /*
@@ -1171,10 +1265,33 @@ xlog_do_recovery_pass(xlog_t    *log,
         */
        blk_no = tail_blk;
        while (blk_no < log->l_logBBsize) {
-
-           /* Read header of one block */
-           if ((error = xlog_bread(log, blk_no, 1, hbp)))
-               goto bread_err;
+           /*
+            * Check for header wrapping around physical end-of-log
+            */
+           wrapped_hblks = 0;
+           if (blk_no+hblks <= log->l_logBBsize) {
+               /* Read header in one read */
+               if ((error = xlog_bread(log, blk_no, hblks, hbp)))
+                   goto bread_err2;
+           } else {
+               /* This log record is split across physical end of log */
+               split_hblks = 0;
+               if (blk_no != log->l_logBBsize) {
+                   /* some data is before physical end of log */
+                   ASSERT(blk_no <= INT_MAX);
+                   split_hblks = log->l_logBBsize - (int)blk_no;
+                   ASSERT(split_hblks > 0);
+                   if ((error = xlog_bread(log, blk_no, split_hblks, hbp)))
+                       goto bread_err2;
+               }
+               bufaddr = XFS_BUF_PTR(hbp);
+               XFS_BUF_SET_PTR(hbp, bufaddr + BBTOB(split_hblks),
+                       BBTOB(hblks - split_hblks));
+               wrapped_hblks = hblks - split_hblks;
+               if ((error = xlog_bread(log, 0, wrapped_hblks, hbp)))
+                   goto bread_err2;
+               XFS_BUF_SET_PTR(hbp, bufaddr, hblks);
+           }
            rhead = (xlog_rec_header_t *)XFS_BUF_PTR(hbp);
            ASSERT(INT_GET(rhead->h_magicno, ARCH_CONVERT) == XLOG_HEADER_MAGIC_NUM);
            ASSERT(BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT) <= INT_MAX));            
@@ -1182,21 +1299,19 @@ xlog_do_recovery_pass(xlog_t    *log,
 
            /* LR body must have data or it wouldn't have been written */
            ASSERT(bblks > 0);
-           blk_no++;                   /* successfully read header */
-           ASSERT(blk_no <= log->l_logBBsize);
+           blk_no += hblks;                    /* successfully read header */
 
            if ((INT_GET(rhead->h_magicno, ARCH_CONVERT) != XLOG_HEADER_MAGIC_NUM) ||
                (BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT) > INT_MAX)) ||
-               (bblks <= 0) ||
-               (blk_no > log->l_logBBsize)) {
+               (bblks <= 0)) {
                    error = EFSCORRUPTED;
-                   goto bread_err;
+                   goto bread_err2;
            }
                    
            /* Read in data for log record */
            if (blk_no+bblks <= log->l_logBBsize) {
                if ((error = xlog_bread(log, blk_no, bblks, dbp)))
-                   goto bread_err;
+                   goto bread_err2;
            } else {
                /* This log record is split across physical end of log */
                split_bblks = 0;
@@ -1207,20 +1322,21 @@ xlog_do_recovery_pass(xlog_t    *log,
                    split_bblks = log->l_logBBsize - (int)blk_no;
                    ASSERT(split_bblks > 0);
                    if ((error = xlog_bread(log, blk_no, split_bblks, dbp)))
-                       goto bread_err;
+                       goto bread_err2;
                }
                bufaddr = XFS_BUF_PTR(dbp);
                XFS_BUF_SET_PTR(dbp, bufaddr + BBTOB(split_bblks),
                        BBTOB(bblks - split_bblks));
-               if ((error = xlog_bread(log, 0, bblks - split_bblks, dbp)))
-                   goto bread_err;
-               XFS_BUF_SET_PTR(dbp, bufaddr, XLOG_MAX_RECORD_BSIZE);
+               if ((error = xlog_bread(log, wrapped_hblks,
+                                       bblks - split_bblks, dbp)))
+                   goto bread_err2;
+               XFS_BUF_SET_PTR(dbp, bufaddr, XLOG_BIG_RECORD_BSIZE);
            }
            xlog_unpack_data(rhead, XFS_BUF_PTR(dbp), log);
            if ((error = xlog_recover_process_data(log, rhash,
                                                  rhead, XFS_BUF_PTR(dbp),
                                                  pass)))
-               goto bread_err;
+               goto bread_err2;
            blk_no += bblks;
        }
 
@@ -1229,26 +1345,27 @@ xlog_do_recovery_pass(xlog_t    *log,
 
        /* read first part of physical log */
        while (blk_no < head_blk) {
-           if ((error = xlog_bread(log, blk_no, 1, hbp)))
-               goto bread_err;
+           if ((error = xlog_bread(log, blk_no, hblks, hbp)))
+               goto bread_err2;
            rhead = (xlog_rec_header_t *)XFS_BUF_PTR(hbp);
            ASSERT(INT_GET(rhead->h_magicno, ARCH_CONVERT) == XLOG_HEADER_MAGIC_NUM);
            ASSERT(BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT) <= INT_MAX));
            bblks = (int) BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT));
            ASSERT(bblks > 0);
-           if ((error = xlog_bread(log, blk_no+1, bblks, dbp)))
-               goto bread_err;
+           if ((error = xlog_bread(log, blk_no+hblks, bblks, dbp)))
+               goto bread_err2;
            xlog_unpack_data(rhead, XFS_BUF_PTR(dbp), log);
            if ((error = xlog_recover_process_data(log, rhash,
                                                  rhead, XFS_BUF_PTR(dbp),
                                                  pass)))
-               goto bread_err;
-           blk_no += (bblks+1);
+               goto bread_err2;
+           blk_no += (bblks+hblks);
         }
     }
 
-bread_err:
+bread_err2:
     xlog_put_bp(dbp);
+bread_err1:
     xlog_put_bp(hbp);
 
     return error;
index 0d1e59a92bf7d7b8479354889f8fdb52296eaaaf..0288ef9d80d5b7c3db4bb70ce50dca623f598ffc 100644 (file)
@@ -306,9 +306,10 @@ Log section options.
 These options specify the location, size, and other parameters of the
 log section of the filesystem.
 The valid suboptions are:
-.BI internal[= value ]
-and
-\f3size=\f1\f2value\f1.
+.BI internal[= value ],
+\f3size=\f1\f2value\f1,
+\f3version=\f1\f2[1|2]\f1 and
+\f3sunit=\f1\f2value\f1.
 .IP
 The
 .B internal
@@ -339,6 +340,21 @@ meaning multiplication by the filesystem block size, as described above.
 The overriding minimum value for size is 512 blocks.
 With some combinations of filesystem block size, inode size,
 and directory block size, the minimum log size is larger than 512 blocks.
+.IP
+Using the
+.B version
+option to set a version 2 log enables the
+.B sunit
+option, and allows the logbsize to be increased beyond 32K.
+The
+.B sunit 
+option specifies the alignment to be used for log writes,
+it can be in bytes or filesystem blocks.
+Log writes will be aligned on this boundary,
+and rounded up to this boundary.
+This gives major improvements in performance on some configurations
+such as software raid5 when the sunit is specified as the filesystem
+block size.
 .TP
 .B \-n
 Naming options.
index d823d6ab27b55072ff676ad1a68a9bb58f7f7ce8..c79469c9a22912bda3dffdef3f336b3f4b4921cd 100644 (file)
@@ -107,12 +107,16 @@ char      *lopts[] = {
        "internal",
 #define        L_SIZE          2
        "size",
-#define L_DEV          3
+#define L_VERSION      3
+       "version",
+#define L_LSUNIT       4
+       "sunit",
+#define L_DEV          5
        "logdev",
 #ifdef MKFS_SIMULATION
-#define        L_FILE          4
+#define        L_FILE          6
        "file",
-#define        L_NAME          5
+#define        L_NAME          7
        "name",
 #endif
        NULL
@@ -340,6 +344,54 @@ check_overwrite(char *device)
        return 0;
 }
 
+xfs_dfsbno_t
+fixup_log_stripe(
+       xfs_mount_t     *mp,
+       int             lsflag,
+       xfs_dfsbno_t    logstart,
+       __uint64_t      agsize,
+       int             sunit,
+       xfs_drfsbno_t   *logblocks,
+       int             blocklog)
+{
+       __uint64_t      tmp_logblocks;
+
+       sunit = XFS_B_TO_FSB(mp, sunit);
+       logstart = ((logstart + (sunit - 1))/sunit) * sunit;
+       /* 
+        * Make sure that the log size is a multiple of the
+        * stripe unit
+        */
+       if ((*logblocks % sunit) != 0) {
+               if (!lsflag) {
+                       tmp_logblocks = ((*logblocks + (sunit - 1))
+                                               / sunit) * sunit;
+                       /*
+                        * If the log is too large, round down
+                        * instead of round up
+                        */
+                       if ((tmp_logblocks > XFS_MAX_LOG_BLOCKS) ||
+                           ((tmp_logblocks << blocklog) > XFS_MAX_LOG_BYTES)) {
+                               tmp_logblocks = (*logblocks / sunit) * sunit;
+                       }
+                       *logblocks = tmp_logblocks;
+               } else {
+                       fprintf(stderr,
+       "internal log size %lld is not a multiple of the log stripe unit %d\n", 
+                                       (long long)*logblocks, sunit);
+                       usage();
+               }
+       }
+
+       if (*logblocks > agsize-XFS_FSB_TO_AGBNO(mp,logstart)) {
+               fprintf(stderr,
+       "Due to stripe alignment, the internal log size %lld is too large.\n"
+       "Must fit in allocation group\n",
+                       (long long)*logblocks);
+               usage();
+       }
+       return logstart;
+}
 
 int
 main(int argc, char **argv)
@@ -394,7 +446,11 @@ main(int argc, char **argv)
        int                     loginternal;
        char                    *logsize;
        xfs_dfsbno_t            logstart;
+       int                     logversion;
+       int                     lvflag;
        int                     lsflag;
+       int                     lsunit;
+       char                    *logstripe;
        int                     min_logblocks;
        mnt_check_state_t       *mnt_check_state;
        int                     mnt_partition_count;
@@ -419,7 +475,6 @@ main(int argc, char **argv)
        xfs_sb_t                *sbp;
        int                     sectlog;
        __uint64_t              tmp_agsize;
-       __uint64_t              tmp_logblocks;
        uuid_t                  uuid;
        int                     worst_freelist;
        libxfs_init_t           xi;
@@ -434,8 +489,9 @@ main(int argc, char **argv)
        blocklog = libxfs_highbit32(blocksize);
        agsize = daflag = dblocks = 0;
        ilflag = imflag = ipflag = isflag = 0;
-       liflag = laflag = lsflag = ldflag = 0;
+       liflag = laflag = lsflag = ldflag = lvflag = 0;
        loginternal = 1;
+       logversion = 1;
        logagno = logblocks = rtblocks = 0;
        nlflag = nsflag = nvflag = 0;
        dirblocklog = dirblocksize = dirversion = 0;
@@ -446,9 +502,9 @@ main(int argc, char **argv)
        xi.notvolok = 1;
        xi.setblksize = 1;
        dfile = logfile = rtfile = NULL;
-       dsize = logsize = rtsize = rtextsize = protofile = NULL;
+       dsize = logsize = logstripe = rtsize = rtextsize = protofile = NULL;
        opterr = 0;
-       dsu = dsw = dsunit = dswidth = nodsflag = lalign = 0;
+       dsu = dsw = dsunit = dswidth = nodsflag = lalign = lsunit = 0;
        do_overlap_checks = 1;
        extent_flagging = 0;
        force_overwrite = 0;
@@ -750,6 +806,13 @@ main(int argc, char **argv)
                                                illegal(value, "l internal");
                                        liflag = 1;
                                        break;
+                               case L_LSUNIT:
+                                       if (!value)
+                                               reqval('l', lopts, L_LSUNIT);
+                                       if (logstripe)
+                                               respec('l', lopts, L_LSUNIT);
+                                       logstripe = value;
+                                       break;
 #ifdef HAVE_VOLUME_MANAGER
                                case L_NAME:
                                        if (!value)
@@ -762,6 +825,16 @@ main(int argc, char **argv)
                                        xi.logname = value;
                                        break;
 #endif
+                               case L_VERSION:
+                                       if (!value)
+                                               reqval('n', nopts, L_VERSION);
+                                       if (lvflag)
+                                               respec('n', nopts, L_VERSION);
+                                       logversion = atoi(value);
+                                       if (logversion < 1 || logversion > 2)
+                                               illegal(value, "l version");
+                                       lvflag = 1;
+                                       break;
                                case L_SIZE:
                                        if (!value)
                                                reqval('l', lopts, L_SIZE);
@@ -1004,6 +1077,9 @@ main(int argc, char **argv)
                                (long long)logbytes, blocksize,
                                (long long)(logblocks << blocklog));
        }
+       if (logstripe) {
+               lsunit = cvtnum(blocksize, logstripe);
+       }
 #ifdef HAVE_VOLUME_MANAGER
        if (xi.risfile && (!rtsize || !xi.rtname)) {
                fprintf(stderr,
@@ -1560,6 +1636,28 @@ main(int argc, char **argv)
                }
        }
 
+       /*
+        * check that log sunit is modulo fsblksize or default it to dsunit.
+        */
+
+       if (lsunit) {
+               if (lsunit % blocksize != 0) {
+                       fprintf(stderr,
+"log stripe unit (%d) is not a multiple of the block size (%d)\n",
+                       lsunit, blocksize);
+                       exit(1);
+               }
+       } else {
+               if (dsunit)
+                       lsunit = dsunit;
+       }
+
+       if (lsunit > 256 * 1024) {
+               fprintf(stderr,
+"log stripe unit (%d) is too large for kernel to handle\n", lsunit);
+               exit(1);
+       }
+
        protostring = setup_proto(protofile);
        bsize = 1 << (blocklog - BBSHIFT);
        mp = &mbuf;
@@ -1597,40 +1695,16 @@ main(int argc, char **argv)
                /*
                 * Align the logstart at stripe unit boundary.
                 */
-               if (dsunit && ((logstart % dsunit) != 0)) {
-                       logstart = ((logstart + (dsunit - 1))/dsunit) * dsunit;
-                       /* 
-                        * Make sure that the log size is a multiple of the
-                        * stripe unit
-                        */
-                       if ((logblocks % dsunit) != 0) {
-                           if (!lsflag) {
-                               tmp_logblocks = ((logblocks + (dsunit - 1))
-                                                       / dsunit) * dsunit;
-                               /*
-                                * If the log is too large, round down
-                                * instead of round up
-                                */
-                               if ((tmp_logblocks > XFS_MAX_LOG_BLOCKS) ||
-                                   ((tmp_logblocks << blocklog) > XFS_MAX_LOG_BYTES)) {
-                                       tmp_logblocks = (logblocks / dsunit) * dsunit;
-                               }
-                               logblocks = tmp_logblocks;
-                           } else {
-                               fprintf(stderr,
-       "internal log size %lld is not a multiple of the stripe unit %d\n", 
-                                       (long long)logblocks, dsunit);
-                               usage();
-                           }
-                       }
 
-                       if (logblocks > agsize-XFS_FSB_TO_AGBNO(mp,logstart)) {
-                               fprintf(stderr,
-       "Due to stripe alignment, the internal log size %lld is too large.\n"
-       "Must fit in allocation group\n",
-                                       (long long)logblocks);
-                               usage();
-                       }
+               if (lsunit && ((logstart % lsunit) != 0)) {
+                       logstart = fixup_log_stripe(mp, lsflag, logstart,
+                                               agsize, lsunit, &logblocks,
+                                               blocklog);
+                       lalign = 1;
+               } else if (dsunit && ((logstart % dsunit) != 0)) {
+                       logstart = fixup_log_stripe(mp, lsflag, logstart,
+                                               agsize, dsunit, &logblocks,
+                                               blocklog);
                        lalign = 1;
                }
        } else
@@ -1674,6 +1748,10 @@ main(int argc, char **argv)
        sbp->sb_width = dswidth;
        if (dirversion == 2)
                sbp->sb_dirblklog = dirblocklog - blocklog;
+       if (logversion == 2)
+               sbp->sb_logsunit = (lsunit == 0) ? 1 : lsunit;
+       else
+               sbp->sb_logsunit = 0;
        if (iaflag) {
                sbp->sb_inoalignmt = XFS_INODE_BIG_CLUSTER_SIZE >> blocklog;
                iaflag = sbp->sb_inoalignmt != 0;
@@ -1681,7 +1759,7 @@ main(int argc, char **argv)
                sbp->sb_inoalignmt = 0;
        sbp->sb_versionnum =
                XFS_SB_VERSION_MKFS(iaflag, dsunit != 0, extent_flagging,
-                       dirversion == 2);
+                       dirversion == 2, logversion == 2);
 
        /*
         * Zero out the first 68k in on the device, to obliterate any old 
@@ -1707,13 +1785,15 @@ main(int argc, char **argv)
                   "data     =%-22s bsize=%-6d blocks=%lld, imaxpct=%d\n"
                   "         =%-22s sunit=%-6d swidth=%d blks, unwritten=%d\n"
                   "naming   =version %-14d bsize=%-6d\n"
-                  "log      =%-22s bsize=%-6d blocks=%lld\n"
+                  "log      =%-22s bsize=%-6d blocks=%lld, version=%d\n"
+                  "         =%-22s sunit=%d\n"
                   "realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n",
                        dfile, isize, (long long)agcount, (long long)agsize,
                        "", blocksize, (long long)dblocks, sbp->sb_imax_pct,
                        "", dsunit, dswidth, extent_flagging,
                        dirversion, dirversion == 1 ? blocksize : dirblocksize,
                        logfile, 1 << blocklog, (long long)logblocks,
+                       logversion, "", lsunit,
                        rtfile, rtextblocks << blocklog,
                        (long long)rtblocks, (long long)rtextents);
        /*
@@ -1749,7 +1829,7 @@ main(int argc, char **argv)
                     XFS_FSB_TO_DADDR(mp, logstart),
                    (xfs_extlen_t)XFS_FSB_TO_BB(mp, logblocks),
                     &sbp->sb_uuid,
-                    XLOG_FMT);
+                    logversion, lsunit, XLOG_FMT);
 
        mp = libxfs_mount(mp, sbp, xi.ddev, xi.logdev, xi.rtdev, 1);
        if (mp == NULL) {
@@ -2143,6 +2223,7 @@ usage(void)
                            su=value,sw=value]\n\
 /* inode size */       [-i log=n|perblock=n|size=num,maxpct=n]\n\
 /* log subvol */       [-l agnum=n,internal,size=num,logdev=xxx]\n\
+                           version=n,sunit=value]\n\
 /* naming */           [-n log=n|size=num|version=n]\n\
 /* label */            [-L label (maximum 12 characters)]\n\
 /* prototype file */   [-p fname]\n\
index a1ecff71b089010f1b26f719d457da0f440ba00b..ad61bb73a4c18c0f9ce49ca56a8aa28b055ee637 100644 (file)
@@ -241,7 +241,10 @@ secondary_sb_wack(xfs_mount_t *mp, xfs_buf_t *sbuf, xfs_sb_t *sb,
                 * work against older filesystems when the superblock
                 * gets rev'ed again with new fields appended.
                 */
-               if (XFS_SB_VERSION_HASDIRV2(sb))
+               if (XFS_SB_VERSION_HASLOGV2(sb))
+                       size = (__psint_t)&sb->sb_logsunit
+                               + sizeof(sb->sb_logsunit) - (__psint_t)sb;
+               else if (XFS_SB_VERSION_HASDIRV2(sb))
                        size = (__psint_t)&sb->sb_dirblklog
                                + sizeof(sb->sb_dirblklog) - (__psint_t)sb;
                else
index 1a14d61a2e0323347ca97825e846cf2c52e05691..fdf85a9f9330a5ceb7d3021daae42967d6edb8ac 100644 (file)
@@ -95,7 +95,8 @@ zero_log(xfs_mount_t *mp)
                XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart),
                (xfs_extlen_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks),
                &mp->m_sb.sb_uuid,
-               XLOG_FMT);
+               XFS_SB_VERSION_HASLOGV2(&mp->m_sb) ? 2 : 1,
+               mp->m_sb.sb_logsunit, XLOG_FMT);
 }
 
 /*