aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/aoe/aoeblk.c
diff options
context:
space:
mode:
authorEd L. Cashin <ecashin@coraid.com>2008-02-08 07:20:00 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-08 12:22:31 -0500
commit68e0d42f39d85b334d3867a4e5fc2e0e775c1a6c (patch)
treef4cdb47157de4dace5b99e69fc39ea017495922e /drivers/block/aoe/aoeblk.c
parent8911ef4dc97f77797f297318010a7424300d2d50 (diff)
aoe: handle multiple network paths to AoE device
A remote AoE device is something can process ATA commands and is identified by an AoE shelf number and an AoE slot number. Such a device might have more than one network interface, and it might be reachable by more than one local network interface. This patch tracks the available network paths available to each AoE device, allowing them to be used more efficiently. Andrew Morton asked about the call to msleep_interruptible in the revalidate function. Yes, if a signal is pending, then msleep_interruptible will not return 0. That means we will not loop but will call aoenet_xmit with a NULL skb, which is a noop. If the system is too low on memory or the aoe driver is too low on frames, then the user can hit control-C to interrupt the attempt to do a revalidate. I have added a comment to the code summarizing that. Andrew Morton asked whether the allocation performed inside addtgt could use a more relaxed allocation like GFP_KERNEL, but addtgt is called when the aoedev lock has been locked with spin_lock_irqsave. It would be nice to allocate the memory under fewer restrictions, but targets are only added when the device is being discovered, and if the target can't be added right now, we can try again in a minute when then next AoE config query broadcast goes out. Andrew Morton pointed out that the "too many targets" message could be printed for failing GFP_ATOMIC allocations. The last patch in this series makes the messages more specific. Signed-off-by: Ed L. Cashin <ecashin@coraid.com> Cc: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/block/aoe/aoeblk.c')
-rw-r--r--drivers/block/aoe/aoeblk.c62
1 files changed, 55 insertions, 7 deletions
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index 826d12381e21..c2649c954278 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -24,7 +24,7 @@ static ssize_t aoedisk_show_state(struct device *dev,
24 return snprintf(page, PAGE_SIZE, 24 return snprintf(page, PAGE_SIZE,
25 "%s%s\n", 25 "%s%s\n",
26 (d->flags & DEVFL_UP) ? "up" : "down", 26 (d->flags & DEVFL_UP) ? "up" : "down",
27 (d->flags & DEVFL_PAUSE) ? ",paused" : 27 (d->flags & DEVFL_KICKME) ? ",kickme" :
28 (d->nopen && !(d->flags & DEVFL_UP)) ? ",closewait" : ""); 28 (d->nopen && !(d->flags & DEVFL_UP)) ? ",closewait" : "");
29 /* I'd rather see nopen exported so we can ditch closewait */ 29 /* I'd rather see nopen exported so we can ditch closewait */
30} 30}
@@ -33,17 +33,49 @@ static ssize_t aoedisk_show_mac(struct device *dev,
33{ 33{
34 struct gendisk *disk = dev_to_disk(dev); 34 struct gendisk *disk = dev_to_disk(dev);
35 struct aoedev *d = disk->private_data; 35 struct aoedev *d = disk->private_data;
36 struct aoetgt *t = d->targets[0];
36 37
38 if (t == NULL)
39 return snprintf(page, PAGE_SIZE, "none\n");
37 return snprintf(page, PAGE_SIZE, "%012llx\n", 40 return snprintf(page, PAGE_SIZE, "%012llx\n",
38 (unsigned long long)mac_addr(d->addr)); 41 (unsigned long long)mac_addr(t->addr));
39} 42}
40static ssize_t aoedisk_show_netif(struct device *dev, 43static ssize_t aoedisk_show_netif(struct device *dev,
41 struct device_attribute *attr, char *page) 44 struct device_attribute *attr, char *page)
42{ 45{
43 struct gendisk *disk = dev_to_disk(dev); 46 struct gendisk *disk = dev_to_disk(dev);
44 struct aoedev *d = disk->private_data; 47 struct aoedev *d = disk->private_data;
48 struct net_device *nds[8], **nd, **nnd, **ne;
49 struct aoetgt **t, **te;
50 struct aoeif *ifp, *e;
51 char *p;
52
53 memset(nds, 0, sizeof nds);
54 nd = nds;
55 ne = nd + ARRAY_SIZE(nds);
56 t = d->targets;
57 te = t + NTARGETS;
58 for (; t < te && *t; t++) {
59 ifp = (*t)->ifs;
60 e = ifp + NAOEIFS;
61 for (; ifp < e && ifp->nd; ifp++) {
62 for (nnd = nds; nnd < nd; nnd++)
63 if (*nnd == ifp->nd)
64 break;
65 if (nnd == nd && nd != ne)
66 *nd++ = ifp->nd;
67 }
68 }
45 69
46 return snprintf(page, PAGE_SIZE, "%s\n", d->ifp->name); 70 ne = nd;
71 nd = nds;
72 if (*nd == NULL)
73 return snprintf(page, PAGE_SIZE, "none\n");
74 for (p = page; nd < ne; nd++)
75 p += snprintf(p, PAGE_SIZE - (p-page), "%s%s",
76 p == page ? "" : ",", (*nd)->name);
77 p += snprintf(p, PAGE_SIZE - (p-page), "\n");
78 return p-page;
47} 79}
48/* firmware version */ 80/* firmware version */
49static ssize_t aoedisk_show_fwver(struct device *dev, 81static ssize_t aoedisk_show_fwver(struct device *dev,
@@ -134,7 +166,23 @@ aoeblk_make_request(struct request_queue *q, struct bio *bio)
134 166
135 blk_queue_bounce(q, &bio); 167 blk_queue_bounce(q, &bio);
136 168
169 if (bio == NULL) {
170 printk(KERN_ERR "aoe: bio is NULL\n");
171 BUG();
172 return 0;
173 }
137 d = bio->bi_bdev->bd_disk->private_data; 174 d = bio->bi_bdev->bd_disk->private_data;
175 if (d == NULL) {
176 printk(KERN_ERR "aoe: bd_disk->private_data is NULL\n");
177 BUG();
178 bio_endio(bio, -ENXIO);
179 return 0;
180 } else if (bio->bi_io_vec == NULL) {
181 printk(KERN_ERR "aoe: bi_io_vec is NULL\n");
182 BUG();
183 bio_endio(bio, -ENXIO);
184 return 0;
185 }
138 buf = mempool_alloc(d->bufpool, GFP_NOIO); 186 buf = mempool_alloc(d->bufpool, GFP_NOIO);
139 if (buf == NULL) { 187 if (buf == NULL) {
140 printk(KERN_INFO "aoe: buf allocation failure\n"); 188 printk(KERN_INFO "aoe: buf allocation failure\n");
@@ -143,14 +191,14 @@ aoeblk_make_request(struct request_queue *q, struct bio *bio)
143 } 191 }
144 memset(buf, 0, sizeof(*buf)); 192 memset(buf, 0, sizeof(*buf));
145 INIT_LIST_HEAD(&buf->bufs); 193 INIT_LIST_HEAD(&buf->bufs);
146 buf->start_time = jiffies; 194 buf->stime = jiffies;
147 buf->bio = bio; 195 buf->bio = bio;
148 buf->resid = bio->bi_size; 196 buf->resid = bio->bi_size;
149 buf->sector = bio->bi_sector; 197 buf->sector = bio->bi_sector;
150 buf->bv = &bio->bi_io_vec[bio->bi_idx]; 198 buf->bv = &bio->bi_io_vec[bio->bi_idx];
151 WARN_ON(buf->bv->bv_len == 0);
152 buf->bv_resid = buf->bv->bv_len; 199 buf->bv_resid = buf->bv->bv_len;
153 buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset; 200 WARN_ON(buf->bv_resid == 0);
201 buf->bv_off = buf->bv->bv_offset;
154 202
155 spin_lock_irqsave(&d->lock, flags); 203 spin_lock_irqsave(&d->lock, flags);
156 204
@@ -229,7 +277,7 @@ aoeblk_gdalloc(void *vp)
229 gd->fops = &aoe_bdops; 277 gd->fops = &aoe_bdops;
230 gd->private_data = d; 278 gd->private_data = d;
231 gd->capacity = d->ssize; 279 gd->capacity = d->ssize;
232 snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%ld", 280 snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d",
233 d->aoemajor, d->aoeminor); 281 d->aoemajor, d->aoeminor);
234 282
235 gd->queue = &d->blkq; 283 gd->queue = &d->blkq;