@@ -132,6 +132,8 @@ uint32_t *blk_overflow(uint32_t *p, uint32_t *end, size_t nbytes);
} while (0)
/* blocklayoutdev.c */
+struct block_device *nfs4_blkdev_get(dev_t dev);
+int nfs4_blkdev_put(struct block_device *bdev);
struct pnfs_block_dev *nfs4_blk_decode_device(struct super_block *sb,
struct pnfs_device *dev,
struct list_head *sdlist);
@@ -52,7 +52,7 @@ uint32_t *blk_overflow(uint32_t *p, uint32_t *end, size_t nbytes)
EXPORT_SYMBOL(blk_overflow);
/* Open a block_device by device number. */
-static struct block_device *nfs4_blkdev_get(dev_t dev)
+struct block_device *nfs4_blkdev_get(dev_t dev)
{
struct block_device *bd;
@@ -70,7 +70,7 @@ fail:
/*
* Release the block device
*/
-static int nfs4_blkdev_put(struct block_device *bdev)
+int nfs4_blkdev_put(struct block_device *bdev)
{
dprintk("%s for device %d:%d\n", __func__, MAJOR(bdev->bd_dev),
MINOR(bdev->bd_dev));
@@ -30,14 +30,51 @@
* possibility of such damages.
*/
+#include <linux/genhd.h> /* gendisk - used in a dprintk*/
+
#include "blocklayout.h"
#define NFSDBG_FACILITY NFSDBG_PNFS_LD
-/* Stub */
+static int dev_create(const char *name, dev_t *dev)
+{
+ struct dm_ioctl ctrl;
+ int rv;
+
+ memset(&ctrl, 0, sizeof(ctrl));
+ strncpy(ctrl.name, name, DM_NAME_LEN-1);
+ rv = dm_dev_create(&ctrl); /* XXX - need to pull data out of ctrl */
+ dprintk("Tried to create %s, got %i\n", name, rv);
+ if (!rv) {
+ *dev = huge_decode_dev(ctrl.dev);
+ dprintk("dev = (%i, %i)\n", MAJOR(*dev), MINOR(*dev));
+ }
+ return rv;
+}
+
+static int dev_remove(const char *name)
+{
+ struct dm_ioctl ctrl;
+ memset(&ctrl, 0, sizeof(ctrl));
+ strncpy(ctrl.name, name, DM_NAME_LEN-1);
+ return dm_dev_remove(&ctrl);
+}
+
+/*
+ * Release meta device
+ */
static int nfs4_blk_metadev_release(struct pnfs_block_dev *bdev)
{
- return 0;
+ int rv;
+
+ dprintk("%s Releasing %s\n", __func__, bdev->bm_mdevname);
+ /* XXX Check return? */
+ rv = nfs4_blkdev_put(bdev->bm_mdev);
+ dprintk("%s nfs4_blkdev_put returns %d\n", __func__, rv);
+
+ rv = dev_remove(bdev->bm_mdevname);
+ dprintk("%s Returns %d\n", __func__, rv);
+ return rv;
}
void free_block_dev(struct pnfs_block_dev *bdev)
@@ -56,10 +93,51 @@ void free_block_dev(struct pnfs_block_dev *bdev)
}
}
-/* Stub */
+/*
+ * Create meta device. Keep it open to use for I/O.
+ */
struct pnfs_block_dev *nfs4_blk_init_metadev(struct super_block *sb,
struct pnfs_device *dev)
{
+ static uint64_t dev_count; /* STUB used for device names */
+ struct block_device *bd;
+ dev_t meta_dev;
+ struct pnfs_block_dev *rv;
+ int status;
+
+ dprintk("%s enter\n", __func__);
+
+ rv = kmalloc(sizeof(*rv) + 32, GFP_KERNEL);
+ if (!rv)
+ return NULL;
+ rv->bm_mdevname = (char *)rv + sizeof(*rv);
+ sprintf(rv->bm_mdevname, "FRED_%llu", dev_count++);
+ status = dev_create(rv->bm_mdevname, &meta_dev);
+ if (status)
+ goto out_err;
+ bd = nfs4_blkdev_get(meta_dev);
+ if (!bd)
+ goto out_err;
+ if (bd_claim(bd, sb)) {
+ dprintk("%s: failed to claim device %d:%d\n",
+ __func__,
+ MAJOR(meta_dev),
+ MINOR(meta_dev));
+ blkdev_put(bd, FMODE_READ);
+ goto out_err;
+ }
+
+ rv->bm_mdev = bd;
+ memcpy(&rv->bm_mdevid, &dev->dev_id, sizeof(struct pnfs_deviceid));
+ dprintk("%s Created device %s named %s with bd_block_size %u\n",
+ __func__,
+ bd->bd_disk->disk_name,
+ rv->bm_mdevname,
+ bd->bd_block_size);
+ return rv;
+
+ out_err:
+ kfree(rv);
return NULL;
}