Commit 6d192a9b authored by Tim Shimmin's avatar Tim Shimmin Committed by Nathan Scott

[XFS] inode items and EFI/EFDs have different ondisk format for 32bit and

64bit kernels allow recovery to handle both versions and do the necessary
decoding

SGI-PV: 952214
SGI-Modid: xfs-linux-melb:xfs-kern:26011a
Signed-off-by: default avatarTim Shimmin <tes@sgi.com>
Signed-off-by: default avatarNathan Scott <nathans@sgi.com>
parent d210a28c
...@@ -293,6 +293,62 @@ xfs_efi_init(xfs_mount_t *mp, ...@@ -293,6 +293,62 @@ xfs_efi_init(xfs_mount_t *mp,
return (efip); return (efip);
} }
/*
* Copy an EFI format buffer from the given buf, and into the destination
* EFI format structure.
* The given buffer can be in 32 bit or 64 bit form (which has different padding),
* one of which will be the native format for this kernel.
* It will handle the conversion of formats if necessary.
*/
int
xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt)
{
xfs_efi_log_format_t *src_efi_fmt = (xfs_efi_log_format_t *)buf->i_addr;
uint i;
uint len = sizeof(xfs_efi_log_format_t) +
(src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_t);
uint len32 = sizeof(xfs_efi_log_format_32_t) +
(src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_32_t);
uint len64 = sizeof(xfs_efi_log_format_64_t) +
(src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_64_t);
if (buf->i_len == len) {
memcpy((char *)dst_efi_fmt, (char*)src_efi_fmt, len);
return 0;
} else if (buf->i_len == len32) {
xfs_efi_log_format_32_t *src_efi_fmt_32 =
(xfs_efi_log_format_32_t *)buf->i_addr;
dst_efi_fmt->efi_type = src_efi_fmt_32->efi_type;
dst_efi_fmt->efi_size = src_efi_fmt_32->efi_size;
dst_efi_fmt->efi_nextents = src_efi_fmt_32->efi_nextents;
dst_efi_fmt->efi_id = src_efi_fmt_32->efi_id;
for (i = 0; i < dst_efi_fmt->efi_nextents; i++) {
dst_efi_fmt->efi_extents[i].ext_start =
src_efi_fmt_32->efi_extents[i].ext_start;
dst_efi_fmt->efi_extents[i].ext_len =
src_efi_fmt_32->efi_extents[i].ext_len;
}
return 0;
} else if (buf->i_len == len64) {
xfs_efi_log_format_64_t *src_efi_fmt_64 =
(xfs_efi_log_format_64_t *)buf->i_addr;
dst_efi_fmt->efi_type = src_efi_fmt_64->efi_type;
dst_efi_fmt->efi_size = src_efi_fmt_64->efi_size;
dst_efi_fmt->efi_nextents = src_efi_fmt_64->efi_nextents;
dst_efi_fmt->efi_id = src_efi_fmt_64->efi_id;
for (i = 0; i < dst_efi_fmt->efi_nextents; i++) {
dst_efi_fmt->efi_extents[i].ext_start =
src_efi_fmt_64->efi_extents[i].ext_start;
dst_efi_fmt->efi_extents[i].ext_len =
src_efi_fmt_64->efi_extents[i].ext_len;
}
return 0;
}
return EFSCORRUPTED;
}
/* /*
* This is called by the efd item code below to release references to * This is called by the efd item code below to release references to
* the given efi item. Each efd calls this with the number of * the given efi item. Each efd calls this with the number of
......
...@@ -26,6 +26,24 @@ typedef struct xfs_extent { ...@@ -26,6 +26,24 @@ typedef struct xfs_extent {
xfs_extlen_t ext_len; xfs_extlen_t ext_len;
} xfs_extent_t; } xfs_extent_t;
/*
* Since an xfs_extent_t has types (start:64, len: 32)
* there are different alignments on 32 bit and 64 bit kernels.
* So we provide the different variants for use by a
* conversion routine.
*/
typedef struct xfs_extent_32 {
xfs_dfsbno_t ext_start;
xfs_extlen_t ext_len;
} __attribute__((packed)) xfs_extent_32_t;
typedef struct xfs_extent_64 {
xfs_dfsbno_t ext_start;
xfs_extlen_t ext_len;
__uint32_t ext_pad;
} xfs_extent_64_t;
/* /*
* This is the structure used to lay out an efi log item in the * This is the structure used to lay out an efi log item in the
* log. The efi_extents field is a variable size array whose * log. The efi_extents field is a variable size array whose
...@@ -39,6 +57,22 @@ typedef struct xfs_efi_log_format { ...@@ -39,6 +57,22 @@ typedef struct xfs_efi_log_format {
xfs_extent_t efi_extents[1]; /* array of extents to free */ xfs_extent_t efi_extents[1]; /* array of extents to free */
} xfs_efi_log_format_t; } xfs_efi_log_format_t;
typedef struct xfs_efi_log_format_32 {
unsigned short efi_type; /* efi log item type */
unsigned short efi_size; /* size of this item */
uint efi_nextents; /* # extents to free */
__uint64_t efi_id; /* efi identifier */
xfs_extent_32_t efi_extents[1]; /* array of extents to free */
} __attribute__((packed)) xfs_efi_log_format_32_t;
typedef struct xfs_efi_log_format_64 {
unsigned short efi_type; /* efi log item type */
unsigned short efi_size; /* size of this item */
uint efi_nextents; /* # extents to free */
__uint64_t efi_id; /* efi identifier */
xfs_extent_64_t efi_extents[1]; /* array of extents to free */
} xfs_efi_log_format_64_t;
/* /*
* This is the structure used to lay out an efd log item in the * This is the structure used to lay out an efd log item in the
* log. The efd_extents array is a variable size array whose * log. The efd_extents array is a variable size array whose
...@@ -52,6 +86,22 @@ typedef struct xfs_efd_log_format { ...@@ -52,6 +86,22 @@ typedef struct xfs_efd_log_format {
xfs_extent_t efd_extents[1]; /* array of extents freed */ xfs_extent_t efd_extents[1]; /* array of extents freed */
} xfs_efd_log_format_t; } xfs_efd_log_format_t;
typedef struct xfs_efd_log_format_32 {
unsigned short efd_type; /* efd log item type */
unsigned short efd_size; /* size of this item */
uint efd_nextents; /* # of extents freed */
__uint64_t efd_efi_id; /* id of corresponding efi */
xfs_extent_32_t efd_extents[1]; /* array of extents freed */
} __attribute__((packed)) xfs_efd_log_format_32_t;
typedef struct xfs_efd_log_format_64 {
unsigned short efd_type; /* efd log item type */
unsigned short efd_size; /* size of this item */
uint efd_nextents; /* # of extents freed */
__uint64_t efd_efi_id; /* id of corresponding efi */
xfs_extent_64_t efd_extents[1]; /* array of extents freed */
} xfs_efd_log_format_64_t;
#ifdef __KERNEL__ #ifdef __KERNEL__
...@@ -103,7 +153,8 @@ extern struct kmem_zone *xfs_efd_zone; ...@@ -103,7 +153,8 @@ extern struct kmem_zone *xfs_efd_zone;
xfs_efi_log_item_t *xfs_efi_init(struct xfs_mount *, uint); xfs_efi_log_item_t *xfs_efi_init(struct xfs_mount *, uint);
xfs_efd_log_item_t *xfs_efd_init(struct xfs_mount *, xfs_efi_log_item_t *, xfs_efd_log_item_t *xfs_efd_init(struct xfs_mount *, xfs_efi_log_item_t *,
uint); uint);
int xfs_efi_copy_format(xfs_log_iovec_t *buf,
xfs_efi_log_format_t *dst_efi_fmt);
void xfs_efi_item_free(xfs_efi_log_item_t *); void xfs_efi_item_free(xfs_efi_log_item_t *);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -1084,3 +1084,52 @@ xfs_istale_done( ...@@ -1084,3 +1084,52 @@ xfs_istale_done(
{ {
xfs_iflush_abort(iip->ili_inode); xfs_iflush_abort(iip->ili_inode);
} }
/*
* convert an xfs_inode_log_format struct from either 32 or 64 bit versions
* (which can have different field alignments) to the native version
*/
int
xfs_inode_item_format_convert(
xfs_log_iovec_t *buf,
xfs_inode_log_format_t *in_f)
{
if (buf->i_len == sizeof(xfs_inode_log_format_32_t)) {
xfs_inode_log_format_32_t *in_f32;
in_f32 = (xfs_inode_log_format_32_t *)buf->i_addr;
in_f->ilf_type = in_f32->ilf_type;
in_f->ilf_size = in_f32->ilf_size;
in_f->ilf_fields = in_f32->ilf_fields;
in_f->ilf_asize = in_f32->ilf_asize;
in_f->ilf_dsize = in_f32->ilf_dsize;
in_f->ilf_ino = in_f32->ilf_ino;
/* copy biggest field of ilf_u */
memcpy(in_f->ilf_u.ilfu_uuid.__u_bits,
in_f32->ilf_u.ilfu_uuid.__u_bits,
sizeof(uuid_t));
in_f->ilf_blkno = in_f32->ilf_blkno;
in_f->ilf_len = in_f32->ilf_len;
in_f->ilf_boffset = in_f32->ilf_boffset;
return 0;
} else if (buf->i_len == sizeof(xfs_inode_log_format_64_t)){
xfs_inode_log_format_64_t *in_f64;
in_f64 = (xfs_inode_log_format_64_t *)buf->i_addr;
in_f->ilf_type = in_f64->ilf_type;
in_f->ilf_size = in_f64->ilf_size;
in_f->ilf_fields = in_f64->ilf_fields;
in_f->ilf_asize = in_f64->ilf_asize;
in_f->ilf_dsize = in_f64->ilf_dsize;
in_f->ilf_ino = in_f64->ilf_ino;
/* copy biggest field of ilf_u */
memcpy(in_f->ilf_u.ilfu_uuid.__u_bits,
in_f64->ilf_u.ilfu_uuid.__u_bits,
sizeof(uuid_t));
in_f->ilf_blkno = in_f64->ilf_blkno;
in_f->ilf_len = in_f64->ilf_len;
in_f->ilf_boffset = in_f64->ilf_boffset;
return 0;
}
return EFSCORRUPTED;
}
...@@ -23,25 +23,6 @@ ...@@ -23,25 +23,6 @@
* log. The size of the inline data/extents/b-tree root to be logged * log. The size of the inline data/extents/b-tree root to be logged
* (if any) is indicated in the ilf_dsize field. Changes to this structure * (if any) is indicated in the ilf_dsize field. Changes to this structure
* must be added on to the end. * must be added on to the end.
*
* Convention for naming inode log item versions : The current version
* is always named XFS_LI_INODE. When an inode log item gets superseded,
* add the latest version of IRIX that will generate logs with that item
* to the version name.
*
* -Version 1 of this structure (XFS_LI_5_3_INODE) included up to the first
* union (ilf_u) field. This was released with IRIX 5.3-XFS.
* -Version 2 of this structure (XFS_LI_6_1_INODE) is currently the entire
* structure. This was released with IRIX 6.0.1-XFS and IRIX 6.1.
* -Version 3 of this structure (XFS_LI_INODE) is the same as version 2
* so a new structure definition wasn't necessary. However, we had
* to add a new type because the inode cluster size changed from 4K
* to 8K and the version number had to be rev'ved to keep older kernels
* from trying to recover logs with the 8K buffers in them. The logging
* code can handle recovery on different-sized clusters now so hopefully
* this'll be the last time we need to change the inode log item just
* for a change in the inode cluster size. This new version was
* released with IRIX 6.2.
*/ */
typedef struct xfs_inode_log_format { typedef struct xfs_inode_log_format {
unsigned short ilf_type; /* inode log item type */ unsigned short ilf_type; /* inode log item type */
...@@ -59,18 +40,38 @@ typedef struct xfs_inode_log_format { ...@@ -59,18 +40,38 @@ typedef struct xfs_inode_log_format {
int ilf_boffset; /* off of inode in buffer */ int ilf_boffset; /* off of inode in buffer */
} xfs_inode_log_format_t; } xfs_inode_log_format_t;
/* Initial version shipped with IRIX 5.3-XFS */ typedef struct xfs_inode_log_format_32 {
typedef struct xfs_inode_log_format_v1 { unsigned short ilf_type; /* 16: inode log item type */
unsigned short ilf_type; /* inode log item type */ unsigned short ilf_size; /* 16: size of this item */
unsigned short ilf_size; /* size of this item */ uint ilf_fields; /* 32: flags for fields logged */
uint ilf_fields; /* flags for fields logged */ ushort ilf_asize; /* 32: size of attr d/ext/root */
uint ilf_dsize; /* size of data/ext/root */ ushort ilf_dsize; /* 32: size of data/ext/root */
xfs_ino_t ilf_ino; /* inode number */ xfs_ino_t ilf_ino; /* 64: inode number */
union { union {
xfs_dev_t ilfu_rdev; /* rdev value for dev inode*/ xfs_dev_t ilfu_rdev; /* 32: rdev value for dev inode*/
uuid_t ilfu_uuid; /* mount point value */ uuid_t ilfu_uuid; /* 128: mount point value */
} ilf_u;
__int64_t ilf_blkno; /* 64: blkno of inode buffer */
int ilf_len; /* 32: len of inode buffer */
int ilf_boffset; /* 32: off of inode in buffer */
} __attribute__((packed)) xfs_inode_log_format_32_t;
typedef struct xfs_inode_log_format_64 {
unsigned short ilf_type; /* 16: inode log item type */
unsigned short ilf_size; /* 16: size of this item */
uint ilf_fields; /* 32: flags for fields logged */
ushort ilf_asize; /* 32: size of attr d/ext/root */
ushort ilf_dsize; /* 32: size of data/ext/root */
__uint32_t ilf_pad; /* 32: pad for 64 bit boundary */
xfs_ino_t ilf_ino; /* 64: inode number */
union {
xfs_dev_t ilfu_rdev; /* 32: rdev value for dev inode*/
uuid_t ilfu_uuid; /* 128: mount point value */
} ilf_u; } ilf_u;
} xfs_inode_log_format_t_v1; __int64_t ilf_blkno; /* 64: blkno of inode buffer */
int ilf_len; /* 32: len of inode buffer */
int ilf_boffset; /* 32: off of inode in buffer */
} xfs_inode_log_format_64_t;
/* /*
* Flags for xfs_trans_log_inode flags field. * Flags for xfs_trans_log_inode flags field.
...@@ -172,6 +173,8 @@ extern void xfs_inode_item_destroy(struct xfs_inode *); ...@@ -172,6 +173,8 @@ extern void xfs_inode_item_destroy(struct xfs_inode *);
extern void xfs_iflush_done(struct xfs_buf *, xfs_inode_log_item_t *); extern void xfs_iflush_done(struct xfs_buf *, xfs_inode_log_item_t *);
extern void xfs_istale_done(struct xfs_buf *, xfs_inode_log_item_t *); extern void xfs_istale_done(struct xfs_buf *, xfs_inode_log_item_t *);
extern void xfs_iflush_abort(struct xfs_inode *); extern void xfs_iflush_abort(struct xfs_inode *);
extern int xfs_inode_item_format_convert(xfs_log_iovec_t *,
xfs_inode_log_format_t *);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -2292,12 +2292,22 @@ xlog_recover_do_inode_trans( ...@@ -2292,12 +2292,22 @@ xlog_recover_do_inode_trans(
int attr_index; int attr_index;
uint fields; uint fields;
xfs_dinode_core_t *dicp; xfs_dinode_core_t *dicp;
int need_free = 0;
if (pass == XLOG_RECOVER_PASS1) { if (pass == XLOG_RECOVER_PASS1) {
return 0; return 0;
} }
if (item->ri_buf[0].i_len == sizeof(xfs_inode_log_format_t)) {
in_f = (xfs_inode_log_format_t *)item->ri_buf[0].i_addr; in_f = (xfs_inode_log_format_t *)item->ri_buf[0].i_addr;
} else {
in_f = (xfs_inode_log_format_t *)kmem_alloc(
sizeof(xfs_inode_log_format_t), KM_SLEEP);
need_free = 1;
error = xfs_inode_item_format_convert(&item->ri_buf[0], in_f);
if (error)
goto error;
}
ino = in_f->ilf_ino; ino = in_f->ilf_ino;
mp = log->l_mp; mp = log->l_mp;
if (ITEM_TYPE(item) == XFS_LI_INODE) { if (ITEM_TYPE(item) == XFS_LI_INODE) {
...@@ -2323,8 +2333,10 @@ xlog_recover_do_inode_trans( ...@@ -2323,8 +2333,10 @@ xlog_recover_do_inode_trans(
* Inode buffers can be freed, look out for it, * Inode buffers can be freed, look out for it,
* and do not replay the inode. * and do not replay the inode.
*/ */
if (xlog_check_buffer_cancelled(log, imap.im_blkno, imap.im_len, 0)) if (xlog_check_buffer_cancelled(log, imap.im_blkno, imap.im_len, 0)) {
return 0; error = 0;
goto error;
}
bp = xfs_buf_read_flags(mp->m_ddev_targp, imap.im_blkno, imap.im_len, bp = xfs_buf_read_flags(mp->m_ddev_targp, imap.im_blkno, imap.im_len,
XFS_BUF_LOCK); XFS_BUF_LOCK);
...@@ -2333,7 +2345,7 @@ xlog_recover_do_inode_trans( ...@@ -2333,7 +2345,7 @@ xlog_recover_do_inode_trans(
bp, imap.im_blkno); bp, imap.im_blkno);
error = XFS_BUF_GETERROR(bp); error = XFS_BUF_GETERROR(bp);
xfs_buf_relse(bp); xfs_buf_relse(bp);
return error; goto error;
} }
error = 0; error = 0;
ASSERT(in_f->ilf_fields & XFS_ILOG_CORE); ASSERT(in_f->ilf_fields & XFS_ILOG_CORE);
...@@ -2350,7 +2362,8 @@ xlog_recover_do_inode_trans( ...@@ -2350,7 +2362,8 @@ xlog_recover_do_inode_trans(
dip, bp, ino); dip, bp, ino);
XFS_ERROR_REPORT("xlog_recover_do_inode_trans(1)", XFS_ERROR_REPORT("xlog_recover_do_inode_trans(1)",
XFS_ERRLEVEL_LOW, mp); XFS_ERRLEVEL_LOW, mp);
return XFS_ERROR(EFSCORRUPTED); error = EFSCORRUPTED;
goto error;
} }
dicp = (xfs_dinode_core_t*)(item->ri_buf[1].i_addr); dicp = (xfs_dinode_core_t*)(item->ri_buf[1].i_addr);
if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) { if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) {
...@@ -2360,7 +2373,8 @@ xlog_recover_do_inode_trans( ...@@ -2360,7 +2373,8 @@ xlog_recover_do_inode_trans(
item, ino); item, ino);
XFS_ERROR_REPORT("xlog_recover_do_inode_trans(2)", XFS_ERROR_REPORT("xlog_recover_do_inode_trans(2)",
XFS_ERRLEVEL_LOW, mp); XFS_ERRLEVEL_LOW, mp);
return XFS_ERROR(EFSCORRUPTED); error = EFSCORRUPTED;
goto error;
} }
/* Skip replay when the on disk inode is newer than the log one */ /* Skip replay when the on disk inode is newer than the log one */
...@@ -2376,7 +2390,8 @@ xlog_recover_do_inode_trans( ...@@ -2376,7 +2390,8 @@ xlog_recover_do_inode_trans(
/* do nothing */ /* do nothing */
} else { } else {
xfs_buf_relse(bp); xfs_buf_relse(bp);
return 0; error = 0;
goto error;
} }
} }
/* Take the opportunity to reset the flush iteration count */ /* Take the opportunity to reset the flush iteration count */
...@@ -2391,7 +2406,8 @@ xlog_recover_do_inode_trans( ...@@ -2391,7 +2406,8 @@ xlog_recover_do_inode_trans(
xfs_fs_cmn_err(CE_ALERT, mp, xfs_fs_cmn_err(CE_ALERT, mp,
"xfs_inode_recover: Bad regular inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", "xfs_inode_recover: Bad regular inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
item, dip, bp, ino); item, dip, bp, ino);
return XFS_ERROR(EFSCORRUPTED); error = EFSCORRUPTED;
goto error;
} }
} else if (unlikely((dicp->di_mode & S_IFMT) == S_IFDIR)) { } else if (unlikely((dicp->di_mode & S_IFMT) == S_IFDIR)) {
if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) && if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) &&
...@@ -2403,7 +2419,8 @@ xlog_recover_do_inode_trans( ...@@ -2403,7 +2419,8 @@ xlog_recover_do_inode_trans(
xfs_fs_cmn_err(CE_ALERT, mp, xfs_fs_cmn_err(CE_ALERT, mp,
"xfs_inode_recover: Bad dir inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", "xfs_inode_recover: Bad dir inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
item, dip, bp, ino); item, dip, bp, ino);
return XFS_ERROR(EFSCORRUPTED); error = EFSCORRUPTED;
goto error;
} }
} }
if (unlikely(dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks)){ if (unlikely(dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks)){
...@@ -2415,7 +2432,8 @@ xlog_recover_do_inode_trans( ...@@ -2415,7 +2432,8 @@ xlog_recover_do_inode_trans(
item, dip, bp, ino, item, dip, bp, ino,
dicp->di_nextents + dicp->di_anextents, dicp->di_nextents + dicp->di_anextents,
dicp->di_nblocks); dicp->di_nblocks);
return XFS_ERROR(EFSCORRUPTED); error = EFSCORRUPTED;
goto error;
} }
if (unlikely(dicp->di_forkoff > mp->m_sb.sb_inodesize)) { if (unlikely(dicp->di_forkoff > mp->m_sb.sb_inodesize)) {
XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(6)", XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(6)",
...@@ -2424,7 +2442,8 @@ xlog_recover_do_inode_trans( ...@@ -2424,7 +2442,8 @@ xlog_recover_do_inode_trans(
xfs_fs_cmn_err(CE_ALERT, mp, xfs_fs_cmn_err(CE_ALERT, mp,
"xfs_inode_recover: Bad inode log rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, forkoff 0x%x", "xfs_inode_recover: Bad inode log rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, forkoff 0x%x",
item, dip, bp, ino, dicp->di_forkoff); item, dip, bp, ino, dicp->di_forkoff);
return XFS_ERROR(EFSCORRUPTED); error = EFSCORRUPTED;
goto error;
} }
if (unlikely(item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t))) { if (unlikely(item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t))) {
XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(7)", XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(7)",
...@@ -2433,7 +2452,8 @@ xlog_recover_do_inode_trans( ...@@ -2433,7 +2452,8 @@ xlog_recover_do_inode_trans(
xfs_fs_cmn_err(CE_ALERT, mp, xfs_fs_cmn_err(CE_ALERT, mp,
"xfs_inode_recover: Bad inode log record length %d, rec ptr 0x%p", "xfs_inode_recover: Bad inode log record length %d, rec ptr 0x%p",
item->ri_buf[1].i_len, item); item->ri_buf[1].i_len, item);
return XFS_ERROR(EFSCORRUPTED); error = EFSCORRUPTED;
goto error;
} }
/* The core is in in-core format */ /* The core is in in-core format */
...@@ -2521,7 +2541,8 @@ xlog_recover_do_inode_trans( ...@@ -2521,7 +2541,8 @@ xlog_recover_do_inode_trans(
xlog_warn("XFS: xlog_recover_do_inode_trans: Invalid flag"); xlog_warn("XFS: xlog_recover_do_inode_trans: Invalid flag");
ASSERT(0); ASSERT(0);
xfs_buf_relse(bp); xfs_buf_relse(bp);
return XFS_ERROR(EIO); error = EIO;
goto error;
} }
} }
...@@ -2537,7 +2558,10 @@ xlog_recover_do_inode_trans( ...@@ -2537,7 +2558,10 @@ xlog_recover_do_inode_trans(
error = xfs_bwrite(mp, bp); error = xfs_bwrite(mp, bp);
} }
return (error); error:
if (need_free)
kmem_free(in_f, sizeof(*in_f));
return XFS_ERROR(error);
} }
/* /*
...@@ -2674,32 +2698,32 @@ xlog_recover_do_dquot_trans( ...@@ -2674,32 +2698,32 @@ xlog_recover_do_dquot_trans(
* structure into it, and adds the efi to the AIL with the given * structure into it, and adds the efi to the AIL with the given
* LSN. * LSN.
*/ */
STATIC void STATIC int
xlog_recover_do_efi_trans( xlog_recover_do_efi_trans(
xlog_t *log, xlog_t *log,
xlog_recover_item_t *item, xlog_recover_item_t *item,
xfs_lsn_t lsn, xfs_lsn_t lsn,
int pass) int pass)
{ {
int error;
xfs_mount_t *mp; xfs_mount_t *mp;
xfs_efi_log_item_t *efip; xfs_efi_log_item_t *efip;
xfs_efi_log_format_t *efi_formatp; xfs_efi_log_format_t *efi_formatp;
SPLDECL(s); SPLDECL(s);
if (pass == XLOG_RECOVER_PASS1) { if (pass == XLOG_RECOVER_PASS1) {
return; return 0;
} }
efi_formatp = (xfs_efi_log_format_t *)item->ri_buf[0].i_addr; efi_formatp = (xfs_efi_log_format_t *)item->ri_buf[0].i_addr;
ASSERT(item->ri_buf[0].i_len ==
(sizeof(xfs_efi_log_format_t) +
((efi_formatp->efi_nextents - 1) * sizeof(xfs_extent_t))));
mp = log->l_mp; mp = log->l_mp;
efip = xfs_efi_init(mp, efi_formatp->efi_nextents); efip = xfs_efi_init(mp, efi_formatp->efi_nextents);
memcpy((char *)&(efip->efi_format), (char *)efi_formatp, if ((error = xfs_efi_copy_format(&(item->ri_buf[0]),
sizeof(xfs_efi_log_format_t) + &(efip->efi_format)))) {
((efi_formatp->efi_nextents - 1) * sizeof(xfs_extent_t))); xfs_efi_item_free(efip);
return error;
}
efip->efi_next_extent = efi_formatp->efi_nextents; efip->efi_next_extent = efi_formatp->efi_nextents;
efip->efi_flags |= XFS_EFI_COMMITTED; efip->efi_flags |= XFS_EFI_COMMITTED;
...@@ -2708,6 +2732,7 @@ xlog_recover_do_efi_trans( ...@@ -2708,6 +2732,7 @@ xlog_recover_do_efi_trans(
* xfs_trans_update_ail() drops the AIL lock. * xfs_trans_update_ail() drops the AIL lock.
*/ */
xfs_trans_update_ail(mp, (xfs_log_item_t *)efip, lsn, s); xfs_trans_update_ail(mp, (xfs_log_item_t *)efip, lsn, s);
return 0;
} }
...@@ -2738,9 +2763,10 @@ xlog_recover_do_efd_trans( ...@@ -2738,9 +2763,10 @@ xlog_recover_do_efd_trans(
} }
efd_formatp = (xfs_efd_log_format_t *)item->ri_buf[0].i_addr; efd_formatp = (xfs_efd_log_format_t *)item->ri_buf[0].i_addr;
ASSERT(item->ri_buf[0].i_len == ASSERT((item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_32_t) +
(sizeof(xfs_efd_log_format_t) + ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_32_t)))) ||
((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_t)))); (item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_64_t) +
((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_64_t)))));
efi_id = efd_formatp->efd_efi_id; efi_id = efd_formatp->efd_efi_id;
/* /*
...@@ -2810,15 +2836,14 @@ xlog_recover_do_trans( ...@@ -2810,15 +2836,14 @@ xlog_recover_do_trans(
if ((error = xlog_recover_do_buffer_trans(log, item, if ((error = xlog_recover_do_buffer_trans(log, item,
pass))) pass)))
break; break;
} else if ((ITEM_TYPE(item) == XFS_LI_INODE) || } else if ((ITEM_TYPE(item) == XFS_LI_INODE)) {
(ITEM_TYPE(item) == XFS_LI_6_1_INODE) ||
(ITEM_TYPE(item) == XFS_LI_5_3_INODE)) {
if ((error = xlog_recover_do_inode_trans(log, item, if ((error = xlog_recover_do_inode_trans(log, item,
pass))) pass)))
break; break;
} else if (ITEM_TYPE(item) == XFS_LI_EFI) { } else if (ITEM_TYPE(item) == XFS_LI_EFI) {
xlog_recover_do_efi_trans(log, item, trans->r_lsn, if ((error = xlog_recover_do_efi_trans(log, item, trans->r_lsn,
pass); pass)))
break;
} else if (ITEM_TYPE(item) == XFS_LI_EFD) { } else if (ITEM_TYPE(item) == XFS_LI_EFD) {
xlog_recover_do_efd_trans(log, item, pass); xlog_recover_do_efd_trans(log, item, pass);
} else if (ITEM_TYPE(item) == XFS_LI_DQUOT) { } else if (ITEM_TYPE(item) == XFS_LI_DQUOT) {
...@@ -3798,7 +3823,7 @@ xlog_do_log_recovery( ...@@ -3798,7 +3823,7 @@ xlog_do_log_recovery(
error = xlog_do_recovery_pass(log, head_blk, tail_blk, error = xlog_do_recovery_pass(log, head_blk, tail_blk,
XLOG_RECOVER_PASS2); XLOG_RECOVER_PASS2);
#ifdef DEBUG #ifdef DEBUG
{ if (!error) {
int i; int i;
for (i = 0; i < XLOG_BC_TABLE_SIZE; i++) for (i = 0; i < XLOG_BC_TABLE_SIZE; i++)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment