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
);
40 /* firmware version */
41 static ssize_t
aoedisk_show_fwver(struct gendisk
* disk
, char *page
)
43 struct aoedev
*d
= disk
->private_data
;
45 return snprintf(page
, PAGE_SIZE
, "0x%04x\n", (unsigned int) d
->fw_ver
);
48 static struct disk_attribute disk_attr_state
= {
49 .attr
= {.name
= "state", .mode
= S_IRUGO
},
50 .show
= aoedisk_show_state
52 static struct disk_attribute disk_attr_mac
= {
53 .attr
= {.name
= "mac", .mode
= S_IRUGO
},
54 .show
= aoedisk_show_mac
56 static struct disk_attribute disk_attr_netif
= {
57 .attr
= {.name
= "netif", .mode
= S_IRUGO
},
58 .show
= aoedisk_show_netif
60 static struct disk_attribute disk_attr_fwver
= {
61 .attr
= {.name
= "firmware-version", .mode
= S_IRUGO
},
62 .show
= aoedisk_show_fwver
66 aoedisk_add_sysfs(struct aoedev
*d
)
68 sysfs_create_file(&d
->gd
->kobj
, &disk_attr_state
.attr
);
69 sysfs_create_file(&d
->gd
->kobj
, &disk_attr_mac
.attr
);
70 sysfs_create_file(&d
->gd
->kobj
, &disk_attr_netif
.attr
);
71 sysfs_create_file(&d
->gd
->kobj
, &disk_attr_fwver
.attr
);
74 aoedisk_rm_sysfs(struct aoedev
*d
)
76 sysfs_remove_link(&d
->gd
->kobj
, "state");
77 sysfs_remove_link(&d
->gd
->kobj
, "mac");
78 sysfs_remove_link(&d
->gd
->kobj
, "netif");
79 sysfs_remove_link(&d
->gd
->kobj
, "firmware-version");
83 aoeblk_open(struct inode
*inode
, struct file
*filp
)
88 d
= inode
->i_bdev
->bd_disk
->private_data
;
90 spin_lock_irqsave(&d
->lock
, flags
);
91 if (d
->flags
& DEVFL_UP
) {
93 spin_unlock_irqrestore(&d
->lock
, flags
);
96 spin_unlock_irqrestore(&d
->lock
, flags
);
101 aoeblk_release(struct inode
*inode
, struct file
*filp
)
106 d
= inode
->i_bdev
->bd_disk
->private_data
;
108 spin_lock_irqsave(&d
->lock
, flags
);
110 if (--d
->nopen
== 0 && (d
->flags
& DEVFL_CLOSEWAIT
)) {
111 d
->flags
&= ~DEVFL_CLOSEWAIT
;
112 spin_unlock_irqrestore(&d
->lock
, flags
);
113 aoecmd_cfg(d
->aoemajor
, d
->aoeminor
);
116 spin_unlock_irqrestore(&d
->lock
, flags
);
122 aoeblk_make_request(request_queue_t
*q
, struct bio
*bio
)
129 blk_queue_bounce(q
, &bio
);
131 d
= bio
->bi_bdev
->bd_disk
->private_data
;
132 buf
= mempool_alloc(d
->bufpool
, GFP_NOIO
);
134 printk(KERN_INFO
"aoe: aoeblk_make_request: buf allocation "
136 bio_endio(bio
, bio
->bi_size
, -ENOMEM
);
139 memset(buf
, 0, sizeof(*buf
));
140 INIT_LIST_HEAD(&buf
->bufs
);
141 buf
->start_time
= jiffies
;
143 buf
->resid
= bio
->bi_size
;
144 buf
->sector
= bio
->bi_sector
;
145 buf
->bv
= buf
->bio
->bi_io_vec
;
146 buf
->bv_resid
= buf
->bv
->bv_len
;
147 buf
->bufaddr
= page_address(buf
->bv
->bv_page
) + buf
->bv
->bv_offset
;
149 spin_lock_irqsave(&d
->lock
, flags
);
151 if ((d
->flags
& DEVFL_UP
) == 0) {
152 printk(KERN_INFO
"aoe: aoeblk_make_request: device %ld.%ld is not up\n",
153 d
->aoemajor
, d
->aoeminor
);
154 spin_unlock_irqrestore(&d
->lock
, flags
);
155 mempool_free(buf
, d
->bufpool
);
156 bio_endio(bio
, bio
->bi_size
, -ENXIO
);
160 list_add_tail(&buf
->bufs
, &d
->bufq
);
164 d
->sendq_hd
= d
->sendq_tl
= NULL
;
166 spin_unlock_irqrestore(&d
->lock
, flags
);
173 aoeblk_getgeo(struct block_device
*bdev
, struct hd_geometry
*geo
)
175 struct aoedev
*d
= bdev
->bd_disk
->private_data
;
177 if ((d
->flags
& DEVFL_UP
) == 0) {
178 printk(KERN_ERR
"aoe: aoeblk_ioctl: disk not up\n");
182 geo
->cylinders
= d
->geo
.cylinders
;
183 geo
->heads
= d
->geo
.heads
;
184 geo
->sectors
= d
->geo
.sectors
;
188 static struct block_device_operations aoe_bdops
= {
190 .release
= aoeblk_release
,
191 .getgeo
= aoeblk_getgeo
,
192 .owner
= THIS_MODULE
,
195 /* alloc_disk and add_disk can sleep */
197 aoeblk_gdalloc(void *vp
)
199 struct aoedev
*d
= vp
;
203 gd
= alloc_disk(AOE_PARTITIONS
);
205 printk(KERN_ERR
"aoe: aoeblk_gdalloc: cannot allocate disk "
206 "structure for %ld.%ld\n", d
->aoemajor
, d
->aoeminor
);
207 spin_lock_irqsave(&d
->lock
, flags
);
208 d
->flags
&= ~DEVFL_WORKON
;
209 spin_unlock_irqrestore(&d
->lock
, flags
);
213 d
->bufpool
= mempool_create(MIN_BUFS
,
214 mempool_alloc_slab
, mempool_free_slab
,
216 if (d
->bufpool
== NULL
) {
217 printk(KERN_ERR
"aoe: aoeblk_gdalloc: cannot allocate bufpool "
218 "for %ld.%ld\n", d
->aoemajor
, d
->aoeminor
);
220 spin_lock_irqsave(&d
->lock
, flags
);
221 d
->flags
&= ~DEVFL_WORKON
;
222 spin_unlock_irqrestore(&d
->lock
, flags
);
226 spin_lock_irqsave(&d
->lock
, flags
);
227 blk_queue_make_request(&d
->blkq
, aoeblk_make_request
);
228 gd
->major
= AOE_MAJOR
;
229 gd
->first_minor
= d
->sysminor
* AOE_PARTITIONS
;
230 gd
->fops
= &aoe_bdops
;
231 gd
->private_data
= d
;
232 gd
->capacity
= d
->ssize
;
233 snprintf(gd
->disk_name
, sizeof gd
->disk_name
, "etherd/e%ld.%ld",
234 d
->aoemajor
, d
->aoeminor
);
236 gd
->queue
= &d
->blkq
;
238 d
->flags
&= ~DEVFL_WORKON
;
239 d
->flags
|= DEVFL_UP
;
241 spin_unlock_irqrestore(&d
->lock
, flags
);
244 aoedisk_add_sysfs(d
);
246 printk(KERN_INFO
"aoe: %012llx e%lu.%lu v%04x has %llu "
247 "sectors\n", (unsigned long long)mac_addr(d
->addr
),
248 d
->aoemajor
, d
->aoeminor
,
249 d
->fw_ver
, (long long)d
->ssize
);
255 kmem_cache_destroy(buf_pool_cache
);
261 buf_pool_cache
= kmem_cache_create("aoe_bufs",
264 if (buf_pool_cache
== NULL
)