Blame view

fs/lockd/xdr4.c 7.34 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
  /*
   * linux/fs/lockd/xdr4.c
   *
   * XDR support for lockd and the lock client.
   *
   * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
   * Copyright (C) 1999, Trond Myklebust <trond.myklebust@fys.uio.no>
   */
  
  #include <linux/types.h>
  #include <linux/sched.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
16
17
18
  #include <linux/nfs.h>
  
  #include <linux/sunrpc/xdr.h>
  #include <linux/sunrpc/clnt.h>
  #include <linux/sunrpc/svc.h>
  #include <linux/sunrpc/stats.h>
  #include <linux/lockd/lockd.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
  
  #define NLMDBG_FACILITY		NLMDBG_XDR
  
  static inline loff_t
  s64_to_loff_t(__s64 offset)
  {
  	return (loff_t)offset;
  }
  
  
  static inline s64
  loff_t_to_s64(loff_t offset)
  {
  	s64 res;
  	if (offset > NLM4_OFFSET_MAX)
  		res = NLM4_OFFSET_MAX;
  	else if (offset < -NLM4_OFFSET_MAX)
  		res = -NLM4_OFFSET_MAX;
  	else
  		res = offset;
  	return res;
  }
  
  /*
   * XDR functions for basic NLM types
   */
52921e02a   Al Viro   [PATCH] lockd end...
45
46
  static __be32 *
  nlm4_decode_cookie(__be32 *p, struct nlm_cookie *c)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
  {
  	unsigned int	len;
  
  	len = ntohl(*p++);
  	
  	if(len==0)
  	{
  		c->len=4;
  		memset(c->data, 0, 4);	/* hockeypux brain damage */
  	}
  	else if(len<=NLM_MAXCOOKIELEN)
  	{
  		c->len=len;
  		memcpy(c->data, p, len);
  		p+=XDR_QUADLEN(len);
  	}
  	else 
  	{
e159a08b6   Chuck Lever   LOCKD: Convert pr...
65
66
67
68
  		dprintk("lockd: bad cookie size %d (only cookies under "
  			"%d bytes are supported.)
  ",
  				len, NLM_MAXCOOKIELEN);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
71
72
  		return NULL;
  	}
  	return p;
  }
52921e02a   Al Viro   [PATCH] lockd end...
73
74
  static __be32 *
  nlm4_encode_cookie(__be32 *p, struct nlm_cookie *c)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
76
77
78
79
80
  {
  	*p++ = htonl(c->len);
  	memcpy(p, c->data, c->len);
  	p+=XDR_QUADLEN(c->len);
  	return p;
  }
52921e02a   Al Viro   [PATCH] lockd end...
81
82
  static __be32 *
  nlm4_decode_fh(__be32 *p, struct nfs_fh *f)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
84
85
86
  {
  	memset(f->data, 0, sizeof(f->data));
  	f->size = ntohl(*p++);
  	if (f->size > NFS_MAXFHSIZE) {
e159a08b6   Chuck Lever   LOCKD: Convert pr...
87
88
  		dprintk("lockd: bad fhandle size %d (should be <=%d)
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
90
91
92
93
94
  			f->size, NFS_MAXFHSIZE);
  		return NULL;
  	}
        	memcpy(f->data, p, f->size);
  	return p + XDR_QUADLEN(f->size);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
96
97
  /*
   * Encode and decode owner handle
   */
52921e02a   Al Viro   [PATCH] lockd end...
98
99
  static __be32 *
  nlm4_decode_oh(__be32 *p, struct xdr_netobj *oh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
102
  {
  	return xdr_decode_netobj(p, oh);
  }
52921e02a   Al Viro   [PATCH] lockd end...
103
  static __be32 *
52921e02a   Al Viro   [PATCH] lockd end...
104
  nlm4_decode_lock(__be32 *p, struct nlm_lock *lock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
106
  {
  	struct file_lock	*fl = &lock->fl;
d48c5f410   Trond Myklebust   NLM: Fix sparse w...
107
108
  	__u64			len, start;
  	__s64			end;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
110
111
112
113
114
  
  	if (!(p = xdr_decode_string_inplace(p, &lock->caller,
  					    &lock->len, NLM_MAXSTRLEN))
  	 || !(p = nlm4_decode_fh(p, &lock->fh))
  	 || !(p = nlm4_decode_oh(p, &lock->oh)))
  		return NULL;
7bab377fc   Trond Myklebust   lockd: Don't expo...
115
  	lock->svid  = ntohl(*p++);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
117
118
  
  	locks_init_lock(fl);
  	fl->fl_owner = current->files;
7bab377fc   Trond Myklebust   lockd: Don't expo...
119
  	fl->fl_pid   = (pid_t)lock->svid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
  	fl->fl_flags = FL_POSIX;
  	fl->fl_type  = F_RDLCK;		/* as good as anything else */
  	p = xdr_decode_hyper(p, &start);
  	p = xdr_decode_hyper(p, &len);
  	end = start + len - 1;
  
  	fl->fl_start = s64_to_loff_t(start);
  
  	if (len == 0 || end < 0)
  		fl->fl_end = OFFSET_MAX;
  	else
  		fl->fl_end = s64_to_loff_t(end);
  	return p;
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
137
   * Encode result of a TEST/TEST_MSG call
   */
52921e02a   Al Viro   [PATCH] lockd end...
138
139
  static __be32 *
  nlm4_encode_testres(__be32 *p, struct nlm_res *resp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
141
142
143
144
145
146
147
148
149
150
151
152
  {
  	s64		start, len;
  
  	dprintk("xdr: before encode_testres (p %p resp %p)
  ", p, resp);
  	if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
  		return NULL;
  	*p++ = resp->status;
  
  	if (resp->status == nlm_lck_denied) {
  		struct file_lock	*fl = &resp->lock.fl;
  
  		*p++ = (fl->fl_type == F_RDLCK)? xdr_zero : xdr_one;
7bab377fc   Trond Myklebust   lockd: Don't expo...
153
  		*p++ = htonl(resp->lock.svid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
155
156
157
158
159
160
161
162
163
164
165
166
  
  		/* Encode owner handle. */
  		if (!(p = xdr_encode_netobj(p, &resp->lock.oh)))
  			return NULL;
  
  		start = loff_t_to_s64(fl->fl_start);
  		if (fl->fl_end == OFFSET_MAX)
  			len = 0;
  		else
  			len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1);
  		
  		p = xdr_encode_hyper(p, start);
  		p = xdr_encode_hyper(p, len);
7bab377fc   Trond Myklebust   lockd: Don't expo...
167
168
169
  		dprintk("xdr: encode_testres (status %u pid %d type %d start %Ld end %Ld)
  ",
  			resp->status, (int)resp->lock.svid, fl->fl_type,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
171
172
173
174
175
176
177
178
179
180
181
182
  			(long long)fl->fl_start,  (long long)fl->fl_end);
  	}
  
  	dprintk("xdr: after encode_testres (p %p resp %p)
  ", p, resp);
  	return p;
  }
  
  
  /*
   * First, the server side XDR functions
   */
  int
52921e02a   Al Viro   [PATCH] lockd end...
183
  nlm4svc_decode_testargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
  {
  	u32	exclusive;
  
  	if (!(p = nlm4_decode_cookie(p, &argp->cookie)))
  		return 0;
  
  	exclusive = ntohl(*p++);
  	if (!(p = nlm4_decode_lock(p, &argp->lock)))
  		return 0;
  	if (exclusive)
  		argp->lock.fl.fl_type = F_WRLCK;
  
  	return xdr_argsize_check(rqstp, p);
  }
  
  int
52921e02a   Al Viro   [PATCH] lockd end...
200
  nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
202
203
204
205
206
207
  {
  	if (!(p = nlm4_encode_testres(p, resp)))
  		return 0;
  	return xdr_ressize_check(rqstp, p);
  }
  
  int
52921e02a   Al Viro   [PATCH] lockd end...
208
  nlm4svc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
  {
  	u32	exclusive;
  
  	if (!(p = nlm4_decode_cookie(p, &argp->cookie)))
  		return 0;
  	argp->block  = ntohl(*p++);
  	exclusive    = ntohl(*p++);
  	if (!(p = nlm4_decode_lock(p, &argp->lock)))
  		return 0;
  	if (exclusive)
  		argp->lock.fl.fl_type = F_WRLCK;
  	argp->reclaim = ntohl(*p++);
  	argp->state   = ntohl(*p++);
  	argp->monitor = 1;		/* monitor client by default */
  
  	return xdr_argsize_check(rqstp, p);
  }
  
  int
52921e02a   Al Viro   [PATCH] lockd end...
228
  nlm4svc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
  {
  	u32	exclusive;
  
  	if (!(p = nlm4_decode_cookie(p, &argp->cookie)))
  		return 0;
  	argp->block = ntohl(*p++);
  	exclusive = ntohl(*p++);
  	if (!(p = nlm4_decode_lock(p, &argp->lock)))
  		return 0;
  	if (exclusive)
  		argp->lock.fl.fl_type = F_WRLCK;
  	return xdr_argsize_check(rqstp, p);
  }
  
  int
52921e02a   Al Viro   [PATCH] lockd end...
244
  nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
246
247
248
249
250
251
252
253
  {
  	if (!(p = nlm4_decode_cookie(p, &argp->cookie))
  	 || !(p = nlm4_decode_lock(p, &argp->lock)))
  		return 0;
  	argp->lock.fl.fl_type = F_UNLCK;
  	return xdr_argsize_check(rqstp, p);
  }
  
  int
52921e02a   Al Viro   [PATCH] lockd end...
254
  nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
256
257
258
259
  {
  	struct nlm_lock	*lock = &argp->lock;
  
  	memset(lock, 0, sizeof(*lock));
  	locks_init_lock(&lock->fl);
7bab377fc   Trond Myklebust   lockd: Don't expo...
260
261
  	lock->svid = ~(u32) 0;
  	lock->fl.fl_pid = (pid_t)lock->svid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
263
264
265
266
267
268
269
270
271
272
273
274
  
  	if (!(p = nlm4_decode_cookie(p, &argp->cookie))
  	 || !(p = xdr_decode_string_inplace(p, &lock->caller,
  					    &lock->len, NLM_MAXSTRLEN))
  	 || !(p = nlm4_decode_fh(p, &lock->fh))
  	 || !(p = nlm4_decode_oh(p, &lock->oh)))
  		return 0;
  	argp->fsm_mode = ntohl(*p++);
  	argp->fsm_access = ntohl(*p++);
  	return xdr_argsize_check(rqstp, p);
  }
  
  int
52921e02a   Al Viro   [PATCH] lockd end...
275
  nlm4svc_encode_shareres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
277
278
279
280
281
282
283
284
  {
  	if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
  		return 0;
  	*p++ = resp->status;
  	*p++ = xdr_zero;		/* sequence argument */
  	return xdr_ressize_check(rqstp, p);
  }
  
  int
52921e02a   Al Viro   [PATCH] lockd end...
285
  nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286
287
288
289
290
291
292
293
  {
  	if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
  		return 0;
  	*p++ = resp->status;
  	return xdr_ressize_check(rqstp, p);
  }
  
  int
52921e02a   Al Viro   [PATCH] lockd end...
294
  nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p, struct nlm_args *argp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
296
297
298
299
300
301
302
303
304
305
  {
  	struct nlm_lock	*lock = &argp->lock;
  
  	if (!(p = xdr_decode_string_inplace(p, &lock->caller,
  					    &lock->len, NLM_MAXSTRLEN)))
  		return 0;
  	argp->state = ntohl(*p++);
  	return xdr_argsize_check(rqstp, p);
  }
  
  int
52921e02a   Al Viro   [PATCH] lockd end...
306
  nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p, struct nlm_reboot *argp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
308
309
310
  {
  	if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN)))
  		return 0;
  	argp->state = ntohl(*p++);
576df4634   Chuck Lever   NLM: Decode "priv...
311
312
  	memcpy(&argp->priv.data, p, sizeof(argp->priv.data));
  	p += XDR_QUADLEN(SM_PRIV_SIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313
314
315
316
  	return xdr_argsize_check(rqstp, p);
  }
  
  int
52921e02a   Al Viro   [PATCH] lockd end...
317
  nlm4svc_decode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
319
320
  {
  	if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
  		return 0;
e8c5c045d   Al Viro   [PATCH] lockd end...
321
  	resp->status = *p++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
323
324
325
  	return xdr_argsize_check(rqstp, p);
  }
  
  int
52921e02a   Al Viro   [PATCH] lockd end...
326
  nlm4svc_decode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
328
329
330
331
  {
  	return xdr_argsize_check(rqstp, p);
  }
  
  int
52921e02a   Al Viro   [PATCH] lockd end...
332
  nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333
334
335
  {
  	return xdr_ressize_check(rqstp, p);
  }