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

Commit 27999f25 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

NFSv4.1: Ensure that the layout recall callback matches layout stateids



It is not sufficient to compare filehandles when we receive a layout
recall from the server; we also need to check that the layout stateids
match.

Reported-by: default avatarshaobingqing <shaobingqing@bwstor.com.cn>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent e999e80e
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
@@ -112,7 +112,8 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy,
 * TODO: keep track of all layouts (and delegations) in a hash table
 * hashed by filehandle.
 */
static struct pnfs_layout_hdr * get_layout_by_fh_locked(struct nfs_client *clp, struct nfs_fh *fh)
static struct pnfs_layout_hdr * get_layout_by_fh_locked(struct nfs_client *clp,
		struct nfs_fh *fh, nfs4_stateid *stateid)
{
	struct nfs_server *server;
	struct inode *ino;
@@ -120,6 +121,8 @@ static struct pnfs_layout_hdr * get_layout_by_fh_locked(struct nfs_client *clp,

	list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
		list_for_each_entry(lo, &server->layouts, plh_layouts) {
			if (!nfs4_stateid_match_other(&lo->plh_stateid, stateid))
				continue;
			if (nfs_compare_fh(fh, &NFS_I(lo->plh_inode)->fh))
				continue;
			ino = igrab(lo->plh_inode);
@@ -141,13 +144,14 @@ static struct pnfs_layout_hdr * get_layout_by_fh_locked(struct nfs_client *clp,
	return NULL;
}

static struct pnfs_layout_hdr * get_layout_by_fh(struct nfs_client *clp, struct nfs_fh *fh)
static struct pnfs_layout_hdr * get_layout_by_fh(struct nfs_client *clp,
		struct nfs_fh *fh, nfs4_stateid *stateid)
{
	struct pnfs_layout_hdr *lo;

	spin_lock(&clp->cl_lock);
	rcu_read_lock();
	lo = get_layout_by_fh_locked(clp, fh);
	lo = get_layout_by_fh_locked(clp, fh, stateid);
	rcu_read_unlock();
	spin_unlock(&clp->cl_lock);

@@ -162,9 +166,9 @@ static u32 initiate_file_draining(struct nfs_client *clp,
	u32 rv = NFS4ERR_NOMATCHING_LAYOUT;
	LIST_HEAD(free_me_list);

	lo = get_layout_by_fh(clp, &args->cbl_fh);
	lo = get_layout_by_fh(clp, &args->cbl_fh, &args->cbl_stateid);
	if (!lo)
		return NFS4ERR_NOMATCHING_LAYOUT;
		goto out;

	ino = lo->plh_inode;
	spin_lock(&ino->i_lock);
@@ -179,6 +183,7 @@ static u32 initiate_file_draining(struct nfs_client *clp,
	pnfs_free_lseg_list(&free_me_list);
	pnfs_put_layout_hdr(lo);
	iput(ino);
out:
	return rv;
}