Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 93346919 authored by Manoj Naik's avatar Manoj Naik Committed by Linus Torvalds
Browse files

[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: default avatarManoj Naik <manoj@almaden.ibm.com>
Signed-off-by: default avatarFred Isaman <iisaman@citi.umich.edu>
Signed-off-by: default avatarJ. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: default avatarNeil Brown <neilb@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent b009a873
Loading
Loading
Loading
Loading
+114 −4
Original line number Diff line number Diff line
@@ -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,
@@ -509,7 +594,7 @@ static int svc_export_show(struct seq_file *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->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)
+20 −0
Original line number Diff line number Diff line
@@ -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