mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 16:54:21 +00:00 
			
		
		
		
	xfs: fix dir3 freespace block corruption
When the directory freespace index grows to a second block (2017
4k data blocks in the directory), the initialisation of the second
new block header goes wrong. The write verifier fires a corruption
error indicating that the block number in the header is zero. This
was being tripped by xfs/110.
The problem is that the initialisation of the new block is done just
fine in xfs_dir3_free_get_buf(), but the caller then users a dirv2
structure to zero on-disk header fields that xfs_dir3_free_get_buf()
has already zeroed. These lined up with the block number in the dir
v3 header format.
While looking at this, I noticed that the struct xfs_dir3_free_hdr()
had 4 bytes of padding in it that wasn't defined as padding or being
zeroed by the initialisation. Add a pad field declaration and fully
zero the on disk and in-core headers in xfs_dir3_free_get_buf() so
that this is never an issue in the future. Note that this doesn't
change the on-disk layout, just makes the 32 bits of padding in the
layout explicit.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Ben Myers <bpm@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
(cherry picked from commit 5ae6e6a401)
			
			
This commit is contained in:
		
							parent
							
								
									7c9950fd2a
								
							
						
					
					
						commit
						e400d27d16
					
				
					 2 changed files with 7 additions and 7 deletions
				
			
		|  | @ -715,6 +715,7 @@ struct xfs_dir3_free_hdr { | ||||||
| 	__be32			firstdb;	/* db of first entry */ | 	__be32			firstdb;	/* db of first entry */ | ||||||
| 	__be32			nvalid;		/* count of valid entries */ | 	__be32			nvalid;		/* count of valid entries */ | ||||||
| 	__be32			nused;		/* count of used entries */ | 	__be32			nused;		/* count of used entries */ | ||||||
|  | 	__be32			pad;		/* 64 bit alignment. */ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct xfs_dir3_free { | struct xfs_dir3_free { | ||||||
|  |  | ||||||
|  | @ -263,18 +263,19 @@ xfs_dir3_free_get_buf( | ||||||
| 	 * Initialize the new block to be empty, and remember | 	 * Initialize the new block to be empty, and remember | ||||||
| 	 * its first slot as our empty slot. | 	 * its first slot as our empty slot. | ||||||
| 	 */ | 	 */ | ||||||
| 	hdr.magic = XFS_DIR2_FREE_MAGIC; | 	memset(bp->b_addr, 0, sizeof(struct xfs_dir3_free_hdr)); | ||||||
| 	hdr.firstdb = 0; | 	memset(&hdr, 0, sizeof(hdr)); | ||||||
| 	hdr.nused = 0; | 
 | ||||||
| 	hdr.nvalid = 0; |  | ||||||
| 	if (xfs_sb_version_hascrc(&mp->m_sb)) { | 	if (xfs_sb_version_hascrc(&mp->m_sb)) { | ||||||
| 		struct xfs_dir3_free_hdr *hdr3 = bp->b_addr; | 		struct xfs_dir3_free_hdr *hdr3 = bp->b_addr; | ||||||
| 
 | 
 | ||||||
| 		hdr.magic = XFS_DIR3_FREE_MAGIC; | 		hdr.magic = XFS_DIR3_FREE_MAGIC; | ||||||
|  | 
 | ||||||
| 		hdr3->hdr.blkno = cpu_to_be64(bp->b_bn); | 		hdr3->hdr.blkno = cpu_to_be64(bp->b_bn); | ||||||
| 		hdr3->hdr.owner = cpu_to_be64(dp->i_ino); | 		hdr3->hdr.owner = cpu_to_be64(dp->i_ino); | ||||||
| 		uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_uuid); | 		uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_uuid); | ||||||
| 	} | 	} else | ||||||
|  | 		hdr.magic = XFS_DIR2_FREE_MAGIC; | ||||||
| 	xfs_dir3_free_hdr_to_disk(bp->b_addr, &hdr); | 	xfs_dir3_free_hdr_to_disk(bp->b_addr, &hdr); | ||||||
| 	*bpp = bp; | 	*bpp = bp; | ||||||
| 	return 0; | 	return 0; | ||||||
|  | @ -1921,8 +1922,6 @@ xfs_dir2_node_addname_int( | ||||||
| 			 */ | 			 */ | ||||||
| 			freehdr.firstdb = (fbno - XFS_DIR2_FREE_FIRSTDB(mp)) * | 			freehdr.firstdb = (fbno - XFS_DIR2_FREE_FIRSTDB(mp)) * | ||||||
| 					xfs_dir3_free_max_bests(mp); | 					xfs_dir3_free_max_bests(mp); | ||||||
| 			free->hdr.nvalid = 0; |  | ||||||
| 			free->hdr.nused = 0; |  | ||||||
| 		} else { | 		} else { | ||||||
| 			free = fbp->b_addr; | 			free = fbp->b_addr; | ||||||
| 			bests = xfs_dir3_free_bests_p(mp, free); | 			bests = xfs_dir3_free_bests_p(mp, free); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Dave Chinner
						Dave Chinner