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
);
172 /* This ioctl implementation expects userland to have the device node
173 * permissions set so that only priviledged users can open an aoe
174 * block device directly.
177 aoeblk_ioctl(struct inode
*inode
, struct file
*filp
, uint cmd
, ulong arg
)
184 d
= inode
->i_bdev
->bd_disk
->private_data
;
185 if ((d
->flags
& DEVFL_UP
) == 0) {
186 printk(KERN_ERR
"aoe: aoeblk_ioctl: disk not up\n");
190 if (cmd
== HDIO_GETGEO
) {
191 d
->geo
.start
= get_start_sect(inode
->i_bdev
);
192 if (!copy_to_user((void __user
*) arg
, &d
->geo
, sizeof d
->geo
))
196 printk(KERN_INFO
"aoe: aoeblk_ioctl: unknown ioctl %d\n", cmd
);
200 static struct block_device_operations aoe_bdops
= {
202 .release
= aoeblk_release
,
203 .ioctl
= aoeblk_ioctl
,
204 .owner
= THIS_MODULE
,
207 /* alloc_disk and add_disk can sleep */
209 aoeblk_gdalloc(void *vp
)
211 struct aoedev
*d
= vp
;
215 gd
= alloc_disk(AOE_PARTITIONS
);
217 printk(KERN_ERR
"aoe: aoeblk_gdalloc: cannot allocate disk "
218 "structure for %ld.%ld\n", d
->aoemajor
, d
->aoeminor
);
219 spin_lock_irqsave(&d
->lock
, flags
);
220 d
->flags
&= ~DEVFL_WORKON
;
221 spin_unlock_irqrestore(&d
->lock
, flags
);
225 d
->bufpool
= mempool_create(MIN_BUFS
,
226 mempool_alloc_slab
, mempool_free_slab
,
228 if (d
->bufpool
== NULL
) {
229 printk(KERN_ERR
"aoe: aoeblk_gdalloc: cannot allocate bufpool "
230 "for %ld.%ld\n", d
->aoemajor
, d
->aoeminor
);
232 spin_lock_irqsave(&d
->lock
, flags
);
233 d
->flags
&= ~DEVFL_WORKON
;
234 spin_unlock_irqrestore(&d
->lock
, flags
);
238 spin_lock_irqsave(&d
->lock
, flags
);
239 blk_queue_make_request(&d
->blkq
, aoeblk_make_request
);
240 gd
->major
= AOE_MAJOR
;
241 gd
->first_minor
= d
->sysminor
* AOE_PARTITIONS
;
242 gd
->fops
= &aoe_bdops
;
243 gd
->private_data
= d
;
244 gd
->capacity
= d
->ssize
;
245 snprintf(gd
->disk_name
, sizeof gd
->disk_name
, "etherd/e%ld.%ld",
246 d
->aoemajor
, d
->aoeminor
);
248 gd
->queue
= &d
->blkq
;
250 d
->flags
&= ~DEVFL_WORKON
;
251 d
->flags
|= DEVFL_UP
;
253 spin_unlock_irqrestore(&d
->lock
, flags
);
256 aoedisk_add_sysfs(d
);
258 printk(KERN_INFO
"aoe: %012llx e%lu.%lu v%04x has %llu "
259 "sectors\n", (unsigned long long)mac_addr(d
->addr
),
260 d
->aoemajor
, d
->aoeminor
,
261 d
->fw_ver
, (long long)d
->ssize
);
267 kmem_cache_destroy(buf_pool_cache
);
273 buf_pool_cache
= kmem_cache_create("aoe_bufs",
276 if (buf_pool_cache
== NULL
)