Blame view

fs/nfs/proc.c 18.8 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  /*
   *  linux/fs/nfs/proc.c
   *
   *  Copyright (C) 1992, 1993, 1994  Rick Sladkey
   *
   *  OS-independent nfs remote procedure call functions
   *
   *  Tuned by Alan Cox <A.Cox@swansea.ac.uk> for >3K buffers
   *  so at last we can have decent(ish) throughput off a 
   *  Sun server.
   *
   *  Coding optimized and cleaned up by Florian La Roche.
   *  Note: Error returns are optimized for NFS_OK, which isn't translated via
   *  nfs_stat_to_errno(), but happens to be already the right return code.
   *
   *  Also, the code currently doesn't check the size of the packet, when
   *  it decodes the packet.
   *
   *  Feel free to fix it and mail me the diffs if it worries you.
   *
   *  Completely rewritten to support the new RPC call interface;
   *  rewrote and moved the entire XDR stuff to xdr.c
   *  --Olaf Kirch June 1996
   *
   *  The code below initializes all auto variables explicitly, otherwise
   *  it will fail to work as a module (gcc generates a memset call for an
   *  incomplete struct).
   */
  
  #include <linux/types.h>
  #include <linux/param.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
  #include <linux/time.h>
  #include <linux/mm.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
37
38
39
40
41
42
43
  #include <linux/errno.h>
  #include <linux/string.h>
  #include <linux/in.h>
  #include <linux/pagemap.h>
  #include <linux/sunrpc/clnt.h>
  #include <linux/nfs.h>
  #include <linux/nfs2.h>
  #include <linux/nfs_fs.h>
  #include <linux/nfs_page.h>
  #include <linux/lockd/bind.h>
d310310cb   Jeff Layton   Freezer / sunrpc ...
44
  #include <linux/freezer.h>
f7b422b17   David Howells   NFS: Split fs/nfs...
45
  #include "internal.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
  
  #define NFSDBG_FACILITY		NFSDBG_PROC
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
50
51
52
53
54
55
56
  /*
   * Bare-bones access to getattr: this is for nfs_read_super.
   */
  static int
  nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
  		  struct nfs_fsinfo *info)
  {
  	struct nfs_fattr *fattr = info->fattr;
  	struct nfs2_fsstat fsinfo;
dead28da8   Chuck Lever   SUNRPC: eliminate...
57
58
59
60
61
  	struct rpc_message msg = {
  		.rpc_proc	= &nfs_procedures[NFSPROC_GETATTR],
  		.rpc_argp	= fhandle,
  		.rpc_resp	= fattr,
  	};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
  	int status;
3110ff804   Harvey Harrison   nfs: replace rema...
63
64
  	dprintk("%s: call getattr
  ", __func__);
0e574af1b   Trond Myklebust   NFS: Cleanup init...
65
  	nfs_fattr_init(fattr);
37ca8f5c6   EG Keizer   nfs: authenticate...
66
67
68
69
  	status = rpc_call_sync(server->client, &msg, 0);
  	/* Retry with default authentication if different */
  	if (status && server->nfs_client->cl_rpcclient != server->client)
  		status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0);
3110ff804   Harvey Harrison   nfs: replace rema...
70
71
  	dprintk("%s: reply getattr: %d
  ", __func__, status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
  	if (status)
  		return status;
3110ff804   Harvey Harrison   nfs: replace rema...
74
75
  	dprintk("%s: call statfs
  ", __func__);
dead28da8   Chuck Lever   SUNRPC: eliminate...
76
77
  	msg.rpc_proc = &nfs_procedures[NFSPROC_STATFS];
  	msg.rpc_resp = &fsinfo;
37ca8f5c6   EG Keizer   nfs: authenticate...
78
79
80
81
  	status = rpc_call_sync(server->client, &msg, 0);
  	/* Retry with default authentication if different */
  	if (status && server->nfs_client->cl_rpcclient != server->client)
  		status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0);
3110ff804   Harvey Harrison   nfs: replace rema...
82
83
  	dprintk("%s: reply statfs: %d
  ", __func__, status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
  	if (status)
  		return status;
  	info->rtmax  = NFS_MAXDATA;
  	info->rtpref = fsinfo.tsize;
  	info->rtmult = fsinfo.bsize;
  	info->wtmax  = NFS_MAXDATA;
  	info->wtpref = fsinfo.tsize;
  	info->wtmult = fsinfo.bsize;
  	info->dtpref = fsinfo.tsize;
  	info->maxfilesize = 0x7FFFFFFF;
  	info->lease_time = 0;
  	return 0;
  }
  
  /*
   * One function for each procedure in the NFS protocol.
   */
  static int
  nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
1775fd3e8   David Quigley   NFS:Add labels to...
103
  		struct nfs_fattr *fattr, struct nfs4_label *label)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
  {
dead28da8   Chuck Lever   SUNRPC: eliminate...
105
106
107
108
109
  	struct rpc_message msg = {
  		.rpc_proc	= &nfs_procedures[NFSPROC_GETATTR],
  		.rpc_argp	= fhandle,
  		.rpc_resp	= fattr,
  	};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
111
112
113
  	int	status;
  
  	dprintk("NFS call  getattr
  ");
0e574af1b   Trond Myklebust   NFS: Cleanup init...
114
  	nfs_fattr_init(fattr);
dead28da8   Chuck Lever   SUNRPC: eliminate...
115
  	status = rpc_call_sync(server->client, &msg, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
117
118
119
120
121
122
123
124
  	dprintk("NFS reply getattr: %d
  ", status);
  	return status;
  }
  
  static int
  nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
  		 struct iattr *sattr)
  {
2b0143b5c   David Howells   VFS: normal files...
125
  	struct inode *inode = d_inode(dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
128
129
  	struct nfs_sattrargs	arg = { 
  		.fh	= NFS_FH(inode),
  		.sattr	= sattr
  	};
dead28da8   Chuck Lever   SUNRPC: eliminate...
130
131
132
133
134
  	struct rpc_message msg = {
  		.rpc_proc	= &nfs_procedures[NFSPROC_SETATTR],
  		.rpc_argp	= &arg,
  		.rpc_resp	= fattr,
  	};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135
  	int	status;
cf3fff54a   Trond Myklebust   NFS: Send valid m...
136
137
  	/* Mask out the non-modebit related stuff from attr->ia_mode */
  	sattr->ia_mode &= S_IALLUGO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
139
  	dprintk("NFS call  setattr
  ");
659bfcd6d   Trond Myklebust   NFS: Fix the ftru...
140
141
  	if (sattr->ia_valid & ATTR_FILE)
  		msg.rpc_cred = nfs_file_cred(sattr->ia_file);
0e574af1b   Trond Myklebust   NFS: Cleanup init...
142
  	nfs_fattr_init(fattr);
dead28da8   Chuck Lever   SUNRPC: eliminate...
143
  	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
65e4308d2   Trond Myklebust   [PATCH] NFS: Ensu...
144
  	if (status == 0)
f044636d9   Trond Myklebust   NFS: Add attribut...
145
  		nfs_setattr_update_inode(inode, sattr, fattr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
147
148
149
150
151
  	dprintk("NFS reply setattr: %d
  ", status);
  	return status;
  }
  
  static int
beffb8feb   Al Viro   qstr: constify in...
152
  nfs_proc_lookup(struct inode *dir, const struct qstr *name,
1775fd3e8   David Quigley   NFS:Add labels to...
153
154
  		struct nfs_fh *fhandle, struct nfs_fattr *fattr,
  		struct nfs4_label *label)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155
156
157
158
159
160
161
162
163
164
  {
  	struct nfs_diropargs	arg = {
  		.fh		= NFS_FH(dir),
  		.name		= name->name,
  		.len		= name->len
  	};
  	struct nfs_diropok	res = {
  		.fh		= fhandle,
  		.fattr		= fattr
  	};
dead28da8   Chuck Lever   SUNRPC: eliminate...
165
166
167
168
169
  	struct rpc_message msg = {
  		.rpc_proc	= &nfs_procedures[NFSPROC_LOOKUP],
  		.rpc_argp	= &arg,
  		.rpc_resp	= &res,
  	};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
171
172
173
  	int			status;
  
  	dprintk("NFS call  lookup %s
  ", name->name);
0e574af1b   Trond Myklebust   NFS: Cleanup init...
174
  	nfs_fattr_init(fattr);
dead28da8   Chuck Lever   SUNRPC: eliminate...
175
  	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
177
178
179
180
181
182
183
184
185
186
187
188
189
  	dprintk("NFS reply lookup: %d
  ", status);
  	return status;
  }
  
  static int nfs_proc_readlink(struct inode *inode, struct page *page,
  		unsigned int pgbase, unsigned int pglen)
  {
  	struct nfs_readlinkargs	args = {
  		.fh		= NFS_FH(inode),
  		.pgbase		= pgbase,
  		.pglen		= pglen,
  		.pages		= &page
  	};
dead28da8   Chuck Lever   SUNRPC: eliminate...
190
191
192
193
  	struct rpc_message msg = {
  		.rpc_proc	= &nfs_procedures[NFSPROC_READLINK],
  		.rpc_argp	= &args,
  	};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
195
196
197
  	int			status;
  
  	dprintk("NFS call  readlink
  ");
dead28da8   Chuck Lever   SUNRPC: eliminate...
198
  	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
201
202
  	dprintk("NFS reply readlink: %d
  ", status);
  	return status;
  }
eb872f0c8   Trond Myklebust   NFS: Reduce the s...
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
  struct nfs_createdata {
  	struct nfs_createargs arg;
  	struct nfs_diropok res;
  	struct nfs_fh fhandle;
  	struct nfs_fattr fattr;
  };
  
  static struct nfs_createdata *nfs_alloc_createdata(struct inode *dir,
  		struct dentry *dentry, struct iattr *sattr)
  {
  	struct nfs_createdata *data;
  
  	data = kmalloc(sizeof(*data), GFP_KERNEL);
  
  	if (data != NULL) {
  		data->arg.fh = NFS_FH(dir);
  		data->arg.name = dentry->d_name.name;
  		data->arg.len = dentry->d_name.len;
  		data->arg.sattr = sattr;
  		nfs_fattr_init(&data->fattr);
  		data->fhandle.size = 0;
  		data->res.fh = &data->fhandle;
  		data->res.fattr = &data->fattr;
  	}
  	return data;
  };
  
  static void nfs_free_createdata(const struct nfs_createdata *data)
  {
  	kfree(data);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
235
  static int
  nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
8867fe589   Miklos Szeredi   nfs: clean up ->c...
236
  		int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
  {
eb872f0c8   Trond Myklebust   NFS: Reduce the s...
238
  	struct nfs_createdata *data;
dead28da8   Chuck Lever   SUNRPC: eliminate...
239
240
  	struct rpc_message msg = {
  		.rpc_proc	= &nfs_procedures[NFSPROC_CREATE],
dead28da8   Chuck Lever   SUNRPC: eliminate...
241
  	};
eb872f0c8   Trond Myklebust   NFS: Reduce the s...
242
  	int status = -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243

6de1472f1   Al Viro   nfs: use %p[dD] i...
244
245
  	dprintk("NFS call  create %pd
  ", dentry);
eb872f0c8   Trond Myklebust   NFS: Reduce the s...
246
247
248
249
250
  	data = nfs_alloc_createdata(dir, dentry, sattr);
  	if (data == NULL)
  		goto out;
  	msg.rpc_argp = &data->arg;
  	msg.rpc_resp = &data->res;
dead28da8   Chuck Lever   SUNRPC: eliminate...
251
  	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
bad2a5241   Trond Myklebust   NFSv2: Ensure tha...
252
  	nfs_mark_for_revalidate(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
  	if (status == 0)
1775fd3e8   David Quigley   NFS:Add labels to...
254
  		status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, NULL);
eb872f0c8   Trond Myklebust   NFS: Reduce the s...
255
256
  	nfs_free_createdata(data);
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
258
259
260
261
262
263
264
265
266
267
268
  	dprintk("NFS reply create: %d
  ", status);
  	return status;
  }
  
  /*
   * In NFSv2, mknod is grafted onto the create call.
   */
  static int
  nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
  	       dev_t rdev)
  {
eb872f0c8   Trond Myklebust   NFS: Reduce the s...
269
  	struct nfs_createdata *data;
dead28da8   Chuck Lever   SUNRPC: eliminate...
270
271
  	struct rpc_message msg = {
  		.rpc_proc	= &nfs_procedures[NFSPROC_CREATE],
dead28da8   Chuck Lever   SUNRPC: eliminate...
272
  	};
eb872f0c8   Trond Myklebust   NFS: Reduce the s...
273
274
  	umode_t mode;
  	int status = -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275

6de1472f1   Al Viro   nfs: use %p[dD] i...
276
277
  	dprintk("NFS call  mknod %pd
  ", dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278
279
280
281
282
283
284
285
286
  
  	mode = sattr->ia_mode;
  	if (S_ISFIFO(mode)) {
  		sattr->ia_mode = (mode & ~S_IFMT) | S_IFCHR;
  		sattr->ia_valid &= ~ATTR_SIZE;
  	} else if (S_ISCHR(mode) || S_ISBLK(mode)) {
  		sattr->ia_valid |= ATTR_SIZE;
  		sattr->ia_size = new_encode_dev(rdev);/* get out your barf bag */
  	}
eb872f0c8   Trond Myklebust   NFS: Reduce the s...
287
288
289
290
291
  	data = nfs_alloc_createdata(dir, dentry, sattr);
  	if (data == NULL)
  		goto out;
  	msg.rpc_argp = &data->arg;
  	msg.rpc_resp = &data->res;
dead28da8   Chuck Lever   SUNRPC: eliminate...
292
  	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
decf491f3   Trond Myklebust   NFS: Don't let nf...
293
  	nfs_mark_for_revalidate(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
294
295
296
  
  	if (status == -EINVAL && S_ISFIFO(mode)) {
  		sattr->ia_mode = mode;
eb872f0c8   Trond Myklebust   NFS: Reduce the s...
297
  		nfs_fattr_init(data->res.fattr);
dead28da8   Chuck Lever   SUNRPC: eliminate...
298
  		status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
300
  	}
  	if (status == 0)
1775fd3e8   David Quigley   NFS:Add labels to...
301
  		status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, NULL);
eb872f0c8   Trond Myklebust   NFS: Reduce the s...
302
303
  	nfs_free_createdata(data);
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
305
306
307
308
309
  	dprintk("NFS reply mknod: %d
  ", status);
  	return status;
  }
    
  static int
beffb8feb   Al Viro   qstr: constify in...
310
  nfs_proc_remove(struct inode *dir, const struct qstr *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311
  {
4fdc17b2a   Trond Myklebust   NFS: Introduce st...
312
313
  	struct nfs_removeargs arg = {
  		.fh = NFS_FH(dir),
26fe57502   Linus Torvalds   vfs: make it poss...
314
  		.name = *name,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
  	};
4fdc17b2a   Trond Myklebust   NFS: Introduce st...
316
317
318
  	struct rpc_message msg = { 
  		.rpc_proc = &nfs_procedures[NFSPROC_REMOVE],
  		.rpc_argp = &arg,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
319
320
321
322
323
324
  	};
  	int			status;
  
  	dprintk("NFS call  remove %s
  ", name->name);
  	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
decf491f3   Trond Myklebust   NFS: Don't let nf...
325
  	nfs_mark_for_revalidate(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
326
327
328
329
330
  
  	dprintk("NFS reply remove: %d
  ", status);
  	return status;
  }
e4eff1a62   Trond Myklebust   SUNRPC: Clean up ...
331
332
  static void
  nfs_proc_unlink_setup(struct rpc_message *msg, struct inode *dir)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
  	msg->rpc_proc = &nfs_procedures[NFSPROC_REMOVE];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
  }
34e137cc7   Bryan Schumaker   NFS: Remove nfs4_...
336
337
338
339
  static void nfs_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data)
  {
  	rpc_call_start(task);
  }
e4eff1a62   Trond Myklebust   SUNRPC: Clean up ...
340
  static int nfs_proc_unlink_done(struct rpc_task *task, struct inode *dir)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
  {
e4eff1a62   Trond Myklebust   SUNRPC: Clean up ...
342
343
  	nfs_mark_for_revalidate(dir);
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344
  }
d3d4152a5   Jeff Layton   nfs: make sillyre...
345
346
347
348
349
  static void
  nfs_proc_rename_setup(struct rpc_message *msg, struct inode *dir)
  {
  	msg->rpc_proc = &nfs_procedures[NFSPROC_RENAME];
  }
c6bfa1a16   Bryan Schumaker   NFS: Remove nfs4_...
350
351
352
353
  static void nfs_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renamedata *data)
  {
  	rpc_call_start(task);
  }
d3d4152a5   Jeff Layton   nfs: make sillyre...
354
355
356
357
  static int
  nfs_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
  		     struct inode *new_dir)
  {
d3d4152a5   Jeff Layton   nfs: make sillyre...
358
359
360
361
  	nfs_mark_for_revalidate(old_dir);
  	nfs_mark_for_revalidate(new_dir);
  	return 1;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
  static int
beffb8feb   Al Viro   qstr: constify in...
363
  nfs_proc_link(struct inode *inode, struct inode *dir, const struct qstr *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
364
365
366
367
368
369
370
  {
  	struct nfs_linkargs	arg = {
  		.fromfh		= NFS_FH(inode),
  		.tofh		= NFS_FH(dir),
  		.toname		= name->name,
  		.tolen		= name->len
  	};
dead28da8   Chuck Lever   SUNRPC: eliminate...
371
372
373
374
  	struct rpc_message msg = {
  		.rpc_proc	= &nfs_procedures[NFSPROC_LINK],
  		.rpc_argp	= &arg,
  	};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
376
377
378
  	int			status;
  
  	dprintk("NFS call  link %s
  ", name->name);
dead28da8   Chuck Lever   SUNRPC: eliminate...
379
  	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
5ba7cc480   Trond Myklebust   NFS: Fix post-op ...
380
  	nfs_mark_for_revalidate(inode);
decf491f3   Trond Myklebust   NFS: Don't let nf...
381
  	nfs_mark_for_revalidate(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382
383
384
385
386
387
  	dprintk("NFS reply link: %d
  ", status);
  	return status;
  }
  
  static int
94a6d7532   Chuck Lever   NFS: Use cached p...
388
389
  nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
  		 unsigned int len, struct iattr *sattr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
390
  {
23a306120   Trond Myklebust   NFS: Reduce the s...
391
392
  	struct nfs_fh *fh;
  	struct nfs_fattr *fattr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
394
  	struct nfs_symlinkargs	arg = {
  		.fromfh		= NFS_FH(dir),
4f390c152   Chuck Lever   NFS: Fix double d...
395
396
  		.fromname	= dentry->d_name.name,
  		.fromlen	= dentry->d_name.len,
94a6d7532   Chuck Lever   NFS: Use cached p...
397
398
  		.pages		= &page,
  		.pathlen	= len,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
399
400
  		.sattr		= sattr
  	};
dead28da8   Chuck Lever   SUNRPC: eliminate...
401
402
403
404
  	struct rpc_message msg = {
  		.rpc_proc	= &nfs_procedures[NFSPROC_SYMLINK],
  		.rpc_argp	= &arg,
  	};
23a306120   Trond Myklebust   NFS: Reduce the s...
405
  	int status = -ENAMETOOLONG;
6de1472f1   Al Viro   nfs: use %p[dD] i...
406
407
  	dprintk("NFS call  symlink %pd
  ", dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
408

94a6d7532   Chuck Lever   NFS: Use cached p...
409
  	if (len > NFS2_MAXPATHLEN)
23a306120   Trond Myklebust   NFS: Reduce the s...
410
  		goto out;
4f390c152   Chuck Lever   NFS: Fix double d...
411

23a306120   Trond Myklebust   NFS: Reduce the s...
412
413
414
415
  	fh = nfs_alloc_fhandle();
  	fattr = nfs_alloc_fattr();
  	status = -ENOMEM;
  	if (fh == NULL || fattr == NULL)
878215feb   Jesper Juhl   NFS: Don't leak i...
416
  		goto out_free;
94a6d7532   Chuck Lever   NFS: Use cached p...
417

dead28da8   Chuck Lever   SUNRPC: eliminate...
418
  	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
decf491f3   Trond Myklebust   NFS: Don't let nf...
419
  	nfs_mark_for_revalidate(dir);
4f390c152   Chuck Lever   NFS: Fix double d...
420
421
422
423
424
425
  
  	/*
  	 * V2 SYMLINK requests don't return any attributes.  Setting the
  	 * filehandle size to zero indicates to nfs_instantiate that it
  	 * should fill in the data with a LOOKUP call on the wire.
  	 */
23a306120   Trond Myklebust   NFS: Reduce the s...
426
  	if (status == 0)
1775fd3e8   David Quigley   NFS:Add labels to...
427
  		status = nfs_instantiate(dentry, fh, fattr, NULL);
4f390c152   Chuck Lever   NFS: Fix double d...
428

878215feb   Jesper Juhl   NFS: Don't leak i...
429
  out_free:
23a306120   Trond Myklebust   NFS: Reduce the s...
430
431
432
  	nfs_free_fattr(fattr);
  	nfs_free_fhandle(fh);
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
434
435
436
437
438
439
440
  	dprintk("NFS reply symlink: %d
  ", status);
  	return status;
  }
  
  static int
  nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
  {
eb872f0c8   Trond Myklebust   NFS: Reduce the s...
441
  	struct nfs_createdata *data;
dead28da8   Chuck Lever   SUNRPC: eliminate...
442
443
  	struct rpc_message msg = {
  		.rpc_proc	= &nfs_procedures[NFSPROC_MKDIR],
dead28da8   Chuck Lever   SUNRPC: eliminate...
444
  	};
eb872f0c8   Trond Myklebust   NFS: Reduce the s...
445
  	int status = -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446

6de1472f1   Al Viro   nfs: use %p[dD] i...
447
448
  	dprintk("NFS call  mkdir %pd
  ", dentry);
eb872f0c8   Trond Myklebust   NFS: Reduce the s...
449
450
451
452
453
  	data = nfs_alloc_createdata(dir, dentry, sattr);
  	if (data == NULL)
  		goto out;
  	msg.rpc_argp = &data->arg;
  	msg.rpc_resp = &data->res;
dead28da8   Chuck Lever   SUNRPC: eliminate...
454
  	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
decf491f3   Trond Myklebust   NFS: Don't let nf...
455
  	nfs_mark_for_revalidate(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
456
  	if (status == 0)
1775fd3e8   David Quigley   NFS:Add labels to...
457
  		status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, NULL);
eb872f0c8   Trond Myklebust   NFS: Reduce the s...
458
459
  	nfs_free_createdata(data);
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
460
461
462
463
464
465
  	dprintk("NFS reply mkdir: %d
  ", status);
  	return status;
  }
  
  static int
beffb8feb   Al Viro   qstr: constify in...
466
  nfs_proc_rmdir(struct inode *dir, const struct qstr *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
467
468
469
470
471
472
  {
  	struct nfs_diropargs	arg = {
  		.fh		= NFS_FH(dir),
  		.name		= name->name,
  		.len		= name->len
  	};
dead28da8   Chuck Lever   SUNRPC: eliminate...
473
474
475
476
  	struct rpc_message msg = {
  		.rpc_proc	= &nfs_procedures[NFSPROC_RMDIR],
  		.rpc_argp	= &arg,
  	};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477
478
479
480
  	int			status;
  
  	dprintk("NFS call  rmdir %s
  ", name->name);
dead28da8   Chuck Lever   SUNRPC: eliminate...
481
  	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
decf491f3   Trond Myklebust   NFS: Don't let nf...
482
  	nfs_mark_for_revalidate(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
483
484
485
486
487
488
489
490
491
492
493
494
495
496
  	dprintk("NFS reply rmdir: %d
  ", status);
  	return status;
  }
  
  /*
   * The READDIR implementation is somewhat hackish - we pass a temporary
   * buffer to the encode function, which installs it in the receive
   * the receive iovec. The decode function just parses the reply to make
   * sure it is syntactically correct; the entries itself are decoded
   * from nfs_readdir by calling the decode_entry function directly.
   */
  static int
  nfs_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
56e4ebf87   Bryan Schumaker   NFS: readdir with...
497
  		 u64 cookie, struct page **pages, unsigned int count, int plus)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
498
  {
2b0143b5c   David Howells   VFS: normal files...
499
  	struct inode		*dir = d_inode(dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
501
502
503
  	struct nfs_readdirargs	arg = {
  		.fh		= NFS_FH(dir),
  		.cookie		= cookie,
  		.count		= count,
56e4ebf87   Bryan Schumaker   NFS: readdir with...
504
  		.pages		= pages,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
505
506
507
508
  	};
  	struct rpc_message	msg = {
  		.rpc_proc	= &nfs_procedures[NFSPROC_READDIR],
  		.rpc_argp	= &arg,
dead28da8   Chuck Lever   SUNRPC: eliminate...
509
  		.rpc_cred	= cred,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
510
511
  	};
  	int			status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
512
513
514
  	dprintk("NFS call  readdir %d
  ", (unsigned int)cookie);
  	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
c48129983   Trond Myklebust   NFS: Fix atime re...
515
  	nfs_invalidate_atime(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
517
  	dprintk("NFS reply readdir: %d
  ", status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518
519
520
521
522
523
524
525
  	return status;
  }
  
  static int
  nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
  			struct nfs_fsstat *stat)
  {
  	struct nfs2_fsstat fsinfo;
dead28da8   Chuck Lever   SUNRPC: eliminate...
526
527
528
529
530
  	struct rpc_message msg = {
  		.rpc_proc	= &nfs_procedures[NFSPROC_STATFS],
  		.rpc_argp	= fhandle,
  		.rpc_resp	= &fsinfo,
  	};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531
532
533
534
  	int	status;
  
  	dprintk("NFS call  statfs
  ");
0e574af1b   Trond Myklebust   NFS: Cleanup init...
535
  	nfs_fattr_init(stat->fattr);
dead28da8   Chuck Lever   SUNRPC: eliminate...
536
  	status = rpc_call_sync(server->client, &msg, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
  	dprintk("NFS reply statfs: %d
  ", status);
  	if (status)
  		goto out;
  	stat->tbytes = (u64)fsinfo.blocks * fsinfo.bsize;
  	stat->fbytes = (u64)fsinfo.bfree  * fsinfo.bsize;
  	stat->abytes = (u64)fsinfo.bavail * fsinfo.bsize;
  	stat->tfiles = 0;
  	stat->ffiles = 0;
  	stat->afiles = 0;
  out:
  	return status;
  }
  
  static int
  nfs_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
  			struct nfs_fsinfo *info)
  {
  	struct nfs2_fsstat fsinfo;
dead28da8   Chuck Lever   SUNRPC: eliminate...
556
557
558
559
560
  	struct rpc_message msg = {
  		.rpc_proc	= &nfs_procedures[NFSPROC_STATFS],
  		.rpc_argp	= fhandle,
  		.rpc_resp	= &fsinfo,
  	};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
561
562
563
564
  	int	status;
  
  	dprintk("NFS call  fsinfo
  ");
0e574af1b   Trond Myklebust   NFS: Cleanup init...
565
  	nfs_fattr_init(info->fattr);
dead28da8   Chuck Lever   SUNRPC: eliminate...
566
  	status = rpc_call_sync(server->client, &msg, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
  	dprintk("NFS reply fsinfo: %d
  ", status);
  	if (status)
  		goto out;
  	info->rtmax  = NFS_MAXDATA;
  	info->rtpref = fsinfo.tsize;
  	info->rtmult = fsinfo.bsize;
  	info->wtmax  = NFS_MAXDATA;
  	info->wtpref = fsinfo.tsize;
  	info->wtmult = fsinfo.bsize;
  	info->dtpref = fsinfo.tsize;
  	info->maxfilesize = 0x7FFFFFFF;
  	info->lease_time = 0;
  out:
  	return status;
  }
  
  static int
  nfs_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
  		  struct nfs_pathconf *info)
  {
  	info->max_link = 0;
  	info->max_namelen = NFS2_MAXNAMLEN;
  	return 0;
  }
d45f60c67   Weston Andros Adamson   nfs: merge nfs_pg...
592
  static int nfs_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
593
  {
d45f60c67   Weston Andros Adamson   nfs: merge nfs_pg...
594
  	struct inode *inode = hdr->inode;
cd841605f   Fred Isaman   NFS: create commo...
595

cd841605f   Fred Isaman   NFS: create commo...
596
  	nfs_invalidate_atime(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
597
  	if (task->tk_status >= 0) {
d45f60c67   Weston Andros Adamson   nfs: merge nfs_pg...
598
  		nfs_refresh_inode(inode, hdr->res.fattr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
599
600
601
  		/* Emulate the eof flag, which isn't normally needed in NFSv2
  		 * as it is guaranteed to always return the file attributes
  		 */
d45f60c67   Weston Andros Adamson   nfs: merge nfs_pg...
602
603
  		if (hdr->args.offset + hdr->res.count >= hdr->res.fattr->size)
  			hdr->res.eof = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
604
  	}
ec06c096e   Trond Myklebust   NFS: Cleanup of N...
605
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
606
  }
d45f60c67   Weston Andros Adamson   nfs: merge nfs_pg...
607
608
  static void nfs_proc_read_setup(struct nfs_pgio_header *hdr,
  				struct rpc_message *msg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
609
  {
bdc7f021f   Trond Myklebust   NFS: Clean up the...
610
  	msg->rpc_proc = &nfs_procedures[NFSPROC_READ];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
611
  }
d45f60c67   Weston Andros Adamson   nfs: merge nfs_pg...
612
613
  static int nfs_proc_pgio_rpc_prepare(struct rpc_task *task,
  				     struct nfs_pgio_header *hdr)
ea7c33036   Bryan Schumaker   NFS: Remove nfs4_...
614
615
  {
  	rpc_call_start(task);
ef1820f9b   NeilBrown   NFSv4: Don't try ...
616
  	return 0;
ea7c33036   Bryan Schumaker   NFS: Remove nfs4_...
617
  }
d45f60c67   Weston Andros Adamson   nfs: merge nfs_pg...
618
  static int nfs_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
619
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
620
  	if (task->tk_status >= 0)
a08a8cd37   Trond Myklebust   NFS: Add attribut...
621
  		nfs_writeback_update_inode(hdr);
788e7a89a   Trond Myklebust   NFS: Cleanup of N...
622
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
623
  }
d45f60c67   Weston Andros Adamson   nfs: merge nfs_pg...
624
625
  static void nfs_proc_write_setup(struct nfs_pgio_header *hdr,
  				 struct rpc_message *msg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
626
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627
  	/* Note: NFSv2 ignores @stable and always uses NFS_FILE_SYNC */
d45f60c67   Weston Andros Adamson   nfs: merge nfs_pg...
628
  	hdr->args.stable = NFS_FILE_SYNC;
bdc7f021f   Trond Myklebust   NFS: Clean up the...
629
  	msg->rpc_proc = &nfs_procedures[NFSPROC_WRITE];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
630
  }
0b7c01533   Fred Isaman   NFS: add a struct...
631
632
633
634
  static void nfs_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data)
  {
  	BUG();
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
635
  static void
0b7c01533   Fred Isaman   NFS: add a struct...
636
  nfs_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
637
638
639
640
641
642
643
  {
  	BUG();
  }
  
  static int
  nfs_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
  {
496ad9aa8   Al Viro   new helper: file_...
644
  	struct inode *inode = file_inode(filp);
1093a60ef   Chuck Lever   NLM/NFS: Use cach...
645
646
  
  	return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
647
  }
2116271a3   Trond Myklebust   NFS: Add correct ...
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
  /* Helper functions for NFS lock bounds checking */
  #define NFS_LOCK32_OFFSET_MAX ((__s32)0x7fffffffUL)
  static int nfs_lock_check_bounds(const struct file_lock *fl)
  {
  	__s32 start, end;
  
  	start = (__s32)fl->fl_start;
  	if ((loff_t)start != fl->fl_start)
  		goto out_einval;
  
  	if (fl->fl_end != OFFSET_MAX) {
  		end = (__s32)fl->fl_end;
  		if ((loff_t)end != fl->fl_end)
  			goto out_einval;
  	} else
  		end = NFS_LOCK32_OFFSET_MAX;
  
  	if (start < 0 || start > end)
  		goto out_einval;
  	return 0;
  out_einval:
  	return -EINVAL;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
671

011e2a7fd   Bryan Schumaker   NFS: Create a hav...
672
673
674
675
  static int nfs_have_delegation(struct inode *inode, fmode_t flags)
  {
  	return 0;
  }
57ec14c55   Bryan Schumaker   NFS: Create a ret...
676
677
678
679
680
  static int nfs_return_delegation(struct inode *inode)
  {
  	nfs_wb_all(inode);
  	return 0;
  }
597d92891   Bryan Schumaker   NFS: Split out NF...
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
  static const struct inode_operations nfs_dir_inode_operations = {
  	.create		= nfs_create,
  	.lookup		= nfs_lookup,
  	.link		= nfs_link,
  	.unlink		= nfs_unlink,
  	.symlink	= nfs_symlink,
  	.mkdir		= nfs_mkdir,
  	.rmdir		= nfs_rmdir,
  	.mknod		= nfs_mknod,
  	.rename		= nfs_rename,
  	.permission	= nfs_permission,
  	.getattr	= nfs_getattr,
  	.setattr	= nfs_setattr,
  };
  
  static const struct inode_operations nfs_file_inode_operations = {
  	.permission	= nfs_permission,
  	.getattr	= nfs_getattr,
  	.setattr	= nfs_setattr,
  };
509de8111   David Howells   NFS: Add extra co...
701
  const struct nfs_rpc_ops nfs_v2_clientops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
702
703
704
  	.version	= 2,		       /* protocol version */
  	.dentry_ops	= &nfs_dentry_operations,
  	.dir_inode_ops	= &nfs_dir_inode_operations,
92cfc62cb   J. Bruce Fields   [PATCH] NFS: Allo...
705
  	.file_inode_ops	= &nfs_file_inode_operations,
1788ea6e3   Jeff Layton   nfs: when attempt...
706
  	.file_ops	= &nfs_file_operations,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
707
  	.getroot	= nfs_proc_get_root,
281cad46b   Bryan Schumaker   NFS: Create a sub...
708
  	.submount	= nfs_submount,
ff9099f26   Bryan Schumaker   NFS: Create a try...
709
  	.try_mount	= nfs_try_mount,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710
711
712
713
714
  	.getattr	= nfs_proc_getattr,
  	.setattr	= nfs_proc_setattr,
  	.lookup		= nfs_proc_lookup,
  	.access		= NULL,		       /* access */
  	.readlink	= nfs_proc_readlink,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
715
716
717
  	.create		= nfs_proc_create,
  	.remove		= nfs_proc_remove,
  	.unlink_setup	= nfs_proc_unlink_setup,
34e137cc7   Bryan Schumaker   NFS: Remove nfs4_...
718
  	.unlink_rpc_prepare = nfs_proc_unlink_rpc_prepare,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
719
  	.unlink_done	= nfs_proc_unlink_done,
d3d4152a5   Jeff Layton   nfs: make sillyre...
720
  	.rename_setup	= nfs_proc_rename_setup,
c6bfa1a16   Bryan Schumaker   NFS: Remove nfs4_...
721
  	.rename_rpc_prepare = nfs_proc_rename_rpc_prepare,
d3d4152a5   Jeff Layton   nfs: make sillyre...
722
  	.rename_done	= nfs_proc_rename_done,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
723
724
725
726
727
728
729
730
731
  	.link		= nfs_proc_link,
  	.symlink	= nfs_proc_symlink,
  	.mkdir		= nfs_proc_mkdir,
  	.rmdir		= nfs_proc_rmdir,
  	.readdir	= nfs_proc_readdir,
  	.mknod		= nfs_proc_mknod,
  	.statfs		= nfs_proc_statfs,
  	.fsinfo		= nfs_proc_fsinfo,
  	.pathconf	= nfs_proc_pathconf,
f796f8b3a   Chuck Lever   NFS: Introduce ne...
732
  	.decode_dirent	= nfs2_decode_dirent,
a4cdda591   Anna Schumaker   NFS: Create a com...
733
  	.pgio_rpc_prepare = nfs_proc_pgio_rpc_prepare,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
  	.read_setup	= nfs_proc_read_setup,
ec06c096e   Trond Myklebust   NFS: Cleanup of N...
735
  	.read_done	= nfs_read_done,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
736
  	.write_setup	= nfs_proc_write_setup,
788e7a89a   Trond Myklebust   NFS: Cleanup of N...
737
  	.write_done	= nfs_write_done,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
738
  	.commit_setup	= nfs_proc_commit_setup,
0b7c01533   Fred Isaman   NFS: add a struct...
739
  	.commit_rpc_prepare = nfs_proc_commit_rpc_prepare,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
740
  	.lock		= nfs_proc_lock,
2116271a3   Trond Myklebust   NFS: Add correct ...
741
  	.lock_check_bounds = nfs_lock_check_bounds,
7fe5c398f   Trond Myklebust   NFS: Optimise NFS...
742
  	.close_context	= nfs_close_context,
011e2a7fd   Bryan Schumaker   NFS: Create a hav...
743
  	.have_delegation = nfs_have_delegation,
57ec14c55   Bryan Schumaker   NFS: Create a ret...
744
  	.return_delegation = nfs_return_delegation,
6663ee7f8   Bryan Schumaker   NFS: Create an al...
745
  	.alloc_client	= nfs_alloc_client,
45a52a020   Andy Adamson   NFS move nfs_clie...
746
  	.init_client	= nfs_init_client,
cdb7ecede   Bryan Schumaker   NFS: Create a fre...
747
  	.free_client	= nfs_free_client,
1179acc6a   Bryan Schumaker   NFS: Only initial...
748
749
  	.create_server	= nfs_create_server,
  	.clone_server	= nfs_clone_server,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
750
  };