Blame view

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