diff options
-rw-r--r-- | fs/xfs/libxfs/xfs_log_format.h | 27 | ||||
-rw-r--r-- | fs/xfs/xfs_inode_item.c | 79 | ||||
-rw-r--r-- | fs/xfs/xfs_ondisk.h | 2 |
3 files changed, 50 insertions, 58 deletions
diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h index 8372e9bcd7b6..71de185735e0 100644 --- a/fs/xfs/libxfs/xfs_log_format.h +++ b/fs/xfs/libxfs/xfs_log_format.h | |||
@@ -270,6 +270,7 @@ typedef struct xfs_inode_log_format { | |||
270 | uint32_t ilf_fields; /* flags for fields logged */ | 270 | uint32_t ilf_fields; /* flags for fields logged */ |
271 | uint16_t ilf_asize; /* size of attr d/ext/root */ | 271 | uint16_t ilf_asize; /* size of attr d/ext/root */ |
272 | uint16_t ilf_dsize; /* size of data/ext/root */ | 272 | uint16_t ilf_dsize; /* size of data/ext/root */ |
273 | uint32_t ilf_pad; /* pad for 64 bit boundary */ | ||
273 | uint64_t ilf_ino; /* inode number */ | 274 | uint64_t ilf_ino; /* inode number */ |
274 | union { | 275 | union { |
275 | uint32_t ilfu_rdev; /* rdev value for dev inode*/ | 276 | uint32_t ilfu_rdev; /* rdev value for dev inode*/ |
@@ -280,29 +281,17 @@ typedef struct xfs_inode_log_format { | |||
280 | int32_t ilf_boffset; /* off of inode in buffer */ | 281 | int32_t ilf_boffset; /* off of inode in buffer */ |
281 | } xfs_inode_log_format_t; | 282 | } xfs_inode_log_format_t; |
282 | 283 | ||
283 | typedef struct xfs_inode_log_format_32 { | 284 | /* |
284 | uint16_t ilf_type; /* inode log item type */ | 285 | * Old 32 bit systems will log in this format without the 64 bit |
285 | uint16_t ilf_size; /* size of this item */ | 286 | * alignment padding. Recovery will detect this and convert it to the |
286 | uint32_t ilf_fields; /* flags for fields logged */ | 287 | * correct format. |
287 | uint16_t ilf_asize; /* size of attr d/ext/root */ | 288 | */ |
288 | uint16_t ilf_dsize; /* size of data/ext/root */ | 289 | struct xfs_inode_log_format_32 { |
289 | uint64_t ilf_ino; /* inode number */ | ||
290 | union { | ||
291 | uint32_t ilfu_rdev; /* rdev value for dev inode*/ | ||
292 | uuid_t ilfu_uuid; /* mount point value */ | ||
293 | } ilf_u; | ||
294 | int64_t ilf_blkno; /* blkno of inode buffer */ | ||
295 | int32_t ilf_len; /* len of inode buffer */ | ||
296 | int32_t ilf_boffset; /* off of inode in buffer */ | ||
297 | } __attribute__((packed)) xfs_inode_log_format_32_t; | ||
298 | |||
299 | typedef struct xfs_inode_log_format_64 { | ||
300 | uint16_t ilf_type; /* inode log item type */ | 290 | uint16_t ilf_type; /* inode log item type */ |
301 | uint16_t ilf_size; /* size of this item */ | 291 | uint16_t ilf_size; /* size of this item */ |
302 | uint32_t ilf_fields; /* flags for fields logged */ | 292 | uint32_t ilf_fields; /* flags for fields logged */ |
303 | uint16_t ilf_asize; /* size of attr d/ext/root */ | 293 | uint16_t ilf_asize; /* size of attr d/ext/root */ |
304 | uint16_t ilf_dsize; /* size of data/ext/root */ | 294 | uint16_t ilf_dsize; /* size of data/ext/root */ |
305 | uint32_t ilf_pad; /* pad for 64 bit boundary */ | ||
306 | uint64_t ilf_ino; /* inode number */ | 295 | uint64_t ilf_ino; /* inode number */ |
307 | union { | 296 | union { |
308 | uint32_t ilfu_rdev; /* rdev value for dev inode*/ | 297 | uint32_t ilfu_rdev; /* rdev value for dev inode*/ |
@@ -311,7 +300,7 @@ typedef struct xfs_inode_log_format_64 { | |||
311 | int64_t ilf_blkno; /* blkno of inode buffer */ | 300 | int64_t ilf_blkno; /* blkno of inode buffer */ |
312 | int32_t ilf_len; /* len of inode buffer */ | 301 | int32_t ilf_len; /* len of inode buffer */ |
313 | int32_t ilf_boffset; /* off of inode in buffer */ | 302 | int32_t ilf_boffset; /* off of inode in buffer */ |
314 | } xfs_inode_log_format_64_t; | 303 | } __attribute__((packed)); |
315 | 304 | ||
316 | 305 | ||
317 | /* | 306 | /* |
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index a705f34b58fa..9bbc2d7cc8cb 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c | |||
@@ -364,6 +364,9 @@ xfs_inode_to_log_dinode( | |||
364 | to->di_dmstate = from->di_dmstate; | 364 | to->di_dmstate = from->di_dmstate; |
365 | to->di_flags = from->di_flags; | 365 | to->di_flags = from->di_flags; |
366 | 366 | ||
367 | /* log a dummy value to ensure log structure is fully initialised */ | ||
368 | to->di_next_unlinked = NULLAGINO; | ||
369 | |||
367 | if (from->di_version == 3) { | 370 | if (from->di_version == 3) { |
368 | to->di_changecount = inode->i_version; | 371 | to->di_changecount = inode->i_version; |
369 | to->di_crtime.t_sec = from->di_crtime.t_sec; | 372 | to->di_crtime.t_sec = from->di_crtime.t_sec; |
@@ -404,6 +407,11 @@ xfs_inode_item_format_core( | |||
404 | * the second with the on-disk inode structure, and a possible third and/or | 407 | * the second with the on-disk inode structure, and a possible third and/or |
405 | * fourth with the inode data/extents/b-tree root and inode attributes | 408 | * fourth with the inode data/extents/b-tree root and inode attributes |
406 | * data/extents/b-tree root. | 409 | * data/extents/b-tree root. |
410 | * | ||
411 | * Note: Always use the 64 bit inode log format structure so we don't | ||
412 | * leave an uninitialised hole in the format item on 64 bit systems. Log | ||
413 | * recovery on 32 bit systems handles this just fine, so there's no reason | ||
414 | * for not using an initialising the properly padded structure all the time. | ||
407 | */ | 415 | */ |
408 | STATIC void | 416 | STATIC void |
409 | xfs_inode_item_format( | 417 | xfs_inode_item_format( |
@@ -412,8 +420,8 @@ xfs_inode_item_format( | |||
412 | { | 420 | { |
413 | struct xfs_inode_log_item *iip = INODE_ITEM(lip); | 421 | struct xfs_inode_log_item *iip = INODE_ITEM(lip); |
414 | struct xfs_inode *ip = iip->ili_inode; | 422 | struct xfs_inode *ip = iip->ili_inode; |
415 | struct xfs_inode_log_format *ilf; | ||
416 | struct xfs_log_iovec *vecp = NULL; | 423 | struct xfs_log_iovec *vecp = NULL; |
424 | struct xfs_inode_log_format *ilf; | ||
417 | 425 | ||
418 | ASSERT(ip->i_d.di_version > 1); | 426 | ASSERT(ip->i_d.di_version > 1); |
419 | 427 | ||
@@ -425,7 +433,17 @@ xfs_inode_item_format( | |||
425 | ilf->ilf_boffset = ip->i_imap.im_boffset; | 433 | ilf->ilf_boffset = ip->i_imap.im_boffset; |
426 | ilf->ilf_fields = XFS_ILOG_CORE; | 434 | ilf->ilf_fields = XFS_ILOG_CORE; |
427 | ilf->ilf_size = 2; /* format + core */ | 435 | ilf->ilf_size = 2; /* format + core */ |
428 | xlog_finish_iovec(lv, vecp, sizeof(struct xfs_inode_log_format)); | 436 | |
437 | /* | ||
438 | * make sure we don't leak uninitialised data into the log in the case | ||
439 | * when we don't log every field in the inode. | ||
440 | */ | ||
441 | ilf->ilf_dsize = 0; | ||
442 | ilf->ilf_asize = 0; | ||
443 | ilf->ilf_pad = 0; | ||
444 | uuid_copy(&ilf->ilf_u.ilfu_uuid, &uuid_null); | ||
445 | |||
446 | xlog_finish_iovec(lv, vecp, sizeof(*ilf)); | ||
429 | 447 | ||
430 | xfs_inode_item_format_core(ip, lv, &vecp); | 448 | xfs_inode_item_format_core(ip, lv, &vecp); |
431 | xfs_inode_item_format_data_fork(iip, ilf, lv, &vecp); | 449 | xfs_inode_item_format_data_fork(iip, ilf, lv, &vecp); |
@@ -855,44 +873,29 @@ xfs_istale_done( | |||
855 | } | 873 | } |
856 | 874 | ||
857 | /* | 875 | /* |
858 | * convert an xfs_inode_log_format struct from either 32 or 64 bit versions | 876 | * convert an xfs_inode_log_format struct from the old 32 bit version |
859 | * (which can have different field alignments) to the native version | 877 | * (which can have different field alignments) to the native 64 bit version |
860 | */ | 878 | */ |
861 | int | 879 | int |
862 | xfs_inode_item_format_convert( | 880 | xfs_inode_item_format_convert( |
863 | xfs_log_iovec_t *buf, | 881 | struct xfs_log_iovec *buf, |
864 | xfs_inode_log_format_t *in_f) | 882 | struct xfs_inode_log_format *in_f) |
865 | { | 883 | { |
866 | if (buf->i_len == sizeof(xfs_inode_log_format_32_t)) { | 884 | struct xfs_inode_log_format_32 *in_f32 = buf->i_addr; |
867 | xfs_inode_log_format_32_t *in_f32 = buf->i_addr; | 885 | |
868 | 886 | if (buf->i_len != sizeof(*in_f32)) | |
869 | in_f->ilf_type = in_f32->ilf_type; | 887 | return -EFSCORRUPTED; |
870 | in_f->ilf_size = in_f32->ilf_size; | 888 | |
871 | in_f->ilf_fields = in_f32->ilf_fields; | 889 | in_f->ilf_type = in_f32->ilf_type; |
872 | in_f->ilf_asize = in_f32->ilf_asize; | 890 | in_f->ilf_size = in_f32->ilf_size; |
873 | in_f->ilf_dsize = in_f32->ilf_dsize; | 891 | in_f->ilf_fields = in_f32->ilf_fields; |
874 | in_f->ilf_ino = in_f32->ilf_ino; | 892 | in_f->ilf_asize = in_f32->ilf_asize; |
875 | /* copy biggest field of ilf_u */ | 893 | in_f->ilf_dsize = in_f32->ilf_dsize; |
876 | uuid_copy(&in_f->ilf_u.ilfu_uuid, &in_f32->ilf_u.ilfu_uuid); | 894 | in_f->ilf_ino = in_f32->ilf_ino; |
877 | in_f->ilf_blkno = in_f32->ilf_blkno; | 895 | /* copy biggest field of ilf_u */ |
878 | in_f->ilf_len = in_f32->ilf_len; | 896 | uuid_copy(&in_f->ilf_u.ilfu_uuid, &in_f32->ilf_u.ilfu_uuid); |
879 | in_f->ilf_boffset = in_f32->ilf_boffset; | 897 | in_f->ilf_blkno = in_f32->ilf_blkno; |
880 | return 0; | 898 | in_f->ilf_len = in_f32->ilf_len; |
881 | } else if (buf->i_len == sizeof(xfs_inode_log_format_64_t)){ | 899 | in_f->ilf_boffset = in_f32->ilf_boffset; |
882 | xfs_inode_log_format_64_t *in_f64 = buf->i_addr; | 900 | return 0; |
883 | |||
884 | in_f->ilf_type = in_f64->ilf_type; | ||
885 | in_f->ilf_size = in_f64->ilf_size; | ||
886 | in_f->ilf_fields = in_f64->ilf_fields; | ||
887 | in_f->ilf_asize = in_f64->ilf_asize; | ||
888 | in_f->ilf_dsize = in_f64->ilf_dsize; | ||
889 | in_f->ilf_ino = in_f64->ilf_ino; | ||
890 | /* copy biggest field of ilf_u */ | ||
891 | uuid_copy(&in_f->ilf_u.ilfu_uuid, &in_f64->ilf_u.ilfu_uuid); | ||
892 | in_f->ilf_blkno = in_f64->ilf_blkno; | ||
893 | in_f->ilf_len = in_f64->ilf_len; | ||
894 | in_f->ilf_boffset = in_f64->ilf_boffset; | ||
895 | return 0; | ||
896 | } | ||
897 | return -EFSCORRUPTED; | ||
898 | } | 901 | } |
diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h index 0c381d71b242..0492436a053f 100644 --- a/fs/xfs/xfs_ondisk.h +++ b/fs/xfs/xfs_ondisk.h | |||
@@ -134,7 +134,7 @@ xfs_check_ondisk_structs(void) | |||
134 | XFS_CHECK_STRUCT_SIZE(struct xfs_icreate_log, 28); | 134 | XFS_CHECK_STRUCT_SIZE(struct xfs_icreate_log, 28); |
135 | XFS_CHECK_STRUCT_SIZE(struct xfs_ictimestamp, 8); | 135 | XFS_CHECK_STRUCT_SIZE(struct xfs_ictimestamp, 8); |
136 | XFS_CHECK_STRUCT_SIZE(struct xfs_inode_log_format_32, 52); | 136 | XFS_CHECK_STRUCT_SIZE(struct xfs_inode_log_format_32, 52); |
137 | XFS_CHECK_STRUCT_SIZE(struct xfs_inode_log_format_64, 56); | 137 | XFS_CHECK_STRUCT_SIZE(struct xfs_inode_log_format, 56); |
138 | XFS_CHECK_STRUCT_SIZE(struct xfs_qoff_logformat, 20); | 138 | XFS_CHECK_STRUCT_SIZE(struct xfs_qoff_logformat, 20); |
139 | XFS_CHECK_STRUCT_SIZE(struct xfs_trans_header, 16); | 139 | XFS_CHECK_STRUCT_SIZE(struct xfs_trans_header, 16); |
140 | } | 140 | } |