aoe: improve handling of misbehaving network paths
Subsystems (3)
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/7 aoe: improve handling of misbehaving network paths
An AoE target can have multiple network ports used for AoE, and in the aoe driver, those are tracked by the aoetgt struct. These changes allow the aoe driver to handle network paths, or aoetgts, that are not working well, compared to the others.
Paths that do not get responses despite the retransmission of AoE commands are marked as "tainted", and non-tainted paths are preferred.
Meanwhile, the aoe driver attempts to "probe" the tainted path in the background by issuing reads of LBA 0 that are padded out to full (possibly jumbo-frame) size. If the probes get responses, then the path is "redeemed", and its taint is removed.
This mechanism has been shown to be helpful in transparently handling and recovering from real-world network "brown outs" in ways that the earlier "shoot the help-needing target in the head" mechanism could not.
--- drivers/block/aoe/aoe.h | 11 ++- drivers/block/aoe/aoecmd.c | 377 ++++++++++++++++++++++++++++++-------------- drivers/block/aoe/aoedev.c | 1 - 3 files changed, 268 insertions(+), 121 deletions(-)
drivers/block/aoe/aoe.h +10 -1
@@ -91,6 +91,9 @@ enum {RTTDSCALE =3 ,RTTAVG_INIT =USEC_PER_SEC /4 <<RTTSCALE ,RTTDEV_INIT =RTTAVG_INIT /4 , + +HARD_SCORN_SECS =10 ,/* try another remote port after this */ + MAX_TAINT = 1000, /* cap on aoetgt taint */ }; struct buf {
@@ -103,6 +106,10 @@ struct buf {struct request *rq; }; +enum frame_flags { +FFL_PROBE =1 , +}; +struct frame {struct list_head head;u32 tag;
@@ -118,6 +125,7 @@ struct frame {struct bio_vec *bv;ulong bcnt;ulong bv_off; +char flags; };struct aoeif {
@@ -138,8 +146,10 @@ struct aoetgt {ushort next_cwnd;/* incr maxout after decrementing to zero */ ushort ssthresh;/* slow start threshold */ ulong falloc;/* number of allocated frames */ +int taint;/* how much we want to avoid this aoetgt */ int minbcnt;int wpkts, rpkts; +char nout_probes; };struct aoedev {
@@ -174,7 +184,6 @@ struct aoedev {struct list_head rexmitq;/* deferred retransmissions */ struct aoetgt *targets[NTARGETS ];struct aoetgt **tgt;/* target in use when working */ -struct aoetgt *htgt;/* target needing rexmit assistance */ ulong ntargets;ulong kicked;char ident[512 ];
drivers/block/aoe/aoecmd.c +258 -119
602 lines not on this page · raw message
drivers/block/aoe/aoedev.c +0 -1
@@ -223,7 +223,6 @@ aoedev_downdev(struct aoedev *d)/* clean out the in-process request (if any) */ aoe_failip (d); - d->htgt =NULL ;/* fast fail all pending I/O */ if (d->blkq) {
Signature · 1 line
1.7.1
Quoted 24 lines · On Mon, 3 Dec 2012 20:40:55 -0500 Ed Cashin <[email protected]> wrote:
An AoE target can have multiple network ports used for AoE, and in the aoe driver, those are tracked by the aoetgt struct. These changes allow the aoe driver to handle network paths, or aoetgts, that are not working well, compared to the others.
Paths that do not get responses despite the retransmission of AoE commands are marked as "tainted", and non-tainted paths are preferred.
Meanwhile, the aoe driver attempts to "probe" the tainted path in the background by issuing reads of LBA 0 that are padded out to full (possibly jumbo-frame) size. If the probes get responses, then the path is "redeemed", and its taint is removed.
This mechanism has been shown to be helpful in transparently handling and recovering from real-world network "brown outs" in ways that the earlier "shoot the help-needing target in the head" mechanism could not.
...
drivers/block/aoe/aoecmd.c +2
-0+static void +ata_rw_frameinit (struct frame *f)
drivers/block/aoe/aoecmd.c fhash(struct frame *f) · line 322
Quoted 10 lines
drivers/block/aoe/aoecmd.c +10
-0+{ +struct aoetgt *t; +struct aoe_hdr *h; +struct aoe_atahdr *ah; +struct sk_buff *skb; +char writebit, extbit; + + skb = f->skb; + h = (struct aoe_hdr *)skb_mac_header (skb); + ah = (struct aoe_atahdr *) (h +1 );
Well. It would be neater to have a
struct whatever {
struct aoe_hdr hdr;
struct aoe_atahdr atahdr;
};Quoted 15 lines
drivers/block/aoe/aoecmd.c +6
-2+skb_put (skb,sizeof (*h) +sizeof (*ah)); +memset (h,0 , skb->len); + + writebit =0x10 ; + extbit =0x4 ; +@@ -462,11 +488,14 @@ resend(struct aoedev *d, struct frame *f) h = (struct aoe_hdr *)skb_mac_header (skb); ah = (struct aoe_atahdr *) (h+1 ); - snprintf(buf, sizeof buf, - "%15s e%ld.%d oldtag=%08x@%08lx newtag=%08x s=%pm d=%pm nout=%d\n",
drivers/block/aoe/aoecmd.c resend(struct aoedev *d, struct frame *f) · line 497
Quoted 10 lines
drivers/block/aoe/aoecmd.c +7
-3-"retransmit" , d->aoemajor, d->aoeminor, f->tag, jiffies, n, - h->src, h->dst, t->nout); -aoechr_error (buf); +if (!(f->flags &FFL_PROBE )) { +snprintf (buf,sizeof (buf), +"%15s e%ld.%d oldtag=%08x@%08lx newtag=%08x s=%pm d=%pm nout=%d\n" , +"retransmit" , d->aoemajor, d->aoeminor, + f->tag, jiffies, n, + h->src, h->dst, t->nout); +aoechr_error (buf);
Could use kasprintf() here. That avoids the fixed-size local buffer and avoids the GFP_ATOMIC allocation and copy in aoechr_error().
Quoted 6 lines
drivers/block/aoe/aoecmd.c +1
-0+ } f->tag = n;fhash (f);
drivers/block/aoe/aoecmd.c aoe_flush_iocq(void) · line 1721
Quoted 10 lines
drivers/block/aoe/aoecmd.c +7
-0aoecmd_init (void) { +void *p; + +/* get_zeroed_page returns page with ref count 1 */ + p = (void *)get_zeroed_page (GFP_KERNEL | __GFP_REPEAT); +if (!p) +return -ENOMEM ; + empty_page =virt_to_page (p);
Could use alloc_pages() and remove `p' and the virt_to_page().
Why is __GFP_REPEAT used? I don't think this __init function is more important than all the other ones in the kernel?
Quoted 6 lines
drivers/block/aoe/aoecmd.c +0
-0INIT_LIST_HEAD (&iocq.head);spin_lock_init (&iocq.lock);init_waitqueue_head (&ktiowq);
Quoted 2 lines · Andrew Morton
On Mon, 3 Dec 2012 20:40:55 -0500
Ed Cashin <[email protected]> wrote:
...
Quoted 15 lines
drivers/block/aoe/aoecmd.c fhash(struct frame *f) · line 322
Quoted 12 lines
drivers/block/aoe/aoecmd.c +12
-0+static void +ata_rw_frameinit (struct frame *f) +{ +struct aoetgt *t; +struct aoe_hdr *h; +struct aoe_atahdr *ah; +struct sk_buff *skb; +char writebit, extbit; + + skb = f->skb; + h = (struct aoe_hdr *)skb_mac_header (skb); + ah = (struct aoe_atahdr *) (h +1 );Well. It would be neater to have a
Quoted 4 lines
struct whatever {
struct aoe_hdr hdr;
struct aoe_atahdr atahdr;
};This code just moved from aoecmd_ata_rw into a function that can be used by both aoecmd_ata_rw() and the new probe() function, so this "h+1" way of getting at the ATA header is not new. I'll make a note of your recommendation for future new code and for cleanups.
...
Quoted 4 lines
Quoted 4 lines
drivers/block/aoe/aoecmd.c +0
-0@@ -462,11 +488,14 @@ resend(struct aoedev *d, struct frame *f) h = (struct aoe_hdr *)skb_mac_header (skb); ah = (struct aoe_atahdr *) (h+1 );
Quoted 15 lines
drivers/block/aoe/aoecmd.c resend(struct aoedev *d, struct frame *f) · line 497
Quoted 12 lines
drivers/block/aoe/aoecmd.c +7
-5-snprintf (buf,sizeof buf, -"%15s e%ld.%d oldtag=%08x@%08lx newtag=%08x s=%pm d=%pm nout=%d\n" , -"retransmit" , d->aoemajor, d->aoeminor, f->tag, jiffies, n, - h->src, h->dst, t->nout); -aoechr_error (buf); +if (!(f->flags &FFL_PROBE )) { +snprintf (buf,sizeof (buf), +"%15s e%ld.%d oldtag=%08x@%08lx newtag=%08x s=%pm d=%pm nout=%d\n" , +"retransmit" , d->aoemajor, d->aoeminor, + f->tag, jiffies, n, + h->src, h->dst, t->nout); +aoechr_error (buf);Could use
kasprintf()here. That avoids the fixed-size local buffer and avoids theGFP_ATOMICallocation and copy inaoechr_error().
This patch doesn't change the way aoechr_error() is used. But thinking about the suggestion, I see that avoiding the GFP_ATOMIC allocation isn't practical here, because resend() is called after spin_lock_irq(). Let me know if you still think it would be worth cleaning up. It could go on the todo list.
...
Quoted 12 lines
drivers/block/aoe/aoecmd.c aoe_flush_iocq(void) · line 1721
Quoted 9 lines
drivers/block/aoe/aoecmd.c +7
-0aoecmd_init (void) { +void *p; + +/* get_zeroed_page returns page with ref count 1 */ + p = (void *)get_zeroed_page (GFP_KERNEL | __GFP_REPEAT); +if (!p) +return -ENOMEM ; + empty_page =virt_to_page (p);Could use
alloc_pages()and remove `p' and thevirt_to_page().
Quoted 2 lines
Why is
__GFP_REPEATused? I don't think this__initfunction is more important than all the other ones in the kernel?
I think you are not implying that it's hurting the rest of the kernel for __GFP_REPEAT to be used here but that you mean the aoe driver's initialization should behave like the other initialization code in the kernel, and nobody else is using __GFP_REPEAT, so aoe should follow suit. Please let me know if I'm misinterpreting your feedback.
Anyway, it's fine with me if you want to remove __GFP_REPEAT, or I can resubmit this patch without it if you prefer.
Signature · 2 lines
Ed Cashin [email protected]
PATCH 2/7 aoe: avoid races between device destruction and discovery
In reply to a message not in the archiveThis change avoids a race that could result in a NULL pointer derference following a WARNing from kobject_add_internal, "don't try to register things with the same name in the same directory."
The problem was found with a test that forgets and discovers an aoe device in a loop:
while test ! -r /tmp/stop; do
aoe-flush -a
aoe-discover
done
The race was between aoedev_flush taking aoedevs out of the devlist, allowing a new discovery of the same AoE target to take place before the driver gets around to calling sysfs_remove_group. Fixing that one revealed another race between do_open and add_disk, and this patch avoids that, too.
The fix required some care, because for flushing (forgetting) an aoedev, some of the steps must be performed under lock and some must be able to sleep. Also, for discovering a new aoedev, some steps might sleep.
The check for a bad aoedev pointer remains from a time when about half of this patch was done, and it was possible for the bdev->bd_disk->private_data to become corrupted. The check should be removed eventually, but it is not expected to add significant overhead, occurring in the aoeblk_open routine.
--- drivers/block/aoe/aoe.h | 7 ++- drivers/block/aoe/aoeblk.c | 36 +++++++++- drivers/block/aoe/aoedev.c | 166 ++++++++++++++++++++++++++++---------------- 3 files changed, 146 insertions(+), 63 deletions(-)
drivers/block/aoe/aoe.h +5 -2
@@ -74,8 +74,11 @@ enum {DEVFL_TKILL = (1 <<1 ),/* flag for timer to know when to kill self */ DEVFL_EXT = (1 <<2 ),/* device accepts lba48 commands */ DEVFL_GDALLOC = (1 <<3 ),/* need to alloc gendisk */ -DEVFL_KICKME = (1 <<4 ),/* slow polling network card catch */ - DEVFL_NEWSIZE = (1<<5), /* need to update dev size in block layer */ +DEVFL_GD_NOW = (1 <<4 ),/* allocating gendisk */ +DEVFL_KICKME = (1 <<5 ),/* slow polling network card catch */ +DEVFL_NEWSIZE = (1 <<6 ),/* need to update dev size in block layer */ +DEVFL_FREEING = (1 <<7 ),/* set when device is being cleaned up */ + DEVFL_FREED = (1<<8), /* device has been cleaned up */ }; enum {
drivers/block/aoe/aoeblk.c +34 -2
@@ -147,9 +147,18 @@ aoeblk_open(struct block_device *bdev, fmode_t mode)struct aoedev *d = bdev->bd_disk->private_data;ulong flags; +if (!virt_addr_valid (d)) { +pr_crit ("aoe: invalid device pointer in %s\n" , + __func__); +WARN_ON (1 ); +return -ENODEV ; + } +if (!(d->flags &DEVFL_UP ) || d->flags &DEVFL_TKILL ) +return -ENODEV ; +mutex_lock (&aoeblk_mutex);spin_lock_irqsave (&d->lock, flags); -if (d->flags &DEVFL_UP ) { +if (d->flags &DEVFL_UP && !(d->flags &DEVFL_TKILL )) { d->nopen++;spin_unlock_irqrestore (&d->lock, flags);mutex_unlock (&aoeblk_mutex);
@@ -259,6 +268,18 @@ aoeblk_gdalloc(void *vp)struct request_queue *q;enum {KB =1024 ,MB =KB *KB ,READ_AHEAD =2 *MB , };ulong flags; +int late =0 ; + +spin_lock_irqsave (&d->lock, flags); +if (d->flags &DEVFL_GDALLOC + && !(d->flags &DEVFL_TKILL ) + && !(d->flags &DEVFL_GD_NOW )) + d->flags |=DEVFL_GD_NOW ; +else + late =1 ; +spin_unlock_irqrestore (&d->lock, flags); +if (late) +return ; gd =alloc_disk (AOE_PARTITIONS );if (gd ==NULL ) {
@@ -282,6 +303,11 @@ aoeblk_gdalloc(void *vp) }spin_lock_irqsave (&d->lock, flags); +WARN_ON (!(d->flags &DEVFL_GD_NOW )); +WARN_ON (!(d->flags &DEVFL_GDALLOC )); +WARN_ON (d->flags &DEVFL_TKILL ); +WARN_ON (d->gd); +WARN_ON (d->flags &DEVFL_UP );blk_queue_max_hw_sectors (q,BLK_DEF_MAX_SECTORS ); q->backing_dev_info.name ="aoe" ; q->backing_dev_info.ra_pages =READ_AHEAD /PAGE_CACHE_SIZE ;
@@ -306,6 +332,11 @@ aoeblk_gdalloc(void *vp)add_disk (gd);aoedisk_add_sysfs (d); + +spin_lock_irqsave (&d->lock, flags); +WARN_ON (!(d->flags &DEVFL_GD_NOW )); + d->flags &= ~DEVFL_GD_NOW ; +spin_unlock_irqrestore (&d->lock, flags);return ; err_mempool:
@@ -314,7 +345,8 @@ err_disk:put_disk (gd); err:spin_lock_irqsave (&d->lock, flags); - d->flags &= ~DEVFL_GDALLOC ; + d->flags &= ~DEVFL_GD_NOW ; +schedule_work (&d->work);spin_unlock_irqrestore (&d->lock, flags); }
drivers/block/aoe/aoedev.c +107 -59
227 lines not on this page · raw message
Signature · 1 line
1.7.1
Re: [PATCH 2/7] aoe: avoid races between device destruction and discovery
Quoted 35 lines · On Mon, 3 Dec 2012 20:42:56 -0500 Ed Cashin <[email protected]> wrote:
This change avoids a race that could result in a NULL pointer derference following a WARNing from
kobject_add_internal, "don't try to register things with the same name in the same directory."The problem was found with a test that forgets and discovers an aoe device in a loop:
while test ! -r
/tmp/stop; do
aoe-flush -a
aoe-discover
doneThe race was between
aoedev_flushtaking aoedevs out of the devlist, allowing a new discovery of the same AoE target to take place before the driver gets around to callingsysfs_remove_group. Fixing that one revealed another race betweendo_openandadd_disk, and this patch avoids that, too.The fix required some care, because for flushing (forgetting) an aoedev, some of the steps must be performed under lock and some must be able to sleep. Also, for discovering a new aoedev, some steps might sleep.
The check for a bad aoedev pointer remains from a time when about half of this patch was done, and it was possible for the
bdev->bd_disk->private_datato become corrupted. The check should be removed eventually, but it is not expected to add significant overhead, occurring in theaoeblk_openroutine....
drivers/block/aoe/aoeblk.c aoeblk_open(struct block_device *bdev, fmode_t mode) · line 155
Quoted 9 lines
drivers/block/aoe/aoeblk.c +6
-0@@ -147,9 +147,18 @@ aoeblk_open(struct block_device *bdev, fmode_t mode)struct aoedev *d = bdev->bd_disk->private_data;ulong flags; +if (!virt_addr_valid (d)) { +pr_crit ("aoe: invalid device pointer in %s\n" , + __func__); +WARN_ON (1 ); +return -ENODEV ; + }
Can this ever happen?
Quoted 11 lines
drivers/block/aoe/aoeblk.c +4
-1+if (!(d->flags &DEVFL_UP ) || d->flags &DEVFL_TKILL ) +return -ENODEV ; +mutex_lock (&aoeblk_mutex);spin_lock_irqsave (&d->lock, flags); -if (d->flags &DEVFL_UP ) { +if (d->flags &DEVFL_UP && !(d->flags &DEVFL_TKILL )) { d->nopen++;spin_unlock_irqrestore (&d->lock, flags);mutex_unlock (&aoeblk_mutex);
drivers/block/aoe/aoeblk.c aoeblk_gdalloc(void *vp) · line 276
Quoted 9 lines
drivers/block/aoe/aoeblk.c +6
-0@@ -259,6 +268,18 @@ aoeblk_gdalloc(void *vp)struct request_queue *q;enum {KB =1024 ,MB =KB *KB ,READ_AHEAD =2 *MB , };ulong flags; +int late =0 ; + +spin_lock_irqsave (&d->lock, flags); +if (d->flags &DEVFL_GDALLOC + && !(d->flags &DEVFL_TKILL ) + && !(d->flags &DEVFL_GD_NOW ))
That's pretty sickly-looking code layout.
We often do
if ((d->flags & (DEVFL_GDALLOC|DEVFL_TKILL|DEVFL_GD_NOW)) == DEVFL_GDALLOC)
in these cases.
Quoted 12 lines
drivers/block/aoe/aoeblk.c +6
-0+ d->flags |=DEVFL_GD_NOW ; + else + late =1 ; +spin_unlock_irqrestore (&d->lock, flags); +if (late) +return ; gd =alloc_disk (AOE_PARTITIONS );if (gd ==NULL ) {
Re: [PATCH 2/7] aoe: avoid races between device destruction and discovery
Quoted 6 lines · Andrew Morton
Quoted 3 lines · On Mon, 3 Dec 2012 20:42:56 -0500 Ed Cashin <[email protected]> wrote:
This change avoids a race that could result in a NULL pointer derference following a WARNing from
kobject_add_internal, "don't try to register things with the same name in the same directory."
...
Quoted 5 lines
Quoted 5 lines
The check for a bad aoedev pointer remains from a time when about half of this patch was done, and it was possible for the
bdev->bd_disk->private_datato become corrupted. The check should be removed eventually, but it is not expected to add significant overhead, occurring in theaoeblk_openroutine.
...
Quoted 6 lines
Quoted 6 lines
drivers/block/aoe/aoeblk.c +0
-0@@ -147,9 +147,18 @@ aoeblk_open(struct block_device *bdev, fmode_t mode)struct aoedev *d = bdev->bd_disk->private_data;ulong flags;
Quoted 8 lines
drivers/block/aoe/aoeblk.c aoeblk_open(struct block_device *bdev, fmode_t mode) · line 155
Quoted 6 lines
drivers/block/aoe/aoeblk.c +6
-0+if (!virt_addr_valid (d)) { +pr_crit ("aoe: invalid device pointer in %s\n" , + __func__); +WARN_ON (1 ); +return -ENODEV ; + }Can this ever happen?
This is the check mentioned in the last paragraph of the changelog message. I don't think it can happen now. Folks have been using it like this and nobody has seen the invalid device pointer message.
I'll go ahead and remove the check and resubmit the patch.
...
Quoted 13 lines
drivers/block/aoe/aoeblk.c aoeblk_gdalloc(void *vp) · line 276
Quoted 10 lines
drivers/block/aoe/aoeblk.c +6
-0@@ -259,6 +268,18 @@ aoeblk_gdalloc(void *vp)struct request_queue *q;enum {KB =1024 ,MB =KB *KB ,READ_AHEAD =2 *MB , };ulong flags; +int late =0 ; + +spin_lock_irqsave (&d->lock, flags); +if (d->flags &DEVFL_GDALLOC + && !(d->flags &DEVFL_TKILL ) + && !(d->flags &DEVFL_GD_NOW ))That's pretty sickly-looking code layout.
Quoted 6 lines
We often do
if ((d->flags & (DEVFL_GDALLOC|DEVFL_TKILL|DEVFL_GD_NOW)) == DEVFL_GDALLOC)in these cases.
OK. When I'm resubmitting these patches, I'm planning to submit the series of 7 patches and include info in the cover letter about what has changed in the resubmission.
Signature · 2 lines
Ed Cashin [email protected]
PATCH 3/7 aoe: use dynamic number of remote ports for AoE storage target
In reply to a message not in the archiveMany AoE targets have four or fewer network ports, but some existing storage devices have many, and the AoE protocol sets no limit.
This patch allows the use of more than eight remote MAC addresses per AoE target, while reducing the amount of memory used by the aoe driver in cases where there are many AoE targets with fewer than eight MAC addresses each.
--- drivers/block/aoe/aoe.h | 6 ++-- drivers/block/aoe/aoeblk.c | 2 +- drivers/block/aoe/aoecmd.c | 50 ++++++++++++++++++++++++++++++------------- drivers/block/aoe/aoedev.c | 12 ++++++++- 4 files changed, 49 insertions(+), 21 deletions(-)
drivers/block/aoe/aoe.h +3 -3
@@ -84,7 +84,7 @@ enum {enum {DEFAULTBCNT =2 *512 ,/* 2 sectors */ MIN_BUFS =16 , -NTARGETS =8 , +NTARGETS =4 ,NAOEIFS =8 ,NSKBPOOLMAX =256 ,NFACTIVE =61 ,
@@ -185,9 +185,9 @@ struct aoedev {ulong maxbcnt;struct list_head factive[NFACTIVE ];/* hash of active frames */ struct list_head rexmitq;/* deferred retransmissions */ -struct aoetgt *targets[NTARGETS ]; +struct aoetgt **targets; +ulong ntargets;/* number of allocated aoetgt pointers */ struct aoetgt **tgt;/* target in use when working */ -ulong ntargets;ulong kicked;char ident[512 ]; };
drivers/block/aoe/aoeblk.c +1 -1
@@ -67,7 +67,7 @@ static ssize_t aoedisk_show_netif(struct device *dev, nd = nds; ne = nd +ARRAY_SIZE (nds); t = d->targets; - te = t +NTARGETS ; + te = t + d->ntargets;for (; t < te && *t; t++) { ifp = (*t)->ifs; e = ifp +NAOEIFS ;
drivers/block/aoe/aoecmd.c +35 -15
104 lines not on this page · raw message
drivers/block/aoe/aoedev.c +10 -2
@@ -214,7 +214,7 @@ aoedev_downdev(struct aoedev *d)/* reset window dressings */ tt = d->targets; - te = tt +NTARGETS ; + te = tt + d->ntargets;for (; tt < te && (t = *tt); tt++) {aoecmd_wreset (t); t->nout =0 ;
@@ -284,7 +284,7 @@ freedev(struct aoedev *d)blk_cleanup_queue (d->blkq); } t = d->targets; - e = t +NTARGETS ; + e = t + d->ntargets;for (; t < e && *t; t++)freetgt (d, *t);if (d->bufpool)
@@ -376,6 +376,8 @@ restart: dd = &d->next; }spin_unlock (&d->lock); +if (doomed) +kfree (doomed->targets);kfree (doomed); }spin_unlock_irqrestore (&devlist_lock, flags);
@@ -456,6 +458,12 @@ aoedev_by_aoeaddr(ulong maj, int min, int do_alloc) d =kcalloc (1 ,sizeof *d,GFP_ATOMIC );if (!d) goto out; + d->targets =kcalloc (NTARGETS ,sizeof (*d->targets),GFP_ATOMIC ); +if (!d->targets) { +kfree (d); + goto out; + } + d->ntargets =NTARGETS ;INIT_WORK (&d->work, aoecmd_sleepwork);spin_lock_init (&d->lock);skb_queue_head_init (&d->skbpool);
Signature · 1 line
1.7.1
PATCH 4/7 aoe: allow user to disable target failure timeout
In reply to a message not in the archiveWith this change, the aoe driver treats the value zero as special for the aoe_deadsecs module parameter. Normally, this value specifies the number of seconds during which the driver will continue to attempt retransmits to an unresponsive AoE target. After aoe_deadsecs has elapsed, the aoe driver marks the aoe device as "down" and fails all I/O.
The new meaning of an aoe_deadsecs of zero is for the driver to retransmit commands indefinitely.
--- Documentation/aoe/aoe.txt | 4 +++- drivers/block/aoe/aoecmd.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-)
Documentation/aoe/aoe.txt +3 -1
@@ -125,7 +125,9 @@ DRIVER OPTIONS The aoe_deadsecs module parameter determines the maximum number of seconds that the driver will wait for an AoE device to provide a response to an AoE command. After aoe_deadsecs seconds have - elapsed, the AoE device will be marked as "down". + elapsed, the AoE device will be marked as "down". A value of zero + is supported for testing purposes and makes the aoe driver keep + trying AoE commands forever. The aoe_maxout module parameter has a default of 128. This is the maximum number of unresponded packets that will be sent to an AoE
drivers/block/aoe/aoecmd.c +3 -1
@@ -812,7 +812,9 @@ rexmit_timer(ulong vp) since =tsince_hr (f); n = f->waited_total + since; n /=USEC_PER_SEC ; -if (n > aoe_deadsecs && !(f->flags &FFL_PROBE )) { +if (aoe_deadsecs + && n > aoe_deadsecs + && !(f->flags &FFL_PROBE )) {/* Waited too long. Device failure. * Hang all frames on first hash bucket for downdev * to clean up.
Signature · 1 line
1.7.1
PATCH 5/7 aoe: allow comma separator in aoe_iflist value
In reply to a message not in the archiveBy default, the aoe driver uses any ethernet interface for AoE, but the aoe_iflist module parameter provides a convenient way to limit AoE traffic to a specific list of local network interfaces.
This change allows a list to be specified using the comma character as a separator. For example,
modprobe aoe aoe_iflist=eth2,eth3
Before, it was inconvenient to get the quoting right in shell scripts when setting aoe_iflist to have more than one network interface.
--- drivers/block/aoe/aoe.h | 2 +- drivers/block/aoe/aoenet.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/block/aoe/aoe.h +1 -1
@@ -11,7 +11,7 @@#define AOE_PARTITIONS (16)#endif -#define WHITESPACE " \t\v\f\n" +#define WHITESPACE " \t\v\f\n,"enum {AOECMD_ATA ,
drivers/block/aoe/aoenet.c +1 -1
@@ -31,7 +31,7 @@ enum {static char aoe_iflist[IFLISTSZ ];module_param_string (aoe_iflist, aoe_iflist,IFLISTSZ ,0600 ); -MODULE_PARM_DESC (aoe_iflist,"aoe_iflist=\"dev1 [dev2 ...]\"" ); +MODULE_PARM_DESC (aoe_iflist,"aoe_iflist=dev1[,dev2...]" );static wait_queue_head_t txwq;static struct ktstate kts;
Signature · 1 line
1.7.1
PATCH 6/7 aoe: identify source of runt AoE packets
In reply to a message not in the archiveThis change only affects experimental AoE storage networks.
It modifies the console message about runt packets detected so that the AoE major and minor addresses of the AoE target that generated the runt are mentioned.
--- drivers/block/aoe/aoecmd.c | 10 +++++++--- 1 files changed, 7 insertions(+), 3 deletions(-)
drivers/block/aoe/aoecmd.c +7 -3
@@ -1217,8 +1217,10 @@ noskb: if (buf)case ATA_CMD_PIO_READ :case ATA_CMD_PIO_READ_EXT :if (skb->len < n) { -pr_err ("aoe: runt data size in read. skb->len=%d need=%ld\n" , - skb->len, n); +pr_err ("%s e%ld.%d. skb->len=%d need=%ld\n" , +"aoe: runt data size in read from" , + (long ) d->aoemajor, d->aoeminor, + skb->len, n);clear_bit (BIO_UPTODATE , &buf->bio->bi_flags);break ; }
@@ -1233,7 +1235,9 @@ noskb: if (buf)break ;case ATA_CMD_ID_ATA :if (skb->len <512 ) { -pr_info ("aoe: runt data size in ataid. skb->len=%d\n" , +pr_info ("%s e%ld.%d. skb->len=%d need=512\n" , +"aoe: runt data size in ataid from" , + (long ) d->aoemajor, d->aoeminor, skb->len);break ; }
Signature · 1 line
1.7.1
PATCH 7/7 aoe: update internal version number to 81
In reply to a message not in the archiveThis version number is printed to the console on module initialization and is available in sysfs, which is where the userland aoe-version tool looks for it.
--- drivers/block/aoe/aoe.h | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-)
drivers/block/aoe/aoe.h +1 -2
@@ -1,6 +1,5 @@ -/* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */ -#define VERSION "64+" +#define VERSION "81"#define AOE_MAJOR 152#define DEVICE_NAME "aoe"
Signature · 1 line
1.7.1