Blame view

net/sunrpc/xprt.c 30.3 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
  /*
   *  linux/net/sunrpc/xprt.c
   *
   *  This is a generic RPC call interface supporting congestion avoidance,
   *  and asynchronous calls.
   *
   *  The interface works like this:
   *
   *  -	When a process places a call, it allocates a request slot if
   *	one is available. Otherwise, it sleeps on the backlog queue
   *	(xprt_reserve).
   *  -	Next, the caller puts together the RPC message, stuffs it into
55aa4f58a   Chuck Lever   [PATCH] RPC: clie...
13
14
   *	the request struct, and calls xprt_transmit().
   *  -	xprt_transmit sends the message and installs the caller on the
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
15
16
17
   *	transport's wait list. At the same time, if a reply is expected,
   *	it installs a timer that is run after the packet's timeout has
   *	expired.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
   *  -	When a packet arrives, the data_ready handler walks the list of
55aa4f58a   Chuck Lever   [PATCH] RPC: clie...
19
   *	pending requests for that transport. If a matching XID is found, the
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
   *	caller is woken up, and the timer removed.
   *  -	When no reply arrives within the timeout interval, the timer is
   *	fired by the kernel and runs xprt_timer(). It either adjusts the
   *	timeout values (minor timeout) or wakes up the caller with a status
   *	of -ETIMEDOUT.
   *  -	When the caller receives a notification from RPC that a reply arrived,
   *	it should release the RPC slot, and process the reply.
   *	If the call timed out, it may choose to retry the operation by
   *	adjusting the initial timeout value, and simply calling rpc_call
   *	again.
   *
   *  Support for async RPC is done through a set of RPC-specific scheduling
   *  primitives that `transparently' work for processes as well as async
   *  tasks that rely on callbacks.
   *
   *  Copyright (C) 1995-1997, Olaf Kirch <okir@monad.swb.de>
55aa4f58a   Chuck Lever   [PATCH] RPC: clie...
36
37
   *
   *  Transport switch API copyright (C) 2005, Chuck Lever <cel@netapp.com>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
   */
a246b0105   Chuck Lever   [PATCH] RPC: intr...
39
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  #include <linux/types.h>
a246b0105   Chuck Lever   [PATCH] RPC: intr...
41
  #include <linux/interrupt.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
  #include <linux/workqueue.h>
bf3fcf895   Chuck Lever   SUNRPC: NFS_ROOT ...
43
  #include <linux/net.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44

a246b0105   Chuck Lever   [PATCH] RPC: intr...
45
  #include <linux/sunrpc/clnt.h>
11c556b3d   Chuck Lever   SUNRPC: provide a...
46
  #include <linux/sunrpc/metrics.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47

55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
48
  #include "sunrpc.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
51
52
53
  /*
   * Local variables
   */
  
  #ifdef RPC_DEBUG
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
  # define RPCDBG_FACILITY	RPCDBG_XPRT
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
58
59
60
  /*
   * Local functions
   */
  static void	xprt_request_init(struct rpc_task *, struct rpc_xprt *);
  static inline void	do_xprt_reserve(struct rpc_task *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
  static void	xprt_connect_status(struct rpc_task *task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
  static int      __xprt_get_cong(struct rpc_xprt *, struct rpc_task *);
5ba03e82b   Jiri Slaby   [SUNRPC]: Remove ...
63
  static DEFINE_SPINLOCK(xprt_list_lock);
81c098af3   \"Talpey, Thomas\   SUNRPC: Provide a...
64
  static LIST_HEAD(xprt_list);
555ee3af1   Chuck Lever   [PATCH] RPC: clea...
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
  /*
   * The transport code maintains an estimate on the maximum number of out-
   * standing RPC requests, using a smoothed version of the congestion
   * avoidance implemented in 44BSD. This is basically the Van Jacobson
   * congestion algorithm: If a retransmit occurs, the congestion window is
   * halved; otherwise, it is incremented by 1/cwnd when
   *
   *	-	a reply is received and
   *	-	a full number of requests are outstanding and
   *	-	the congestion window hasn't been updated recently.
   */
  #define RPC_CWNDSHIFT		(8U)
  #define RPC_CWNDSCALE		(1U << RPC_CWNDSHIFT)
  #define RPC_INITCWND		RPC_CWNDSCALE
  #define RPC_MAXCWND(xprt)	((xprt)->max_reqs << RPC_CWNDSHIFT)
  
  #define RPCXPRT_CONGESTED(xprt) ((xprt)->cong >= (xprt)->cwnd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82

12a804698   Chuck Lever   [PATCH] RPC: expo...
83
  /**
81c098af3   \"Talpey, Thomas\   SUNRPC: Provide a...
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
   * xprt_register_transport - register a transport implementation
   * @transport: transport to register
   *
   * If a transport implementation is loaded as a kernel module, it can
   * call this interface to make itself known to the RPC client.
   *
   * Returns:
   * 0:		transport successfully registered
   * -EEXIST:	transport already registered
   * -EINVAL:	transport module being unloaded
   */
  int xprt_register_transport(struct xprt_class *transport)
  {
  	struct xprt_class *t;
  	int result;
  
  	result = -EEXIST;
  	spin_lock(&xprt_list_lock);
  	list_for_each_entry(t, &xprt_list, list) {
  		/* don't register the same transport class twice */
4fa016eb2   \"Talpey, Thomas\   NFS/SUNRPC: suppo...
104
  		if (t->ident == transport->ident)
81c098af3   \"Talpey, Thomas\   SUNRPC: Provide a...
105
106
  			goto out;
  	}
c9f6cde6e   Denis V. Lunev   sunrpc: do not pi...
107
108
109
110
111
  	list_add_tail(&transport->list, &xprt_list);
  	printk(KERN_INFO "RPC: Registered %s transport module.
  ",
  	       transport->name);
  	result = 0;
81c098af3   \"Talpey, Thomas\   SUNRPC: Provide a...
112
113
114
115
116
117
118
119
120
  
  out:
  	spin_unlock(&xprt_list_lock);
  	return result;
  }
  EXPORT_SYMBOL_GPL(xprt_register_transport);
  
  /**
   * xprt_unregister_transport - unregister a transport implementation
65b6e42cd   Randy Dunlap   docbook: sunrpc f...
121
   * @transport: transport to unregister
81c098af3   \"Talpey, Thomas\   SUNRPC: Provide a...
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
   *
   * Returns:
   * 0:		transport successfully unregistered
   * -ENOENT:	transport never registered
   */
  int xprt_unregister_transport(struct xprt_class *transport)
  {
  	struct xprt_class *t;
  	int result;
  
  	result = 0;
  	spin_lock(&xprt_list_lock);
  	list_for_each_entry(t, &xprt_list, list) {
  		if (t == transport) {
  			printk(KERN_INFO
  				"RPC: Unregistered %s transport module.
  ",
  				transport->name);
  			list_del_init(&transport->list);
81c098af3   \"Talpey, Thomas\   SUNRPC: Provide a...
141
142
143
144
145
146
147
148
149
150
151
152
  			goto out;
  		}
  	}
  	result = -ENOENT;
  
  out:
  	spin_unlock(&xprt_list_lock);
  	return result;
  }
  EXPORT_SYMBOL_GPL(xprt_unregister_transport);
  
  /**
441e3e242   Tom Talpey   SUNRPC: dynamical...
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
   * xprt_load_transport - load a transport implementation
   * @transport_name: transport to load
   *
   * Returns:
   * 0:		transport successfully loaded
   * -ENOENT:	transport module not available
   */
  int xprt_load_transport(const char *transport_name)
  {
  	struct xprt_class *t;
  	char module_name[sizeof t->name + 5];
  	int result;
  
  	result = 0;
  	spin_lock(&xprt_list_lock);
  	list_for_each_entry(t, &xprt_list, list) {
  		if (strcmp(t->name, transport_name) == 0) {
  			spin_unlock(&xprt_list_lock);
  			goto out;
  		}
  	}
  	spin_unlock(&xprt_list_lock);
  	strcpy(module_name, "xprt");
  	strncat(module_name, transport_name, sizeof t->name);
  	result = request_module(module_name);
  out:
  	return result;
  }
  EXPORT_SYMBOL_GPL(xprt_load_transport);
  
  /**
12a804698   Chuck Lever   [PATCH] RPC: expo...
184
185
186
187
188
189
190
191
192
   * xprt_reserve_xprt - serialize write access to transports
   * @task: task that is requesting access to the transport
   *
   * This prevents mixing the payload of separate requests, and prevents
   * transport connects from colliding with writes.  No congestion control
   * is provided.
   */
  int xprt_reserve_xprt(struct rpc_task *task)
  {
12a804698   Chuck Lever   [PATCH] RPC: expo...
193
  	struct rpc_rqst *req = task->tk_rqstp;
343952fa5   Rahul Iyer   nfs41: Get the rp...
194
  	struct rpc_xprt	*xprt = req->rq_xprt;
12a804698   Chuck Lever   [PATCH] RPC: expo...
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
  
  	if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) {
  		if (task == xprt->snd_task)
  			return 1;
  		if (task == NULL)
  			return 0;
  		goto out_sleep;
  	}
  	xprt->snd_task = task;
  	if (req) {
  		req->rq_bytes_sent = 0;
  		req->rq_ntrans++;
  	}
  	return 1;
  
  out_sleep:
46121cf7d   Chuck Lever   SUNRPC: fix print...
211
212
  	dprintk("RPC: %5u failed to lock transport %p
  ",
12a804698   Chuck Lever   [PATCH] RPC: expo...
213
214
215
216
  			task->tk_pid, xprt);
  	task->tk_timeout = 0;
  	task->tk_status = -EAGAIN;
  	if (req && req->rq_ntrans)
5d00837b9   Trond Myklebust   SUNRPC: Run rpc t...
217
  		rpc_sleep_on(&xprt->resend, task, NULL);
12a804698   Chuck Lever   [PATCH] RPC: expo...
218
  	else
5d00837b9   Trond Myklebust   SUNRPC: Run rpc t...
219
  		rpc_sleep_on(&xprt->sending, task, NULL);
12a804698   Chuck Lever   [PATCH] RPC: expo...
220
221
  	return 0;
  }
124448097   \"Talpey, Thomas\   SUNRPC: add EXPOR...
222
  EXPORT_SYMBOL_GPL(xprt_reserve_xprt);
12a804698   Chuck Lever   [PATCH] RPC: expo...
223

632e3bdc5   Trond Myklebust   SUNRPC: Ensure cl...
224
225
226
227
228
229
230
231
  static void xprt_clear_locked(struct rpc_xprt *xprt)
  {
  	xprt->snd_task = NULL;
  	if (!test_bit(XPRT_CLOSE_WAIT, &xprt->state) || xprt->shutdown) {
  		smp_mb__before_clear_bit();
  		clear_bit(XPRT_LOCKED, &xprt->state);
  		smp_mb__after_clear_bit();
  	} else
c1384c9c4   Trond Myklebust   SUNRPC: fix hang ...
232
  		queue_work(rpciod_workqueue, &xprt->task_cleanup);
632e3bdc5   Trond Myklebust   SUNRPC: Ensure cl...
233
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
  /*
12a804698   Chuck Lever   [PATCH] RPC: expo...
235
236
237
238
239
240
   * xprt_reserve_xprt_cong - serialize write access to transports
   * @task: task that is requesting access to the transport
   *
   * Same as xprt_reserve_xprt, but Van Jacobson congestion control is
   * integrated into the decision of whether a request is allowed to be
   * woken up and given access to the transport.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241
   */
12a804698   Chuck Lever   [PATCH] RPC: expo...
242
  int xprt_reserve_xprt_cong(struct rpc_task *task)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
  {
12a804698   Chuck Lever   [PATCH] RPC: expo...
244
  	struct rpc_xprt	*xprt = task->tk_xprt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
  	struct rpc_rqst *req = task->tk_rqstp;
2226feb6b   Chuck Lever   [PATCH] RPC: rena...
246
  	if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
248
  		if (task == xprt->snd_task)
  			return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
250
  		goto out_sleep;
  	}
12a804698   Chuck Lever   [PATCH] RPC: expo...
251
  	if (__xprt_get_cong(xprt, task)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252
253
254
255
256
257
258
  		xprt->snd_task = task;
  		if (req) {
  			req->rq_bytes_sent = 0;
  			req->rq_ntrans++;
  		}
  		return 1;
  	}
632e3bdc5   Trond Myklebust   SUNRPC: Ensure cl...
259
  	xprt_clear_locked(xprt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
  out_sleep:
46121cf7d   Chuck Lever   SUNRPC: fix print...
261
262
  	dprintk("RPC: %5u failed to lock transport %p
  ", task->tk_pid, xprt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
264
265
  	task->tk_timeout = 0;
  	task->tk_status = -EAGAIN;
  	if (req && req->rq_ntrans)
5d00837b9   Trond Myklebust   SUNRPC: Run rpc t...
266
  		rpc_sleep_on(&xprt->resend, task, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
  	else
5d00837b9   Trond Myklebust   SUNRPC: Run rpc t...
268
  		rpc_sleep_on(&xprt->sending, task, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
270
  	return 0;
  }
124448097   \"Talpey, Thomas\   SUNRPC: add EXPOR...
271
  EXPORT_SYMBOL_GPL(xprt_reserve_xprt_cong);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272

12a804698   Chuck Lever   [PATCH] RPC: expo...
273
  static inline int xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
275
  {
  	int retval;
4a0f8c04f   Chuck Lever   [PATCH] RPC: Rena...
276
  	spin_lock_bh(&xprt->transport_lock);
12a804698   Chuck Lever   [PATCH] RPC: expo...
277
  	retval = xprt->ops->reserve_xprt(task);
4a0f8c04f   Chuck Lever   [PATCH] RPC: Rena...
278
  	spin_unlock_bh(&xprt->transport_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
280
  	return retval;
  }
12a804698   Chuck Lever   [PATCH] RPC: expo...
281
  static void __xprt_lock_write_next(struct rpc_xprt *xprt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
283
  {
  	struct rpc_task *task;
49e9a8908   Chuck Lever   [PATCH] RPC: expo...
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
  	struct rpc_rqst *req;
  
  	if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
  		return;
  
  	task = rpc_wake_up_next(&xprt->resend);
  	if (!task) {
  		task = rpc_wake_up_next(&xprt->sending);
  		if (!task)
  			goto out_unlock;
  	}
  
  	req = task->tk_rqstp;
  	xprt->snd_task = task;
  	if (req) {
  		req->rq_bytes_sent = 0;
  		req->rq_ntrans++;
  	}
  	return;
  
  out_unlock:
632e3bdc5   Trond Myklebust   SUNRPC: Ensure cl...
305
  	xprt_clear_locked(xprt);
49e9a8908   Chuck Lever   [PATCH] RPC: expo...
306
307
308
309
310
  }
  
  static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt)
  {
  	struct rpc_task *task;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311

2226feb6b   Chuck Lever   [PATCH] RPC: rena...
312
  	if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313
  		return;
49e9a8908   Chuck Lever   [PATCH] RPC: expo...
314
  	if (RPCXPRT_CONGESTED(xprt))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
316
317
318
319
320
321
  		goto out_unlock;
  	task = rpc_wake_up_next(&xprt->resend);
  	if (!task) {
  		task = rpc_wake_up_next(&xprt->sending);
  		if (!task)
  			goto out_unlock;
  	}
49e9a8908   Chuck Lever   [PATCH] RPC: expo...
322
  	if (__xprt_get_cong(xprt, task)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
324
325
326
327
328
329
330
331
  		struct rpc_rqst *req = task->tk_rqstp;
  		xprt->snd_task = task;
  		if (req) {
  			req->rq_bytes_sent = 0;
  			req->rq_ntrans++;
  		}
  		return;
  	}
  out_unlock:
632e3bdc5   Trond Myklebust   SUNRPC: Ensure cl...
332
  	xprt_clear_locked(xprt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333
  }
49e9a8908   Chuck Lever   [PATCH] RPC: expo...
334
335
336
337
338
339
  /**
   * xprt_release_xprt - allow other requests to use a transport
   * @xprt: transport with other tasks potentially waiting
   * @task: task that is releasing access to the transport
   *
   * Note that "task" can be NULL.  No congestion control is provided.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340
   */
49e9a8908   Chuck Lever   [PATCH] RPC: expo...
341
  void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
342
343
  {
  	if (xprt->snd_task == task) {
632e3bdc5   Trond Myklebust   SUNRPC: Ensure cl...
344
  		xprt_clear_locked(xprt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
345
346
347
  		__xprt_lock_write_next(xprt);
  	}
  }
124448097   \"Talpey, Thomas\   SUNRPC: add EXPOR...
348
  EXPORT_SYMBOL_GPL(xprt_release_xprt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349

49e9a8908   Chuck Lever   [PATCH] RPC: expo...
350
351
352
353
354
355
356
357
358
359
360
  /**
   * xprt_release_xprt_cong - allow other requests to use a transport
   * @xprt: transport with other tasks potentially waiting
   * @task: task that is releasing access to the transport
   *
   * Note that "task" can be NULL.  Another task is awoken to use the
   * transport if the transport's congestion window allows it.
   */
  void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task)
  {
  	if (xprt->snd_task == task) {
632e3bdc5   Trond Myklebust   SUNRPC: Ensure cl...
361
  		xprt_clear_locked(xprt);
49e9a8908   Chuck Lever   [PATCH] RPC: expo...
362
363
364
  		__xprt_lock_write_next_cong(xprt);
  	}
  }
124448097   \"Talpey, Thomas\   SUNRPC: add EXPOR...
365
  EXPORT_SYMBOL_GPL(xprt_release_xprt_cong);
49e9a8908   Chuck Lever   [PATCH] RPC: expo...
366
367
  
  static inline void xprt_release_write(struct rpc_xprt *xprt, struct rpc_task *task)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368
  {
4a0f8c04f   Chuck Lever   [PATCH] RPC: Rena...
369
  	spin_lock_bh(&xprt->transport_lock);
49e9a8908   Chuck Lever   [PATCH] RPC: expo...
370
  	xprt->ops->release_xprt(xprt, task);
4a0f8c04f   Chuck Lever   [PATCH] RPC: Rena...
371
  	spin_unlock_bh(&xprt->transport_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
372
373
374
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
376
377
378
379
380
381
382
383
384
   * Van Jacobson congestion avoidance. Check if the congestion window
   * overflowed. Put the task to sleep if this is the case.
   */
  static int
  __xprt_get_cong(struct rpc_xprt *xprt, struct rpc_task *task)
  {
  	struct rpc_rqst *req = task->tk_rqstp;
  
  	if (req->rq_cong)
  		return 1;
46121cf7d   Chuck Lever   SUNRPC: fix print...
385
386
  	dprintk("RPC: %5u xprt_cwnd_limited cong = %lu cwnd = %lu
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
  			task->tk_pid, xprt->cong, xprt->cwnd);
  	if (RPCXPRT_CONGESTED(xprt))
  		return 0;
  	req->rq_cong = 1;
  	xprt->cong += RPC_CWNDSCALE;
  	return 1;
  }
  
  /*
   * Adjust the congestion window, and wake up the next task
   * that has been sleeping due to congestion
   */
  static void
  __xprt_put_cong(struct rpc_xprt *xprt, struct rpc_rqst *req)
  {
  	if (!req->rq_cong)
  		return;
  	req->rq_cong = 0;
  	xprt->cong -= RPC_CWNDSCALE;
49e9a8908   Chuck Lever   [PATCH] RPC: expo...
406
  	__xprt_lock_write_next_cong(xprt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
407
  }
46c0ee8bc   Chuck Lever   [PATCH] RPC: sepa...
408
  /**
a58dd398f   Chuck Lever   [PATCH] RPC: add ...
409
410
411
412
413
414
415
416
417
   * xprt_release_rqst_cong - housekeeping when request is complete
   * @task: RPC request that recently completed
   *
   * Useful for transports that require congestion control.
   */
  void xprt_release_rqst_cong(struct rpc_task *task)
  {
  	__xprt_put_cong(task->tk_xprt, task->tk_rqstp);
  }
124448097   \"Talpey, Thomas\   SUNRPC: add EXPOR...
418
  EXPORT_SYMBOL_GPL(xprt_release_rqst_cong);
a58dd398f   Chuck Lever   [PATCH] RPC: add ...
419
420
  
  /**
46c0ee8bc   Chuck Lever   [PATCH] RPC: sepa...
421
422
423
424
   * xprt_adjust_cwnd - adjust transport congestion window
   * @task: recently completed RPC request used to adjust window
   * @result: result code of completed RPC request
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
425
426
   * We use a time-smoothed congestion estimator to avoid heavy oscillation.
   */
46c0ee8bc   Chuck Lever   [PATCH] RPC: sepa...
427
  void xprt_adjust_cwnd(struct rpc_task *task, int result)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428
  {
46c0ee8bc   Chuck Lever   [PATCH] RPC: sepa...
429
430
431
  	struct rpc_rqst *req = task->tk_rqstp;
  	struct rpc_xprt *xprt = task->tk_xprt;
  	unsigned long cwnd = xprt->cwnd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
434
435
436
437
438
  	if (result >= 0 && cwnd <= xprt->cong) {
  		/* The (cwnd >> 1) term makes sure
  		 * the result gets rounded properly. */
  		cwnd += (RPC_CWNDSCALE * RPC_CWNDSCALE + (cwnd >> 1)) / cwnd;
  		if (cwnd > RPC_MAXCWND(xprt))
  			cwnd = RPC_MAXCWND(xprt);
49e9a8908   Chuck Lever   [PATCH] RPC: expo...
439
  		__xprt_lock_write_next_cong(xprt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
440
441
442
443
444
  	} else if (result == -ETIMEDOUT) {
  		cwnd >>= 1;
  		if (cwnd < RPC_CWNDSCALE)
  			cwnd = RPC_CWNDSCALE;
  	}
46121cf7d   Chuck Lever   SUNRPC: fix print...
445
446
  	dprintk("RPC:       cong %ld, cwnd was %ld, now %ld
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
448
  			xprt->cong, xprt->cwnd, cwnd);
  	xprt->cwnd = cwnd;
46c0ee8bc   Chuck Lever   [PATCH] RPC: sepa...
449
  	__xprt_put_cong(xprt, req);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450
  }
124448097   \"Talpey, Thomas\   SUNRPC: add EXPOR...
451
  EXPORT_SYMBOL_GPL(xprt_adjust_cwnd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
452

44fbac228   Chuck Lever   [PATCH] RPC: Add ...
453
454
455
456
457
458
459
460
461
462
463
464
465
  /**
   * xprt_wake_pending_tasks - wake all tasks on a transport's pending queue
   * @xprt: transport with waiting tasks
   * @status: result code to plant in each task before waking it
   *
   */
  void xprt_wake_pending_tasks(struct rpc_xprt *xprt, int status)
  {
  	if (status < 0)
  		rpc_wake_up_status(&xprt->pending, status);
  	else
  		rpc_wake_up(&xprt->pending);
  }
124448097   \"Talpey, Thomas\   SUNRPC: add EXPOR...
466
  EXPORT_SYMBOL_GPL(xprt_wake_pending_tasks);
44fbac228   Chuck Lever   [PATCH] RPC: Add ...
467

c7b2cae8a   Chuck Lever   [PATCH] RPC: sepa...
468
469
470
  /**
   * xprt_wait_for_buffer_space - wait for transport output buffer to clear
   * @task: task to be put to sleep
0b80ae420   Randy Dunlap   sunrpc: fix missi...
471
   * @action: function pointer to be executed after wait
c7b2cae8a   Chuck Lever   [PATCH] RPC: sepa...
472
   */
b6ddf64ff   Trond Myklebust   SUNRPC: Fix up xp...
473
  void xprt_wait_for_buffer_space(struct rpc_task *task, rpc_action action)
c7b2cae8a   Chuck Lever   [PATCH] RPC: sepa...
474
475
476
477
478
  {
  	struct rpc_rqst *req = task->tk_rqstp;
  	struct rpc_xprt *xprt = req->rq_xprt;
  
  	task->tk_timeout = req->rq_timeout;
b6ddf64ff   Trond Myklebust   SUNRPC: Fix up xp...
479
  	rpc_sleep_on(&xprt->pending, task, action);
c7b2cae8a   Chuck Lever   [PATCH] RPC: sepa...
480
  }
124448097   \"Talpey, Thomas\   SUNRPC: add EXPOR...
481
  EXPORT_SYMBOL_GPL(xprt_wait_for_buffer_space);
c7b2cae8a   Chuck Lever   [PATCH] RPC: sepa...
482
483
484
485
486
487
488
489
490
491
492
493
494
495
  
  /**
   * xprt_write_space - wake the task waiting for transport output buffer space
   * @xprt: transport with waiting tasks
   *
   * Can be called in a soft IRQ context, so xprt_write_space never sleeps.
   */
  void xprt_write_space(struct rpc_xprt *xprt)
  {
  	if (unlikely(xprt->shutdown))
  		return;
  
  	spin_lock_bh(&xprt->transport_lock);
  	if (xprt->snd_task) {
46121cf7d   Chuck Lever   SUNRPC: fix print...
496
497
498
  		dprintk("RPC:       write space: waking waiting task on "
  				"xprt %p
  ", xprt);
fda139393   Trond Myklebust   SUNRPC: Convert u...
499
  		rpc_wake_up_queued_task(&xprt->pending, xprt->snd_task);
c7b2cae8a   Chuck Lever   [PATCH] RPC: sepa...
500
501
502
  	}
  	spin_unlock_bh(&xprt->transport_lock);
  }
124448097   \"Talpey, Thomas\   SUNRPC: add EXPOR...
503
  EXPORT_SYMBOL_GPL(xprt_write_space);
c7b2cae8a   Chuck Lever   [PATCH] RPC: sepa...
504

fe3aca290   Chuck Lever   [PATCH] RPC: add ...
505
506
507
508
509
510
511
512
513
514
515
516
  /**
   * xprt_set_retrans_timeout_def - set a request's retransmit timeout
   * @task: task whose timeout is to be set
   *
   * Set a request's retransmit timeout based on the transport's
   * default timeout parameters.  Used by transports that don't adjust
   * the retransmit timeout based on round-trip time estimation.
   */
  void xprt_set_retrans_timeout_def(struct rpc_task *task)
  {
  	task->tk_timeout = task->tk_rqstp->rq_timeout;
  }
124448097   \"Talpey, Thomas\   SUNRPC: add EXPOR...
517
  EXPORT_SYMBOL_GPL(xprt_set_retrans_timeout_def);
fe3aca290   Chuck Lever   [PATCH] RPC: add ...
518
519
520
521
  
  /*
   * xprt_set_retrans_timeout_rtt - set a request's retransmit timeout
   * @task: task whose timeout is to be set
cca5172a7   YOSHIFUJI Hideaki   [NET] SUNRPC: Fix...
522
   *
fe3aca290   Chuck Lever   [PATCH] RPC: add ...
523
524
525
526
527
   * Set a request's retransmit timeout using the RTT estimator.
   */
  void xprt_set_retrans_timeout_rtt(struct rpc_task *task)
  {
  	int timer = task->tk_msg.rpc_proc->p_timer;
ba7392bb3   Trond Myklebust   SUNRPC: Add suppo...
528
529
  	struct rpc_clnt *clnt = task->tk_client;
  	struct rpc_rtt *rtt = clnt->cl_rtt;
fe3aca290   Chuck Lever   [PATCH] RPC: add ...
530
  	struct rpc_rqst *req = task->tk_rqstp;
ba7392bb3   Trond Myklebust   SUNRPC: Add suppo...
531
  	unsigned long max_timeout = clnt->cl_timeout->to_maxval;
fe3aca290   Chuck Lever   [PATCH] RPC: add ...
532
533
534
535
536
537
  
  	task->tk_timeout = rpc_calc_rto(rtt, timer);
  	task->tk_timeout <<= rpc_ntimeo(rtt, timer) + req->rq_retries;
  	if (task->tk_timeout > max_timeout || task->tk_timeout == 0)
  		task->tk_timeout = max_timeout;
  }
124448097   \"Talpey, Thomas\   SUNRPC: add EXPOR...
538
  EXPORT_SYMBOL_GPL(xprt_set_retrans_timeout_rtt);
fe3aca290   Chuck Lever   [PATCH] RPC: add ...
539

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
540
541
  static void xprt_reset_majortimeo(struct rpc_rqst *req)
  {
ba7392bb3   Trond Myklebust   SUNRPC: Add suppo...
542
  	const struct rpc_timeout *to = req->rq_task->tk_client->cl_timeout;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
543
544
545
546
547
548
549
550
551
552
  
  	req->rq_majortimeo = req->rq_timeout;
  	if (to->to_exponential)
  		req->rq_majortimeo <<= to->to_retries;
  	else
  		req->rq_majortimeo += to->to_increment * to->to_retries;
  	if (req->rq_majortimeo > to->to_maxval || req->rq_majortimeo == 0)
  		req->rq_majortimeo = to->to_maxval;
  	req->rq_majortimeo += jiffies;
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
553
554
555
556
  /**
   * xprt_adjust_timeout - adjust timeout values for next retransmit
   * @req: RPC request containing parameters to use for the adjustment
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557
558
559
560
   */
  int xprt_adjust_timeout(struct rpc_rqst *req)
  {
  	struct rpc_xprt *xprt = req->rq_xprt;
ba7392bb3   Trond Myklebust   SUNRPC: Add suppo...
561
  	const struct rpc_timeout *to = req->rq_task->tk_client->cl_timeout;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562
563
564
565
566
567
568
569
570
571
  	int status = 0;
  
  	if (time_before(jiffies, req->rq_majortimeo)) {
  		if (to->to_exponential)
  			req->rq_timeout <<= 1;
  		else
  			req->rq_timeout += to->to_increment;
  		if (to->to_maxval && req->rq_timeout >= to->to_maxval)
  			req->rq_timeout = to->to_maxval;
  		req->rq_retries++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
572
573
574
575
576
  	} else {
  		req->rq_timeout = to->to_initval;
  		req->rq_retries = 0;
  		xprt_reset_majortimeo(req);
  		/* Reset the RTT counters == "slow start" */
4a0f8c04f   Chuck Lever   [PATCH] RPC: Rena...
577
  		spin_lock_bh(&xprt->transport_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
578
  		rpc_init_rtt(req->rq_task->tk_client->cl_rtt, to->to_initval);
4a0f8c04f   Chuck Lever   [PATCH] RPC: Rena...
579
  		spin_unlock_bh(&xprt->transport_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
581
582
583
584
585
586
587
588
589
  		status = -ETIMEDOUT;
  	}
  
  	if (req->rq_timeout == 0) {
  		printk(KERN_WARNING "xprt_adjust_timeout: rq_timeout = 0!
  ");
  		req->rq_timeout = 5 * HZ;
  	}
  	return status;
  }
65f27f384   David Howells   WorkStruct: Pass ...
590
  static void xprt_autoclose(struct work_struct *work)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
591
  {
65f27f384   David Howells   WorkStruct: Pass ...
592
593
  	struct rpc_xprt *xprt =
  		container_of(work, struct rpc_xprt, task_cleanup);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594

a246b0105   Chuck Lever   [PATCH] RPC: intr...
595
  	xprt->ops->close(xprt);
66af1e558   Trond Myklebust   SUNRPC: Fix a rac...
596
  	clear_bit(XPRT_CLOSE_WAIT, &xprt->state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
597
598
  	xprt_release_write(xprt, NULL);
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
599
  /**
62da3b248   Trond Myklebust   SUNRPC: Rename xp...
600
   * xprt_disconnect_done - mark a transport as disconnected
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
601
602
   * @xprt: transport to flag for disconnect
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
603
   */
62da3b248   Trond Myklebust   SUNRPC: Rename xp...
604
  void xprt_disconnect_done(struct rpc_xprt *xprt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
  {
46121cf7d   Chuck Lever   SUNRPC: fix print...
606
607
  	dprintk("RPC:       disconnected transport %p
  ", xprt);
4a0f8c04f   Chuck Lever   [PATCH] RPC: Rena...
608
  	spin_lock_bh(&xprt->transport_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
609
  	xprt_clear_connected(xprt);
2a4919919   Trond Myklebust   SUNRPC: Return EA...
610
  	xprt_wake_pending_tasks(xprt, -EAGAIN);
4a0f8c04f   Chuck Lever   [PATCH] RPC: Rena...
611
  	spin_unlock_bh(&xprt->transport_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
612
  }
62da3b248   Trond Myklebust   SUNRPC: Rename xp...
613
  EXPORT_SYMBOL_GPL(xprt_disconnect_done);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
614

66af1e558   Trond Myklebust   SUNRPC: Fix a rac...
615
616
617
618
619
620
621
622
623
624
625
626
627
  /**
   * xprt_force_disconnect - force a transport to disconnect
   * @xprt: transport to disconnect
   *
   */
  void xprt_force_disconnect(struct rpc_xprt *xprt)
  {
  	/* Don't race with the test_bit() in xprt_clear_locked() */
  	spin_lock_bh(&xprt->transport_lock);
  	set_bit(XPRT_CLOSE_WAIT, &xprt->state);
  	/* Try to schedule an autoclose RPC call */
  	if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
  		queue_work(rpciod_workqueue, &xprt->task_cleanup);
2a4919919   Trond Myklebust   SUNRPC: Return EA...
628
  	xprt_wake_pending_tasks(xprt, -EAGAIN);
66af1e558   Trond Myklebust   SUNRPC: Fix a rac...
629
630
  	spin_unlock_bh(&xprt->transport_lock);
  }
66af1e558   Trond Myklebust   SUNRPC: Fix a rac...
631

7c1d71cf5   Trond Myklebust   SUNRPC: Don't dis...
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
  /**
   * xprt_conditional_disconnect - force a transport to disconnect
   * @xprt: transport to disconnect
   * @cookie: 'connection cookie'
   *
   * This attempts to break the connection if and only if 'cookie' matches
   * the current transport 'connection cookie'. It ensures that we don't
   * try to break the connection more than once when we need to retransmit
   * a batch of RPC requests.
   *
   */
  void xprt_conditional_disconnect(struct rpc_xprt *xprt, unsigned int cookie)
  {
  	/* Don't race with the test_bit() in xprt_clear_locked() */
  	spin_lock_bh(&xprt->transport_lock);
  	if (cookie != xprt->connect_cookie)
  		goto out;
  	if (test_bit(XPRT_CLOSING, &xprt->state) || !xprt_connected(xprt))
  		goto out;
  	set_bit(XPRT_CLOSE_WAIT, &xprt->state);
  	/* Try to schedule an autoclose RPC call */
  	if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
  		queue_work(rpciod_workqueue, &xprt->task_cleanup);
2a4919919   Trond Myklebust   SUNRPC: Return EA...
655
  	xprt_wake_pending_tasks(xprt, -EAGAIN);
7c1d71cf5   Trond Myklebust   SUNRPC: Don't dis...
656
657
658
  out:
  	spin_unlock_bh(&xprt->transport_lock);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
659
660
661
662
  static void
  xprt_init_autodisconnect(unsigned long data)
  {
  	struct rpc_xprt *xprt = (struct rpc_xprt *)data;
4a0f8c04f   Chuck Lever   [PATCH] RPC: Rena...
663
  	spin_lock(&xprt->transport_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
664
665
  	if (!list_empty(&xprt->recv) || xprt->shutdown)
  		goto out_abort;
2226feb6b   Chuck Lever   [PATCH] RPC: rena...
666
  	if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
667
  		goto out_abort;
4a0f8c04f   Chuck Lever   [PATCH] RPC: Rena...
668
  	spin_unlock(&xprt->transport_lock);
f75e6745a   Trond Myklebust   SUNRPC: Fix the p...
669
670
  	set_bit(XPRT_CONNECTION_CLOSE, &xprt->state);
  	queue_work(rpciod_workqueue, &xprt->task_cleanup);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
671
672
  	return;
  out_abort:
4a0f8c04f   Chuck Lever   [PATCH] RPC: Rena...
673
  	spin_unlock(&xprt->transport_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
674
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
675
676
677
  /**
   * xprt_connect - schedule a transport connect operation
   * @task: RPC task that is requesting the connect
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
678
679
680
681
682
   *
   */
  void xprt_connect(struct rpc_task *task)
  {
  	struct rpc_xprt	*xprt = task->tk_xprt;
46121cf7d   Chuck Lever   SUNRPC: fix print...
683
684
  	dprintk("RPC: %5u xprt_connect xprt %p %s connected
  ", task->tk_pid,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
685
  			xprt, (xprt_connected(xprt) ? "is" : "is not"));
ec739ef03   Chuck Lever   SUNRPC: Create a ...
686
  	if (!xprt_bound(xprt)) {
01d37c428   Trond Myklebust   SUNRPC: xprt_conn...
687
  		task->tk_status = -EAGAIN;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
688
689
690
691
692
  		return;
  	}
  	if (!xprt_lock_write(xprt, task))
  		return;
  	if (xprt_connected(xprt))
a246b0105   Chuck Lever   [PATCH] RPC: intr...
693
694
695
696
  		xprt_release_write(xprt, task);
  	else {
  		if (task->tk_rqstp)
  			task->tk_rqstp->rq_bytes_sent = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
697

03bf4b707   Chuck Lever   [PATCH] RPC: para...
698
  		task->tk_timeout = xprt->connect_timeout;
5d00837b9   Trond Myklebust   SUNRPC: Run rpc t...
699
  		rpc_sleep_on(&xprt->pending, task, xprt_connect_status);
262ca07de   Chuck Lever   SUNRPC: add a han...
700
  		xprt->stat.connect_start = jiffies;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
701
  		xprt->ops->connect(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
702
703
  	}
  	return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
705
  static void xprt_connect_status(struct rpc_task *task)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
706
707
  {
  	struct rpc_xprt	*xprt = task->tk_xprt;
cd983ef81   Chuck Lever   SUNRPC: Remove ob...
708
  	if (task->tk_status == 0) {
262ca07de   Chuck Lever   SUNRPC: add a han...
709
710
  		xprt->stat.connect_count++;
  		xprt->stat.connect_time += (long)jiffies - xprt->stat.connect_start;
46121cf7d   Chuck Lever   SUNRPC: fix print...
711
712
  		dprintk("RPC: %5u xprt_connect_status: connection established
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
713
714
715
  				task->tk_pid);
  		return;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
716
  	switch (task->tk_status) {
2a4919919   Trond Myklebust   SUNRPC: Return EA...
717
718
719
  	case -EAGAIN:
  		dprintk("RPC: %5u xprt_connect_status: retrying
  ", task->tk_pid);
23475d66b   Chuck Lever   [PATCH] RPC: Repo...
720
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
721
  	case -ETIMEDOUT:
46121cf7d   Chuck Lever   SUNRPC: fix print...
722
723
724
  		dprintk("RPC: %5u xprt_connect_status: connect attempt timed "
  				"out
  ", task->tk_pid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
725
726
  		break;
  	default:
46121cf7d   Chuck Lever   SUNRPC: fix print...
727
728
729
730
  		dprintk("RPC: %5u xprt_connect_status: error %d connecting to "
  				"server %s
  ", task->tk_pid, -task->tk_status,
  				task->tk_client->cl_server);
23475d66b   Chuck Lever   [PATCH] RPC: Repo...
731
732
  		xprt_release_write(xprt, task);
  		task->tk_status = -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
733
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
735
736
737
738
739
  /**
   * xprt_lookup_rqst - find an RPC request corresponding to an XID
   * @xprt: transport on which the original request was transmitted
   * @xid: RPC XID of incoming reply
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
740
   */
d8ed029d6   Alexey Dobriyan   [SUNRPC]: trivial...
741
  struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, __be32 xid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
743
  {
  	struct list_head *pos;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
745
746
  
  	list_for_each(pos, &xprt->recv) {
  		struct rpc_rqst *entry = list_entry(pos, struct rpc_rqst, rq_list);
262ca07de   Chuck Lever   SUNRPC: add a han...
747
748
  		if (entry->rq_xid == xid)
  			return entry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
749
  	}
46121cf7d   Chuck Lever   SUNRPC: fix print...
750
751
752
753
  
  	dprintk("RPC:       xprt_lookup_rqst did not find xid %08x
  ",
  			ntohl(xid));
262ca07de   Chuck Lever   SUNRPC: add a han...
754
755
  	xprt->stat.bad_xids++;
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
756
  }
124448097   \"Talpey, Thomas\   SUNRPC: add EXPOR...
757
  EXPORT_SYMBOL_GPL(xprt_lookup_rqst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
758

9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
759
  /**
1570c1e41   Chuck Lever   [PATCH] RPC: add ...
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
   * xprt_update_rtt - update an RPC client's RTT state after receiving a reply
   * @task: RPC request that recently completed
   *
   */
  void xprt_update_rtt(struct rpc_task *task)
  {
  	struct rpc_rqst *req = task->tk_rqstp;
  	struct rpc_rtt *rtt = task->tk_client->cl_rtt;
  	unsigned timer = task->tk_msg.rpc_proc->p_timer;
  
  	if (timer) {
  		if (req->rq_ntrans == 1)
  			rpc_update_rtt(rtt, timer,
  					(long)jiffies - req->rq_xtime);
  		rpc_set_timeo(rtt, timer, req->rq_ntrans - 1);
  	}
  }
124448097   \"Talpey, Thomas\   SUNRPC: add EXPOR...
777
  EXPORT_SYMBOL_GPL(xprt_update_rtt);
1570c1e41   Chuck Lever   [PATCH] RPC: add ...
778
779
  
  /**
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
780
   * xprt_complete_rqst - called when reply processing is complete
1570c1e41   Chuck Lever   [PATCH] RPC: add ...
781
   * @task: RPC request that recently completed
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
782
783
   * @copied: actual number of bytes received from the transport
   *
1570c1e41   Chuck Lever   [PATCH] RPC: add ...
784
   * Caller holds transport lock.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
785
   */
1570c1e41   Chuck Lever   [PATCH] RPC: add ...
786
  void xprt_complete_rqst(struct rpc_task *task, int copied)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
787
  {
1570c1e41   Chuck Lever   [PATCH] RPC: add ...
788
  	struct rpc_rqst *req = task->tk_rqstp;
fda139393   Trond Myklebust   SUNRPC: Convert u...
789
  	struct rpc_xprt *xprt = req->rq_xprt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
790

1570c1e41   Chuck Lever   [PATCH] RPC: add ...
791
792
793
  	dprintk("RPC: %5u xid %08x complete (%d bytes received)
  ",
  			task->tk_pid, ntohl(req->rq_xid), copied);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
794

fda139393   Trond Myklebust   SUNRPC: Convert u...
795
  	xprt->stat.recvs++;
ef759a2e5   Chuck Lever   SUNRPC: introduce...
796
  	task->tk_rtt = (long)jiffies - req->rq_xtime;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
797
  	list_del_init(&req->rq_list);
1e799b673   Trond Myklebust   SUNRPC: Fix read ...
798
  	req->rq_private_buf.len = copied;
dd2b63d04   Ricardo Labiaga   nfs41: Rename rq_...
799
800
  	/* Ensure all writes are done before we update */
  	/* req->rq_reply_bytes_recvd */
43ac3f296   Trond Myklebust   SUNRPC: Fix memor...
801
  	smp_wmb();
dd2b63d04   Ricardo Labiaga   nfs41: Rename rq_...
802
  	req->rq_reply_bytes_recvd = copied;
fda139393   Trond Myklebust   SUNRPC: Convert u...
803
  	rpc_wake_up_queued_task(&xprt->pending, task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
804
  }
124448097   \"Talpey, Thomas\   SUNRPC: add EXPOR...
805
  EXPORT_SYMBOL_GPL(xprt_complete_rqst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
806

46c0ee8bc   Chuck Lever   [PATCH] RPC: sepa...
807
  static void xprt_timer(struct rpc_task *task)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
808
  {
46c0ee8bc   Chuck Lever   [PATCH] RPC: sepa...
809
  	struct rpc_rqst *req = task->tk_rqstp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
810
  	struct rpc_xprt *xprt = req->rq_xprt;
5d00837b9   Trond Myklebust   SUNRPC: Run rpc t...
811
812
  	if (task->tk_status != -ETIMEDOUT)
  		return;
46121cf7d   Chuck Lever   SUNRPC: fix print...
813
814
  	dprintk("RPC: %5u xprt_timer
  ", task->tk_pid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
815

5d00837b9   Trond Myklebust   SUNRPC: Run rpc t...
816
  	spin_lock_bh(&xprt->transport_lock);
dd2b63d04   Ricardo Labiaga   nfs41: Rename rq_...
817
  	if (!req->rq_reply_bytes_recvd) {
46c0ee8bc   Chuck Lever   [PATCH] RPC: sepa...
818
819
  		if (xprt->ops->timer)
  			xprt->ops->timer(task);
5d00837b9   Trond Myklebust   SUNRPC: Run rpc t...
820
821
822
  	} else
  		task->tk_status = 0;
  	spin_unlock_bh(&xprt->transport_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
823
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
824
825
826
827
  /**
   * xprt_prepare_transmit - reserve the transport before sending a request
   * @task: RPC task about to send a request
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
828
   */
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
829
  int xprt_prepare_transmit(struct rpc_task *task)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
830
831
832
833
  {
  	struct rpc_rqst	*req = task->tk_rqstp;
  	struct rpc_xprt	*xprt = req->rq_xprt;
  	int err = 0;
46121cf7d   Chuck Lever   SUNRPC: fix print...
834
835
  	dprintk("RPC: %5u xprt_prepare_transmit
  ", task->tk_pid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
836

4a0f8c04f   Chuck Lever   [PATCH] RPC: Rena...
837
  	spin_lock_bh(&xprt->transport_lock);
dd2b63d04   Ricardo Labiaga   nfs41: Rename rq_...
838
839
  	if (req->rq_reply_bytes_recvd && !req->rq_bytes_sent) {
  		err = req->rq_reply_bytes_recvd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
840
841
  		goto out_unlock;
  	}
2a4919919   Trond Myklebust   SUNRPC: Return EA...
842
  	if (!xprt->ops->reserve_xprt(task))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
843
  		err = -EAGAIN;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
844
  out_unlock:
4a0f8c04f   Chuck Lever   [PATCH] RPC: Rena...
845
  	spin_unlock_bh(&xprt->transport_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
846
847
  	return err;
  }
e0ab53dea   Trond Myklebust   RPC: Ensure that ...
848
  void xprt_end_transmit(struct rpc_task *task)
5e5ce5be6   Trond Myklebust   RPC: allow call_e...
849
  {
343952fa5   Rahul Iyer   nfs41: Get the rp...
850
  	xprt_release_write(task->tk_rqstp->rq_xprt, task);
5e5ce5be6   Trond Myklebust   RPC: allow call_e...
851
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
852
853
854
855
856
857
858
  /**
   * xprt_transmit - send an RPC request on a transport
   * @task: controlling RPC task
   *
   * We have to copy the iovec because sendmsg fiddles with its contents.
   */
  void xprt_transmit(struct rpc_task *task)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
859
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
860
861
  	struct rpc_rqst	*req = task->tk_rqstp;
  	struct rpc_xprt	*xprt = req->rq_xprt;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
862
  	int status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
863

46121cf7d   Chuck Lever   SUNRPC: fix print...
864
865
  	dprintk("RPC: %5u xprt_transmit(%u)
  ", task->tk_pid, req->rq_slen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
866

dd2b63d04   Ricardo Labiaga   nfs41: Rename rq_...
867
  	if (!req->rq_reply_bytes_recvd) {
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
868
869
870
871
  		if (list_empty(&req->rq_list) && rpc_reply_expected(task)) {
  			/*
  			 * Add to the list only if we're expecting a reply
  			 */
4a0f8c04f   Chuck Lever   [PATCH] RPC: Rena...
872
  			spin_lock_bh(&xprt->transport_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
873
874
875
876
877
  			/* Update the softirq receive buffer */
  			memcpy(&req->rq_private_buf, &req->rq_rcv_buf,
  					sizeof(req->rq_private_buf));
  			/* Add request to the receive list */
  			list_add_tail(&req->rq_list, &xprt->recv);
4a0f8c04f   Chuck Lever   [PATCH] RPC: Rena...
878
  			spin_unlock_bh(&xprt->transport_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
879
  			xprt_reset_majortimeo(req);
0f9dc2b16   Trond Myklebust   [PATCH] RPC: Clea...
880
881
  			/* Turn off autodisconnect */
  			del_singleshot_timer_sync(&xprt->timer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
882
883
884
  		}
  	} else if (!req->rq_bytes_sent)
  		return;
7c1d71cf5   Trond Myklebust   SUNRPC: Don't dis...
885
  	req->rq_connect_cookie = xprt->connect_cookie;
b22602a67   Chuck Lever   SUNRPC: Ensure al...
886
  	req->rq_xtime = jiffies;
a246b0105   Chuck Lever   [PATCH] RPC: intr...
887
  	status = xprt->ops->send_request(task);
c8485e4d6   Trond Myklebust   SUNRPC: Handle EC...
888
889
890
891
  	if (status != 0) {
  		task->tk_status = status;
  		return;
  	}
262ca07de   Chuck Lever   SUNRPC: add a han...
892

c8485e4d6   Trond Myklebust   SUNRPC: Handle EC...
893
894
895
  	dprintk("RPC: %5u xmit complete
  ", task->tk_pid);
  	spin_lock_bh(&xprt->transport_lock);
262ca07de   Chuck Lever   SUNRPC: add a han...
896

c8485e4d6   Trond Myklebust   SUNRPC: Handle EC...
897
  	xprt->ops->set_retrans_timeout(task);
262ca07de   Chuck Lever   SUNRPC: add a han...
898

c8485e4d6   Trond Myklebust   SUNRPC: Handle EC...
899
900
901
  	xprt->stat.sends++;
  	xprt->stat.req_u += xprt->stat.sends - xprt->stat.recvs;
  	xprt->stat.bklog_u += xprt->backlog.qlen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
902

c8485e4d6   Trond Myklebust   SUNRPC: Handle EC...
903
904
905
  	/* Don't race with disconnect */
  	if (!xprt_connected(xprt))
  		task->tk_status = -ENOTCONN;
dd2b63d04   Ricardo Labiaga   nfs41: Rename rq_...
906
  	else if (!req->rq_reply_bytes_recvd && rpc_reply_expected(task)) {
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
907
908
909
910
  		/*
  		 * Sleep on the pending queue since
  		 * we're expecting a reply.
  		 */
c8485e4d6   Trond Myklebust   SUNRPC: Handle EC...
911
  		rpc_sleep_on(&xprt->pending, task, xprt_timer);
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
912
  	}
c8485e4d6   Trond Myklebust   SUNRPC: Handle EC...
913
  	spin_unlock_bh(&xprt->transport_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
914
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
915
  static inline void do_xprt_reserve(struct rpc_task *task)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
916
917
918
919
920
921
922
923
924
925
926
927
928
  {
  	struct rpc_xprt	*xprt = task->tk_xprt;
  
  	task->tk_status = 0;
  	if (task->tk_rqstp)
  		return;
  	if (!list_empty(&xprt->free)) {
  		struct rpc_rqst	*req = list_entry(xprt->free.next, struct rpc_rqst, rq_list);
  		list_del_init(&req->rq_list);
  		task->tk_rqstp = req;
  		xprt_request_init(task, xprt);
  		return;
  	}
46121cf7d   Chuck Lever   SUNRPC: fix print...
929
930
  	dprintk("RPC:       waiting for request slot
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
931
932
  	task->tk_status = -EAGAIN;
  	task->tk_timeout = 0;
5d00837b9   Trond Myklebust   SUNRPC: Run rpc t...
933
  	rpc_sleep_on(&xprt->backlog, task, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
934
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
935
936
937
938
939
940
941
942
  /**
   * xprt_reserve - allocate an RPC request slot
   * @task: RPC task requesting a slot allocation
   *
   * If no more slots are available, place the task on the transport's
   * backlog queue.
   */
  void xprt_reserve(struct rpc_task *task)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
943
944
945
946
  {
  	struct rpc_xprt	*xprt = task->tk_xprt;
  
  	task->tk_status = -EIO;
0065db328   Trond Myklebust   SUNRPC: Clean up ...
947
948
949
  	spin_lock(&xprt->reserve_lock);
  	do_xprt_reserve(task);
  	spin_unlock(&xprt->reserve_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
950
  }
d8ed029d6   Alexey Dobriyan   [SUNRPC]: trivial...
951
  static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
952
953
954
955
956
957
  {
  	return xprt->xid++;
  }
  
  static inline void xprt_init_xid(struct rpc_xprt *xprt)
  {
bf3fcf895   Chuck Lever   SUNRPC: NFS_ROOT ...
958
  	xprt->xid = net_random();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
959
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
960
  static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
961
962
  {
  	struct rpc_rqst	*req = task->tk_rqstp;
ba7392bb3   Trond Myklebust   SUNRPC: Add suppo...
963
  	req->rq_timeout = task->tk_client->cl_timeout->to_initval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
964
965
  	req->rq_task	= task;
  	req->rq_xprt    = xprt;
021071483   Chuck Lever   SUNRPC: switchabl...
966
  	req->rq_buffer  = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
967
  	req->rq_xid     = xprt_alloc_xid(xprt);
ead5e1c26   J. Bruce Fields   SUNRPC: Provide a...
968
  	req->rq_release_snd_buf = NULL;
da45828e2   Trond Myklebust   SUNRPC: Clean up ...
969
  	xprt_reset_majortimeo(req);
46121cf7d   Chuck Lever   SUNRPC: fix print...
970
971
  	dprintk("RPC: %5u reserved req %p xid %08x
  ", task->tk_pid,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
972
973
  			req, ntohl(req->rq_xid));
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
974
975
976
977
  /**
   * xprt_release - release an RPC request slot
   * @task: task which is finished with the slot
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
978
   */
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
979
  void xprt_release(struct rpc_task *task)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
980
  {
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
981
  	struct rpc_xprt	*xprt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
982
  	struct rpc_rqst	*req;
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
983
  	int is_bc_request;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
984
985
986
  
  	if (!(req = task->tk_rqstp))
  		return;
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
987
988
989
990
991
  
  	/* Preallocated backchannel request? */
  	is_bc_request = bc_prealloc(req);
  
  	xprt = req->rq_xprt;
11c556b3d   Chuck Lever   SUNRPC: provide a...
992
  	rpc_count_iostats(task);
4a0f8c04f   Chuck Lever   [PATCH] RPC: Rena...
993
  	spin_lock_bh(&xprt->transport_lock);
49e9a8908   Chuck Lever   [PATCH] RPC: expo...
994
  	xprt->ops->release_xprt(xprt, task);
a58dd398f   Chuck Lever   [PATCH] RPC: add ...
995
996
  	if (xprt->ops->release_request)
  		xprt->ops->release_request(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
997
998
999
  	if (!list_empty(&req->rq_list))
  		list_del(&req->rq_list);
  	xprt->last_used = jiffies;
0065db328   Trond Myklebust   SUNRPC: Clean up ...
1000
  	if (list_empty(&xprt->recv))
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1001
  		mod_timer(&xprt->timer,
03bf4b707   Chuck Lever   [PATCH] RPC: para...
1002
  				xprt->last_used + xprt->idle_timeout);
4a0f8c04f   Chuck Lever   [PATCH] RPC: Rena...
1003
  	spin_unlock_bh(&xprt->transport_lock);
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
1004
1005
  	if (!bc_prealloc(req))
  		xprt->ops->buf_free(req->rq_buffer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1006
  	task->tk_rqstp = NULL;
ead5e1c26   J. Bruce Fields   SUNRPC: Provide a...
1007
1008
  	if (req->rq_release_snd_buf)
  		req->rq_release_snd_buf(req);
55ae1aabf   Ricardo Labiaga   nfs41: Add backch...
1009
1010
1011
1012
1013
1014
1015
  
  	/*
  	 * Early exit if this is a backchannel preallocated request.
  	 * There is no need to have it added to the RPC slot list.
  	 */
  	if (is_bc_request)
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1016
  	memset(req, 0, sizeof(*req));	/* mark unused */
46121cf7d   Chuck Lever   SUNRPC: fix print...
1017
1018
  	dprintk("RPC: %5u release request %p
  ", task->tk_pid, req);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1019

5dc07727f   Chuck Lever   [PATCH] RPC: Rena...
1020
  	spin_lock(&xprt->reserve_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1021
  	list_add(&req->rq_list, &xprt->free);
555ee3af1   Chuck Lever   [PATCH] RPC: clea...
1022
  	rpc_wake_up_next(&xprt->backlog);
5dc07727f   Chuck Lever   [PATCH] RPC: Rena...
1023
  	spin_unlock(&xprt->reserve_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1024
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
1025
  /**
c2866763b   Chuck Lever   SUNRPC: use socka...
1026
   * xprt_create_transport - create an RPC transport
96802a095   Frank van Maarseveen   SUNRPC: cleanup t...
1027
   * @args: rpc transport creation arguments
c2866763b   Chuck Lever   SUNRPC: use socka...
1028
1029
   *
   */
3c341b0b9   \"Talpey, Thomas\   SUNRPC: rename th...
1030
  struct rpc_xprt *xprt_create_transport(struct xprt_create *args)
c2866763b   Chuck Lever   SUNRPC: use socka...
1031
  {
c2866763b   Chuck Lever   SUNRPC: use socka...
1032
1033
  	struct rpc_xprt	*xprt;
  	struct rpc_rqst	*req;
bc25571e2   \"Talpey, Thomas\   SUNRPC: Finish AP...
1034
  	struct xprt_class *t;
c2866763b   Chuck Lever   SUNRPC: use socka...
1035

bc25571e2   \"Talpey, Thomas\   SUNRPC: Finish AP...
1036
1037
  	spin_lock(&xprt_list_lock);
  	list_for_each_entry(t, &xprt_list, list) {
4fa016eb2   \"Talpey, Thomas\   NFS/SUNRPC: suppo...
1038
  		if (t->ident == args->ident) {
bc25571e2   \"Talpey, Thomas\   SUNRPC: Finish AP...
1039
1040
1041
  			spin_unlock(&xprt_list_lock);
  			goto found;
  		}
c2866763b   Chuck Lever   SUNRPC: use socka...
1042
  	}
bc25571e2   \"Talpey, Thomas\   SUNRPC: Finish AP...
1043
  	spin_unlock(&xprt_list_lock);
4fa016eb2   \"Talpey, Thomas\   NFS/SUNRPC: suppo...
1044
1045
  	printk(KERN_ERR "RPC: transport (%d) not supported
  ", args->ident);
bc25571e2   \"Talpey, Thomas\   SUNRPC: Finish AP...
1046
1047
1048
1049
  	return ERR_PTR(-EIO);
  
  found:
  	xprt = t->setup(args);
c8541ecdd   Chuck Lever   SUNRPC: Make the ...
1050
  	if (IS_ERR(xprt)) {
46121cf7d   Chuck Lever   SUNRPC: fix print...
1051
1052
  		dprintk("RPC:       xprt_create_transport: failed, %ld
  ",
c8541ecdd   Chuck Lever   SUNRPC: Make the ...
1053
1054
  				-PTR_ERR(xprt));
  		return xprt;
c2866763b   Chuck Lever   SUNRPC: use socka...
1055
  	}
6b6ca86b7   Trond Myklebust   SUNRPC: Add refco...
1056
  	kref_init(&xprt->kref);
c2866763b   Chuck Lever   SUNRPC: use socka...
1057
1058
1059
1060
1061
  	spin_lock_init(&xprt->transport_lock);
  	spin_lock_init(&xprt->reserve_lock);
  
  	INIT_LIST_HEAD(&xprt->free);
  	INIT_LIST_HEAD(&xprt->recv);
f9acac1a4   Ricardo Labiaga   nfs41: Initialize...
1062
1063
1064
1065
  #if defined(CONFIG_NFS_V4_1)
  	spin_lock_init(&xprt->bc_pa_lock);
  	INIT_LIST_HEAD(&xprt->bc_pa_list);
  #endif /* CONFIG_NFS_V4_1 */
65f27f384   David Howells   WorkStruct: Pass ...
1066
  	INIT_WORK(&xprt->task_cleanup, xprt_autoclose);
b24b8a247   Pavel Emelyanov   [NET]: Convert in...
1067
1068
  	setup_timer(&xprt->timer, xprt_init_autodisconnect,
  			(unsigned long)xprt);
c2866763b   Chuck Lever   SUNRPC: use socka...
1069
1070
  	xprt->last_used = jiffies;
  	xprt->cwnd = RPC_INITCWND;
a509050bd   Chuck Lever   SUNRPC: introduce...
1071
  	xprt->bind_index = 0;
c2866763b   Chuck Lever   SUNRPC: use socka...
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
  
  	rpc_init_wait_queue(&xprt->binding, "xprt_binding");
  	rpc_init_wait_queue(&xprt->pending, "xprt_pending");
  	rpc_init_wait_queue(&xprt->sending, "xprt_sending");
  	rpc_init_wait_queue(&xprt->resend, "xprt_resend");
  	rpc_init_priority_wait_queue(&xprt->backlog, "xprt_backlog");
  
  	/* initialize free list */
  	for (req = &xprt->slot[xprt->max_reqs-1]; req >= &xprt->slot[0]; req--)
  		list_add(&req->rq_list, &xprt->free);
  
  	xprt_init_xid(xprt);
46121cf7d   Chuck Lever   SUNRPC: fix print...
1084
1085
  	dprintk("RPC:       created transport %p with %u slots
  ", xprt,
c2866763b   Chuck Lever   SUNRPC: use socka...
1086
1087
1088
1089
  			xprt->max_reqs);
  
  	return xprt;
  }
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
1090
1091
  /**
   * xprt_destroy - destroy an RPC transport, killing off all requests.
6b6ca86b7   Trond Myklebust   SUNRPC: Add refco...
1092
   * @kref: kref for the transport to destroy
9903cd1c2   Chuck Lever   [PATCH] RPC: tran...
1093
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1094
   */
6b6ca86b7   Trond Myklebust   SUNRPC: Add refco...
1095
  static void xprt_destroy(struct kref *kref)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1096
  {
6b6ca86b7   Trond Myklebust   SUNRPC: Add refco...
1097
  	struct rpc_xprt *xprt = container_of(kref, struct rpc_xprt, kref);
46121cf7d   Chuck Lever   SUNRPC: fix print...
1098
1099
  	dprintk("RPC:       destroying transport %p
  ", xprt);
0065db328   Trond Myklebust   SUNRPC: Clean up ...
1100
1101
  	xprt->shutdown = 1;
  	del_timer_sync(&xprt->timer);
c8541ecdd   Chuck Lever   SUNRPC: Make the ...
1102

f6a1cc893   Trond Myklebust   SUNRPC: Add a (em...
1103
1104
1105
1106
1107
  	rpc_destroy_wait_queue(&xprt->binding);
  	rpc_destroy_wait_queue(&xprt->pending);
  	rpc_destroy_wait_queue(&xprt->sending);
  	rpc_destroy_wait_queue(&xprt->resend);
  	rpc_destroy_wait_queue(&xprt->backlog);
c8541ecdd   Chuck Lever   SUNRPC: Make the ...
1108
1109
1110
  	/*
  	 * Tear down transport state and free the rpc_xprt
  	 */
a246b0105   Chuck Lever   [PATCH] RPC: intr...
1111
  	xprt->ops->destroy(xprt);
6b6ca86b7   Trond Myklebust   SUNRPC: Add refco...
1112
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1113

6b6ca86b7   Trond Myklebust   SUNRPC: Add refco...
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
  /**
   * xprt_put - release a reference to an RPC transport.
   * @xprt: pointer to the transport
   *
   */
  void xprt_put(struct rpc_xprt *xprt)
  {
  	kref_put(&xprt->kref, xprt_destroy);
  }
  
  /**
   * xprt_get - return a reference to an RPC transport.
   * @xprt: pointer to the transport
   *
   */
  struct rpc_xprt *xprt_get(struct rpc_xprt *xprt)
  {
  	kref_get(&xprt->kref);
  	return xprt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1133
  }