|
@@ -157,17 +157,153 @@ bl_cleanup_layoutcommit(struct nfs4_layoutcommit_data *lcdata)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
+static void free_blk_mountid(struct block_mount_id *mid)
|
|
|
+{
|
|
|
+ if (mid) {
|
|
|
+ struct pnfs_block_dev *dev;
|
|
|
+ spin_lock(&mid->bm_lock);
|
|
|
+ while (!list_empty(&mid->bm_devlist)) {
|
|
|
+ dev = list_first_entry(&mid->bm_devlist,
|
|
|
+ struct pnfs_block_dev,
|
|
|
+ bm_node);
|
|
|
+ list_del(&dev->bm_node);
|
|
|
+ bl_free_block_dev(dev);
|
|
|
+ }
|
|
|
+ spin_unlock(&mid->bm_lock);
|
|
|
+ kfree(mid);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* This is mostly copied from the filelayout's get_device_info function.
|
|
|
+ * It seems much of this should be at the generic pnfs level.
|
|
|
+ */
|
|
|
+static struct pnfs_block_dev *
|
|
|
+nfs4_blk_get_deviceinfo(struct nfs_server *server, const struct nfs_fh *fh,
|
|
|
+ struct nfs4_deviceid *d_id)
|
|
|
+{
|
|
|
+ struct pnfs_device *dev;
|
|
|
+ struct pnfs_block_dev *rv = NULL;
|
|
|
+ u32 max_resp_sz;
|
|
|
+ int max_pages;
|
|
|
+ struct page **pages = NULL;
|
|
|
+ int i, rc;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Use the session max response size as the basis for setting
|
|
|
+ * GETDEVICEINFO's maxcount
|
|
|
+ */
|
|
|
+ max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
|
|
|
+ max_pages = max_resp_sz >> PAGE_SHIFT;
|
|
|
+ dprintk("%s max_resp_sz %u max_pages %d\n",
|
|
|
+ __func__, max_resp_sz, max_pages);
|
|
|
+
|
|
|
+ dev = kmalloc(sizeof(*dev), GFP_NOFS);
|
|
|
+ if (!dev) {
|
|
|
+ dprintk("%s kmalloc failed\n", __func__);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ pages = kzalloc(max_pages * sizeof(struct page *), GFP_NOFS);
|
|
|
+ if (pages == NULL) {
|
|
|
+ kfree(dev);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ for (i = 0; i < max_pages; i++) {
|
|
|
+ pages[i] = alloc_page(GFP_NOFS);
|
|
|
+ if (!pages[i])
|
|
|
+ goto out_free;
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy(&dev->dev_id, d_id, sizeof(*d_id));
|
|
|
+ dev->layout_type = LAYOUT_BLOCK_VOLUME;
|
|
|
+ dev->pages = pages;
|
|
|
+ dev->pgbase = 0;
|
|
|
+ dev->pglen = PAGE_SIZE * max_pages;
|
|
|
+ dev->mincount = 0;
|
|
|
+
|
|
|
+ dprintk("%s: dev_id: %s\n", __func__, dev->dev_id.data);
|
|
|
+ rc = nfs4_proc_getdeviceinfo(server, dev);
|
|
|
+ dprintk("%s getdevice info returns %d\n", __func__, rc);
|
|
|
+ if (rc)
|
|
|
+ goto out_free;
|
|
|
+
|
|
|
+ rv = nfs4_blk_decode_device(server, dev);
|
|
|
+ out_free:
|
|
|
+ for (i = 0; i < max_pages; i++)
|
|
|
+ __free_page(pages[i]);
|
|
|
+ kfree(pages);
|
|
|
+ kfree(dev);
|
|
|
+ return rv;
|
|
|
+}
|
|
|
+
|
|
|
static int
|
|
|
bl_set_layoutdriver(struct nfs_server *server, const struct nfs_fh *fh)
|
|
|
{
|
|
|
+ struct block_mount_id *b_mt_id = NULL;
|
|
|
+ struct pnfs_devicelist *dlist = NULL;
|
|
|
+ struct pnfs_block_dev *bdev;
|
|
|
+ LIST_HEAD(block_disklist);
|
|
|
+ int status = 0, i;
|
|
|
+
|
|
|
dprintk("%s enter\n", __func__);
|
|
|
- return 0;
|
|
|
+
|
|
|
+ if (server->pnfs_blksize == 0) {
|
|
|
+ dprintk("%s Server did not return blksize\n", __func__);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ b_mt_id = kzalloc(sizeof(struct block_mount_id), GFP_NOFS);
|
|
|
+ if (!b_mt_id) {
|
|
|
+ status = -ENOMEM;
|
|
|
+ goto out_error;
|
|
|
+ }
|
|
|
+ /* Initialize nfs4 block layout mount id */
|
|
|
+ spin_lock_init(&b_mt_id->bm_lock);
|
|
|
+ INIT_LIST_HEAD(&b_mt_id->bm_devlist);
|
|
|
+
|
|
|
+ dlist = kmalloc(sizeof(struct pnfs_devicelist), GFP_NOFS);
|
|
|
+ if (!dlist) {
|
|
|
+ status = -ENOMEM;
|
|
|
+ goto out_error;
|
|
|
+ }
|
|
|
+ dlist->eof = 0;
|
|
|
+ while (!dlist->eof) {
|
|
|
+ status = nfs4_proc_getdevicelist(server, fh, dlist);
|
|
|
+ if (status)
|
|
|
+ goto out_error;
|
|
|
+ dprintk("%s GETDEVICELIST numdevs=%i, eof=%i\n",
|
|
|
+ __func__, dlist->num_devs, dlist->eof);
|
|
|
+ for (i = 0; i < dlist->num_devs; i++) {
|
|
|
+ bdev = nfs4_blk_get_deviceinfo(server, fh,
|
|
|
+ &dlist->dev_id[i]);
|
|
|
+ if (!bdev) {
|
|
|
+ status = -ENODEV;
|
|
|
+ goto out_error;
|
|
|
+ }
|
|
|
+ spin_lock(&b_mt_id->bm_lock);
|
|
|
+ list_add(&bdev->bm_node, &b_mt_id->bm_devlist);
|
|
|
+ spin_unlock(&b_mt_id->bm_lock);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ dprintk("%s SUCCESS\n", __func__);
|
|
|
+ server->pnfs_ld_data = b_mt_id;
|
|
|
+
|
|
|
+ out_return:
|
|
|
+ kfree(dlist);
|
|
|
+ return status;
|
|
|
+
|
|
|
+ out_error:
|
|
|
+ free_blk_mountid(b_mt_id);
|
|
|
+ goto out_return;
|
|
|
}
|
|
|
|
|
|
static int
|
|
|
bl_clear_layoutdriver(struct nfs_server *server)
|
|
|
{
|
|
|
+ struct block_mount_id *b_mt_id = server->pnfs_ld_data;
|
|
|
+
|
|
|
dprintk("%s enter\n", __func__);
|
|
|
+ free_blk_mountid(b_mt_id);
|
|
|
+ dprintk("%s RETURNS\n", __func__);
|
|
|
return 0;
|
|
|
}
|
|
|
|