1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (c) 2002, 2003 Cluster File Systems, Inc.
5 * Author: Zach Brown <zab@clusterfs.com>
7 * This file is part of Lustre, http://www.lustre.org.
9 * Lustre is free software; you can redistribute it and/or
10 * modify it under the terms of version 2 of the GNU General Public
11 * License as published by the Free Software Foundation.
13 * Lustre is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with Lustre; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include <linux/module.h>
23 #include <linux/major.h>
24 #include <linux/smp.h>
26 #define DEBUG_SUBSYSTEM S_PTLBD
28 #include <linux/lustre_lite.h>
29 #include <linux/lustre_ha.h>
30 #include <linux/obd_support.h>
31 #include <linux/lustre_idl.h>
32 #include <linux/obd_ptlbd.h>
36 * assign proper major number
38 * discover actual block sizes?
39 * allow more than one sector per io
41 * restrict single ops to sequential block io
42 * ddn target addresses need to be 32 bit
43 * cant get to addresses after 0xFFFF0000
46 #define PTLBD_MAJOR 253
47 #define PTLBD_MAX_MINOR 1
49 #define MAJOR_NR PTLBD_MAJOR
50 #define LOCAL_END_REQUEST
51 #include <linux/blk.h>
52 #include <linux/blkdev.h>
53 #include <linux/blkpg.h>
54 #include <linux/devfs_fs_kernel.h>
56 static int ptlbd_size_size[PTLBD_MAX_MINOR];
57 static int ptlbd_size[PTLBD_MAX_MINOR];
58 static int ptlbd_hardsect_size[PTLBD_MAX_MINOR];
59 static int ptlbd_max_sectors[PTLBD_MAX_MINOR];
60 //RHism static char ptlbd_dev_varyio[PTLBD_MAX_MINOR];
63 * per minor state, indexed by minor.
66 static struct ptlbd_obd *one_for_now;
68 void ptlbd_blk_register(struct ptlbd_obd *ptlbd)
75 static struct ptlbd_obd * ptlbd_get_minor(int minor)
78 if ( minor >= PTLBD_MAX_MINOR )
79 RETURN( ERR_PTR(-ENODEV) );
83 static struct ptlbd_obd * ptlbd_get_inode(struct inode *inode)
87 if ( inode == NULL ) /* can this really happen? */
88 RETURN( ERR_PTR(-EINVAL) );
90 return ptlbd_get_minor(MINOR(inode->i_rdev));
93 static int ptlbd_open(struct inode *inode, struct file *file)
95 struct ptlbd_obd *ptlbd = ptlbd_get_inode(inode);
99 RETURN(PTR_ERR(ptlbd));
100 if ( ptlbd->bd_import.imp_connection == NULL )
107 static int ptlbd_ioctl(struct inode *inode, struct file *file,
108 unsigned int cmd, unsigned long arg)
110 struct ptlbd_obd *ptlbd;
113 if ( ! capable(CAP_SYS_ADMIN) )
116 ptlbd = ptlbd_get_inode(inode);
118 RETURN( PTR_ERR(ptlbd) );
122 ret = blk_ioctl(inode->i_rdev, cmd, arg);
132 static int ptlbd_release(struct inode *inode, struct file *file)
134 struct ptlbd_obd *ptlbd = ptlbd_get_inode(inode);
138 RETURN( PTR_ERR(ptlbd) );
144 static void ptlbd_end_request_havelock(struct request *req)
146 struct buffer_head *bh;
152 while( (bh = req->bh) != NULL ) {
153 blk_finished_io(bh->b_size >> 9);
154 req->bh = bh->b_reqnext;
155 bh->b_reqnext = NULL;
156 bh->b_end_io(bh, uptodate);
158 blkdev_release_request(req);
162 static void ptlbd_end_request_getlock(struct request *req)
166 spin_lock_irqsave(&io_request_lock, flags);
167 ptlbd_end_request_havelock(req);
168 spin_unlock_irqrestore(&io_request_lock, flags);
172 static void ptlbd_request(request_queue_t *q)
174 struct ptlbd_obd *ptlbd;
179 while ( !QUEUE_EMPTY ) {
181 ptlbd = ptlbd_get_minor(MINOR(req->rq_dev));
183 blkdev_dequeue_request(req);
185 if ( ptlbd->refcount <= 0 ) {
187 ptlbd_end_request_havelock(req);
191 spin_unlock_irq(&io_request_lock);
193 /* XXX dunno if we're supposed to get this or not.. */
194 LASSERT(req->cmd != READA);
196 if ( req->cmd == READ )
201 ptlbd_send_req(ptlbd, cmd, req->bh);
203 spin_lock_irq(&io_request_lock);
205 ptlbd_end_request_havelock(req);
209 static struct block_device_operations ptlbd_ops = {
210 .owner = THIS_MODULE,
212 .release = ptlbd_release,
213 .ioctl = ptlbd_ioctl,
216 int ptlbd_blk_init(void)
222 ret = register_blkdev(PTLBD_MAJOR, "ptlbd", &ptlbd_ops);
226 blk_size[PTLBD_MAJOR] = ptlbd_size;
227 blksize_size[PTLBD_MAJOR] = ptlbd_size_size;
228 hardsect_size[PTLBD_MAJOR] = ptlbd_hardsect_size;
229 max_sectors[PTLBD_MAJOR] = ptlbd_max_sectors;
230 //RHism blkdev_varyio[PTLBD_MAJOR] = ptlbd_dev_varyio;
232 blk_init_queue(BLK_DEFAULT_QUEUE(PTLBD_MAJOR), ptlbd_request);
233 blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR), 0);
235 for ( i = 0 ; i < PTLBD_MAX_MINOR ; i++) {
236 ptlbd_size_size[i] = 4096;
237 ptlbd_size[i] = (4096*2048) >> BLOCK_SIZE_BITS;
238 ptlbd_hardsect_size[i] = 4096;
239 ptlbd_max_sectors[i] = 2;
240 //RHism ptlbd_dev_varyio[i] = 0;
241 /* XXX register_disk? */
247 void ptlbd_blk_exit(void)
251 blk_cleanup_queue(BLK_DEFAULT_QUEUE(PTLBD_MAJOR));
252 ret = unregister_blkdev(PTLBD_MAJOR, "ptlbd");
254 printk("unregister_blkdev() failed: %d\n", ret);