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