xref: /openbmc/linux/net/sunrpc/rpc_pipe.c (revision a35d632c)
1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * net/sunrpc/rpc_pipe.c
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * Userland/kernel interface for rpcauth_gss.
61da177e4SLinus Torvalds  * Code shamelessly plagiarized from fs/nfsd/nfsctl.c
7d51fe1beSRolf Eike Beer  * and fs/sysfs/inode.c
81da177e4SLinus Torvalds  *
91da177e4SLinus Torvalds  * Copyright (c) 2002, Trond Myklebust <trond.myklebust@fys.uio.no>
101da177e4SLinus Torvalds  *
111da177e4SLinus Torvalds  */
121da177e4SLinus Torvalds #include <linux/module.h>
131da177e4SLinus Torvalds #include <linux/slab.h>
141da177e4SLinus Torvalds #include <linux/string.h>
151da177e4SLinus Torvalds #include <linux/pagemap.h>
161da177e4SLinus Torvalds #include <linux/mount.h>
171da177e4SLinus Torvalds #include <linux/namei.h>
1850e437d5STrond Myklebust #include <linux/fsnotify.h>
191da177e4SLinus Torvalds #include <linux/kernel.h>
202446ab60STrond Myklebust #include <linux/rcupdate.h>
21e2f0c83aSJeff Layton #include <linux/utsname.h>
221da177e4SLinus Torvalds 
231da177e4SLinus Torvalds #include <asm/ioctls.h>
241da177e4SLinus Torvalds #include <linux/poll.h>
251da177e4SLinus Torvalds #include <linux/wait.h>
261da177e4SLinus Torvalds #include <linux/seq_file.h>
271da177e4SLinus Torvalds 
281da177e4SLinus Torvalds #include <linux/sunrpc/clnt.h>
291da177e4SLinus Torvalds #include <linux/workqueue.h>
301da177e4SLinus Torvalds #include <linux/sunrpc/rpc_pipe_fs.h>
318854e82dSTrond Myklebust #include <linux/sunrpc/cache.h>
32021c68deSStanislav Kinsbursky #include <linux/nsproxy.h>
332d00131aSStanislav Kinsbursky #include <linux/notifier.h>
341da177e4SLinus Torvalds 
35021c68deSStanislav Kinsbursky #include "netns.h"
362d00131aSStanislav Kinsbursky #include "sunrpc.h"
371da177e4SLinus Torvalds 
38efc46bf2SStanislav Kinsbursky #define RPCDBG_FACILITY RPCDBG_DEBUG
39efc46bf2SStanislav Kinsbursky 
40efc46bf2SStanislav Kinsbursky #define NET_NAME(net)	((net == &init_net) ? " (init_net)" : "")
411da177e4SLinus Torvalds 
421da177e4SLinus Torvalds static struct file_system_type rpc_pipe_fs_type;
434b9a445eSJeff Layton static const struct rpc_pipe_ops gssd_dummy_pipe_ops;
441da177e4SLinus Torvalds 
45e18b890bSChristoph Lameter static struct kmem_cache *rpc_inode_cachep __read_mostly;
461da177e4SLinus Torvalds 
471da177e4SLinus Torvalds #define RPC_UPCALL_TIMEOUT (30*HZ)
481da177e4SLinus Torvalds 
492d00131aSStanislav Kinsbursky static BLOCKING_NOTIFIER_HEAD(rpc_pipefs_notifier_list);
502d00131aSStanislav Kinsbursky 
512d00131aSStanislav Kinsbursky int rpc_pipefs_notifier_register(struct notifier_block *nb)
522d00131aSStanislav Kinsbursky {
532d00131aSStanislav Kinsbursky 	return blocking_notifier_chain_cond_register(&rpc_pipefs_notifier_list, nb);
542d00131aSStanislav Kinsbursky }
552d00131aSStanislav Kinsbursky EXPORT_SYMBOL_GPL(rpc_pipefs_notifier_register);
562d00131aSStanislav Kinsbursky 
572d00131aSStanislav Kinsbursky void rpc_pipefs_notifier_unregister(struct notifier_block *nb)
582d00131aSStanislav Kinsbursky {
592d00131aSStanislav Kinsbursky 	blocking_notifier_chain_unregister(&rpc_pipefs_notifier_list, nb);
602d00131aSStanislav Kinsbursky }
612d00131aSStanislav Kinsbursky EXPORT_SYMBOL_GPL(rpc_pipefs_notifier_unregister);
622d00131aSStanislav Kinsbursky 
63591ad7feSStanislav Kinsbursky static void rpc_purge_list(wait_queue_head_t *waitq, struct list_head *head,
649842ef35STrond Myklebust 		void (*destroy_msg)(struct rpc_pipe_msg *), int err)
65b3eb67a2STrond Myklebust {
66b3eb67a2STrond Myklebust 	struct rpc_pipe_msg *msg;
67b3eb67a2STrond Myklebust 
689842ef35STrond Myklebust 	if (list_empty(head))
699842ef35STrond Myklebust 		return;
709842ef35STrond Myklebust 	do {
71b3eb67a2STrond Myklebust 		msg = list_entry(head->next, struct rpc_pipe_msg, list);
725a67657aSTrond Myklebust 		list_del_init(&msg->list);
73b3eb67a2STrond Myklebust 		msg->errno = err;
74b3eb67a2STrond Myklebust 		destroy_msg(msg);
759842ef35STrond Myklebust 	} while (!list_empty(head));
7692123e06SJeff Layton 
7792123e06SJeff Layton 	if (waitq)
78591ad7feSStanislav Kinsbursky 		wake_up(waitq);
791da177e4SLinus Torvalds }
801da177e4SLinus Torvalds 
811da177e4SLinus Torvalds static void
8265f27f38SDavid Howells rpc_timeout_upcall_queue(struct work_struct *work)
831da177e4SLinus Torvalds {
849842ef35STrond Myklebust 	LIST_HEAD(free_list);
85ba9e0975SStanislav Kinsbursky 	struct rpc_pipe *pipe =
86ba9e0975SStanislav Kinsbursky 		container_of(work, struct rpc_pipe, queue_timeout.work);
879842ef35STrond Myklebust 	void (*destroy_msg)(struct rpc_pipe_msg *);
88591ad7feSStanislav Kinsbursky 	struct dentry *dentry;
891da177e4SLinus Torvalds 
90ba9e0975SStanislav Kinsbursky 	spin_lock(&pipe->lock);
91ba9e0975SStanislav Kinsbursky 	destroy_msg = pipe->ops->destroy_msg;
92ba9e0975SStanislav Kinsbursky 	if (pipe->nreaders == 0) {
93ba9e0975SStanislav Kinsbursky 		list_splice_init(&pipe->pipe, &free_list);
94ba9e0975SStanislav Kinsbursky 		pipe->pipelen = 0;
959842ef35STrond Myklebust 	}
96591ad7feSStanislav Kinsbursky 	dentry = dget(pipe->dentry);
97ba9e0975SStanislav Kinsbursky 	spin_unlock(&pipe->lock);
98c5ef6035SDavid Howells 	rpc_purge_list(dentry ? &RPC_I(d_inode(dentry))->waitq : NULL,
99591ad7feSStanislav Kinsbursky 			&free_list, destroy_msg, -ETIMEDOUT);
100591ad7feSStanislav Kinsbursky 	dput(dentry);
1019842ef35STrond Myklebust }
1021da177e4SLinus Torvalds 
103c1225158SPeng Tao ssize_t rpc_pipe_generic_upcall(struct file *filp, struct rpc_pipe_msg *msg,
104c1225158SPeng Tao 				char __user *dst, size_t buflen)
105c1225158SPeng Tao {
106c1225158SPeng Tao 	char *data = (char *)msg->data + msg->copied;
107c1225158SPeng Tao 	size_t mlen = min(msg->len - msg->copied, buflen);
108c1225158SPeng Tao 	unsigned long left;
109c1225158SPeng Tao 
110c1225158SPeng Tao 	left = copy_to_user(dst, data, mlen);
111c1225158SPeng Tao 	if (left == mlen) {
112c1225158SPeng Tao 		msg->errno = -EFAULT;
113c1225158SPeng Tao 		return -EFAULT;
114c1225158SPeng Tao 	}
115c1225158SPeng Tao 
116c1225158SPeng Tao 	mlen -= left;
117c1225158SPeng Tao 	msg->copied += mlen;
118c1225158SPeng Tao 	msg->errno = 0;
119c1225158SPeng Tao 	return mlen;
120c1225158SPeng Tao }
121c1225158SPeng Tao EXPORT_SYMBOL_GPL(rpc_pipe_generic_upcall);
122c1225158SPeng Tao 
12393a44a75SJ. Bruce Fields /**
1241a5778aaSBen Hutchings  * rpc_queue_upcall - queue an upcall message to userspace
125bda14606SRandy Dunlap  * @pipe: upcall pipe on which to queue given message
12693a44a75SJ. Bruce Fields  * @msg: message to queue
12793a44a75SJ. Bruce Fields  *
12893a44a75SJ. Bruce Fields  * Call with an @inode created by rpc_mkpipe() to queue an upcall.
12993a44a75SJ. Bruce Fields  * A userspace process may then later read the upcall by performing a
13093a44a75SJ. Bruce Fields  * read on an open file for this inode.  It is up to the caller to
13193a44a75SJ. Bruce Fields  * initialize the fields of @msg (other than @msg->list) appropriately.
13293a44a75SJ. Bruce Fields  */
1331da177e4SLinus Torvalds int
134d706ed1fSStanislav Kinsbursky rpc_queue_upcall(struct rpc_pipe *pipe, struct rpc_pipe_msg *msg)
1351da177e4SLinus Torvalds {
1366070fe6fSTrond Myklebust 	int res = -EPIPE;
137591ad7feSStanislav Kinsbursky 	struct dentry *dentry;
1381da177e4SLinus Torvalds 
139d0fe13baSStanislav Kinsbursky 	spin_lock(&pipe->lock);
140d0fe13baSStanislav Kinsbursky 	if (pipe->nreaders) {
141d0fe13baSStanislav Kinsbursky 		list_add_tail(&msg->list, &pipe->pipe);
142d0fe13baSStanislav Kinsbursky 		pipe->pipelen += msg->len;
1436070fe6fSTrond Myklebust 		res = 0;
144d0fe13baSStanislav Kinsbursky 	} else if (pipe->flags & RPC_PIPE_WAIT_FOR_OPEN) {
145d0fe13baSStanislav Kinsbursky 		if (list_empty(&pipe->pipe))
14624c5d9d7STrond Myklebust 			queue_delayed_work(rpciod_workqueue,
147d0fe13baSStanislav Kinsbursky 					&pipe->queue_timeout,
1481da177e4SLinus Torvalds 					RPC_UPCALL_TIMEOUT);
149d0fe13baSStanislav Kinsbursky 		list_add_tail(&msg->list, &pipe->pipe);
150d0fe13baSStanislav Kinsbursky 		pipe->pipelen += msg->len;
1516070fe6fSTrond Myklebust 		res = 0;
1526070fe6fSTrond Myklebust 	}
153591ad7feSStanislav Kinsbursky 	dentry = dget(pipe->dentry);
154d0fe13baSStanislav Kinsbursky 	spin_unlock(&pipe->lock);
155591ad7feSStanislav Kinsbursky 	if (dentry) {
156c5ef6035SDavid Howells 		wake_up(&RPC_I(d_inode(dentry))->waitq);
157591ad7feSStanislav Kinsbursky 		dput(dentry);
158591ad7feSStanislav Kinsbursky 	}
1591da177e4SLinus Torvalds 	return res;
1601da177e4SLinus Torvalds }
161468039eeSTrond Myklebust EXPORT_SYMBOL_GPL(rpc_queue_upcall);
1621da177e4SLinus Torvalds 
1636070fe6fSTrond Myklebust static inline void
1646070fe6fSTrond Myklebust rpc_inode_setowner(struct inode *inode, void *private)
1656070fe6fSTrond Myklebust {
1666070fe6fSTrond Myklebust 	RPC_I(inode)->private = private;
1676070fe6fSTrond Myklebust }
1686070fe6fSTrond Myklebust 
1691da177e4SLinus Torvalds static void
1701da177e4SLinus Torvalds rpc_close_pipes(struct inode *inode)
1711da177e4SLinus Torvalds {
172ba9e0975SStanislav Kinsbursky 	struct rpc_pipe *pipe = RPC_I(inode)->pipe;
173e712804aS\"J. Bruce Fields\ 	int need_release;
174ad6b1340SStanislav Kinsbursky 	LIST_HEAD(free_list);
1751da177e4SLinus Torvalds 
1765955102cSAl Viro 	inode_lock(inode);
177ba9e0975SStanislav Kinsbursky 	spin_lock(&pipe->lock);
178ba9e0975SStanislav Kinsbursky 	need_release = pipe->nreaders != 0 || pipe->nwriters != 0;
179ba9e0975SStanislav Kinsbursky 	pipe->nreaders = 0;
180ba9e0975SStanislav Kinsbursky 	list_splice_init(&pipe->in_upcall, &free_list);
181ba9e0975SStanislav Kinsbursky 	list_splice_init(&pipe->pipe, &free_list);
182ba9e0975SStanislav Kinsbursky 	pipe->pipelen = 0;
183ad6b1340SStanislav Kinsbursky 	pipe->dentry = NULL;
184ba9e0975SStanislav Kinsbursky 	spin_unlock(&pipe->lock);
185591ad7feSStanislav Kinsbursky 	rpc_purge_list(&RPC_I(inode)->waitq, &free_list, pipe->ops->destroy_msg, -EPIPE);
186ba9e0975SStanislav Kinsbursky 	pipe->nwriters = 0;
187ad6b1340SStanislav Kinsbursky 	if (need_release && pipe->ops->release_pipe)
188ad6b1340SStanislav Kinsbursky 		pipe->ops->release_pipe(inode);
189ba9e0975SStanislav Kinsbursky 	cancel_delayed_work_sync(&pipe->queue_timeout);
1906070fe6fSTrond Myklebust 	rpc_inode_setowner(inode, NULL);
1912c9030eeSStanislav Kinsbursky 	RPC_I(inode)->pipe = NULL;
1925955102cSAl Viro 	inode_unlock(inode);
1931da177e4SLinus Torvalds }
1941da177e4SLinus Torvalds 
1951da177e4SLinus Torvalds static struct inode *
1961da177e4SLinus Torvalds rpc_alloc_inode(struct super_block *sb)
1971da177e4SLinus Torvalds {
1981da177e4SLinus Torvalds 	struct rpc_inode *rpci;
199adcda652SHimangi Saraogi 	rpci = kmem_cache_alloc(rpc_inode_cachep, GFP_KERNEL);
2001da177e4SLinus Torvalds 	if (!rpci)
2011da177e4SLinus Torvalds 		return NULL;
2021da177e4SLinus Torvalds 	return &rpci->vfs_inode;
2031da177e4SLinus Torvalds }
2041da177e4SLinus Torvalds 
2051da177e4SLinus Torvalds static void
206bef252faSAl Viro rpc_free_inode(struct inode *inode)
207fa0d7e3dSNick Piggin {
208fa0d7e3dSNick Piggin 	kmem_cache_free(rpc_inode_cachep, RPC_I(inode));
209fa0d7e3dSNick Piggin }
210fa0d7e3dSNick Piggin 
2111da177e4SLinus Torvalds static int
2121da177e4SLinus Torvalds rpc_pipe_open(struct inode *inode, struct file *filp)
2131da177e4SLinus Torvalds {
2142c9030eeSStanislav Kinsbursky 	struct rpc_pipe *pipe;
215c3810608S\"J. Bruce Fields\ 	int first_open;
2161da177e4SLinus Torvalds 	int res = -ENXIO;
2171da177e4SLinus Torvalds 
2185955102cSAl Viro 	inode_lock(inode);
2192c9030eeSStanislav Kinsbursky 	pipe = RPC_I(inode)->pipe;
2202c9030eeSStanislav Kinsbursky 	if (pipe == NULL)
221c3810608S\"J. Bruce Fields\ 		goto out;
222d0fe13baSStanislav Kinsbursky 	first_open = pipe->nreaders == 0 && pipe->nwriters == 0;
223d0fe13baSStanislav Kinsbursky 	if (first_open && pipe->ops->open_pipe) {
224d0fe13baSStanislav Kinsbursky 		res = pipe->ops->open_pipe(inode);
225c3810608S\"J. Bruce Fields\ 		if (res)
226c3810608S\"J. Bruce Fields\ 			goto out;
227c3810608S\"J. Bruce Fields\ 	}
2281da177e4SLinus Torvalds 	if (filp->f_mode & FMODE_READ)
229d0fe13baSStanislav Kinsbursky 		pipe->nreaders++;
2301da177e4SLinus Torvalds 	if (filp->f_mode & FMODE_WRITE)
231d0fe13baSStanislav Kinsbursky 		pipe->nwriters++;
2321da177e4SLinus Torvalds 	res = 0;
233c3810608S\"J. Bruce Fields\ out:
2345955102cSAl Viro 	inode_unlock(inode);
2351da177e4SLinus Torvalds 	return res;
2361da177e4SLinus Torvalds }
2371da177e4SLinus Torvalds 
2381da177e4SLinus Torvalds static int
2391da177e4SLinus Torvalds rpc_pipe_release(struct inode *inode, struct file *filp)
2401da177e4SLinus Torvalds {
2412c9030eeSStanislav Kinsbursky 	struct rpc_pipe *pipe;
2421da177e4SLinus Torvalds 	struct rpc_pipe_msg *msg;
243e712804aS\"J. Bruce Fields\ 	int last_close;
2441da177e4SLinus Torvalds 
2455955102cSAl Viro 	inode_lock(inode);
2462c9030eeSStanislav Kinsbursky 	pipe = RPC_I(inode)->pipe;
2472c9030eeSStanislav Kinsbursky 	if (pipe == NULL)
2481da177e4SLinus Torvalds 		goto out;
249655b5bb4SJoe Perches 	msg = filp->private_data;
2501da177e4SLinus Torvalds 	if (msg != NULL) {
251ba9e0975SStanislav Kinsbursky 		spin_lock(&pipe->lock);
25248e49187STrond Myklebust 		msg->errno = -EAGAIN;
2535a67657aSTrond Myklebust 		list_del_init(&msg->list);
254ba9e0975SStanislav Kinsbursky 		spin_unlock(&pipe->lock);
255ba9e0975SStanislav Kinsbursky 		pipe->ops->destroy_msg(msg);
2561da177e4SLinus Torvalds 	}
2571da177e4SLinus Torvalds 	if (filp->f_mode & FMODE_WRITE)
258ba9e0975SStanislav Kinsbursky 		pipe->nwriters --;
2599842ef35STrond Myklebust 	if (filp->f_mode & FMODE_READ) {
260ba9e0975SStanislav Kinsbursky 		pipe->nreaders --;
261ba9e0975SStanislav Kinsbursky 		if (pipe->nreaders == 0) {
2629842ef35STrond Myklebust 			LIST_HEAD(free_list);
263ba9e0975SStanislav Kinsbursky 			spin_lock(&pipe->lock);
264ba9e0975SStanislav Kinsbursky 			list_splice_init(&pipe->pipe, &free_list);
265ba9e0975SStanislav Kinsbursky 			pipe->pipelen = 0;
266ba9e0975SStanislav Kinsbursky 			spin_unlock(&pipe->lock);
267591ad7feSStanislav Kinsbursky 			rpc_purge_list(&RPC_I(inode)->waitq, &free_list,
268ba9e0975SStanislav Kinsbursky 					pipe->ops->destroy_msg, -EAGAIN);
2699842ef35STrond Myklebust 		}
2709842ef35STrond Myklebust 	}
271ba9e0975SStanislav Kinsbursky 	last_close = pipe->nwriters == 0 && pipe->nreaders == 0;
272ba9e0975SStanislav Kinsbursky 	if (last_close && pipe->ops->release_pipe)
273ba9e0975SStanislav Kinsbursky 		pipe->ops->release_pipe(inode);
2741da177e4SLinus Torvalds out:
2755955102cSAl Viro 	inode_unlock(inode);
2761da177e4SLinus Torvalds 	return 0;
2771da177e4SLinus Torvalds }
2781da177e4SLinus Torvalds 
2791da177e4SLinus Torvalds static ssize_t
2801da177e4SLinus Torvalds rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset)
2811da177e4SLinus Torvalds {
282496ad9aaSAl Viro 	struct inode *inode = file_inode(filp);
2832c9030eeSStanislav Kinsbursky 	struct rpc_pipe *pipe;
2841da177e4SLinus Torvalds 	struct rpc_pipe_msg *msg;
2851da177e4SLinus Torvalds 	int res = 0;
2861da177e4SLinus Torvalds 
2875955102cSAl Viro 	inode_lock(inode);
2882c9030eeSStanislav Kinsbursky 	pipe = RPC_I(inode)->pipe;
2892c9030eeSStanislav Kinsbursky 	if (pipe == NULL) {
2901da177e4SLinus Torvalds 		res = -EPIPE;
2911da177e4SLinus Torvalds 		goto out_unlock;
2921da177e4SLinus Torvalds 	}
2931da177e4SLinus Torvalds 	msg = filp->private_data;
2941da177e4SLinus Torvalds 	if (msg == NULL) {
295d0fe13baSStanislav Kinsbursky 		spin_lock(&pipe->lock);
296d0fe13baSStanislav Kinsbursky 		if (!list_empty(&pipe->pipe)) {
297d0fe13baSStanislav Kinsbursky 			msg = list_entry(pipe->pipe.next,
2981da177e4SLinus Torvalds 					struct rpc_pipe_msg,
2991da177e4SLinus Torvalds 					list);
300d0fe13baSStanislav Kinsbursky 			list_move(&msg->list, &pipe->in_upcall);
301d0fe13baSStanislav Kinsbursky 			pipe->pipelen -= msg->len;
3021da177e4SLinus Torvalds 			filp->private_data = msg;
3031da177e4SLinus Torvalds 			msg->copied = 0;
3041da177e4SLinus Torvalds 		}
305d0fe13baSStanislav Kinsbursky 		spin_unlock(&pipe->lock);
3061da177e4SLinus Torvalds 		if (msg == NULL)
3071da177e4SLinus Torvalds 			goto out_unlock;
3081da177e4SLinus Torvalds 	}
3091da177e4SLinus Torvalds 	/* NOTE: it is up to the callback to update msg->copied */
310d0fe13baSStanislav Kinsbursky 	res = pipe->ops->upcall(filp, msg, buf, len);
3111da177e4SLinus Torvalds 	if (res < 0 || msg->len == msg->copied) {
3121da177e4SLinus Torvalds 		filp->private_data = NULL;
313d0fe13baSStanislav Kinsbursky 		spin_lock(&pipe->lock);
3145a67657aSTrond Myklebust 		list_del_init(&msg->list);
315d0fe13baSStanislav Kinsbursky 		spin_unlock(&pipe->lock);
316d0fe13baSStanislav Kinsbursky 		pipe->ops->destroy_msg(msg);
3171da177e4SLinus Torvalds 	}
3181da177e4SLinus Torvalds out_unlock:
3195955102cSAl Viro 	inode_unlock(inode);
3201da177e4SLinus Torvalds 	return res;
3211da177e4SLinus Torvalds }
3221da177e4SLinus Torvalds 
3231da177e4SLinus Torvalds static ssize_t
3241da177e4SLinus Torvalds rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *offset)
3251da177e4SLinus Torvalds {
326496ad9aaSAl Viro 	struct inode *inode = file_inode(filp);
3271da177e4SLinus Torvalds 	int res;
3281da177e4SLinus Torvalds 
3295955102cSAl Viro 	inode_lock(inode);
3301da177e4SLinus Torvalds 	res = -EPIPE;
3312c9030eeSStanislav Kinsbursky 	if (RPC_I(inode)->pipe != NULL)
3322c9030eeSStanislav Kinsbursky 		res = RPC_I(inode)->pipe->ops->downcall(filp, buf, len);
3335955102cSAl Viro 	inode_unlock(inode);
3341da177e4SLinus Torvalds 	return res;
3351da177e4SLinus Torvalds }
3361da177e4SLinus Torvalds 
337ade994f4SAl Viro static __poll_t
3381da177e4SLinus Torvalds rpc_pipe_poll(struct file *filp, struct poll_table_struct *wait)
3391da177e4SLinus Torvalds {
340496ad9aaSAl Viro 	struct inode *inode = file_inode(filp);
341591ad7feSStanislav Kinsbursky 	struct rpc_inode *rpci = RPC_I(inode);
342a9a08845SLinus Torvalds 	__poll_t mask = EPOLLOUT | EPOLLWRNORM;
3431da177e4SLinus Torvalds 
3441da177e4SLinus Torvalds 	poll_wait(filp, &rpci->waitq, wait);
3451da177e4SLinus Torvalds 
3465955102cSAl Viro 	inode_lock(inode);
347591ad7feSStanislav Kinsbursky 	if (rpci->pipe == NULL)
348a9a08845SLinus Torvalds 		mask |= EPOLLERR | EPOLLHUP;
349591ad7feSStanislav Kinsbursky 	else if (filp->private_data || !list_empty(&rpci->pipe->pipe))
350a9a08845SLinus Torvalds 		mask |= EPOLLIN | EPOLLRDNORM;
3515955102cSAl Viro 	inode_unlock(inode);
3521da177e4SLinus Torvalds 	return mask;
3531da177e4SLinus Torvalds }
3541da177e4SLinus Torvalds 
355a6f8dbc6SArnd Bergmann static long
356a6f8dbc6SArnd Bergmann rpc_pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
3571da177e4SLinus Torvalds {
358496ad9aaSAl Viro 	struct inode *inode = file_inode(filp);
3592c9030eeSStanislav Kinsbursky 	struct rpc_pipe *pipe;
3601da177e4SLinus Torvalds 	int len;
3611da177e4SLinus Torvalds 
3621da177e4SLinus Torvalds 	switch (cmd) {
3631da177e4SLinus Torvalds 	case FIONREAD:
3645955102cSAl Viro 		inode_lock(inode);
3652c9030eeSStanislav Kinsbursky 		pipe = RPC_I(inode)->pipe;
3662c9030eeSStanislav Kinsbursky 		if (pipe == NULL) {
3675955102cSAl Viro 			inode_unlock(inode);
3681da177e4SLinus Torvalds 			return -EPIPE;
369a6f8dbc6SArnd Bergmann 		}
3702c9030eeSStanislav Kinsbursky 		spin_lock(&pipe->lock);
371d0fe13baSStanislav Kinsbursky 		len = pipe->pipelen;
3721da177e4SLinus Torvalds 		if (filp->private_data) {
3731da177e4SLinus Torvalds 			struct rpc_pipe_msg *msg;
374655b5bb4SJoe Perches 			msg = filp->private_data;
3751da177e4SLinus Torvalds 			len += msg->len - msg->copied;
3761da177e4SLinus Torvalds 		}
377d0fe13baSStanislav Kinsbursky 		spin_unlock(&pipe->lock);
3785955102cSAl Viro 		inode_unlock(inode);
3791da177e4SLinus Torvalds 		return put_user(len, (int __user *)arg);
3801da177e4SLinus Torvalds 	default:
3811da177e4SLinus Torvalds 		return -EINVAL;
3821da177e4SLinus Torvalds 	}
3831da177e4SLinus Torvalds }
3841da177e4SLinus Torvalds 
385da7071d7SArjan van de Ven static const struct file_operations rpc_pipe_fops = {
3861da177e4SLinus Torvalds 	.owner		= THIS_MODULE,
3871da177e4SLinus Torvalds 	.llseek		= no_llseek,
3881da177e4SLinus Torvalds 	.read		= rpc_pipe_read,
3891da177e4SLinus Torvalds 	.write		= rpc_pipe_write,
3901da177e4SLinus Torvalds 	.poll		= rpc_pipe_poll,
391674b604cSFrederic Weisbecker 	.unlocked_ioctl	= rpc_pipe_ioctl,
3921da177e4SLinus Torvalds 	.open		= rpc_pipe_open,
3931da177e4SLinus Torvalds 	.release	= rpc_pipe_release,
3941da177e4SLinus Torvalds };
3951da177e4SLinus Torvalds 
3961da177e4SLinus Torvalds static int
3971da177e4SLinus Torvalds rpc_show_info(struct seq_file *m, void *v)
3981da177e4SLinus Torvalds {
3991da177e4SLinus Torvalds 	struct rpc_clnt *clnt = m->private;
4001da177e4SLinus Torvalds 
4012446ab60STrond Myklebust 	rcu_read_lock();
4024e0038b6STrond Myklebust 	seq_printf(m, "RPC server: %s\n",
4034e0038b6STrond Myklebust 			rcu_dereference(clnt->cl_xprt)->servername);
40455909f21STrond Myklebust 	seq_printf(m, "service: %s (%d) version %d\n", clnt->cl_program->name,
4051da177e4SLinus Torvalds 			clnt->cl_prog, clnt->cl_vers);
406e7f78657SChuck Lever 	seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR));
407e7f78657SChuck Lever 	seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO));
408bf19aaceSJ. Bruce Fields 	seq_printf(m, "port: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PORT));
4092446ab60STrond Myklebust 	rcu_read_unlock();
4101da177e4SLinus Torvalds 	return 0;
4111da177e4SLinus Torvalds }
4121da177e4SLinus Torvalds 
4131da177e4SLinus Torvalds static int
4141da177e4SLinus Torvalds rpc_info_open(struct inode *inode, struct file *file)
4151da177e4SLinus Torvalds {
416006abe88STrond Myklebust 	struct rpc_clnt *clnt = NULL;
4171da177e4SLinus Torvalds 	int ret = single_open(file, rpc_show_info, NULL);
4181da177e4SLinus Torvalds 
4191da177e4SLinus Torvalds 	if (!ret) {
4201da177e4SLinus Torvalds 		struct seq_file *m = file->private_data;
421006abe88STrond Myklebust 
422006abe88STrond Myklebust 		spin_lock(&file->f_path.dentry->d_lock);
423006abe88STrond Myklebust 		if (!d_unhashed(file->f_path.dentry))
4241da177e4SLinus Torvalds 			clnt = RPC_I(inode)->private;
425006abe88STrond Myklebust 		if (clnt != NULL && atomic_inc_not_zero(&clnt->cl_count)) {
426006abe88STrond Myklebust 			spin_unlock(&file->f_path.dentry->d_lock);
4271da177e4SLinus Torvalds 			m->private = clnt;
4281da177e4SLinus Torvalds 		} else {
429006abe88STrond Myklebust 			spin_unlock(&file->f_path.dentry->d_lock);
4301da177e4SLinus Torvalds 			single_release(inode, file);
4311da177e4SLinus Torvalds 			ret = -EINVAL;
4321da177e4SLinus Torvalds 		}
4331da177e4SLinus Torvalds 	}
4341da177e4SLinus Torvalds 	return ret;
4351da177e4SLinus Torvalds }
4361da177e4SLinus Torvalds 
4371da177e4SLinus Torvalds static int
4381da177e4SLinus Torvalds rpc_info_release(struct inode *inode, struct file *file)
4391da177e4SLinus Torvalds {
4401da177e4SLinus Torvalds 	struct seq_file *m = file->private_data;
4411da177e4SLinus Torvalds 	struct rpc_clnt *clnt = (struct rpc_clnt *)m->private;
4421da177e4SLinus Torvalds 
4431da177e4SLinus Torvalds 	if (clnt)
4441da177e4SLinus Torvalds 		rpc_release_client(clnt);
4451da177e4SLinus Torvalds 	return single_release(inode, file);
4461da177e4SLinus Torvalds }
4471da177e4SLinus Torvalds 
448da7071d7SArjan van de Ven static const struct file_operations rpc_info_operations = {
4491da177e4SLinus Torvalds 	.owner		= THIS_MODULE,
4501da177e4SLinus Torvalds 	.open		= rpc_info_open,
4511da177e4SLinus Torvalds 	.read		= seq_read,
4521da177e4SLinus Torvalds 	.llseek		= seq_lseek,
4531da177e4SLinus Torvalds 	.release	= rpc_info_release,
4541da177e4SLinus Torvalds };
4551da177e4SLinus Torvalds 
4561da177e4SLinus Torvalds 
4571da177e4SLinus Torvalds /*
4581da177e4SLinus Torvalds  * Description of fs contents.
4591da177e4SLinus Torvalds  */
4601da177e4SLinus Torvalds struct rpc_filelist {
461ac6feceeSTrond Myklebust 	const char *name;
46299ac48f5SArjan van de Ven 	const struct file_operations *i_fop;
4637364af6aSTrond Myklebust 	umode_t mode;
4641da177e4SLinus Torvalds };
4651da177e4SLinus Torvalds 
4661da177e4SLinus Torvalds static struct inode *
4677364af6aSTrond Myklebust rpc_get_inode(struct super_block *sb, umode_t mode)
4681da177e4SLinus Torvalds {
4691da177e4SLinus Torvalds 	struct inode *inode = new_inode(sb);
4701da177e4SLinus Torvalds 	if (!inode)
4711da177e4SLinus Torvalds 		return NULL;
47285fe4025SChristoph Hellwig 	inode->i_ino = get_next_ino();
4731da177e4SLinus Torvalds 	inode->i_mode = mode;
474078cd827SDeepa Dinamani 	inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
4751da177e4SLinus Torvalds 	switch (mode & S_IFMT) {
4761da177e4SLinus Torvalds 	case S_IFDIR:
4771da177e4SLinus Torvalds 		inode->i_fop = &simple_dir_operations;
478275448ebSJeff Layton 		inode->i_op = &simple_dir_inode_operations;
479d8c76e6fSDave Hansen 		inc_nlink(inode);
4801da177e4SLinus Torvalds 	default:
4811da177e4SLinus Torvalds 		break;
4821da177e4SLinus Torvalds 	}
4831da177e4SLinus Torvalds 	return inode;
4841da177e4SLinus Torvalds }
4851da177e4SLinus Torvalds 
4867589806eSTrond Myklebust static int __rpc_create_common(struct inode *dir, struct dentry *dentry,
4877589806eSTrond Myklebust 			       umode_t mode,
4887589806eSTrond Myklebust 			       const struct file_operations *i_fop,
4897589806eSTrond Myklebust 			       void *private)
4907589806eSTrond Myklebust {
4917589806eSTrond Myklebust 	struct inode *inode;
4927589806eSTrond Myklebust 
493beb0f0a9STrond Myklebust 	d_drop(dentry);
4947589806eSTrond Myklebust 	inode = rpc_get_inode(dir->i_sb, mode);
4957589806eSTrond Myklebust 	if (!inode)
4967589806eSTrond Myklebust 		goto out_err;
4977589806eSTrond Myklebust 	inode->i_ino = iunique(dir->i_sb, 100);
4987589806eSTrond Myklebust 	if (i_fop)
4997589806eSTrond Myklebust 		inode->i_fop = i_fop;
5007589806eSTrond Myklebust 	if (private)
5017589806eSTrond Myklebust 		rpc_inode_setowner(inode, private);
5027589806eSTrond Myklebust 	d_add(dentry, inode);
5037589806eSTrond Myklebust 	return 0;
5047589806eSTrond Myklebust out_err:
5051e903edaSAl Viro 	printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %pd\n",
5061e903edaSAl Viro 			__FILE__, __func__, dentry);
5077589806eSTrond Myklebust 	dput(dentry);
5087589806eSTrond Myklebust 	return -ENOMEM;
5097589806eSTrond Myklebust }
5107589806eSTrond Myklebust 
511ac6feceeSTrond Myklebust static int __rpc_create(struct inode *dir, struct dentry *dentry,
512ac6feceeSTrond Myklebust 			umode_t mode,
513ac6feceeSTrond Myklebust 			const struct file_operations *i_fop,
514ac6feceeSTrond Myklebust 			void *private)
515ac6feceeSTrond Myklebust {
516ac6feceeSTrond Myklebust 	int err;
517ac6feceeSTrond Myklebust 
518ac6feceeSTrond Myklebust 	err = __rpc_create_common(dir, dentry, S_IFREG | mode, i_fop, private);
519ac6feceeSTrond Myklebust 	if (err)
520ac6feceeSTrond Myklebust 		return err;
521ac6feceeSTrond Myklebust 	fsnotify_create(dir, dentry);
522ac6feceeSTrond Myklebust 	return 0;
523ac6feceeSTrond Myklebust }
524ac6feceeSTrond Myklebust 
5257589806eSTrond Myklebust static int __rpc_mkdir(struct inode *dir, struct dentry *dentry,
5267589806eSTrond Myklebust 		       umode_t mode,
5277589806eSTrond Myklebust 		       const struct file_operations *i_fop,
5287589806eSTrond Myklebust 		       void *private)
5297589806eSTrond Myklebust {
5307589806eSTrond Myklebust 	int err;
5317589806eSTrond Myklebust 
5327589806eSTrond Myklebust 	err = __rpc_create_common(dir, dentry, S_IFDIR | mode, i_fop, private);
5337589806eSTrond Myklebust 	if (err)
5347589806eSTrond Myklebust 		return err;
5357589806eSTrond Myklebust 	inc_nlink(dir);
5367589806eSTrond Myklebust 	fsnotify_mkdir(dir, dentry);
5377589806eSTrond Myklebust 	return 0;
5387589806eSTrond Myklebust }
5397589806eSTrond Myklebust 
540ba9e0975SStanislav Kinsbursky static void
541ba9e0975SStanislav Kinsbursky init_pipe(struct rpc_pipe *pipe)
542ba9e0975SStanislav Kinsbursky {
543ba9e0975SStanislav Kinsbursky 	pipe->nreaders = 0;
544ba9e0975SStanislav Kinsbursky 	pipe->nwriters = 0;
545ba9e0975SStanislav Kinsbursky 	INIT_LIST_HEAD(&pipe->in_upcall);
546ba9e0975SStanislav Kinsbursky 	INIT_LIST_HEAD(&pipe->in_downcall);
547ba9e0975SStanislav Kinsbursky 	INIT_LIST_HEAD(&pipe->pipe);
548ba9e0975SStanislav Kinsbursky 	pipe->pipelen = 0;
549ba9e0975SStanislav Kinsbursky 	INIT_DELAYED_WORK(&pipe->queue_timeout,
550ba9e0975SStanislav Kinsbursky 			    rpc_timeout_upcall_queue);
551ba9e0975SStanislav Kinsbursky 	pipe->ops = NULL;
552ba9e0975SStanislav Kinsbursky 	spin_lock_init(&pipe->lock);
553c239d83bSStanislav Kinsbursky 	pipe->dentry = NULL;
554ba9e0975SStanislav Kinsbursky }
555ba9e0975SStanislav Kinsbursky 
556c239d83bSStanislav Kinsbursky void rpc_destroy_pipe_data(struct rpc_pipe *pipe)
557c239d83bSStanislav Kinsbursky {
558c239d83bSStanislav Kinsbursky 	kfree(pipe);
559c239d83bSStanislav Kinsbursky }
560c239d83bSStanislav Kinsbursky EXPORT_SYMBOL_GPL(rpc_destroy_pipe_data);
561c239d83bSStanislav Kinsbursky 
562c239d83bSStanislav Kinsbursky struct rpc_pipe *rpc_mkpipe_data(const struct rpc_pipe_ops *ops, int flags)
5637589806eSTrond Myklebust {
564ba9e0975SStanislav Kinsbursky 	struct rpc_pipe *pipe;
5657589806eSTrond Myklebust 
566ba9e0975SStanislav Kinsbursky 	pipe = kzalloc(sizeof(struct rpc_pipe), GFP_KERNEL);
567ba9e0975SStanislav Kinsbursky 	if (!pipe)
568c239d83bSStanislav Kinsbursky 		return ERR_PTR(-ENOMEM);
569ba9e0975SStanislav Kinsbursky 	init_pipe(pipe);
570c239d83bSStanislav Kinsbursky 	pipe->ops = ops;
571c239d83bSStanislav Kinsbursky 	pipe->flags = flags;
572c239d83bSStanislav Kinsbursky 	return pipe;
573ba9e0975SStanislav Kinsbursky }
574c239d83bSStanislav Kinsbursky EXPORT_SYMBOL_GPL(rpc_mkpipe_data);
575c239d83bSStanislav Kinsbursky 
576c239d83bSStanislav Kinsbursky static int __rpc_mkpipe_dentry(struct inode *dir, struct dentry *dentry,
5777589806eSTrond Myklebust 			       umode_t mode,
5787589806eSTrond Myklebust 			       const struct file_operations *i_fop,
5797589806eSTrond Myklebust 			       void *private,
580c239d83bSStanislav Kinsbursky 			       struct rpc_pipe *pipe)
5817589806eSTrond Myklebust {
5827589806eSTrond Myklebust 	struct rpc_inode *rpci;
5837589806eSTrond Myklebust 	int err;
5847589806eSTrond Myklebust 
5857589806eSTrond Myklebust 	err = __rpc_create_common(dir, dentry, S_IFIFO | mode, i_fop, private);
5867589806eSTrond Myklebust 	if (err)
5877589806eSTrond Myklebust 		return err;
588c5ef6035SDavid Howells 	rpci = RPC_I(d_inode(dentry));
5897589806eSTrond Myklebust 	rpci->private = private;
590ba9e0975SStanislav Kinsbursky 	rpci->pipe = pipe;
5917589806eSTrond Myklebust 	fsnotify_create(dir, dentry);
5927589806eSTrond Myklebust 	return 0;
5937589806eSTrond Myklebust }
5947589806eSTrond Myklebust 
595ac6feceeSTrond Myklebust static int __rpc_rmdir(struct inode *dir, struct dentry *dentry)
596ac6feceeSTrond Myklebust {
597ac6feceeSTrond Myklebust 	int ret;
598ac6feceeSTrond Myklebust 
599ac6feceeSTrond Myklebust 	dget(dentry);
600ac6feceeSTrond Myklebust 	ret = simple_rmdir(dir, dentry);
601a35d632cSAmir Goldstein 	if (!ret)
602a35d632cSAmir Goldstein 		fsnotify_rmdir(dir, dentry);
603ac6feceeSTrond Myklebust 	d_delete(dentry);
604ac6feceeSTrond Myklebust 	dput(dentry);
605ac6feceeSTrond Myklebust 	return ret;
606ac6feceeSTrond Myklebust }
607ac6feceeSTrond Myklebust 
608810d90bcSTrond Myklebust static int __rpc_unlink(struct inode *dir, struct dentry *dentry)
609810d90bcSTrond Myklebust {
610810d90bcSTrond Myklebust 	int ret;
611810d90bcSTrond Myklebust 
612810d90bcSTrond Myklebust 	dget(dentry);
613810d90bcSTrond Myklebust 	ret = simple_unlink(dir, dentry);
614a35d632cSAmir Goldstein 	if (!ret)
615a35d632cSAmir Goldstein 		fsnotify_unlink(dir, dentry);
616810d90bcSTrond Myklebust 	d_delete(dentry);
617810d90bcSTrond Myklebust 	dput(dentry);
618810d90bcSTrond Myklebust 	return ret;
619810d90bcSTrond Myklebust }
620810d90bcSTrond Myklebust 
621810d90bcSTrond Myklebust static int __rpc_rmpipe(struct inode *dir, struct dentry *dentry)
622810d90bcSTrond Myklebust {
623c5ef6035SDavid Howells 	struct inode *inode = d_inode(dentry);
624810d90bcSTrond Myklebust 
625810d90bcSTrond Myklebust 	rpc_close_pipes(inode);
626810d90bcSTrond Myklebust 	return __rpc_unlink(dir, dentry);
627810d90bcSTrond Myklebust }
628810d90bcSTrond Myklebust 
629cfeaa4a3STrond Myklebust static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent,
630d3db90b0SAl Viro 					  const char *name)
631cfeaa4a3STrond Myklebust {
632d3db90b0SAl Viro 	struct qstr q = QSTR_INIT(name, strlen(name));
633d3db90b0SAl Viro 	struct dentry *dentry = d_hash_and_lookup(parent, &q);
6345bff0386SStanislav Kinsbursky 	if (!dentry) {
635d3db90b0SAl Viro 		dentry = d_alloc(parent, &q);
6365bff0386SStanislav Kinsbursky 		if (!dentry)
6375bff0386SStanislav Kinsbursky 			return ERR_PTR(-ENOMEM);
6385bff0386SStanislav Kinsbursky 	}
639c5ef6035SDavid Howells 	if (d_really_is_negative(dentry))
640f1f0abe1SDan Carpenter 		return dentry;
641cfeaa4a3STrond Myklebust 	dput(dentry);
642cfeaa4a3STrond Myklebust 	return ERR_PTR(-EEXIST);
643cfeaa4a3STrond Myklebust }
644cfeaa4a3STrond Myklebust 
6451da177e4SLinus Torvalds /*
6461da177e4SLinus Torvalds  * FIXME: This probably has races.
6471da177e4SLinus Torvalds  */
648ac6feceeSTrond Myklebust static void __rpc_depopulate(struct dentry *parent,
649ac6feceeSTrond Myklebust 			     const struct rpc_filelist *files,
650ac6feceeSTrond Myklebust 			     int start, int eof)
6511da177e4SLinus Torvalds {
652c5ef6035SDavid Howells 	struct inode *dir = d_inode(parent);
653ac6feceeSTrond Myklebust 	struct dentry *dentry;
654ac6feceeSTrond Myklebust 	struct qstr name;
655ac6feceeSTrond Myklebust 	int i;
656ac6feceeSTrond Myklebust 
657ac6feceeSTrond Myklebust 	for (i = start; i < eof; i++) {
658ac6feceeSTrond Myklebust 		name.name = files[i].name;
659ac6feceeSTrond Myklebust 		name.len = strlen(files[i].name);
660d3db90b0SAl Viro 		dentry = d_hash_and_lookup(parent, &name);
661ac6feceeSTrond Myklebust 
662ac6feceeSTrond Myklebust 		if (dentry == NULL)
663ac6feceeSTrond Myklebust 			continue;
664c5ef6035SDavid Howells 		if (d_really_is_negative(dentry))
665ac6feceeSTrond Myklebust 			goto next;
666c5ef6035SDavid Howells 		switch (d_inode(dentry)->i_mode & S_IFMT) {
667ac6feceeSTrond Myklebust 			default:
668ac6feceeSTrond Myklebust 				BUG();
669ac6feceeSTrond Myklebust 			case S_IFREG:
670ac6feceeSTrond Myklebust 				__rpc_unlink(dir, dentry);
671ac6feceeSTrond Myklebust 				break;
672ac6feceeSTrond Myklebust 			case S_IFDIR:
673ac6feceeSTrond Myklebust 				__rpc_rmdir(dir, dentry);
674ac6feceeSTrond Myklebust 		}
675ac6feceeSTrond Myklebust next:
676ac6feceeSTrond Myklebust 		dput(dentry);
677ac6feceeSTrond Myklebust 	}
678ac6feceeSTrond Myklebust }
679ac6feceeSTrond Myklebust 
680ac6feceeSTrond Myklebust static void rpc_depopulate(struct dentry *parent,
681ac6feceeSTrond Myklebust 			   const struct rpc_filelist *files,
682ac6feceeSTrond Myklebust 			   int start, int eof)
683ac6feceeSTrond Myklebust {
684c5ef6035SDavid Howells 	struct inode *dir = d_inode(parent);
6851da177e4SLinus Torvalds 
6865955102cSAl Viro 	inode_lock_nested(dir, I_MUTEX_CHILD);
687ac6feceeSTrond Myklebust 	__rpc_depopulate(parent, files, start, eof);
6885955102cSAl Viro 	inode_unlock(dir);
6891da177e4SLinus Torvalds }
6901da177e4SLinus Torvalds 
691ac6feceeSTrond Myklebust static int rpc_populate(struct dentry *parent,
692ac6feceeSTrond Myklebust 			const struct rpc_filelist *files,
693ac6feceeSTrond Myklebust 			int start, int eof,
694ac6feceeSTrond Myklebust 			void *private)
6951da177e4SLinus Torvalds {
696c5ef6035SDavid Howells 	struct inode *dir = d_inode(parent);
6971da177e4SLinus Torvalds 	struct dentry *dentry;
698ac6feceeSTrond Myklebust 	int i, err;
6991da177e4SLinus Torvalds 
7005955102cSAl Viro 	inode_lock(dir);
7011da177e4SLinus Torvalds 	for (i = start; i < eof; i++) {
702d3db90b0SAl Viro 		dentry = __rpc_lookup_create_exclusive(parent, files[i].name);
703ac6feceeSTrond Myklebust 		err = PTR_ERR(dentry);
704ac6feceeSTrond Myklebust 		if (IS_ERR(dentry))
7051da177e4SLinus Torvalds 			goto out_bad;
706ac6feceeSTrond Myklebust 		switch (files[i].mode & S_IFMT) {
707ac6feceeSTrond Myklebust 			default:
708ac6feceeSTrond Myklebust 				BUG();
709ac6feceeSTrond Myklebust 			case S_IFREG:
710ac6feceeSTrond Myklebust 				err = __rpc_create(dir, dentry,
711ac6feceeSTrond Myklebust 						files[i].mode,
712ac6feceeSTrond Myklebust 						files[i].i_fop,
713ac6feceeSTrond Myklebust 						private);
714ac6feceeSTrond Myklebust 				break;
715ac6feceeSTrond Myklebust 			case S_IFDIR:
716ac6feceeSTrond Myklebust 				err = __rpc_mkdir(dir, dentry,
717ac6feceeSTrond Myklebust 						files[i].mode,
718ac6feceeSTrond Myklebust 						NULL,
719ac6feceeSTrond Myklebust 						private);
7201da177e4SLinus Torvalds 		}
721ac6feceeSTrond Myklebust 		if (err != 0)
722ac6feceeSTrond Myklebust 			goto out_bad;
7231da177e4SLinus Torvalds 	}
7245955102cSAl Viro 	inode_unlock(dir);
7251da177e4SLinus Torvalds 	return 0;
7261da177e4SLinus Torvalds out_bad:
727ac6feceeSTrond Myklebust 	__rpc_depopulate(parent, files, start, eof);
7285955102cSAl Viro 	inode_unlock(dir);
7291e903edaSAl Viro 	printk(KERN_WARNING "%s: %s failed to populate directory %pd\n",
7301e903edaSAl Viro 			__FILE__, __func__, parent);
731ac6feceeSTrond Myklebust 	return err;
732f134585aSTrond Myklebust }
733f134585aSTrond Myklebust 
734e57aed77STrond Myklebust static struct dentry *rpc_mkdir_populate(struct dentry *parent,
735a95e691fSAl Viro 		const char *name, umode_t mode, void *private,
736e57aed77STrond Myklebust 		int (*populate)(struct dentry *, void *), void *args_populate)
737f134585aSTrond Myklebust {
738f134585aSTrond Myklebust 	struct dentry *dentry;
739c5ef6035SDavid Howells 	struct inode *dir = d_inode(parent);
740f134585aSTrond Myklebust 	int error;
741f134585aSTrond Myklebust 
7425955102cSAl Viro 	inode_lock_nested(dir, I_MUTEX_PARENT);
7437d59d1e8STrond Myklebust 	dentry = __rpc_lookup_create_exclusive(parent, name);
744f134585aSTrond Myklebust 	if (IS_ERR(dentry))
7457d59d1e8STrond Myklebust 		goto out;
7467d59d1e8STrond Myklebust 	error = __rpc_mkdir(dir, dentry, mode, NULL, private);
7477589806eSTrond Myklebust 	if (error != 0)
7487589806eSTrond Myklebust 		goto out_err;
749e57aed77STrond Myklebust 	if (populate != NULL) {
750e57aed77STrond Myklebust 		error = populate(dentry, args_populate);
751f134585aSTrond Myklebust 		if (error)
752ac6feceeSTrond Myklebust 			goto err_rmdir;
753e57aed77STrond Myklebust 	}
754f134585aSTrond Myklebust out:
7555955102cSAl Viro 	inode_unlock(dir);
7565c3e985aSTrond Myklebust 	return dentry;
757ac6feceeSTrond Myklebust err_rmdir:
758f134585aSTrond Myklebust 	__rpc_rmdir(dir, dentry);
7597589806eSTrond Myklebust out_err:
760f134585aSTrond Myklebust 	dentry = ERR_PTR(error);
761f134585aSTrond Myklebust 	goto out;
762f134585aSTrond Myklebust }
763f134585aSTrond Myklebust 
764e57aed77STrond Myklebust static int rpc_rmdir_depopulate(struct dentry *dentry,
765e57aed77STrond Myklebust 		void (*depopulate)(struct dentry *))
766f134585aSTrond Myklebust {
767dff02cc1STrond Myklebust 	struct dentry *parent;
768f134585aSTrond Myklebust 	struct inode *dir;
769f134585aSTrond Myklebust 	int error;
770f134585aSTrond Myklebust 
771dff02cc1STrond Myklebust 	parent = dget_parent(dentry);
772c5ef6035SDavid Howells 	dir = d_inode(parent);
7735955102cSAl Viro 	inode_lock_nested(dir, I_MUTEX_PARENT);
774e57aed77STrond Myklebust 	if (depopulate != NULL)
775e57aed77STrond Myklebust 		depopulate(dentry);
776f134585aSTrond Myklebust 	error = __rpc_rmdir(dir, dentry);
7775955102cSAl Viro 	inode_unlock(dir);
778dff02cc1STrond Myklebust 	dput(parent);
779f134585aSTrond Myklebust 	return error;
780f134585aSTrond Myklebust }
7811da177e4SLinus Torvalds 
78293a44a75SJ. Bruce Fields /**
78393a44a75SJ. Bruce Fields  * rpc_mkpipe - make an rpc_pipefs file for kernel<->userspace communication
78493a44a75SJ. Bruce Fields  * @parent: dentry of directory to create new "pipe" in
78593a44a75SJ. Bruce Fields  * @name: name of pipe
78693a44a75SJ. Bruce Fields  * @private: private data to associate with the pipe, for the caller's use
787bda14606SRandy Dunlap  * @pipe: &rpc_pipe containing input parameters
78893a44a75SJ. Bruce Fields  *
78993a44a75SJ. Bruce Fields  * Data is made available for userspace to read by calls to
79093a44a75SJ. Bruce Fields  * rpc_queue_upcall().  The actual reads will result in calls to
79193a44a75SJ. Bruce Fields  * @ops->upcall, which will be called with the file pointer,
79293a44a75SJ. Bruce Fields  * message, and userspace buffer to copy to.
79393a44a75SJ. Bruce Fields  *
79493a44a75SJ. Bruce Fields  * Writes can come at any time, and do not necessarily have to be
79593a44a75SJ. Bruce Fields  * responses to upcalls.  They will result in calls to @msg->downcall.
79693a44a75SJ. Bruce Fields  *
79793a44a75SJ. Bruce Fields  * The @private argument passed here will be available to all these methods
798496ad9aaSAl Viro  * from the file pointer, via RPC_I(file_inode(file))->private.
79993a44a75SJ. Bruce Fields  */
800c239d83bSStanislav Kinsbursky struct dentry *rpc_mkpipe_dentry(struct dentry *parent, const char *name,
801c239d83bSStanislav Kinsbursky 				 void *private, struct rpc_pipe *pipe)
8021da177e4SLinus Torvalds {
8031da177e4SLinus Torvalds 	struct dentry *dentry;
804c5ef6035SDavid Howells 	struct inode *dir = d_inode(parent);
805d6444062SJoe Perches 	umode_t umode = S_IFIFO | 0600;
8067589806eSTrond Myklebust 	int err;
8077364af6aSTrond Myklebust 
808c239d83bSStanislav Kinsbursky 	if (pipe->ops->upcall == NULL)
809d6444062SJoe Perches 		umode &= ~0444;
810c239d83bSStanislav Kinsbursky 	if (pipe->ops->downcall == NULL)
811d6444062SJoe Perches 		umode &= ~0222;
8121da177e4SLinus Torvalds 
8135955102cSAl Viro 	inode_lock_nested(dir, I_MUTEX_PARENT);
814d3db90b0SAl Viro 	dentry = __rpc_lookup_create_exclusive(parent, name);
8151da177e4SLinus Torvalds 	if (IS_ERR(dentry))
816cfeaa4a3STrond Myklebust 		goto out;
817c239d83bSStanislav Kinsbursky 	err = __rpc_mkpipe_dentry(dir, dentry, umode, &rpc_pipe_fops,
818c239d83bSStanislav Kinsbursky 				  private, pipe);
8197589806eSTrond Myklebust 	if (err)
8207589806eSTrond Myklebust 		goto out_err;
821f134585aSTrond Myklebust out:
8225955102cSAl Viro 	inode_unlock(dir);
8235c3e985aSTrond Myklebust 	return dentry;
8247589806eSTrond Myklebust out_err:
8257589806eSTrond Myklebust 	dentry = ERR_PTR(err);
8261e903edaSAl Viro 	printk(KERN_WARNING "%s: %s() failed to create pipe %pd/%s (errno = %d)\n",
8271e903edaSAl Viro 			__FILE__, __func__, parent, name,
8287589806eSTrond Myklebust 			err);
829f134585aSTrond Myklebust 	goto out;
8301da177e4SLinus Torvalds }
831c239d83bSStanislav Kinsbursky EXPORT_SYMBOL_GPL(rpc_mkpipe_dentry);
8321da177e4SLinus Torvalds 
83393a44a75SJ. Bruce Fields /**
83493a44a75SJ. Bruce Fields  * rpc_unlink - remove a pipe
83593a44a75SJ. Bruce Fields  * @dentry: dentry for the pipe, as returned from rpc_mkpipe
83693a44a75SJ. Bruce Fields  *
83793a44a75SJ. Bruce Fields  * After this call, lookups will no longer find the pipe, and any
83893a44a75SJ. Bruce Fields  * attempts to read or write using preexisting opens of the pipe will
83993a44a75SJ. Bruce Fields  * return -EPIPE.
84093a44a75SJ. Bruce Fields  */
841f134585aSTrond Myklebust int
8425d67476fSTrond Myklebust rpc_unlink(struct dentry *dentry)
8431da177e4SLinus Torvalds {
8445d67476fSTrond Myklebust 	struct dentry *parent;
845f134585aSTrond Myklebust 	struct inode *dir;
8465d67476fSTrond Myklebust 	int error = 0;
8471da177e4SLinus Torvalds 
8485d67476fSTrond Myklebust 	parent = dget_parent(dentry);
849c5ef6035SDavid Howells 	dir = d_inode(parent);
8505955102cSAl Viro 	inode_lock_nested(dir, I_MUTEX_PARENT);
851810d90bcSTrond Myklebust 	error = __rpc_rmpipe(dir, dentry);
8525955102cSAl Viro 	inode_unlock(dir);
8535d67476fSTrond Myklebust 	dput(parent);
854f134585aSTrond Myklebust 	return error;
8551da177e4SLinus Torvalds }
856468039eeSTrond Myklebust EXPORT_SYMBOL_GPL(rpc_unlink);
8571da177e4SLinus Torvalds 
8586739ffb7STrond Myklebust /**
8596739ffb7STrond Myklebust  * rpc_init_pipe_dir_head - initialise a struct rpc_pipe_dir_head
8606739ffb7STrond Myklebust  * @pdh: pointer to struct rpc_pipe_dir_head
8616739ffb7STrond Myklebust  */
8626739ffb7STrond Myklebust void rpc_init_pipe_dir_head(struct rpc_pipe_dir_head *pdh)
8636739ffb7STrond Myklebust {
8646739ffb7STrond Myklebust 	INIT_LIST_HEAD(&pdh->pdh_entries);
8656739ffb7STrond Myklebust 	pdh->pdh_dentry = NULL;
8666739ffb7STrond Myklebust }
8676739ffb7STrond Myklebust EXPORT_SYMBOL_GPL(rpc_init_pipe_dir_head);
8686739ffb7STrond Myklebust 
8696739ffb7STrond Myklebust /**
8706739ffb7STrond Myklebust  * rpc_init_pipe_dir_object - initialise a struct rpc_pipe_dir_object
8716739ffb7STrond Myklebust  * @pdo: pointer to struct rpc_pipe_dir_object
8726739ffb7STrond Myklebust  * @pdo_ops: pointer to const struct rpc_pipe_dir_object_ops
8736739ffb7STrond Myklebust  * @pdo_data: pointer to caller-defined data
8746739ffb7STrond Myklebust  */
8756739ffb7STrond Myklebust void rpc_init_pipe_dir_object(struct rpc_pipe_dir_object *pdo,
8766739ffb7STrond Myklebust 		const struct rpc_pipe_dir_object_ops *pdo_ops,
8776739ffb7STrond Myklebust 		void *pdo_data)
8786739ffb7STrond Myklebust {
8796739ffb7STrond Myklebust 	INIT_LIST_HEAD(&pdo->pdo_head);
8806739ffb7STrond Myklebust 	pdo->pdo_ops = pdo_ops;
8816739ffb7STrond Myklebust 	pdo->pdo_data = pdo_data;
8826739ffb7STrond Myklebust }
8836739ffb7STrond Myklebust EXPORT_SYMBOL_GPL(rpc_init_pipe_dir_object);
8846739ffb7STrond Myklebust 
8856739ffb7STrond Myklebust static int
8866739ffb7STrond Myklebust rpc_add_pipe_dir_object_locked(struct net *net,
8876739ffb7STrond Myklebust 		struct rpc_pipe_dir_head *pdh,
8886739ffb7STrond Myklebust 		struct rpc_pipe_dir_object *pdo)
8896739ffb7STrond Myklebust {
8906739ffb7STrond Myklebust 	int ret = 0;
8916739ffb7STrond Myklebust 
8926739ffb7STrond Myklebust 	if (pdh->pdh_dentry)
8936739ffb7STrond Myklebust 		ret = pdo->pdo_ops->create(pdh->pdh_dentry, pdo);
8946739ffb7STrond Myklebust 	if (ret == 0)
8956739ffb7STrond Myklebust 		list_add_tail(&pdo->pdo_head, &pdh->pdh_entries);
8966739ffb7STrond Myklebust 	return ret;
8976739ffb7STrond Myklebust }
8986739ffb7STrond Myklebust 
8996739ffb7STrond Myklebust static void
9006739ffb7STrond Myklebust rpc_remove_pipe_dir_object_locked(struct net *net,
9016739ffb7STrond Myklebust 		struct rpc_pipe_dir_head *pdh,
9026739ffb7STrond Myklebust 		struct rpc_pipe_dir_object *pdo)
9036739ffb7STrond Myklebust {
9046739ffb7STrond Myklebust 	if (pdh->pdh_dentry)
9056739ffb7STrond Myklebust 		pdo->pdo_ops->destroy(pdh->pdh_dentry, pdo);
9066739ffb7STrond Myklebust 	list_del_init(&pdo->pdo_head);
9076739ffb7STrond Myklebust }
9086739ffb7STrond Myklebust 
9096739ffb7STrond Myklebust /**
9106739ffb7STrond Myklebust  * rpc_add_pipe_dir_object - associate a rpc_pipe_dir_object to a directory
9116739ffb7STrond Myklebust  * @net: pointer to struct net
9126739ffb7STrond Myklebust  * @pdh: pointer to struct rpc_pipe_dir_head
9136739ffb7STrond Myklebust  * @pdo: pointer to struct rpc_pipe_dir_object
9146739ffb7STrond Myklebust  *
9156739ffb7STrond Myklebust  */
9166739ffb7STrond Myklebust int
9176739ffb7STrond Myklebust rpc_add_pipe_dir_object(struct net *net,
9186739ffb7STrond Myklebust 		struct rpc_pipe_dir_head *pdh,
9196739ffb7STrond Myklebust 		struct rpc_pipe_dir_object *pdo)
9206739ffb7STrond Myklebust {
9216739ffb7STrond Myklebust 	int ret = 0;
9226739ffb7STrond Myklebust 
9236739ffb7STrond Myklebust 	if (list_empty(&pdo->pdo_head)) {
9246739ffb7STrond Myklebust 		struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
9256739ffb7STrond Myklebust 
9266739ffb7STrond Myklebust 		mutex_lock(&sn->pipefs_sb_lock);
9276739ffb7STrond Myklebust 		ret = rpc_add_pipe_dir_object_locked(net, pdh, pdo);
9286739ffb7STrond Myklebust 		mutex_unlock(&sn->pipefs_sb_lock);
9296739ffb7STrond Myklebust 	}
9306739ffb7STrond Myklebust 	return ret;
9316739ffb7STrond Myklebust }
9326739ffb7STrond Myklebust EXPORT_SYMBOL_GPL(rpc_add_pipe_dir_object);
9336739ffb7STrond Myklebust 
9346739ffb7STrond Myklebust /**
9356739ffb7STrond Myklebust  * rpc_remove_pipe_dir_object - remove a rpc_pipe_dir_object from a directory
9366739ffb7STrond Myklebust  * @net: pointer to struct net
9376739ffb7STrond Myklebust  * @pdh: pointer to struct rpc_pipe_dir_head
9386739ffb7STrond Myklebust  * @pdo: pointer to struct rpc_pipe_dir_object
9396739ffb7STrond Myklebust  *
9406739ffb7STrond Myklebust  */
9416739ffb7STrond Myklebust void
9426739ffb7STrond Myklebust rpc_remove_pipe_dir_object(struct net *net,
9436739ffb7STrond Myklebust 		struct rpc_pipe_dir_head *pdh,
9446739ffb7STrond Myklebust 		struct rpc_pipe_dir_object *pdo)
9456739ffb7STrond Myklebust {
9466739ffb7STrond Myklebust 	if (!list_empty(&pdo->pdo_head)) {
9476739ffb7STrond Myklebust 		struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
9486739ffb7STrond Myklebust 
9496739ffb7STrond Myklebust 		mutex_lock(&sn->pipefs_sb_lock);
9506739ffb7STrond Myklebust 		rpc_remove_pipe_dir_object_locked(net, pdh, pdo);
9516739ffb7STrond Myklebust 		mutex_unlock(&sn->pipefs_sb_lock);
9526739ffb7STrond Myklebust 	}
9536739ffb7STrond Myklebust }
9546739ffb7STrond Myklebust EXPORT_SYMBOL_GPL(rpc_remove_pipe_dir_object);
9556739ffb7STrond Myklebust 
956298fc355STrond Myklebust /**
957298fc355STrond Myklebust  * rpc_find_or_alloc_pipe_dir_object
958298fc355STrond Myklebust  * @net: pointer to struct net
959298fc355STrond Myklebust  * @pdh: pointer to struct rpc_pipe_dir_head
960298fc355STrond Myklebust  * @match: match struct rpc_pipe_dir_object to data
961298fc355STrond Myklebust  * @alloc: allocate a new struct rpc_pipe_dir_object
962298fc355STrond Myklebust  * @data: user defined data for match() and alloc()
963298fc355STrond Myklebust  *
964298fc355STrond Myklebust  */
965298fc355STrond Myklebust struct rpc_pipe_dir_object *
966298fc355STrond Myklebust rpc_find_or_alloc_pipe_dir_object(struct net *net,
967298fc355STrond Myklebust 		struct rpc_pipe_dir_head *pdh,
968298fc355STrond Myklebust 		int (*match)(struct rpc_pipe_dir_object *, void *),
969298fc355STrond Myklebust 		struct rpc_pipe_dir_object *(*alloc)(void *),
970298fc355STrond Myklebust 		void *data)
971298fc355STrond Myklebust {
972298fc355STrond Myklebust 	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
973298fc355STrond Myklebust 	struct rpc_pipe_dir_object *pdo;
974298fc355STrond Myklebust 
975298fc355STrond Myklebust 	mutex_lock(&sn->pipefs_sb_lock);
976298fc355STrond Myklebust 	list_for_each_entry(pdo, &pdh->pdh_entries, pdo_head) {
977298fc355STrond Myklebust 		if (!match(pdo, data))
978298fc355STrond Myklebust 			continue;
979298fc355STrond Myklebust 		goto out;
980298fc355STrond Myklebust 	}
981298fc355STrond Myklebust 	pdo = alloc(data);
982298fc355STrond Myklebust 	if (!pdo)
983298fc355STrond Myklebust 		goto out;
984298fc355STrond Myklebust 	rpc_add_pipe_dir_object_locked(net, pdh, pdo);
985298fc355STrond Myklebust out:
986298fc355STrond Myklebust 	mutex_unlock(&sn->pipefs_sb_lock);
987298fc355STrond Myklebust 	return pdo;
988298fc355STrond Myklebust }
989298fc355STrond Myklebust EXPORT_SYMBOL_GPL(rpc_find_or_alloc_pipe_dir_object);
990298fc355STrond Myklebust 
9916739ffb7STrond Myklebust static void
9926739ffb7STrond Myklebust rpc_create_pipe_dir_objects(struct rpc_pipe_dir_head *pdh)
9936739ffb7STrond Myklebust {
9946739ffb7STrond Myklebust 	struct rpc_pipe_dir_object *pdo;
9956739ffb7STrond Myklebust 	struct dentry *dir = pdh->pdh_dentry;
9966739ffb7STrond Myklebust 
9976739ffb7STrond Myklebust 	list_for_each_entry(pdo, &pdh->pdh_entries, pdo_head)
9986739ffb7STrond Myklebust 		pdo->pdo_ops->create(dir, pdo);
9996739ffb7STrond Myklebust }
10006739ffb7STrond Myklebust 
10016739ffb7STrond Myklebust static void
10026739ffb7STrond Myklebust rpc_destroy_pipe_dir_objects(struct rpc_pipe_dir_head *pdh)
10036739ffb7STrond Myklebust {
10046739ffb7STrond Myklebust 	struct rpc_pipe_dir_object *pdo;
10056739ffb7STrond Myklebust 	struct dentry *dir = pdh->pdh_dentry;
10066739ffb7STrond Myklebust 
10076739ffb7STrond Myklebust 	list_for_each_entry(pdo, &pdh->pdh_entries, pdo_head)
10086739ffb7STrond Myklebust 		pdo->pdo_ops->destroy(dir, pdo);
10096739ffb7STrond Myklebust }
10106739ffb7STrond Myklebust 
1011e57aed77STrond Myklebust enum {
1012e57aed77STrond Myklebust 	RPCAUTH_info,
1013e57aed77STrond Myklebust 	RPCAUTH_EOF
1014e57aed77STrond Myklebust };
1015e57aed77STrond Myklebust 
1016e57aed77STrond Myklebust static const struct rpc_filelist authfiles[] = {
1017e57aed77STrond Myklebust 	[RPCAUTH_info] = {
1018e57aed77STrond Myklebust 		.name = "info",
1019e57aed77STrond Myklebust 		.i_fop = &rpc_info_operations,
1020d6444062SJoe Perches 		.mode = S_IFREG | 0400,
1021e57aed77STrond Myklebust 	},
1022e57aed77STrond Myklebust };
1023e57aed77STrond Myklebust 
1024e57aed77STrond Myklebust static int rpc_clntdir_populate(struct dentry *dentry, void *private)
1025e57aed77STrond Myklebust {
1026e57aed77STrond Myklebust 	return rpc_populate(dentry,
1027e57aed77STrond Myklebust 			    authfiles, RPCAUTH_info, RPCAUTH_EOF,
1028e57aed77STrond Myklebust 			    private);
1029e57aed77STrond Myklebust }
1030e57aed77STrond Myklebust 
1031e57aed77STrond Myklebust static void rpc_clntdir_depopulate(struct dentry *dentry)
1032e57aed77STrond Myklebust {
1033e57aed77STrond Myklebust 	rpc_depopulate(dentry, authfiles, RPCAUTH_info, RPCAUTH_EOF);
1034e57aed77STrond Myklebust }
1035e57aed77STrond Myklebust 
10367d59d1e8STrond Myklebust /**
10377d59d1e8STrond Myklebust  * rpc_create_client_dir - Create a new rpc_client directory in rpc_pipefs
1038a95e691fSAl Viro  * @dentry: the parent of new directory
1039a95e691fSAl Viro  * @name: the name of new directory
10407d59d1e8STrond Myklebust  * @rpc_client: rpc client to associate with this directory
10417d59d1e8STrond Myklebust  *
10427d59d1e8STrond Myklebust  * This creates a directory at the given @path associated with
10437d59d1e8STrond Myklebust  * @rpc_clnt, which will contain a file named "info" with some basic
10447d59d1e8STrond Myklebust  * information about the client, together with any "pipes" that may
10457d59d1e8STrond Myklebust  * later be created using rpc_mkpipe().
10467d59d1e8STrond Myklebust  */
104723ac6581STrond Myklebust struct dentry *rpc_create_client_dir(struct dentry *dentry,
1048a95e691fSAl Viro 				   const char *name,
10497d59d1e8STrond Myklebust 				   struct rpc_clnt *rpc_client)
10507d59d1e8STrond Myklebust {
10516739ffb7STrond Myklebust 	struct dentry *ret;
10526739ffb7STrond Myklebust 
1053d6444062SJoe Perches 	ret = rpc_mkdir_populate(dentry, name, 0555, NULL,
1054e57aed77STrond Myklebust 				 rpc_clntdir_populate, rpc_client);
10556739ffb7STrond Myklebust 	if (!IS_ERR(ret)) {
10566739ffb7STrond Myklebust 		rpc_client->cl_pipedir_objects.pdh_dentry = ret;
10576739ffb7STrond Myklebust 		rpc_create_pipe_dir_objects(&rpc_client->cl_pipedir_objects);
10586739ffb7STrond Myklebust 	}
10596739ffb7STrond Myklebust 	return ret;
1060e57aed77STrond Myklebust }
1061e57aed77STrond Myklebust 
1062e57aed77STrond Myklebust /**
1063e57aed77STrond Myklebust  * rpc_remove_client_dir - Remove a directory created with rpc_create_client_dir()
10646739ffb7STrond Myklebust  * @rpc_client: rpc_client for the pipe
1065e57aed77STrond Myklebust  */
1066c36dcfe1STrond Myklebust int rpc_remove_client_dir(struct rpc_clnt *rpc_client)
1067e57aed77STrond Myklebust {
1068c36dcfe1STrond Myklebust 	struct dentry *dentry = rpc_client->cl_pipedir_objects.pdh_dentry;
1069c36dcfe1STrond Myklebust 
1070c36dcfe1STrond Myklebust 	if (dentry == NULL)
1071c36dcfe1STrond Myklebust 		return 0;
10726739ffb7STrond Myklebust 	rpc_destroy_pipe_dir_objects(&rpc_client->cl_pipedir_objects);
10736739ffb7STrond Myklebust 	rpc_client->cl_pipedir_objects.pdh_dentry = NULL;
1074e57aed77STrond Myklebust 	return rpc_rmdir_depopulate(dentry, rpc_clntdir_depopulate);
10757d59d1e8STrond Myklebust }
10767d59d1e8STrond Myklebust 
10778854e82dSTrond Myklebust static const struct rpc_filelist cache_pipefs_files[3] = {
10788854e82dSTrond Myklebust 	[0] = {
10798854e82dSTrond Myklebust 		.name = "channel",
10808854e82dSTrond Myklebust 		.i_fop = &cache_file_operations_pipefs,
1081d6444062SJoe Perches 		.mode = S_IFREG | 0600,
10828854e82dSTrond Myklebust 	},
10838854e82dSTrond Myklebust 	[1] = {
10848854e82dSTrond Myklebust 		.name = "content",
10858854e82dSTrond Myklebust 		.i_fop = &content_file_operations_pipefs,
1086d6444062SJoe Perches 		.mode = S_IFREG | 0400,
10878854e82dSTrond Myklebust 	},
10888854e82dSTrond Myklebust 	[2] = {
10898854e82dSTrond Myklebust 		.name = "flush",
10908854e82dSTrond Myklebust 		.i_fop = &cache_flush_operations_pipefs,
1091d6444062SJoe Perches 		.mode = S_IFREG | 0600,
10928854e82dSTrond Myklebust 	},
10938854e82dSTrond Myklebust };
10948854e82dSTrond Myklebust 
10958854e82dSTrond Myklebust static int rpc_cachedir_populate(struct dentry *dentry, void *private)
10968854e82dSTrond Myklebust {
10978854e82dSTrond Myklebust 	return rpc_populate(dentry,
10988854e82dSTrond Myklebust 			    cache_pipefs_files, 0, 3,
10998854e82dSTrond Myklebust 			    private);
11008854e82dSTrond Myklebust }
11018854e82dSTrond Myklebust 
11028854e82dSTrond Myklebust static void rpc_cachedir_depopulate(struct dentry *dentry)
11038854e82dSTrond Myklebust {
11048854e82dSTrond Myklebust 	rpc_depopulate(dentry, cache_pipefs_files, 0, 3);
11058854e82dSTrond Myklebust }
11068854e82dSTrond Myklebust 
1107a95e691fSAl Viro struct dentry *rpc_create_cache_dir(struct dentry *parent, const char *name,
110864f1426fSAl Viro 				    umode_t umode, struct cache_detail *cd)
11098854e82dSTrond Myklebust {
11108854e82dSTrond Myklebust 	return rpc_mkdir_populate(parent, name, umode, NULL,
11118854e82dSTrond Myklebust 			rpc_cachedir_populate, cd);
11128854e82dSTrond Myklebust }
11138854e82dSTrond Myklebust 
11148854e82dSTrond Myklebust void rpc_remove_cache_dir(struct dentry *dentry)
11158854e82dSTrond Myklebust {
11168854e82dSTrond Myklebust 	rpc_rmdir_depopulate(dentry, rpc_cachedir_depopulate);
11178854e82dSTrond Myklebust }
11188854e82dSTrond Myklebust 
11191da177e4SLinus Torvalds /*
11201da177e4SLinus Torvalds  * populate the filesystem
11211da177e4SLinus Torvalds  */
1122b87221deSAlexey Dobriyan static const struct super_operations s_ops = {
11231da177e4SLinus Torvalds 	.alloc_inode	= rpc_alloc_inode,
1124bef252faSAl Viro 	.free_inode	= rpc_free_inode,
11251da177e4SLinus Torvalds 	.statfs		= simple_statfs,
11261da177e4SLinus Torvalds };
11271da177e4SLinus Torvalds 
11281da177e4SLinus Torvalds #define RPCAUTH_GSSMAGIC 0x67596969
11291da177e4SLinus Torvalds 
1130bb156749STrond Myklebust /*
1131bb156749STrond Myklebust  * We have a single directory with 1 node in it.
1132bb156749STrond Myklebust  */
1133bb156749STrond Myklebust enum {
1134bb156749STrond Myklebust 	RPCAUTH_lockd,
1135bb156749STrond Myklebust 	RPCAUTH_mount,
1136bb156749STrond Myklebust 	RPCAUTH_nfs,
1137bb156749STrond Myklebust 	RPCAUTH_portmap,
1138bb156749STrond Myklebust 	RPCAUTH_statd,
1139bb156749STrond Myklebust 	RPCAUTH_nfsd4_cb,
1140e571cbf1STrond Myklebust 	RPCAUTH_cache,
1141b3537c35SJeff Layton 	RPCAUTH_nfsd,
11424b9a445eSJeff Layton 	RPCAUTH_gssd,
1143bb156749STrond Myklebust 	RPCAUTH_RootEOF
1144bb156749STrond Myklebust };
1145bb156749STrond Myklebust 
1146bb156749STrond Myklebust static const struct rpc_filelist files[] = {
1147bb156749STrond Myklebust 	[RPCAUTH_lockd] = {
1148bb156749STrond Myklebust 		.name = "lockd",
1149d6444062SJoe Perches 		.mode = S_IFDIR | 0555,
1150bb156749STrond Myklebust 	},
1151bb156749STrond Myklebust 	[RPCAUTH_mount] = {
1152bb156749STrond Myklebust 		.name = "mount",
1153d6444062SJoe Perches 		.mode = S_IFDIR | 0555,
1154bb156749STrond Myklebust 	},
1155bb156749STrond Myklebust 	[RPCAUTH_nfs] = {
1156bb156749STrond Myklebust 		.name = "nfs",
1157d6444062SJoe Perches 		.mode = S_IFDIR | 0555,
1158bb156749STrond Myklebust 	},
1159bb156749STrond Myklebust 	[RPCAUTH_portmap] = {
1160bb156749STrond Myklebust 		.name = "portmap",
1161d6444062SJoe Perches 		.mode = S_IFDIR | 0555,
1162bb156749STrond Myklebust 	},
1163bb156749STrond Myklebust 	[RPCAUTH_statd] = {
1164bb156749STrond Myklebust 		.name = "statd",
1165d6444062SJoe Perches 		.mode = S_IFDIR | 0555,
1166bb156749STrond Myklebust 	},
1167bb156749STrond Myklebust 	[RPCAUTH_nfsd4_cb] = {
1168bb156749STrond Myklebust 		.name = "nfsd4_cb",
1169d6444062SJoe Perches 		.mode = S_IFDIR | 0555,
1170bb156749STrond Myklebust 	},
1171e571cbf1STrond Myklebust 	[RPCAUTH_cache] = {
1172e571cbf1STrond Myklebust 		.name = "cache",
1173d6444062SJoe Perches 		.mode = S_IFDIR | 0555,
1174e571cbf1STrond Myklebust 	},
1175b3537c35SJeff Layton 	[RPCAUTH_nfsd] = {
1176b3537c35SJeff Layton 		.name = "nfsd",
1177d6444062SJoe Perches 		.mode = S_IFDIR | 0555,
1178b3537c35SJeff Layton 	},
11794b9a445eSJeff Layton 	[RPCAUTH_gssd] = {
11804b9a445eSJeff Layton 		.name = "gssd",
1181d6444062SJoe Perches 		.mode = S_IFDIR | 0555,
11824b9a445eSJeff Layton 	},
1183bb156749STrond Myklebust };
1184bb156749STrond Myklebust 
1185432eb1a5SStanislav Kinsbursky /*
1186432eb1a5SStanislav Kinsbursky  * This call can be used only in RPC pipefs mount notification hooks.
1187432eb1a5SStanislav Kinsbursky  */
1188432eb1a5SStanislav Kinsbursky struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
1189432eb1a5SStanislav Kinsbursky 			       const unsigned char *dir_name)
1190432eb1a5SStanislav Kinsbursky {
119126fe5750SLinus Torvalds 	struct qstr dir = QSTR_INIT(dir_name, strlen(dir_name));
1192d3db90b0SAl Viro 	return d_hash_and_lookup(sb->s_root, &dir);
1193432eb1a5SStanislav Kinsbursky }
1194432eb1a5SStanislav Kinsbursky EXPORT_SYMBOL_GPL(rpc_d_lookup_sb);
1195432eb1a5SStanislav Kinsbursky 
11964b9a445eSJeff Layton int rpc_pipefs_init_net(struct net *net)
1197c21a588fSStanislav Kinsbursky {
1198c21a588fSStanislav Kinsbursky 	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1199c21a588fSStanislav Kinsbursky 
12004b9a445eSJeff Layton 	sn->gssd_dummy = rpc_mkpipe_data(&gssd_dummy_pipe_ops, 0);
12014b9a445eSJeff Layton 	if (IS_ERR(sn->gssd_dummy))
12024b9a445eSJeff Layton 		return PTR_ERR(sn->gssd_dummy);
12034b9a445eSJeff Layton 
1204c21a588fSStanislav Kinsbursky 	mutex_init(&sn->pipefs_sb_lock);
12052aed8b47STrond Myklebust 	sn->pipe_version = -1;
12064b9a445eSJeff Layton 	return 0;
12074b9a445eSJeff Layton }
12084b9a445eSJeff Layton 
12094b9a445eSJeff Layton void rpc_pipefs_exit_net(struct net *net)
12104b9a445eSJeff Layton {
12114b9a445eSJeff Layton 	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
12124b9a445eSJeff Layton 
12134b9a445eSJeff Layton 	rpc_destroy_pipe_data(sn->gssd_dummy);
1214c21a588fSStanislav Kinsbursky }
1215c21a588fSStanislav Kinsbursky 
1216c21a588fSStanislav Kinsbursky /*
1217c21a588fSStanislav Kinsbursky  * This call will be used for per network namespace operations calls.
1218c21a588fSStanislav Kinsbursky  * Note: Function will be returned with pipefs_sb_lock taken if superblock was
1219c21a588fSStanislav Kinsbursky  * found. This lock have to be released by rpc_put_sb_net() when all operations
1220c21a588fSStanislav Kinsbursky  * will be completed.
1221c21a588fSStanislav Kinsbursky  */
1222c21a588fSStanislav Kinsbursky struct super_block *rpc_get_sb_net(const struct net *net)
1223c21a588fSStanislav Kinsbursky {
1224c21a588fSStanislav Kinsbursky 	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1225c21a588fSStanislav Kinsbursky 
1226c21a588fSStanislav Kinsbursky 	mutex_lock(&sn->pipefs_sb_lock);
1227c21a588fSStanislav Kinsbursky 	if (sn->pipefs_sb)
1228c21a588fSStanislav Kinsbursky 		return sn->pipefs_sb;
1229c21a588fSStanislav Kinsbursky 	mutex_unlock(&sn->pipefs_sb_lock);
1230c21a588fSStanislav Kinsbursky 	return NULL;
1231c21a588fSStanislav Kinsbursky }
1232c21a588fSStanislav Kinsbursky EXPORT_SYMBOL_GPL(rpc_get_sb_net);
1233c21a588fSStanislav Kinsbursky 
1234c21a588fSStanislav Kinsbursky void rpc_put_sb_net(const struct net *net)
1235c21a588fSStanislav Kinsbursky {
1236c21a588fSStanislav Kinsbursky 	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1237c21a588fSStanislav Kinsbursky 
1238749386e9SWeston Andros Adamson 	WARN_ON(sn->pipefs_sb == NULL);
1239c21a588fSStanislav Kinsbursky 	mutex_unlock(&sn->pipefs_sb_lock);
1240c21a588fSStanislav Kinsbursky }
1241c21a588fSStanislav Kinsbursky EXPORT_SYMBOL_GPL(rpc_put_sb_net);
1242c21a588fSStanislav Kinsbursky 
12434b9a445eSJeff Layton static const struct rpc_filelist gssd_dummy_clnt_dir[] = {
12444b9a445eSJeff Layton 	[0] = {
12454b9a445eSJeff Layton 		.name = "clntXX",
1246d6444062SJoe Perches 		.mode = S_IFDIR | 0555,
12474b9a445eSJeff Layton 	},
12484b9a445eSJeff Layton };
12494b9a445eSJeff Layton 
12504b9a445eSJeff Layton static ssize_t
12514b9a445eSJeff Layton dummy_downcall(struct file *filp, const char __user *src, size_t len)
12524b9a445eSJeff Layton {
12534b9a445eSJeff Layton 	return -EINVAL;
12544b9a445eSJeff Layton }
12554b9a445eSJeff Layton 
12564b9a445eSJeff Layton static const struct rpc_pipe_ops gssd_dummy_pipe_ops = {
12574b9a445eSJeff Layton 	.upcall		= rpc_pipe_generic_upcall,
12584b9a445eSJeff Layton 	.downcall	= dummy_downcall,
12594b9a445eSJeff Layton };
12604b9a445eSJeff Layton 
1261e2f0c83aSJeff Layton /*
1262e2f0c83aSJeff Layton  * Here we present a bogus "info" file to keep rpc.gssd happy. We don't expect
1263e2f0c83aSJeff Layton  * that it will ever use this info to handle an upcall, but rpc.gssd expects
1264e2f0c83aSJeff Layton  * that this file will be there and have a certain format.
1265e2f0c83aSJeff Layton  */
1266e2f0c83aSJeff Layton static int
1267260f71efSYangtao Li rpc_dummy_info_show(struct seq_file *m, void *v)
1268e2f0c83aSJeff Layton {
1269e2f0c83aSJeff Layton 	seq_printf(m, "RPC server: %s\n", utsname()->nodename);
1270e2f0c83aSJeff Layton 	seq_printf(m, "service: foo (1) version 0\n");
1271e2f0c83aSJeff Layton 	seq_printf(m, "address: 127.0.0.1\n");
1272e2f0c83aSJeff Layton 	seq_printf(m, "protocol: tcp\n");
1273e2f0c83aSJeff Layton 	seq_printf(m, "port: 0\n");
1274e2f0c83aSJeff Layton 	return 0;
1275e2f0c83aSJeff Layton }
1276260f71efSYangtao Li DEFINE_SHOW_ATTRIBUTE(rpc_dummy_info);
1277e2f0c83aSJeff Layton 
1278e2f0c83aSJeff Layton static const struct rpc_filelist gssd_dummy_info_file[] = {
1279e2f0c83aSJeff Layton 	[0] = {
1280e2f0c83aSJeff Layton 		.name = "info",
1281260f71efSYangtao Li 		.i_fop = &rpc_dummy_info_fops,
1282d6444062SJoe Perches 		.mode = S_IFREG | 0400,
1283e2f0c83aSJeff Layton 	},
1284e2f0c83aSJeff Layton };
1285e2f0c83aSJeff Layton 
12864b9a445eSJeff Layton /**
12874b9a445eSJeff Layton  * rpc_gssd_dummy_populate - create a dummy gssd pipe
12884b9a445eSJeff Layton  * @root:	root of the rpc_pipefs filesystem
12894b9a445eSJeff Layton  * @pipe_data:	pipe data created when netns is initialized
12904b9a445eSJeff Layton  *
12914b9a445eSJeff Layton  * Create a dummy set of directories and a pipe that gssd can hold open to
12924b9a445eSJeff Layton  * indicate that it is up and running.
12934b9a445eSJeff Layton  */
12944b9a445eSJeff Layton static struct dentry *
12954b9a445eSJeff Layton rpc_gssd_dummy_populate(struct dentry *root, struct rpc_pipe *pipe_data)
12964b9a445eSJeff Layton {
12974b9a445eSJeff Layton 	int ret = 0;
12984b9a445eSJeff Layton 	struct dentry *gssd_dentry;
12994b9a445eSJeff Layton 	struct dentry *clnt_dentry = NULL;
13004b9a445eSJeff Layton 	struct dentry *pipe_dentry = NULL;
13014b9a445eSJeff Layton 	struct qstr q = QSTR_INIT(files[RPCAUTH_gssd].name,
13024b9a445eSJeff Layton 				  strlen(files[RPCAUTH_gssd].name));
13034b9a445eSJeff Layton 
13044b9a445eSJeff Layton 	/* We should never get this far if "gssd" doesn't exist */
13054b9a445eSJeff Layton 	gssd_dentry = d_hash_and_lookup(root, &q);
13064b9a445eSJeff Layton 	if (!gssd_dentry)
13074b9a445eSJeff Layton 		return ERR_PTR(-ENOENT);
13084b9a445eSJeff Layton 
13094b9a445eSJeff Layton 	ret = rpc_populate(gssd_dentry, gssd_dummy_clnt_dir, 0, 1, NULL);
13104b9a445eSJeff Layton 	if (ret) {
13114b9a445eSJeff Layton 		pipe_dentry = ERR_PTR(ret);
13124b9a445eSJeff Layton 		goto out;
13134b9a445eSJeff Layton 	}
13144b9a445eSJeff Layton 
13154b9a445eSJeff Layton 	q.name = gssd_dummy_clnt_dir[0].name;
13164b9a445eSJeff Layton 	q.len = strlen(gssd_dummy_clnt_dir[0].name);
13174b9a445eSJeff Layton 	clnt_dentry = d_hash_and_lookup(gssd_dentry, &q);
13184b9a445eSJeff Layton 	if (!clnt_dentry) {
13194b9a445eSJeff Layton 		pipe_dentry = ERR_PTR(-ENOENT);
13204b9a445eSJeff Layton 		goto out;
13214b9a445eSJeff Layton 	}
13224b9a445eSJeff Layton 
1323e2f0c83aSJeff Layton 	ret = rpc_populate(clnt_dentry, gssd_dummy_info_file, 0, 1, NULL);
1324e2f0c83aSJeff Layton 	if (ret) {
13253396f92fSJeff Layton 		__rpc_depopulate(gssd_dentry, gssd_dummy_clnt_dir, 0, 1);
1326e2f0c83aSJeff Layton 		pipe_dentry = ERR_PTR(ret);
1327e2f0c83aSJeff Layton 		goto out;
1328e2f0c83aSJeff Layton 	}
1329e2f0c83aSJeff Layton 
1330e2f0c83aSJeff Layton 	pipe_dentry = rpc_mkpipe_dentry(clnt_dentry, "gssd", NULL, pipe_data);
1331e2f0c83aSJeff Layton 	if (IS_ERR(pipe_dentry)) {
1332e2f0c83aSJeff Layton 		__rpc_depopulate(clnt_dentry, gssd_dummy_info_file, 0, 1);
1333e2f0c83aSJeff Layton 		__rpc_depopulate(gssd_dentry, gssd_dummy_clnt_dir, 0, 1);
1334e2f0c83aSJeff Layton 	}
13354b9a445eSJeff Layton out:
13364b9a445eSJeff Layton 	dput(clnt_dentry);
13374b9a445eSJeff Layton 	dput(gssd_dentry);
13384b9a445eSJeff Layton 	return pipe_dentry;
13394b9a445eSJeff Layton }
13404b9a445eSJeff Layton 
134123e66ba9SJeff Layton static void
134223e66ba9SJeff Layton rpc_gssd_dummy_depopulate(struct dentry *pipe_dentry)
134323e66ba9SJeff Layton {
134423e66ba9SJeff Layton 	struct dentry *clnt_dir = pipe_dentry->d_parent;
134523e66ba9SJeff Layton 	struct dentry *gssd_dir = clnt_dir->d_parent;
134623e66ba9SJeff Layton 
13474a3877c4SAl Viro 	dget(pipe_dentry);
1348c5ef6035SDavid Howells 	__rpc_rmpipe(d_inode(clnt_dir), pipe_dentry);
134923e66ba9SJeff Layton 	__rpc_depopulate(clnt_dir, gssd_dummy_info_file, 0, 1);
135023e66ba9SJeff Layton 	__rpc_depopulate(gssd_dir, gssd_dummy_clnt_dir, 0, 1);
135123e66ba9SJeff Layton 	dput(pipe_dentry);
135223e66ba9SJeff Layton }
135323e66ba9SJeff Layton 
13541da177e4SLinus Torvalds static int
13551da177e4SLinus Torvalds rpc_fill_super(struct super_block *sb, void *data, int silent)
13561da177e4SLinus Torvalds {
13571da177e4SLinus Torvalds 	struct inode *inode;
13584b9a445eSJeff Layton 	struct dentry *root, *gssd_dentry;
1359d91ee87dSEric W. Biederman 	struct net *net = get_net(sb->s_fs_info);
136090c4e829SStanislav Kinsbursky 	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
13612d00131aSStanislav Kinsbursky 	int err;
13621da177e4SLinus Torvalds 
136309cbfeafSKirill A. Shutemov 	sb->s_blocksize = PAGE_SIZE;
136409cbfeafSKirill A. Shutemov 	sb->s_blocksize_bits = PAGE_SHIFT;
13651da177e4SLinus Torvalds 	sb->s_magic = RPCAUTH_GSSMAGIC;
13661da177e4SLinus Torvalds 	sb->s_op = &s_ops;
1367b26d4cd3SAl Viro 	sb->s_d_op = &simple_dentry_operations;
13681da177e4SLinus Torvalds 	sb->s_time_gran = 1;
13691da177e4SLinus Torvalds 
1370d6444062SJoe Perches 	inode = rpc_get_inode(sb, S_IFDIR | 0555);
137148fde701SAl Viro 	sb->s_root = root = d_make_root(inode);
137248fde701SAl Viro 	if (!root)
13731da177e4SLinus Torvalds 		return -ENOMEM;
1374ac6feceeSTrond Myklebust 	if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL))
13751da177e4SLinus Torvalds 		return -ENOMEM;
13764b9a445eSJeff Layton 
13774b9a445eSJeff Layton 	gssd_dentry = rpc_gssd_dummy_populate(root, sn->gssd_dummy);
13784b9a445eSJeff Layton 	if (IS_ERR(gssd_dentry)) {
13794b9a445eSJeff Layton 		__rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF);
13804b9a445eSJeff Layton 		return PTR_ERR(gssd_dentry);
13814b9a445eSJeff Layton 	}
13824b9a445eSJeff Layton 
13836c67a3e4SVasily Averin 	dprintk("RPC:       sending pipefs MOUNT notification for net %x%s\n",
13846c67a3e4SVasily Averin 		net->ns.inum, NET_NAME(net));
138538481605SStanislav Kinsbursky 	mutex_lock(&sn->pipefs_sb_lock);
138637629b57SStanislav Kinsbursky 	sn->pipefs_sb = sb;
13872d00131aSStanislav Kinsbursky 	err = blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
13882d00131aSStanislav Kinsbursky 					   RPC_PIPEFS_MOUNT,
13892d00131aSStanislav Kinsbursky 					   sb);
13902d00131aSStanislav Kinsbursky 	if (err)
13912d00131aSStanislav Kinsbursky 		goto err_depopulate;
139238481605SStanislav Kinsbursky 	mutex_unlock(&sn->pipefs_sb_lock);
1393fc7bed8cSAl Viro 	return 0;
13942d00131aSStanislav Kinsbursky 
13952d00131aSStanislav Kinsbursky err_depopulate:
139623e66ba9SJeff Layton 	rpc_gssd_dummy_depopulate(gssd_dentry);
13972d00131aSStanislav Kinsbursky 	blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
13982d00131aSStanislav Kinsbursky 					   RPC_PIPEFS_UMOUNT,
13992d00131aSStanislav Kinsbursky 					   sb);
140037629b57SStanislav Kinsbursky 	sn->pipefs_sb = NULL;
14012d00131aSStanislav Kinsbursky 	__rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF);
140238481605SStanislav Kinsbursky 	mutex_unlock(&sn->pipefs_sb_lock);
14032d00131aSStanislav Kinsbursky 	return err;
14041da177e4SLinus Torvalds }
14051da177e4SLinus Torvalds 
140689f84243SJeff Layton bool
140789f84243SJeff Layton gssd_running(struct net *net)
140889f84243SJeff Layton {
140989f84243SJeff Layton 	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
141089f84243SJeff Layton 	struct rpc_pipe *pipe = sn->gssd_dummy;
141189f84243SJeff Layton 
141289f84243SJeff Layton 	return pipe->nreaders || pipe->nwriters;
141389f84243SJeff Layton }
141489f84243SJeff Layton EXPORT_SYMBOL_GPL(gssd_running);
141589f84243SJeff Layton 
1416fc14f2feSAl Viro static struct dentry *
1417fc14f2feSAl Viro rpc_mount(struct file_system_type *fs_type,
1418fc14f2feSAl Viro 		int flags, const char *dev_name, void *data)
14191da177e4SLinus Torvalds {
1420d91ee87dSEric W. Biederman 	struct net *net = current->nsproxy->net_ns;
1421d91ee87dSEric W. Biederman 	return mount_ns(fs_type, flags, data, net, net->user_ns, rpc_fill_super);
14221da177e4SLinus Torvalds }
14231da177e4SLinus Torvalds 
142409acfea5STrond Myklebust static void rpc_kill_sb(struct super_block *sb)
1425021c68deSStanislav Kinsbursky {
1426021c68deSStanislav Kinsbursky 	struct net *net = sb->s_fs_info;
142790c4e829SStanislav Kinsbursky 	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1428021c68deSStanislav Kinsbursky 
1429c21a588fSStanislav Kinsbursky 	mutex_lock(&sn->pipefs_sb_lock);
1430642fe4d0STrond Myklebust 	if (sn->pipefs_sb != sb) {
1431642fe4d0STrond Myklebust 		mutex_unlock(&sn->pipefs_sb_lock);
1432642fe4d0STrond Myklebust 		goto out;
1433642fe4d0STrond Myklebust 	}
143490c4e829SStanislav Kinsbursky 	sn->pipefs_sb = NULL;
14356c67a3e4SVasily Averin 	dprintk("RPC:       sending pipefs UMOUNT notification for net %x%s\n",
14366c67a3e4SVasily Averin 		net->ns.inum, NET_NAME(net));
14372d00131aSStanislav Kinsbursky 	blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
14382d00131aSStanislav Kinsbursky 					   RPC_PIPEFS_UMOUNT,
14392d00131aSStanislav Kinsbursky 					   sb);
1440adb6fa7fSStanislav Kinsbursky 	mutex_unlock(&sn->pipefs_sb_lock);
1441642fe4d0STrond Myklebust out:
1442021c68deSStanislav Kinsbursky 	kill_litter_super(sb);
1443d91ee87dSEric W. Biederman 	put_net(net);
14441da177e4SLinus Torvalds }
14451da177e4SLinus Torvalds 
14461da177e4SLinus Torvalds static struct file_system_type rpc_pipe_fs_type = {
14471da177e4SLinus Torvalds 	.owner		= THIS_MODULE,
14481da177e4SLinus Torvalds 	.name		= "rpc_pipefs",
1449fc14f2feSAl Viro 	.mount		= rpc_mount,
1450021c68deSStanislav Kinsbursky 	.kill_sb	= rpc_kill_sb,
14511da177e4SLinus Torvalds };
14527f78e035SEric W. Biederman MODULE_ALIAS_FS("rpc_pipefs");
1453fa7614ddSEric W. Biederman MODULE_ALIAS("rpc_pipefs");
14541da177e4SLinus Torvalds 
14551da177e4SLinus Torvalds static void
145651cc5068SAlexey Dobriyan init_once(void *foo)
14571da177e4SLinus Torvalds {
14581da177e4SLinus Torvalds 	struct rpc_inode *rpci = (struct rpc_inode *) foo;
14591da177e4SLinus Torvalds 
14601da177e4SLinus Torvalds 	inode_init_once(&rpci->vfs_inode);
14611da177e4SLinus Torvalds 	rpci->private = NULL;
1462ba9e0975SStanislav Kinsbursky 	rpci->pipe = NULL;
14631da177e4SLinus Torvalds 	init_waitqueue_head(&rpci->waitq);
14641da177e4SLinus Torvalds }
14651da177e4SLinus Torvalds 
14661da177e4SLinus Torvalds int register_rpc_pipefs(void)
14671da177e4SLinus Torvalds {
14685bd5f581SAkinobu Mita 	int err;
14695bd5f581SAkinobu Mita 
14701da177e4SLinus Torvalds 	rpc_inode_cachep = kmem_cache_create("rpc_inode_cache",
14711da177e4SLinus Torvalds 				sizeof(struct rpc_inode),
1472fffb60f9SPaul Jackson 				0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
14735d097056SVladimir Davydov 						SLAB_MEM_SPREAD|SLAB_ACCOUNT),
147420c2df83SPaul Mundt 				init_once);
14751da177e4SLinus Torvalds 	if (!rpc_inode_cachep)
14761da177e4SLinus Torvalds 		return -ENOMEM;
147780df9d20SStanislav Kinsbursky 	err = rpc_clients_notifier_register();
147880df9d20SStanislav Kinsbursky 	if (err)
147980df9d20SStanislav Kinsbursky 		goto err_notifier;
14805bd5f581SAkinobu Mita 	err = register_filesystem(&rpc_pipe_fs_type);
148180df9d20SStanislav Kinsbursky 	if (err)
148280df9d20SStanislav Kinsbursky 		goto err_register;
148380df9d20SStanislav Kinsbursky 	return 0;
148480df9d20SStanislav Kinsbursky 
148580df9d20SStanislav Kinsbursky err_register:
148680df9d20SStanislav Kinsbursky 	rpc_clients_notifier_unregister();
148780df9d20SStanislav Kinsbursky err_notifier:
14885bd5f581SAkinobu Mita 	kmem_cache_destroy(rpc_inode_cachep);
14895bd5f581SAkinobu Mita 	return err;
14905bd5f581SAkinobu Mita }
14915bd5f581SAkinobu Mita 
14921da177e4SLinus Torvalds void unregister_rpc_pipefs(void)
14931da177e4SLinus Torvalds {
149480df9d20SStanislav Kinsbursky 	rpc_clients_notifier_unregister();
14951a1d92c1SAlexey Dobriyan 	kmem_cache_destroy(rpc_inode_cachep);
14961da177e4SLinus Torvalds 	unregister_filesystem(&rpc_pipe_fs_type);
14971da177e4SLinus Torvalds }
1498