[pnfs] [PATCH 2/6] 2.6-latest-pnfs-client-draft-13-device-decode
andros at umich.edu
andros at umich.edu
Fri Oct 19 14:13:18 EDT 2007
From: Andy Adamson <andros at umich.edu>
Update the decoding of device_addr4 to draft-13. Used by GETDEVICELIST and
GETDEVICEINFO.
Add a list of data servers to nfs4_pnfs_dev_hlist and use for all
stripes (deviceID's).
Note: nfs4_pnfs_device_get() will be updated in a following patch
Signed-off by: Andy Adamson<andros at umich.edu>
---
fs/nfs/nfs4_fs.h | 2 +-
fs/nfs/nfs4filelayout.c | 32 +++--
fs/nfs/nfs4filelayout.h | 41 ++++--
fs/nfs/nfs4filelayoutdev.c | 348 ++++++++++++++++++++++++++++++++++----------
fs/nfs/nfs4proc.c | 11 +-
fs/nfs/super.c | 3 +-
include/linux/nfs_fs_sb.h | 9 +-
7 files changed, 332 insertions(+), 114 deletions(-)
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 1a0f0a3..8a010c4 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -199,7 +199,7 @@ extern struct nfs4_state_recovery_ops *nfs4_network_partition_recovery_ops[];
#ifdef CONFIG_NFS_V4_1
extern void nfs4_put_session(struct nfs4_session **session);
extern struct nfs4_session *nfs4_alloc_session(void);
-extern int nfs4_proc_destroy_session(struct nfs_server *sp);
+extern int nfs4_proc_destroy_session(struct nfs4_session *, struct rpc_clnt *);
#endif /* CONFIG_NFS_V4_1 */
extern const u32 nfs4_fattr_bitmap[2];
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index ef3f107..563ede4 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -153,7 +153,7 @@ error_ret: ;
int
filelayout_uninitialize_mountpoint(struct pnfs_mount_type* mountid)
{
-struct filelayout_mount_type* fl_mt = NULL;
+ struct filelayout_mount_type* fl_mt = NULL;
if (mountid)
fl_mt = (struct filelayout_mount_type*)mountid->mountid;
@@ -291,8 +291,11 @@ ssize_t filelayout_read_pagelist(
status = 0;
}
else {
- data->pnfs_client = dserver.dev_item->server->client;
- data->session = dserver.dev_item->server->session;
+ struct nfs4_pnfs_ds *ds = dserver.dev->ds_list[0];
+
+ /* just try the first data server for the index..*/
+ data->pnfs_client = ds->ds_clp->cl_rpcclient;
+ data->session = ds->ds_clp->cl_ds_session;
data->args.fh = dserver.fh;
/* Now get the file offset on the dserver
@@ -361,15 +364,17 @@ ssize_t filelayout_write_pagelist(
&dserver);
/* ANDROS: XXX should fail if no data server */
if(!status) {
- data->pnfs_client = dserver.dev_item->server->client;
- data->session = dserver.dev_item->server->session;
+ struct nfs4_pnfs_ds *ds = dserver.dev->ds_list[0];
+
+ /* just try the first data server for the index.. */
+ data->pnfs_client = ds->ds_clp->cl_rpcclient;
+ data->session = ds->ds_clp->cl_ds_session;
data->args.fh = dserver.fh;
}
- dprintk("%s set wb_devid %d\n", __FUNCTION__,
- dserver.dev_item[0].dev_id);
+ dprintk("%s set wb_devid %d\n", __FUNCTION__, dserver.dev_id);
list_for_each(h, &data->pages) {
req = list_entry(h, struct nfs_page, wb_list);
- req->wb_devid = dserver.dev_item[0].dev_id;
+ req->wb_devid = dserver.dev_id;
}
/* Now get the file offset on the dserver
@@ -512,6 +517,7 @@ filelayout_commit(struct pnfs_layout_type * layoutid, struct inode* ino, struct
struct pnfs_layout_type* laytype;
struct nfs4_filelayout* nfslay;
struct nfs4_pnfs_dserver dserver;
+ struct nfs4_pnfs_ds *ds;
struct nfs_page* first;
struct nfs_page* req;
struct list_head *pos, *tmp;
@@ -544,8 +550,8 @@ filelayout_commit(struct pnfs_layout_type * layoutid, struct inode* ino, struct
}
if (!dsdata)
goto out_bad;
- dserver.dev_item = nfs4_pnfs_device_get(ino, dev_id);
- if (dserver.dev_item == NULL) {
+ dserver.dev = nfs4_pnfs_device_get(ino, dev_id);
+ if (dserver.dev == NULL) {
return 1;
}
list_for_each_safe(pos, tmp, &data->pages) {
@@ -569,8 +575,10 @@ filelayout_commit(struct pnfs_layout_type * layoutid, struct inode* ino, struct
dprintk("%s call nfs_commit_rpcsetup i %d devid %d\n",
__FUNCTION__, i, dev_id);
- dsdata->pnfs_client = dserver.dev_item->server->client;
- dsdata->session = dserver.dev_item->server->session;
+ /* just try the first data server for the index.. */
+ ds = dserver.dev->ds_list[0];
+ dsdata->pnfs_client = ds->ds_clp->cl_rpcclient;
+ dsdata->session = ds->ds_clp->cl_ds_session;
nfs_commit_rpcsetup(dsdata, sync);
diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h
index 7045876..ab7f716 100644
--- a/fs/nfs/nfs4filelayout.h
+++ b/fs/nfs/nfs4filelayout.h
@@ -18,31 +18,43 @@
#define NFS4_PNFS_DEV_HASH_BITS 5
#define NFS4_PNFS_DEV_HASH (1 << NFS4_PNFS_DEV_HASH_BITS)
-#define NFS4_PNFS_MAX_DEVS 16
+#define NFS4_PNFS_MAX_STRIPE_CNT 16
+#define NFS4_PNFS_MAX_MULTI_DS 2
struct nfs4_session *nfs41_alloc_session(void);
int _nfs4_proc_create_session(struct nfs_client *clp, struct nfs4_session *session,
struct rpc_clnt *clnt);
-int _nfs4_proc_destroy_session(struct nfs4_session **session, struct rpc_clnt *clnt);
-
enum stripetype4 {
STRIPE_SPARSE = 1,
STRIPE_DENSE = 2
};
+struct nfs4_pnfs_ds {
+ struct hlist_node ds_node; /* nfs4_pnfs_dev_hlist dev_dslist */
+ u32 ds_ip_addr;
+ u32 ds_port;
+ struct nfs_client *ds_clp;
+ atomic_t ds_count;
+};
+
+struct nfs4_pnfs_dev {
+ u32 stripe_index;
+ int num_ds;
+ struct nfs4_pnfs_ds *ds_list[NFS4_PNFS_MAX_MULTI_DS];
+};
+
+/* stripe_count is length of dev_list, bounded by NFS4_PNFS_MAX_STRIPE_CNT */
struct nfs4_pnfs_dev_item {
- struct hlist_node hash_node;
- u32 dev_id;
- u32 ip_addr;
- u32 port;
- atomic_t count;
-/* struct nfs_client *clp; */
- struct nfs_server *server;
+ struct hlist_node hash_node; /* nfs4_pnfs_dev_hlist dev_list */
+ u32 dev_id;
+ u32 stripe_count;
+ struct nfs4_pnfs_dev *stripe_devs;
};
struct nfs4_pnfs_dev_hlist {
- rwlock_t dev_lock;
- struct hlist_head dev_list[NFS4_PNFS_DEV_HASH];
+ rwlock_t dev_lock;
+ struct hlist_head dev_list[NFS4_PNFS_DEV_HASH];
+ struct hlist_head dev_dslist[NFS4_PNFS_DEV_HASH];
};
struct nfs4_pnfs_devaddr {
@@ -58,7 +70,8 @@ struct nfs4_pnfs_devlist {
struct nfs4_pnfs_dserver {
struct nfs_fh *fh;
- struct nfs4_pnfs_dev_item *dev_item;
+ struct nfs4_pnfs_dev *dev;
+ u32 dev_id;
};
struct nfs4_filelayout_devs {
@@ -79,7 +92,7 @@ struct nfs4_filelayout {
u64 stripe_unit;
unsigned int index_len;
unsigned int num_devs;
- struct nfs4_filelayout_devs devs[NFS4_PNFS_MAX_DEVS];
+ struct nfs4_filelayout_devs devs[NFS4_PNFS_MAX_STRIPE_CNT];
};
struct filelayout_mount_type {
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c
index 117ec33..da462e4 100644
--- a/fs/nfs/nfs4filelayoutdev.c
+++ b/fs/nfs/nfs4filelayoutdev.c
@@ -63,6 +63,38 @@ create_nfs_rpcclient(struct rpc_xprt *xprt,
rpc_authflavor_t authflavor,
int *err);
+void
+print_ds_list(struct nfs4_pnfs_dev *fdev)
+{
+ struct nfs4_pnfs_ds *ds;
+ int i;
+
+ ds = fdev->ds_list[0];
+ for (i = 0; i < fdev->num_ds; i++) {
+ dprintk(" ip_addr %x\n", ntohl(ds->ds_ip_addr));
+ dprintk(" port %hu\n", ntohs(ds->ds_port));
+ dprintk(" client %p\n", ds->ds_clp);
+ dprintk(" cl_exchange_flags %x\n",
+ ds->ds_clp->cl_exchange_flags);
+ ds++;
+ }
+}
+
+void
+print_stripe_devs(struct nfs4_pnfs_dev_item *dev)
+{
+ struct nfs4_pnfs_dev *fdev;
+ int i;
+
+ fdev = &dev->stripe_devs[0];
+ for (i = 0; i < dev->stripe_count; i++) {
+ dprintk(" stripe_index %u\n", fdev->stripe_index);
+ dprintk(" num_ds %d\n", fdev->num_ds);
+ print_ds_list(fdev);
+ fdev++;
+ }
+}
+
/* Assumes lock is held */
static inline struct nfs4_pnfs_dev_item *
_device_lookup(struct nfs4_pnfs_dev_hlist *hlist, u32 dev_id)
@@ -85,33 +117,74 @@ _device_lookup(struct nfs4_pnfs_dev_hlist *hlist, u32 dev_id)
}
/* Assumes lock is held */
+static inline struct nfs4_pnfs_ds *
+_data_server_lookup(struct nfs4_pnfs_dev_hlist *hlist, u32 ip_addr, u32 port)
+{
+ unsigned long hash;
+ struct hlist_node *np;
+
+ dprintk("_data_server_lookup: ip_addr=%x port=%hu\n",
+ ntohl(ip_addr), ntohs(port));
+
+ hash = hash_long(ip_addr, NFS4_PNFS_DEV_HASH_BITS);
+
+ hlist_for_each(np, &hlist->dev_dslist[hash]) {
+ struct nfs4_pnfs_ds *ds;
+ ds = hlist_entry(np, struct nfs4_pnfs_ds, ds_node);
+ if (ds->ds_ip_addr == ip_addr &&
+ ds->ds_port == port) {
+ return ds;
+ }
+ }
+ return NULL;
+}
+
+
+/* Assumes lock is held */
static inline void
_device_add(struct nfs4_pnfs_dev_hlist *hlist, struct nfs4_pnfs_dev_item *dev)
{
unsigned long hash;
- dprintk("_device_add: dev_id=%u, ip=%x, port=%hu\n", dev->dev_id,
- ntohl(dev->ip_addr), ntohs(dev->port));
+ dprintk("_device_add: dev_id=%u stripe_devs:\n", dev->dev_id);
+ print_stripe_devs(dev);
hash = hash_long(dev->dev_id, NFS4_PNFS_DEV_HASH_BITS);
hlist_add_head(&dev->hash_node, &hlist->dev_list[hash]);
}
-/* Create an rpc to the data server defined in 'dev' */
+/* Assumes lock is held */
+static inline void
+_data_server_add(struct nfs4_pnfs_dev_hlist *hlist, struct nfs4_pnfs_ds *ds)
+{
+ unsigned long hash;
+
+ dprintk("_data_server_add: ip_addr=%x port=%hu\n",
+ ntohl(ds->ds_ip_addr), ntohs(ds->ds_port));
+
+ hash = hash_long(ds->ds_ip_addr, NFS4_PNFS_DEV_HASH_BITS);
+ hlist_add_head(&ds->ds_node, &hlist->dev_dslist[hash]);
+}
+
+/* Create an rpc to the data server defined in 'dev_list' */
static int
-device_create(struct rpc_clnt *mds_rpc, struct nfs4_pnfs_dev_item *dev)
+device_create(struct rpc_clnt *mds_rpc, struct nfs4_pnfs_dev *dev)
{
//struct rpc_clnt *clnt;
//struct rpc_xprt *xprt;
+ struct nfs4_pnfs_ds *ds;
struct sockaddr_in sin;
int err = 0;
+ /* just use the first ds in ds list...*/
+ ds = dev->ds_list[0];
+
sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = dev->ip_addr;
- sin.sin_port = dev->port;
+ sin.sin_addr.s_addr = ds->ds_ip_addr;
+ sin.sin_port = ds->ds_port;
- dprintk("device_create: dev_id=%u, ip=%x, port=%hu, rpcclient %p\n",
- dev->dev_id, ntohl(dev->ip_addr), ntohs(dev->port), mds_rpc);
+ dprintk("device_create: ip=%x, port=%hu, rpcclient %p\n",
+ ntohl(ds->ds_ip_addr), ntohs(ds->ds_port), mds_rpc);
/*
* XXX Need to implement.
@@ -137,28 +210,63 @@ out:
return err;
}
+/* Assumes lock is held */
+static int
+unhash_ds(struct nfs4_pnfs_ds *ds)
+{
+
+ if (!atomic_dec_and_test(&ds->ds_count))
+ return 0;
+
+ hlist_del_init(&ds->ds_node);
+ return 1;
+}
+
static void
-device_destroy(struct nfs4_pnfs_dev_item *dev)
+destroy_ds(struct nfs4_pnfs_ds *ds)
{
+ nfs4_proc_destroy_session(ds->ds_clp->cl_ds_session,
+ ds->ds_clp->cl_rpcclient);
+ rpc_shutdown_client(ds->ds_clp->cl_rpcclient);
+ ds->ds_clp->cl_rpcclient = NULL;
+ kfree(ds);
+}
+
+/* Assumes lock is NOT held */
+static void
+device_destroy(struct nfs4_pnfs_dev_item *dev, struct nfs4_pnfs_dev_hlist *hlist )
+{
+ struct nfs4_pnfs_dev *fdev;
+ struct nfs4_pnfs_ds *ds;
+ HLIST_HEAD(release);
+ struct hlist_node *np;
+ int i, j;
+
if (!dev)
return;
- dprintk("device_destroy: did=%u, ip=%x, port=%hu, rpcclient %p flags %x\n",
- dev->dev_id, ntohl(dev->ip_addr), ntohs(dev->port),
- dev->server->client,
- dev->server->nfs_client->cl_exchange_flags);
-
- /* if not created for DS just return */
- if (dev->server->nfs_client->cl_exchange_flags &
- EXCHGID4_FLAG_USE_PNFS_DS &&
- !(dev->server->nfs_client->cl_exchange_flags &
- EXCHGID4_FLAG_USE_PNFS_MDS)) {
- nfs4_proc_destroy_session(dev->server);
- // BUG_ON(!atomic_sub_and_test(0, &dev->count));
- rpc_shutdown_client(dev->server->client);
- dev->server->client = NULL;
- }
+ dprintk("device_destroy: did=%u dev_list: \n", dev->dev_id);
+ print_stripe_devs(dev);
+ write_lock(&hlist->dev_lock);
+ hlist_del_rcu(&dev->hash_node);
+
+ fdev = &dev->stripe_devs[0];
+ for (i =0; i < dev->stripe_count; i++) {
+ for (j = 0; j < fdev->num_ds; j++) {
+ ds = fdev->ds_list[j];
+ if (unhash_ds(ds)) {
+ hlist_add_head(&ds->ds_node, &release);
+ }
+ }
+ fdev++;
+ }
+ write_unlock(&hlist->dev_lock);
+ hlist_for_each(np, &release) {
+ ds = hlist_entry(np, struct nfs4_pnfs_ds, ds_node);
+ destroy_ds(ds);
+ }
+ kfree(dev->stripe_devs);
kfree(dev);
}
@@ -171,6 +279,7 @@ nfs4_pnfs_devlist_init(struct nfs4_pnfs_dev_hlist *hlist)
for (i = 0; i < NFS4_PNFS_DEV_HASH; i++) {
INIT_HLIST_HEAD(&hlist->dev_list[i]);
+ INIT_HLIST_HEAD(&hlist->dev_dslist[i]);
}
return 0;
@@ -194,8 +303,8 @@ nfs4_pnfs_devlist_destroy(struct nfs4_pnfs_dev_hlist *hlist)
hlist_for_each_safe(np, next, &hlist->dev_list[i]) {
struct nfs4_pnfs_dev_item *dev;
dev = hlist_entry(np, struct nfs4_pnfs_dev_item, hash_node);
- hlist_del_rcu(&dev->hash_node);
- device_destroy(dev);
+ /* device_destroy grabs hlist->dev_lock */
+ device_destroy(dev, hlist);
}
}
}
@@ -209,7 +318,6 @@ nfs4_pnfs_device_add(struct filelayout_mount_type *mt,
struct nfs4_pnfs_dev_item *dev)
{
struct nfs4_pnfs_dev_item *tmp_dev;
- int err;
struct nfs4_pnfs_dev_hlist *hlist = mt->hlist;
dprintk("nfs4_pnfs_device_add\n");
@@ -225,60 +333,61 @@ nfs4_pnfs_device_add(struct filelayout_mount_type *mt,
/* Cleanup, if device was recently added */
if (tmp_dev != NULL) {
dprintk(" device found, not adding (after creation)\n");
- device_destroy(dev);
+ device_destroy(dev, hlist);
}
return 0;
}
-/* Decode opaque device data and return the result
- */
-static struct nfs4_pnfs_dev_item*
-decode_device(struct pnfs_device* dev)
+static void
+nfs4_pnfs_ds_add(struct filelayout_mount_type *mt, struct nfs4_pnfs_ds **dsp, u32 ip_addr, u32 port)
{
- int index, i, j, len;
- int tmp[6];
- uint32_t *p = (uint32_t*)dev->dev_addr_buf;
- struct nfs4_pnfs_dev_item* file_dev;
- char r_addr[29]; /* max size of ip/port string */
-
- if ((file_dev = kmalloc(sizeof(struct nfs4_pnfs_dev_item), GFP_KERNEL)) == NULL)
- {
- return NULL;
- }
- /* Initialize dev */
- INIT_HLIST_NODE(&file_dev->hash_node);
- atomic_set(&file_dev->count, 0);
+ struct nfs4_pnfs_ds *tmp_ds, *ds;
+ struct nfs4_pnfs_dev_hlist *hlist = mt->hlist;
- /* Device id */
- file_dev->dev_id = dev->dev_id;
+ *dsp = NULL;
- READ32(index);
- for (i = 0; i < index; i++) { /* skip indices list */
- READ32(j);
- }
-
- READ32(len);
- BUG_ON(len != 1); /* 1 DS per device id */
+ ds = kzalloc(sizeof(*tmp_ds), GFP_KERNEL);
+ if (!ds)
+ return;
- /* Get the device count */
- READ32(dev->dev_count);
+ /* Initialize ds */
+ ds->ds_ip_addr = ip_addr;
+ ds->ds_port = port;
+ atomic_set(&ds->ds_count, 1);
+ INIT_HLIST_NODE(&ds->ds_node);
- if (dev->dev_count > 1)
- printk(KERN_NOTICE "%s: Add loop for multipath dev_count %d dev_id %d\n",
- __FUNCTION__, dev->dev_count, dev->dev_id);
+ write_lock(&hlist->dev_lock);
+ tmp_ds = _data_server_lookup(hlist, ip_addr, port);
+ if (tmp_ds == NULL) {
+ _data_server_add(hlist, ds);
+ *dsp = ds;
+ }
+ write_unlock(&hlist->dev_lock);
+ if (tmp_ds != NULL) {
+ dprintk(" data server found, not adding (after creation)\n");
+ destroy_ds(ds);
+ *dsp = tmp_ds;
+ }
- /* Decode contents of device*/
+}
- /* device addr -- r_netid, r_addr */
+static struct nfs4_pnfs_ds *
+decode_and_add_ds(uint32_t **pp, struct filelayout_mount_type *mt)
+{
+ struct nfs4_pnfs_ds *ds = NULL;
+ char r_addr[29]; /* max size of ip/port string */
+ int len;
+ u32 ip_addr, port;
+ int tmp[6];
+ uint32_t *p = *pp;
+ dprintk("%s enter\n", __FUNCTION__);
/* check and skip r_netid */
READ32(len);
if (len != 3) { /* "tcp" */
- printk("%s: ERROR: Device index %d dev_count %d len %d\n",
- __FUNCTION__, index, dev->dev_count, len);
- kfree(file_dev);
- return NULL;
+ printk("%s: ERROR: non TCP r_netid len %d\n", __FUNCTION__, len);
+ goto out_err;
}
/* Read the bytes into a temporary buffer */
/* TODO: should probably sanity check them */
@@ -286,20 +395,105 @@ decode_device(struct pnfs_device* dev)
READ32(len);
if (len > 29) {
- printk("%s: ERROR: Device ip/port string too long (%d)\n",__FUNCTION__, len);
- kfree(file_dev);
- return NULL;
+ printk("%s: ERROR: Device ip/port too long (%d)\n",
+ __FUNCTION__, len);
+ goto out_err;
}
- memcpy(r_addr, p, len);
+ COPYMEM(r_addr, len);
+ *pp = p;
r_addr[len] = '\0';
sscanf(r_addr, "%d.%d.%d.%d.%d.%d", &tmp[0], &tmp[1],
- &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
- file_dev->ip_addr = htonl((tmp[0]<<24) | (tmp[1]<<16) |
- (tmp[2]<<8) | (tmp[3]));
- file_dev->port = htons((tmp[4] << 8) | (tmp[5]));
+ &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
+ ip_addr = htonl((tmp[0]<<24) | (tmp[1]<<16) |
+ (tmp[2]<<8) | (tmp[3]));
+ port = htons((tmp[4] << 8) | (tmp[5]));
+
+ nfs4_pnfs_ds_add(mt, &ds, ip_addr, port);
+
+ /* adding ds to stripe */
+ atomic_inc(&ds->ds_count);
dprintk("%s: addr:port string = %s\n",__FUNCTION__, r_addr);
+ return ds;
+out_err:
+ dprintk("%s returned NULL\n", __FUNCTION__);
+ return NULL;
+}
+/* Decode opaque device data and return the result
+ */
+static struct nfs4_pnfs_dev_item*
+decode_device(struct filelayout_mount_type *mt, struct pnfs_device* dev)
+{
+ int i, len;
+ uint32_t *p = (uint32_t*)dev->dev_addr_buf;
+ struct nfs4_pnfs_dev_item* file_dev;
+ struct nfs4_pnfs_dev* fdev;
+
+ /* Get the stripe count (number of stripe index) */
+ READ32(len);
+ if (len > NFS4_PNFS_MAX_STRIPE_CNT) {
+ printk(KERN_WARNING "%s: stripe count %d greater than supported maximum %d\n", __func__, len, NFS4_PNFS_MAX_STRIPE_CNT);
+
+ goto out_err;
+ }
+
+ file_dev = kzalloc(sizeof(*file_dev), GFP_KERNEL);
+ if (!file_dev)
+ goto out_err;
+
+ file_dev->stripe_devs = kzalloc(sizeof(struct nfs4_pnfs_dev) * len, GFP_KERNEL);
+ if (!file_dev->stripe_devs)
+ goto out_err_free;
+ file_dev->stripe_count = len;
+
+ /* Initialize dev */
+ INIT_HLIST_NODE(&file_dev->hash_node);
+
+ /* Device id */
+ file_dev->dev_id = dev->dev_id;
+
+ fdev = &file_dev->stripe_devs[0];
+ for (i = 0; i < len; i++) {
+ READ32(fdev->stripe_index);
+ fdev++;
+ }
+
+ /* Get the device count, which has to equal the stripe count */
+ READ32(len);
+ if(len != file_dev->stripe_count) {
+ printk("%s: ERROR: device count %d != index count %d\n",
+ __func__, len, file_dev->stripe_count);
+ goto out_err_free;
+ }
+
+ fdev = &file_dev->stripe_devs[0];
+ for (i = 0; i < file_dev->stripe_count; i++) {
+ int j, num;
+
+ /* Get the multipath count for this stripe index */
+ READ32(num);
+ if (num > NFS4_PNFS_MAX_MULTI_DS) {
+ printk(KERN_WARNING "%s: Multipath count %d not supported, setting to %d\n", __func__, num, NFS4_PNFS_MAX_MULTI_DS);
+
+ num = NFS4_PNFS_MAX_MULTI_DS;
+ }
+
+ fdev->num_ds = num;
+
+ for (j = 0; j < fdev->num_ds; j++) {
+ fdev->ds_list[j] = decode_and_add_ds(&p, mt);
+ if (fdev->ds_list[j] == NULL)
+ goto out_err_free;
+ }
+ fdev++;
+ }
return file_dev;
+
+out_err_free:
+ device_destroy(file_dev, mt->hlist);
+out_err:
+ dprintk("%s ERROR: returning NULL\n", __func__);
+ return NULL;
}
/* Decode the opaque device specified in 'dev'
@@ -312,7 +506,7 @@ decode_and_add_device(struct filelayout_mount_type *mt, struct pnfs_device* dev)
{
struct nfs4_pnfs_dev_item* file_dev;
- file_dev = decode_device(dev);
+ file_dev = decode_device(mt, dev);
if (!file_dev) {
printk(KERN_WARNING "%s Could not decode device\n",
__FUNCTION__);
@@ -437,8 +631,10 @@ nfs4_pnfs_dserver_get(struct inode *inode,
dev_id = layout->devs[stripe_idx].dev_id;
- dserver->dev_item = nfs4_pnfs_device_get(inode, dev_id);
- if (dserver->dev_item == NULL)
+ /* NOTE: resolved in following patch.
+ *dserver->dev = nfs4_pnfs_device_get(inode, dev_id); */
+
+ if (dserver->dev == NULL)
return 1;
dserver->fh = &layout->devs[stripe_idx].fh;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index d2dcd0f..2a856b6 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4102,20 +4102,19 @@ out:
* Issue the over-the-wire RPC DESTROY_SESSION.
* The caller must serialize access to this routine.
*/
-int nfs4_proc_destroy_session(struct nfs_server *sp)
+int nfs4_proc_destroy_session(struct nfs4_session *session, struct rpc_clnt *clnt)
{
int status = 0;
struct rpc_message msg;
dprintk("--> nfs4_proc_destroy_session\n");
- BUG_ON(sp == NULL);
- BUG_ON(sp->session == NULL);
+ BUG_ON(session == NULL);
msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DESTROY_SESSION];
- msg.rpc_argp = sp->session;
+ msg.rpc_argp = session;
msg.rpc_resp = NULL;
msg.rpc_cred = NULL;
- status = rpc_call_sync(sp->nfs_client->cl_rpcclient, &msg, 0);
+ status = rpc_call_sync(clnt, &msg, 0);
if (status) {
printk(KERN_WARNING "Got error %d from the server on DESTROY_SESSION. Session has been destroyed regardless...\n", status);
@@ -4124,7 +4123,7 @@ int nfs4_proc_destroy_session(struct nfs_server *sp)
* Since the caller has serialized access to this routine I don't
* grab a lock to modify the expired value.
*/
- nfs41_set_session_expired(sp->session); /* Mark session as expired */
+ nfs41_set_session_expired(session); /* Mark session as expired */
dprintk("<-- nfs4_proc_destroy_session\n");
return status;
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index a46b1b1..c686b58 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -1836,6 +1836,7 @@ error_splat_super:
static void nfs4_kill_super(struct super_block *sb)
{
struct nfs_server *server = NFS_SB(sb);
+ struct rpc_clnt *clnt = server->nfs_client->cl_rpcclient;
dprintk("--> %s\n", __FUNCTION__);
nfs_return_all_delegations(sb);
@@ -1847,7 +1848,7 @@ static void nfs4_kill_super(struct super_block *sb)
if (server->session) {
dprintk("%s Destroy session %p for nfs_server %p\n",
__FUNCTION__, server->session, server);
- nfs4_proc_destroy_session(server);
+ nfs4_proc_destroy_session(server->session, clnt);
}
break;
default:
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 68118aa..c36b6dd 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -6,10 +6,12 @@
#if defined (CONFIG_NFS_V4_1)
#include <linux/nfs4_session.h>
+struct nfs4_session; /* NFSv4.1 session */
#endif
struct nfs_iostats;
+
/*
* The nfs_client identifies our client state to the server.
*/
@@ -77,12 +79,11 @@ struct nfs_client {
/* The flags used for obtaining the clientid during EXCHANGE_ID */
u32 cl_exchange_flags;
#endif
+#ifdef CONFIG_PNFS
+ struct nfs4_session * cl_ds_session; /* pNFS data server session */
+#endif /* CONFIG_PNFS */
};
-#ifdef CONFIG_NFS_V4_1
- struct nfs4_session; /* NFSv4.1 session */
-#endif
-
/*
* NFS client parameters stored in the superblock.
*/
--
1.5.0.2
More information about the pNFS
mailing list