Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 950ee956 authored by J. Bruce Fields's avatar J. Bruce Fields Committed by Al Viro
Browse files

exportfs: fix 32-bit nfsd handling of 64-bit inode numbers



Symptoms were spurious -ENOENTs on stat of an NFS filesystem from a
32-bit NFS server exporting a very large XFS filesystem, when the
server's cache is cold (so the inodes in question are not in cache).

Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reported-by: default avatarTrevor Cordes <trevor@tecnopolis.ca>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent b7a6ec52
Loading
Loading
Loading
Loading
+16 −2
Original line number Diff line number Diff line
@@ -215,7 +215,7 @@ struct getdents_callback {
	struct dir_context ctx;
	char *name;		/* name that was found. It already points to a
				   buffer NAME_MAX+1 is size */
	unsigned long ino;	/* the inum we are looking for */
	u64 ino;		/* the inum we are looking for */
	int found;		/* inode matched? */
	int sequence;		/* sequence counter */
};
@@ -255,10 +255,14 @@ static int get_name(const struct path *path, char *name, struct dentry *child)
	struct inode *dir = path->dentry->d_inode;
	int error;
	struct file *file;
	struct kstat stat;
	struct path child_path = {
		.mnt = path->mnt,
		.dentry = child,
	};
	struct getdents_callback buffer = {
		.ctx.actor = filldir_one,
		.name = name,
		.ino = child->d_inode->i_ino
	};

	error = -ENOTDIR;
@@ -267,6 +271,16 @@ static int get_name(const struct path *path, char *name, struct dentry *child)
	error = -EINVAL;
	if (!dir->i_fop)
		goto out;
	/*
	 * inode->i_ino is unsigned long, kstat->ino is u64, so the
	 * former would be insufficient on 32-bit hosts when the
	 * filesystem supports 64-bit inode numbers.  So we need to
	 * actually call ->getattr, not just read i_ino:
	 */
	error = vfs_getattr_nosec(&child_path, &stat);
	if (error)
		return error;
	buffer.ino = stat.ino;
	/*
	 * Open the directory ...
	 */