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