[PATCH] knfsd: nfsd4: fslocations data structures
Define FS locations structures, some functions to manipulate them, and add code to parse FS locations in downcall and add to the exports structure. [bfields@fieldses.org: bunch of fixes and cleanups] Signed-off-by: Manoj Naik <manoj@almaden.ibm.com> Signed-off-by: Fred Isaman <iisaman@citi.umich.edu> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Родитель
b009a873de
Коммит
933469190e
118
fs/nfsd/export.c
118
fs/nfsd/export.c
|
@ -319,6 +319,17 @@ svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old)
|
|||
|
||||
static struct cache_head *export_table[EXPORT_HASHMAX];
|
||||
|
||||
static void nfsd4_fslocs_free(struct nfsd4_fs_locations *fsloc)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < fsloc->locations_count; i++) {
|
||||
kfree(fsloc->locations[i].path);
|
||||
kfree(fsloc->locations[i].hosts);
|
||||
}
|
||||
kfree(fsloc->locations);
|
||||
}
|
||||
|
||||
static void svc_export_put(struct kref *ref)
|
||||
{
|
||||
struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
|
||||
|
@ -326,6 +337,7 @@ static void svc_export_put(struct kref *ref)
|
|||
mntput(exp->ex_mnt);
|
||||
auth_domain_put(exp->ex_client);
|
||||
kfree(exp->ex_path);
|
||||
nfsd4_fslocs_free(&exp->ex_fslocs);
|
||||
kfree(exp);
|
||||
}
|
||||
|
||||
|
@ -387,6 +399,69 @@ static int check_export(struct inode *inode, int flags)
|
|||
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NFSD_V4
|
||||
|
||||
static int
|
||||
fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc)
|
||||
{
|
||||
int len;
|
||||
int migrated, i, err;
|
||||
|
||||
len = qword_get(mesg, buf, PAGE_SIZE);
|
||||
if (len != 5 || memcmp(buf, "fsloc", 5))
|
||||
return 0;
|
||||
|
||||
/* listsize */
|
||||
err = get_int(mesg, &fsloc->locations_count);
|
||||
if (err)
|
||||
return err;
|
||||
if (fsloc->locations_count > MAX_FS_LOCATIONS)
|
||||
return -EINVAL;
|
||||
if (fsloc->locations_count == 0)
|
||||
return 0;
|
||||
|
||||
fsloc->locations = kzalloc(fsloc->locations_count
|
||||
* sizeof(struct nfsd4_fs_location), GFP_KERNEL);
|
||||
if (!fsloc->locations)
|
||||
return -ENOMEM;
|
||||
for (i=0; i < fsloc->locations_count; i++) {
|
||||
/* colon separated host list */
|
||||
err = -EINVAL;
|
||||
len = qword_get(mesg, buf, PAGE_SIZE);
|
||||
if (len <= 0)
|
||||
goto out_free_all;
|
||||
err = -ENOMEM;
|
||||
fsloc->locations[i].hosts = kstrdup(buf, GFP_KERNEL);
|
||||
if (!fsloc->locations[i].hosts)
|
||||
goto out_free_all;
|
||||
err = -EINVAL;
|
||||
/* slash separated path component list */
|
||||
len = qword_get(mesg, buf, PAGE_SIZE);
|
||||
if (len <= 0)
|
||||
goto out_free_all;
|
||||
err = -ENOMEM;
|
||||
fsloc->locations[i].path = kstrdup(buf, GFP_KERNEL);
|
||||
if (!fsloc->locations[i].path)
|
||||
goto out_free_all;
|
||||
}
|
||||
/* migrated */
|
||||
err = get_int(mesg, &migrated);
|
||||
if (err)
|
||||
goto out_free_all;
|
||||
err = -EINVAL;
|
||||
if (migrated < 0 || migrated > 1)
|
||||
goto out_free_all;
|
||||
fsloc->migrated = migrated;
|
||||
return 0;
|
||||
out_free_all:
|
||||
nfsd4_fslocs_free(fsloc);
|
||||
return err;
|
||||
}
|
||||
|
||||
#else /* CONFIG_NFSD_V4 */
|
||||
static inline int fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc) { return 0; }
|
||||
#endif
|
||||
|
||||
static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
|
||||
{
|
||||
/* client path expiry [flags anonuid anongid fsid] */
|
||||
|
@ -441,6 +516,11 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
|
|||
if (exp.h.expiry_time == 0)
|
||||
goto out;
|
||||
|
||||
/* fs locations */
|
||||
exp.ex_fslocs.locations = NULL;
|
||||
exp.ex_fslocs.locations_count = 0;
|
||||
exp.ex_fslocs.migrated = 0;
|
||||
|
||||
/* flags */
|
||||
err = get_int(&mesg, &an_int);
|
||||
if (err == -ENOENT)
|
||||
|
@ -466,6 +546,10 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
|
|||
|
||||
err = check_export(nd.dentry->d_inode, exp.ex_flags);
|
||||
if (err) goto out;
|
||||
|
||||
err = fsloc_parse(&mesg, buf, &exp.ex_fslocs);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
expp = svc_export_lookup(&exp);
|
||||
|
@ -489,7 +573,8 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
|
|||
return err;
|
||||
}
|
||||
|
||||
static void exp_flags(struct seq_file *m, int flag, int fsid, uid_t anonu, uid_t anong);
|
||||
static void exp_flags(struct seq_file *m, int flag, int fsid,
|
||||
uid_t anonu, uid_t anong, struct nfsd4_fs_locations *fslocs);
|
||||
|
||||
static int svc_export_show(struct seq_file *m,
|
||||
struct cache_detail *cd,
|
||||
|
@ -508,8 +593,8 @@ static int svc_export_show(struct seq_file *m,
|
|||
seq_putc(m, '(');
|
||||
if (test_bit(CACHE_VALID, &h->flags) &&
|
||||
!test_bit(CACHE_NEGATIVE, &h->flags))
|
||||
exp_flags(m, exp->ex_flags, exp->ex_fsid,
|
||||
exp->ex_anon_uid, exp->ex_anon_gid);
|
||||
exp_flags(m, exp->ex_flags, exp->ex_fsid,
|
||||
exp->ex_anon_uid, exp->ex_anon_gid, &exp->ex_fslocs);
|
||||
seq_puts(m, ")\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -532,6 +617,9 @@ static void svc_export_init(struct cache_head *cnew, struct cache_head *citem)
|
|||
new->ex_dentry = dget(item->ex_dentry);
|
||||
new->ex_mnt = mntget(item->ex_mnt);
|
||||
new->ex_path = NULL;
|
||||
new->ex_fslocs.locations = NULL;
|
||||
new->ex_fslocs.locations_count = 0;
|
||||
new->ex_fslocs.migrated = 0;
|
||||
}
|
||||
|
||||
static void export_update(struct cache_head *cnew, struct cache_head *citem)
|
||||
|
@ -545,6 +633,12 @@ static void export_update(struct cache_head *cnew, struct cache_head *citem)
|
|||
new->ex_fsid = item->ex_fsid;
|
||||
new->ex_path = item->ex_path;
|
||||
item->ex_path = NULL;
|
||||
new->ex_fslocs.locations = item->ex_fslocs.locations;
|
||||
item->ex_fslocs.locations = NULL;
|
||||
new->ex_fslocs.locations_count = item->ex_fslocs.locations_count;
|
||||
item->ex_fslocs.locations_count = 0;
|
||||
new->ex_fslocs.migrated = item->ex_fslocs.migrated;
|
||||
item->ex_fslocs.migrated = 0;
|
||||
}
|
||||
|
||||
static struct cache_head *svc_export_alloc(void)
|
||||
|
@ -1159,7 +1253,8 @@ static struct flags {
|
|||
{ 0, {"", ""}}
|
||||
};
|
||||
|
||||
static void exp_flags(struct seq_file *m, int flag, int fsid, uid_t anonu, uid_t anong)
|
||||
static void exp_flags(struct seq_file *m, int flag, int fsid,
|
||||
uid_t anonu, uid_t anong, struct nfsd4_fs_locations *fsloc)
|
||||
{
|
||||
int first = 0;
|
||||
struct flags *flg;
|
||||
|
@ -1175,6 +1270,21 @@ static void exp_flags(struct seq_file *m, int flag, int fsid, uid_t anonu, uid_t
|
|||
seq_printf(m, "%sanonuid=%d", first++?",":"", anonu);
|
||||
if (anong != (gid_t)-2 && anong != (0x10000-2))
|
||||
seq_printf(m, "%sanongid=%d", first++?",":"", anong);
|
||||
if (fsloc && fsloc->locations_count > 0) {
|
||||
char *loctype = (fsloc->migrated) ? "refer" : "replicas";
|
||||
int i;
|
||||
|
||||
seq_printf(m, "%s%s=", first++?",":"", loctype);
|
||||
seq_escape(m, fsloc->locations[0].path, ",;@ \t\n\\");
|
||||
seq_putc(m, '@');
|
||||
seq_escape(m, fsloc->locations[0].hosts, ",;@ \t\n\\");
|
||||
for (i = 1; i < fsloc->locations_count; i++) {
|
||||
seq_putc(m, ';');
|
||||
seq_escape(m, fsloc->locations[i].path, ",;@ \t\n\\");
|
||||
seq_putc(m, '@');
|
||||
seq_escape(m, fsloc->locations[i].hosts, ",;@ \t\n\\");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int e_show(struct seq_file *m, void *p)
|
||||
|
|
|
@ -45,6 +45,25 @@
|
|||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/*
|
||||
* FS Locations
|
||||
*/
|
||||
|
||||
#define MAX_FS_LOCATIONS 128
|
||||
|
||||
struct nfsd4_fs_location {
|
||||
char *hosts; /* colon separated list of hosts */
|
||||
char *path; /* slash separated list of path components */
|
||||
};
|
||||
|
||||
struct nfsd4_fs_locations {
|
||||
uint32_t locations_count;
|
||||
struct nfsd4_fs_location *locations;
|
||||
/* If we're not actually serving this data ourselves (only providing a
|
||||
* list of replicas that do serve it) then we set "migrated": */
|
||||
int migrated;
|
||||
};
|
||||
|
||||
struct svc_export {
|
||||
struct cache_head h;
|
||||
struct auth_domain * ex_client;
|
||||
|
@ -55,6 +74,7 @@ struct svc_export {
|
|||
uid_t ex_anon_uid;
|
||||
gid_t ex_anon_gid;
|
||||
int ex_fsid;
|
||||
struct nfsd4_fs_locations ex_fslocs;
|
||||
};
|
||||
|
||||
/* an "export key" (expkey) maps a filehandlefragement to an
|
||||
|
|
Загрузка…
Ссылка в новой задаче