Blame view

net/sunrpc/rpc_pipe.c 35.8 KB
457c89965   Thomas Gleixner   treewide: Add SPD...
1
  // SPDX-License-Identifier: GPL-2.0-only
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
  /*
   * net/sunrpc/rpc_pipe.c
   *
   * Userland/kernel interface for rpcauth_gss.
   * Code shamelessly plagiarized from fs/nfsd/nfsctl.c
d51fe1be3   Rolf Eike Beer   [PATCH] remove dr...
7
   * and fs/sysfs/inode.c
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
11
   *
   * Copyright (c) 2002, Trond Myklebust <trond.myklebust@fys.uio.no>
   *
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
16
  #include <linux/module.h>
  #include <linux/slab.h>
  #include <linux/string.h>
  #include <linux/pagemap.h>
  #include <linux/mount.h>
b9662f310   David Howells   vfs: Convert rpc_...
17
  #include <linux/fs_context.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
  #include <linux/namei.h>
50e437d52   Trond Myklebust   SUNRPC: Convert r...
19
  #include <linux/fsnotify.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
  #include <linux/kernel.h>
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
21
  #include <linux/rcupdate.h>
e2f0c83a9   Jeff Layton   sunrpc: add an "i...
22
  #include <linux/utsname.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
  
  #include <asm/ioctls.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
27
28
29
30
31
  #include <linux/poll.h>
  #include <linux/wait.h>
  #include <linux/seq_file.h>
  
  #include <linux/sunrpc/clnt.h>
  #include <linux/workqueue.h>
  #include <linux/sunrpc/rpc_pipe_fs.h>
8854e82d9   Trond Myklebust   SUNRPC: Add an rp...
32
  #include <linux/sunrpc/cache.h>
021c68dec   Stanislav Kinsbursky   SUNRPC: hold curr...
33
  #include <linux/nsproxy.h>
2d00131ac   Stanislav Kinsbursky   SUNRPC: send noti...
34
  #include <linux/notifier.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35

021c68dec   Stanislav Kinsbursky   SUNRPC: hold curr...
36
  #include "netns.h"
2d00131ac   Stanislav Kinsbursky   SUNRPC: send noti...
37
  #include "sunrpc.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38

efc46bf2b   Stanislav Kinsbursky   SUNRPC: added deb...
39
40
41
  #define RPCDBG_FACILITY RPCDBG_DEBUG
  
  #define NET_NAME(net)	((net == &init_net) ? " (init_net)" : "")
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
  
  static struct file_system_type rpc_pipe_fs_type;
4b9a445e3   Jeff Layton   sunrpc: create a ...
44
  static const struct rpc_pipe_ops gssd_dummy_pipe_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45

e18b890bb   Christoph Lameter   [PATCH] slab: rem...
46
  static struct kmem_cache *rpc_inode_cachep __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
48
  
  #define RPC_UPCALL_TIMEOUT (30*HZ)
2d00131ac   Stanislav Kinsbursky   SUNRPC: send noti...
49
50
51
52
  static BLOCKING_NOTIFIER_HEAD(rpc_pipefs_notifier_list);
  
  int rpc_pipefs_notifier_register(struct notifier_block *nb)
  {
260a2679e   Xiaoming Ni   kernel/notifier.c...
53
  	return blocking_notifier_chain_register(&rpc_pipefs_notifier_list, nb);
2d00131ac   Stanislav Kinsbursky   SUNRPC: send noti...
54
55
56
57
58
59
60
61
  }
  EXPORT_SYMBOL_GPL(rpc_pipefs_notifier_register);
  
  void rpc_pipefs_notifier_unregister(struct notifier_block *nb)
  {
  	blocking_notifier_chain_unregister(&rpc_pipefs_notifier_list, nb);
  }
  EXPORT_SYMBOL_GPL(rpc_pipefs_notifier_unregister);
591ad7fea   Stanislav Kinsbursky   SUNRPC: move wait...
62
  static void rpc_purge_list(wait_queue_head_t *waitq, struct list_head *head,
9842ef355   Trond Myklebust   SUNRPC: rpc_timeo...
63
  		void (*destroy_msg)(struct rpc_pipe_msg *), int err)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
  	struct rpc_pipe_msg *msg;
9842ef355   Trond Myklebust   SUNRPC: rpc_timeo...
66
67
68
  	if (list_empty(head))
  		return;
  	do {
b3eb67a2a   Trond Myklebust   SUNRPC: Funny loo...
69
  		msg = list_entry(head->next, struct rpc_pipe_msg, list);
5a67657a2   Trond Myklebust   SUNRPC: Fix race ...
70
  		list_del_init(&msg->list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
  		msg->errno = err;
b3eb67a2a   Trond Myklebust   SUNRPC: Funny loo...
72
  		destroy_msg(msg);
9842ef355   Trond Myklebust   SUNRPC: rpc_timeo...
73
  	} while (!list_empty(head));
92123e068   Jeff Layton   rpc_pipefs: allow...
74
75
76
  
  	if (waitq)
  		wake_up(waitq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
78
79
  }
  
  static void
65f27f384   David Howells   WorkStruct: Pass ...
80
  rpc_timeout_upcall_queue(struct work_struct *work)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
  {
9842ef355   Trond Myklebust   SUNRPC: rpc_timeo...
82
  	LIST_HEAD(free_list);
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
83
84
  	struct rpc_pipe *pipe =
  		container_of(work, struct rpc_pipe, queue_timeout.work);
9842ef355   Trond Myklebust   SUNRPC: rpc_timeo...
85
  	void (*destroy_msg)(struct rpc_pipe_msg *);
591ad7fea   Stanislav Kinsbursky   SUNRPC: move wait...
86
  	struct dentry *dentry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87

ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
88
  	spin_lock(&pipe->lock);
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
89
90
91
92
  	destroy_msg = pipe->ops->destroy_msg;
  	if (pipe->nreaders == 0) {
  		list_splice_init(&pipe->pipe, &free_list);
  		pipe->pipelen = 0;
9842ef355   Trond Myklebust   SUNRPC: rpc_timeo...
93
  	}
591ad7fea   Stanislav Kinsbursky   SUNRPC: move wait...
94
  	dentry = dget(pipe->dentry);
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
95
  	spin_unlock(&pipe->lock);
c5ef60352   David Howells   VFS: net/: d_inod...
96
  	rpc_purge_list(dentry ? &RPC_I(d_inode(dentry))->waitq : NULL,
92123e068   Jeff Layton   rpc_pipefs: allow...
97
98
  			&free_list, destroy_msg, -ETIMEDOUT);
  	dput(dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
  }
c1225158a   Peng Tao   SUNRPC/NFS: make ...
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
  ssize_t rpc_pipe_generic_upcall(struct file *filp, struct rpc_pipe_msg *msg,
  				char __user *dst, size_t buflen)
  {
  	char *data = (char *)msg->data + msg->copied;
  	size_t mlen = min(msg->len - msg->copied, buflen);
  	unsigned long left;
  
  	left = copy_to_user(dst, data, mlen);
  	if (left == mlen) {
  		msg->errno = -EFAULT;
  		return -EFAULT;
  	}
  
  	mlen -= left;
  	msg->copied += mlen;
  	msg->errno = 0;
  	return mlen;
  }
  EXPORT_SYMBOL_GPL(rpc_pipe_generic_upcall);
93a44a75b   J. Bruce Fields   sunrpc: document ...
119
  /**
1a5778aa0   Ben Hutchings   net: Fix first li...
120
   * rpc_queue_upcall - queue an upcall message to userspace
bda14606a   Randy Dunlap   sunrpc: fix kerne...
121
   * @pipe: upcall pipe on which to queue given message
93a44a75b   J. Bruce Fields   sunrpc: document ...
122
123
124
125
126
127
128
   * @msg: message to queue
   *
   * Call with an @inode created by rpc_mkpipe() to queue an upcall.
   * A userspace process may then later read the upcall by performing a
   * read on an open file for this inode.  It is up to the caller to
   * initialize the fields of @msg (other than @msg->list) appropriately.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
  int
d706ed1f5   Stanislav Kinsbursky   SUNPRC: cleanup R...
130
  rpc_queue_upcall(struct rpc_pipe *pipe, struct rpc_pipe_msg *msg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
  {
6070fe6f8   Trond Myklebust   RPC: Ensure that ...
132
  	int res = -EPIPE;
591ad7fea   Stanislav Kinsbursky   SUNRPC: move wait...
133
  	struct dentry *dentry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134

d0fe13ba9   Stanislav Kinsbursky   SUNRPC: cleanup P...
135
  	spin_lock(&pipe->lock);
d0fe13ba9   Stanislav Kinsbursky   SUNRPC: cleanup P...
136
137
138
  	if (pipe->nreaders) {
  		list_add_tail(&msg->list, &pipe->pipe);
  		pipe->pipelen += msg->len;
6070fe6f8   Trond Myklebust   RPC: Ensure that ...
139
  		res = 0;
d0fe13ba9   Stanislav Kinsbursky   SUNRPC: cleanup P...
140
141
  	} else if (pipe->flags & RPC_PIPE_WAIT_FOR_OPEN) {
  		if (list_empty(&pipe->pipe))
24c5d9d7e   Trond Myklebust   SUNRPC: Run rpci-...
142
  			queue_delayed_work(rpciod_workqueue,
d0fe13ba9   Stanislav Kinsbursky   SUNRPC: cleanup P...
143
  					&pipe->queue_timeout,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
  					RPC_UPCALL_TIMEOUT);
d0fe13ba9   Stanislav Kinsbursky   SUNRPC: cleanup P...
145
146
  		list_add_tail(&msg->list, &pipe->pipe);
  		pipe->pipelen += msg->len;
6070fe6f8   Trond Myklebust   RPC: Ensure that ...
147
148
  		res = 0;
  	}
591ad7fea   Stanislav Kinsbursky   SUNRPC: move wait...
149
  	dentry = dget(pipe->dentry);
d0fe13ba9   Stanislav Kinsbursky   SUNRPC: cleanup P...
150
  	spin_unlock(&pipe->lock);
591ad7fea   Stanislav Kinsbursky   SUNRPC: move wait...
151
  	if (dentry) {
c5ef60352   David Howells   VFS: net/: d_inod...
152
  		wake_up(&RPC_I(d_inode(dentry))->waitq);
591ad7fea   Stanislav Kinsbursky   SUNRPC: move wait...
153
154
  		dput(dentry);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155
156
  	return res;
  }
468039ee4   Trond Myklebust   SUNRPC: Convert t...
157
  EXPORT_SYMBOL_GPL(rpc_queue_upcall);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158

6070fe6f8   Trond Myklebust   RPC: Ensure that ...
159
160
161
162
163
  static inline void
  rpc_inode_setowner(struct inode *inode, void *private)
  {
  	RPC_I(inode)->private = private;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
166
  static void
  rpc_close_pipes(struct inode *inode)
  {
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
167
  	struct rpc_pipe *pipe = RPC_I(inode)->pipe;
e712804ae   \"J. Bruce Fields\   rpc: call release...
168
  	int need_release;
ad6b13400   Stanislav Kinsbursky   SUNRPC: fix pipe-...
169
  	LIST_HEAD(free_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170

5955102c9   Al Viro   wrappers for ->i_...
171
  	inode_lock(inode);
ad6b13400   Stanislav Kinsbursky   SUNRPC: fix pipe-...
172
173
174
175
176
177
178
179
  	spin_lock(&pipe->lock);
  	need_release = pipe->nreaders != 0 || pipe->nwriters != 0;
  	pipe->nreaders = 0;
  	list_splice_init(&pipe->in_upcall, &free_list);
  	list_splice_init(&pipe->pipe, &free_list);
  	pipe->pipelen = 0;
  	pipe->dentry = NULL;
  	spin_unlock(&pipe->lock);
591ad7fea   Stanislav Kinsbursky   SUNRPC: move wait...
180
  	rpc_purge_list(&RPC_I(inode)->waitq, &free_list, pipe->ops->destroy_msg, -EPIPE);
ad6b13400   Stanislav Kinsbursky   SUNRPC: fix pipe-...
181
182
183
184
  	pipe->nwriters = 0;
  	if (need_release && pipe->ops->release_pipe)
  		pipe->ops->release_pipe(inode);
  	cancel_delayed_work_sync(&pipe->queue_timeout);
6070fe6f8   Trond Myklebust   RPC: Ensure that ...
185
  	rpc_inode_setowner(inode, NULL);
2c9030eef   Stanislav Kinsbursky   SUNRPC: check RPC...
186
  	RPC_I(inode)->pipe = NULL;
5955102c9   Al Viro   wrappers for ->i_...
187
  	inode_unlock(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
190
191
192
  static struct inode *
  rpc_alloc_inode(struct super_block *sb)
  {
  	struct rpc_inode *rpci;
adcda652c   Himangi Saraogi   rpc_pipe: Drop me...
193
  	rpci = kmem_cache_alloc(rpc_inode_cachep, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
195
196
197
198
199
  	if (!rpci)
  		return NULL;
  	return &rpci->vfs_inode;
  }
  
  static void
bef252fa1   Al Viro   rpcpipe: switch t...
200
  rpc_free_inode(struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
202
203
204
205
206
207
  {
  	kmem_cache_free(rpc_inode_cachep, RPC_I(inode));
  }
  
  static int
  rpc_pipe_open(struct inode *inode, struct file *filp)
  {
2c9030eef   Stanislav Kinsbursky   SUNRPC: check RPC...
208
  	struct rpc_pipe *pipe;
c38106086   \"J. Bruce Fields\   rpc: add an rpc_p...
209
  	int first_open;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
  	int res = -ENXIO;
5955102c9   Al Viro   wrappers for ->i_...
211
  	inode_lock(inode);
2c9030eef   Stanislav Kinsbursky   SUNRPC: check RPC...
212
213
  	pipe = RPC_I(inode)->pipe;
  	if (pipe == NULL)
c38106086   \"J. Bruce Fields\   rpc: add an rpc_p...
214
  		goto out;
d0fe13ba9   Stanislav Kinsbursky   SUNRPC: cleanup P...
215
216
217
  	first_open = pipe->nreaders == 0 && pipe->nwriters == 0;
  	if (first_open && pipe->ops->open_pipe) {
  		res = pipe->ops->open_pipe(inode);
c38106086   \"J. Bruce Fields\   rpc: add an rpc_p...
218
219
  		if (res)
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
  	}
c38106086   \"J. Bruce Fields\   rpc: add an rpc_p...
221
  	if (filp->f_mode & FMODE_READ)
d0fe13ba9   Stanislav Kinsbursky   SUNRPC: cleanup P...
222
  		pipe->nreaders++;
c38106086   \"J. Bruce Fields\   rpc: add an rpc_p...
223
  	if (filp->f_mode & FMODE_WRITE)
d0fe13ba9   Stanislav Kinsbursky   SUNRPC: cleanup P...
224
  		pipe->nwriters++;
c38106086   \"J. Bruce Fields\   rpc: add an rpc_p...
225
226
  	res = 0;
  out:
5955102c9   Al Viro   wrappers for ->i_...
227
  	inode_unlock(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
229
230
231
232
233
  	return res;
  }
  
  static int
  rpc_pipe_release(struct inode *inode, struct file *filp)
  {
2c9030eef   Stanislav Kinsbursky   SUNRPC: check RPC...
234
  	struct rpc_pipe *pipe;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
  	struct rpc_pipe_msg *msg;
e712804ae   \"J. Bruce Fields\   rpc: call release...
236
  	int last_close;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237

5955102c9   Al Viro   wrappers for ->i_...
238
  	inode_lock(inode);
2c9030eef   Stanislav Kinsbursky   SUNRPC: check RPC...
239
240
  	pipe = RPC_I(inode)->pipe;
  	if (pipe == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241
  		goto out;
655b5bb4a   Joe Perches   net/sunrpc/rpc_pi...
242
  	msg = filp->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
  	if (msg != NULL) {
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
244
  		spin_lock(&pipe->lock);
48e491877   Trond Myklebust   SUNRPC: Fix "EPIP...
245
  		msg->errno = -EAGAIN;
5a67657a2   Trond Myklebust   SUNRPC: Fix race ...
246
  		list_del_init(&msg->list);
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
247
248
  		spin_unlock(&pipe->lock);
  		pipe->ops->destroy_msg(msg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
250
  	}
  	if (filp->f_mode & FMODE_WRITE)
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
251
  		pipe->nwriters --;
9842ef355   Trond Myklebust   SUNRPC: rpc_timeo...
252
  	if (filp->f_mode & FMODE_READ) {
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
253
254
  		pipe->nreaders --;
  		if (pipe->nreaders == 0) {
9842ef355   Trond Myklebust   SUNRPC: rpc_timeo...
255
  			LIST_HEAD(free_list);
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
256
257
258
259
  			spin_lock(&pipe->lock);
  			list_splice_init(&pipe->pipe, &free_list);
  			pipe->pipelen = 0;
  			spin_unlock(&pipe->lock);
591ad7fea   Stanislav Kinsbursky   SUNRPC: move wait...
260
  			rpc_purge_list(&RPC_I(inode)->waitq, &free_list,
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
261
  					pipe->ops->destroy_msg, -EAGAIN);
9842ef355   Trond Myklebust   SUNRPC: rpc_timeo...
262
263
  		}
  	}
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
264
265
266
  	last_close = pipe->nwriters == 0 && pipe->nreaders == 0;
  	if (last_close && pipe->ops->release_pipe)
  		pipe->ops->release_pipe(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
  out:
5955102c9   Al Viro   wrappers for ->i_...
268
  	inode_unlock(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
270
271
272
273
274
  	return 0;
  }
  
  static ssize_t
  rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset)
  {
496ad9aa8   Al Viro   new helper: file_...
275
  	struct inode *inode = file_inode(filp);
2c9030eef   Stanislav Kinsbursky   SUNRPC: check RPC...
276
  	struct rpc_pipe *pipe;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277
278
  	struct rpc_pipe_msg *msg;
  	int res = 0;
5955102c9   Al Viro   wrappers for ->i_...
279
  	inode_lock(inode);
2c9030eef   Stanislav Kinsbursky   SUNRPC: check RPC...
280
281
  	pipe = RPC_I(inode)->pipe;
  	if (pipe == NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
283
284
285
286
  		res = -EPIPE;
  		goto out_unlock;
  	}
  	msg = filp->private_data;
  	if (msg == NULL) {
d0fe13ba9   Stanislav Kinsbursky   SUNRPC: cleanup P...
287
288
289
  		spin_lock(&pipe->lock);
  		if (!list_empty(&pipe->pipe)) {
  			msg = list_entry(pipe->pipe.next,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290
291
  					struct rpc_pipe_msg,
  					list);
d0fe13ba9   Stanislav Kinsbursky   SUNRPC: cleanup P...
292
293
  			list_move(&msg->list, &pipe->in_upcall);
  			pipe->pipelen -= msg->len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
294
295
296
  			filp->private_data = msg;
  			msg->copied = 0;
  		}
d0fe13ba9   Stanislav Kinsbursky   SUNRPC: cleanup P...
297
  		spin_unlock(&pipe->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
298
299
300
301
  		if (msg == NULL)
  			goto out_unlock;
  	}
  	/* NOTE: it is up to the callback to update msg->copied */
d0fe13ba9   Stanislav Kinsbursky   SUNRPC: cleanup P...
302
  	res = pipe->ops->upcall(filp, msg, buf, len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303
304
  	if (res < 0 || msg->len == msg->copied) {
  		filp->private_data = NULL;
d0fe13ba9   Stanislav Kinsbursky   SUNRPC: cleanup P...
305
  		spin_lock(&pipe->lock);
5a67657a2   Trond Myklebust   SUNRPC: Fix race ...
306
  		list_del_init(&msg->list);
d0fe13ba9   Stanislav Kinsbursky   SUNRPC: cleanup P...
307
308
  		spin_unlock(&pipe->lock);
  		pipe->ops->destroy_msg(msg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
310
  	}
  out_unlock:
5955102c9   Al Viro   wrappers for ->i_...
311
  	inode_unlock(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
313
314
315
316
317
  	return res;
  }
  
  static ssize_t
  rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *offset)
  {
496ad9aa8   Al Viro   new helper: file_...
318
  	struct inode *inode = file_inode(filp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
319
  	int res;
5955102c9   Al Viro   wrappers for ->i_...
320
  	inode_lock(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321
  	res = -EPIPE;
2c9030eef   Stanislav Kinsbursky   SUNRPC: check RPC...
322
323
  	if (RPC_I(inode)->pipe != NULL)
  		res = RPC_I(inode)->pipe->ops->downcall(filp, buf, len);
5955102c9   Al Viro   wrappers for ->i_...
324
  	inode_unlock(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
326
  	return res;
  }
ade994f4f   Al Viro   net: annotate ->p...
327
  static __poll_t
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
328
329
  rpc_pipe_poll(struct file *filp, struct poll_table_struct *wait)
  {
496ad9aa8   Al Viro   new helper: file_...
330
  	struct inode *inode = file_inode(filp);
591ad7fea   Stanislav Kinsbursky   SUNRPC: move wait...
331
  	struct rpc_inode *rpci = RPC_I(inode);
a9a08845e   Linus Torvalds   vfs: do bulk POLL...
332
  	__poll_t mask = EPOLLOUT | EPOLLWRNORM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
  	poll_wait(filp, &rpci->waitq, wait);
5955102c9   Al Viro   wrappers for ->i_...
335
  	inode_lock(inode);
591ad7fea   Stanislav Kinsbursky   SUNRPC: move wait...
336
  	if (rpci->pipe == NULL)
a9a08845e   Linus Torvalds   vfs: do bulk POLL...
337
  		mask |= EPOLLERR | EPOLLHUP;
591ad7fea   Stanislav Kinsbursky   SUNRPC: move wait...
338
  	else if (filp->private_data || !list_empty(&rpci->pipe->pipe))
a9a08845e   Linus Torvalds   vfs: do bulk POLL...
339
  		mask |= EPOLLIN | EPOLLRDNORM;
5955102c9   Al Viro   wrappers for ->i_...
340
  	inode_unlock(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
342
  	return mask;
  }
a6f8dbc65   Arnd Bergmann   sunrpc: remove th...
343
344
  static long
  rpc_pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
345
  {
496ad9aa8   Al Viro   new helper: file_...
346
  	struct inode *inode = file_inode(filp);
2c9030eef   Stanislav Kinsbursky   SUNRPC: check RPC...
347
  	struct rpc_pipe *pipe;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
349
350
351
  	int len;
  
  	switch (cmd) {
  	case FIONREAD:
5955102c9   Al Viro   wrappers for ->i_...
352
  		inode_lock(inode);
2c9030eef   Stanislav Kinsbursky   SUNRPC: check RPC...
353
354
  		pipe = RPC_I(inode)->pipe;
  		if (pipe == NULL) {
5955102c9   Al Viro   wrappers for ->i_...
355
  			inode_unlock(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356
  			return -EPIPE;
a6f8dbc65   Arnd Bergmann   sunrpc: remove th...
357
  		}
2c9030eef   Stanislav Kinsbursky   SUNRPC: check RPC...
358
  		spin_lock(&pipe->lock);
d0fe13ba9   Stanislav Kinsbursky   SUNRPC: cleanup P...
359
  		len = pipe->pipelen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360
361
  		if (filp->private_data) {
  			struct rpc_pipe_msg *msg;
655b5bb4a   Joe Perches   net/sunrpc/rpc_pi...
362
  			msg = filp->private_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
364
  			len += msg->len - msg->copied;
  		}
d0fe13ba9   Stanislav Kinsbursky   SUNRPC: cleanup P...
365
  		spin_unlock(&pipe->lock);
5955102c9   Al Viro   wrappers for ->i_...
366
  		inode_unlock(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367
368
369
370
371
  		return put_user(len, (int __user *)arg);
  	default:
  		return -EINVAL;
  	}
  }
da7071d7e   Arjan van de Ven   [PATCH] mark stru...
372
  static const struct file_operations rpc_pipe_fops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
374
375
376
377
  	.owner		= THIS_MODULE,
  	.llseek		= no_llseek,
  	.read		= rpc_pipe_read,
  	.write		= rpc_pipe_write,
  	.poll		= rpc_pipe_poll,
674b604cd   Frederic Weisbecker   sunrpc: Pushdown ...
378
  	.unlocked_ioctl	= rpc_pipe_ioctl,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379
380
381
382
383
384
385
386
  	.open		= rpc_pipe_open,
  	.release	= rpc_pipe_release,
  };
  
  static int
  rpc_show_info(struct seq_file *m, void *v)
  {
  	struct rpc_clnt *clnt = m->private;
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
387
  	rcu_read_lock();
4e0038b6b   Trond Myklebust   SUNRPC: Move clnt...
388
389
390
  	seq_printf(m, "RPC server: %s
  ",
  			rcu_dereference(clnt->cl_xprt)->servername);
55909f21a   Trond Myklebust   SUNRPC: Deprecate...
391
392
  	seq_printf(m, "service: %s (%d) version %d
  ", clnt->cl_program->name,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
  			clnt->cl_prog, clnt->cl_vers);
e7f786574   Chuck Lever   SUNRPC: Teach rpc...
394
395
396
397
  	seq_printf(m, "address: %s
  ", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR));
  	seq_printf(m, "protocol: %s
  ", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO));
bf19aacec   J. Bruce Fields   nfs: add server p...
398
399
  	seq_printf(m, "port: %s
  ", rpc_peeraddr2str(clnt, RPC_DISPLAY_PORT));
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
400
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
401
402
403
404
405
406
  	return 0;
  }
  
  static int
  rpc_info_open(struct inode *inode, struct file *file)
  {
006abe887   Trond Myklebust   SUNRPC: Fix a rac...
407
  	struct rpc_clnt *clnt = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
408
409
410
411
  	int ret = single_open(file, rpc_show_info, NULL);
  
  	if (!ret) {
  		struct seq_file *m = file->private_data;
006abe887   Trond Myklebust   SUNRPC: Fix a rac...
412
413
414
415
416
417
  
  		spin_lock(&file->f_path.dentry->d_lock);
  		if (!d_unhashed(file->f_path.dentry))
  			clnt = RPC_I(inode)->private;
  		if (clnt != NULL && atomic_inc_not_zero(&clnt->cl_count)) {
  			spin_unlock(&file->f_path.dentry->d_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
418
419
  			m->private = clnt;
  		} else {
006abe887   Trond Myklebust   SUNRPC: Fix a rac...
420
  			spin_unlock(&file->f_path.dentry->d_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
421
422
423
  			single_release(inode, file);
  			ret = -EINVAL;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
425
426
427
428
429
430
431
432
433
434
435
436
437
  	}
  	return ret;
  }
  
  static int
  rpc_info_release(struct inode *inode, struct file *file)
  {
  	struct seq_file *m = file->private_data;
  	struct rpc_clnt *clnt = (struct rpc_clnt *)m->private;
  
  	if (clnt)
  		rpc_release_client(clnt);
  	return single_release(inode, file);
  }
da7071d7e   Arjan van de Ven   [PATCH] mark stru...
438
  static const struct file_operations rpc_info_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439
440
441
442
443
444
445
446
447
  	.owner		= THIS_MODULE,
  	.open		= rpc_info_open,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
  	.release	= rpc_info_release,
  };
  
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
449
450
   * Description of fs contents.
   */
  struct rpc_filelist {
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
451
  	const char *name;
99ac48f54   Arjan van de Ven   [PATCH] mark f_op...
452
  	const struct file_operations *i_fop;
7364af6a2   Trond Myklebust   SUNRPC: Allow rpc...
453
  	umode_t mode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
454
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455
  static struct inode *
7364af6a2   Trond Myklebust   SUNRPC: Allow rpc...
456
  rpc_get_inode(struct super_block *sb, umode_t mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457
458
459
460
  {
  	struct inode *inode = new_inode(sb);
  	if (!inode)
  		return NULL;
85fe4025c   Christoph Hellwig   fs: do not assign...
461
  	inode->i_ino = get_next_ino();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
462
  	inode->i_mode = mode;
078cd8279   Deepa Dinamani   fs: Replace CURRE...
463
  	inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
89f0e4fea   Joe Perches   sunrpc: Reduce sw...
464
465
466
  	switch (mode & S_IFMT) {
  	case S_IFDIR:
  		inode->i_fop = &simple_dir_operations;
275448eb1   Jeff Layton   rpc_pipe: convert...
467
  		inode->i_op = &simple_dir_inode_operations;
89f0e4fea   Joe Perches   sunrpc: Reduce sw...
468
469
470
  		inc_nlink(inode);
  	default:
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
471
472
473
  	}
  	return inode;
  }
7589806e9   Trond Myklebust   SUNRPC: Clean up ...
474
475
476
477
478
479
  static int __rpc_create_common(struct inode *dir, struct dentry *dentry,
  			       umode_t mode,
  			       const struct file_operations *i_fop,
  			       void *private)
  {
  	struct inode *inode;
beb0f0a9f   Trond Myklebust   kernel panic when...
480
  	d_drop(dentry);
7589806e9   Trond Myklebust   SUNRPC: Clean up ...
481
482
483
484
485
486
487
488
489
490
491
  	inode = rpc_get_inode(dir->i_sb, mode);
  	if (!inode)
  		goto out_err;
  	inode->i_ino = iunique(dir->i_sb, 100);
  	if (i_fop)
  		inode->i_fop = i_fop;
  	if (private)
  		rpc_inode_setowner(inode, private);
  	d_add(dentry, inode);
  	return 0;
  out_err:
1e903edad   Al Viro   sunrpc: switch to...
492
493
494
  	printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %pd
  ",
  			__FILE__, __func__, dentry);
7589806e9   Trond Myklebust   SUNRPC: Clean up ...
495
496
497
  	dput(dentry);
  	return -ENOMEM;
  }
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
498
499
500
501
502
503
504
505
506
507
508
509
510
  static int __rpc_create(struct inode *dir, struct dentry *dentry,
  			umode_t mode,
  			const struct file_operations *i_fop,
  			void *private)
  {
  	int err;
  
  	err = __rpc_create_common(dir, dentry, S_IFREG | mode, i_fop, private);
  	if (err)
  		return err;
  	fsnotify_create(dir, dentry);
  	return 0;
  }
7589806e9   Trond Myklebust   SUNRPC: Clean up ...
511
512
513
514
515
516
517
518
519
520
521
522
523
524
  static int __rpc_mkdir(struct inode *dir, struct dentry *dentry,
  		       umode_t mode,
  		       const struct file_operations *i_fop,
  		       void *private)
  {
  	int err;
  
  	err = __rpc_create_common(dir, dentry, S_IFDIR | mode, i_fop, private);
  	if (err)
  		return err;
  	inc_nlink(dir);
  	fsnotify_mkdir(dir, dentry);
  	return 0;
  }
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
525
526
527
528
529
530
531
532
533
  static void
  init_pipe(struct rpc_pipe *pipe)
  {
  	pipe->nreaders = 0;
  	pipe->nwriters = 0;
  	INIT_LIST_HEAD(&pipe->in_upcall);
  	INIT_LIST_HEAD(&pipe->in_downcall);
  	INIT_LIST_HEAD(&pipe->pipe);
  	pipe->pipelen = 0;
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
534
535
536
537
  	INIT_DELAYED_WORK(&pipe->queue_timeout,
  			    rpc_timeout_upcall_queue);
  	pipe->ops = NULL;
  	spin_lock_init(&pipe->lock);
c239d83b9   Stanislav Kinsbursky   SUNRPC: split SUN...
538
539
  	pipe->dentry = NULL;
  }
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
540

c239d83b9   Stanislav Kinsbursky   SUNRPC: split SUN...
541
542
543
  void rpc_destroy_pipe_data(struct rpc_pipe *pipe)
  {
  	kfree(pipe);
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
544
  }
c239d83b9   Stanislav Kinsbursky   SUNRPC: split SUN...
545
  EXPORT_SYMBOL_GPL(rpc_destroy_pipe_data);
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
546

c239d83b9   Stanislav Kinsbursky   SUNRPC: split SUN...
547
  struct rpc_pipe *rpc_mkpipe_data(const struct rpc_pipe_ops *ops, int flags)
7589806e9   Trond Myklebust   SUNRPC: Clean up ...
548
  {
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
549
  	struct rpc_pipe *pipe;
7589806e9   Trond Myklebust   SUNRPC: Clean up ...
550

ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
551
552
  	pipe = kzalloc(sizeof(struct rpc_pipe), GFP_KERNEL);
  	if (!pipe)
c239d83b9   Stanislav Kinsbursky   SUNRPC: split SUN...
553
  		return ERR_PTR(-ENOMEM);
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
554
  	init_pipe(pipe);
c239d83b9   Stanislav Kinsbursky   SUNRPC: split SUN...
555
556
557
558
559
560
561
562
563
564
565
  	pipe->ops = ops;
  	pipe->flags = flags;
  	return pipe;
  }
  EXPORT_SYMBOL_GPL(rpc_mkpipe_data);
  
  static int __rpc_mkpipe_dentry(struct inode *dir, struct dentry *dentry,
  			       umode_t mode,
  			       const struct file_operations *i_fop,
  			       void *private,
  			       struct rpc_pipe *pipe)
7589806e9   Trond Myklebust   SUNRPC: Clean up ...
566
567
568
569
570
571
572
  {
  	struct rpc_inode *rpci;
  	int err;
  
  	err = __rpc_create_common(dir, dentry, S_IFIFO | mode, i_fop, private);
  	if (err)
  		return err;
c5ef60352   David Howells   VFS: net/: d_inod...
573
  	rpci = RPC_I(d_inode(dentry));
7589806e9   Trond Myklebust   SUNRPC: Clean up ...
574
  	rpci->private = private;
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
575
  	rpci->pipe = pipe;
7589806e9   Trond Myklebust   SUNRPC: Clean up ...
576
577
578
  	fsnotify_create(dir, dentry);
  	return 0;
  }
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
579
580
581
582
583
584
  static int __rpc_rmdir(struct inode *dir, struct dentry *dentry)
  {
  	int ret;
  
  	dget(dentry);
  	ret = simple_rmdir(dir, dentry);
a35d632c7   Amir Goldstein   rpc_pipefs: call ...
585
586
  	if (!ret)
  		fsnotify_rmdir(dir, dentry);
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
587
588
589
590
  	d_delete(dentry);
  	dput(dentry);
  	return ret;
  }
810d90bc2   Trond Myklebust   SUNRPC: Clean up ...
591
592
593
594
595
596
  static int __rpc_unlink(struct inode *dir, struct dentry *dentry)
  {
  	int ret;
  
  	dget(dentry);
  	ret = simple_unlink(dir, dentry);
a35d632c7   Amir Goldstein   rpc_pipefs: call ...
597
598
  	if (!ret)
  		fsnotify_unlink(dir, dentry);
810d90bc2   Trond Myklebust   SUNRPC: Clean up ...
599
600
601
602
603
604
605
  	d_delete(dentry);
  	dput(dentry);
  	return ret;
  }
  
  static int __rpc_rmpipe(struct inode *dir, struct dentry *dentry)
  {
c5ef60352   David Howells   VFS: net/: d_inod...
606
  	struct inode *inode = d_inode(dentry);
810d90bc2   Trond Myklebust   SUNRPC: Clean up ...
607

810d90bc2   Trond Myklebust   SUNRPC: Clean up ...
608
609
610
  	rpc_close_pipes(inode);
  	return __rpc_unlink(dir, dentry);
  }
5bff03863   Stanislav Kinsbursky   SUNRPC: remove no...
611
  static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent,
d3db90b0a   Al Viro   __rpc_lookup_crea...
612
  					  const char *name)
cfeaa4a3c   Trond Myklebust   SUNRPC: Clean up ...
613
  {
d3db90b0a   Al Viro   __rpc_lookup_crea...
614
615
  	struct qstr q = QSTR_INIT(name, strlen(name));
  	struct dentry *dentry = d_hash_and_lookup(parent, &q);
cfeaa4a3c   Trond Myklebust   SUNRPC: Clean up ...
616
  	if (!dentry) {
d3db90b0a   Al Viro   __rpc_lookup_crea...
617
  		dentry = d_alloc(parent, &q);
5bff03863   Stanislav Kinsbursky   SUNRPC: remove no...
618
619
  		if (!dentry)
  			return ERR_PTR(-ENOMEM);
cfeaa4a3c   Trond Myklebust   SUNRPC: Clean up ...
620
  	}
c5ef60352   David Howells   VFS: net/: d_inod...
621
  	if (d_really_is_negative(dentry))
cfeaa4a3c   Trond Myklebust   SUNRPC: Clean up ...
622
623
624
625
  		return dentry;
  	dput(dentry);
  	return ERR_PTR(-EEXIST);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
626
627
628
  /*
   * FIXME: This probably has races.
   */
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
629
630
631
  static void __rpc_depopulate(struct dentry *parent,
  			     const struct rpc_filelist *files,
  			     int start, int eof)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
  {
c5ef60352   David Howells   VFS: net/: d_inod...
633
  	struct inode *dir = d_inode(parent);
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
634
635
636
  	struct dentry *dentry;
  	struct qstr name;
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
637

ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
638
639
640
  	for (i = start; i < eof; i++) {
  		name.name = files[i].name;
  		name.len = strlen(files[i].name);
d3db90b0a   Al Viro   __rpc_lookup_crea...
641
  		dentry = d_hash_and_lookup(parent, &name);
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
642
643
  
  		if (dentry == NULL)
62e1761ce   Trond Myklebust   SUNRPC: Clean up ...
644
  			continue;
c5ef60352   David Howells   VFS: net/: d_inod...
645
  		if (d_really_is_negative(dentry))
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
646
  			goto next;
c5ef60352   David Howells   VFS: net/: d_inod...
647
  		switch (d_inode(dentry)->i_mode & S_IFMT) {
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
648
649
650
651
  			default:
  				BUG();
  			case S_IFREG:
  				__rpc_unlink(dir, dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
652
  				break;
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
653
654
655
656
657
  			case S_IFDIR:
  				__rpc_rmdir(dir, dentry);
  		}
  next:
  		dput(dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658
  	}
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
659
660
661
662
663
664
  }
  
  static void rpc_depopulate(struct dentry *parent,
  			   const struct rpc_filelist *files,
  			   int start, int eof)
  {
c5ef60352   David Howells   VFS: net/: d_inod...
665
  	struct inode *dir = d_inode(parent);
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
666

5955102c9   Al Viro   wrappers for ->i_...
667
  	inode_lock_nested(dir, I_MUTEX_CHILD);
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
668
  	__rpc_depopulate(parent, files, start, eof);
5955102c9   Al Viro   wrappers for ->i_...
669
  	inode_unlock(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
670
  }
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
671
672
673
674
  static int rpc_populate(struct dentry *parent,
  			const struct rpc_filelist *files,
  			int start, int eof,
  			void *private)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
675
  {
c5ef60352   David Howells   VFS: net/: d_inod...
676
  	struct inode *dir = d_inode(parent);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
677
  	struct dentry *dentry;
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
678
  	int i, err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679

5955102c9   Al Viro   wrappers for ->i_...
680
  	inode_lock(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
  	for (i = start; i < eof; i++) {
d3db90b0a   Al Viro   __rpc_lookup_crea...
682
  		dentry = __rpc_lookup_create_exclusive(parent, files[i].name);
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
683
684
  		err = PTR_ERR(dentry);
  		if (IS_ERR(dentry))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
685
  			goto out_bad;
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
686
687
688
689
690
691
692
693
694
695
696
697
698
699
  		switch (files[i].mode & S_IFMT) {
  			default:
  				BUG();
  			case S_IFREG:
  				err = __rpc_create(dir, dentry,
  						files[i].mode,
  						files[i].i_fop,
  						private);
  				break;
  			case S_IFDIR:
  				err = __rpc_mkdir(dir, dentry,
  						files[i].mode,
  						NULL,
  						private);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
700
  		}
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
701
702
  		if (err != 0)
  			goto out_bad;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703
  	}
5955102c9   Al Viro   wrappers for ->i_...
704
  	inode_unlock(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
705
706
  	return 0;
  out_bad:
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
707
  	__rpc_depopulate(parent, files, start, eof);
5955102c9   Al Viro   wrappers for ->i_...
708
  	inode_unlock(dir);
1e903edad   Al Viro   sunrpc: switch to...
709
710
711
  	printk(KERN_WARNING "%s: %s failed to populate directory %pd
  ",
  			__FILE__, __func__, parent);
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
712
  	return err;
f134585a7   Trond Myklebust   Revert "[PATCH] R...
713
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
714

e57aed77a   Trond Myklebust   SUNRPC: One more ...
715
  static struct dentry *rpc_mkdir_populate(struct dentry *parent,
a95e691f9   Al Viro   rpc_create_*_dir:...
716
  		const char *name, umode_t mode, void *private,
e57aed77a   Trond Myklebust   SUNRPC: One more ...
717
  		int (*populate)(struct dentry *, void *), void *args_populate)
f134585a7   Trond Myklebust   Revert "[PATCH] R...
718
  {
f134585a7   Trond Myklebust   Revert "[PATCH] R...
719
  	struct dentry *dentry;
c5ef60352   David Howells   VFS: net/: d_inod...
720
  	struct inode *dir = d_inode(parent);
f134585a7   Trond Myklebust   Revert "[PATCH] R...
721
  	int error;
5955102c9   Al Viro   wrappers for ->i_...
722
  	inode_lock_nested(dir, I_MUTEX_PARENT);
7d59d1e86   Trond Myklebust   SUNRPC: Clean up ...
723
  	dentry = __rpc_lookup_create_exclusive(parent, name);
f134585a7   Trond Myklebust   Revert "[PATCH] R...
724
  	if (IS_ERR(dentry))
7d59d1e86   Trond Myklebust   SUNRPC: Clean up ...
725
726
  		goto out;
  	error = __rpc_mkdir(dir, dentry, mode, NULL, private);
7589806e9   Trond Myklebust   SUNRPC: Clean up ...
727
728
  	if (error != 0)
  		goto out_err;
e57aed77a   Trond Myklebust   SUNRPC: One more ...
729
730
731
732
733
  	if (populate != NULL) {
  		error = populate(dentry, args_populate);
  		if (error)
  			goto err_rmdir;
  	}
f134585a7   Trond Myklebust   Revert "[PATCH] R...
734
  out:
5955102c9   Al Viro   wrappers for ->i_...
735
  	inode_unlock(dir);
5c3e985a2   Trond Myklebust   SUNRPC: Fix obvio...
736
  	return dentry;
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
737
  err_rmdir:
f134585a7   Trond Myklebust   Revert "[PATCH] R...
738
  	__rpc_rmdir(dir, dentry);
7589806e9   Trond Myklebust   SUNRPC: Clean up ...
739
  out_err:
f134585a7   Trond Myklebust   Revert "[PATCH] R...
740
741
  	dentry = ERR_PTR(error);
  	goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
  }
e57aed77a   Trond Myklebust   SUNRPC: One more ...
743
744
  static int rpc_rmdir_depopulate(struct dentry *dentry,
  		void (*depopulate)(struct dentry *))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
745
  {
dff02cc1a   Trond Myklebust   NFS: clean up rpc...
746
  	struct dentry *parent;
f134585a7   Trond Myklebust   Revert "[PATCH] R...
747
748
  	struct inode *dir;
  	int error;
278c995c8   Christoph Hellwig   [PATCH] RPC,NFS: ...
749

dff02cc1a   Trond Myklebust   NFS: clean up rpc...
750
  	parent = dget_parent(dentry);
c5ef60352   David Howells   VFS: net/: d_inod...
751
  	dir = d_inode(parent);
5955102c9   Al Viro   wrappers for ->i_...
752
  	inode_lock_nested(dir, I_MUTEX_PARENT);
e57aed77a   Trond Myklebust   SUNRPC: One more ...
753
754
  	if (depopulate != NULL)
  		depopulate(dentry);
f134585a7   Trond Myklebust   Revert "[PATCH] R...
755
  	error = __rpc_rmdir(dir, dentry);
5955102c9   Al Viro   wrappers for ->i_...
756
  	inode_unlock(dir);
dff02cc1a   Trond Myklebust   NFS: clean up rpc...
757
  	dput(parent);
f134585a7   Trond Myklebust   Revert "[PATCH] R...
758
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
759
  }
93a44a75b   J. Bruce Fields   sunrpc: document ...
760
761
762
763
764
  /**
   * rpc_mkpipe - make an rpc_pipefs file for kernel<->userspace communication
   * @parent: dentry of directory to create new "pipe" in
   * @name: name of pipe
   * @private: private data to associate with the pipe, for the caller's use
bda14606a   Randy Dunlap   sunrpc: fix kerne...
765
   * @pipe: &rpc_pipe containing input parameters
93a44a75b   J. Bruce Fields   sunrpc: document ...
766
767
768
769
770
771
772
773
774
775
   *
   * Data is made available for userspace to read by calls to
   * rpc_queue_upcall().  The actual reads will result in calls to
   * @ops->upcall, which will be called with the file pointer,
   * message, and userspace buffer to copy to.
   *
   * Writes can come at any time, and do not necessarily have to be
   * responses to upcalls.  They will result in calls to @msg->downcall.
   *
   * The @private argument passed here will be available to all these methods
496ad9aa8   Al Viro   new helper: file_...
776
   * from the file pointer, via RPC_I(file_inode(file))->private.
93a44a75b   J. Bruce Fields   sunrpc: document ...
777
   */
c239d83b9   Stanislav Kinsbursky   SUNRPC: split SUN...
778
779
  struct dentry *rpc_mkpipe_dentry(struct dentry *parent, const char *name,
  				 void *private, struct rpc_pipe *pipe)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
780
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
781
  	struct dentry *dentry;
c5ef60352   David Howells   VFS: net/: d_inod...
782
  	struct inode *dir = d_inode(parent);
d6444062f   Joe Perches   net: Use octal no...
783
  	umode_t umode = S_IFIFO | 0600;
7589806e9   Trond Myklebust   SUNRPC: Clean up ...
784
  	int err;
7364af6a2   Trond Myklebust   SUNRPC: Allow rpc...
785

c239d83b9   Stanislav Kinsbursky   SUNRPC: split SUN...
786
  	if (pipe->ops->upcall == NULL)
d6444062f   Joe Perches   net: Use octal no...
787
  		umode &= ~0444;
c239d83b9   Stanislav Kinsbursky   SUNRPC: split SUN...
788
  	if (pipe->ops->downcall == NULL)
d6444062f   Joe Perches   net: Use octal no...
789
  		umode &= ~0222;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
790

5955102c9   Al Viro   wrappers for ->i_...
791
  	inode_lock_nested(dir, I_MUTEX_PARENT);
d3db90b0a   Al Viro   __rpc_lookup_crea...
792
  	dentry = __rpc_lookup_create_exclusive(parent, name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
793
  	if (IS_ERR(dentry))
cfeaa4a3c   Trond Myklebust   SUNRPC: Clean up ...
794
  		goto out;
c239d83b9   Stanislav Kinsbursky   SUNRPC: split SUN...
795
796
  	err = __rpc_mkpipe_dentry(dir, dentry, umode, &rpc_pipe_fops,
  				  private, pipe);
7589806e9   Trond Myklebust   SUNRPC: Clean up ...
797
798
  	if (err)
  		goto out_err;
f134585a7   Trond Myklebust   Revert "[PATCH] R...
799
  out:
5955102c9   Al Viro   wrappers for ->i_...
800
  	inode_unlock(dir);
5c3e985a2   Trond Myklebust   SUNRPC: Fix obvio...
801
  	return dentry;
7589806e9   Trond Myklebust   SUNRPC: Clean up ...
802
803
  out_err:
  	dentry = ERR_PTR(err);
1e903edad   Al Viro   sunrpc: switch to...
804
805
806
  	printk(KERN_WARNING "%s: %s() failed to create pipe %pd/%s (errno = %d)
  ",
  			__FILE__, __func__, parent, name,
7589806e9   Trond Myklebust   SUNRPC: Clean up ...
807
  			err);
f134585a7   Trond Myklebust   Revert "[PATCH] R...
808
  	goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
809
  }
c239d83b9   Stanislav Kinsbursky   SUNRPC: split SUN...
810
  EXPORT_SYMBOL_GPL(rpc_mkpipe_dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
811

93a44a75b   J. Bruce Fields   sunrpc: document ...
812
813
814
815
816
817
818
819
  /**
   * rpc_unlink - remove a pipe
   * @dentry: dentry for the pipe, as returned from rpc_mkpipe
   *
   * After this call, lookups will no longer find the pipe, and any
   * attempts to read or write using preexisting opens of the pipe will
   * return -EPIPE.
   */
f134585a7   Trond Myklebust   Revert "[PATCH] R...
820
  int
5d67476ff   Trond Myklebust   SUNRPC: make rpc_...
821
  rpc_unlink(struct dentry *dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
822
  {
5d67476ff   Trond Myklebust   SUNRPC: make rpc_...
823
  	struct dentry *parent;
f134585a7   Trond Myklebust   Revert "[PATCH] R...
824
  	struct inode *dir;
5d67476ff   Trond Myklebust   SUNRPC: make rpc_...
825
  	int error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
826

5d67476ff   Trond Myklebust   SUNRPC: make rpc_...
827
  	parent = dget_parent(dentry);
c5ef60352   David Howells   VFS: net/: d_inod...
828
  	dir = d_inode(parent);
5955102c9   Al Viro   wrappers for ->i_...
829
  	inode_lock_nested(dir, I_MUTEX_PARENT);
810d90bc2   Trond Myklebust   SUNRPC: Clean up ...
830
  	error = __rpc_rmpipe(dir, dentry);
5955102c9   Al Viro   wrappers for ->i_...
831
  	inode_unlock(dir);
5d67476ff   Trond Myklebust   SUNRPC: make rpc_...
832
  	dput(parent);
f134585a7   Trond Myklebust   Revert "[PATCH] R...
833
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
834
  }
468039ee4   Trond Myklebust   SUNRPC: Convert t...
835
  EXPORT_SYMBOL_GPL(rpc_unlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
836

6739ffb75   Trond Myklebust   SUNRPC: Add a fra...
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
  /**
   * rpc_init_pipe_dir_head - initialise a struct rpc_pipe_dir_head
   * @pdh: pointer to struct rpc_pipe_dir_head
   */
  void rpc_init_pipe_dir_head(struct rpc_pipe_dir_head *pdh)
  {
  	INIT_LIST_HEAD(&pdh->pdh_entries);
  	pdh->pdh_dentry = NULL;
  }
  EXPORT_SYMBOL_GPL(rpc_init_pipe_dir_head);
  
  /**
   * rpc_init_pipe_dir_object - initialise a struct rpc_pipe_dir_object
   * @pdo: pointer to struct rpc_pipe_dir_object
   * @pdo_ops: pointer to const struct rpc_pipe_dir_object_ops
   * @pdo_data: pointer to caller-defined data
   */
  void rpc_init_pipe_dir_object(struct rpc_pipe_dir_object *pdo,
  		const struct rpc_pipe_dir_object_ops *pdo_ops,
  		void *pdo_data)
  {
  	INIT_LIST_HEAD(&pdo->pdo_head);
  	pdo->pdo_ops = pdo_ops;
  	pdo->pdo_data = pdo_data;
  }
  EXPORT_SYMBOL_GPL(rpc_init_pipe_dir_object);
  
  static int
  rpc_add_pipe_dir_object_locked(struct net *net,
  		struct rpc_pipe_dir_head *pdh,
  		struct rpc_pipe_dir_object *pdo)
  {
  	int ret = 0;
  
  	if (pdh->pdh_dentry)
  		ret = pdo->pdo_ops->create(pdh->pdh_dentry, pdo);
  	if (ret == 0)
  		list_add_tail(&pdo->pdo_head, &pdh->pdh_entries);
  	return ret;
  }
  
  static void
  rpc_remove_pipe_dir_object_locked(struct net *net,
  		struct rpc_pipe_dir_head *pdh,
  		struct rpc_pipe_dir_object *pdo)
  {
  	if (pdh->pdh_dentry)
  		pdo->pdo_ops->destroy(pdh->pdh_dentry, pdo);
  	list_del_init(&pdo->pdo_head);
  }
  
  /**
   * rpc_add_pipe_dir_object - associate a rpc_pipe_dir_object to a directory
   * @net: pointer to struct net
   * @pdh: pointer to struct rpc_pipe_dir_head
   * @pdo: pointer to struct rpc_pipe_dir_object
   *
   */
  int
  rpc_add_pipe_dir_object(struct net *net,
  		struct rpc_pipe_dir_head *pdh,
  		struct rpc_pipe_dir_object *pdo)
  {
  	int ret = 0;
  
  	if (list_empty(&pdo->pdo_head)) {
  		struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
  
  		mutex_lock(&sn->pipefs_sb_lock);
  		ret = rpc_add_pipe_dir_object_locked(net, pdh, pdo);
  		mutex_unlock(&sn->pipefs_sb_lock);
  	}
  	return ret;
  }
  EXPORT_SYMBOL_GPL(rpc_add_pipe_dir_object);
  
  /**
   * rpc_remove_pipe_dir_object - remove a rpc_pipe_dir_object from a directory
   * @net: pointer to struct net
   * @pdh: pointer to struct rpc_pipe_dir_head
   * @pdo: pointer to struct rpc_pipe_dir_object
   *
   */
  void
  rpc_remove_pipe_dir_object(struct net *net,
  		struct rpc_pipe_dir_head *pdh,
  		struct rpc_pipe_dir_object *pdo)
  {
  	if (!list_empty(&pdo->pdo_head)) {
  		struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
  
  		mutex_lock(&sn->pipefs_sb_lock);
  		rpc_remove_pipe_dir_object_locked(net, pdh, pdo);
  		mutex_unlock(&sn->pipefs_sb_lock);
  	}
  }
  EXPORT_SYMBOL_GPL(rpc_remove_pipe_dir_object);
298fc3558   Trond Myklebust   SUNRPC: Add a hel...
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
  /**
   * rpc_find_or_alloc_pipe_dir_object
   * @net: pointer to struct net
   * @pdh: pointer to struct rpc_pipe_dir_head
   * @match: match struct rpc_pipe_dir_object to data
   * @alloc: allocate a new struct rpc_pipe_dir_object
   * @data: user defined data for match() and alloc()
   *
   */
  struct rpc_pipe_dir_object *
  rpc_find_or_alloc_pipe_dir_object(struct net *net,
  		struct rpc_pipe_dir_head *pdh,
  		int (*match)(struct rpc_pipe_dir_object *, void *),
  		struct rpc_pipe_dir_object *(*alloc)(void *),
  		void *data)
  {
  	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
  	struct rpc_pipe_dir_object *pdo;
  
  	mutex_lock(&sn->pipefs_sb_lock);
  	list_for_each_entry(pdo, &pdh->pdh_entries, pdo_head) {
  		if (!match(pdo, data))
  			continue;
  		goto out;
  	}
  	pdo = alloc(data);
  	if (!pdo)
  		goto out;
  	rpc_add_pipe_dir_object_locked(net, pdh, pdo);
  out:
  	mutex_unlock(&sn->pipefs_sb_lock);
  	return pdo;
  }
  EXPORT_SYMBOL_GPL(rpc_find_or_alloc_pipe_dir_object);
6739ffb75   Trond Myklebust   SUNRPC: Add a fra...
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
  static void
  rpc_create_pipe_dir_objects(struct rpc_pipe_dir_head *pdh)
  {
  	struct rpc_pipe_dir_object *pdo;
  	struct dentry *dir = pdh->pdh_dentry;
  
  	list_for_each_entry(pdo, &pdh->pdh_entries, pdo_head)
  		pdo->pdo_ops->create(dir, pdo);
  }
  
  static void
  rpc_destroy_pipe_dir_objects(struct rpc_pipe_dir_head *pdh)
  {
  	struct rpc_pipe_dir_object *pdo;
  	struct dentry *dir = pdh->pdh_dentry;
  
  	list_for_each_entry(pdo, &pdh->pdh_entries, pdo_head)
  		pdo->pdo_ops->destroy(dir, pdo);
  }
e57aed77a   Trond Myklebust   SUNRPC: One more ...
987
988
989
990
991
992
993
994
995
  enum {
  	RPCAUTH_info,
  	RPCAUTH_EOF
  };
  
  static const struct rpc_filelist authfiles[] = {
  	[RPCAUTH_info] = {
  		.name = "info",
  		.i_fop = &rpc_info_operations,
d6444062f   Joe Perches   net: Use octal no...
996
  		.mode = S_IFREG | 0400,
e57aed77a   Trond Myklebust   SUNRPC: One more ...
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
  	},
  };
  
  static int rpc_clntdir_populate(struct dentry *dentry, void *private)
  {
  	return rpc_populate(dentry,
  			    authfiles, RPCAUTH_info, RPCAUTH_EOF,
  			    private);
  }
  
  static void rpc_clntdir_depopulate(struct dentry *dentry)
  {
  	rpc_depopulate(dentry, authfiles, RPCAUTH_info, RPCAUTH_EOF);
  }
7d59d1e86   Trond Myklebust   SUNRPC: Clean up ...
1011
1012
  /**
   * rpc_create_client_dir - Create a new rpc_client directory in rpc_pipefs
a95e691f9   Al Viro   rpc_create_*_dir:...
1013
1014
   * @dentry: the parent of new directory
   * @name: the name of new directory
7d59d1e86   Trond Myklebust   SUNRPC: Clean up ...
1015
1016
1017
1018
1019
1020
1021
   * @rpc_client: rpc client to associate with this directory
   *
   * This creates a directory at the given @path associated with
   * @rpc_clnt, which will contain a file named "info" with some basic
   * information about the client, together with any "pipes" that may
   * later be created using rpc_mkpipe().
   */
23ac65817   Trond Myklebust   SUNRPC: clean up ...
1022
  struct dentry *rpc_create_client_dir(struct dentry *dentry,
a95e691f9   Al Viro   rpc_create_*_dir:...
1023
  				   const char *name,
e57aed77a   Trond Myklebust   SUNRPC: One more ...
1024
1025
  				   struct rpc_clnt *rpc_client)
  {
6739ffb75   Trond Myklebust   SUNRPC: Add a fra...
1026
  	struct dentry *ret;
d6444062f   Joe Perches   net: Use octal no...
1027
1028
  	ret = rpc_mkdir_populate(dentry, name, 0555, NULL,
  				 rpc_clntdir_populate, rpc_client);
6739ffb75   Trond Myklebust   SUNRPC: Add a fra...
1029
1030
1031
1032
1033
  	if (!IS_ERR(ret)) {
  		rpc_client->cl_pipedir_objects.pdh_dentry = ret;
  		rpc_create_pipe_dir_objects(&rpc_client->cl_pipedir_objects);
  	}
  	return ret;
e57aed77a   Trond Myklebust   SUNRPC: One more ...
1034
1035
1036
1037
  }
  
  /**
   * rpc_remove_client_dir - Remove a directory created with rpc_create_client_dir()
6739ffb75   Trond Myklebust   SUNRPC: Add a fra...
1038
   * @rpc_client: rpc_client for the pipe
e57aed77a   Trond Myklebust   SUNRPC: One more ...
1039
   */
c36dcfe1f   Trond Myklebust   SUNRPC: Remove th...
1040
  int rpc_remove_client_dir(struct rpc_clnt *rpc_client)
7d59d1e86   Trond Myklebust   SUNRPC: Clean up ...
1041
  {
c36dcfe1f   Trond Myklebust   SUNRPC: Remove th...
1042
1043
1044
1045
1046
1047
  	struct dentry *dentry = rpc_client->cl_pipedir_objects.pdh_dentry;
  
  	if (dentry == NULL)
  		return 0;
  	rpc_destroy_pipe_dir_objects(&rpc_client->cl_pipedir_objects);
  	rpc_client->cl_pipedir_objects.pdh_dentry = NULL;
e57aed77a   Trond Myklebust   SUNRPC: One more ...
1048
  	return rpc_rmdir_depopulate(dentry, rpc_clntdir_depopulate);
7d59d1e86   Trond Myklebust   SUNRPC: Clean up ...
1049
  }
8854e82d9   Trond Myklebust   SUNRPC: Add an rp...
1050
1051
1052
1053
  static const struct rpc_filelist cache_pipefs_files[3] = {
  	[0] = {
  		.name = "channel",
  		.i_fop = &cache_file_operations_pipefs,
d6444062f   Joe Perches   net: Use octal no...
1054
  		.mode = S_IFREG | 0600,
8854e82d9   Trond Myklebust   SUNRPC: Add an rp...
1055
1056
1057
1058
  	},
  	[1] = {
  		.name = "content",
  		.i_fop = &content_file_operations_pipefs,
d6444062f   Joe Perches   net: Use octal no...
1059
  		.mode = S_IFREG | 0400,
8854e82d9   Trond Myklebust   SUNRPC: Add an rp...
1060
1061
1062
1063
  	},
  	[2] = {
  		.name = "flush",
  		.i_fop = &cache_flush_operations_pipefs,
d6444062f   Joe Perches   net: Use octal no...
1064
  		.mode = S_IFREG | 0600,
8854e82d9   Trond Myklebust   SUNRPC: Add an rp...
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
  	},
  };
  
  static int rpc_cachedir_populate(struct dentry *dentry, void *private)
  {
  	return rpc_populate(dentry,
  			    cache_pipefs_files, 0, 3,
  			    private);
  }
  
  static void rpc_cachedir_depopulate(struct dentry *dentry)
  {
  	rpc_depopulate(dentry, cache_pipefs_files, 0, 3);
  }
a95e691f9   Al Viro   rpc_create_*_dir:...
1079
  struct dentry *rpc_create_cache_dir(struct dentry *parent, const char *name,
64f1426f3   Al Viro   sunrpc: propagate...
1080
  				    umode_t umode, struct cache_detail *cd)
8854e82d9   Trond Myklebust   SUNRPC: Add an rp...
1081
1082
1083
1084
1085
1086
1087
1088
1089
  {
  	return rpc_mkdir_populate(parent, name, umode, NULL,
  			rpc_cachedir_populate, cd);
  }
  
  void rpc_remove_cache_dir(struct dentry *dentry)
  {
  	rpc_rmdir_depopulate(dentry, rpc_cachedir_depopulate);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1090
1091
1092
  /*
   * populate the filesystem
   */
b87221de6   Alexey Dobriyan   const: mark remai...
1093
  static const struct super_operations s_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1094
  	.alloc_inode	= rpc_alloc_inode,
bef252fa1   Al Viro   rpcpipe: switch t...
1095
  	.free_inode	= rpc_free_inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1096
1097
1098
1099
  	.statfs		= simple_statfs,
  };
  
  #define RPCAUTH_GSSMAGIC 0x67596969
bb1567491   Trond Myklebust   SUNRPC: rpc_pipef...
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
  /*
   * We have a single directory with 1 node in it.
   */
  enum {
  	RPCAUTH_lockd,
  	RPCAUTH_mount,
  	RPCAUTH_nfs,
  	RPCAUTH_portmap,
  	RPCAUTH_statd,
  	RPCAUTH_nfsd4_cb,
e571cbf1a   Trond Myklebust   NFS: Add a dns re...
1110
  	RPCAUTH_cache,
b3537c35c   Jeff Layton   sunrpc: create nf...
1111
  	RPCAUTH_nfsd,
4b9a445e3   Jeff Layton   sunrpc: create a ...
1112
  	RPCAUTH_gssd,
bb1567491   Trond Myklebust   SUNRPC: rpc_pipef...
1113
1114
1115
1116
1117
1118
  	RPCAUTH_RootEOF
  };
  
  static const struct rpc_filelist files[] = {
  	[RPCAUTH_lockd] = {
  		.name = "lockd",
d6444062f   Joe Perches   net: Use octal no...
1119
  		.mode = S_IFDIR | 0555,
bb1567491   Trond Myklebust   SUNRPC: rpc_pipef...
1120
1121
1122
  	},
  	[RPCAUTH_mount] = {
  		.name = "mount",
d6444062f   Joe Perches   net: Use octal no...
1123
  		.mode = S_IFDIR | 0555,
bb1567491   Trond Myklebust   SUNRPC: rpc_pipef...
1124
1125
1126
  	},
  	[RPCAUTH_nfs] = {
  		.name = "nfs",
d6444062f   Joe Perches   net: Use octal no...
1127
  		.mode = S_IFDIR | 0555,
bb1567491   Trond Myklebust   SUNRPC: rpc_pipef...
1128
1129
1130
  	},
  	[RPCAUTH_portmap] = {
  		.name = "portmap",
d6444062f   Joe Perches   net: Use octal no...
1131
  		.mode = S_IFDIR | 0555,
bb1567491   Trond Myklebust   SUNRPC: rpc_pipef...
1132
1133
1134
  	},
  	[RPCAUTH_statd] = {
  		.name = "statd",
d6444062f   Joe Perches   net: Use octal no...
1135
  		.mode = S_IFDIR | 0555,
bb1567491   Trond Myklebust   SUNRPC: rpc_pipef...
1136
1137
1138
  	},
  	[RPCAUTH_nfsd4_cb] = {
  		.name = "nfsd4_cb",
d6444062f   Joe Perches   net: Use octal no...
1139
  		.mode = S_IFDIR | 0555,
bb1567491   Trond Myklebust   SUNRPC: rpc_pipef...
1140
  	},
e571cbf1a   Trond Myklebust   NFS: Add a dns re...
1141
1142
  	[RPCAUTH_cache] = {
  		.name = "cache",
d6444062f   Joe Perches   net: Use octal no...
1143
  		.mode = S_IFDIR | 0555,
e571cbf1a   Trond Myklebust   NFS: Add a dns re...
1144
  	},
b3537c35c   Jeff Layton   sunrpc: create nf...
1145
1146
  	[RPCAUTH_nfsd] = {
  		.name = "nfsd",
d6444062f   Joe Perches   net: Use octal no...
1147
  		.mode = S_IFDIR | 0555,
b3537c35c   Jeff Layton   sunrpc: create nf...
1148
  	},
4b9a445e3   Jeff Layton   sunrpc: create a ...
1149
1150
  	[RPCAUTH_gssd] = {
  		.name = "gssd",
d6444062f   Joe Perches   net: Use octal no...
1151
  		.mode = S_IFDIR | 0555,
4b9a445e3   Jeff Layton   sunrpc: create a ...
1152
  	},
bb1567491   Trond Myklebust   SUNRPC: rpc_pipef...
1153
  };
432eb1a5f   Stanislav Kinsbursky   SUNRPC: pipefs de...
1154
1155
1156
1157
1158
1159
  /*
   * This call can be used only in RPC pipefs mount notification hooks.
   */
  struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
  			       const unsigned char *dir_name)
  {
26fe57502   Linus Torvalds   vfs: make it poss...
1160
  	struct qstr dir = QSTR_INIT(dir_name, strlen(dir_name));
d3db90b0a   Al Viro   __rpc_lookup_crea...
1161
  	return d_hash_and_lookup(sb->s_root, &dir);
432eb1a5f   Stanislav Kinsbursky   SUNRPC: pipefs de...
1162
1163
  }
  EXPORT_SYMBOL_GPL(rpc_d_lookup_sb);
4b9a445e3   Jeff Layton   sunrpc: create a ...
1164
  int rpc_pipefs_init_net(struct net *net)
c21a588f3   Stanislav Kinsbursky   SUNRPC: pipefs pe...
1165
1166
  {
  	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
4b9a445e3   Jeff Layton   sunrpc: create a ...
1167
1168
1169
  	sn->gssd_dummy = rpc_mkpipe_data(&gssd_dummy_pipe_ops, 0);
  	if (IS_ERR(sn->gssd_dummy))
  		return PTR_ERR(sn->gssd_dummy);
c21a588f3   Stanislav Kinsbursky   SUNRPC: pipefs pe...
1170
  	mutex_init(&sn->pipefs_sb_lock);
2aed8b476   Trond Myklebust   SUNRPC: Convert a...
1171
  	sn->pipe_version = -1;
4b9a445e3   Jeff Layton   sunrpc: create a ...
1172
1173
1174
1175
1176
1177
1178
1179
  	return 0;
  }
  
  void rpc_pipefs_exit_net(struct net *net)
  {
  	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
  
  	rpc_destroy_pipe_data(sn->gssd_dummy);
c21a588f3   Stanislav Kinsbursky   SUNRPC: pipefs pe...
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
  }
  
  /*
   * This call will be used for per network namespace operations calls.
   * Note: Function will be returned with pipefs_sb_lock taken if superblock was
   * found. This lock have to be released by rpc_put_sb_net() when all operations
   * will be completed.
   */
  struct super_block *rpc_get_sb_net(const struct net *net)
  {
  	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
  
  	mutex_lock(&sn->pipefs_sb_lock);
  	if (sn->pipefs_sb)
  		return sn->pipefs_sb;
  	mutex_unlock(&sn->pipefs_sb_lock);
  	return NULL;
  }
  EXPORT_SYMBOL_GPL(rpc_get_sb_net);
  
  void rpc_put_sb_net(const struct net *net)
  {
  	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
749386e90   Weston Andros Adamson   SUNRPC: remove BU...
1203
  	WARN_ON(sn->pipefs_sb == NULL);
c21a588f3   Stanislav Kinsbursky   SUNRPC: pipefs pe...
1204
1205
1206
  	mutex_unlock(&sn->pipefs_sb_lock);
  }
  EXPORT_SYMBOL_GPL(rpc_put_sb_net);
4b9a445e3   Jeff Layton   sunrpc: create a ...
1207
1208
1209
  static const struct rpc_filelist gssd_dummy_clnt_dir[] = {
  	[0] = {
  		.name = "clntXX",
d6444062f   Joe Perches   net: Use octal no...
1210
  		.mode = S_IFDIR | 0555,
4b9a445e3   Jeff Layton   sunrpc: create a ...
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
  	},
  };
  
  static ssize_t
  dummy_downcall(struct file *filp, const char __user *src, size_t len)
  {
  	return -EINVAL;
  }
  
  static const struct rpc_pipe_ops gssd_dummy_pipe_ops = {
  	.upcall		= rpc_pipe_generic_upcall,
  	.downcall	= dummy_downcall,
  };
e2f0c83a9   Jeff Layton   sunrpc: add an "i...
1224
1225
1226
1227
1228
1229
  /*
   * Here we present a bogus "info" file to keep rpc.gssd happy. We don't expect
   * that it will ever use this info to handle an upcall, but rpc.gssd expects
   * that this file will be there and have a certain format.
   */
  static int
260f71eff   Yangtao Li   sunrpc: convert t...
1230
  rpc_dummy_info_show(struct seq_file *m, void *v)
e2f0c83a9   Jeff Layton   sunrpc: add an "i...
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
  {
  	seq_printf(m, "RPC server: %s
  ", utsname()->nodename);
  	seq_printf(m, "service: foo (1) version 0
  ");
  	seq_printf(m, "address: 127.0.0.1
  ");
  	seq_printf(m, "protocol: tcp
  ");
  	seq_printf(m, "port: 0
  ");
  	return 0;
  }
260f71eff   Yangtao Li   sunrpc: convert t...
1244
  DEFINE_SHOW_ATTRIBUTE(rpc_dummy_info);
e2f0c83a9   Jeff Layton   sunrpc: add an "i...
1245
1246
1247
1248
  
  static const struct rpc_filelist gssd_dummy_info_file[] = {
  	[0] = {
  		.name = "info",
260f71eff   Yangtao Li   sunrpc: convert t...
1249
  		.i_fop = &rpc_dummy_info_fops,
d6444062f   Joe Perches   net: Use octal no...
1250
  		.mode = S_IFREG | 0400,
e2f0c83a9   Jeff Layton   sunrpc: add an "i...
1251
1252
  	},
  };
4b9a445e3   Jeff Layton   sunrpc: create a ...
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
  /**
   * rpc_gssd_dummy_populate - create a dummy gssd pipe
   * @root:	root of the rpc_pipefs filesystem
   * @pipe_data:	pipe data created when netns is initialized
   *
   * Create a dummy set of directories and a pipe that gssd can hold open to
   * indicate that it is up and running.
   */
  static struct dentry *
  rpc_gssd_dummy_populate(struct dentry *root, struct rpc_pipe *pipe_data)
  {
  	int ret = 0;
  	struct dentry *gssd_dentry;
  	struct dentry *clnt_dentry = NULL;
  	struct dentry *pipe_dentry = NULL;
  	struct qstr q = QSTR_INIT(files[RPCAUTH_gssd].name,
  				  strlen(files[RPCAUTH_gssd].name));
  
  	/* We should never get this far if "gssd" doesn't exist */
  	gssd_dentry = d_hash_and_lookup(root, &q);
  	if (!gssd_dentry)
  		return ERR_PTR(-ENOENT);
  
  	ret = rpc_populate(gssd_dentry, gssd_dummy_clnt_dir, 0, 1, NULL);
  	if (ret) {
  		pipe_dentry = ERR_PTR(ret);
  		goto out;
  	}
  
  	q.name = gssd_dummy_clnt_dir[0].name;
  	q.len = strlen(gssd_dummy_clnt_dir[0].name);
  	clnt_dentry = d_hash_and_lookup(gssd_dentry, &q);
  	if (!clnt_dentry) {
b7ade3816   Vasily Averin   sunrpc: fixed rol...
1286
  		__rpc_depopulate(gssd_dentry, gssd_dummy_clnt_dir, 0, 1);
4b9a445e3   Jeff Layton   sunrpc: create a ...
1287
1288
1289
  		pipe_dentry = ERR_PTR(-ENOENT);
  		goto out;
  	}
e2f0c83a9   Jeff Layton   sunrpc: add an "i...
1290
1291
1292
1293
1294
1295
  	ret = rpc_populate(clnt_dentry, gssd_dummy_info_file, 0, 1, NULL);
  	if (ret) {
  		__rpc_depopulate(gssd_dentry, gssd_dummy_clnt_dir, 0, 1);
  		pipe_dentry = ERR_PTR(ret);
  		goto out;
  	}
4b9a445e3   Jeff Layton   sunrpc: create a ...
1296
  	pipe_dentry = rpc_mkpipe_dentry(clnt_dentry, "gssd", NULL, pipe_data);
e2f0c83a9   Jeff Layton   sunrpc: add an "i...
1297
1298
  	if (IS_ERR(pipe_dentry)) {
  		__rpc_depopulate(clnt_dentry, gssd_dummy_info_file, 0, 1);
3396f92f8   Jeff Layton   rpc_pipe: remove ...
1299
  		__rpc_depopulate(gssd_dentry, gssd_dummy_clnt_dir, 0, 1);
e2f0c83a9   Jeff Layton   sunrpc: add an "i...
1300
  	}
4b9a445e3   Jeff Layton   sunrpc: create a ...
1301
1302
1303
1304
1305
  out:
  	dput(clnt_dentry);
  	dput(gssd_dentry);
  	return pipe_dentry;
  }
23e66ba97   Jeff Layton   rpc_pipe: fix cle...
1306
1307
1308
1309
1310
  static void
  rpc_gssd_dummy_depopulate(struct dentry *pipe_dentry)
  {
  	struct dentry *clnt_dir = pipe_dentry->d_parent;
  	struct dentry *gssd_dir = clnt_dir->d_parent;
4a3877c4c   Al Viro   rpc_pipefs: fix d...
1311
  	dget(pipe_dentry);
c5ef60352   David Howells   VFS: net/: d_inod...
1312
  	__rpc_rmpipe(d_inode(clnt_dir), pipe_dentry);
23e66ba97   Jeff Layton   rpc_pipe: fix cle...
1313
1314
1315
1316
  	__rpc_depopulate(clnt_dir, gssd_dummy_info_file, 0, 1);
  	__rpc_depopulate(gssd_dir, gssd_dummy_clnt_dir, 0, 1);
  	dput(pipe_dentry);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1317
  static int
b9662f310   David Howells   vfs: Convert rpc_...
1318
  rpc_fill_super(struct super_block *sb, struct fs_context *fc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1319
1320
  {
  	struct inode *inode;
4b9a445e3   Jeff Layton   sunrpc: create a ...
1321
  	struct dentry *root, *gssd_dentry;
b9662f310   David Howells   vfs: Convert rpc_...
1322
  	struct net *net = sb->s_fs_info;
90c4e8299   Stanislav Kinsbursky   SUNRPC: put pipef...
1323
  	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
2d00131ac   Stanislav Kinsbursky   SUNRPC: send noti...
1324
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1325

09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1326
1327
  	sb->s_blocksize = PAGE_SIZE;
  	sb->s_blocksize_bits = PAGE_SHIFT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1328
1329
  	sb->s_magic = RPCAUTH_GSSMAGIC;
  	sb->s_op = &s_ops;
b26d4cd38   Al Viro   consolidate simpl...
1330
  	sb->s_d_op = &simple_dentry_operations;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1331
  	sb->s_time_gran = 1;
d6444062f   Joe Perches   net: Use octal no...
1332
  	inode = rpc_get_inode(sb, S_IFDIR | 0555);
48fde701a   Al Viro   switch open-coded...
1333
1334
  	sb->s_root = root = d_make_root(inode);
  	if (!root)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1335
  		return -ENOMEM;
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
1336
  	if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL))
fc7bed8c8   Al Viro   Don't bother with...
1337
  		return -ENOMEM;
4b9a445e3   Jeff Layton   sunrpc: create a ...
1338
1339
1340
1341
1342
1343
  
  	gssd_dentry = rpc_gssd_dummy_populate(root, sn->gssd_dummy);
  	if (IS_ERR(gssd_dentry)) {
  		__rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF);
  		return PTR_ERR(gssd_dentry);
  	}
6c67a3e4a   Vasily Averin   sunrpc: remove ne...
1344
1345
1346
  	dprintk("RPC:       sending pipefs MOUNT notification for net %x%s
  ",
  		net->ns.inum, NET_NAME(net));
384816051   Stanislav Kinsbursky   SUNRPC: fix races...
1347
  	mutex_lock(&sn->pipefs_sb_lock);
37629b572   Stanislav Kinsbursky   SUNRPC: set per-n...
1348
  	sn->pipefs_sb = sb;
2d00131ac   Stanislav Kinsbursky   SUNRPC: send noti...
1349
1350
1351
1352
1353
  	err = blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
  					   RPC_PIPEFS_MOUNT,
  					   sb);
  	if (err)
  		goto err_depopulate;
384816051   Stanislav Kinsbursky   SUNRPC: fix races...
1354
  	mutex_unlock(&sn->pipefs_sb_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1355
  	return 0;
2d00131ac   Stanislav Kinsbursky   SUNRPC: send noti...
1356
1357
  
  err_depopulate:
23e66ba97   Jeff Layton   rpc_pipe: fix cle...
1358
  	rpc_gssd_dummy_depopulate(gssd_dentry);
2d00131ac   Stanislav Kinsbursky   SUNRPC: send noti...
1359
1360
1361
  	blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
  					   RPC_PIPEFS_UMOUNT,
  					   sb);
37629b572   Stanislav Kinsbursky   SUNRPC: set per-n...
1362
  	sn->pipefs_sb = NULL;
2d00131ac   Stanislav Kinsbursky   SUNRPC: send noti...
1363
  	__rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF);
384816051   Stanislav Kinsbursky   SUNRPC: fix races...
1364
  	mutex_unlock(&sn->pipefs_sb_lock);
2d00131ac   Stanislav Kinsbursky   SUNRPC: send noti...
1365
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1366
  }
89f842435   Jeff Layton   sunrpc: replace s...
1367
1368
1369
1370
1371
1372
1373
1374
1375
  bool
  gssd_running(struct net *net)
  {
  	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
  	struct rpc_pipe *pipe = sn->gssd_dummy;
  
  	return pipe->nreaders || pipe->nwriters;
  }
  EXPORT_SYMBOL_GPL(gssd_running);
b9662f310   David Howells   vfs: Convert rpc_...
1376
1377
  static int rpc_fs_get_tree(struct fs_context *fc)
  {
533770cc0   Al Viro   new helper: get_t...
1378
  	return get_tree_keyed(fc, rpc_fill_super, get_net(fc->net_ns));
b9662f310   David Howells   vfs: Convert rpc_...
1379
1380
1381
  }
  
  static void rpc_fs_free_fc(struct fs_context *fc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1382
  {
b9662f310   David Howells   vfs: Convert rpc_...
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
  	if (fc->s_fs_info)
  		put_net(fc->s_fs_info);
  }
  
  static const struct fs_context_operations rpc_fs_context_ops = {
  	.free		= rpc_fs_free_fc,
  	.get_tree	= rpc_fs_get_tree,
  };
  
  static int rpc_init_fs_context(struct fs_context *fc)
  {
  	put_user_ns(fc->user_ns);
  	fc->user_ns = get_user_ns(fc->net_ns->user_ns);
  	fc->ops = &rpc_fs_context_ops;
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1398
  }
09acfea5d   Trond Myklebust   SUNRPC: Fix a few...
1399
  static void rpc_kill_sb(struct super_block *sb)
021c68dec   Stanislav Kinsbursky   SUNRPC: hold curr...
1400
1401
  {
  	struct net *net = sb->s_fs_info;
90c4e8299   Stanislav Kinsbursky   SUNRPC: put pipef...
1402
  	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
021c68dec   Stanislav Kinsbursky   SUNRPC: hold curr...
1403

c21a588f3   Stanislav Kinsbursky   SUNRPC: pipefs pe...
1404
  	mutex_lock(&sn->pipefs_sb_lock);
642fe4d00   Trond Myklebust   SUNRPC: Fix valid...
1405
1406
1407
1408
  	if (sn->pipefs_sb != sb) {
  		mutex_unlock(&sn->pipefs_sb_lock);
  		goto out;
  	}
90c4e8299   Stanislav Kinsbursky   SUNRPC: put pipef...
1409
  	sn->pipefs_sb = NULL;
6c67a3e4a   Vasily Averin   sunrpc: remove ne...
1410
1411
1412
  	dprintk("RPC:       sending pipefs UMOUNT notification for net %x%s
  ",
  		net->ns.inum, NET_NAME(net));
2d00131ac   Stanislav Kinsbursky   SUNRPC: send noti...
1413
1414
1415
  	blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
  					   RPC_PIPEFS_UMOUNT,
  					   sb);
adb6fa7ff   Stanislav Kinsbursky   SUNRPC: fix races...
1416
  	mutex_unlock(&sn->pipefs_sb_lock);
642fe4d00   Trond Myklebust   SUNRPC: Fix valid...
1417
  out:
021c68dec   Stanislav Kinsbursky   SUNRPC: hold curr...
1418
  	kill_litter_super(sb);
d91ee87d8   Eric W. Biederman   vfs: Pass data, n...
1419
  	put_net(net);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1420
1421
1422
1423
1424
  }
  
  static struct file_system_type rpc_pipe_fs_type = {
  	.owner		= THIS_MODULE,
  	.name		= "rpc_pipefs",
b9662f310   David Howells   vfs: Convert rpc_...
1425
  	.init_fs_context = rpc_init_fs_context,
021c68dec   Stanislav Kinsbursky   SUNRPC: hold curr...
1426
  	.kill_sb	= rpc_kill_sb,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1427
  };
7f78e0351   Eric W. Biederman   fs: Limit sys_mou...
1428
  MODULE_ALIAS_FS("rpc_pipefs");
fa7614ddd   Eric W. Biederman   fs: Readd the fs ...
1429
  MODULE_ALIAS("rpc_pipefs");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1430
1431
  
  static void
51cc50685   Alexey Dobriyan   SL*B: drop kmem c...
1432
  init_once(void *foo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1433
1434
  {
  	struct rpc_inode *rpci = (struct rpc_inode *) foo;
a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
1435
1436
  	inode_init_once(&rpci->vfs_inode);
  	rpci->private = NULL;
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
1437
  	rpci->pipe = NULL;
a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
1438
  	init_waitqueue_head(&rpci->waitq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1439
1440
1441
1442
  }
  
  int register_rpc_pipefs(void)
  {
5bd5f5812   Akinobu Mita   sunrpc: fix error...
1443
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1444
  	rpc_inode_cachep = kmem_cache_create("rpc_inode_cache",
fffb60f93   Paul Jackson   [PATCH] cpuset me...
1445
1446
  				sizeof(struct rpc_inode),
  				0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
5d097056c   Vladimir Davydov   kmemcg: account c...
1447
  						SLAB_MEM_SPREAD|SLAB_ACCOUNT),
20c2df83d   Paul Mundt   mm: Remove slab d...
1448
  				init_once);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1449
1450
  	if (!rpc_inode_cachep)
  		return -ENOMEM;
80df9d202   Stanislav Kinsbursky   SUNRPC: subscribe...
1451
1452
1453
  	err = rpc_clients_notifier_register();
  	if (err)
  		goto err_notifier;
5bd5f5812   Akinobu Mita   sunrpc: fix error...
1454
  	err = register_filesystem(&rpc_pipe_fs_type);
80df9d202   Stanislav Kinsbursky   SUNRPC: subscribe...
1455
1456
  	if (err)
  		goto err_register;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1457
  	return 0;
80df9d202   Stanislav Kinsbursky   SUNRPC: subscribe...
1458
1459
1460
1461
1462
1463
  
  err_register:
  	rpc_clients_notifier_unregister();
  err_notifier:
  	kmem_cache_destroy(rpc_inode_cachep);
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1464
1465
1466
1467
  }
  
  void unregister_rpc_pipefs(void)
  {
80df9d202   Stanislav Kinsbursky   SUNRPC: subscribe...
1468
  	rpc_clients_notifier_unregister();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1469
  	unregister_filesystem(&rpc_pipe_fs_type);
4a400f0d0   Dan Aloni   sunrpc: destroy r...
1470
  	kmem_cache_destroy(rpc_inode_cachep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1471
  }