Blame view

net/sunrpc/rpc_pipe.c 36.3 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
  /*
   * 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...
6
   * and fs/sysfs/inode.c
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
9
10
   *
   * Copyright (c) 2002, Trond Myklebust <trond.myklebust@fys.uio.no>
   *
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
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>
  #include <linux/namei.h>
50e437d52   Trond Myklebust   SUNRPC: Convert r...
17
  #include <linux/fsnotify.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
  #include <linux/kernel.h>
2446ab607   Trond Myklebust   SUNRPC: Use RCU t...
19
  #include <linux/rcupdate.h>
e2f0c83a9   Jeff Layton   sunrpc: add an "i...
20
  #include <linux/utsname.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
  
  #include <asm/ioctls.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
25
26
27
28
29
  #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...
30
  #include <linux/sunrpc/cache.h>
021c68dec   Stanislav Kinsbursky   SUNRPC: hold curr...
31
  #include <linux/nsproxy.h>
2d00131ac   Stanislav Kinsbursky   SUNRPC: send noti...
32
  #include <linux/notifier.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33

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

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

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

ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
86
  	spin_lock(&pipe->lock);
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
87
88
89
90
  	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...
91
  	}
591ad7fea   Stanislav Kinsbursky   SUNRPC: move wait...
92
  	dentry = dget(pipe->dentry);
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
93
  	spin_unlock(&pipe->lock);
c5ef60352   David Howells   VFS: net/: d_inod...
94
  	rpc_purge_list(dentry ? &RPC_I(d_inode(dentry))->waitq : NULL,
92123e068   Jeff Layton   rpc_pipefs: allow...
95
96
  			&free_list, destroy_msg, -ETIMEDOUT);
  	dput(dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
  }
c1225158a   Peng Tao   SUNRPC/NFS: make ...
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  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 ...
117
  /**
1a5778aa0   Ben Hutchings   net: Fix first li...
118
   * rpc_queue_upcall - queue an upcall message to userspace
bda14606a   Randy Dunlap   sunrpc: fix kerne...
119
   * @pipe: upcall pipe on which to queue given message
93a44a75b   J. Bruce Fields   sunrpc: document ...
120
121
122
123
124
125
126
   * @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
127
  int
d706ed1f5   Stanislav Kinsbursky   SUNPRC: cleanup R...
128
  rpc_queue_upcall(struct rpc_pipe *pipe, struct rpc_pipe_msg *msg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
  {
6070fe6f8   Trond Myklebust   RPC: Ensure that ...
130
  	int res = -EPIPE;
591ad7fea   Stanislav Kinsbursky   SUNRPC: move wait...
131
  	struct dentry *dentry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132

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

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

5955102c9   Al Viro   wrappers for ->i_...
169
  	inode_lock(inode);
ad6b13400   Stanislav Kinsbursky   SUNRPC: fix pipe-...
170
171
172
173
174
175
176
177
  	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...
178
  	rpc_purge_list(&RPC_I(inode)->waitq, &free_list, pipe->ops->destroy_msg, -EPIPE);
ad6b13400   Stanislav Kinsbursky   SUNRPC: fix pipe-...
179
180
181
182
  	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 ...
183
  	rpc_inode_setowner(inode, NULL);
2c9030eef   Stanislav Kinsbursky   SUNRPC: check RPC...
184
  	RPC_I(inode)->pipe = NULL;
5955102c9   Al Viro   wrappers for ->i_...
185
  	inode_unlock(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
188
189
190
  static struct inode *
  rpc_alloc_inode(struct super_block *sb)
  {
  	struct rpc_inode *rpci;
adcda652c   Himangi Saraogi   rpc_pipe: Drop me...
191
  	rpci = kmem_cache_alloc(rpc_inode_cachep, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
193
194
195
196
197
  	if (!rpci)
  		return NULL;
  	return &rpci->vfs_inode;
  }
  
  static void
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
198
  rpc_i_callback(struct rcu_head *head)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
  {
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
200
  	struct inode *inode = container_of(head, struct inode, i_rcu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
202
  	kmem_cache_free(rpc_inode_cachep, RPC_I(inode));
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
203
204
205
206
207
  static void
  rpc_destroy_inode(struct inode *inode)
  {
  	call_rcu(&inode->i_rcu, rpc_i_callback);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
209
210
  static int
  rpc_pipe_open(struct inode *inode, struct file *filp)
  {
2c9030eef   Stanislav Kinsbursky   SUNRPC: check RPC...
211
  	struct rpc_pipe *pipe;
c38106086   \"J. Bruce Fields\   rpc: add an rpc_p...
212
  	int first_open;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
  	int res = -ENXIO;
5955102c9   Al Viro   wrappers for ->i_...
214
  	inode_lock(inode);
2c9030eef   Stanislav Kinsbursky   SUNRPC: check RPC...
215
216
  	pipe = RPC_I(inode)->pipe;
  	if (pipe == NULL)
c38106086   \"J. Bruce Fields\   rpc: add an rpc_p...
217
  		goto out;
d0fe13ba9   Stanislav Kinsbursky   SUNRPC: cleanup P...
218
219
220
  	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...
221
222
  		if (res)
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
  	}
c38106086   \"J. Bruce Fields\   rpc: add an rpc_p...
224
  	if (filp->f_mode & FMODE_READ)
d0fe13ba9   Stanislav Kinsbursky   SUNRPC: cleanup P...
225
  		pipe->nreaders++;
c38106086   \"J. Bruce Fields\   rpc: add an rpc_p...
226
  	if (filp->f_mode & FMODE_WRITE)
d0fe13ba9   Stanislav Kinsbursky   SUNRPC: cleanup P...
227
  		pipe->nwriters++;
c38106086   \"J. Bruce Fields\   rpc: add an rpc_p...
228
229
  	res = 0;
  out:
5955102c9   Al Viro   wrappers for ->i_...
230
  	inode_unlock(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231
232
233
234
235
236
  	return res;
  }
  
  static int
  rpc_pipe_release(struct inode *inode, struct file *filp)
  {
2c9030eef   Stanislav Kinsbursky   SUNRPC: check RPC...
237
  	struct rpc_pipe *pipe;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
  	struct rpc_pipe_msg *msg;
e712804ae   \"J. Bruce Fields\   rpc: call release...
239
  	int last_close;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240

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

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

c239d83b9   Stanislav Kinsbursky   SUNRPC: split SUN...
545
546
547
  void rpc_destroy_pipe_data(struct rpc_pipe *pipe)
  {
  	kfree(pipe);
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
548
  }
c239d83b9   Stanislav Kinsbursky   SUNRPC: split SUN...
549
  EXPORT_SYMBOL_GPL(rpc_destroy_pipe_data);
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
550

c239d83b9   Stanislav Kinsbursky   SUNRPC: split SUN...
551
  struct rpc_pipe *rpc_mkpipe_data(const struct rpc_pipe_ops *ops, int flags)
7589806e9   Trond Myklebust   SUNRPC: Clean up ...
552
  {
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
553
  	struct rpc_pipe *pipe;
7589806e9   Trond Myklebust   SUNRPC: Clean up ...
554

ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
555
556
  	pipe = kzalloc(sizeof(struct rpc_pipe), GFP_KERNEL);
  	if (!pipe)
c239d83b9   Stanislav Kinsbursky   SUNRPC: split SUN...
557
  		return ERR_PTR(-ENOMEM);
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
558
  	init_pipe(pipe);
c239d83b9   Stanislav Kinsbursky   SUNRPC: split SUN...
559
560
561
562
563
564
565
566
567
568
569
  	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 ...
570
571
572
573
574
575
576
  {
  	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...
577
  	rpci = RPC_I(d_inode(dentry));
7589806e9   Trond Myklebust   SUNRPC: Clean up ...
578
  	rpci->private = private;
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
579
  	rpci->pipe = pipe;
7589806e9   Trond Myklebust   SUNRPC: Clean up ...
580
581
582
  	fsnotify_create(dir, dentry);
  	return 0;
  }
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
583
584
585
586
587
588
589
590
591
592
  static int __rpc_rmdir(struct inode *dir, struct dentry *dentry)
  {
  	int ret;
  
  	dget(dentry);
  	ret = simple_rmdir(dir, dentry);
  	d_delete(dentry);
  	dput(dentry);
  	return ret;
  }
eee17325f   Stanislav Kinsbursky   NFS: idmap PipeFS...
593
594
595
596
597
598
599
  int rpc_rmdir(struct dentry *dentry)
  {
  	struct dentry *parent;
  	struct inode *dir;
  	int error;
  
  	parent = dget_parent(dentry);
c5ef60352   David Howells   VFS: net/: d_inod...
600
  	dir = d_inode(parent);
5955102c9   Al Viro   wrappers for ->i_...
601
  	inode_lock_nested(dir, I_MUTEX_PARENT);
eee17325f   Stanislav Kinsbursky   NFS: idmap PipeFS...
602
  	error = __rpc_rmdir(dir, dentry);
5955102c9   Al Viro   wrappers for ->i_...
603
  	inode_unlock(dir);
eee17325f   Stanislav Kinsbursky   NFS: idmap PipeFS...
604
605
606
607
  	dput(parent);
  	return error;
  }
  EXPORT_SYMBOL_GPL(rpc_rmdir);
810d90bc2   Trond Myklebust   SUNRPC: Clean up ...
608
609
610
611
612
613
614
615
616
617
618
619
620
  static int __rpc_unlink(struct inode *dir, struct dentry *dentry)
  {
  	int ret;
  
  	dget(dentry);
  	ret = simple_unlink(dir, dentry);
  	d_delete(dentry);
  	dput(dentry);
  	return ret;
  }
  
  static int __rpc_rmpipe(struct inode *dir, struct dentry *dentry)
  {
c5ef60352   David Howells   VFS: net/: d_inod...
621
  	struct inode *inode = d_inode(dentry);
810d90bc2   Trond Myklebust   SUNRPC: Clean up ...
622

810d90bc2   Trond Myklebust   SUNRPC: Clean up ...
623
624
625
  	rpc_close_pipes(inode);
  	return __rpc_unlink(dir, dentry);
  }
5bff03863   Stanislav Kinsbursky   SUNRPC: remove no...
626
  static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent,
d3db90b0a   Al Viro   __rpc_lookup_crea...
627
  					  const char *name)
cfeaa4a3c   Trond Myklebust   SUNRPC: Clean up ...
628
  {
d3db90b0a   Al Viro   __rpc_lookup_crea...
629
630
  	struct qstr q = QSTR_INIT(name, strlen(name));
  	struct dentry *dentry = d_hash_and_lookup(parent, &q);
cfeaa4a3c   Trond Myklebust   SUNRPC: Clean up ...
631
  	if (!dentry) {
d3db90b0a   Al Viro   __rpc_lookup_crea...
632
  		dentry = d_alloc(parent, &q);
5bff03863   Stanislav Kinsbursky   SUNRPC: remove no...
633
634
  		if (!dentry)
  			return ERR_PTR(-ENOMEM);
cfeaa4a3c   Trond Myklebust   SUNRPC: Clean up ...
635
  	}
c5ef60352   David Howells   VFS: net/: d_inod...
636
  	if (d_really_is_negative(dentry))
cfeaa4a3c   Trond Myklebust   SUNRPC: Clean up ...
637
638
639
640
  		return dentry;
  	dput(dentry);
  	return ERR_PTR(-EEXIST);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
641
642
643
  /*
   * FIXME: This probably has races.
   */
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
644
645
646
  static void __rpc_depopulate(struct dentry *parent,
  			     const struct rpc_filelist *files,
  			     int start, int eof)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
647
  {
c5ef60352   David Howells   VFS: net/: d_inod...
648
  	struct inode *dir = d_inode(parent);
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
649
650
651
  	struct dentry *dentry;
  	struct qstr name;
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
652

ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
653
654
655
  	for (i = start; i < eof; i++) {
  		name.name = files[i].name;
  		name.len = strlen(files[i].name);
d3db90b0a   Al Viro   __rpc_lookup_crea...
656
  		dentry = d_hash_and_lookup(parent, &name);
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
657
658
  
  		if (dentry == NULL)
62e1761ce   Trond Myklebust   SUNRPC: Clean up ...
659
  			continue;
c5ef60352   David Howells   VFS: net/: d_inod...
660
  		if (d_really_is_negative(dentry))
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
661
  			goto next;
c5ef60352   David Howells   VFS: net/: d_inod...
662
  		switch (d_inode(dentry)->i_mode & S_IFMT) {
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
663
664
665
666
  			default:
  				BUG();
  			case S_IFREG:
  				__rpc_unlink(dir, dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
667
  				break;
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
668
669
670
671
672
  			case S_IFDIR:
  				__rpc_rmdir(dir, dentry);
  		}
  next:
  		dput(dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
673
  	}
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
674
675
676
677
678
679
  }
  
  static void rpc_depopulate(struct dentry *parent,
  			   const struct rpc_filelist *files,
  			   int start, int eof)
  {
c5ef60352   David Howells   VFS: net/: d_inod...
680
  	struct inode *dir = d_inode(parent);
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
681

5955102c9   Al Viro   wrappers for ->i_...
682
  	inode_lock_nested(dir, I_MUTEX_CHILD);
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
683
  	__rpc_depopulate(parent, files, start, eof);
5955102c9   Al Viro   wrappers for ->i_...
684
  	inode_unlock(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
685
  }
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
686
687
688
689
  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
690
  {
c5ef60352   David Howells   VFS: net/: d_inod...
691
  	struct inode *dir = d_inode(parent);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
692
  	struct dentry *dentry;
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
693
  	int i, err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
694

5955102c9   Al Viro   wrappers for ->i_...
695
  	inode_lock(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
696
  	for (i = start; i < eof; i++) {
d3db90b0a   Al Viro   __rpc_lookup_crea...
697
  		dentry = __rpc_lookup_create_exclusive(parent, files[i].name);
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
698
699
  		err = PTR_ERR(dentry);
  		if (IS_ERR(dentry))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
700
  			goto out_bad;
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
701
702
703
704
705
706
707
708
709
710
711
712
713
714
  		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
715
  		}
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
716
717
  		if (err != 0)
  			goto out_bad;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
718
  	}
5955102c9   Al Viro   wrappers for ->i_...
719
  	inode_unlock(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
720
721
  	return 0;
  out_bad:
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
722
  	__rpc_depopulate(parent, files, start, eof);
5955102c9   Al Viro   wrappers for ->i_...
723
  	inode_unlock(dir);
1e903edad   Al Viro   sunrpc: switch to...
724
725
726
  	printk(KERN_WARNING "%s: %s failed to populate directory %pd
  ",
  			__FILE__, __func__, parent);
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
727
  	return err;
f134585a7   Trond Myklebust   Revert "[PATCH] R...
728
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
729

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

dff02cc1a   Trond Myklebust   NFS: clean up rpc...
765
  	parent = dget_parent(dentry);
c5ef60352   David Howells   VFS: net/: d_inod...
766
  	dir = d_inode(parent);
5955102c9   Al Viro   wrappers for ->i_...
767
  	inode_lock_nested(dir, I_MUTEX_PARENT);
e57aed77a   Trond Myklebust   SUNRPC: One more ...
768
769
  	if (depopulate != NULL)
  		depopulate(dentry);
f134585a7   Trond Myklebust   Revert "[PATCH] R...
770
  	error = __rpc_rmdir(dir, dentry);
5955102c9   Al Viro   wrappers for ->i_...
771
  	inode_unlock(dir);
dff02cc1a   Trond Myklebust   NFS: clean up rpc...
772
  	dput(parent);
f134585a7   Trond Myklebust   Revert "[PATCH] R...
773
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774
  }
93a44a75b   J. Bruce Fields   sunrpc: document ...
775
776
777
778
779
  /**
   * 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...
780
   * @pipe: &rpc_pipe containing input parameters
93a44a75b   J. Bruce Fields   sunrpc: document ...
781
782
783
784
785
786
787
788
789
790
   *
   * 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_...
791
   * from the file pointer, via RPC_I(file_inode(file))->private.
93a44a75b   J. Bruce Fields   sunrpc: document ...
792
   */
c239d83b9   Stanislav Kinsbursky   SUNRPC: split SUN...
793
794
  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
795
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
796
  	struct dentry *dentry;
c5ef60352   David Howells   VFS: net/: d_inod...
797
  	struct inode *dir = d_inode(parent);
7364af6a2   Trond Myklebust   SUNRPC: Allow rpc...
798
  	umode_t umode = S_IFIFO | S_IRUSR | S_IWUSR;
7589806e9   Trond Myklebust   SUNRPC: Clean up ...
799
  	int err;
7364af6a2   Trond Myklebust   SUNRPC: Allow rpc...
800

c239d83b9   Stanislav Kinsbursky   SUNRPC: split SUN...
801
  	if (pipe->ops->upcall == NULL)
7364af6a2   Trond Myklebust   SUNRPC: Allow rpc...
802
  		umode &= ~S_IRUGO;
c239d83b9   Stanislav Kinsbursky   SUNRPC: split SUN...
803
  	if (pipe->ops->downcall == NULL)
7364af6a2   Trond Myklebust   SUNRPC: Allow rpc...
804
  		umode &= ~S_IWUGO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
805

5955102c9   Al Viro   wrappers for ->i_...
806
  	inode_lock_nested(dir, I_MUTEX_PARENT);
d3db90b0a   Al Viro   __rpc_lookup_crea...
807
  	dentry = __rpc_lookup_create_exclusive(parent, name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
808
  	if (IS_ERR(dentry))
cfeaa4a3c   Trond Myklebust   SUNRPC: Clean up ...
809
  		goto out;
c239d83b9   Stanislav Kinsbursky   SUNRPC: split SUN...
810
811
  	err = __rpc_mkpipe_dentry(dir, dentry, umode, &rpc_pipe_fops,
  				  private, pipe);
7589806e9   Trond Myklebust   SUNRPC: Clean up ...
812
813
  	if (err)
  		goto out_err;
f134585a7   Trond Myklebust   Revert "[PATCH] R...
814
  out:
5955102c9   Al Viro   wrappers for ->i_...
815
  	inode_unlock(dir);
5c3e985a2   Trond Myklebust   SUNRPC: Fix obvio...
816
  	return dentry;
7589806e9   Trond Myklebust   SUNRPC: Clean up ...
817
818
  out_err:
  	dentry = ERR_PTR(err);
1e903edad   Al Viro   sunrpc: switch to...
819
820
821
  	printk(KERN_WARNING "%s: %s() failed to create pipe %pd/%s (errno = %d)
  ",
  			__FILE__, __func__, parent, name,
7589806e9   Trond Myklebust   SUNRPC: Clean up ...
822
  			err);
f134585a7   Trond Myklebust   Revert "[PATCH] R...
823
  	goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824
  }
c239d83b9   Stanislav Kinsbursky   SUNRPC: split SUN...
825
  EXPORT_SYMBOL_GPL(rpc_mkpipe_dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
826

93a44a75b   J. Bruce Fields   sunrpc: document ...
827
828
829
830
831
832
833
834
  /**
   * 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...
835
  int
5d67476ff   Trond Myklebust   SUNRPC: make rpc_...
836
  rpc_unlink(struct dentry *dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
837
  {
5d67476ff   Trond Myklebust   SUNRPC: make rpc_...
838
  	struct dentry *parent;
f134585a7   Trond Myklebust   Revert "[PATCH] R...
839
  	struct inode *dir;
5d67476ff   Trond Myklebust   SUNRPC: make rpc_...
840
  	int error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
841

5d67476ff   Trond Myklebust   SUNRPC: make rpc_...
842
  	parent = dget_parent(dentry);
c5ef60352   David Howells   VFS: net/: d_inod...
843
  	dir = d_inode(parent);
5955102c9   Al Viro   wrappers for ->i_...
844
  	inode_lock_nested(dir, I_MUTEX_PARENT);
810d90bc2   Trond Myklebust   SUNRPC: Clean up ...
845
  	error = __rpc_rmpipe(dir, dentry);
5955102c9   Al Viro   wrappers for ->i_...
846
  	inode_unlock(dir);
5d67476ff   Trond Myklebust   SUNRPC: make rpc_...
847
  	dput(parent);
f134585a7   Trond Myklebust   Revert "[PATCH] R...
848
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
849
  }
468039ee4   Trond Myklebust   SUNRPC: Convert t...
850
  EXPORT_SYMBOL_GPL(rpc_unlink);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
851

6739ffb75   Trond Myklebust   SUNRPC: Add a fra...
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
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
  /**
   * 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...
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
  /**
   * 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...
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
  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 ...
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
  enum {
  	RPCAUTH_info,
  	RPCAUTH_EOF
  };
  
  static const struct rpc_filelist authfiles[] = {
  	[RPCAUTH_info] = {
  		.name = "info",
  		.i_fop = &rpc_info_operations,
  		.mode = S_IFREG | S_IRUSR,
  	},
  };
  
  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 ...
1026
1027
  /**
   * rpc_create_client_dir - Create a new rpc_client directory in rpc_pipefs
a95e691f9   Al Viro   rpc_create_*_dir:...
1028
1029
   * @dentry: the parent of new directory
   * @name: the name of new directory
7d59d1e86   Trond Myklebust   SUNRPC: Clean up ...
1030
1031
1032
1033
1034
1035
1036
   * @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 ...
1037
  struct dentry *rpc_create_client_dir(struct dentry *dentry,
a95e691f9   Al Viro   rpc_create_*_dir:...
1038
  				   const char *name,
e57aed77a   Trond Myklebust   SUNRPC: One more ...
1039
1040
  				   struct rpc_clnt *rpc_client)
  {
6739ffb75   Trond Myklebust   SUNRPC: Add a fra...
1041
1042
1043
  	struct dentry *ret;
  
  	ret = rpc_mkdir_populate(dentry, name, S_IRUGO | S_IXUGO, NULL,
e57aed77a   Trond Myklebust   SUNRPC: One more ...
1044
  			rpc_clntdir_populate, rpc_client);
6739ffb75   Trond Myklebust   SUNRPC: Add a fra...
1045
1046
1047
1048
1049
  	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 ...
1050
1051
1052
1053
  }
  
  /**
   * rpc_remove_client_dir - Remove a directory created with rpc_create_client_dir()
6739ffb75   Trond Myklebust   SUNRPC: Add a fra...
1054
   * @rpc_client: rpc_client for the pipe
e57aed77a   Trond Myklebust   SUNRPC: One more ...
1055
   */
c36dcfe1f   Trond Myklebust   SUNRPC: Remove th...
1056
  int rpc_remove_client_dir(struct rpc_clnt *rpc_client)
7d59d1e86   Trond Myklebust   SUNRPC: Clean up ...
1057
  {
c36dcfe1f   Trond Myklebust   SUNRPC: Remove th...
1058
1059
1060
1061
1062
1063
  	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 ...
1064
  	return rpc_rmdir_depopulate(dentry, rpc_clntdir_depopulate);
7d59d1e86   Trond Myklebust   SUNRPC: Clean up ...
1065
  }
8854e82d9   Trond Myklebust   SUNRPC: Add an rp...
1066
1067
1068
1069
  static const struct rpc_filelist cache_pipefs_files[3] = {
  	[0] = {
  		.name = "channel",
  		.i_fop = &cache_file_operations_pipefs,
96c61cbd0   Trond Myklebust   SUNRPC: Fix a typ...
1070
  		.mode = S_IFREG|S_IRUSR|S_IWUSR,
8854e82d9   Trond Myklebust   SUNRPC: Add an rp...
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
  	},
  	[1] = {
  		.name = "content",
  		.i_fop = &content_file_operations_pipefs,
  		.mode = S_IFREG|S_IRUSR,
  	},
  	[2] = {
  		.name = "flush",
  		.i_fop = &cache_flush_operations_pipefs,
  		.mode = S_IFREG|S_IRUSR|S_IWUSR,
  	},
  };
  
  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:...
1095
  struct dentry *rpc_create_cache_dir(struct dentry *parent, const char *name,
64f1426f3   Al Viro   sunrpc: propagate...
1096
  				    umode_t umode, struct cache_detail *cd)
8854e82d9   Trond Myklebust   SUNRPC: Add an rp...
1097
1098
1099
1100
1101
1102
1103
1104
1105
  {
  	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
1106
1107
1108
  /*
   * populate the filesystem
   */
b87221de6   Alexey Dobriyan   const: mark remai...
1109
  static const struct super_operations s_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1110
1111
1112
1113
1114
1115
  	.alloc_inode	= rpc_alloc_inode,
  	.destroy_inode	= rpc_destroy_inode,
  	.statfs		= simple_statfs,
  };
  
  #define RPCAUTH_GSSMAGIC 0x67596969
bb1567491   Trond Myklebust   SUNRPC: rpc_pipef...
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
  /*
   * 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...
1126
  	RPCAUTH_cache,
b3537c35c   Jeff Layton   sunrpc: create nf...
1127
  	RPCAUTH_nfsd,
4b9a445e3   Jeff Layton   sunrpc: create a ...
1128
  	RPCAUTH_gssd,
bb1567491   Trond Myklebust   SUNRPC: rpc_pipef...
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
  	RPCAUTH_RootEOF
  };
  
  static const struct rpc_filelist files[] = {
  	[RPCAUTH_lockd] = {
  		.name = "lockd",
  		.mode = S_IFDIR | S_IRUGO | S_IXUGO,
  	},
  	[RPCAUTH_mount] = {
  		.name = "mount",
  		.mode = S_IFDIR | S_IRUGO | S_IXUGO,
  	},
  	[RPCAUTH_nfs] = {
  		.name = "nfs",
  		.mode = S_IFDIR | S_IRUGO | S_IXUGO,
  	},
  	[RPCAUTH_portmap] = {
  		.name = "portmap",
  		.mode = S_IFDIR | S_IRUGO | S_IXUGO,
  	},
  	[RPCAUTH_statd] = {
  		.name = "statd",
  		.mode = S_IFDIR | S_IRUGO | S_IXUGO,
  	},
  	[RPCAUTH_nfsd4_cb] = {
  		.name = "nfsd4_cb",
  		.mode = S_IFDIR | S_IRUGO | S_IXUGO,
  	},
e571cbf1a   Trond Myklebust   NFS: Add a dns re...
1157
1158
1159
1160
  	[RPCAUTH_cache] = {
  		.name = "cache",
  		.mode = S_IFDIR | S_IRUGO | S_IXUGO,
  	},
b3537c35c   Jeff Layton   sunrpc: create nf...
1161
1162
1163
1164
  	[RPCAUTH_nfsd] = {
  		.name = "nfsd",
  		.mode = S_IFDIR | S_IRUGO | S_IXUGO,
  	},
4b9a445e3   Jeff Layton   sunrpc: create a ...
1165
1166
1167
1168
  	[RPCAUTH_gssd] = {
  		.name = "gssd",
  		.mode = S_IFDIR | S_IRUGO | S_IXUGO,
  	},
bb1567491   Trond Myklebust   SUNRPC: rpc_pipef...
1169
  };
432eb1a5f   Stanislav Kinsbursky   SUNRPC: pipefs de...
1170
1171
1172
1173
1174
1175
  /*
   * 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...
1176
  	struct qstr dir = QSTR_INIT(dir_name, strlen(dir_name));
d3db90b0a   Al Viro   __rpc_lookup_crea...
1177
  	return d_hash_and_lookup(sb->s_root, &dir);
432eb1a5f   Stanislav Kinsbursky   SUNRPC: pipefs de...
1178
1179
  }
  EXPORT_SYMBOL_GPL(rpc_d_lookup_sb);
4b9a445e3   Jeff Layton   sunrpc: create a ...
1180
  int rpc_pipefs_init_net(struct net *net)
c21a588f3   Stanislav Kinsbursky   SUNRPC: pipefs pe...
1181
1182
  {
  	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
4b9a445e3   Jeff Layton   sunrpc: create a ...
1183
1184
1185
  	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...
1186
  	mutex_init(&sn->pipefs_sb_lock);
2aed8b476   Trond Myklebust   SUNRPC: Convert a...
1187
  	sn->pipe_version = -1;
4b9a445e3   Jeff Layton   sunrpc: create a ...
1188
1189
1190
1191
1192
1193
1194
1195
  	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...
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
  }
  
  /*
   * 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...
1219
  	WARN_ON(sn->pipefs_sb == NULL);
c21a588f3   Stanislav Kinsbursky   SUNRPC: pipefs pe...
1220
1221
1222
  	mutex_unlock(&sn->pipefs_sb_lock);
  }
  EXPORT_SYMBOL_GPL(rpc_put_sb_net);
4b9a445e3   Jeff Layton   sunrpc: create a ...
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
  static const struct rpc_filelist gssd_dummy_clnt_dir[] = {
  	[0] = {
  		.name = "clntXX",
  		.mode = S_IFDIR | S_IRUGO | S_IXUGO,
  	},
  };
  
  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...
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
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
  /*
   * 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
  rpc_show_dummy_info(struct seq_file *m, void *v)
  {
  	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;
  }
  
  static int
  rpc_dummy_info_open(struct inode *inode, struct file *file)
  {
  	return single_open(file, rpc_show_dummy_info, NULL);
  }
  
  static const struct file_operations rpc_dummy_info_operations = {
  	.owner		= THIS_MODULE,
  	.open		= rpc_dummy_info_open,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
  	.release	= single_release,
  };
  
  static const struct rpc_filelist gssd_dummy_info_file[] = {
  	[0] = {
  		.name = "info",
  		.i_fop = &rpc_dummy_info_operations,
  		.mode = S_IFREG | S_IRUSR,
  	},
  };
4b9a445e3   Jeff Layton   sunrpc: create a ...
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
  /**
   * 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) {
  		pipe_dentry = ERR_PTR(-ENOENT);
  		goto out;
  	}
e2f0c83a9   Jeff Layton   sunrpc: add an "i...
1318
1319
1320
1321
1322
1323
  	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 ...
1324
  	pipe_dentry = rpc_mkpipe_dentry(clnt_dentry, "gssd", NULL, pipe_data);
e2f0c83a9   Jeff Layton   sunrpc: add an "i...
1325
1326
  	if (IS_ERR(pipe_dentry)) {
  		__rpc_depopulate(clnt_dentry, gssd_dummy_info_file, 0, 1);
3396f92f8   Jeff Layton   rpc_pipe: remove ...
1327
  		__rpc_depopulate(gssd_dentry, gssd_dummy_clnt_dir, 0, 1);
e2f0c83a9   Jeff Layton   sunrpc: add an "i...
1328
  	}
4b9a445e3   Jeff Layton   sunrpc: create a ...
1329
1330
1331
1332
1333
  out:
  	dput(clnt_dentry);
  	dput(gssd_dentry);
  	return pipe_dentry;
  }
23e66ba97   Jeff Layton   rpc_pipe: fix cle...
1334
1335
1336
1337
1338
  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;
085125572   Al Viro   rpc_pipefs: fix d...
1339
  	dget(pipe_dentry);
c5ef60352   David Howells   VFS: net/: d_inod...
1340
  	__rpc_rmpipe(d_inode(clnt_dir), pipe_dentry);
23e66ba97   Jeff Layton   rpc_pipe: fix cle...
1341
1342
1343
1344
  	__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
1345
1346
1347
1348
  static int
  rpc_fill_super(struct super_block *sb, void *data, int silent)
  {
  	struct inode *inode;
4b9a445e3   Jeff Layton   sunrpc: create a ...
1349
  	struct dentry *root, *gssd_dentry;
d91ee87d8   Eric W. Biederman   vfs: Pass data, n...
1350
  	struct net *net = get_net(sb->s_fs_info);
90c4e8299   Stanislav Kinsbursky   SUNRPC: put pipef...
1351
  	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
2d00131ac   Stanislav Kinsbursky   SUNRPC: send noti...
1352
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1353

09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1354
1355
  	sb->s_blocksize = PAGE_SIZE;
  	sb->s_blocksize_bits = PAGE_SHIFT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1356
1357
  	sb->s_magic = RPCAUTH_GSSMAGIC;
  	sb->s_op = &s_ops;
b26d4cd38   Al Viro   consolidate simpl...
1358
  	sb->s_d_op = &simple_dentry_operations;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1359
  	sb->s_time_gran = 1;
7e450b4e4   Jeff Layton   rpc_pipefs: clear...
1360
  	inode = rpc_get_inode(sb, S_IFDIR | S_IRUGO | S_IXUGO);
48fde701a   Al Viro   switch open-coded...
1361
1362
  	sb->s_root = root = d_make_root(inode);
  	if (!root)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1363
  		return -ENOMEM;
ac6fecee3   Trond Myklebust   SUNRPC: Clean up ...
1364
  	if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL))
fc7bed8c8   Al Viro   Don't bother with...
1365
  		return -ENOMEM;
4b9a445e3   Jeff Layton   sunrpc: create a ...
1366
1367
1368
1369
1370
1371
  
  	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);
  	}
d8af9bc16   Chuck Lever   SUNRPC: Clean up ...
1372
1373
1374
  	dprintk("RPC:       sending pipefs MOUNT notification for net %p%s
  ",
  		net, NET_NAME(net));
384816051   Stanislav Kinsbursky   SUNRPC: fix races...
1375
  	mutex_lock(&sn->pipefs_sb_lock);
37629b572   Stanislav Kinsbursky   SUNRPC: set per-n...
1376
  	sn->pipefs_sb = sb;
2d00131ac   Stanislav Kinsbursky   SUNRPC: send noti...
1377
1378
1379
1380
1381
  	err = blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
  					   RPC_PIPEFS_MOUNT,
  					   sb);
  	if (err)
  		goto err_depopulate;
384816051   Stanislav Kinsbursky   SUNRPC: fix races...
1382
  	mutex_unlock(&sn->pipefs_sb_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1383
  	return 0;
2d00131ac   Stanislav Kinsbursky   SUNRPC: send noti...
1384
1385
  
  err_depopulate:
23e66ba97   Jeff Layton   rpc_pipe: fix cle...
1386
  	rpc_gssd_dummy_depopulate(gssd_dentry);
2d00131ac   Stanislav Kinsbursky   SUNRPC: send noti...
1387
1388
1389
  	blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
  					   RPC_PIPEFS_UMOUNT,
  					   sb);
37629b572   Stanislav Kinsbursky   SUNRPC: set per-n...
1390
  	sn->pipefs_sb = NULL;
2d00131ac   Stanislav Kinsbursky   SUNRPC: send noti...
1391
  	__rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF);
384816051   Stanislav Kinsbursky   SUNRPC: fix races...
1392
  	mutex_unlock(&sn->pipefs_sb_lock);
2d00131ac   Stanislav Kinsbursky   SUNRPC: send noti...
1393
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1394
  }
89f842435   Jeff Layton   sunrpc: replace s...
1395
1396
1397
1398
1399
1400
1401
1402
1403
  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);
fc14f2fef   Al Viro   convert get_sb_si...
1404
1405
1406
  static struct dentry *
  rpc_mount(struct file_system_type *fs_type,
  		int flags, const char *dev_name, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1407
  {
d91ee87d8   Eric W. Biederman   vfs: Pass data, n...
1408
1409
  	struct net *net = current->nsproxy->net_ns;
  	return mount_ns(fs_type, flags, data, net, net->user_ns, rpc_fill_super);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1410
  }
09acfea5d   Trond Myklebust   SUNRPC: Fix a few...
1411
  static void rpc_kill_sb(struct super_block *sb)
021c68dec   Stanislav Kinsbursky   SUNRPC: hold curr...
1412
1413
  {
  	struct net *net = sb->s_fs_info;
90c4e8299   Stanislav Kinsbursky   SUNRPC: put pipef...
1414
  	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
021c68dec   Stanislav Kinsbursky   SUNRPC: hold curr...
1415

c21a588f3   Stanislav Kinsbursky   SUNRPC: pipefs pe...
1416
  	mutex_lock(&sn->pipefs_sb_lock);
642fe4d00   Trond Myklebust   SUNRPC: Fix valid...
1417
1418
1419
1420
  	if (sn->pipefs_sb != sb) {
  		mutex_unlock(&sn->pipefs_sb_lock);
  		goto out;
  	}
90c4e8299   Stanislav Kinsbursky   SUNRPC: put pipef...
1421
  	sn->pipefs_sb = NULL;
d8af9bc16   Chuck Lever   SUNRPC: Clean up ...
1422
1423
1424
  	dprintk("RPC:       sending pipefs UMOUNT notification for net %p%s
  ",
  		net, NET_NAME(net));
2d00131ac   Stanislav Kinsbursky   SUNRPC: send noti...
1425
1426
1427
  	blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
  					   RPC_PIPEFS_UMOUNT,
  					   sb);
adb6fa7ff   Stanislav Kinsbursky   SUNRPC: fix races...
1428
  	mutex_unlock(&sn->pipefs_sb_lock);
642fe4d00   Trond Myklebust   SUNRPC: Fix valid...
1429
  out:
021c68dec   Stanislav Kinsbursky   SUNRPC: hold curr...
1430
  	kill_litter_super(sb);
d91ee87d8   Eric W. Biederman   vfs: Pass data, n...
1431
  	put_net(net);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1432
1433
1434
1435
1436
  }
  
  static struct file_system_type rpc_pipe_fs_type = {
  	.owner		= THIS_MODULE,
  	.name		= "rpc_pipefs",
fc14f2fef   Al Viro   convert get_sb_si...
1437
  	.mount		= rpc_mount,
021c68dec   Stanislav Kinsbursky   SUNRPC: hold curr...
1438
  	.kill_sb	= rpc_kill_sb,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1439
  };
7f78e0351   Eric W. Biederman   fs: Limit sys_mou...
1440
  MODULE_ALIAS_FS("rpc_pipefs");
fa7614ddd   Eric W. Biederman   fs: Readd the fs ...
1441
  MODULE_ALIAS("rpc_pipefs");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1442
1443
  
  static void
51cc50685   Alexey Dobriyan   SL*B: drop kmem c...
1444
  init_once(void *foo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1445
1446
  {
  	struct rpc_inode *rpci = (struct rpc_inode *) foo;
a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
1447
1448
  	inode_init_once(&rpci->vfs_inode);
  	rpci->private = NULL;
ba9e09759   Stanislav Kinsbursky   SUNRPC: split SUN...
1449
  	rpci->pipe = NULL;
a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
1450
  	init_waitqueue_head(&rpci->waitq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1451
1452
1453
1454
  }
  
  int register_rpc_pipefs(void)
  {
5bd5f5812   Akinobu Mita   sunrpc: fix error...
1455
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1456
  	rpc_inode_cachep = kmem_cache_create("rpc_inode_cache",
fffb60f93   Paul Jackson   [PATCH] cpuset me...
1457
1458
  				sizeof(struct rpc_inode),
  				0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
5d097056c   Vladimir Davydov   kmemcg: account c...
1459
  						SLAB_MEM_SPREAD|SLAB_ACCOUNT),
20c2df83d   Paul Mundt   mm: Remove slab d...
1460
  				init_once);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1461
1462
  	if (!rpc_inode_cachep)
  		return -ENOMEM;
80df9d202   Stanislav Kinsbursky   SUNRPC: subscribe...
1463
1464
1465
  	err = rpc_clients_notifier_register();
  	if (err)
  		goto err_notifier;
5bd5f5812   Akinobu Mita   sunrpc: fix error...
1466
  	err = register_filesystem(&rpc_pipe_fs_type);
80df9d202   Stanislav Kinsbursky   SUNRPC: subscribe...
1467
1468
  	if (err)
  		goto err_register;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1469
  	return 0;
80df9d202   Stanislav Kinsbursky   SUNRPC: subscribe...
1470
1471
1472
1473
1474
1475
  
  err_register:
  	rpc_clients_notifier_unregister();
  err_notifier:
  	kmem_cache_destroy(rpc_inode_cachep);
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1476
1477
1478
1479
  }
  
  void unregister_rpc_pipefs(void)
  {
80df9d202   Stanislav Kinsbursky   SUNRPC: subscribe...
1480
  	rpc_clients_notifier_unregister();
1a1d92c10   Alexey Dobriyan   [PATCH] Really ig...
1481
  	kmem_cache_destroy(rpc_inode_cachep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1482
1483
  	unregister_filesystem(&rpc_pipe_fs_type);
  }