aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/xfs_extfree_item.c56
-rw-r--r--fs/xfs/xfs_extfree_item.h53
-rw-r--r--fs/xfs/xfs_inode_item.c49
-rw-r--r--fs/xfs/xfs_inode_item.h61
-rw-r--r--fs/xfs/xfs_log_recover.c87
5 files changed, 245 insertions, 61 deletions
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index f19282ec8549..8b028f128547 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -294,6 +294,62 @@ xfs_efi_init(xfs_mount_t *mp,
294} 294}
295 295
296/* 296/*
297 * Copy an EFI format buffer from the given buf, and into the destination
298 * EFI format structure.
299 * The given buffer can be in 32 bit or 64 bit form (which has different padding),
300 * one of which will be the native format for this kernel.
301 * It will handle the conversion of formats if necessary.
302 */
303int
304xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt)
305{
306 xfs_efi_log_format_t *src_efi_fmt = (xfs_efi_log_format_t *)buf->i_addr;
307 uint i;
308 uint len = sizeof(xfs_efi_log_format_t) +
309 (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_t);
310 uint len32 = sizeof(xfs_efi_log_format_32_t) +
311 (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_32_t);
312 uint len64 = sizeof(xfs_efi_log_format_64_t) +
313 (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_64_t);
314
315 if (buf->i_len == len) {
316 memcpy((char *)dst_efi_fmt, (char*)src_efi_fmt, len);
317 return 0;
318 } else if (buf->i_len == len32) {
319 xfs_efi_log_format_32_t *src_efi_fmt_32 =
320 (xfs_efi_log_format_32_t *)buf->i_addr;
321
322 dst_efi_fmt->efi_type = src_efi_fmt_32->efi_type;
323 dst_efi_fmt->efi_size = src_efi_fmt_32->efi_size;
324 dst_efi_fmt->efi_nextents = src_efi_fmt_32->efi_nextents;
325 dst_efi_fmt->efi_id = src_efi_fmt_32->efi_id;
326 for (i = 0; i < dst_efi_fmt->efi_nextents; i++) {
327 dst_efi_fmt->efi_extents[i].ext_start =
328 src_efi_fmt_32->efi_extents[i].ext_start;
329 dst_efi_fmt->efi_extents[i].ext_len =
330 src_efi_fmt_32->efi_extents[i].ext_len;
331 }
332 return 0;
333 } else if (buf->i_len == len64) {
334 xfs_efi_log_format_64_t *src_efi_fmt_64 =
335 (xfs_efi_log_format_64_t *)buf->i_addr;
336
337 dst_efi_fmt->efi_type = src_efi_fmt_64->efi_type;
338 dst_efi_fmt->efi_size = src_efi_fmt_64->efi_size;
339 dst_efi_fmt->efi_nextents = src_efi_fmt_64->efi_nextents;
340 dst_efi_fmt->efi_id = src_efi_fmt_64->efi_id;
341 for (i = 0; i < dst_efi_fmt->efi_nextents; i++) {
342 dst_efi_fmt->efi_extents[i].ext_start =
343 src_efi_fmt_64->efi_extents[i].ext_start;
344 dst_efi_fmt->efi_extents[i].ext_len =
345 src_efi_fmt_64->efi_extents[i].ext_len;
346 }
347 return 0;
348 }
349 return EFSCORRUPTED;
350}
351
352/*
297 * This is called by the efd item code below to release references to 353 * This is called by the efd item code below to release references to
298 * the given efi item. Each efd calls this with the number of 354 * the given efi item. Each efd calls this with the number of
299 * extents that it has logged, and when the sum of these reaches 355 * extents that it has logged, and when the sum of these reaches
diff --git a/fs/xfs/xfs_extfree_item.h b/fs/xfs/xfs_extfree_item.h
index 5bf681708fec..0ea45edaab03 100644
--- a/fs/xfs/xfs_extfree_item.h
+++ b/fs/xfs/xfs_extfree_item.h
@@ -27,6 +27,24 @@ typedef struct xfs_extent {
27} xfs_extent_t; 27} xfs_extent_t;
28 28
29/* 29/*
30 * Since an xfs_extent_t has types (start:64, len: 32)
31 * there are different alignments on 32 bit and 64 bit kernels.
32 * So we provide the different variants for use by a
33 * conversion routine.
34 */
35
36typedef struct xfs_extent_32 {
37 xfs_dfsbno_t ext_start;
38 xfs_extlen_t ext_len;
39} __attribute__((packed)) xfs_extent_32_t;
40
41typedef struct xfs_extent_64 {
42 xfs_dfsbno_t ext_start;
43 xfs_extlen_t ext_len;
44 __uint32_t ext_pad;
45} xfs_extent_64_t;
46
47/*
30 * This is the structure used to lay out an efi log item in the 48 * This is the structure used to lay out an efi log item in the
31 * log. The efi_extents field is a variable size array whose 49 * log. The efi_extents field is a variable size array whose
32 * size is given by efi_nextents. 50 * size is given by efi_nextents.
@@ -39,6 +57,22 @@ typedef struct xfs_efi_log_format {
39 xfs_extent_t efi_extents[1]; /* array of extents to free */ 57 xfs_extent_t efi_extents[1]; /* array of extents to free */
40} xfs_efi_log_format_t; 58} xfs_efi_log_format_t;
41 59
60typedef struct xfs_efi_log_format_32 {
61 unsigned short efi_type; /* efi log item type */
62 unsigned short efi_size; /* size of this item */
63 uint efi_nextents; /* # extents to free */
64 __uint64_t efi_id; /* efi identifier */
65 xfs_extent_32_t efi_extents[1]; /* array of extents to free */
66} __attribute__((packed)) xfs_efi_log_format_32_t;
67
68typedef struct xfs_efi_log_format_64 {
69 unsigned short efi_type; /* efi log item type */
70 unsigned short efi_size; /* size of this item */
71 uint efi_nextents; /* # extents to free */
72 __uint64_t efi_id; /* efi identifier */
73 xfs_extent_64_t efi_extents[1]; /* array of extents to free */
74} xfs_efi_log_format_64_t;
75
42/* 76/*
43 * This is the structure used to lay out an efd log item in the 77 * This is the structure used to lay out an efd log item in the
44 * log. The efd_extents array is a variable size array whose 78 * log. The efd_extents array is a variable size array whose
@@ -52,6 +86,22 @@ typedef struct xfs_efd_log_format {
52 xfs_extent_t efd_extents[1]; /* array of extents freed */ 86 xfs_extent_t efd_extents[1]; /* array of extents freed */
53} xfs_efd_log_format_t; 87} xfs_efd_log_format_t;
54 88
89typedef struct xfs_efd_log_format_32 {
90 unsigned short efd_type; /* efd log item type */
91 unsigned short efd_size; /* size of this item */
92 uint efd_nextents; /* # of extents freed */
93 __uint64_t efd_efi_id; /* id of corresponding efi */
94 xfs_extent_32_t efd_extents[1]; /* array of extents freed */
95} __attribute__((packed)) xfs_efd_log_format_32_t;
96
97typedef struct xfs_efd_log_format_64 {
98 unsigned short efd_type; /* efd log item type */
99 unsigned short efd_size; /* size of this item */
100 uint efd_nextents; /* # of extents freed */
101 __uint64_t efd_efi_id; /* id of corresponding efi */
102 xfs_extent_64_t efd_extents[1]; /* array of extents freed */
103} xfs_efd_log_format_64_t;
104
55 105
56#ifdef __KERNEL__ 106#ifdef __KERNEL__
57 107
@@ -103,7 +153,8 @@ extern struct kmem_zone *xfs_efd_zone;
103xfs_efi_log_item_t *xfs_efi_init(struct xfs_mount *, uint); 153xfs_efi_log_item_t *xfs_efi_init(struct xfs_mount *, uint);
104xfs_efd_log_item_t *xfs_efd_init(struct xfs_mount *, xfs_efi_log_item_t *, 154xfs_efd_log_item_t *xfs_efd_init(struct xfs_mount *, xfs_efi_log_item_t *,
105 uint); 155 uint);
106 156int xfs_efi_copy_format(xfs_log_iovec_t *buf,
157 xfs_efi_log_format_t *dst_efi_fmt);
107void xfs_efi_item_free(xfs_efi_log_item_t *); 158void xfs_efi_item_free(xfs_efi_log_item_t *);
108 159
109#endif /* __KERNEL__ */ 160#endif /* __KERNEL__ */
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 7497a481b2f5..cd65a565b4fe 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -1084,3 +1084,52 @@ xfs_istale_done(
1084{ 1084{
1085 xfs_iflush_abort(iip->ili_inode); 1085 xfs_iflush_abort(iip->ili_inode);
1086} 1086}
1087
1088/*
1089 * convert an xfs_inode_log_format struct from either 32 or 64 bit versions
1090 * (which can have different field alignments) to the native version
1091 */
1092int
1093xfs_inode_item_format_convert(
1094 xfs_log_iovec_t *buf,
1095 xfs_inode_log_format_t *in_f)
1096{
1097 if (buf->i_len == sizeof(xfs_inode_log_format_32_t)) {
1098 xfs_inode_log_format_32_t *in_f32;
1099
1100 in_f32 = (xfs_inode_log_format_32_t *)buf->i_addr;
1101 in_f->ilf_type = in_f32->ilf_type;
1102 in_f->ilf_size = in_f32->ilf_size;
1103 in_f->ilf_fields = in_f32->ilf_fields;
1104 in_f->ilf_asize = in_f32->ilf_asize;
1105 in_f->ilf_dsize = in_f32->ilf_dsize;
1106 in_f->ilf_ino = in_f32->ilf_ino;
1107 /* copy biggest field of ilf_u */
1108 memcpy(in_f->ilf_u.ilfu_uuid.__u_bits,
1109 in_f32->ilf_u.ilfu_uuid.__u_bits,
1110 sizeof(uuid_t));
1111 in_f->ilf_blkno = in_f32->ilf_blkno;
1112 in_f->ilf_len = in_f32->ilf_len;
1113 in_f->ilf_boffset = in_f32->ilf_boffset;
1114 return 0;
1115 } else if (buf->i_len == sizeof(xfs_inode_log_format_64_t)){
1116 xfs_inode_log_format_64_t *in_f64;
1117
1118 in_f64 = (xfs_inode_log_format_64_t *)buf->i_addr;
1119 in_f->ilf_type = in_f64->ilf_type;
1120 in_f->ilf_size = in_f64->ilf_size;
1121 in_f->ilf_fields = in_f64->ilf_fields;
1122 in_f->ilf_asize = in_f64->ilf_asize;
1123 in_f->ilf_dsize = in_f64->ilf_dsize;
1124 in_f->ilf_ino = in_f64->ilf_ino;
1125 /* copy biggest field of ilf_u */
1126 memcpy(in_f->ilf_u.ilfu_uuid.__u_bits,
1127 in_f64->ilf_u.ilfu_uuid.__u_bits,
1128 sizeof(uuid_t));
1129 in_f->ilf_blkno = in_f64->ilf_blkno;
1130 in_f->ilf_len = in_f64->ilf_len;
1131 in_f->ilf_boffset = in_f64->ilf_boffset;
1132 return 0;
1133 }
1134 return EFSCORRUPTED;
1135}
diff --git a/fs/xfs/xfs_inode_item.h b/fs/xfs/xfs_inode_item.h
index c5dbf93b6661..5db6cd1b4cf3 100644
--- a/fs/xfs/xfs_inode_item.h
+++ b/fs/xfs/xfs_inode_item.h
@@ -23,25 +23,6 @@
23 * log. The size of the inline data/extents/b-tree root to be logged 23 * log. The size of the inline data/extents/b-tree root to be logged
24 * (if any) is indicated in the ilf_dsize field. Changes to this structure 24 * (if any) is indicated in the ilf_dsize field. Changes to this structure
25 * must be added on to the end. 25 * must be added on to the end.
26 *
27 * Convention for naming inode log item versions : The current version
28 * is always named XFS_LI_INODE. When an inode log item gets superseded,
29 * add the latest version of IRIX that will generate logs with that item
30 * to the version name.
31 *
32 * -Version 1 of this structure (XFS_LI_5_3_INODE) included up to the first
33 * union (ilf_u) field. This was released with IRIX 5.3-XFS.
34 * -Version 2 of this structure (XFS_LI_6_1_INODE) is currently the entire
35 * structure. This was released with IRIX 6.0.1-XFS and IRIX 6.1.
36 * -Version 3 of this structure (XFS_LI_INODE) is the same as version 2
37 * so a new structure definition wasn't necessary. However, we had
38 * to add a new type because the inode cluster size changed from 4K
39 * to 8K and the version number had to be rev'ved to keep older kernels
40 * from trying to recover logs with the 8K buffers in them. The logging
41 * code can handle recovery on different-sized clusters now so hopefully
42 * this'll be the last time we need to change the inode log item just
43 * for a change in the inode cluster size. This new version was
44 * released with IRIX 6.2.
45 */ 26 */
46typedef struct xfs_inode_log_format { 27typedef struct xfs_inode_log_format {
47 unsigned short ilf_type; /* inode log item type */ 28 unsigned short ilf_type; /* inode log item type */
@@ -59,18 +40,38 @@ typedef struct xfs_inode_log_format {
59 int ilf_boffset; /* off of inode in buffer */ 40 int ilf_boffset; /* off of inode in buffer */
60} xfs_inode_log_format_t; 41} xfs_inode_log_format_t;
61 42
62/* Initial version shipped with IRIX 5.3-XFS */ 43typedef struct xfs_inode_log_format_32 {
63typedef struct xfs_inode_log_format_v1 { 44 unsigned short ilf_type; /* 16: inode log item type */
64 unsigned short ilf_type; /* inode log item type */ 45 unsigned short ilf_size; /* 16: size of this item */
65 unsigned short ilf_size; /* size of this item */ 46 uint ilf_fields; /* 32: flags for fields logged */
66 uint ilf_fields; /* flags for fields logged */ 47 ushort ilf_asize; /* 32: size of attr d/ext/root */
67 uint ilf_dsize; /* size of data/ext/root */ 48 ushort ilf_dsize; /* 32: size of data/ext/root */
68 xfs_ino_t ilf_ino; /* inode number */ 49 xfs_ino_t ilf_ino; /* 64: inode number */
69 union { 50 union {
70 xfs_dev_t ilfu_rdev; /* rdev value for dev inode*/ 51 xfs_dev_t ilfu_rdev; /* 32: rdev value for dev inode*/
71 uuid_t ilfu_uuid; /* mount point value */ 52 uuid_t ilfu_uuid; /* 128: mount point value */
53 } ilf_u;
54 __int64_t ilf_blkno; /* 64: blkno of inode buffer */
55 int ilf_len; /* 32: len of inode buffer */
56 int ilf_boffset; /* 32: off of inode in buffer */
57} __attribute__((packed)) xfs_inode_log_format_32_t;
58
59typedef struct xfs_inode_log_format_64 {
60 unsigned short ilf_type; /* 16: inode log item type */
61 unsigned short ilf_size; /* 16: size of this item */
62 uint ilf_fields; /* 32: flags for fields logged */
63 ushort ilf_asize; /* 32: size of attr d/ext/root */
64 ushort ilf_dsize; /* 32: size of data/ext/root */
65 __uint32_t ilf_pad; /* 32: pad for 64 bit boundary */
66 xfs_ino_t ilf_ino; /* 64: inode number */
67 union {
68 xfs_dev_t ilfu_rdev; /* 32: rdev value for dev inode*/
69 uuid_t ilfu_uuid; /* 128: mount point value */
72 } ilf_u; 70 } ilf_u;
73} xfs_inode_log_format_t_v1; 71 __int64_t ilf_blkno; /* 64: blkno of inode buffer */
72 int ilf_len; /* 32: len of inode buffer */
73 int ilf_boffset; /* 32: off of inode in buffer */
74} xfs_inode_log_format_64_t;
74 75
75/* 76/*
76 * Flags for xfs_trans_log_inode flags field. 77 * Flags for xfs_trans_log_inode flags field.
@@ -172,6 +173,8 @@ extern void xfs_inode_item_destroy(struct xfs_inode *);
172extern void xfs_iflush_done(struct xfs_buf *, xfs_inode_log_item_t *); 173extern void xfs_iflush_done(struct xfs_buf *, xfs_inode_log_item_t *);
173extern void xfs_istale_done(struct xfs_buf *, xfs_inode_log_item_t *); 174extern void xfs_istale_done(struct xfs_buf *, xfs_inode_log_item_t *);
174extern void xfs_iflush_abort(struct xfs_inode *); 175extern void xfs_iflush_abort(struct xfs_inode *);
176extern int xfs_inode_item_format_convert(xfs_log_iovec_t *,
177 xfs_inode_log_format_t *);
175 178
176#endif /* __KERNEL__ */ 179#endif /* __KERNEL__ */
177 180
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 1f0016b0b4ec..efffa75fd5cf 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -2292,12 +2292,22 @@ xlog_recover_do_inode_trans(
2292 int attr_index; 2292 int attr_index;
2293 uint fields; 2293 uint fields;
2294 xfs_dinode_core_t *dicp; 2294 xfs_dinode_core_t *dicp;
2295 int need_free = 0;
2295 2296
2296 if (pass == XLOG_RECOVER_PASS1) { 2297 if (pass == XLOG_RECOVER_PASS1) {
2297 return 0; 2298 return 0;
2298 } 2299 }
2299 2300
2300 in_f = (xfs_inode_log_format_t *)item->ri_buf[0].i_addr; 2301 if (item->ri_buf[0].i_len == sizeof(xfs_inode_log_format_t)) {
2302 in_f = (xfs_inode_log_format_t *)item->ri_buf[0].i_addr;
2303 } else {
2304 in_f = (xfs_inode_log_format_t *)kmem_alloc(
2305 sizeof(xfs_inode_log_format_t), KM_SLEEP);
2306 need_free = 1;
2307 error = xfs_inode_item_format_convert(&item->ri_buf[0], in_f);
2308 if (error)
2309 goto error;
2310 }
2301 ino = in_f->ilf_ino; 2311 ino = in_f->ilf_ino;
2302 mp = log->l_mp; 2312 mp = log->l_mp;
2303 if (ITEM_TYPE(item) == XFS_LI_INODE) { 2313 if (ITEM_TYPE(item) == XFS_LI_INODE) {
@@ -2323,8 +2333,10 @@ xlog_recover_do_inode_trans(
2323 * Inode buffers can be freed, look out for it, 2333 * Inode buffers can be freed, look out for it,
2324 * and do not replay the inode. 2334 * and do not replay the inode.
2325 */ 2335 */
2326 if (xlog_check_buffer_cancelled(log, imap.im_blkno, imap.im_len, 0)) 2336 if (xlog_check_buffer_cancelled(log, imap.im_blkno, imap.im_len, 0)) {
2327 return 0; 2337 error = 0;
2338 goto error;
2339 }
2328 2340
2329 bp = xfs_buf_read_flags(mp->m_ddev_targp, imap.im_blkno, imap.im_len, 2341 bp = xfs_buf_read_flags(mp->m_ddev_targp, imap.im_blkno, imap.im_len,
2330 XFS_BUF_LOCK); 2342 XFS_BUF_LOCK);
@@ -2333,7 +2345,7 @@ xlog_recover_do_inode_trans(
2333 bp, imap.im_blkno); 2345 bp, imap.im_blkno);
2334 error = XFS_BUF_GETERROR(bp); 2346 error = XFS_BUF_GETERROR(bp);
2335 xfs_buf_relse(bp); 2347 xfs_buf_relse(bp);
2336 return error; 2348 goto error;
2337 } 2349 }
2338 error = 0; 2350 error = 0;
2339 ASSERT(in_f->ilf_fields & XFS_ILOG_CORE); 2351 ASSERT(in_f->ilf_fields & XFS_ILOG_CORE);
@@ -2350,7 +2362,8 @@ xlog_recover_do_inode_trans(
2350 dip, bp, ino); 2362 dip, bp, ino);
2351 XFS_ERROR_REPORT("xlog_recover_do_inode_trans(1)", 2363 XFS_ERROR_REPORT("xlog_recover_do_inode_trans(1)",
2352 XFS_ERRLEVEL_LOW, mp); 2364 XFS_ERRLEVEL_LOW, mp);
2353 return XFS_ERROR(EFSCORRUPTED); 2365 error = EFSCORRUPTED;
2366 goto error;
2354 } 2367 }
2355 dicp = (xfs_dinode_core_t*)(item->ri_buf[1].i_addr); 2368 dicp = (xfs_dinode_core_t*)(item->ri_buf[1].i_addr);
2356 if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) { 2369 if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) {
@@ -2360,7 +2373,8 @@ xlog_recover_do_inode_trans(
2360 item, ino); 2373 item, ino);
2361 XFS_ERROR_REPORT("xlog_recover_do_inode_trans(2)", 2374 XFS_ERROR_REPORT("xlog_recover_do_inode_trans(2)",
2362 XFS_ERRLEVEL_LOW, mp); 2375 XFS_ERRLEVEL_LOW, mp);
2363 return XFS_ERROR(EFSCORRUPTED); 2376 error = EFSCORRUPTED;
2377 goto error;
2364 } 2378 }
2365 2379
2366 /* Skip replay when the on disk inode is newer than the log one */ 2380 /* Skip replay when the on disk inode is newer than the log one */
@@ -2376,7 +2390,8 @@ xlog_recover_do_inode_trans(
2376 /* do nothing */ 2390 /* do nothing */
2377 } else { 2391 } else {
2378 xfs_buf_relse(bp); 2392 xfs_buf_relse(bp);
2379 return 0; 2393 error = 0;
2394 goto error;
2380 } 2395 }
2381 } 2396 }
2382 /* Take the opportunity to reset the flush iteration count */ 2397 /* Take the opportunity to reset the flush iteration count */
@@ -2391,7 +2406,8 @@ xlog_recover_do_inode_trans(
2391 xfs_fs_cmn_err(CE_ALERT, mp, 2406 xfs_fs_cmn_err(CE_ALERT, mp,
2392 "xfs_inode_recover: Bad regular inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", 2407 "xfs_inode_recover: Bad regular inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
2393 item, dip, bp, ino); 2408 item, dip, bp, ino);
2394 return XFS_ERROR(EFSCORRUPTED); 2409 error = EFSCORRUPTED;
2410 goto error;
2395 } 2411 }
2396 } else if (unlikely((dicp->di_mode & S_IFMT) == S_IFDIR)) { 2412 } else if (unlikely((dicp->di_mode & S_IFMT) == S_IFDIR)) {
2397 if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) && 2413 if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) &&
@@ -2403,7 +2419,8 @@ xlog_recover_do_inode_trans(
2403 xfs_fs_cmn_err(CE_ALERT, mp, 2419 xfs_fs_cmn_err(CE_ALERT, mp,
2404 "xfs_inode_recover: Bad dir inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", 2420 "xfs_inode_recover: Bad dir inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
2405 item, dip, bp, ino); 2421 item, dip, bp, ino);
2406 return XFS_ERROR(EFSCORRUPTED); 2422 error = EFSCORRUPTED;
2423 goto error;
2407 } 2424 }
2408 } 2425 }
2409 if (unlikely(dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks)){ 2426 if (unlikely(dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks)){
@@ -2415,7 +2432,8 @@ xlog_recover_do_inode_trans(
2415 item, dip, bp, ino, 2432 item, dip, bp, ino,
2416 dicp->di_nextents + dicp->di_anextents, 2433 dicp->di_nextents + dicp->di_anextents,
2417 dicp->di_nblocks); 2434 dicp->di_nblocks);
2418 return XFS_ERROR(EFSCORRUPTED); 2435 error = EFSCORRUPTED;
2436 goto error;
2419 } 2437 }
2420 if (unlikely(dicp->di_forkoff > mp->m_sb.sb_inodesize)) { 2438 if (unlikely(dicp->di_forkoff > mp->m_sb.sb_inodesize)) {
2421 XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(6)", 2439 XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(6)",
@@ -2424,7 +2442,8 @@ xlog_recover_do_inode_trans(
2424 xfs_fs_cmn_err(CE_ALERT, mp, 2442 xfs_fs_cmn_err(CE_ALERT, mp,
2425 "xfs_inode_recover: Bad inode log rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, forkoff 0x%x", 2443 "xfs_inode_recover: Bad inode log rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, forkoff 0x%x",
2426 item, dip, bp, ino, dicp->di_forkoff); 2444 item, dip, bp, ino, dicp->di_forkoff);
2427 return XFS_ERROR(EFSCORRUPTED); 2445 error = EFSCORRUPTED;
2446 goto error;
2428 } 2447 }
2429 if (unlikely(item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t))) { 2448 if (unlikely(item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t))) {
2430 XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(7)", 2449 XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(7)",
@@ -2433,7 +2452,8 @@ xlog_recover_do_inode_trans(
2433 xfs_fs_cmn_err(CE_ALERT, mp, 2452 xfs_fs_cmn_err(CE_ALERT, mp,
2434 "xfs_inode_recover: Bad inode log record length %d, rec ptr 0x%p", 2453 "xfs_inode_recover: Bad inode log record length %d, rec ptr 0x%p",
2435 item->ri_buf[1].i_len, item); 2454 item->ri_buf[1].i_len, item);
2436 return XFS_ERROR(EFSCORRUPTED); 2455 error = EFSCORRUPTED;
2456 goto error;
2437 } 2457 }
2438 2458
2439 /* The core is in in-core format */ 2459 /* The core is in in-core format */
@@ -2521,7 +2541,8 @@ xlog_recover_do_inode_trans(
2521 xlog_warn("XFS: xlog_recover_do_inode_trans: Invalid flag"); 2541 xlog_warn("XFS: xlog_recover_do_inode_trans: Invalid flag");
2522 ASSERT(0); 2542 ASSERT(0);
2523 xfs_buf_relse(bp); 2543 xfs_buf_relse(bp);
2524 return XFS_ERROR(EIO); 2544 error = EIO;
2545 goto error;
2525 } 2546 }
2526 } 2547 }
2527 2548
@@ -2537,7 +2558,10 @@ write_inode_buffer:
2537 error = xfs_bwrite(mp, bp); 2558 error = xfs_bwrite(mp, bp);
2538 } 2559 }
2539 2560
2540 return (error); 2561error:
2562 if (need_free)
2563 kmem_free(in_f, sizeof(*in_f));
2564 return XFS_ERROR(error);
2541} 2565}
2542 2566
2543/* 2567/*
@@ -2674,32 +2698,32 @@ xlog_recover_do_dquot_trans(
2674 * structure into it, and adds the efi to the AIL with the given 2698 * structure into it, and adds the efi to the AIL with the given
2675 * LSN. 2699 * LSN.
2676 */ 2700 */
2677STATIC void 2701STATIC int
2678xlog_recover_do_efi_trans( 2702xlog_recover_do_efi_trans(
2679 xlog_t *log, 2703 xlog_t *log,
2680 xlog_recover_item_t *item, 2704 xlog_recover_item_t *item,
2681 xfs_lsn_t lsn, 2705 xfs_lsn_t lsn,
2682 int pass) 2706 int pass)
2683{ 2707{
2708 int error;
2684 xfs_mount_t *mp; 2709 xfs_mount_t *mp;
2685 xfs_efi_log_item_t *efip; 2710 xfs_efi_log_item_t *efip;
2686 xfs_efi_log_format_t *efi_formatp; 2711 xfs_efi_log_format_t *efi_formatp;
2687 SPLDECL(s); 2712 SPLDECL(s);
2688 2713
2689 if (pass == XLOG_RECOVER_PASS1) { 2714 if (pass == XLOG_RECOVER_PASS1) {
2690 return; 2715 return 0;
2691 } 2716 }
2692 2717
2693 efi_formatp = (xfs_efi_log_format_t *)item->ri_buf[0].i_addr; 2718 efi_formatp = (xfs_efi_log_format_t *)item->ri_buf[0].i_addr;
2694 ASSERT(item->ri_buf[0].i_len ==
2695 (sizeof(xfs_efi_log_format_t) +
2696 ((efi_formatp->efi_nextents - 1) * sizeof(xfs_extent_t))));
2697 2719
2698 mp = log->l_mp; 2720 mp = log->l_mp;
2699 efip = xfs_efi_init(mp, efi_formatp->efi_nextents); 2721 efip = xfs_efi_init(mp, efi_formatp->efi_nextents);
2700 memcpy((char *)&(efip->efi_format), (char *)efi_formatp, 2722 if ((error = xfs_efi_copy_format(&(item->ri_buf[0]),
2701 sizeof(xfs_efi_log_format_t) + 2723 &(efip->efi_format)))) {
2702 ((efi_formatp->efi_nextents - 1) * sizeof(xfs_extent_t))); 2724 xfs_efi_item_free(efip);
2725 return error;
2726 }
2703 efip->efi_next_extent = efi_formatp->efi_nextents; 2727 efip->efi_next_extent = efi_formatp->efi_nextents;
2704 efip->efi_flags |= XFS_EFI_COMMITTED; 2728 efip->efi_flags |= XFS_EFI_COMMITTED;
2705 2729
@@ -2708,6 +2732,7 @@ xlog_recover_do_efi_trans(
2708 * xfs_trans_update_ail() drops the AIL lock. 2732 * xfs_trans_update_ail() drops the AIL lock.
2709 */ 2733 */
2710 xfs_trans_update_ail(mp, (xfs_log_item_t *)efip, lsn, s); 2734 xfs_trans_update_ail(mp, (xfs_log_item_t *)efip, lsn, s);
2735 return 0;
2711} 2736}
2712 2737
2713 2738
@@ -2738,9 +2763,10 @@ xlog_recover_do_efd_trans(
2738 } 2763 }
2739 2764
2740 efd_formatp = (xfs_efd_log_format_t *)item->ri_buf[0].i_addr; 2765 efd_formatp = (xfs_efd_log_format_t *)item->ri_buf[0].i_addr;
2741 ASSERT(item->ri_buf[0].i_len == 2766 ASSERT((item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_32_t) +
2742 (sizeof(xfs_efd_log_format_t) + 2767 ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_32_t)))) ||
2743 ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_t)))); 2768 (item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_64_t) +
2769 ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_64_t)))));
2744 efi_id = efd_formatp->efd_efi_id; 2770 efi_id = efd_formatp->efd_efi_id;
2745 2771
2746 /* 2772 /*
@@ -2810,15 +2836,14 @@ xlog_recover_do_trans(
2810 if ((error = xlog_recover_do_buffer_trans(log, item, 2836 if ((error = xlog_recover_do_buffer_trans(log, item,
2811 pass))) 2837 pass)))
2812 break; 2838 break;
2813 } else if ((ITEM_TYPE(item) == XFS_LI_INODE) || 2839 } else if ((ITEM_TYPE(item) == XFS_LI_INODE)) {
2814 (ITEM_TYPE(item) == XFS_LI_6_1_INODE) ||
2815 (ITEM_TYPE(item) == XFS_LI_5_3_INODE)) {
2816 if ((error = xlog_recover_do_inode_trans(log, item, 2840 if ((error = xlog_recover_do_inode_trans(log, item,
2817 pass))) 2841 pass)))
2818 break; 2842 break;
2819 } else if (ITEM_TYPE(item) == XFS_LI_EFI) { 2843 } else if (ITEM_TYPE(item) == XFS_LI_EFI) {
2820 xlog_recover_do_efi_trans(log, item, trans->r_lsn, 2844 if ((error = xlog_recover_do_efi_trans(log, item, trans->r_lsn,
2821 pass); 2845 pass)))
2846 break;
2822 } else if (ITEM_TYPE(item) == XFS_LI_EFD) { 2847 } else if (ITEM_TYPE(item) == XFS_LI_EFD) {
2823 xlog_recover_do_efd_trans(log, item, pass); 2848 xlog_recover_do_efd_trans(log, item, pass);
2824 } else if (ITEM_TYPE(item) == XFS_LI_DQUOT) { 2849 } else if (ITEM_TYPE(item) == XFS_LI_DQUOT) {
@@ -3798,7 +3823,7 @@ xlog_do_log_recovery(
3798 error = xlog_do_recovery_pass(log, head_blk, tail_blk, 3823 error = xlog_do_recovery_pass(log, head_blk, tail_blk,
3799 XLOG_RECOVER_PASS2); 3824 XLOG_RECOVER_PASS2);
3800#ifdef DEBUG 3825#ifdef DEBUG
3801 { 3826 if (!error) {
3802 int i; 3827 int i;
3803 3828
3804 for (i = 0; i < XLOG_BC_TABLE_SIZE; i++) 3829 for (i = 0; i < XLOG_BC_TABLE_SIZE; i++)