12a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
22a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik/*
32a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik   osdblk.c -- Export a single SCSI OSD object as a Linux block device
42a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
52a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
62a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik   Copyright 2009 Red Hat, Inc.
72a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
82a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik   This program is free software; you can redistribute it and/or modify
92a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik   it under the terms of the GNU General Public License as published by
102a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik   the Free Software Foundation.
112a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
122a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik   This program is distributed in the hope that it will be useful,
132a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik   but WITHOUT ANY WARRANTY; without even the implied warranty of
142a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
152a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik   GNU General Public License for more details.
162a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
172a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik   You should have received a copy of the GNU General Public License
182a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik   along with this program; see the file COPYING.  If not, write to
192a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
202a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
212a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
222a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik   Instructions for use
232a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik   --------------------
242a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
252a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik   1) Map a Linux block device to an existing OSD object.
262a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
272a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik      In this example, we will use partition id 1234, object id 5678,
282a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik      OSD device /dev/osd1.
292a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
302a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik      $ echo "1234 5678 /dev/osd1" > /sys/class/osdblk/add
312a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
322a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
332a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik   2) List all active blkdev<->object mappings.
342a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
352a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik      In this example, we have performed step #1 twice, creating two blkdevs,
362a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik      mapped to two separate OSD objects.
372a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
382a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik      $ cat /sys/class/osdblk/list
392a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik      0 174 1234 5678 /dev/osd1
402a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik      1 179 1994 897123 /dev/osd0
412a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
422a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik      The columns, in order, are:
432a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik      - blkdev unique id
442a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik      - blkdev assigned major
452a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik      - OSD object partition id
462a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik      - OSD object id
472a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik      - OSD device
482a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
492a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
502a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik   3) Remove an active blkdev<->object mapping.
512a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
522a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik      In this example, we remove the mapping with blkdev unique id 1.
532a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
542a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik      $ echo 1 > /sys/class/osdblk/remove
552a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
562a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
572a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik   NOTE:  The actual creation and deletion of OSD objects is outside the scope
582a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik   of this driver.
592a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
602a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik */
612a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
622a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik#include <linux/kernel.h>
632a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik#include <linux/device.h>
642a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik#include <linux/module.h>
652a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik#include <linux/fs.h>
665a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
672a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik#include <scsi/osd_initiator.h>
682a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik#include <scsi/osd_attributes.h>
692a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik#include <scsi/osd_sec.h>
70bc47df0fa705887242c26c7b040e7cf0170ab1f1Boaz Harrosh#include <scsi/scsi_device.h>
712a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
722a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik#define DRV_NAME "osdblk"
732a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik#define PFX DRV_NAME ": "
742a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
752a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik/* #define _OSDBLK_DEBUG */
762a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik#ifdef _OSDBLK_DEBUG
772a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik#define OSDBLK_DEBUG(fmt, a...) \
782a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	printk(KERN_NOTICE "osdblk @%s:%d: " fmt, __func__, __LINE__, ##a)
792a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik#else
802a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik#define OSDBLK_DEBUG(fmt, a...) \
812a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	do { if (0) printk(fmt, ##a); } while (0)
822a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik#endif
832a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
842a13877c5ef3207a2a5c56250742e60808677f90Jeff GarzikMODULE_AUTHOR("Jeff Garzik <jeff@garzik.org>");
852a13877c5ef3207a2a5c56250742e60808677f90Jeff GarzikMODULE_DESCRIPTION("block device inside an OSD object osdblk.ko");
862a13877c5ef3207a2a5c56250742e60808677f90Jeff GarzikMODULE_LICENSE("GPL");
872a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
882a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstruct osdblk_device;
892a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
902a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikenum {
912a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	OSDBLK_MINORS_PER_MAJOR	= 256,		/* max minors per blkdev */
922a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	OSDBLK_MAX_REQ		= 32,		/* max parallel requests */
932a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	OSDBLK_OP_TIMEOUT	= 4 * 60,	/* sync OSD req timeout */
942a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik};
952a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
962a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstruct osdblk_request {
972a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct request		*rq;		/* blk layer request */
982a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct bio		*bio;		/* cloned bio */
992a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct osdblk_device	*osdev;		/* associated blkdev */
1002a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik};
1012a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1022a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstruct osdblk_device {
1032a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	int			id;		/* blkdev unique id */
1042a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1052a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	int			major;		/* blkdev assigned major */
1062a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct gendisk		*disk;		/* blkdev's gendisk and rq */
1072a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct request_queue	*q;
1082a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1092a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct osd_dev		*osd;		/* associated OSD */
1102a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1112a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	char			name[32];	/* blkdev name, e.g. osdblk34 */
1122a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1132a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	spinlock_t		lock;		/* queue lock */
1142a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1152a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct osd_obj_id	obj;		/* OSD partition, obj id */
1162a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	uint8_t			obj_cred[OSD_CAP_LEN]; /* OSD cred */
1172a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1182a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct osdblk_request	req[OSDBLK_MAX_REQ]; /* request table */
1192a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1202a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct list_head	node;
1212a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1222a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	char			osd_path[0];	/* OSD device path */
1232a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik};
1242a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1252a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstatic struct class *class_osdblk;		/* /sys/class/osdblk */
1262a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstatic DEFINE_MUTEX(ctl_mutex);	/* Serialize open/close/setup/teardown */
1272a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstatic LIST_HEAD(osdblkdev_list);
1282a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
12983d5cde47dedf01b6a4a4331882cbc0a7eea3c2eAlexey Dobriyanstatic const struct block_device_operations osdblk_bd_ops = {
1302a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	.owner		= THIS_MODULE,
1312a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik};
1322a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1332a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstatic const struct osd_attr g_attr_logical_length = ATTR_DEF(
1342a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8);
1352a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1362a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstatic void osdblk_make_credential(u8 cred_a[OSD_CAP_LEN],
1372a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik				   const struct osd_obj_id *obj)
1382a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik{
1392a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	osd_sec_init_nosec_doall_caps(cred_a, obj, false, true);
1402a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik}
1412a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1422a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik/* copied from exofs; move to libosd? */
1432a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik/*
1442a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik * Perform a synchronous OSD operation.  copied from exofs; move to libosd?
1452a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik */
1462a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstatic int osd_sync_op(struct osd_request *or, int timeout, uint8_t *credential)
1472a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik{
1482a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	int ret;
1492a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1502a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	or->timeout = timeout;
1512a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	ret = osd_finalize_request(or, 0, credential, NULL);
1522a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (ret)
1532a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		return ret;
1542a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1552a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	ret = osd_execute_request(or);
1562a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1572a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* osd_req_decode_sense(or, ret); */
1582a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	return ret;
1592a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik}
1602a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1612a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik/*
1622a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik * Perform an asynchronous OSD operation.  copied from exofs; move to libosd?
1632a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik */
1642a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstatic int osd_async_op(struct osd_request *or, osd_req_done_fn *async_done,
1652a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		   void *caller_context, u8 *cred)
1662a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik{
1672a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	int ret;
1682a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1692a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	ret = osd_finalize_request(or, 0, cred, NULL);
1702a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (ret)
1712a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		return ret;
1722a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1732a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	ret = osd_execute_request_async(or, async_done, caller_context);
1742a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1752a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	return ret;
1762a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik}
1772a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1782a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik/* copied from exofs; move to libosd? */
1792a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstatic int extract_attr_from_req(struct osd_request *or, struct osd_attr *attr)
1802a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik{
1812a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct osd_attr cur_attr = {.attr_page = 0}; /* start with zeros */
1822a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	void *iter = NULL;
1832a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	int nelem;
1842a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1852a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	do {
1862a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		nelem = 1;
1872a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		osd_req_decode_get_attr_list(or, &cur_attr, &nelem, &iter);
1882a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		if ((cur_attr.attr_page == attr->attr_page) &&
1892a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		    (cur_attr.attr_id == attr->attr_id)) {
1902a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			attr->len = cur_attr.len;
1912a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			attr->val_ptr = cur_attr.val_ptr;
1922a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			return 0;
1932a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		}
1942a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	} while (iter);
1952a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1962a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	return -EIO;
1972a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik}
1982a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
1992a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstatic int osdblk_get_obj_size(struct osdblk_device *osdev, u64 *size_out)
2002a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik{
2012a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct osd_request *or;
2022a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct osd_attr attr;
2032a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	int ret;
2042a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
2052a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* start request */
2062a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	or = osd_start_request(osdev->osd, GFP_KERNEL);
2072a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (!or)
2082a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		return -ENOMEM;
2092a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
2102a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* create a get-attributes(length) request */
2112a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	osd_req_get_attributes(or, &osdev->obj);
2122a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
2132a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	osd_req_add_get_attr_list(or, &g_attr_logical_length, 1);
2142a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
2152a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* execute op synchronously */
2162a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	ret = osd_sync_op(or, OSDBLK_OP_TIMEOUT, osdev->obj_cred);
2172a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (ret)
2182a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		goto out;
2192a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
2202a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* extract length from returned attribute info */
2212a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	attr = g_attr_logical_length;
2222a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	ret = extract_attr_from_req(or, &attr);
2232a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (ret)
2242a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		goto out;
2252a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
2262a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	*size_out = get_unaligned_be64(attr.val_ptr);
2272a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
2282a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikout:
2292a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	osd_end_request(or);
2302a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	return ret;
2312a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
2322a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik}
2332a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
2342a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstatic void osdblk_osd_complete(struct osd_request *or, void *private)
2352a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik{
2362a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct osdblk_request *orq = private;
2372a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct osd_sense_info osi;
2382a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	int ret = osd_req_decode_sense(or, &osi);
2392a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
2402a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (ret) {
2412a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		ret = -EIO;
2422a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		OSDBLK_DEBUG("osdblk_osd_complete with err=%d\n", ret);
2432a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	}
2442a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
2452a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* complete OSD request */
2462a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	osd_end_request(or);
2472a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
2482a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* complete request passed to osdblk by block layer */
2492a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	__blk_end_request_all(orq->rq, ret);
2502a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik}
2512a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
2522a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstatic void bio_chain_put(struct bio *chain)
2532a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik{
2542a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct bio *tmp;
2552a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
2562a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	while (chain) {
2572a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		tmp = chain;
2582a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		chain = chain->bi_next;
2592a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
2602a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		bio_put(tmp);
2612a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	}
2622a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik}
2632a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
2642a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstatic struct bio *bio_chain_clone(struct bio *old_chain, gfp_t gfpmask)
2652a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik{
2662a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct bio *tmp, *new_chain = NULL, *tail = NULL;
2672a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
2682a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	while (old_chain) {
2692a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		tmp = bio_kmalloc(gfpmask, old_chain->bi_max_vecs);
2702a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		if (!tmp)
2712a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			goto err_out;
2722a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
2732a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		__bio_clone(tmp, old_chain);
2742a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		tmp->bi_bdev = NULL;
2752a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		gfpmask &= ~__GFP_WAIT;
2762a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		tmp->bi_next = NULL;
2772a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
2782a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		if (!new_chain)
2792a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			new_chain = tail = tmp;
2802a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		else {
2812a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			tail->bi_next = tmp;
2822a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			tail = tmp;
2832a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		}
2842a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
2852a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		old_chain = old_chain->bi_next;
2862a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	}
2872a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
2882a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	return new_chain;
2892a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
2902a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikerr_out:
2912a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	OSDBLK_DEBUG("bio_chain_clone with err\n");
2922a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	bio_chain_put(new_chain);
2932a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	return NULL;
2942a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik}
2952a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
2962a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstatic void osdblk_rq_fn(struct request_queue *q)
2972a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik{
2982a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct osdblk_device *osdev = q->queuedata;
2992a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
3002a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	while (1) {
3012a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		struct request *rq;
3022a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		struct osdblk_request *orq;
3032a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		struct osd_request *or;
3042a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		struct bio *bio;
3052a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		bool do_write, do_flush;
3062a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
3072a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		/* peek at request from block layer */
3082a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		rq = blk_fetch_request(q);
3092a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		if (!rq)
3102a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			break;
3112a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
3122a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		/* filter out block requests we don't understand */
3139cbbdca44ae1a6f512ea1e2be11ced8bbb9d430aTejun Heo		if (rq->cmd_type != REQ_TYPE_FS) {
3142a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			blk_end_request_all(rq, 0);
3152a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			continue;
3162a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		}
3172a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
3182a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		/* deduce our operation (read, write, flush) */
3192a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		/* I wish the block layer simplified cmd_type/cmd_flags/cmd[]
3202a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		 * into a clearly defined set of RPC commands:
3212a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		 * read, write, flush, scsi command, power mgmt req,
3222a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		 * driver-specific, etc.
3232a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		 */
3242a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
3257f9815f09dc201f2205981c11fadcf82a9e3cc42FUJITA Tomonori		do_flush = rq->cmd_flags & REQ_FLUSH;
3262a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		do_write = (rq_data_dir(rq) == WRITE);
3272a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
3282a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		if (!do_flush) { /* osd_flush does not use a bio */
3292a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			/* a bio clone to be passed down to OSD request */
3302a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			bio = bio_chain_clone(rq->bio, GFP_ATOMIC);
3312a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			if (!bio)
3322a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik				break;
3332a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		} else
3342a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			bio = NULL;
3352a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
3362a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		/* alloc internal OSD request, for OSD command execution */
3372a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		or = osd_start_request(osdev->osd, GFP_ATOMIC);
3382a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		if (!or) {
3392a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			bio_chain_put(bio);
3402a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			OSDBLK_DEBUG("osd_start_request with err\n");
3412a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			break;
3422a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		}
3432a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
3442a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		orq = &osdev->req[rq->tag];
3452a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		orq->rq = rq;
3462a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		orq->bio = bio;
3472a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		orq->osdev = osdev;
3482a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
3492a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		/* init OSD command: flush, write or read */
3502a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		if (do_flush)
3512a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			osd_req_flush_object(or, &osdev->obj,
3522a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik					     OSD_CDB_FLUSH_ALL, 0, 0);
3532a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		else if (do_write)
3542a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			osd_req_write(or, &osdev->obj, blk_rq_pos(rq) * 512ULL,
3552a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik				      bio, blk_rq_bytes(rq));
3562a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		else
3572a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			osd_req_read(or, &osdev->obj, blk_rq_pos(rq) * 512ULL,
3582a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik				     bio, blk_rq_bytes(rq));
3592a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
3602a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		OSDBLK_DEBUG("%s 0x%x bytes at 0x%llx\n",
3612a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			do_flush ? "flush" : do_write ?
3622a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik				"write" : "read", blk_rq_bytes(rq),
3632a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			blk_rq_pos(rq) * 512ULL);
3642a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
3652a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		/* begin OSD command execution */
3662a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		if (osd_async_op(or, osdblk_osd_complete, orq,
3672a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik				 osdev->obj_cred)) {
3682a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			osd_end_request(or);
3692a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			blk_requeue_request(q, rq);
3702a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			bio_chain_put(bio);
3712a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			OSDBLK_DEBUG("osd_execute_request_async with err\n");
3722a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			break;
3732a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		}
3742a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
3752a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		/* remove the special 'flush' marker, now that the command
3762a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		 * is executing
3772a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		 */
3782a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		rq->special = NULL;
3792a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	}
3802a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik}
3812a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
3822a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstatic void osdblk_free_disk(struct osdblk_device *osdev)
3832a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik{
3842a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct gendisk *disk = osdev->disk;
3852a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
3862a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (!disk)
3872a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		return;
3882a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
3892a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (disk->flags & GENHD_FL_UP)
3902a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		del_gendisk(disk);
3912a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (disk->queue)
3922a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		blk_cleanup_queue(disk->queue);
3932a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	put_disk(disk);
3942a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik}
3952a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
3962a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstatic int osdblk_init_disk(struct osdblk_device *osdev)
3972a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik{
3982a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct gendisk *disk;
3992a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct request_queue *q;
4002a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	int rc;
4012a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	u64 obj_size = 0;
4022a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
4032a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* contact OSD, request size info about the object being mapped */
4042a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	rc = osdblk_get_obj_size(osdev, &obj_size);
4052a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (rc)
4062a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		return rc;
4072a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
4082a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* create gendisk info */
4092a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	disk = alloc_disk(OSDBLK_MINORS_PER_MAJOR);
4102a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (!disk)
4112a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		return -ENOMEM;
4122a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
4132a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	sprintf(disk->disk_name, DRV_NAME "%d", osdev->id);
4142a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	disk->major = osdev->major;
4152a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	disk->first_minor = 0;
4162a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	disk->fops = &osdblk_bd_ops;
4172a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	disk->private_data = osdev;
4182a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
4192a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* init rq */
4202a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	q = blk_init_queue(osdblk_rq_fn, &osdev->lock);
4212a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (!q) {
4222a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		put_disk(disk);
4232a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		return -ENOMEM;
4242a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	}
4252a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
4262a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* switch queue to TCQ mode; allocate tag map */
4272a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	rc = blk_queue_init_tags(q, OSDBLK_MAX_REQ, NULL);
4282a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (rc) {
4292a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		blk_cleanup_queue(q);
4302a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		put_disk(disk);
4312a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		return rc;
4322a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	}
4332a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
434bc47df0fa705887242c26c7b040e7cf0170ab1f1Boaz Harrosh	/* Set our limits to the lower device limits, because osdblk cannot
435bc47df0fa705887242c26c7b040e7cf0170ab1f1Boaz Harrosh	 * sleep when allocating a lower-request and therefore cannot be
436bc47df0fa705887242c26c7b040e7cf0170ab1f1Boaz Harrosh	 * bouncing.
437bc47df0fa705887242c26c7b040e7cf0170ab1f1Boaz Harrosh	 */
438bc47df0fa705887242c26c7b040e7cf0170ab1f1Boaz Harrosh	blk_queue_stack_limits(q, osd_request_queue(osdev->osd));
439bc47df0fa705887242c26c7b040e7cf0170ab1f1Boaz Harrosh
4402a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	blk_queue_prep_rq(q, blk_queue_start_tag);
4414913efe456c987057e5d36a3f0a55422a9072caeTejun Heo	blk_queue_flush(q, REQ_FLUSH);
4422a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
4432a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	disk->queue = q;
4442a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
4452a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	q->queuedata = osdev;
4462a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
4472a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	osdev->disk = disk;
4482a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	osdev->q = q;
4492a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
4502a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* finally, announce the disk to the world */
4512a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	set_capacity(disk, obj_size / 512ULL);
4522a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	add_disk(disk);
4532a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
4542a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	printk(KERN_INFO "%s: Added of size 0x%llx\n",
4552a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		disk->disk_name, (unsigned long long)obj_size);
4562a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
4572a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	return 0;
4582a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik}
4592a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
4602a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik/********************************************************************
4612a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik * /sys/class/osdblk/
4622a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik *                   add	map OSD object to blkdev
4632a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik *                   remove	unmap OSD object
4642a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik *                   list	show mappings
4652a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik *******************************************************************/
4662a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
4672a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstatic void class_osdblk_release(struct class *cls)
4682a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik{
4692a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	kfree(cls);
4702a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik}
4712a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
47228812fe11a21826ba4c97c6c7971a619987cd912Andi Kleenstatic ssize_t class_osdblk_list(struct class *c,
47328812fe11a21826ba4c97c6c7971a619987cd912Andi Kleen				struct class_attribute *attr,
47428812fe11a21826ba4c97c6c7971a619987cd912Andi Kleen				char *data)
4752a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik{
4762a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	int n = 0;
4772a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct list_head *tmp;
4782a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
4792a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
4802a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
4812a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	list_for_each(tmp, &osdblkdev_list) {
4822a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		struct osdblk_device *osdev;
4832a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
4842a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		osdev = list_entry(tmp, struct osdblk_device, node);
4852a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
4862a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		n += sprintf(data+n, "%d %d %llu %llu %s\n",
4872a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			osdev->id,
4882a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			osdev->major,
4892a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			osdev->obj.partition,
4902a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			osdev->obj.id,
4912a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			osdev->osd_path);
4922a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	}
4932a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
4942a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	mutex_unlock(&ctl_mutex);
4952a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	return n;
4962a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik}
4972a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
49828812fe11a21826ba4c97c6c7971a619987cd912Andi Kleenstatic ssize_t class_osdblk_add(struct class *c,
49928812fe11a21826ba4c97c6c7971a619987cd912Andi Kleen				struct class_attribute *attr,
50028812fe11a21826ba4c97c6c7971a619987cd912Andi Kleen				const char *buf, size_t count)
5012a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik{
5022a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct osdblk_device *osdev;
5032a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	ssize_t rc;
5042a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	int irc, new_id = 0;
5052a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct list_head *tmp;
5062a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
5072a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (!try_module_get(THIS_MODULE))
5082a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		return -ENODEV;
5092a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
5102a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* new osdblk_device object */
5112a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	osdev = kzalloc(sizeof(*osdev) + strlen(buf) + 1, GFP_KERNEL);
5122a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (!osdev) {
5132a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		rc = -ENOMEM;
5142a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		goto err_out_mod;
5152a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	}
5162a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
5172a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* static osdblk_device initialization */
5182a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	spin_lock_init(&osdev->lock);
5192a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	INIT_LIST_HEAD(&osdev->node);
5202a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
5212a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* generate unique id: find highest unique id, add one */
5222a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
5232a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
5242a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
5252a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	list_for_each(tmp, &osdblkdev_list) {
5262a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		struct osdblk_device *osdev;
5272a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
5282a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		osdev = list_entry(tmp, struct osdblk_device, node);
5292a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		if (osdev->id > new_id)
5302a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			new_id = osdev->id + 1;
5312a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	}
5322a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
5332a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	osdev->id = new_id;
5342a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
5352a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* add to global list */
5362a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	list_add_tail(&osdev->node, &osdblkdev_list);
5372a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
5382a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	mutex_unlock(&ctl_mutex);
5392a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
5402a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* parse add command */
5412a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (sscanf(buf, "%llu %llu %s", &osdev->obj.partition, &osdev->obj.id,
5422a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		   osdev->osd_path) != 3) {
5432a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		rc = -EINVAL;
5442a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		goto err_out_slot;
5452a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	}
5462a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
5472a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* initialize rest of new object */
5482a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	sprintf(osdev->name, DRV_NAME "%d", osdev->id);
5492a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
5502a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* contact requested OSD */
5512a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	osdev->osd = osduld_path_lookup(osdev->osd_path);
5522a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (IS_ERR(osdev->osd)) {
5532a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		rc = PTR_ERR(osdev->osd);
5542a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		goto err_out_slot;
5552a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	}
5562a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
5572a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* build OSD credential */
5582a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	osdblk_make_credential(osdev->obj_cred, &osdev->obj);
5592a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
5602a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* register our block device */
5612a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	irc = register_blkdev(0, osdev->name);
5622a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (irc < 0) {
5632a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		rc = irc;
5642a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		goto err_out_osd;
5652a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	}
5662a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
5672a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	osdev->major = irc;
5682a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
5692a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* set up and announce blkdev mapping */
5702a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	rc = osdblk_init_disk(osdev);
5712a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (rc)
5722a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		goto err_out_blkdev;
5732a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
5742a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	return count;
5752a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
5762a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikerr_out_blkdev:
5772a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	unregister_blkdev(osdev->major, osdev->name);
5782a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikerr_out_osd:
5792a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	osduld_put_device(osdev->osd);
5802a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikerr_out_slot:
5812a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
5822a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	list_del_init(&osdev->node);
5832a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	mutex_unlock(&ctl_mutex);
5842a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
5852a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	kfree(osdev);
5862a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikerr_out_mod:
5872a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	OSDBLK_DEBUG("Error adding device %s\n", buf);
5882a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	module_put(THIS_MODULE);
5892a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	return rc;
5902a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik}
5912a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
59228812fe11a21826ba4c97c6c7971a619987cd912Andi Kleenstatic ssize_t class_osdblk_remove(struct class *c,
59328812fe11a21826ba4c97c6c7971a619987cd912Andi Kleen					struct class_attribute *attr,
59428812fe11a21826ba4c97c6c7971a619987cd912Andi Kleen					const char *buf,
5952a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik					size_t count)
5962a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik{
5972a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct osdblk_device *osdev = NULL;
5982a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	int target_id, rc;
5992a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	unsigned long ul;
6002a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	struct list_head *tmp;
6012a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
6022a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	rc = strict_strtoul(buf, 10, &ul);
6032a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (rc)
6042a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		return rc;
6052a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
6062a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* convert to int; abort if we lost anything in the conversion */
6072a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	target_id = (int) ul;
6082a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (target_id != ul)
6092a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		return -EINVAL;
6102a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
6112a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* remove object from list immediately */
6122a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
6132a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
6142a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	list_for_each(tmp, &osdblkdev_list) {
6152a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		osdev = list_entry(tmp, struct osdblk_device, node);
6162a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		if (osdev->id == target_id) {
6172a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			list_del_init(&osdev->node);
6182a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik			break;
6192a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		}
6202a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		osdev = NULL;
6212a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	}
6222a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
6232a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	mutex_unlock(&ctl_mutex);
6242a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
6252a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (!osdev)
6262a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		return -ENOENT;
6272a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
6282a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* clean up and free blkdev and associated OSD connection */
6292a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	osdblk_free_disk(osdev);
6302a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	unregister_blkdev(osdev->major, osdev->name);
6312a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	osduld_put_device(osdev->osd);
6322a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	kfree(osdev);
6332a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
6342a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/* release module ref */
6352a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	module_put(THIS_MODULE);
6362a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
6372a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	return count;
6382a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik}
6392a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
6402a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstatic struct class_attribute class_osdblk_attrs[] = {
6412a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	__ATTR(add,	0200, NULL, class_osdblk_add),
6422a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	__ATTR(remove,	0200, NULL, class_osdblk_remove),
6432a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	__ATTR(list,	0444, class_osdblk_list, NULL),
6442a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	__ATTR_NULL
6452a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik};
6462a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
6472a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstatic int osdblk_sysfs_init(void)
6482a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik{
6492a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	int ret = 0;
6502a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
6512a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	/*
6522a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	 * create control files in sysfs
6532a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	 * /sys/class/osdblk/...
6542a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	 */
6552a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	class_osdblk = kzalloc(sizeof(*class_osdblk), GFP_KERNEL);
6562a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (!class_osdblk)
6572a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		return -ENOMEM;
6582a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
6592a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	class_osdblk->name = DRV_NAME;
6602a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	class_osdblk->owner = THIS_MODULE;
6612a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	class_osdblk->class_release = class_osdblk_release;
6622a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	class_osdblk->class_attrs = class_osdblk_attrs;
6632a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
6642a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	ret = class_register(class_osdblk);
6652a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (ret) {
6662a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		kfree(class_osdblk);
6672a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		class_osdblk = NULL;
6682a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		printk(PFX "failed to create class osdblk\n");
6692a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		return ret;
6702a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	}
6712a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
6722a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	return 0;
6732a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik}
6742a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
6752a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstatic void osdblk_sysfs_cleanup(void)
6762a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik{
6772a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (class_osdblk)
6782a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		class_destroy(class_osdblk);
6792a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	class_osdblk = NULL;
6802a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik}
6812a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
6822a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstatic int __init osdblk_init(void)
6832a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik{
6842a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	int rc;
6852a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
6862a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	rc = osdblk_sysfs_init();
6872a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	if (rc)
6882a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik		return rc;
6892a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
6902a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	return 0;
6912a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik}
6922a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
6932a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikstatic void __exit osdblk_exit(void)
6942a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik{
6952a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik	osdblk_sysfs_cleanup();
6962a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik}
6972a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
6982a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikmodule_init(osdblk_init);
6992a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzikmodule_exit(osdblk_exit);
7002a13877c5ef3207a2a5c56250742e60808677f90Jeff Garzik
701