diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/xfs_extfree_item.c | 56 | ||||
-rw-r--r-- | fs/xfs/xfs_extfree_item.h | 53 | ||||
-rw-r--r-- | fs/xfs/xfs_inode_item.c | 49 | ||||
-rw-r--r-- | fs/xfs/xfs_inode_item.h | 61 | ||||
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 87 |
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 | */ | ||
303 | int | ||
304 | xfs_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 | |||
36 | typedef struct xfs_extent_32 { | ||
37 | xfs_dfsbno_t ext_start; | ||
38 | xfs_extlen_t ext_len; | ||
39 | } __attribute__((packed)) xfs_extent_32_t; | ||
40 | |||
41 | typedef 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 | ||
60 | typedef 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 | |||
68 | typedef 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 | ||
89 | typedef 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 | |||
97 | typedef 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; | |||
103 | xfs_efi_log_item_t *xfs_efi_init(struct xfs_mount *, uint); | 153 | xfs_efi_log_item_t *xfs_efi_init(struct xfs_mount *, uint); |
104 | xfs_efd_log_item_t *xfs_efd_init(struct xfs_mount *, xfs_efi_log_item_t *, | 154 | xfs_efd_log_item_t *xfs_efd_init(struct xfs_mount *, xfs_efi_log_item_t *, |
105 | uint); | 155 | uint); |
106 | 156 | int xfs_efi_copy_format(xfs_log_iovec_t *buf, | |
157 | xfs_efi_log_format_t *dst_efi_fmt); | ||
107 | void xfs_efi_item_free(xfs_efi_log_item_t *); | 158 | void 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 | */ | ||
1092 | int | ||
1093 | xfs_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 | */ |
46 | typedef struct xfs_inode_log_format { | 27 | typedef 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 */ | 43 | typedef struct xfs_inode_log_format_32 { |
63 | typedef 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 | |||
59 | typedef 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 *); | |||
172 | extern void xfs_iflush_done(struct xfs_buf *, xfs_inode_log_item_t *); | 173 | extern void xfs_iflush_done(struct xfs_buf *, xfs_inode_log_item_t *); |
173 | extern void xfs_istale_done(struct xfs_buf *, xfs_inode_log_item_t *); | 174 | extern void xfs_istale_done(struct xfs_buf *, xfs_inode_log_item_t *); |
174 | extern void xfs_iflush_abort(struct xfs_inode *); | 175 | extern void xfs_iflush_abort(struct xfs_inode *); |
176 | extern 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); | 2561 | error: |
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 | */ |
2677 | STATIC void | 2701 | STATIC int |
2678 | xlog_recover_do_efi_trans( | 2702 | xlog_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++) |