fs/nfs/callback_proc.c

Source file repositories/reference/linux-study-clean/fs/nfs/callback_proc.c

File Facts

System
Linux kernel
Corpus path
fs/nfs/callback_proc.c
Extension
.c
Size
20197 bytes
Lines
756
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

list_for_each_entry_rcu(lo, &server->layouts, plh_layouts) {
			if (!pnfs_layout_is_valid(lo))
				continue;
			if (!nfs4_stateid_match_other(stateid, &lo->plh_stateid))
				continue;
			if (nfs_sb_active(server->super))
				inode = igrab(lo->plh_inode);
			else
				inode = ERR_PTR(-EAGAIN);
			rcu_read_unlock();
			if (inode)
				return inode;
			nfs_sb_deactive(server->super);
			return ERR_PTR(-EAGAIN);
		}
	}
	rcu_read_unlock();
	return ERR_PTR(-ENOENT);
}

/*
 * Lookup a layout inode by filehandle.
 *
 * Note: returns a refcount on the inode and superblock
 *
 */
static struct inode *nfs_layout_find_inode_by_fh(struct nfs_client *clp,
		const struct nfs_fh *fh)
{
	struct nfs_server *server;
	struct nfs_inode *nfsi;
	struct inode *inode;
	struct pnfs_layout_hdr *lo;

	rcu_read_lock();
	list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
		list_for_each_entry_rcu(lo, &server->layouts, plh_layouts) {
			nfsi = NFS_I(lo->plh_inode);
			if (nfs_compare_fh(fh, &nfsi->fh))
				continue;
			if (nfsi->layout != lo)
				continue;
			if (nfs_sb_active(server->super))
				inode = igrab(lo->plh_inode);
			else
				inode = ERR_PTR(-EAGAIN);
			rcu_read_unlock();
			if (inode)
				return inode;
			nfs_sb_deactive(server->super);
			return ERR_PTR(-EAGAIN);
		}
	}
	rcu_read_unlock();
	return ERR_PTR(-ENOENT);
}

static struct inode *nfs_layout_find_inode(struct nfs_client *clp,
		const struct nfs_fh *fh,
		const nfs4_stateid *stateid)
{
	struct inode *inode;

	inode = nfs_layout_find_inode_by_stateid(clp, stateid);
	if (inode == ERR_PTR(-ENOENT))
		inode = nfs_layout_find_inode_by_fh(clp, fh);
	return inode;
}

/*
 * Enforce RFC5661 section 12.5.5.2.1. (Layout Recall and Return Sequencing)
 */
static u32 pnfs_check_callback_stateid(struct pnfs_layout_hdr *lo,
					const nfs4_stateid *new,
					struct cb_process_state *cps)
{
	u32 oldseq, newseq;

	/* Is the stateid not initialised? */
	if (!pnfs_layout_is_valid(lo))
		return NFS4ERR_NOMATCHING_LAYOUT;

	/* Mismatched stateid? */
	if (!nfs4_stateid_match_other(&lo->plh_stateid, new))
		return NFS4ERR_BAD_STATEID;

	newseq = be32_to_cpu(new->seqid);
	/* Are we already in a layout recall situation? */
	if (test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags))
		return NFS4ERR_DELAY;

Annotation

Implementation Notes