1 /* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */
4 * block device routines
7 #include <linux/hdreg.h>
8 #include <linux/blkdev.h>
10 #include <linux/ioctl.h>
11 #include <linux/genhd.h>
12 #include <linux/netdevice.h>
15 static kmem_cache_t
*buf_pool_cache
;
17 /* add attributes for our block devices in sysfs */
18 static ssize_t
aoedisk_show_state(struct gendisk
* disk
, char *page
)
20 struct aoedev
*d
= disk
->private_data
;
22 return snprintf(page
, PAGE_SIZE
,
24 (d
->flags
& DEVFL_UP
) ? "up" : "down",
25 (d
->flags
& DEVFL_CLOSEWAIT
) ? ",closewait" : "");
27 static ssize_t
aoedisk_show_mac(struct gendisk
* disk
, char *page
)
29 struct aoedev
*d
= disk
->private_data
;
31 return snprintf(page
, PAGE_SIZE
, "%012llx\n",
32 (unsigned long long)mac_addr(d
->addr
));
34 static ssize_t
aoedisk_show_netif(struct gendisk
* disk
, char *page
)
36 struct aoedev
*d
= disk
->private_data
;
38 return snprintf(page
, PAGE_SIZE
, "%s\n", d
->ifp
->name
);
41 static struct disk_attribute disk_attr_state
= {
42 .attr
= {.name
= "state", .mode
= S_IRUGO
},
43 .show
= aoedisk_show_state
45 static struct disk_attribute disk_attr_mac
= {
46 .attr
= {.name
= "mac", .mode
= S_IRUGO
},
47 .show
= aoedisk_show_mac
49 static struct disk_attribute disk_attr_netif
= {
50 .attr
= {.name
= "netif", .mode
= S_IRUGO
},
51 .show
= aoedisk_show_netif
55 aoedisk_add_sysfs(struct aoedev
*d
)
57 sysfs_create_file(&d
->gd
->kobj
, &disk_attr_state
.attr
);
58 sysfs_create_file(&d
->gd
->kobj
, &disk_attr_mac
.attr
);
59 sysfs_create_file(&d
->gd
->kobj
, &disk_attr_netif
.attr
);
62 aoedisk_rm_sysfs(struct aoedev
*d
)
64 sysfs_remove_link(&d
->gd
->kobj
, "state");
65 sysfs_remove_link(&d
->gd
->kobj
, "mac");
66 sysfs_remove_link(&d
->gd
->kobj
, "netif");
70 aoeblk_open(struct inode
*inode
, struct file
*filp
)
75 d
= inode
->i_bdev
->bd_disk
->private_data
;
77 spin_lock_irqsave(&d
->lock
, flags
);
78 if (d
->flags
& DEVFL_UP
) {
80 spin_unlock_irqrestore(&d
->lock
, flags
);
83 spin_unlock_irqrestore(&d
->lock
, flags
);
88 aoeblk_release(struct inode
*inode
, struct file
*filp
)
93 d
= inode
->i_bdev
->bd_disk
->private_data
;
95 spin_lock_irqsave(&d
->lock
, flags
);
97 if (--d
->nopen
== 0 && (d
->flags
& DEVFL_CLOSEWAIT
)) {
98 d
->flags
&= ~DEVFL_CLOSEWAIT
;
99 spin_unlock_irqrestore(&d
->lock
, flags
);
100 aoecmd_cfg(d
->aoemajor
, d
->aoeminor
);
103 spin_unlock_irqrestore(&d
->lock
, flags
);
109 aoeblk_make_request(request_queue_t
*q
, struct bio
*bio
)
116 blk_queue_bounce(q
, &bio
);
118 d
= bio
->bi_bdev
->bd_disk
->private_data
;
119 buf
= mempool_alloc(d
->bufpool
, GFP_NOIO
);
121 printk(KERN_INFO
"aoe: aoeblk_make_request: buf allocation "
123 bio_endio(bio
, bio
->bi_size
, -ENOMEM
);
126 memset(buf
, 0, sizeof(*buf
));
127 INIT_LIST_HEAD(&buf
->bufs
);
129 buf
->resid
= bio
->bi_size
;
130 buf
->sector
= bio
->bi_sector
;
131 buf
->bv
= buf
->bio
->bi_io_vec
;
132 buf
->bv_resid
= buf
->bv
->bv_len
;
133 buf
->bufaddr
= page_address(buf
->bv
->bv_page
) + buf
->bv
->bv_offset
;
135 spin_lock_irqsave(&d
->lock
, flags
);
137 if ((d
->flags
& DEVFL_UP
) == 0) {
138 printk(KERN_INFO
"aoe: aoeblk_make_request: device %ld.%ld is not up\n",
139 d
->aoemajor
, d
->aoeminor
);
140 spin_unlock_irqrestore(&d
->lock
, flags
);
141 mempool_free(buf
, d
->bufpool
);
142 bio_endio(bio
, bio
->bi_size
, -ENXIO
);
146 list_add_tail(&buf
->bufs
, &d
->bufq
);
152 spin_unlock_irqrestore(&d
->lock
, flags
);
158 /* This ioctl implementation expects userland to have the device node
159 * permissions set so that only priviledged users can open an aoe
160 * block device directly.
163 aoeblk_ioctl(struct inode
*inode
, struct file
*filp
, uint cmd
, ulong arg
)
170 d
= inode
->i_bdev
->bd_disk
->private_data
;
171 if ((d
->flags
& DEVFL_UP
) == 0) {
172 printk(KERN_ERR
"aoe: aoeblk_ioctl: disk not up\n");
176 if (cmd
== HDIO_GETGEO
) {
177 d
->geo
.start
= get_start_sect(inode
->i_bdev
);
178 if (!copy_to_user((void __user
*) arg
, &d
->geo
, sizeof d
->geo
))
182 printk(KERN_INFO
"aoe: aoeblk_ioctl: unknown ioctl %d\n", cmd
);
186 static struct block_device_operations aoe_bdops
= {
188 .release
= aoeblk_release
,
189 .ioctl
= aoeblk_ioctl
,
190 .owner
= THIS_MODULE
,
193 /* alloc_disk and add_disk can sleep */
195 aoeblk_gdalloc(void *vp
)
197 struct aoedev
*d
= vp
;
201 gd
= alloc_disk(AOE_PARTITIONS
);
203 printk(KERN_ERR
"aoe: aoeblk_gdalloc: cannot allocate disk "
204 "structure for %ld.%ld\n", d
->aoemajor
, d
->aoeminor
);
205 spin_lock_irqsave(&d
->lock
, flags
);
206 d
->flags
&= ~DEVFL_WORKON
;
207 spin_unlock_irqrestore(&d
->lock
, flags
);
211 d
->bufpool
= mempool_create(MIN_BUFS
,
212 mempool_alloc_slab
, mempool_free_slab
,
214 if (d
->bufpool
== NULL
) {
215 printk(KERN_ERR
"aoe: aoeblk_gdalloc: cannot allocate bufpool "
216 "for %ld.%ld\n", d
->aoemajor
, d
->aoeminor
);
218 spin_lock_irqsave(&d
->lock
, flags
);
219 d
->flags
&= ~DEVFL_WORKON
;
220 spin_unlock_irqrestore(&d
->lock
, flags
);
224 spin_lock_irqsave(&d
->lock
, flags
);
225 blk_queue_make_request(&d
->blkq
, aoeblk_make_request
);
226 gd
->major
= AOE_MAJOR
;
227 gd
->first_minor
= d
->sysminor
* AOE_PARTITIONS
;
228 gd
->fops
= &aoe_bdops
;
229 gd
->private_data
= d
;
230 gd
->capacity
= d
->ssize
;
231 snprintf(gd
->disk_name
, sizeof gd
->disk_name
, "etherd/e%ld.%ld",
232 d
->aoemajor
, d
->aoeminor
);
234 gd
->queue
= &d
->blkq
;
236 d
->flags
&= ~DEVFL_WORKON
;
237 d
->flags
|= DEVFL_UP
;
239 spin_unlock_irqrestore(&d
->lock
, flags
);
242 aoedisk_add_sysfs(d
);
244 printk(KERN_INFO
"aoe: %012llx e%lu.%lu v%04x has %llu "
245 "sectors\n", (unsigned long long)mac_addr(d
->addr
),
246 d
->aoemajor
, d
->aoeminor
,
247 d
->fw_ver
, (long long)d
->ssize
);
253 kmem_cache_destroy(buf_pool_cache
);
259 buf_pool_cache
= kmem_cache_create("aoe_bufs",
262 if (buf_pool_cache
== NULL
)