]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - fs/nfs/super.c
NFS: Start rpciod in server common management
[mirror_ubuntu-bionic-kernel.git] / fs / nfs / super.c
CommitLineData
f7b422b1
DH
1/*
2 * linux/fs/nfs/super.c
3 *
4 * Copyright (C) 1992 Rick Sladkey
5 *
6 * nfs superblock handling functions
7 *
8 * Modularised by Alan Cox <Alan.Cox@linux.org>, while hacking some
9 * experimental NFS changes. Modularisation taken straight from SYS5 fs.
10 *
11 * Change to nfs_read_super() to permit NFS mounts to multi-homed hosts.
12 * J.S.Peatfield@damtp.cam.ac.uk
13 *
14 * Split from inode.c by David Howells <dhowells@redhat.com>
15 *
16 */
17
18#include <linux/config.h>
19#include <linux/module.h>
20#include <linux/init.h>
21
22#include <linux/time.h>
23#include <linux/kernel.h>
24#include <linux/mm.h>
25#include <linux/string.h>
26#include <linux/stat.h>
27#include <linux/errno.h>
28#include <linux/unistd.h>
29#include <linux/sunrpc/clnt.h>
30#include <linux/sunrpc/stats.h>
31#include <linux/sunrpc/metrics.h>
32#include <linux/nfs_fs.h>
33#include <linux/nfs_mount.h>
34#include <linux/nfs4_mount.h>
35#include <linux/lockd/bind.h>
36#include <linux/smp_lock.h>
37#include <linux/seq_file.h>
38#include <linux/mount.h>
39#include <linux/nfs_idmap.h>
40#include <linux/vfs.h>
41#include <linux/inet.h>
42#include <linux/nfs_xdr.h>
43
44#include <asm/system.h>
45#include <asm/uaccess.h>
46
47#include "nfs4_fs.h"
48#include "callback.h"
49#include "delegation.h"
50#include "iostat.h"
51#include "internal.h"
52
53#define NFSDBG_FACILITY NFSDBG_VFS
54
55/* Maximum number of readahead requests
56 * FIXME: this should really be a sysctl so that users may tune it to suit
57 * their needs. People that do NFS over a slow network, might for
58 * instance want to reduce it to something closer to 1 for improved
59 * interactive response.
60 */
61#define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1)
62
f7b422b1 63static void nfs_umount_begin(struct vfsmount *, int);
816724e6 64static int nfs_statfs(struct dentry *, struct kstatfs *);
f7b422b1
DH
65static int nfs_show_options(struct seq_file *, struct vfsmount *);
66static int nfs_show_stats(struct seq_file *, struct vfsmount *);
816724e6
TM
67static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *);
68static int nfs_clone_nfs_sb(struct file_system_type *fs_type,
69 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
f7b422b1
DH
70static void nfs_kill_super(struct super_block *);
71
72static struct file_system_type nfs_fs_type = {
73 .owner = THIS_MODULE,
74 .name = "nfs",
75 .get_sb = nfs_get_sb,
76 .kill_sb = nfs_kill_super,
77 .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
78};
79
80struct file_system_type clone_nfs_fs_type = {
81 .owner = THIS_MODULE,
82 .name = "nfs",
83 .get_sb = nfs_clone_nfs_sb,
84 .kill_sb = nfs_kill_super,
85 .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
86};
87
88static struct super_operations nfs_sops = {
89 .alloc_inode = nfs_alloc_inode,
90 .destroy_inode = nfs_destroy_inode,
91 .write_inode = nfs_write_inode,
92 .statfs = nfs_statfs,
93 .clear_inode = nfs_clear_inode,
94 .umount_begin = nfs_umount_begin,
95 .show_options = nfs_show_options,
96 .show_stats = nfs_show_stats,
97};
98
99#ifdef CONFIG_NFS_V4
816724e6
TM
100static int nfs4_get_sb(struct file_system_type *fs_type,
101 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
102static int nfs_clone_nfs4_sb(struct file_system_type *fs_type,
103 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
104static int nfs_referral_nfs4_sb(struct file_system_type *fs_type,
105 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
f7b422b1
DH
106static void nfs4_kill_super(struct super_block *sb);
107
108static struct file_system_type nfs4_fs_type = {
109 .owner = THIS_MODULE,
110 .name = "nfs4",
111 .get_sb = nfs4_get_sb,
112 .kill_sb = nfs4_kill_super,
113 .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
114};
115
116struct file_system_type clone_nfs4_fs_type = {
117 .owner = THIS_MODULE,
118 .name = "nfs4",
119 .get_sb = nfs_clone_nfs4_sb,
120 .kill_sb = nfs4_kill_super,
121 .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
122};
123
124struct file_system_type nfs_referral_nfs4_fs_type = {
125 .owner = THIS_MODULE,
126 .name = "nfs4",
127 .get_sb = nfs_referral_nfs4_sb,
128 .kill_sb = nfs4_kill_super,
129 .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
130};
131
132static struct super_operations nfs4_sops = {
133 .alloc_inode = nfs_alloc_inode,
134 .destroy_inode = nfs_destroy_inode,
135 .write_inode = nfs_write_inode,
136 .statfs = nfs_statfs,
137 .clear_inode = nfs4_clear_inode,
138 .umount_begin = nfs_umount_begin,
139 .show_options = nfs_show_options,
140 .show_stats = nfs_show_stats,
141};
142#endif
143
979df72e
TM
144static struct shrinker *acl_shrinker;
145
f7b422b1
DH
146/*
147 * Register the NFS filesystems
148 */
149int __init register_nfs_fs(void)
150{
151 int ret;
152
153 ret = register_filesystem(&nfs_fs_type);
154 if (ret < 0)
155 goto error_0;
156
157#ifdef CONFIG_NFS_V4
158 ret = nfs_register_sysctl();
159 if (ret < 0)
160 goto error_1;
161 ret = register_filesystem(&nfs4_fs_type);
162 if (ret < 0)
163 goto error_2;
164#endif
979df72e 165 acl_shrinker = set_shrinker(DEFAULT_SEEKS, nfs_access_cache_shrinker);
f7b422b1
DH
166 return 0;
167
168#ifdef CONFIG_NFS_V4
169error_2:
170 nfs_unregister_sysctl();
171error_1:
172 unregister_filesystem(&nfs_fs_type);
173#endif
174error_0:
175 return ret;
176}
177
178/*
179 * Unregister the NFS filesystems
180 */
181void __exit unregister_nfs_fs(void)
182{
979df72e
TM
183 if (acl_shrinker != NULL)
184 remove_shrinker(acl_shrinker);
f7b422b1
DH
185#ifdef CONFIG_NFS_V4
186 unregister_filesystem(&nfs4_fs_type);
187 nfs_unregister_sysctl();
188#endif
189 unregister_filesystem(&nfs_fs_type);
190}
191
192/*
193 * Deliver file system statistics to userspace
194 */
816724e6 195static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
f7b422b1 196{
0c7d90cf 197 struct nfs_server *server = NFS_SB(dentry->d_sb);
f7b422b1
DH
198 unsigned char blockbits;
199 unsigned long blockres;
0c7d90cf 200 struct nfs_fh *fh = NFS_FH(dentry->d_inode);
f7b422b1
DH
201 struct nfs_fattr fattr;
202 struct nfs_fsstat res = {
203 .fattr = &fattr,
204 };
205 int error;
206
207 lock_kernel();
208
8fa5c000 209 error = server->nfs_client->rpc_ops->statfs(server, fh, &res);
f7b422b1
DH
210 buf->f_type = NFS_SUPER_MAGIC;
211 if (error < 0)
212 goto out_err;
213
214 /*
215 * Current versions of glibc do not correctly handle the
216 * case where f_frsize != f_bsize. Eventually we want to
217 * report the value of wtmult in this field.
218 */
0c7d90cf 219 buf->f_frsize = dentry->d_sb->s_blocksize;
f7b422b1
DH
220
221 /*
222 * On most *nix systems, f_blocks, f_bfree, and f_bavail
223 * are reported in units of f_frsize. Linux hasn't had
224 * an f_frsize field in its statfs struct until recently,
225 * thus historically Linux's sys_statfs reports these
226 * fields in units of f_bsize.
227 */
0c7d90cf
DH
228 buf->f_bsize = dentry->d_sb->s_blocksize;
229 blockbits = dentry->d_sb->s_blocksize_bits;
f7b422b1
DH
230 blockres = (1 << blockbits) - 1;
231 buf->f_blocks = (res.tbytes + blockres) >> blockbits;
232 buf->f_bfree = (res.fbytes + blockres) >> blockbits;
233 buf->f_bavail = (res.abytes + blockres) >> blockbits;
234
235 buf->f_files = res.tfiles;
236 buf->f_ffree = res.afiles;
237
238 buf->f_namelen = server->namelen;
239 out:
240 unlock_kernel();
241 return 0;
242
243 out_err:
244 dprintk("%s: statfs error = %d\n", __FUNCTION__, -error);
245 buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1;
246 goto out;
247
248}
249
7d4e2747
DH
250/*
251 * Map the security flavour number to a name
252 */
81039f1f
TM
253static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour)
254{
7d4e2747 255 static const struct {
81039f1f
TM
256 rpc_authflavor_t flavour;
257 const char *str;
258 } sec_flavours[] = {
259 { RPC_AUTH_NULL, "null" },
260 { RPC_AUTH_UNIX, "sys" },
261 { RPC_AUTH_GSS_KRB5, "krb5" },
262 { RPC_AUTH_GSS_KRB5I, "krb5i" },
263 { RPC_AUTH_GSS_KRB5P, "krb5p" },
264 { RPC_AUTH_GSS_LKEY, "lkey" },
265 { RPC_AUTH_GSS_LKEYI, "lkeyi" },
266 { RPC_AUTH_GSS_LKEYP, "lkeyp" },
267 { RPC_AUTH_GSS_SPKM, "spkm" },
268 { RPC_AUTH_GSS_SPKMI, "spkmi" },
269 { RPC_AUTH_GSS_SPKMP, "spkmp" },
270 { -1, "unknown" }
271 };
272 int i;
273
274 for (i=0; sec_flavours[i].flavour != -1; i++) {
275 if (sec_flavours[i].flavour == flavour)
276 break;
277 }
278 return sec_flavours[i].str;
279}
280
f7b422b1
DH
281/*
282 * Describe the mount options in force on this server representation
283 */
284static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, int showdefaults)
285{
509de811 286 static const struct proc_nfs_info {
f7b422b1 287 int flag;
509de811
DH
288 const char *str;
289 const char *nostr;
f7b422b1
DH
290 } nfs_info[] = {
291 { NFS_MOUNT_SOFT, ",soft", ",hard" },
292 { NFS_MOUNT_INTR, ",intr", "" },
293 { NFS_MOUNT_NOCTO, ",nocto", "" },
294 { NFS_MOUNT_NOAC, ",noac", "" },
295 { NFS_MOUNT_NONLM, ",nolock", "" },
296 { NFS_MOUNT_NOACL, ",noacl", "" },
297 { 0, NULL, NULL }
298 };
509de811 299 const struct proc_nfs_info *nfs_infop;
8fa5c000 300 struct nfs_client *clp = nfss->nfs_client;
f7b422b1 301 char buf[12];
509de811 302 const char *proto;
f7b422b1 303
8fa5c000 304 seq_printf(m, ",vers=%d", clp->rpc_ops->version);
f7b422b1
DH
305 seq_printf(m, ",rsize=%d", nfss->rsize);
306 seq_printf(m, ",wsize=%d", nfss->wsize);
307 if (nfss->acregmin != 3*HZ || showdefaults)
308 seq_printf(m, ",acregmin=%d", nfss->acregmin/HZ);
309 if (nfss->acregmax != 60*HZ || showdefaults)
310 seq_printf(m, ",acregmax=%d", nfss->acregmax/HZ);
311 if (nfss->acdirmin != 30*HZ || showdefaults)
312 seq_printf(m, ",acdirmin=%d", nfss->acdirmin/HZ);
313 if (nfss->acdirmax != 60*HZ || showdefaults)
314 seq_printf(m, ",acdirmax=%d", nfss->acdirmax/HZ);
315 for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) {
316 if (nfss->flags & nfs_infop->flag)
317 seq_puts(m, nfs_infop->str);
318 else
319 seq_puts(m, nfs_infop->nostr);
320 }
321 switch (nfss->client->cl_xprt->prot) {
322 case IPPROTO_TCP:
323 proto = "tcp";
324 break;
325 case IPPROTO_UDP:
326 proto = "udp";
327 break;
328 default:
329 snprintf(buf, sizeof(buf), "%u", nfss->client->cl_xprt->prot);
330 proto = buf;
331 }
332 seq_printf(m, ",proto=%s", proto);
5006a76c
DH
333 seq_printf(m, ",timeo=%lu", 10U * clp->retrans_timeo / HZ);
334 seq_printf(m, ",retrans=%u", clp->retrans_count);
81039f1f 335 seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor));
f7b422b1
DH
336}
337
338/*
339 * Describe the mount options on this VFS mountpoint
340 */
341static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
342{
343 struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
344
345 nfs_show_mount_options(m, nfss, 0);
346
347 seq_puts(m, ",addr=");
348 seq_escape(m, nfss->hostname, " \t\n\\");
349
350 return 0;
351}
352
353/*
354 * Present statistical information for this VFS mountpoint
355 */
356static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
357{
358 int i, cpu;
359 struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
360 struct rpc_auth *auth = nfss->client->cl_auth;
361 struct nfs_iostats totals = { };
362
363 seq_printf(m, "statvers=%s", NFS_IOSTAT_VERS);
364
365 /*
366 * Display all mount option settings
367 */
368 seq_printf(m, "\n\topts:\t");
369 seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? "ro" : "rw");
370 seq_puts(m, mnt->mnt_sb->s_flags & MS_SYNCHRONOUS ? ",sync" : "");
371 seq_puts(m, mnt->mnt_sb->s_flags & MS_NOATIME ? ",noatime" : "");
372 seq_puts(m, mnt->mnt_sb->s_flags & MS_NODIRATIME ? ",nodiratime" : "");
373 nfs_show_mount_options(m, nfss, 1);
374
375 seq_printf(m, "\n\tage:\t%lu", (jiffies - nfss->mount_time) / HZ);
376
377 seq_printf(m, "\n\tcaps:\t");
378 seq_printf(m, "caps=0x%x", nfss->caps);
379 seq_printf(m, ",wtmult=%d", nfss->wtmult);
380 seq_printf(m, ",dtsize=%d", nfss->dtsize);
381 seq_printf(m, ",bsize=%d", nfss->bsize);
382 seq_printf(m, ",namelen=%d", nfss->namelen);
383
384#ifdef CONFIG_NFS_V4
8fa5c000 385 if (nfss->nfs_client->cl_nfsversion == 4) {
f7b422b1
DH
386 seq_printf(m, "\n\tnfsv4:\t");
387 seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]);
388 seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]);
389 seq_printf(m, ",acl=0x%x", nfss->acl_bitmask);
390 }
391#endif
392
393 /*
394 * Display security flavor in effect for this mount
395 */
396 seq_printf(m, "\n\tsec:\tflavor=%d", auth->au_ops->au_flavor);
397 if (auth->au_flavor)
398 seq_printf(m, ",pseudoflavor=%d", auth->au_flavor);
399
400 /*
401 * Display superblock I/O counters
402 */
403 for_each_possible_cpu(cpu) {
404 struct nfs_iostats *stats;
405
406 preempt_disable();
407 stats = per_cpu_ptr(nfss->io_stats, cpu);
408
409 for (i = 0; i < __NFSIOS_COUNTSMAX; i++)
410 totals.events[i] += stats->events[i];
411 for (i = 0; i < __NFSIOS_BYTESMAX; i++)
412 totals.bytes[i] += stats->bytes[i];
413
414 preempt_enable();
415 }
416
417 seq_printf(m, "\n\tevents:\t");
418 for (i = 0; i < __NFSIOS_COUNTSMAX; i++)
419 seq_printf(m, "%lu ", totals.events[i]);
420 seq_printf(m, "\n\tbytes:\t");
421 for (i = 0; i < __NFSIOS_BYTESMAX; i++)
422 seq_printf(m, "%Lu ", totals.bytes[i]);
423 seq_printf(m, "\n");
424
425 rpc_print_iostats(m, nfss->client);
426
427 return 0;
428}
429
430/*
431 * Begin unmount by attempting to remove all automounted mountpoints we added
432 * in response to traversals
433 */
434static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags)
435{
436 struct nfs_server *server;
437 struct rpc_clnt *rpc;
438
439 shrink_submounts(vfsmnt, &nfs_automount_list);
440 if (!(flags & MNT_FORCE))
441 return;
442 /* -EIO all pending I/O */
443 server = NFS_SB(vfsmnt->mnt_sb);
444 rpc = server->client;
445 if (!IS_ERR(rpc))
446 rpc_killall_tasks(rpc);
447 rpc = server->client_acl;
448 if (!IS_ERR(rpc))
449 rpc_killall_tasks(rpc);
450}
451
452/*
453 * Obtain the root inode of the file system.
454 */
455static struct inode *
456nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh, struct nfs_fsinfo *fsinfo)
457{
458 struct nfs_server *server = NFS_SB(sb);
459 int error;
460
8fa5c000 461 error = server->nfs_client->rpc_ops->getroot(server, rootfh, fsinfo);
f7b422b1
DH
462 if (error < 0) {
463 dprintk("nfs_get_root: getattr error = %d\n", -error);
464 return ERR_PTR(error);
465 }
466
467 server->fsid = fsinfo->fattr->fsid;
468 return nfs_fhget(sb, rootfh, fsinfo->fattr);
469}
470
471/*
472 * Do NFS version-independent mount processing, and sanity checking
473 */
474static int
475nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
476{
477 struct nfs_server *server;
478 struct inode *root_inode;
479 struct nfs_fattr fattr;
480 struct nfs_fsinfo fsinfo = {
481 .fattr = &fattr,
482 };
483 struct nfs_pathconf pathinfo = {
484 .fattr = &fattr,
485 };
486 int no_root_error = 0;
487 unsigned long max_rpc_payload;
488
489 /* We probably want something more informative here */
490 snprintf(sb->s_id, sizeof(sb->s_id), "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev));
491
492 server = NFS_SB(sb);
493
494 sb->s_magic = NFS_SUPER_MAGIC;
495
496 server->io_stats = nfs_alloc_iostats();
497 if (server->io_stats == NULL)
498 return -ENOMEM;
499
500 root_inode = nfs_get_root(sb, &server->fh, &fsinfo);
501 /* Did getting the root inode fail? */
502 if (IS_ERR(root_inode)) {
503 no_root_error = PTR_ERR(root_inode);
504 goto out_no_root;
505 }
506 sb->s_root = d_alloc_root(root_inode);
507 if (!sb->s_root) {
508 no_root_error = -ENOMEM;
509 goto out_no_root;
510 }
8fa5c000 511 sb->s_root->d_op = server->nfs_client->rpc_ops->dentry_ops;
f7b422b1
DH
512
513 /* mount time stamp, in seconds */
514 server->mount_time = jiffies;
515
516 /* Get some general file system info */
517 if (server->namelen == 0 &&
8fa5c000 518 server->nfs_client->rpc_ops->pathconf(server, &server->fh, &pathinfo) >= 0)
f7b422b1
DH
519 server->namelen = pathinfo.max_namelen;
520 /* Work out a lot of parameters */
521 if (server->rsize == 0)
522 server->rsize = nfs_block_size(fsinfo.rtpref, NULL);
523 if (server->wsize == 0)
524 server->wsize = nfs_block_size(fsinfo.wtpref, NULL);
525
526 if (fsinfo.rtmax >= 512 && server->rsize > fsinfo.rtmax)
527 server->rsize = nfs_block_size(fsinfo.rtmax, NULL);
528 if (fsinfo.wtmax >= 512 && server->wsize > fsinfo.wtmax)
529 server->wsize = nfs_block_size(fsinfo.wtmax, NULL);
530
531 max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL);
532 if (server->rsize > max_rpc_payload)
533 server->rsize = max_rpc_payload;
534 if (server->rsize > NFS_MAX_FILE_IO_SIZE)
535 server->rsize = NFS_MAX_FILE_IO_SIZE;
536 server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
537
538 if (server->wsize > max_rpc_payload)
539 server->wsize = max_rpc_payload;
540 if (server->wsize > NFS_MAX_FILE_IO_SIZE)
541 server->wsize = NFS_MAX_FILE_IO_SIZE;
542 server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
543
544 if (sb->s_blocksize == 0)
545 sb->s_blocksize = nfs_block_bits(server->wsize,
546 &sb->s_blocksize_bits);
547 server->wtmult = nfs_block_bits(fsinfo.wtmult, NULL);
548
549 server->dtsize = nfs_block_size(fsinfo.dtpref, NULL);
550 if (server->dtsize > PAGE_CACHE_SIZE)
551 server->dtsize = PAGE_CACHE_SIZE;
552 if (server->dtsize > server->rsize)
553 server->dtsize = server->rsize;
554
555 if (server->flags & NFS_MOUNT_NOAC) {
556 server->acregmin = server->acregmax = 0;
557 server->acdirmin = server->acdirmax = 0;
558 sb->s_flags |= MS_SYNCHRONOUS;
559 }
560 server->backing_dev_info.ra_pages = server->rpages * NFS_MAX_READAHEAD;
561
562 nfs_super_set_maxbytes(sb, fsinfo.maxfilesize);
563
564 server->client->cl_intr = (server->flags & NFS_MOUNT_INTR) ? 1 : 0;
565 server->client->cl_softrtry = (server->flags & NFS_MOUNT_SOFT) ? 1 : 0;
566
567 /* We're airborne Set socket buffersize */
568 rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);
569 return 0;
570 /* Yargs. It didn't work out. */
571out_no_root:
572 dprintk("nfs_sb_init: get root inode failed: errno %d\n", -no_root_error);
573 if (!IS_ERR(root_inode))
574 iput(root_inode);
575 return no_root_error;
576}
577
f7b422b1
DH
578/*
579 * Create an RPC client handle.
580 */
581static struct rpc_clnt *
582nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
583{
27951bd2 584 struct nfs_client *clp;
5006a76c 585 struct rpc_clnt *clnt;
f7b422b1 586 int proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
8fa5c000 587 int nfsversion = 2;
5006a76c 588 int err;
f7b422b1 589
8fa5c000
DH
590#ifdef CONFIG_NFS_V3
591 if (server->flags & NFS_MOUNT_VER3)
592 nfsversion = 3;
593#endif
594
595 clp = nfs_get_client(server->hostname, &server->addr, nfsversion);
27951bd2
DH
596 if (!clp) {
597 dprintk("%s: failed to create NFS4 client.\n", __FUNCTION__);
598 return ERR_PTR(PTR_ERR(clp));
599 }
600
5006a76c
DH
601 if (clp->cl_cons_state == NFS_CS_INITING) {
602 /* Check NFS protocol revision and initialize RPC op
603 * vector and file handle pool. */
8fa5c000 604#ifdef CONFIG_NFS_V3
5006a76c
DH
605 if (nfsversion == 3) {
606 clp->rpc_ops = &nfs_v3_clientops;
607 server->caps |= NFS_CAP_READDIRPLUS;
608 } else {
609 clp->rpc_ops = &nfs_v2_clientops;
610 }
8fa5c000 611#else
5006a76c 612 clp->rpc_ops = &nfs_v2_clientops;
8fa5c000
DH
613#endif
614
5006a76c
DH
615 /* create transport and client */
616 err = nfs_create_rpc_client(clp, proto, data->timeo,
617 data->retrans, RPC_AUTH_UNIX);
618 if (err < 0)
619 goto client_init_error;
620
621 nfs_mark_client_ready(clp, 0);
f7b422b1 622 }
5006a76c
DH
623
624 /* create an nfs_server-specific client */
625 clnt = rpc_clone_client(clp->cl_rpcclient);
f7b422b1 626 if (IS_ERR(clnt)) {
5006a76c
DH
627 dprintk("%s: couldn't create rpc_client!\n", __FUNCTION__);
628 nfs_put_client(clp);
629 return ERR_PTR(PTR_ERR(clnt));
f7b422b1
DH
630 }
631
5006a76c
DH
632 if (data->pseudoflavor != clp->cl_rpcclient->cl_auth->au_flavor) {
633 struct rpc_auth *auth;
634
635 auth = rpcauth_create(data->pseudoflavor, server->client);
636 if (IS_ERR(auth)) {
637 dprintk("%s: couldn't create credcache!\n", __FUNCTION__);
638 return ERR_PTR(PTR_ERR(auth));
639 }
640 }
f7b422b1 641
27951bd2 642 server->nfs_client = clp;
f7b422b1
DH
643 return clnt;
644
5006a76c
DH
645client_init_error:
646 nfs_mark_client_ready(clp, err);
27951bd2 647 nfs_put_client(clp);
5006a76c 648 return ERR_PTR(err);
f7b422b1
DH
649}
650
651/*
652 * Clone a server record
653 */
654static struct nfs_server *nfs_clone_server(struct super_block *sb, struct nfs_clone_mount *data)
655{
656 struct nfs_server *server = NFS_SB(sb);
657 struct nfs_server *parent = NFS_SB(data->sb);
658 struct inode *root_inode;
659 struct nfs_fsinfo fsinfo;
660 void *err = ERR_PTR(-ENOMEM);
661
662 sb->s_op = data->sb->s_op;
663 sb->s_blocksize = data->sb->s_blocksize;
664 sb->s_blocksize_bits = data->sb->s_blocksize_bits;
665 sb->s_maxbytes = data->sb->s_maxbytes;
666
5006a76c 667 server->client_acl = ERR_PTR(-EINVAL);
f7b422b1
DH
668 server->io_stats = nfs_alloc_iostats();
669 if (server->io_stats == NULL)
670 goto out;
671
672 server->client = rpc_clone_client(parent->client);
673 if (IS_ERR((err = server->client)))
674 goto out;
675
f7b422b1
DH
676 if (!IS_ERR(parent->client_acl)) {
677 server->client_acl = rpc_clone_client(parent->client_acl);
678 if (IS_ERR((err = server->client_acl)))
679 goto out;
680 }
681 root_inode = nfs_fhget(sb, data->fh, data->fattr);
682 if (!root_inode)
683 goto out;
684 sb->s_root = d_alloc_root(root_inode);
685 if (!sb->s_root)
686 goto out_put_root;
687 fsinfo.fattr = data->fattr;
688 if (NFS_PROTO(root_inode)->fsinfo(server, data->fh, &fsinfo) == 0)
689 nfs_super_set_maxbytes(sb, fsinfo.maxfilesize);
8fa5c000 690 sb->s_root->d_op = server->nfs_client->rpc_ops->dentry_ops;
f7b422b1
DH
691 sb->s_flags |= MS_ACTIVE;
692 return server;
693out_put_root:
694 iput(root_inode);
695out:
696 return err;
697}
698
699/*
700 * Copy an existing superblock and attach revised data
701 */
816724e6 702static int nfs_clone_generic_sb(struct nfs_clone_mount *data,
f7b422b1 703 struct super_block *(*fill_sb)(struct nfs_server *, struct nfs_clone_mount *),
816724e6
TM
704 struct nfs_server *(*fill_server)(struct super_block *, struct nfs_clone_mount *),
705 struct vfsmount *mnt)
f7b422b1
DH
706{
707 struct nfs_server *server;
708 struct nfs_server *parent = NFS_SB(data->sb);
709 struct super_block *sb = ERR_PTR(-EINVAL);
f7b422b1 710 char *hostname;
816724e6 711 int error = -ENOMEM;
f7b422b1
DH
712 int len;
713
714 server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL);
715 if (server == NULL)
716 goto out_err;
717 memcpy(server, parent, sizeof(*server));
27951bd2 718 atomic_inc(&server->nfs_client->cl_count);
f7b422b1
DH
719 hostname = (data->hostname != NULL) ? data->hostname : parent->hostname;
720 len = strlen(hostname) + 1;
721 server->hostname = kmalloc(len, GFP_KERNEL);
722 if (server->hostname == NULL)
723 goto free_server;
724 memcpy(server->hostname, hostname, len);
f7b422b1
DH
725
726 sb = fill_sb(server, data);
816724e6
TM
727 if (IS_ERR(sb)) {
728 error = PTR_ERR(sb);
cf6d7b5d 729 goto free_hostname;
816724e6 730 }
5006a76c 731
816724e6 732 if (sb->s_root)
cf6d7b5d 733 goto out_share;
f7b422b1
DH
734
735 server = fill_server(sb, data);
816724e6
TM
736 if (IS_ERR(server)) {
737 error = PTR_ERR(server);
f7b422b1 738 goto out_deactivate;
816724e6
TM
739 }
740 return simple_set_mnt(mnt, sb);
f7b422b1
DH
741out_deactivate:
742 up_write(&sb->s_umount);
743 deactivate_super(sb);
816724e6 744 return error;
cf6d7b5d 745out_share:
816724e6 746 kfree(server->hostname);
27951bd2 747 nfs_put_client(server->nfs_client);
816724e6
TM
748 kfree(server);
749 return simple_set_mnt(mnt, sb);
f7b422b1
DH
750free_hostname:
751 kfree(server->hostname);
752free_server:
27951bd2 753 nfs_put_client(server->nfs_client);
f7b422b1
DH
754 kfree(server);
755out_err:
816724e6 756 return error;
f7b422b1
DH
757}
758
759/*
760 * Set up an NFS2/3 superblock
761 *
762 * The way this works is that the mount process passes a structure
763 * in the data argument which contains the server's IP address
764 * and the root file handle obtained from the server's mount
765 * daemon. We stash these away in the private superblock fields.
766 */
767static int
768nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
769{
770 struct nfs_server *server;
771 rpc_authflavor_t authflavor;
772
773 server = NFS_SB(sb);
774 sb->s_blocksize_bits = 0;
775 sb->s_blocksize = 0;
776 if (data->bsize)
777 sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits);
778 if (data->rsize)
779 server->rsize = nfs_block_size(data->rsize, NULL);
780 if (data->wsize)
781 server->wsize = nfs_block_size(data->wsize, NULL);
782 server->flags = data->flags & NFS_MOUNT_FLAGMASK;
783
784 server->acregmin = data->acregmin*HZ;
785 server->acregmax = data->acregmax*HZ;
786 server->acdirmin = data->acdirmin*HZ;
787 server->acdirmax = data->acdirmax*HZ;
788
789 /* Start lockd here, before we might error out */
790 if (!(server->flags & NFS_MOUNT_NONLM))
791 lockd_up();
792
793 server->namelen = data->namlen;
794 server->hostname = kmalloc(strlen(data->hostname) + 1, GFP_KERNEL);
795 if (!server->hostname)
796 return -ENOMEM;
797 strcpy(server->hostname, data->hostname);
798
f7b422b1
DH
799 /* Fill in pseudoflavor for mount version < 5 */
800 if (!(data->flags & NFS_MOUNT_SECFLAVOUR))
801 data->pseudoflavor = RPC_AUTH_UNIX;
802 authflavor = data->pseudoflavor; /* save for sb_init() */
803 /* XXX maybe we want to add a server->pseudoflavor field */
804
805 /* Create RPC client handles */
806 server->client = nfs_create_client(server, data);
807 if (IS_ERR(server->client))
808 return PTR_ERR(server->client);
8fa5c000 809
f7b422b1 810 /* RFC 2623, sec 2.3.2 */
f7b422b1
DH
811 if (server->flags & NFS_MOUNT_VER3) {
812#ifdef CONFIG_NFS_V3_ACL
813 if (!(server->flags & NFS_MOUNT_NOACL)) {
814 server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3);
815 /* No errors! Assume that Sun nfsacls are supported */
816 if (!IS_ERR(server->client_acl))
817 server->caps |= NFS_CAP_ACLS;
818 }
819#else
820 server->flags &= ~NFS_MOUNT_NOACL;
821#endif /* CONFIG_NFS_V3_ACL */
822 /*
823 * The VFS shouldn't apply the umask to mode bits. We will
824 * do so ourselves when necessary.
825 */
826 sb->s_flags |= MS_POSIXACL;
827 if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN)
828 server->namelen = NFS3_MAXNAMLEN;
829 sb->s_time_gran = 1;
830 } else {
831 if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN)
832 server->namelen = NFS2_MAXNAMLEN;
833 }
834
835 sb->s_op = &nfs_sops;
836 return nfs_sb_init(sb, authflavor);
837}
838
839static int nfs_set_super(struct super_block *s, void *data)
840{
841 s->s_fs_info = data;
842 return set_anon_super(s, data);
843}
844
845static int nfs_compare_super(struct super_block *sb, void *data)
846{
847 struct nfs_server *server = data;
848 struct nfs_server *old = NFS_SB(sb);
849
850 if (old->addr.sin_addr.s_addr != server->addr.sin_addr.s_addr)
851 return 0;
852 if (old->addr.sin_port != server->addr.sin_port)
853 return 0;
854 return !nfs_compare_fh(&old->fh, &server->fh);
855}
856
816724e6
TM
857static int nfs_get_sb(struct file_system_type *fs_type,
858 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
f7b422b1
DH
859{
860 int error;
861 struct nfs_server *server = NULL;
862 struct super_block *s;
863 struct nfs_fh *root;
864 struct nfs_mount_data *data = raw_data;
865
816724e6 866 error = -EINVAL;
f7b422b1
DH
867 if (data == NULL) {
868 dprintk("%s: missing data argument\n", __FUNCTION__);
816724e6 869 goto out_err_noserver;
f7b422b1
DH
870 }
871 if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) {
872 dprintk("%s: bad mount version\n", __FUNCTION__);
816724e6 873 goto out_err_noserver;
f7b422b1
DH
874 }
875 switch (data->version) {
876 case 1:
877 data->namlen = 0;
878 case 2:
879 data->bsize = 0;
880 case 3:
881 if (data->flags & NFS_MOUNT_VER3) {
882 dprintk("%s: mount structure version %d does not support NFSv3\n",
883 __FUNCTION__,
884 data->version);
816724e6 885 goto out_err_noserver;
f7b422b1
DH
886 }
887 data->root.size = NFS2_FHSIZE;
888 memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
889 case 4:
890 if (data->flags & NFS_MOUNT_SECFLAVOUR) {
891 dprintk("%s: mount structure version %d does not support strong security\n",
892 __FUNCTION__,
893 data->version);
816724e6 894 goto out_err_noserver;
f7b422b1
DH
895 }
896 case 5:
897 memset(data->context, 0, sizeof(data->context));
898 }
899#ifndef CONFIG_NFS_V3
900 /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */
816724e6 901 error = -EPROTONOSUPPORT;
f7b422b1
DH
902 if (data->flags & NFS_MOUNT_VER3) {
903 dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__);
816724e6 904 goto out_err_noserver;
f7b422b1
DH
905 }
906#endif /* CONFIG_NFS_V3 */
907
816724e6 908 error = -ENOMEM;
f7b422b1
DH
909 server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
910 if (!server)
816724e6 911 goto out_err_noserver;
f7b422b1
DH
912 /* Zero out the NFS state stuff */
913 init_nfsv4_state(server);
5006a76c 914 server->client = server->client_acl = ERR_PTR(-EINVAL);
f7b422b1
DH
915
916 root = &server->fh;
917 if (data->flags & NFS_MOUNT_VER3)
918 root->size = data->root.size;
919 else
920 root->size = NFS2_FHSIZE;
816724e6 921 error = -EINVAL;
f7b422b1
DH
922 if (root->size > sizeof(root->data)) {
923 dprintk("%s: invalid root filehandle\n", __FUNCTION__);
924 goto out_err;
925 }
926 memcpy(root->data, data->root.data, root->size);
927
928 /* We now require that the mount process passes the remote address */
929 memcpy(&server->addr, &data->addr, sizeof(server->addr));
930 if (server->addr.sin_addr.s_addr == INADDR_ANY) {
931 dprintk("%s: mount program didn't pass remote address!\n",
932 __FUNCTION__);
933 goto out_err;
934 }
935
f7b422b1 936 s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
816724e6
TM
937 if (IS_ERR(s)) {
938 error = PTR_ERR(s);
cf6d7b5d 939 goto out_err;
816724e6
TM
940 }
941
942 if (s->s_root)
cf6d7b5d 943 goto out_share;
f7b422b1
DH
944
945 s->s_flags = flags;
946
947 error = nfs_fill_super(s, data, flags & MS_SILENT ? 1 : 0);
948 if (error) {
949 up_write(&s->s_umount);
950 deactivate_super(s);
816724e6 951 return error;
f7b422b1
DH
952 }
953 s->s_flags |= MS_ACTIVE;
816724e6
TM
954 return simple_set_mnt(mnt, s);
955
cf6d7b5d 956out_share:
816724e6
TM
957 kfree(server);
958 return simple_set_mnt(mnt, s);
959
f7b422b1
DH
960out_err:
961 kfree(server);
816724e6
TM
962out_err_noserver:
963 return error;
f7b422b1
DH
964}
965
966static void nfs_kill_super(struct super_block *s)
967{
968 struct nfs_server *server = NFS_SB(s);
969
970 kill_anon_super(s);
971
972 if (!IS_ERR(server->client))
973 rpc_shutdown_client(server->client);
f7b422b1
DH
974 if (!IS_ERR(server->client_acl))
975 rpc_shutdown_client(server->client_acl);
976
977 if (!(server->flags & NFS_MOUNT_NONLM))
978 lockd_down(); /* release rpc.lockd */
979
f7b422b1
DH
980 nfs_free_iostats(server->io_stats);
981 kfree(server->hostname);
27951bd2 982 nfs_put_client(server->nfs_client);
f7b422b1
DH
983 kfree(server);
984 nfs_release_automount_timer();
985}
986
987static struct super_block *nfs_clone_sb(struct nfs_server *server, struct nfs_clone_mount *data)
988{
989 struct super_block *sb;
990
991 server->fsid = data->fattr->fsid;
992 nfs_copy_fh(&server->fh, data->fh);
993 sb = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
994 if (!IS_ERR(sb) && sb->s_root == NULL && !(server->flags & NFS_MOUNT_NONLM))
995 lockd_up();
996 return sb;
997}
998
816724e6
TM
999static int nfs_clone_nfs_sb(struct file_system_type *fs_type,
1000 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
f7b422b1
DH
1001{
1002 struct nfs_clone_mount *data = raw_data;
816724e6 1003 return nfs_clone_generic_sb(data, nfs_clone_sb, nfs_clone_server, mnt);
f7b422b1
DH
1004}
1005
1006#ifdef CONFIG_NFS_V4
1007static struct rpc_clnt *nfs4_create_client(struct nfs_server *server,
5006a76c 1008 int timeo, int retrans, int proto, rpc_authflavor_t flavor)
f7b422b1 1009{
adfa6f98 1010 struct nfs_client *clp;
f7b422b1
DH
1011 struct rpc_clnt *clnt = NULL;
1012 int err = -EIO;
1013
24c8dbbb 1014 clp = nfs_get_client(server->hostname, &server->addr, 4);
f7b422b1
DH
1015 if (!clp) {
1016 dprintk("%s: failed to create NFS4 client.\n", __FUNCTION__);
1017 return ERR_PTR(err);
1018 }
1019
1020 /* Now create transport and client */
24c8dbbb 1021 if (clp->cl_cons_state == NFS_CS_INITING) {
8fa5c000
DH
1022 clp->rpc_ops = &nfs_v4_clientops;
1023
5006a76c
DH
1024 err = nfs_create_rpc_client(clp, proto, timeo, retrans, flavor);
1025 if (err < 0)
24c8dbbb 1026 goto client_init_error;
5006a76c 1027
f7b422b1 1028 memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr));
24c8dbbb
DH
1029 err = nfs_idmap_new(clp);
1030 if (err < 0) {
1031 dprintk("%s: failed to create idmapper.\n",
1032 __FUNCTION__);
1033 goto client_init_error;
1034 }
1035 __set_bit(NFS_CS_IDMAP, &clp->cl_res_state);
1036 nfs_mark_client_ready(clp, 0);
f7b422b1 1037 }
24c8dbbb 1038
f7b422b1 1039 clnt = rpc_clone_client(clp->cl_rpcclient);
f7b422b1
DH
1040
1041 if (IS_ERR(clnt)) {
1042 dprintk("%s: cannot create RPC client. Error = %d\n",
1043 __FUNCTION__, err);
1044 return clnt;
1045 }
1046
f7b422b1
DH
1047 if (clnt->cl_auth->au_flavor != flavor) {
1048 struct rpc_auth *auth;
1049
1050 auth = rpcauth_create(flavor, clnt);
1051 if (IS_ERR(auth)) {
1052 dprintk("%s: couldn't create credcache!\n", __FUNCTION__);
1053 return (struct rpc_clnt *)auth;
1054 }
1055 }
24c8dbbb
DH
1056
1057 server->nfs_client = clp;
1058 down_write(&clp->cl_sem);
1059 list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks);
1060 up_write(&clp->cl_sem);
f7b422b1
DH
1061 return clnt;
1062
24c8dbbb
DH
1063client_init_error:
1064 nfs_mark_client_ready(clp, err);
1065 nfs_put_client(clp);
f7b422b1
DH
1066 return ERR_PTR(err);
1067}
1068
1069/*
1070 * Set up an NFS4 superblock
1071 */
1072static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, int silent)
1073{
1074 struct nfs_server *server;
f7b422b1
DH
1075 rpc_authflavor_t authflavour;
1076 int err = -EIO;
1077
1078 sb->s_blocksize_bits = 0;
1079 sb->s_blocksize = 0;
1080 server = NFS_SB(sb);
1081 if (data->rsize != 0)
1082 server->rsize = nfs_block_size(data->rsize, NULL);
1083 if (data->wsize != 0)
1084 server->wsize = nfs_block_size(data->wsize, NULL);
1085 server->flags = data->flags & NFS_MOUNT_FLAGMASK;
1086 server->caps = NFS_CAP_ATOMIC_OPEN;
1087
1088 server->acregmin = data->acregmin*HZ;
1089 server->acregmax = data->acregmax*HZ;
1090 server->acdirmin = data->acdirmin*HZ;
1091 server->acdirmax = data->acdirmax*HZ;
1092
f7b422b1
DH
1093 /* Now create transport and client */
1094 authflavour = RPC_AUTH_UNIX;
1095 if (data->auth_flavourlen != 0) {
1096 if (data->auth_flavourlen != 1) {
1097 dprintk("%s: Invalid number of RPC auth flavours %d.\n",
1098 __FUNCTION__, data->auth_flavourlen);
1099 err = -EINVAL;
1100 goto out_fail;
1101 }
1102 if (copy_from_user(&authflavour, data->auth_flavours, sizeof(authflavour))) {
1103 err = -EFAULT;
1104 goto out_fail;
1105 }
1106 }
1107
5006a76c
DH
1108 server->client = nfs4_create_client(server, data->timeo, data->retrans,
1109 data->proto, authflavour);
f7b422b1
DH
1110 if (IS_ERR(server->client)) {
1111 err = PTR_ERR(server->client);
1112 dprintk("%s: cannot create RPC client. Error = %d\n",
1113 __FUNCTION__, err);
1114 goto out_fail;
1115 }
1116
1117 sb->s_time_gran = 1;
1118
1119 sb->s_op = &nfs4_sops;
1120 err = nfs_sb_init(sb, authflavour);
1121
1122 out_fail:
1123 return err;
1124}
1125
1126static int nfs4_compare_super(struct super_block *sb, void *data)
1127{
1128 struct nfs_server *server = data;
1129 struct nfs_server *old = NFS_SB(sb);
1130
1131 if (strcmp(server->hostname, old->hostname) != 0)
1132 return 0;
1133 if (strcmp(server->mnt_path, old->mnt_path) != 0)
1134 return 0;
1135 return 1;
1136}
1137
1138static void *
1139nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen)
1140{
1141 void *p = NULL;
1142
1143 if (!src->len)
1144 return ERR_PTR(-EINVAL);
1145 if (src->len < maxlen)
1146 maxlen = src->len;
1147 if (dst == NULL) {
1148 p = dst = kmalloc(maxlen + 1, GFP_KERNEL);
1149 if (p == NULL)
1150 return ERR_PTR(-ENOMEM);
1151 }
1152 if (copy_from_user(dst, src->data, maxlen)) {
1153 kfree(p);
1154 return ERR_PTR(-EFAULT);
1155 }
1156 dst[maxlen] = '\0';
1157 return dst;
1158}
1159
816724e6
TM
1160static int nfs4_get_sb(struct file_system_type *fs_type,
1161 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
f7b422b1
DH
1162{
1163 int error;
1164 struct nfs_server *server;
1165 struct super_block *s;
1166 struct nfs4_mount_data *data = raw_data;
1167 void *p;
1168
1169 if (data == NULL) {
1170 dprintk("%s: missing data argument\n", __FUNCTION__);
816724e6 1171 return -EINVAL;
f7b422b1
DH
1172 }
1173 if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) {
1174 dprintk("%s: bad mount version\n", __FUNCTION__);
816724e6 1175 return -EINVAL;
f7b422b1
DH
1176 }
1177
1178 server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
1179 if (!server)
816724e6 1180 return -ENOMEM;
f7b422b1
DH
1181 /* Zero out the NFS state stuff */
1182 init_nfsv4_state(server);
5006a76c 1183 server->client = server->client_acl = ERR_PTR(-EINVAL);
f7b422b1
DH
1184
1185 p = nfs_copy_user_string(NULL, &data->hostname, 256);
1186 if (IS_ERR(p))
1187 goto out_err;
1188 server->hostname = p;
1189
1190 p = nfs_copy_user_string(NULL, &data->mnt_path, 1024);
1191 if (IS_ERR(p))
1192 goto out_err;
1193 server->mnt_path = p;
1194
1195 p = nfs_copy_user_string(server->ip_addr, &data->client_addr,
1196 sizeof(server->ip_addr) - 1);
1197 if (IS_ERR(p))
1198 goto out_err;
1199
1200 /* We now require that the mount process passes the remote address */
1201 if (data->host_addrlen != sizeof(server->addr)) {
816724e6 1202 error = -EINVAL;
f7b422b1
DH
1203 goto out_free;
1204 }
1205 if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) {
816724e6 1206 error = -EFAULT;
f7b422b1
DH
1207 goto out_free;
1208 }
1209 if (server->addr.sin_family != AF_INET ||
1210 server->addr.sin_addr.s_addr == INADDR_ANY) {
1211 dprintk("%s: mount program didn't pass remote IP address!\n",
1212 __FUNCTION__);
816724e6 1213 error = -EINVAL;
f7b422b1
DH
1214 goto out_free;
1215 }
1216
f7b422b1 1217 s = sget(fs_type, nfs4_compare_super, nfs_set_super, server);
816724e6
TM
1218 if (IS_ERR(s)) {
1219 error = PTR_ERR(s);
f7b422b1 1220 goto out_free;
816724e6
TM
1221 }
1222
1223 if (s->s_root) {
1224 kfree(server->mnt_path);
1225 kfree(server->hostname);
1226 kfree(server);
1227 return simple_set_mnt(mnt, s);
1228 }
f7b422b1
DH
1229
1230 s->s_flags = flags;
1231
1232 error = nfs4_fill_super(s, data, flags & MS_SILENT ? 1 : 0);
1233 if (error) {
1234 up_write(&s->s_umount);
1235 deactivate_super(s);
816724e6 1236 return error;
f7b422b1
DH
1237 }
1238 s->s_flags |= MS_ACTIVE;
816724e6 1239 return simple_set_mnt(mnt, s);
f7b422b1 1240out_err:
816724e6 1241 error = PTR_ERR(p);
f7b422b1
DH
1242out_free:
1243 kfree(server->mnt_path);
1244 kfree(server->hostname);
1245 kfree(server);
816724e6 1246 return error;
f7b422b1
DH
1247}
1248
1249static void nfs4_kill_super(struct super_block *sb)
1250{
1251 struct nfs_server *server = NFS_SB(sb);
1252
1253 nfs_return_all_delegations(sb);
1254 kill_anon_super(sb);
1255
1256 nfs4_renewd_prepare_shutdown(server);
1257
1258 if (server->client != NULL && !IS_ERR(server->client))
1259 rpc_shutdown_client(server->client);
1260
1261 destroy_nfsv4_state(server);
1262
f7b422b1
DH
1263 nfs_free_iostats(server->io_stats);
1264 kfree(server->hostname);
1265 kfree(server);
1266 nfs_release_automount_timer();
1267}
1268
1269/*
1270 * Constructs the SERVER-side path
1271 */
1272static inline char *nfs4_dup_path(const struct dentry *dentry)
1273{
1274 char *page = (char *) __get_free_page(GFP_USER);
1275 char *path;
1276
1277 path = nfs4_path(dentry, page, PAGE_SIZE);
1278 if (!IS_ERR(path)) {
1279 int len = PAGE_SIZE + page - path;
1280 char *tmp = path;
1281
1282 path = kmalloc(len, GFP_KERNEL);
1283 if (path)
1284 memcpy(path, tmp, len);
1285 else
1286 path = ERR_PTR(-ENOMEM);
1287 }
1288 free_page((unsigned long)page);
1289 return path;
1290}
1291
1292static struct super_block *nfs4_clone_sb(struct nfs_server *server, struct nfs_clone_mount *data)
1293{
1294 const struct dentry *dentry = data->dentry;
7539bbab 1295 struct nfs_client *clp = server->nfs_client;
f7b422b1
DH
1296 struct super_block *sb;
1297
1298 server->fsid = data->fattr->fsid;
1299 nfs_copy_fh(&server->fh, data->fh);
1300 server->mnt_path = nfs4_dup_path(dentry);
1301 if (IS_ERR(server->mnt_path)) {
1302 sb = (struct super_block *)server->mnt_path;
1303 goto err;
1304 }
1305 sb = sget(&nfs4_fs_type, nfs4_compare_super, nfs_set_super, server);
1306 if (IS_ERR(sb) || sb->s_root)
1307 goto free_path;
1308 nfs4_server_capabilities(server, &server->fh);
1309
1310 down_write(&clp->cl_sem);
f7b422b1
DH
1311 list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks);
1312 up_write(&clp->cl_sem);
1313 return sb;
1314free_path:
1315 kfree(server->mnt_path);
1316err:
1317 server->mnt_path = NULL;
1318 return sb;
1319}
1320
816724e6
TM
1321static int nfs_clone_nfs4_sb(struct file_system_type *fs_type,
1322 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
f7b422b1
DH
1323{
1324 struct nfs_clone_mount *data = raw_data;
816724e6 1325 return nfs_clone_generic_sb(data, nfs4_clone_sb, nfs_clone_server, mnt);
f7b422b1
DH
1326}
1327
1328static struct super_block *nfs4_referral_sb(struct nfs_server *server, struct nfs_clone_mount *data)
1329{
1330 struct super_block *sb = ERR_PTR(-ENOMEM);
1331 int len;
1332
1333 len = strlen(data->mnt_path) + 1;
1334 server->mnt_path = kmalloc(len, GFP_KERNEL);
1335 if (server->mnt_path == NULL)
1336 goto err;
1337 memcpy(server->mnt_path, data->mnt_path, len);
1338 memcpy(&server->addr, data->addr, sizeof(struct sockaddr_in));
1339
1340 sb = sget(&nfs4_fs_type, nfs4_compare_super, nfs_set_super, server);
1341 if (IS_ERR(sb) || sb->s_root)
1342 goto free_path;
1343 return sb;
1344free_path:
1345 kfree(server->mnt_path);
1346err:
1347 server->mnt_path = NULL;
1348 return sb;
1349}
1350
1351static struct nfs_server *nfs4_referral_server(struct super_block *sb, struct nfs_clone_mount *data)
1352{
1353 struct nfs_server *server = NFS_SB(sb);
f7b422b1
DH
1354 int proto, timeo, retrans;
1355 void *err;
1356
1357 proto = IPPROTO_TCP;
1358 /* Since we are following a referral and there may be alternatives,
1359 set the timeouts and retries to low values */
1360 timeo = 2;
1361 retrans = 1;
f7b422b1 1362
27951bd2
DH
1363 nfs_put_client(server->nfs_client);
1364 server->nfs_client = NULL;
5006a76c
DH
1365 server->client = nfs4_create_client(server, timeo, retrans, proto,
1366 data->authflavor);
f7b422b1
DH
1367 if (IS_ERR((err = server->client)))
1368 goto out_err;
1369
1370 sb->s_time_gran = 1;
1371 sb->s_op = &nfs4_sops;
1372 err = ERR_PTR(nfs_sb_init(sb, data->authflavor));
1373 if (!IS_ERR(err))
1374 return server;
1375out_err:
1376 return (struct nfs_server *)err;
1377}
1378
816724e6
TM
1379static int nfs_referral_nfs4_sb(struct file_system_type *fs_type,
1380 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
f7b422b1
DH
1381{
1382 struct nfs_clone_mount *data = raw_data;
816724e6 1383 return nfs_clone_generic_sb(data, nfs4_referral_sb, nfs4_referral_server, mnt);
f7b422b1
DH
1384}
1385
1386#endif