mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 16:48:26 +02:00 
			
		
		
		
	 07a1076785
			
		
	
	
		07a1076785
		
			
		
	
	
	
	
		
			
			The AFS directory format structure, union afs_xdr_dir_block::meta, has too
many alloc counter slots declared and so pushes the hash table along and
over the data.  This doesn't cause a problem at the moment because I'm
currently ignoring the hash table and only using the correct number of
alloc_ctrs in the code anyway.  In future, however, I should start using
the hash table to try and speed up afs_lookup().
Fix this by using the correct constant to declare the counter array.
Fixes: 4ea219a839 ("afs: Split the directory content defs into a header")
Signed-off-by: David Howells <dhowells@redhat.com>
Link: https://lore.kernel.org/r/20241216204124.3752367-14-dhowells@redhat.com
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
		
	
			
		
			
				
	
	
		
			116 lines
		
	
	
	
		
			2.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			116 lines
		
	
	
	
		
			2.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* SPDX-License-Identifier: GPL-2.0-or-later */
 | |
| /* AFS fileserver XDR types
 | |
|  *
 | |
|  * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
 | |
|  * Written by David Howells (dhowells@redhat.com)
 | |
|  */
 | |
| 
 | |
| #ifndef XDR_FS_H
 | |
| #define XDR_FS_H
 | |
| 
 | |
| struct afs_xdr_AFSFetchStatus {
 | |
| 	__be32	if_version;
 | |
| #define AFS_FSTATUS_VERSION	1
 | |
| 	__be32	type;
 | |
| 	__be32	nlink;
 | |
| 	__be32	size_lo;
 | |
| 	__be32	data_version_lo;
 | |
| 	__be32	author;
 | |
| 	__be32	owner;
 | |
| 	__be32	caller_access;
 | |
| 	__be32	anon_access;
 | |
| 	__be32	mode;
 | |
| 	__be32	parent_vnode;
 | |
| 	__be32	parent_unique;
 | |
| 	__be32	seg_size;
 | |
| 	__be32	mtime_client;
 | |
| 	__be32	mtime_server;
 | |
| 	__be32	group;
 | |
| 	__be32	sync_counter;
 | |
| 	__be32	data_version_hi;
 | |
| 	__be32	lock_count;
 | |
| 	__be32	size_hi;
 | |
| 	__be32	abort_code;
 | |
| } __packed;
 | |
| 
 | |
| #define AFS_DIR_HASHTBL_SIZE	128
 | |
| #define AFS_DIR_DIRENT_SIZE	32
 | |
| #define AFS_DIR_SLOTS_PER_BLOCK	64
 | |
| #define AFS_DIR_BLOCK_SIZE	2048
 | |
| #define AFS_DIR_BLOCKS_PER_PAGE	(PAGE_SIZE / AFS_DIR_BLOCK_SIZE)
 | |
| #define AFS_DIR_MAX_SLOTS	65536
 | |
| #define AFS_DIR_BLOCKS_WITH_CTR	128
 | |
| #define AFS_DIR_MAX_BLOCKS	1023
 | |
| #define AFS_DIR_RESV_BLOCKS	1
 | |
| #define AFS_DIR_RESV_BLOCKS0	13
 | |
| 
 | |
| /*
 | |
|  * Directory entry structure.
 | |
|  */
 | |
| union afs_xdr_dirent {
 | |
| 	struct {
 | |
| 		u8		valid;
 | |
| 		u8		unused[1];
 | |
| 		__be16		hash_next;
 | |
| 		__be32		vnode;
 | |
| 		__be32		unique;
 | |
| 		u8		name[];
 | |
| 		/* When determining the number of dirent slots needed to
 | |
| 		 * represent a directory entry, name should be assumed to be 16
 | |
| 		 * bytes, due to a now-standardised (mis)calculation, but it is
 | |
| 		 * in fact 20 bytes in size.  afs_dir_calc_slots() should be
 | |
| 		 * used for this.
 | |
| 		 *
 | |
| 		 * For names longer than (16 or) 20 bytes, extra slots should
 | |
| 		 * be annexed to this one using the extended_name format.
 | |
| 		 */
 | |
| 	} u;
 | |
| 	u8			extended_name[32];
 | |
| } __packed;
 | |
| 
 | |
| /*
 | |
|  * Directory block header (one at the beginning of every 2048-byte block).
 | |
|  */
 | |
| struct afs_xdr_dir_hdr {
 | |
| 	__be16		npages;
 | |
| 	__be16		magic;
 | |
| #define AFS_DIR_MAGIC htons(1234)
 | |
| 	u8		reserved;
 | |
| 	u8		bitmap[8];
 | |
| 	u8		pad[19];
 | |
| } __packed;
 | |
| 
 | |
| /*
 | |
|  * Directory block layout
 | |
|  */
 | |
| union afs_xdr_dir_block {
 | |
| 	struct afs_xdr_dir_hdr		hdr;
 | |
| 
 | |
| 	struct {
 | |
| 		struct afs_xdr_dir_hdr	hdr;
 | |
| 		u8			alloc_ctrs[AFS_DIR_BLOCKS_WITH_CTR];
 | |
| 		__be16			hashtable[AFS_DIR_HASHTBL_SIZE];
 | |
| 	} meta;
 | |
| 
 | |
| 	union afs_xdr_dirent	dirents[AFS_DIR_SLOTS_PER_BLOCK];
 | |
| } __packed;
 | |
| 
 | |
| /*
 | |
|  * Directory layout on a linux VM page.
 | |
|  */
 | |
| struct afs_xdr_dir_page {
 | |
| 	union afs_xdr_dir_block	blocks[AFS_DIR_BLOCKS_PER_PAGE];
 | |
| };
 | |
| 
 | |
| /*
 | |
|  * Calculate the number of dirent slots required for any given name length.
 | |
|  * The calculation is made assuming the part of the name in the first slot is
 | |
|  * 16 bytes, rather than 20, but this miscalculation is now standardised.
 | |
|  */
 | |
| static inline unsigned int afs_dir_calc_slots(size_t name_len)
 | |
| {
 | |
| 	name_len++; /* NUL-terminated */
 | |
| 	return 1 + ((name_len + 15) / AFS_DIR_DIRENT_SIZE);
 | |
| }
 | |
| 
 | |
| #endif /* XDR_FS_H */
 |