aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/export.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/export.c')
-rw-r--r--fs/nfsd/export.c107
1 files changed, 69 insertions, 38 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 49c310b84923..6f24768272a1 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -16,7 +16,6 @@
16 16
17#include <linux/unistd.h> 17#include <linux/unistd.h>
18#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/sched.h>
20#include <linux/stat.h> 19#include <linux/stat.h>
21#include <linux/in.h> 20#include <linux/in.h>
22#include <linux/seq_file.h> 21#include <linux/seq_file.h>
@@ -190,18 +189,17 @@ static int expkey_show(struct seq_file *m,
190 struct cache_head *h) 189 struct cache_head *h)
191{ 190{
192 struct svc_expkey *ek ; 191 struct svc_expkey *ek ;
192 int i;
193 193
194 if (h ==NULL) { 194 if (h ==NULL) {
195 seq_puts(m, "#domain fsidtype fsid [path]\n"); 195 seq_puts(m, "#domain fsidtype fsid [path]\n");
196 return 0; 196 return 0;
197 } 197 }
198 ek = container_of(h, struct svc_expkey, h); 198 ek = container_of(h, struct svc_expkey, h);
199 seq_printf(m, "%s %d 0x%08x", ek->ek_client->name, 199 seq_printf(m, "%s %d 0x", ek->ek_client->name,
200 ek->ek_fsidtype, ek->ek_fsid[0]); 200 ek->ek_fsidtype);
201 if (ek->ek_fsidtype != 1) 201 for (i=0; i < key_len(ek->ek_fsidtype)/4; i++)
202 seq_printf(m, "%08x", ek->ek_fsid[1]); 202 seq_printf(m, "%08x", ek->ek_fsid[i]);
203 if (ek->ek_fsidtype == 2)
204 seq_printf(m, "%08x", ek->ek_fsid[2]);
205 if (test_bit(CACHE_VALID, &h->flags) && 203 if (test_bit(CACHE_VALID, &h->flags) &&
206 !test_bit(CACHE_NEGATIVE, &h->flags)) { 204 !test_bit(CACHE_NEGATIVE, &h->flags)) {
207 seq_printf(m, " "); 205 seq_printf(m, " ");
@@ -232,9 +230,8 @@ static inline void expkey_init(struct cache_head *cnew,
232 kref_get(&item->ek_client->ref); 230 kref_get(&item->ek_client->ref);
233 new->ek_client = item->ek_client; 231 new->ek_client = item->ek_client;
234 new->ek_fsidtype = item->ek_fsidtype; 232 new->ek_fsidtype = item->ek_fsidtype;
235 new->ek_fsid[0] = item->ek_fsid[0]; 233
236 new->ek_fsid[1] = item->ek_fsid[1]; 234 memcpy(new->ek_fsid, item->ek_fsid, sizeof(new->ek_fsid));
237 new->ek_fsid[2] = item->ek_fsid[2];
238} 235}
239 236
240static inline void expkey_update(struct cache_head *cnew, 237static inline void expkey_update(struct cache_head *cnew,
@@ -363,7 +360,7 @@ static struct svc_export *svc_export_update(struct svc_export *new,
363 struct svc_export *old); 360 struct svc_export *old);
364static struct svc_export *svc_export_lookup(struct svc_export *); 361static struct svc_export *svc_export_lookup(struct svc_export *);
365 362
366static int check_export(struct inode *inode, int flags) 363static int check_export(struct inode *inode, int flags, unsigned char *uuid)
367{ 364{
368 365
369 /* We currently export only dirs and regular files. 366 /* We currently export only dirs and regular files.
@@ -376,12 +373,13 @@ static int check_export(struct inode *inode, int flags)
376 /* There are two requirements on a filesystem to be exportable. 373 /* There are two requirements on a filesystem to be exportable.
377 * 1: We must be able to identify the filesystem from a number. 374 * 1: We must be able to identify the filesystem from a number.
378 * either a device number (so FS_REQUIRES_DEV needed) 375 * either a device number (so FS_REQUIRES_DEV needed)
379 * or an FSID number (so NFSEXP_FSID needed). 376 * or an FSID number (so NFSEXP_FSID or ->uuid is needed).
380 * 2: We must be able to find an inode from a filehandle. 377 * 2: We must be able to find an inode from a filehandle.
381 * This means that s_export_op must be set. 378 * This means that s_export_op must be set.
382 */ 379 */
383 if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) && 380 if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) &&
384 !(flags & NFSEXP_FSID)) { 381 !(flags & NFSEXP_FSID) &&
382 uuid == NULL) {
385 dprintk("exp_export: export of non-dev fs without fsid\n"); 383 dprintk("exp_export: export of non-dev fs without fsid\n");
386 return -EINVAL; 384 return -EINVAL;
387 } 385 }
@@ -406,10 +404,6 @@ fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc)
406 int len; 404 int len;
407 int migrated, i, err; 405 int migrated, i, err;
408 406
409 len = qword_get(mesg, buf, PAGE_SIZE);
410 if (len != 5 || memcmp(buf, "fsloc", 5))
411 return 0;
412
413 /* listsize */ 407 /* listsize */
414 err = get_int(mesg, &fsloc->locations_count); 408 err = get_int(mesg, &fsloc->locations_count);
415 if (err) 409 if (err)
@@ -520,6 +514,8 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
520 exp.ex_fslocs.locations_count = 0; 514 exp.ex_fslocs.locations_count = 0;
521 exp.ex_fslocs.migrated = 0; 515 exp.ex_fslocs.migrated = 0;
522 516
517 exp.ex_uuid = NULL;
518
523 /* flags */ 519 /* flags */
524 err = get_int(&mesg, &an_int); 520 err = get_int(&mesg, &an_int);
525 if (err == -ENOENT) 521 if (err == -ENOENT)
@@ -543,12 +539,33 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
543 if (err) goto out; 539 if (err) goto out;
544 exp.ex_fsid = an_int; 540 exp.ex_fsid = an_int;
545 541
546 err = check_export(nd.dentry->d_inode, exp.ex_flags); 542 while ((len = qword_get(&mesg, buf, PAGE_SIZE)) > 0) {
547 if (err) goto out; 543 if (strcmp(buf, "fsloc") == 0)
544 err = fsloc_parse(&mesg, buf, &exp.ex_fslocs);
545 else if (strcmp(buf, "uuid") == 0) {
546 /* expect a 16 byte uuid encoded as \xXXXX... */
547 len = qword_get(&mesg, buf, PAGE_SIZE);
548 if (len != 16)
549 err = -EINVAL;
550 else {
551 exp.ex_uuid =
552 kmemdup(buf, 16, GFP_KERNEL);
553 if (exp.ex_uuid == NULL)
554 err = -ENOMEM;
555 }
556 } else
557 /* quietly ignore unknown words and anything
558 * following. Newer user-space can try to set
559 * new values, then see what the result was.
560 */
561 break;
562 if (err)
563 goto out;
564 }
548 565
549 err = fsloc_parse(&mesg, buf, &exp.ex_fslocs); 566 err = check_export(nd.dentry->d_inode, exp.ex_flags,
550 if (err) 567 exp.ex_uuid);
551 goto out; 568 if (err) goto out;
552 } 569 }
553 570
554 expp = svc_export_lookup(&exp); 571 expp = svc_export_lookup(&exp);
@@ -562,6 +579,8 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
562 else 579 else
563 exp_put(expp); 580 exp_put(expp);
564 out: 581 out:
582 nfsd4_fslocs_free(&exp.ex_fslocs);
583 kfree(exp.ex_uuid);
565 kfree(exp.ex_path); 584 kfree(exp.ex_path);
566 if (nd.dentry) 585 if (nd.dentry)
567 path_release(&nd); 586 path_release(&nd);
@@ -591,9 +610,19 @@ static int svc_export_show(struct seq_file *m,
591 seq_escape(m, exp->ex_client->name, " \t\n\\"); 610 seq_escape(m, exp->ex_client->name, " \t\n\\");
592 seq_putc(m, '('); 611 seq_putc(m, '(');
593 if (test_bit(CACHE_VALID, &h->flags) && 612 if (test_bit(CACHE_VALID, &h->flags) &&
594 !test_bit(CACHE_NEGATIVE, &h->flags)) 613 !test_bit(CACHE_NEGATIVE, &h->flags)) {
595 exp_flags(m, exp->ex_flags, exp->ex_fsid, 614 exp_flags(m, exp->ex_flags, exp->ex_fsid,
596 exp->ex_anon_uid, exp->ex_anon_gid, &exp->ex_fslocs); 615 exp->ex_anon_uid, exp->ex_anon_gid, &exp->ex_fslocs);
616 if (exp->ex_uuid) {
617 int i;
618 seq_puts(m, ",uuid=");
619 for (i=0; i<16; i++) {
620 if ((i&3) == 0 && i)
621 seq_putc(m, ':');
622 seq_printf(m, "%02x", exp->ex_uuid[i]);
623 }
624 }
625 }
597 seq_puts(m, ")\n"); 626 seq_puts(m, ")\n");
598 return 0; 627 return 0;
599} 628}
@@ -630,6 +659,8 @@ static void export_update(struct cache_head *cnew, struct cache_head *citem)
630 new->ex_anon_uid = item->ex_anon_uid; 659 new->ex_anon_uid = item->ex_anon_uid;
631 new->ex_anon_gid = item->ex_anon_gid; 660 new->ex_anon_gid = item->ex_anon_gid;
632 new->ex_fsid = item->ex_fsid; 661 new->ex_fsid = item->ex_fsid;
662 new->ex_uuid = item->ex_uuid;
663 item->ex_uuid = NULL;
633 new->ex_path = item->ex_path; 664 new->ex_path = item->ex_path;
634 item->ex_path = NULL; 665 item->ex_path = NULL;
635 new->ex_fslocs.locations = item->ex_fslocs.locations; 666 new->ex_fslocs.locations = item->ex_fslocs.locations;
@@ -752,11 +783,11 @@ exp_get_key(svc_client *clp, dev_t dev, ino_t ino)
752 u32 fsidv[3]; 783 u32 fsidv[3];
753 784
754 if (old_valid_dev(dev)) { 785 if (old_valid_dev(dev)) {
755 mk_fsid_v0(fsidv, dev, ino); 786 mk_fsid(FSID_DEV, fsidv, dev, ino, 0, NULL);
756 return exp_find_key(clp, 0, fsidv, NULL); 787 return exp_find_key(clp, FSID_DEV, fsidv, NULL);
757 } 788 }
758 mk_fsid_v3(fsidv, dev, ino); 789 mk_fsid(FSID_ENCODE_DEV, fsidv, dev, ino, 0, NULL);
759 return exp_find_key(clp, 3, fsidv, NULL); 790 return exp_find_key(clp, FSID_ENCODE_DEV, fsidv, NULL);
760} 791}
761 792
762/* 793/*
@@ -767,9 +798,9 @@ exp_get_fsid_key(svc_client *clp, int fsid)
767{ 798{
768 u32 fsidv[2]; 799 u32 fsidv[2];
769 800
770 mk_fsid_v1(fsidv, fsid); 801 mk_fsid(FSID_NUM, fsidv, 0, 0, fsid, NULL);
771 802
772 return exp_find_key(clp, 1, fsidv, NULL); 803 return exp_find_key(clp, FSID_NUM, fsidv, NULL);
773} 804}
774 805
775svc_export * 806svc_export *
@@ -883,8 +914,8 @@ static int exp_fsid_hash(svc_client *clp, struct svc_export *exp)
883 if ((exp->ex_flags & NFSEXP_FSID) == 0) 914 if ((exp->ex_flags & NFSEXP_FSID) == 0)
884 return 0; 915 return 0;
885 916
886 mk_fsid_v1(fsid, exp->ex_fsid); 917 mk_fsid(FSID_NUM, fsid, 0, 0, exp->ex_fsid, NULL);
887 return exp_set_key(clp, 1, fsid, exp); 918 return exp_set_key(clp, FSID_NUM, fsid, exp);
888} 919}
889 920
890static int exp_hash(struct auth_domain *clp, struct svc_export *exp) 921static int exp_hash(struct auth_domain *clp, struct svc_export *exp)
@@ -894,11 +925,11 @@ static int exp_hash(struct auth_domain *clp, struct svc_export *exp)
894 dev_t dev = inode->i_sb->s_dev; 925 dev_t dev = inode->i_sb->s_dev;
895 926
896 if (old_valid_dev(dev)) { 927 if (old_valid_dev(dev)) {
897 mk_fsid_v0(fsid, dev, inode->i_ino); 928 mk_fsid(FSID_DEV, fsid, dev, inode->i_ino, 0, NULL);
898 return exp_set_key(clp, 0, fsid, exp); 929 return exp_set_key(clp, FSID_DEV, fsid, exp);
899 } 930 }
900 mk_fsid_v3(fsid, dev, inode->i_ino); 931 mk_fsid(FSID_ENCODE_DEV, fsid, dev, inode->i_ino, 0, NULL);
901 return exp_set_key(clp, 3, fsid, exp); 932 return exp_set_key(clp, FSID_ENCODE_DEV, fsid, exp);
902} 933}
903 934
904static void exp_unhash(struct svc_export *exp) 935static void exp_unhash(struct svc_export *exp)
@@ -977,7 +1008,7 @@ exp_export(struct nfsctl_export *nxp)
977 goto finish; 1008 goto finish;
978 } 1009 }
979 1010
980 err = check_export(nd.dentry->d_inode, nxp->ex_flags); 1011 err = check_export(nd.dentry->d_inode, nxp->ex_flags, NULL);
981 if (err) goto finish; 1012 if (err) goto finish;
982 1013
983 err = -ENOMEM; 1014 err = -ENOMEM;
@@ -1170,9 +1201,9 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
1170 __be32 rv; 1201 __be32 rv;
1171 u32 fsidv[2]; 1202 u32 fsidv[2];
1172 1203
1173 mk_fsid_v1(fsidv, 0); 1204 mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);
1174 1205
1175 exp = exp_find(clp, 1, fsidv, creq); 1206 exp = exp_find(clp, FSID_NUM, fsidv, creq);
1176 if (IS_ERR(exp)) 1207 if (IS_ERR(exp))
1177 return nfserrno(PTR_ERR(exp)); 1208 return nfserrno(PTR_ERR(exp));
1178 if (exp == NULL) 1209 if (exp == NULL)