Skip to content

Commit

Permalink
[PATCH] knfsd: nfsd4: fslocations data structures
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Manoj Naik authored and Linus Torvalds committed Oct 4, 2006
1 parent b009a87 commit 9334691
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 4 deletions.
118 changes: 114 additions & 4 deletions fs/nfsd/export.c
Original file line number Diff line number Diff line change
Expand Up @@ -319,13 +319,25 @@ 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);
dput(exp->ex_dentry);
mntput(exp->ex_mnt);
auth_domain_put(exp->ex_client);
kfree(exp->ex_path);
nfsd4_fslocs_free(&exp->ex_fslocs);
kfree(exp);
}

Expand Down Expand Up @@ -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] */
Expand Down Expand Up @@ -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)
Expand All @@ -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);
Expand All @@ -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,
Expand All @@ -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;
}
Expand All @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand Down
20 changes: 20 additions & 0 deletions include/linux/nfsd/export.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand Down

0 comments on commit 9334691

Please sign in to comment.