aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/libxfs/xfs_log_format.h27
-rw-r--r--fs/xfs/xfs_inode_item.c79
-rw-r--r--fs/xfs/xfs_ondisk.h2
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
283typedef 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 */ 289struct 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
299typedef 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 */
408STATIC void 416STATIC void
409xfs_inode_item_format( 417xfs_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 */
861int 879int
862xfs_inode_item_format_convert( 880xfs_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}