mirror of
				https://git.proxmox.com/git/mirror_zfs.git
				synced 2025-10-26 18:05:04 +03:00 
			
		
		
		
	Return required size when encode_fh size too small
Quoting <linux/exportfs.h>: > encode_fh() should return the fileid_type on success and on error > returns 255 (if the space needed to encode fh is greater than > @max_len*4 bytes). On error @max_len contains the minimum size (in 4 > byte unit) needed to encode the file handle. ZFS was not setting max_len in the case where the handle was too small. As a result of this, the `t_name_to_handle_at.c' example in name_to_handle_at(2) did not work on ZFS. zfsctl_fid() will itself set max_len if called with a fid that is too small, so if we give zfs_fid() that behavior as well, the fix is quite easy: if the handle is too small, just use a zero-size fid instead of the handle. Tested by running t_name_to_handle_at on a normal file, a directory, a .zfs directory, and a snapshot. Thanks-to: Puck Meerburg <puck@puckipedia.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Tony Nguyen <tony.nguyen@delphix.com> Signed-off-by: Alyssa Ross <hi@alyssa.is> Closes #11995
This commit is contained in:
		
							parent
							
								
									0db64e9036
								
							
						
					
					
						commit
						f15ec889a9
					
				| @ -3950,6 +3950,13 @@ zfs_fid(struct inode *ip, fid_t *fidp) | |||||||
| 	int		size, i, error; | 	int		size, i, error; | ||||||
| 
 | 
 | ||||||
| 	ZFS_ENTER(zfsvfs); | 	ZFS_ENTER(zfsvfs); | ||||||
|  | 
 | ||||||
|  | 	if (fidp->fid_len < SHORT_FID_LEN) { | ||||||
|  | 		fidp->fid_len = SHORT_FID_LEN; | ||||||
|  | 		ZFS_EXIT(zfsvfs); | ||||||
|  | 		return (SET_ERROR(ENOSPC)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	ZFS_VERIFY_ZP(zp); | 	ZFS_VERIFY_ZP(zp); | ||||||
| 
 | 
 | ||||||
| 	if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zfsvfs), | 	if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zfsvfs), | ||||||
|  | |||||||
| @ -41,15 +41,19 @@ zpl_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len, int connectable) | |||||||
| 	struct inode *ip = dentry->d_inode; | 	struct inode *ip = dentry->d_inode; | ||||||
| #endif /* HAVE_ENCODE_FH_WITH_INODE */ | #endif /* HAVE_ENCODE_FH_WITH_INODE */ | ||||||
| 	fstrans_cookie_t cookie; | 	fstrans_cookie_t cookie; | ||||||
| 	fid_t *fid = (fid_t *)fh; | 	ushort_t empty_fid = 0; | ||||||
|  | 	fid_t *fid; | ||||||
| 	int len_bytes, rc; | 	int len_bytes, rc; | ||||||
| 
 | 
 | ||||||
| 	len_bytes = *max_len * sizeof (__u32); | 	len_bytes = *max_len * sizeof (__u32); | ||||||
| 
 | 
 | ||||||
| 	if (len_bytes < offsetof(fid_t, fid_data)) | 	if (len_bytes < offsetof(fid_t, fid_data)) { | ||||||
| 		return (255); | 		fid = (fid_t *)&empty_fid; | ||||||
| 
 | 	} else { | ||||||
|  | 		fid = (fid_t *)fh; | ||||||
| 		fid->fid_len = len_bytes - offsetof(fid_t, fid_data); | 		fid->fid_len = len_bytes - offsetof(fid_t, fid_data); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	cookie = spl_fstrans_mark(); | 	cookie = spl_fstrans_mark(); | ||||||
| 
 | 
 | ||||||
| 	if (zfsctl_is_node(ip)) | 	if (zfsctl_is_node(ip)) | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Alyssa Ross
						Alyssa Ross