aoe driver v49 performance and usability improvements
Subsystems (5)
cover aoe driver v49 performance and usability improvements
These patches go a long way to updating the in-kernel aoe driver with the changes that have been in the coraid.com-distributed version, bringing it from (aoe internal) version 47 to version 49. They apply to commit 23dcfa61bac244e1 of the mainline git tree.
These updates have been too long in coming, but there is reason to be hopeful that once these changes are applied, there is now less of a chance that such a large update gap will occur again for a couple reasons.
For one, the changes between 47 and 49 were originally produced in a form that required a large amount of work before they could be presented to the list in a form that complies with Documenation/Submit*. I have done my best to disentangle the changes and to clean them up. Subsequent changes are more amenable to submission to the LKML and should be easier to prepare soon. Future changes from Coraid are expected to be similarly amenable to LKML submission because of changes we have made for the better in Coraid's development practices in the past few years.
Second, the users of the aoe driver increasingly demand that the in-kernel driver have the same high performance and advanced features as the one distributed at coraid.com.
The plan is to follow up with more changes once this patchset is merged, until the coraid.com-distributed driver and the in-kernel drivers are as close as possible. Some bugfixes from have been backported to this patchset, though, from post-version-49 development. The important thing, though, is to get things started with a minimal and progressive first patchset.
Ed L. Cashin (14):
aoe: for performance support larger packet payloads
aoe: kernel thread handles I/O completions for simple locking
aoe: become I/O request queue handler for increased user control
aoe: use a kernel thread for transmissions
aoe: use packets that work with the smallest-MTU local interface
aoe: failover remote interface based on aoe_deadsecs parameter
aoe: do revalidation steps in order
aoe: disallow unsupported AoE minor addresses
aoe: associate frames with the AoE storage target
aoe: increase net_device reference count while using it
aoe: remove unused code and add cosmetic improvements
aoe: update internal version number to 49
aoe: update copyright year in touched files
aoe: update documentation with new URL and VM settings reference
Documentation/aoe/aoe.txt | 9 +- MAINTAINERS | 2 +- drivers/block/aoe/aoe.h | 85 ++-- drivers/block/aoe/aoeblk.c | 89 +--- drivers/block/aoe/aoechr.c | 11 +- drivers/block/aoe/aoecmd.c | 1227 ++++++++++++++++++++++++++++--------------- drivers/block/aoe/aoedev.c | 161 ++++-- drivers/block/aoe/aoemain.c | 10 +- drivers/block/aoe/aoenet.c | 61 ++- 9 files changed, 1084 insertions(+), 571 deletions(-)
Signature · 1 line
1.7.2.5
PATCH 1/14 aoe: for performance support larger packet payloads
This patch adds the ability to work with large packets composed of a number of segments, using the scatter gather feature of the block layer (biovecs) and the network layer (skb frag array). The motivation is the performance gained by using a packet data payload greater than a page size and by using the network card's scatter gather feature.
Users of the out-of-tree aoe driver already had these changes, but since early 2011, they have complained of increased memory utilization and higher CPU utilization during heavy writes.[1] The commit below appears related, as it disables scatter gather on non-IP protocols inside the harmonize_features function, even when the NIC supports sg.
commit f01a5236bd4b140198fbcc550f085e8361fd73fa
Author: Jesse Gross <[email protected]>
Date: Sun Jan 9 06:23:31 2011 +0000
net offloading: Generalize netif_get_vlan_features().
With that regression in place, transmits always linearize sg AoE packets, but in-kernel users did not have this patch. Before 2.6.38, though, these changes were working to allow sg to increase performance.
1. http://www.spinics.net/lists/linux-mm/msg15184.html
--- drivers/block/aoe/aoe.h | 2 + drivers/block/aoe/aoeblk.c | 3 + drivers/block/aoe/aoecmd.c | 138 ++++++++++++++++++++++++++++++------------- drivers/block/aoe/aoedev.c | 1 + drivers/block/aoe/aoenet.c | 13 +++- 5 files changed, 111 insertions(+), 46 deletions(-)
drivers/block/aoe/aoe.h +2 -0
@@ -119,6 +119,8 @@ struct frame {ulong bcnt;sector_t lba;struct sk_buff *skb; +struct bio_vec *bv; +ulong bv_off; };struct aoeif {
drivers/block/aoe/aoeblk.c +3 -0
@@ -279,6 +279,9 @@ aoeblk_gdalloc(void *vp)if (bdi_init (&d->blkq->backing_dev_info)) goto err_blkq;spin_lock_irqsave (&d->lock, flags); +blk_queue_max_hw_sectors (d->blkq,BLK_DEF_MAX_SECTORS ); + d->blkq->backing_dev_info.ra_pages =BLK_DEF_MAX_SECTORS *1024 ; + d->blkq->backing_dev_info.ra_pages /=PAGE_CACHE_SIZE ; gd->major =AOE_MAJOR ; gd->first_minor = d->sysminor *AOE_PARTITIONS ; gd->fops = &aoe_bdops;
drivers/block/aoe/aoecmd.c +96 -42
247 lines not on this page · raw message
drivers/block/aoe/aoedev.c +1 -0
@@ -182,6 +182,7 @@ skbfree(struct sk_buff *skb) "cannot free skb -- memory leaked.");return ; } + skb->truesize -= skb->data_len;skb_shinfo (skb)->nr_frags = skb->data_len =0 ;skb_trim (skb,0 );dev_kfree_skb (skb);
drivers/block/aoe/aoenet.c +9 -4
@@ -102,7 +102,9 @@ static int aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, struct net_device *orig_dev) { struct aoe_hdr *h; +struct aoe_atahdr *ah;u32 n; +int sn;if (dev_net (ifp) != &init_net) goto exit;
@@ -110,13 +112,16 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, skb =skb_share_check (skb,GFP_ATOMIC );if (skb ==NULL )return 0 ; -if (skb_linearize (skb)) - goto exit;if (!is_aoe_netif (ifp)) goto exit;skb_push (skb,ETH_HLEN );/* (1) */ - - h = (struct aoe_hdr *)skb_mac_header (skb); + sn =sizeof (*h) +sizeof (*ah); +if (skb->len >= sn) { + sn -=skb_headlen (skb); +if (sn >0 && !__pskb_pull_tail (skb, sn)) + goto exit; + } + h = (struct aoe_hdr *) skb->data; n =get_unaligned_be32 (&h->tag);if ((h->verfl &AOEFL_RSP ) ==0 || (n &1 <<31 )) goto exit;
Signature · 1 line
1.7.2.5
Re: [PATCH 01/14] aoe: for performance support larger packet payloads
I probably should have Cc'ed the netdev list for this patch.
Quoted 375 lines · Ed Cashin
This patch adds the ability to work with large packets composed of a number of segments, using the scatter gather feature of the block layer (biovecs) and the network layer (skb frag array). The motivation is the performance gained by using a packet data payload greater than a page size and by using the network card's scatter gather feature.
Users of the out-of-tree aoe driver already had these changes, but since early 2011, they have complained of increased memory utilization and higher CPU utilization during heavy writes.[1] The commit below appears related, as it disables scatter gather on non-IP protocols inside the
harmonize_featuresfunction, even when the NIC supports sg.commit
f01a5236bd4b140198fbcc550f085e8361fd73fa
Author: Jesse Gross <[email protected]>
Date: Sun Jan 9 06:23:31 2011 +0000net offloading: Generalize
netif_get_vlan_features().With that regression in place, transmits always linearize sg AoE packets, but in-kernel users did not have this patch. Before 2.6.38, though, these changes were working to allow sg to increase performance.
1. http://www.spinics.net/lists/linux-mm/msg15184.html
Signed-off-by Ed Cashin <[email protected]>--- drivers/block/aoe/aoe.h | 2 + drivers/block/aoe/aoeblk.c | 3 + drivers/block/aoe/aoecmd.c | 138 ++++++++++++++++++++++++++++++------------- drivers/block/aoe/aoedev.c | 1 + drivers/block/aoe/aoenet.c | 13 +++- 5 files changed, 111 insertions(+), 46 deletions(-)drivers/block/aoe/aoe.h +2
-0@@ -119,6 +119,8 @@ struct frame {ulong bcnt;sector_t lba;struct sk_buff *skb; +struct bio_vec *bv; +ulong bv_off; };struct aoeif {drivers/block/aoe/aoeblk.c +3
-0@@ -279,6 +279,9 @@ aoeblk_gdalloc(void *vp)if (bdi_init (&d->blkq->backing_dev_info)) goto err_blkq;spin_lock_irqsave (&d->lock, flags); +blk_queue_max_hw_sectors (d->blkq,BLK_DEF_MAX_SECTORS ); + d->blkq->backing_dev_info.ra_pages =BLK_DEF_MAX_SECTORS *1024 ; + d->blkq->backing_dev_info.ra_pages /=PAGE_CACHE_SIZE ; gd->major =AOE_MAJOR ; gd->first_minor = d->sysminor *AOE_PARTITIONS ; gd->fops = &aoe_bdops;drivers/block/aoe/aoecmd.c +96
-42@@ -164,7 +164,8 @@ freeframe(struct aoedev *d) rf = f;continue ; } -gotone:skb_shinfo (skb)->nr_frags = skb->data_len =0 ; +gotone: skb->truesize -= skb->data_len; +skb_shinfo (skb)->nr_frags = skb->data_len =0 ;skb_trim (skb,0 ); d->tgt = t;ifrotate (*t);@@ -200,6 +201,24 @@ gotone: skb_shinfo(skb)->nr_frags = skb->data_len = 0;return NULL ; } +static void +skb_fillup (struct sk_buff *skb,struct bio_vec *bv,ulong off,ulong cnt) +{ +int frag =0 ; +ulong fcnt; +loop: + fcnt = bv->bv_len - (off - bv->bv_offset); +if (fcnt > cnt) + fcnt = cnt; +skb_fill_page_desc (skb, frag++, bv->bv_page, off, fcnt); + cnt -= fcnt; +if (cnt <=0 ) +return ; + bv++; + off = bv->bv_offset; + goto loop; +} +static int aoecmd_ata_rw (struct aoedev *d) {@@ -210,7 +229,7 @@ aoecmd_ata_rw(struct aoedev *d)struct bio_vec *bv;struct aoetgt *t;struct sk_buff *skb; -ulong bcnt; +ulong bcnt, fbcnt;char writebit, extbit; writebit =0x10 ;@@ -225,8 +244,28 @@ aoecmd_ata_rw(struct aoedev *d) bcnt = t->ifp->maxbcnt;if (bcnt ==0 ) bcnt =DEFAULTBCNT ; -if (bcnt > buf->bv_resid) - bcnt = buf->bv_resid; +if (bcnt > buf->resid) + bcnt = buf->resid; + fbcnt = bcnt; + f->bv = buf->bv; + f->bv_off = f->bv->bv_offset + (f->bv->bv_len - buf->bv_resid); +do { +if (fbcnt < buf->bv_resid) { + buf->bv_resid -= fbcnt; + buf->resid -= fbcnt; +break ; + } + fbcnt -= buf->bv_resid; + buf->resid -= buf->bv_resid; +if (buf->resid ==0 ) { + d->inprocess =NULL ; +break ; + } + buf->bv++; + buf->bv_resid = buf->bv->bv_len; +WARN_ON (buf->bv_resid ==0 ); + }while (fbcnt); +/* initialize the headers & frame */ skb = f->skb; h = (struct aoe_hdr *)skb_mac_header (skb);@@ -237,7 +276,6 @@ aoecmd_ata_rw(struct aoedev *d) t->nout++; f->waited =0 ; f->buf = buf; - f->bufaddr =page_address (bv->bv_page) + buf->bv_off; f->bcnt = bcnt; f->lba = buf->sector;@@ -252,10 +290,11 @@ aoecmd_ata_rw(struct aoedev *d) ah->lba3 |=0xe0 ;/* LBA bit + obsolete 0xa0 */ }if (bio_data_dir (buf->bio) ==WRITE ) { -skb_fill_page_desc (skb,0 , bv->bv_page, buf->bv_off, bcnt); +skb_fillup (skb, f->bv, f->bv_off, bcnt); ah->aflags |=AOEAFL_WRITE ; skb->len += bcnt; skb->data_len = bcnt; + skb->truesize += bcnt; t->wpkts++; }else { t->rpkts++;@@ -266,18 +305,7 @@ aoecmd_ata_rw(struct aoedev *d)/* mark all tracking fields and load out */ buf->nframesout +=1 ; - buf->bv_off += bcnt; - buf->bv_resid -= bcnt; - buf->resid -= bcnt; buf->sector += bcnt >>9 ; -if (buf->resid ==0 ) { - d->inprocess =NULL ; - }else if (buf->bv_resid ==0 ) { - buf->bv = ++bv; - buf->bv_resid = bv->bv_len; -WARN_ON (buf->bv_resid ==0 ); - buf->bv_off = bv->bv_offset; - } skb->dev = t->ifp->nd; skb =skb_clone (skb,GFP_ATOMIC );@@ -364,14 +392,12 @@ resend(struct aoedev *d, struct aoetgt *t, struct frame *f)put_lba (ah, f->lba); n = f->bcnt; -if (n >DEFAULTBCNT ) - n =DEFAULTBCNT ; ah->scnt = n >>9 ;if (ah->aflags &AOEAFL_WRITE ) { -skb_fill_page_desc (skb,0 ,virt_to_page (f->bufaddr), -offset_in_page (f->bufaddr), n); +skb_fillup (skb, f->bv, f->bv_off, n); skb->len =sizeof *h +sizeof *ah + n; skb->data_len = n; + skb->truesize += n; } } skb->dev = t->ifp->nd;@@ -530,20 +556,6 @@ rexmit_timer(ulong vp)ejectif (t, ifp); ifp =NULL ; } - -if (ata_scnt (skb_mac_header (f->skb)) >DEFAULTBCNT /512 - && ifp && ++ifp->lostjumbo > (t->nframes <<1 ) - && ifp->maxbcnt !=DEFAULTBCNT ) { -printk (KERN_INFO -"aoe: e%ld.%d: " -"too many lost jumbo on " -"%s:%pm - " -"falling back to %d frames.\n" , - d->aoemajor, d->aoeminor, - ifp->nd->name, t->addr, -DEFAULTBCNT ); - ifp->maxbcnt =0 ; - }resend (d, t, f); }@@ -736,6 +748,45 @@ diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sectorpart_stat_unlock (); } +static void +bvcpy (struct bio_vec *bv,ulong off,struct sk_buff *skb,ulong cnt) +{ +ulong fcnt; +char *p; +int soff =0 ; +loop: + fcnt = bv->bv_len - (off - bv->bv_offset); +if (fcnt > cnt) + fcnt = cnt; + p =page_address (bv->bv_page) + off; +skb_copy_bits (skb, soff, p, fcnt); + soff += fcnt; + cnt -= fcnt; +if (cnt <=0 ) +return ; + bv++; + off = bv->bv_offset; + goto loop; +} + +static void +fadvance (struct frame *f,ulong cnt) +{ +ulong fcnt; + + f->lba += cnt >>9 ; +loop: + fcnt = f->bv->bv_len - (f->bv_off - f->bv->bv_offset); +if (fcnt > cnt) { + f->bv_off += cnt; +return ; + } + cnt -= fcnt; + f->bv++; + f->bv_off = f->bv->bv_offset; + goto loop; +} +void aoecmd_ata_rsp (struct sk_buff *skb) {@@ -753,6 +804,7 @@ aoecmd_ata_rsp(struct sk_buff *skb)u16 aoemajor; hin = (struct aoe_hdr *)skb_mac_header (skb); +skb_pull (skb,sizeof (*hin)); aoemajor =get_unaligned_be16 (&hin->major); d =aoedev_by_aoeaddr (aoemajor, hin->minor);if (d ==NULL ) {@@ -790,7 +842,8 @@ aoecmd_ata_rsp(struct sk_buff *skb)calc_rttavg (d,tsince (f->tag)); - ahin = (struct aoe_atahdr *) (hin+1 ); + ahin = (struct aoe_atahdr *) skb->data; +skb_pull (skb,sizeof (*ahin)); hout = (struct aoe_hdr *)skb_mac_header (f->skb); ahout = (struct aoe_atahdr *) (hout+1 ); buf = f->buf;@@ -809,7 +862,7 @@ aoecmd_ata_rsp(struct sk_buff *skb)switch (ahout->cmdstat) {case ATA_CMD_PIO_READ :case ATA_CMD_PIO_READ_EXT : -if (skb->len -sizeof *hin -sizeof *ahin < n) { +if (skb->len < n) {printk (KERN_ERR "aoe: %s. skb->len=%d need=%ld\n" ,"runt data size in read" , skb->len, n);@@ -817,7 +870,7 @@ aoecmd_ata_rsp(struct sk_buff *skb)spin_unlock_irqrestore (&d->lock, flags);return ; } -memcpy (f->bufaddr, ahin+1 , n); +bvcpy (f->bv, f->bv_off, skb, n);case ATA_CMD_PIO_WRITE :case ATA_CMD_PIO_WRITE_EXT : ifp =getif (t, skb->dev);@@ -827,21 +880,22 @@ aoecmd_ata_rsp(struct sk_buff *skb) ifp->lostjumbo =0 ; }if (f->bcnt -= n) { - f->lba += n >>9 ; - f->bufaddr += n; +fadvance (f, n);resend (d, t, f); goto xmit; }break ;case ATA_CMD_ID_ATA : -if (skb->len -sizeof *hin -sizeof *ahin <512 ) { +if (skb->len <512 ) {printk (KERN_INFO "aoe: runt data size in ataid. skb->len=%d\n" , skb->len);spin_unlock_irqrestore (&d->lock, flags);return ; } -ataid_complete (d, t, (char *) (ahin+1 )); +if (skb_linearize (skb)) +break ; +ataid_complete (d, t, skb->data);break ;default : printk(KERN_INFOdrivers/block/aoe/aoedev.c +1
-0@@ -182,6 +182,7 @@ skbfree(struct sk_buff *skb) "cannot free skb -- memory leaked.");return ; } + skb->truesize -= skb->data_len;skb_shinfo (skb)->nr_frags = skb->data_len =0 ;skb_trim (skb,0 );dev_kfree_skb (skb);drivers/block/aoe/aoenet.c +9
-4@@ -102,7 +102,9 @@ static int aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, struct net_device *orig_dev) { struct aoe_hdr *h; +struct aoe_atahdr *ah;u32 n; +int sn;if (dev_net (ifp) != &init_net) goto exit;@@ -110,13 +112,16 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, skb =skb_share_check (skb,GFP_ATOMIC );if (skb ==NULL )return 0 ; -if (skb_linearize (skb)) - goto exit;if (!is_aoe_netif (ifp)) goto exit;skb_push (skb,ETH_HLEN );/* (1) */ - - h = (struct aoe_hdr *)skb_mac_header (skb); + sn =sizeof (*h) +sizeof (*ah); +if (skb->len >= sn) { + sn -=skb_headlen (skb); +if (sn >0 && !__pskb_pull_tail (skb, sn)) + goto exit; + } + h = (struct aoe_hdr *) skb->data; n =get_unaligned_be32 (&h->tag);if ((h->verfl &AOEFL_RSP ) ==0 || (n &1 <<31 )) goto exit;
Signature · 1 line
Ed
Re: [PATCH 01/14] aoe: for performance support larger packet payloads
In reply to Ed CashinI should have Cc'ed netdev for this patch. The series was only sent to linux-kernel, sorry.
Quoted 378 lines · Ed Cashin
This patch adds the ability to work with large packets composed of a number of segments, using the scatter gather feature of the block layer (biovecs) and the network layer (skb frag array). The motivation is the performance gained by using a packet data payload greater than a page size and by using the network card's scatter gather feature.
Users of the out-of-tree aoe driver already had these changes, but since early 2011, they have complained of increased memory utilization and higher CPU utilization during heavy writes.[1] The commit below appears related, as it disables scatter gather on non-IP protocols inside the
harmonize_featuresfunction, even when the NIC supports sg.commit
f01a5236bd4b140198fbcc550f085e8361fd73fa
Author: Jesse Gross <[email protected]>
Date: Sun Jan 9 06:23:31 2011 +0000net offloading: Generalize
netif_get_vlan_features().With that regression in place, transmits always linearize sg AoE packets, but in-kernel users did not have this patch. Before 2.6.38, though, these changes were working to allow sg to increase performance.
1. http://www.spinics.net/lists/linux-mm/msg15184.html
Signed-off-by Ed Cashin <[email protected]>---
drivers/block/aoe/aoe.h | 2 + drivers/block/aoe/aoeblk.c | 3 + drivers/block/aoe/aoecmd.c | 138 ++++++++++++++++++++++++++++++------------- drivers/block/aoe/aoedev.c | 1 + drivers/block/aoe/aoenet.c | 13 +++- 5 files changed, 111 insertions(+), 46 deletions(-)drivers/block/aoe/aoe.h +2
-0@@ -119,6 +119,8 @@ struct frame {ulong bcnt;sector_t lba;struct sk_buff *skb; +struct bio_vec *bv; +ulong bv_off; };struct aoeif {drivers/block/aoe/aoeblk.c +3
-0@@ -279,6 +279,9 @@ aoeblk_gdalloc(void *vp)if (bdi_init (&d->blkq->backing_dev_info)) goto err_blkq;spin_lock_irqsave (&d->lock, flags); +blk_queue_max_hw_sectors (d->blkq,BLK_DEF_MAX_SECTORS ); + d->blkq->backing_dev_info.ra_pages =BLK_DEF_MAX_SECTORS *1024 ; + d->blkq->backing_dev_info.ra_pages /=PAGE_CACHE_SIZE ; gd->major =AOE_MAJOR ; gd->first_minor = d->sysminor *AOE_PARTITIONS ; gd->fops = &aoe_bdops;drivers/block/aoe/aoecmd.c +20
-1@@ -164,7 +164,8 @@ freeframe(struct aoedev *d) rf = f;continue ; } -gotone:skb_shinfo (skb)->nr_frags = skb->data_len =0 ; +gotone: skb->truesize -= skb->data_len; +skb_shinfo (skb)->nr_frags = skb->data_len =0 ;skb_trim (skb,0 ); d->tgt = t;ifrotate (*t);@@ -200,6 +201,24 @@ gotone: skb_shinfo(skb)->nr_frags = skb->data_len = 0;return NULL ; } +static void +skb_fillup (struct sk_buff *skb,struct bio_vec *bv,ulong off,ulong cnt) +{ +int frag =0 ; +ulong fcnt; +loop: + fcnt = bv->bv_len - (off - bv->bv_offset); +if (fcnt > cnt) + fcnt = cnt; +skb_fill_page_desc (skb, frag++, bv->bv_page, off, fcnt); + cnt -= fcnt; +if (cnt <=0 ) +return ; + bv++; + off = bv->bv_offset; + goto loop; +} +static int
aoecmd_ata_rw(struct aoedev *d)
{drivers/block/aoe/aoecmd.c +66
-34@@ -210,7 +229,7 @@ aoecmd_ata_rw(struct aoedev *d)struct bio_vec *bv;struct aoetgt *t;struct sk_buff *skb; -ulong bcnt; +ulong bcnt, fbcnt;char writebit, extbit; writebit =0x10 ;@@ -225,8 +244,28 @@ aoecmd_ata_rw(struct aoedev *d) bcnt = t->ifp->maxbcnt;if (bcnt ==0 ) bcnt =DEFAULTBCNT ; -if (bcnt > buf->bv_resid) - bcnt = buf->bv_resid; +if (bcnt > buf->resid) + bcnt = buf->resid; + fbcnt = bcnt; + f->bv = buf->bv; + f->bv_off = f->bv->bv_offset + (f->bv->bv_len - buf->bv_resid); +do { +if (fbcnt < buf->bv_resid) { + buf->bv_resid -= fbcnt; + buf->resid -= fbcnt; +break ; + } + fbcnt -= buf->bv_resid; + buf->resid -= buf->bv_resid; +if (buf->resid ==0 ) { + d->inprocess =NULL ; +break ; + } + buf->bv++; + buf->bv_resid = buf->bv->bv_len; +WARN_ON (buf->bv_resid ==0 ); + }while (fbcnt); +/* initialize the headers & frame */ skb = f->skb; h = (struct aoe_hdr *)skb_mac_header (skb);@@ -237,7 +276,6 @@ aoecmd_ata_rw(struct aoedev *d) t->nout++; f->waited =0 ; f->buf = buf; - f->bufaddr =page_address (bv->bv_page) + buf->bv_off; f->bcnt = bcnt; f->lba = buf->sector;@@ -252,10 +290,11 @@ aoecmd_ata_rw(struct aoedev *d) ah->lba3 |=0xe0 ;/* LBA bit + obsolete 0xa0 */ }if (bio_data_dir (buf->bio) ==WRITE ) { -skb_fill_page_desc (skb,0 , bv->bv_page, buf->bv_off, bcnt); +skb_fillup (skb, f->bv, f->bv_off, bcnt); ah->aflags |=AOEAFL_WRITE ; skb->len += bcnt; skb->data_len = bcnt; + skb->truesize += bcnt; t->wpkts++; }else { t->rpkts++;@@ -266,18 +305,7 @@ aoecmd_ata_rw(struct aoedev *d)/* mark all tracking fields and load out */ buf->nframesout +=1 ; - buf->bv_off += bcnt; - buf->bv_resid -= bcnt; - buf->resid -= bcnt; buf->sector += bcnt >>9 ; -if (buf->resid ==0 ) { - d->inprocess =NULL ; - }else if (buf->bv_resid ==0 ) { - buf->bv = ++bv; - buf->bv_resid = bv->bv_len; -WARN_ON (buf->bv_resid ==0 ); - buf->bv_off = bv->bv_offset; - } skb->dev = t->ifp->nd; skb =skb_clone (skb,GFP_ATOMIC );@@ -364,14 +392,12 @@ resend(struct aoedev *d, struct aoetgt *t, struct frame *f)put_lba (ah, f->lba); n = f->bcnt; -if (n >DEFAULTBCNT ) - n =DEFAULTBCNT ; ah->scnt = n >>9 ;if (ah->aflags &AOEAFL_WRITE ) { -skb_fill_page_desc (skb,0 ,virt_to_page (f->bufaddr), -offset_in_page (f->bufaddr), n); +skb_fillup (skb, f->bv, f->bv_off, n); skb->len =sizeof *h +sizeof *ah + n; skb->data_len = n; + skb->truesize += n; } } skb->dev = t->ifp->nd;@@ -530,20 +556,6 @@ rexmit_timer(ulong vp)ejectif (t, ifp); ifp =NULL ; } - -if (ata_scnt (skb_mac_header (f->skb)) >DEFAULTBCNT /512 - && ifp && ++ifp->lostjumbo > (t->nframes <<1 ) - && ifp->maxbcnt !=DEFAULTBCNT ) { -printk (KERN_INFO -"aoe: e%ld.%d: " -"too many lost jumbo on " -"%s:%pm - " -"falling back to %d frames.\n" , - d->aoemajor, d->aoeminor, - ifp->nd->name, t->addr, -DEFAULTBCNT ); - ifp->maxbcnt =0 ; - }resend (d, t, f); }@@ -736,6 +748,45 @@ diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sectorpart_stat_unlock (); } +static void +bvcpy (struct bio_vec *bv,ulong off,struct sk_buff *skb,ulong cnt) +{ +ulong fcnt; +char *p; +int soff =0 ; +loop: + fcnt = bv->bv_len - (off - bv->bv_offset); +if (fcnt > cnt) + fcnt = cnt; + p =page_address (bv->bv_page) + off; +skb_copy_bits (skb, soff, p, fcnt); + soff += fcnt; + cnt -= fcnt; +if (cnt <=0 ) +return ; + bv++; + off = bv->bv_offset; + goto loop; +} + +static void +fadvance (struct frame *f,ulong cnt) +{ +ulong fcnt; + + f->lba += cnt >>9 ; +loop: + fcnt = f->bv->bv_len - (f->bv_off - f->bv->bv_offset); +if (fcnt > cnt) { + f->bv_off += cnt; +return ; + } + cnt -= fcnt; + f->bv++; + f->bv_off = f->bv->bv_offset; + goto loop; +} +void
aoecmd_ata_rsp(struct sk_buff *skb)
{drivers/block/aoe/aoecmd.c +10
-7@@ -753,6 +804,7 @@ aoecmd_ata_rsp(struct sk_buff *skb)u16 aoemajor; hin = (struct aoe_hdr *)skb_mac_header (skb); +skb_pull (skb,sizeof (*hin)); aoemajor =get_unaligned_be16 (&hin->major); d =aoedev_by_aoeaddr (aoemajor, hin->minor);if (d ==NULL ) {@@ -790,7 +842,8 @@ aoecmd_ata_rsp(struct sk_buff *skb)calc_rttavg (d,tsince (f->tag)); - ahin = (struct aoe_atahdr *) (hin+1 ); + ahin = (struct aoe_atahdr *) skb->data; +skb_pull (skb,sizeof (*ahin)); hout = (struct aoe_hdr *)skb_mac_header (f->skb); ahout = (struct aoe_atahdr *) (hout+1 ); buf = f->buf;@@ -809,7 +862,7 @@ aoecmd_ata_rsp(struct sk_buff *skb)switch (ahout->cmdstat) {case ATA_CMD_PIO_READ :case ATA_CMD_PIO_READ_EXT : -if (skb->len -sizeof *hin -sizeof *ahin < n) { +if (skb->len < n) {printk (KERN_ERR "aoe: %s. skb->len=%d need=%ld\n" ,"runt data size in read" , skb->len, n);@@ -817,7 +870,7 @@ aoecmd_ata_rsp(struct sk_buff *skb)spin_unlock_irqrestore (&d->lock, flags);return ; } -memcpy (f->bufaddr, ahin+1 , n); +bvcpy (f->bv, f->bv_off, skb, n);case ATA_CMD_PIO_WRITE :case ATA_CMD_PIO_WRITE_EXT : ifp =getif (t, skb->dev);@@ -827,21 +880,22 @@ aoecmd_ata_rsp(struct sk_buff *skb) ifp->lostjumbo =0 ; }if (f->bcnt -= n) { - f->lba += n >>9 ; - f->bufaddr += n; +fadvance (f, n);resend (d, t, f); goto xmit; }break ;case ATA_CMD_ID_ATA : -if (skb->len -sizeof *hin -sizeof *ahin <512 ) { +if (skb->len <512 ) {printk (KERN_INFO "aoe: runt data size in ataid. skb->len=%d\n" , skb->len);spin_unlock_irqrestore (&d->lock, flags);return ; } -ataid_complete (d, t, (char *) (ahin+1 )); +if (skb_linearize (skb)) +break ; +ataid_complete (d, t, skb->data);break ;default : printk(KERN_INFOdrivers/block/aoe/aoedev.c +1
-0@@ -182,6 +182,7 @@ skbfree(struct sk_buff *skb) "cannot free skb -- memory leaked.");return ; } + skb->truesize -= skb->data_len;skb_shinfo (skb)->nr_frags = skb->data_len =0 ;skb_trim (skb,0 );dev_kfree_skb (skb);drivers/block/aoe/aoenet.c +9
-4@@ -102,7 +102,9 @@ static int aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, struct net_device *orig_dev) { struct aoe_hdr *h; +struct aoe_atahdr *ah;u32 n; +int sn;if (dev_net (ifp) != &init_net) goto exit;@@ -110,13 +112,16 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, skb =skb_share_check (skb,GFP_ATOMIC );if (skb ==NULL )return 0 ; -if (skb_linearize (skb)) - goto exit;if (!is_aoe_netif (ifp)) goto exit;skb_push (skb,ETH_HLEN );/* (1) */ - - h = (struct aoe_hdr *)skb_mac_header (skb); + sn =sizeof (*h) +sizeof (*ah); +if (skb->len >= sn) { + sn -=skb_headlen (skb); +if (sn >0 && !__pskb_pull_tail (skb, sn)) + goto exit; + } + h = (struct aoe_hdr *) skb->data; n =get_unaligned_be32 (&h->tag);if ((h->verfl &AOEFL_RSP ) ==0 || (n &1 <<31 )) goto exit;Signature · 1 line
1.7.2.5
Signature · 2 lines
Ed Cashin [email protected]
Re: [PATCH 01/14] aoe: for performance support larger packet payloads
In reply to Ed Cashindrivers/block/aoe/aoeblk.c aoeblk_gdalloc(void *vp) · line 284
Quoted 9 lines · On Fri, 17 Aug 2012 21:18:37 -0400 Ed Cashin <[email protected]> wrote:
drivers/block/aoe/aoeblk.c +3
-0@@ -279,6 +279,9 @@ aoeblk_gdalloc(void *vp)if (bdi_init (&d->blkq->backing_dev_info)) goto err_blkq;spin_lock_irqsave (&d->lock, flags); +blk_queue_max_hw_sectors (d->blkq,BLK_DEF_MAX_SECTORS ); + d->blkq->backing_dev_info.ra_pages =BLK_DEF_MAX_SECTORS *1024 ; + d->blkq->backing_dev_info.ra_pages /=PAGE_CACHE_SIZE ;
This seems a bit abusive of BLK_DEF_MAX_SECTORS, which is in units of 512-byte sectors. (BLK_DEF_MAX_SECTORS * 512)/PAGE_CACHE_SIZE would make sense.
PATCH 1/14 aoe: for performance support larger packet payloads
In reply to Ed CashinThis patch adds the ability to work with large packets composed of a number of segments, using the scatter gather feature of the block layer (biovecs) and the network layer (skb frag array). The motivation is the performance gained by using a packet data payload greater than a page size and by using the network card's scatter gather feature.
Users of the out-of-tree aoe driver already had these changes, but since early 2011, they have complained of increased memory utilization and higher CPU utilization during heavy writes.[1] The commit below appears related, as it disables scatter gather on non-IP protocols inside the harmonize_features function, even when the NIC supports sg.
commit f01a5236bd4b140198fbcc550f085e8361fd73fa
Author: Jesse Gross <[email protected]>
Date: Sun Jan 9 06:23:31 2011 +0000
net offloading: Generalize netif_get_vlan_features().
With that regression in place, transmits always linearize sg AoE packets, but in-kernel users did not have this patch. Before 2.6.38, though, these changes were working to allow sg to increase performance.
1. http://www.spinics.net/lists/linux-mm/msg15184.html
--- drivers/block/aoe/aoe.h | 2 + drivers/block/aoe/aoeblk.c | 3 + drivers/block/aoe/aoecmd.c | 138 ++++++++++++++++++++++++++++++------------- drivers/block/aoe/aoedev.c | 1 + drivers/block/aoe/aoenet.c | 13 +++- 5 files changed, 111 insertions(+), 46 deletions(-)
drivers/block/aoe/aoe.h +2 -0
@@ -119,6 +119,8 @@ struct frame {ulong bcnt;sector_t lba;struct sk_buff *skb; +struct bio_vec *bv; +ulong bv_off; };struct aoeif {
drivers/block/aoe/aoeblk.c +3 -0
@@ -279,6 +279,9 @@ aoeblk_gdalloc(void *vp)if (bdi_init (&d->blkq->backing_dev_info)) goto err_blkq;spin_lock_irqsave (&d->lock, flags); +blk_queue_max_hw_sectors (d->blkq,BLK_DEF_MAX_SECTORS ); + d->blkq->backing_dev_info.ra_pages =BLK_DEF_MAX_SECTORS *1024 ; + d->blkq->backing_dev_info.ra_pages /=PAGE_CACHE_SIZE ; gd->major =AOE_MAJOR ; gd->first_minor = d->sysminor *AOE_PARTITIONS ; gd->fops = &aoe_bdops;
drivers/block/aoe/aoecmd.c +96 -42
247 lines not on this page · raw message
drivers/block/aoe/aoedev.c +1 -0
@@ -182,6 +182,7 @@ skbfree(struct sk_buff *skb) "cannot free skb -- memory leaked.");return ; } + skb->truesize -= skb->data_len;skb_shinfo (skb)->nr_frags = skb->data_len =0 ;skb_trim (skb,0 );dev_kfree_skb (skb);
drivers/block/aoe/aoenet.c +9 -4
@@ -102,7 +102,9 @@ static int aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, struct net_device *orig_dev) { struct aoe_hdr *h; +struct aoe_atahdr *ah;u32 n; +int sn;if (dev_net (ifp) != &init_net) goto exit;
@@ -110,13 +112,16 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, skb =skb_share_check (skb,GFP_ATOMIC );if (skb ==NULL )return 0 ; -if (skb_linearize (skb)) - goto exit;if (!is_aoe_netif (ifp)) goto exit;skb_push (skb,ETH_HLEN );/* (1) */ - - h = (struct aoe_hdr *)skb_mac_header (skb); + sn =sizeof (*h) +sizeof (*ah); +if (skb->len >= sn) { + sn -=skb_headlen (skb); +if (sn >0 && !__pskb_pull_tail (skb, sn)) + goto exit; + } + h = (struct aoe_hdr *) skb->data; n =get_unaligned_be32 (&h->tag);if ((h->verfl &AOEFL_RSP ) ==0 || (n &1 <<31 )) goto exit;
Signature · 1 line
1.7.2.5
PATCH 2/14 aoe: kernel thread handles I/O completions for simple locking
In reply to Ed CashinThis patch makes the frames the aoe driver uses to track the relationship between bios and packets more flexible and detached, so that they can be passed to an "aoe_ktio" thread for completion of I/O.
The frames are handled much like skbs, with a capped amount of preallocation so that real-world use cases are likely to run smoothly and degenerate gracefully even under memory pressure.
Decoupling I/O completion from the receive path and serializing it in a process makes it easier to think about the correctness of the locking in the driver, especially in the case of a remote MAC address becoming unusable.
--- drivers/block/aoe/aoe.h | 33 ++- drivers/block/aoe/aoechr.c | 3 +- drivers/block/aoe/aoecmd.c | 737 ++++++++++++++++++++++++++++--------------- drivers/block/aoe/aoedev.c | 84 +++-- drivers/block/aoe/aoemain.c | 8 +- drivers/block/aoe/aoenet.c | 6 +- 6 files changed, 567 insertions(+), 304 deletions(-)
drivers/block/aoe/aoe.h +27 -6
@@ -91,6 +91,7 @@ enum {NTARGETS =8 ,NAOEIFS =8 ,NSKBPOOLMAX =128 , +NFACTIVE =17 ,TIMERTICK =HZ /10 , MINTIMER = HZ >> 2,
@@ -112,13 +113,16 @@ struct buf { };struct frame { -int tag; +struct list_head head; +u32 tag;ulong waited;struct buf *buf; +struct aoetgt *t;/* parent target I belong to */ char *bufaddr;ulong bcnt;sector_t lba; -struct sk_buff *skb; +struct sk_buff *skb;/* command skb freed on module exit */ +struct sk_buff *r_skb;/* response skb for async processing */ struct bio_vec *bv;ulong bv_off; };
@@ -133,16 +137,18 @@ struct aoeif {struct aoetgt {unsigned char addr[6 ];ushort nframes; -struct frame *frames; +struct aoedev *d;/* parent device I belong to */ +struct list_head factive[NFACTIVE ];/* hash of active frames */ +struct list_head ffree;/* list of free frames */ struct aoeif ifs[NAOEIFS ];struct aoeif *ifp;/* current aoeif in use */ ushort nout;ushort maxout;u16 lasttag;/* last tag sent */ u16 useme; +ulong falloc;ulong lastwadj;/* last window adjustment */ int wpkts, rpkts; -int dataref; };struct aoedev {
@@ -169,9 +175,20 @@ struct aoedev {struct buf *inprocess;/* the one we're currently working on */ struct aoetgt *targets[NTARGETS ];struct aoetgt **tgt;/* target in use when working */ -struct aoetgt **htgt;/* target needing rexmit assistance */ +struct aoetgt *htgt;/* target needing rexmit assistance */ +ulong ntargets; +ulong kicked; }; +/* kthread tracking */ +struct ktstate { +struct completion rendez; +struct task_struct *task; +wait_queue_head_t *waitq; +int (*fn) (void ); +char *name; +spinlock_t *lock; +};int aoeblk_init (void );void aoeblk_exit (void );
@@ -184,11 +201,14 @@ void aoechr_error(char *);void aoecmd_work (struct aoedev *d);void aoecmd_cfg (ushort aoemajor,unsigned char aoeminor); -void aoecmd_ata_rsp (struct sk_buff *); +struct sk_buff *aoecmd_ata_rsp (struct sk_buff *);void aoecmd_cfg_rsp (struct sk_buff *);void aoecmd_sleepwork (struct work_struct *);void aoecmd_cleanslate (struct aoedev *); +void aoecmd_exit (void ); +int aoecmd_init (void );struct sk_buff *aoecmd_ata_id (struct aoedev *); +void aoe_freetframe (struct frame *);int aoedev_init (void );void aoedev_exit (void );
@@ -196,6 +216,7 @@ struct aoedev *aoedev_by_aoeaddr(int maj, int min);struct aoedev *aoedev_by_sysminor_m (ulong sysminor);void aoedev_downdev (struct aoedev *d);int aoedev_flush (const char __user *str,size_t size); +void aoe_failbuf (struct aoedev *d,struct buf *buf);int aoenet_init (void );void aoenet_exit (void );
drivers/block/aoe/aoechr.c +1 -2
@@ -86,10 +86,9 @@ revalidate(const char __user *str, size_t size)if (copy_from_user (buf, str, size))return -EFAULT ; -/* should be e%d.%d format */ n =sscanf (buf,"e%d.%d" , &major, &minor);if (n !=2 ) { -printk (KERN_ERR "aoe: invalid device specification\n" ); +pr_err ("aoe: invalid device specification %s\n" , buf);return -EINVAL ; } d =aoedev_by_aoeaddr (major, minor);
drivers/block/aoe/aoecmd.c +478 -259
955 lines not on this page · raw message
drivers/block/aoe/aoedev.c +50 -34
110 lines not on this page · raw message
drivers/block/aoe/aoemain.c +6 -2
@@ -61,6 +61,7 @@ aoe_exit(void)aoenet_exit ();unregister_blkdev (AOE_MAJOR ,DEVICE_NAME ); +aoecmd_exit ();aoechr_exit ();aoedev_exit ();aoeblk_exit ();/* free cache after de-allocating bufs */
@@ -83,17 +84,20 @@ aoe_init(void) ret =aoenet_init ();if (ret) goto net_fail; + ret =aoecmd_init (); +if (ret) + goto cmd_fail; ret =register_blkdev (AOE_MAJOR ,DEVICE_NAME );if (ret <0 ) {printk (KERN_ERR "aoe: can't register major\n" ); goto blkreg_fail; } -printk (KERN_INFO "aoe: AoE v%s initialised.\n" ,VERSION );discover_timer (TINIT );return 0 ; - blkreg_fail: +aoecmd_exit (); + cmd_fail:aoenet_exit (); net_fail:aoeblk_exit ();
drivers/block/aoe/aoenet.c +5 -1
@@ -142,7 +142,8 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,switch (h->cmd) {case AOECMD_ATA : -aoecmd_ata_rsp (skb); +/* ata_rsp may keep skb for later processing or give it back */ + skb =aoecmd_ata_rsp (skb);break ;case AOECMD_CFG :aoecmd_cfg_rsp (skb);
@@ -152,6 +153,9 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,break ;/* don't complain about vendor commands */ printk (KERN_INFO "aoe: unknown cmd %d\n" , h->cmd); } + +if (!skb) +return 0 ; exit:dev_kfree_skb (skb);return 0 ;
Signature · 1 line
1.7.2.5
Re: [PATCH 02/14] aoe: kernel thread handles I/O completions for simple locking
Quoted 15 lines · On Fri, 17 Aug 2012 21:24:08 -0400 Ed Cashin <[email protected]> wrote:
This patch makes the frames the aoe driver uses to track the relationship between bios and packets more flexible and detached, so that they can be passed to an "
aoe_ktio" thread for completion of I/O.The frames are handled much like skbs, with a capped amount of preallocation so that real-world use cases are likely to run smoothly and degenerate gracefully even under memory pressure.
Decoupling I/O completion from the receive path and serializing it in a process makes it easier to think about the correctness of the locking in the driver, especially in the case of a remote MAC address becoming unusable.
...
drivers/block/aoe/aoecmd.c loop: · line 977
Quoted 10 lines
drivers/block/aoe/aoecmd.c +10
-0+static int +kthread (void *vp) +{ +struct ktstate *k; +DECLARE_WAITQUEUE (wait, current); +sigset_t blocked; +int more; + + k = vp; +#ifdef PF_NOFREEZE
PF_NOFREEZE can never be undefined.
drivers/block/aoe/aoecmd.c loop: · line 983
Quoted 6 lines
drivers/block/aoe/aoecmd.c +6
-0+ current->flags |=PF_NOFREEZE ; +#endif +set_user_nice (current,-10 ); +sigfillset (&blocked); +sigprocmask (SIG_BLOCK , &blocked,NULL ); +flush_signals (current);
This is a kernel thread - it shouldn't need to fiddle with signals.
Review
Quoted 1 line
(quoted diff) +1
-0+ complete(&k->rendez);
That's odd. Why do a complete() before we even start? A code comment is needed if this is indeed correct.
drivers/block/aoe/aoecmd.c loop: · line 986
Quoted 2 lines
drivers/block/aoe/aoecmd.c +2
-0+ do { + __set_current_state(TASK_UNINTERRUPTIBLE);
I think this statement is simply unneeded.
drivers/block/aoe/aoecmd.c loop: · line 998
Quoted 12 lines
drivers/block/aoe/aoecmd.c +12
-0+spin_lock_irq (k->lock); + more = k->fn (); +if (!more) { +add_wait_queue (k->waitq, &wait); +__set_current_state (TASK_INTERRUPTIBLE ); + } +spin_unlock_irq (k->lock); +if (!more) { +schedule (); +remove_wait_queue (k->waitq, &wait); + }else +cond_resched ();
Here we can do a cond_resched() when in state TASK_INTERRUPTIBLE. Such a schedule() will never return unless some other thread flips this task into state TASK_RUNNING. But if another thread does that, we should have been on that waitqueue!
It seems all confused and racy.
drivers/block/aoe/aoecmd.c loop: · line 1000
Quoted 2 lines
drivers/block/aoe/aoecmd.c +2
-0+ }while (!kthread_should_stop ()); +__set_current_state (TASK_RUNNING );
I don't think there's any path by which we can get here in any state other than TASK_RUNNING.
drivers/block/aoe/aoecmd.c loop: · line 1003
Quoted 3 lines
drivers/block/aoe/aoecmd.c +3
-0+complete (&k->rendez); +return 0 ; +}
This function might be a bit neater if it were to use prepare_to_wait()/finish_wait().
Quoted 6 lines
drivers/block/aoe/aoecmd.c +6
-0+static void +aoe_ktstop (struct ktstate *k) +{ +kthread_stop (k->task); +wait_for_completion (&k->rendez); +}
drivers/block/aoe/aoecmd.c loop: · line 1020
Quoted 10 lines
drivers/block/aoe/aoecmd.c +10
-0+ +static int +aoe_ktstart (struct ktstate *k) +{ +struct task_struct *task; + +init_completion (&k->rendez); + task =kthread_run (kthread, k, k->name); +if (task ==NULL ||IS_ERR (task)) +return -EFAULT ;
EFAULT makes no sense?
Quoted 8 lines
drivers/block/aoe/aoecmd.c +5
-0+ k->task = task; +wait_for_completion (&k->rendez); +init_completion (&k->rendez);/* for exit */ +return 0 ; +}
Re: [PATCH 02/14] aoe: kernel thread handles I/O completions for simple locking
Quoted 2 lines · Andrew Morton
On Fri, 17 Aug 2012 21:24:08 -0400
Ed Cashin <[email protected]> wrote:
...
Quoted 5 lines
drivers/block/aoe/aoecmd.c loop: · line 983
Quoted 3 lines
drivers/block/aoe/aoecmd.c +3
-0+sigfillset (&blocked); +sigprocmask (SIG_BLOCK , &blocked,NULL ); +flush_signals (current);This is a kernel thread - it shouldn't need to fiddle with signals.
...
Thanks for the feedback. I'll try out your suggestions and return with changes and explanations.
Signature · 1 line
Ed
Re: [PATCH 02/14] aoe: kernel thread handles I/O completions for simple locking
In reply to Andrew MortonQuoted 2 lines · Andrew Morton
On Fri, 17 Aug 2012 21:24:08 -0400
Ed Cashin <[email protected]> wrote:
...
Quoted 13 lines
Quoted 1 line
+#ifdef
PF_NOFREEZE
PF_NOFREEZEcan never be undefined.Review
Quoted 6 lines
(quoted diff) +6
-0+ current->flags |= PF_NOFREEZE; +#endif + set_user_nice(current, -10); + sigfillset(&blocked); + sigprocmask(SIG_BLOCK, &blocked, NULL); + flush_signals(current);This is a kernel thread - it shouldn't need to fiddle with signals.
Quoted 4 lines
Review
Quoted 1 line
(quoted diff) +1
-0+ complete(&k->rendez);That's odd. Why do a
complete()before we even start? A code comment is needed if this is indeed correct.
There is a whole class of races that goes away when the code starting a thread waits for the thread to be running before proceeding, and that's what this rendezvous is for. I've added a comment that will appear next time I send the patchset.
(More comments below.)
Quoted 23 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ do { + __set_current_state(TASK_UNINTERRUPTIBLE);I think this statement is simply unneeded.
Review
Quoted 12 lines
(quoted diff) +12
-0+ spin_lock_irq(k->lock); + more = k->fn(); + if (!more) { + add_wait_queue(k->waitq, &wait); + __set_current_state(TASK_INTERRUPTIBLE); + } + spin_unlock_irq(k->lock); + if (!more) { + schedule(); + remove_wait_queue(k->waitq, &wait); + } else + cond_resched();Here we can do a
cond_resched()when in stateTASK_INTERRUPTIBLE. Such aschedule()will never return unless some other thread flips this task into stateTASK_RUNNING. But if another thread does that, we should have been on that waitqueue!
Quoted 1 line
It seems all confused and racy.
When we do a cond_resched, it's only when "more" is non-zero, in which case, we did not set the state to TASK_INTERRUPTIBLE. I do like your suggestions, though.
Please check out the (post-patchset) changes below that I plan to incorporate into the patchset for resubmission, and let me know if you see a race now that your suggestions have been incorporated.
It seems to work just as well in the testing I did with the changes below incorporated.
drivers/block/aoe/aoecmd.c +5 -13
@@ -1075,20 +1075,13 @@ kthread(void *vp) {struct ktstate *k;DECLARE_WAITQUEUE (wait, current); -sigset_t blocked;int more; k = vp; -#ifdef PF_NOFREEZE current->flags |=PF_NOFREEZE ; -#endif set_user_nice (current,-10 ); -sigfillset (&blocked); -sigprocmask (SIG_BLOCK , &blocked,NULL ); -flush_signals (current); -complete (&k->rendez); +complete (&k->rendez);/* tell spawner we're running */ do { - __set_current_state(TASK_UNINTERRUPTIBLE); spin_lock_irq(k->lock); more = k->fn(); if (!more) {
@@ -1102,8 +1095,7 @@ kthread(void *vp) }else cond_resched (); }while (!kthread_should_stop ()); -__set_current_state (TASK_RUNNING ); -complete (&k->rendez); +complete (&k->rendez);/* tell spawner we're stopping */ return 0 ; }
@@ -1122,10 +1114,10 @@ aoe_ktstart(struct ktstate *k)init_completion (&k->rendez); task =kthread_run (kthread, k, k->name);if (task ==NULL ||IS_ERR (task)) -return -EFAULT ; +return -ENOMEM ; k->task = task; -wait_for_completion (&k->rendez); -init_completion (&k->rendez);/* for exit */ +wait_for_completion (&k->rendez);/* allow kthread to start */ +init_completion (&k->rendez);/* for waiting for exit later */ return 0 ; }
PATCH 3/14 aoe: become I/O request queue handler for increased user control
In reply to Ed CashinTo allow users to choose an elevator algorithm for their particular workloads, change from a make_request-style driver to an I/O-request-queue-handler-style driver.
We have to do a couple of things that might be surprising. We manipulate the page _count directly on the assumption that we still have no guarantee that users of the block layer are prohibited from submitting bios containing pages with zero reference counts.[1] If such a prohibition now exists, I can get rid of the _count manipulation.
Just as before this patch, we still keep track of the sk_buffs that the network layer still hasn't finished yet and cap the resources we use with a "pool" of skbs.[2]
Now that the block layer maintains the disk stats, the aoe driver's diskstats function can go away.
1. https://lkml.org/lkml/2007/3/1/374
2. https://lkml.org/lkml/2007/7/6/241
--- drivers/block/aoe/aoe.h | 26 ++-- drivers/block/aoe/aoeblk.c | 88 ++++---------- drivers/block/aoe/aoechr.c | 1 + drivers/block/aoe/aoecmd.c | 282 +++++++++++++++++++++++++++++++------------ drivers/block/aoe/aoedev.c | 93 ++++++++++----- 5 files changed, 308 insertions(+), 182 deletions(-)
drivers/block/aoe/aoe.h +14 -12
@@ -90,7 +90,7 @@ enum {MIN_BUFS =16 ,NTARGETS =8 ,NAOEIFS =8 , -NSKBPOOLMAX =128 , +NSKBPOOLMAX =256 ,NFACTIVE =17 , TIMERTICK = HZ / 10,
@@ -100,30 +100,26 @@ enum { };struct buf { -struct list_head bufs; -ulong stime;/* for disk stats */ -ulong flags;ulong nframesout;ulong resid;ulong bv_resid; -ulong bv_off;sector_t sector;struct bio *bio;struct bio_vec *bv; +struct request *rq; };struct frame {struct list_head head;u32 tag;ulong waited; -struct buf *buf;struct aoetgt *t;/* parent target I belong to */ -char *bufaddr; -ulong bcnt;sector_t lba;struct sk_buff *skb;/* command skb freed on module exit */ struct sk_buff *r_skb;/* response skb for async processing */ +struct buf *buf;struct bio_vec *bv; +ulong bcnt;ulong bv_off; };
@@ -161,6 +157,7 @@ struct aoedev {u16 rttavg;/* round trip average of requests/responses */ u16 mintimer;u16 fw_ver;/* version of blade's firmware */ +ulong ref;struct work_struct work;/* disk create work struct */ struct gendisk *gd;struct request_queue *blkq;
@@ -168,11 +165,13 @@ struct aoedev {sector_t ssize;struct timer_list timer;spinlock_t lock; -struct sk_buff_head sendq;struct sk_buff_head skbpool;mempool_t *bufpool;/* for deadlock-free Buf allocation */ -struct list_head bufq;/* queue of bios to work on */ -struct buf *inprocess;/* the one we're currently working on */ +struct {/* pointers to work in progress */ +struct buf *buf; +struct bio *nxbio; +struct request *rq; + } ip;struct aoetgt *targets[NTARGETS ];struct aoetgt **tgt;/* target in use when working */ struct aoetgt *htgt;/* target needing rexmit assistance */
@@ -209,6 +208,8 @@ void aoecmd_exit(void);int aoecmd_init (void );struct sk_buff *aoecmd_ata_id (struct aoedev *);void aoe_freetframe (struct frame *); +void aoe_flush_iocq (void ); +void aoe_end_request (struct aoedev *,struct request *,int );int aoedev_init (void );void aoedev_exit (void );
@@ -216,7 +217,8 @@ struct aoedev *aoedev_by_aoeaddr(int maj, int min);struct aoedev *aoedev_by_sysminor_m (ulong sysminor);void aoedev_downdev (struct aoedev *d);int aoedev_flush (const char __user *str,size_t size); -void aoe_failbuf (struct aoedev *d,struct buf *buf); +void aoe_failbuf (struct aoedev *,struct buf *); +void aoedev_put (struct aoedev *);int aoenet_init (void );void aoenet_exit (void );
drivers/block/aoe/aoeblk.c +26 -62
136 lines not on this page · raw message
drivers/block/aoe/aoechr.c +1 -0
@@ -106,6 +106,7 @@ loop:spin_lock_irqsave (&d->lock, flags); goto loop; } +aoedev_put (d);if (skb) {struct sk_buff_head queue;__skb_queue_head_init (&queue);
drivers/block/aoe/aoecmd.c +203 -79
450 lines not on this page · raw message
drivers/block/aoe/aoedev.c +64 -29
194 lines not on this page · raw message
Signature · 1 line
1.7.2.5
PATCH 4/14 aoe: use a kernel thread for transmissions
In reply to Ed CashinThe dev_queue_xmit function needs to have interrupts enabled, so the most simple way to get the locking right but still fulfill that requirement is to use a process that can call dev_queue_xmit serially over queued transmissions.
--- drivers/block/aoe/aoe.h | 2 ++ drivers/block/aoe/aoecmd.c | 4 ++-- drivers/block/aoe/aoenet.c | 37 ++++++++++++++++++++++++++++++++++++- 3 files changed, 40 insertions(+), 3 deletions(-)
drivers/block/aoe/aoe.h +2 -0
@@ -210,6 +210,8 @@ struct sk_buff *aoecmd_ata_id(struct aoedev *);void aoe_freetframe (struct frame *);void aoe_flush_iocq (void );void aoe_end_request (struct aoedev *,struct request *,int ); +int aoe_ktstart (struct ktstate *k); +void aoe_ktstop (struct ktstate *k);int aoedev_init (void );void aoedev_exit (void );
drivers/block/aoe/aoecmd.c +2 -2
@@ -1117,14 +1117,14 @@ kthread(void *vp)return 0 ; } -static void +void aoe_ktstop (struct ktstate *k) {kthread_stop (k->task);wait_for_completion (&k->rendez); } -static int +int aoe_ktstart (struct ktstate *k) {struct task_struct *task;
drivers/block/aoe/aoenet.c +36 -1
@@ -33,6 +33,9 @@ static char aoe_iflist[IFLISTSZ];module_param_string (aoe_iflist, aoe_iflist,IFLISTSZ ,0600 );MODULE_PARM_DESC (aoe_iflist,"aoe_iflist=\"dev1 [dev2 ...]\"" ); +static wait_queue_head_t txwq; +static struct ktstate kts; +#ifndef MODULE static int __init aoe_iflist_setup (char *str) {
@@ -44,6 +47,23 @@ static int __init aoe_iflist_setup(char *str)__setup ("aoe_iflist=" , aoe_iflist_setup);#endif +static spinlock_t txlock; +static struct sk_buff_head skbtxq; + +/* enters with txlock held */ +static int +tx (void ) +{ +struct sk_buff *skb; + +while ((skb =skb_dequeue (&skbtxq))) { +spin_unlock_irq (&txlock); +dev_queue_xmit (skb); +spin_lock_irq (&txlock); + } +return 0 ; +} +int is_aoe_netif (struct net_device *ifp) {
@@ -88,10 +108,14 @@ void aoenet_xmit(struct sk_buff_head *queue) {struct sk_buff *skb, *tmp; +ulong flags; skb_queue_walk_safe(queue, skb, tmp) {__skb_unlink (skb, queue); -dev_queue_xmit (skb); +spin_lock_irqsave (&txlock, flags); +skb_queue_tail (&skbtxq, skb); +spin_unlock_irqrestore (&txlock, flags); +wake_up (&txwq); } }
@@ -169,6 +193,15 @@ static struct packet_type aoe_pt __read_mostly = {int __init aoenet_init (void ) { +skb_queue_head_init (&skbtxq); +init_waitqueue_head (&txwq); +spin_lock_init (&txlock); + kts.lock = &txlock; + kts.fn = tx; + kts.waitq = &txwq; + kts.name ="aoe_tx" ; +if (aoe_ktstart (&kts)) +return -EAGAIN ;dev_add_pack (&aoe_pt);return 0 ; }
@@ -176,6 +209,8 @@ aoenet_init(void)void aoenet_exit (void ) { +aoe_ktstop (&kts); +skb_queue_purge (&skbtxq);dev_remove_pack (&aoe_pt); }
Signature · 1 line
1.7.2.5
PATCH 5/14 aoe: use packets that work with the smallest-MTU local interface
In reply to Ed CashinUsers with several network interfaces dedicated to AoE generally do not configure them to support different-sized AoE data payloads on purpose.
For a given AoE target, there will be a set of local network interfaces that can reach it. Using only the payload that will fit in the smallest-sized MTU of all those local interfaces greatly simplifies the driver, especially in failure scenarios.
--- drivers/block/aoe/aoe.h | 7 +- drivers/block/aoe/aoecmd.c | 151 ++++++++++++++++++++++++-------------------- 2 files changed, 87 insertions(+), 71 deletions(-)
drivers/block/aoe/aoe.h +4 -3
@@ -125,9 +125,8 @@ struct frame {struct aoeif {struct net_device *nd; -unsigned char lost; -unsigned char lostjumbo; -ushort maxbcnt; +ulong lost; +int bcnt; };struct aoetgt {
@@ -144,6 +143,7 @@ struct aoetgt {u16 useme;ulong falloc;ulong lastwadj;/* last window adjustment */ +int minbcnt;int wpkts, rpkts; };
@@ -172,6 +172,7 @@ struct aoedev {struct bio *nxbio;struct request *rq; } ip; +ulong maxbcnt;struct aoetgt *targets[NTARGETS ];struct aoetgt **tgt;/* target in use when working */ struct aoetgt *htgt;/* target needing rexmit assistance */
drivers/block/aoe/aoecmd.c +83 -68
229 lines not on this page · raw message
Signature · 1 line
1.7.2.5
PATCH 6/14 aoe: failover remote interface based on aoe_deadsecs parameter
In reply to Ed CashinThe aoe_deadsecs module parameter allows the user to specify a hard limit on the number of seconds an AoE command can be retransmitted before the AoE block device is considered to have failed.
Using aoe_deadsecs to determine the time we try using a different remote interface helps to ensure that the hard limit is not reached before we've tried to recover by sending to a different remote port.
As a data storage target, the AoE target is unambiguously identified by its {major, minor} AoE address tuple, and an AoE target can have multiple MAC addresses. However, note that "target" in the driver code and comments means a {major, minor, MAC address} tuple, as in "somewhere to send packets".
--- drivers/block/aoe/aoe.h | 1 - drivers/block/aoe/aoecmd.c | 8 +++----- 2 files changed, 3 insertions(+), 6 deletions(-)
drivers/block/aoe/aoe.h +0 -1
@@ -96,7 +96,6 @@ enum {TIMERTICK =HZ /10 ,MINTIMER =HZ >>2 , MAXTIMER = HZ << 1, - HELPWAIT = 20, }; struct buf {
drivers/block/aoe/aoecmd.c +3 -5
@@ -632,11 +632,9 @@ rexmit_timer(ulong vp)list_del (pos); t = f->t; -if (n >HELPWAIT ) { -/* see if another target can help */ -if (d->ntargets >1 ) - d->htgt = t; - } +if (n > aoe_deadsecs/2 ) + d->htgt = t;/* see if another target can help */ +if (t->nout == t->maxout) {if (t->maxout >1 ) t->maxout--;
Signature · 1 line
1.7.2.5
PATCH 7/14 aoe: do revalidation steps in order
In reply to Ed CashinThe discovery process begins with an optional AoE config query command and an AoE config query response. Normally when an aoe device is already open, the config query response does not trigger an ATA identify device command to be sent out, since the response contains storage capacity information that, if changed, could surprise the user of the device.
The userland "aoe-revalidate" tool uses a character device to trigger an AoE config query for a particular AoE storage target and an ATA device identify command, even when the device is open.
This change causes the config query to go out first, reflecting the normal discovery sequence. The responses could come back in any order, so this change is fairly cosmetic.
--- drivers/block/aoe/aoechr.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
drivers/block/aoe/aoechr.c +2 -2
@@ -96,13 +96,14 @@ revalidate(const char __user *str, size_t size)return -EINVAL ;spin_lock_irqsave (&d->lock, flags);aoecmd_cleanslate (d); +aoecmd_cfg (major, minor); loop: skb =aoecmd_ata_id (d);spin_unlock_irqrestore (&d->lock, flags);/* try again if we are able to sleep a bit, * otherwise give up this revalidation */ -if (!skb && !msleep_interruptible (200 )) { +if (!skb && !msleep_interruptible (250 )) {spin_lock_irqsave (&d->lock, flags); goto loop; }
@@ -113,7 +114,6 @@ loop:__skb_queue_tail (&queue, skb);aoenet_xmit (&queue); } -aoecmd_cfg (major, minor);return 0 ; }
Signature · 1 line
1.7.2.5
PATCH 8/14 aoe: disallow unsupported AoE minor addresses
In reply to Ed CashinA guard is inserted to prevent AoE minor addresses (slot addresses) higher than 15 to be used, as they are not yet supported by the driver.
There is a change coming that will allow the aoe driver to overcome this limit by using system device minor numbers dynamically, but until then, this guard prevents unexpected targets from being used by the driver when AoE targets with high minor numbers are on the AoE network.
--- drivers/block/aoe/aoecmd.c | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-)
drivers/block/aoe/aoecmd.c +7 -0
@@ -1367,6 +1367,13 @@ aoecmd_cfg_rsp(struct sk_buff *skb) "Check shelf dip switches.\n");return ; } +if (h->minor >=NPERSHELF ) { +pr_err ("aoe: e%ld.%d %s, %d\n" , + aoemajor, h->minor, +"slot number larger than the maximum" , +NPERSHELF -1 ); +return ; + } sysminor =SYSMINOR (aoemajor, h->minor);if (sysminor *AOE_PARTITIONS +AOE_PARTITIONS >MINORMASK ) {
Signature · 1 line
1.7.2.5
PATCH 9/14 aoe: associate frames with the AoE storage target
In reply to Ed CashinIn the driver code, "target" and aoetgt refer to a particular remote interface on the AoE storage target. The latter is identified by its AoE major and minor addresses. Commands that are being sent to an AoE storage target {major, minor} can be sent or retransmitted to any of the remote MAC addresses associated with the AoE storage target.
That is, frames are naturally associated with not an aoetgt (AoE major, AoE minor, remote MAC address) but an aoedev (AoE major, AoE minor). Making the code reflect that reality simplifies the driver, especially when the path to a remote MAC address becomes unusable.
--- drivers/block/aoe/aoe.h | 8 +++--- drivers/block/aoe/aoecmd.c | 65 +++++++++++++++++++------------------------- drivers/block/aoe/aoedev.c | 30 +++++++++++--------- 3 files changed, 49 insertions(+), 54 deletions(-)
drivers/block/aoe/aoe.h +4 -4
@@ -91,7 +91,7 @@ enum {NTARGETS =8 ,NAOEIFS =8 ,NSKBPOOLMAX =256 , -NFACTIVE =17 , +NFACTIVE =61 ,TIMERTICK =HZ /10 , MINTIMER = HZ >> 2,
@@ -132,14 +132,11 @@ struct aoetgt {unsigned char addr[6 ];ushort nframes;struct aoedev *d;/* parent device I belong to */ -struct list_head factive[NFACTIVE ];/* hash of active frames */ struct list_head ffree;/* list of free frames */ struct aoeif ifs[NAOEIFS ];struct aoeif *ifp;/* current aoeif in use */ ushort nout;ushort maxout; -u16 lasttag;/* last tag sent */ -u16 useme;ulong falloc;ulong lastwadj;/* last window adjustment */ int minbcnt;
@@ -156,6 +153,8 @@ struct aoedev {u16 rttavg;/* round trip average of requests/responses */ u16 mintimer;u16 fw_ver;/* version of blade's firmware */ +u16 lasttag;/* last tag sent */ +u16 useme;ulong ref;struct work_struct work;/* disk create work struct */ struct gendisk *gd;
@@ -172,6 +171,7 @@ struct aoedev {struct request *rq; } ip;ulong maxbcnt; +struct list_head factive[NFACTIVE ];/* hash of active frames */ struct aoetgt *targets[NTARGETS ];struct aoetgt **tgt;/* target in use when working */ struct aoetgt *htgt;/* target needing rexmit assistance */
drivers/block/aoe/aoecmd.c +28 -37
152 lines not on this page · raw message
drivers/block/aoe/aoedev.c +17 -13
@@ -103,22 +103,23 @@ aoedev_downdev(struct aoedev *d) d->flags &= ~DEVFL_UP ; -/* clean out active buffers on all targets */ +/* clean out active buffers */ +for (i =0 ; i <NFACTIVE ; i++) { + head = &d->factive[i]; +list_for_each_safe (pos, nx, head) { + f = list_entry(pos, struct frame, head); +list_del (pos); +if (f->buf) { + f->buf->nframesout--; +aoe_failbuf (d, f->buf); + } +aoe_freetframe (f); + } + } +/* reset window dressings */ tt = d->targets; te = tt +NTARGETS ;for (; tt < te && (t = *tt); tt++) { -for (i =0 ; i <NFACTIVE ; i++) { - head = &t->factive[i]; -list_for_each_safe (pos, nx, head) { -list_del (pos); - f = list_entry(pos, struct frame, head); -if (f->buf) { - f->buf->nframesout--; -aoe_failbuf (d, f->buf); - } -aoe_freetframe (f); - } - } t->maxout = t->nframes; t->nout =0 ; }
@@ -250,6 +251,7 @@ struct aoedev * aoedev_by_sysminor_m(ulong sysminor) {struct aoedev *d; +int i;ulong flags;spin_lock_irqsave (&devlist_lock, flags);
@@ -275,6 +277,8 @@ aoedev_by_sysminor_m(ulong sysminor) d->bufpool =NULL ;/* defer to aoeblk_gdalloc */ d->tgt = d->targets; d->ref =1 ; +for (i =0 ; i <NFACTIVE ; i++) +INIT_LIST_HEAD (&d->factive[i]); d->sysminor = sysminor; d->aoemajor =AOEMAJOR (sysminor); d->aoeminor =AOEMINOR (sysminor);
Signature · 1 line
1.7.2.5
PATCH 10/14 aoe: increase net_device reference count while using it
In reply to Ed CashinThis change eliminates the danger that the user could rmmod the driver for a network interface that is being used for AoE by the aoe driver.
--- drivers/block/aoe/aoecmd.c | 4 ++++ drivers/block/aoe/aoedev.c | 7 +++++++ 2 files changed, 11 insertions(+), 0 deletions(-)
drivers/block/aoe/aoecmd.c +4 -0
@@ -493,12 +493,15 @@ static void ejectif(struct aoetgt *t, struct aoeif *ifp) { struct aoeif *e; +struct net_device *nd;ulong n; + nd = ifp->nd; e = t->ifs +NAOEIFS -1 ; n = (e - ifp) *sizeof *ifp;memmove (ifp, ifp+1 , n); e->nd =NULL ; +dev_put (nd); } static int
@@ -1325,6 +1328,7 @@ setifbcnt(struct aoetgt *t, struct net_device *nd, int bcnt)pr_err ("aoe: device setifbcnt failure; too many interfaces.\n" );return ; } +dev_hold (nd); p->nd = nd; p->bcnt = bcnt; }
drivers/block/aoe/aoedev.c +7 -0
@@ -295,6 +295,13 @@ freetgt(struct aoedev *d, struct aoetgt *t) {struct frame *f;struct list_head *pos, *nx, *head; +struct aoeif *ifp; + +for (ifp = t->ifs; ifp < &t->ifs[NAOEIFS ]; ++ifp) { +if (!ifp->nd) +break ; +dev_put (ifp->nd); + } head = &t->ffree;list_for_each_safe (pos, nx, head) {
Signature · 1 line
1.7.2.5
PATCH 11/14 aoe: remove unused code and add cosmetic improvements
In reply to Ed CashinThis change removes some unused code and attempts to increase code consistency.
--- drivers/block/aoe/aoe.h | 10 +++------- drivers/block/aoe/aoechr.c | 1 + drivers/block/aoe/aoecmd.c | 13 ++++--------- drivers/block/aoe/aoenet.c | 3 ++- 4 files changed, 10 insertions(+), 17 deletions(-)
drivers/block/aoe/aoe.h +3 -7
@@ -75,18 +75,14 @@ enum {DEVFL_UP =1 ,/* device is installed in system and ready for AoE->ATA commands */ DEVFL_TKILL = (1 <<1 ),/* flag for timer to know when to kill self */ DEVFL_EXT = (1 <<2 ),/* device accepts lba48 commands */ -DEVFL_CLOSEWAIT = (1 <<3 ),/* device is waiting for all closes to revalidate */ -DEVFL_GDALLOC = (1 <<4 ),/* need to alloc gendisk */ -DEVFL_KICKME = (1 <<5 ),/* slow polling network card catch */ -DEVFL_NEWSIZE = (1 <<6 ),/* need to update dev size in block layer */ - - BUFFL_FAIL = 1, +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 */ };enum {DEFAULTBCNT =2 *512 ,/* 2 sectors */ NPERSHELF =16 ,/* number of slots per shelf address */ -FREETAG =-1 ,MIN_BUFS =16 ,NTARGETS =8 , NAOEIFS = 8,
drivers/block/aoe/aoechr.c +1 -0
@@ -174,6 +174,7 @@ aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offpbreak ;case MINOR_FLUSH : ret =aoedev_flush (buf, cnt); +break ; }if (ret ==0 ) ret = cnt;
drivers/block/aoe/aoecmd.c +4 -9
@@ -283,7 +283,6 @@ aoecmd_ata_rw(struct aoedev *d)struct aoe_hdr *h;struct aoe_atahdr *ah;struct buf *buf; -struct bio_vec *bv;struct aoetgt *t;struct sk_buff *skb;struct sk_buff_head queue;
@@ -300,7 +299,6 @@ aoecmd_ata_rw(struct aoedev *d)if (f ==NULL )return 0 ; t = *d->tgt; - bv = buf->bv; bcnt = d->maxbcnt;if (bcnt ==0 ) bcnt =DEFAULTBCNT ;
@@ -787,28 +785,25 @@ void aoecmd_sleepwork(struct work_struct *work) { struct aoedev *d = container_of(work, struct aoedev, work); +struct block_device *bd; +u64 ssize;if (d->flags &DEVFL_GDALLOC )aoeblk_gdalloc (d);if (d->flags &DEVFL_NEWSIZE ) { -struct block_device *bd; -unsigned long flags; -u64 ssize; - ssize =get_capacity (d->gd); bd =bdget_disk (d->gd,0 ); -if (bd) {mutex_lock (&bd->bd_inode->i_mutex);i_size_write (bd->bd_inode, (loff_t )ssize<<9 );mutex_unlock (&bd->bd_inode->i_mutex);bdput (bd); } -spin_lock_irqsave (&d->lock, flags); +spin_lock_irq (&d->lock); d->flags |=DEVFL_UP ; d->flags &= ~DEVFL_NEWSIZE ; -spin_unlock_irqrestore (&d->lock, flags); +spin_unlock_irq (&d->lock); } }
drivers/block/aoe/aoenet.c +2 -1
@@ -175,7 +175,8 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,default :if (h->cmd >=AOECMD_VEND_MIN )break ;/* don't complain about vendor commands */ -printk (KERN_INFO "aoe: unknown cmd %d\n" , h->cmd); +pr_info ("aoe: unknown AoE command type 0x%02x\n" , h->cmd); +break ; }if (!skb)
Signature · 1 line
1.7.2.5
PATCH 12/14 aoe: update internal version number to 49
In reply to Ed CashinThe internal version number of the aoe driver appears in a console message when the driver loads and is usually obtained by the user with the userland aoe-version tool, part of the aoetools.[1]
Although this patchset includes bugfixes backported from higher-numbered versions published on the coraid.com website, it is a form of version 49.
1. http://aoetools.sourceforge.net/
--- drivers/block/aoe/aoe.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/block/aoe/aoe.h +1 -1
@@ -1,5 +1,5 @@/* Copyright (c) 2007 Coraid, Inc. See COPYING for GPL terms. */ -#define VERSION "47" +#define VERSION "49"#define AOE_MAJOR 152#define DEVICE_NAME "aoe"
Signature · 1 line
1.7.2.5
PATCH 13/14 aoe: update copyright year in touched files
In reply to Ed Cashin--- drivers/block/aoe/aoe.h | 2 +- drivers/block/aoe/aoeblk.c | 2 +- drivers/block/aoe/aoechr.c | 2 +- drivers/block/aoe/aoecmd.c | 2 +- drivers/block/aoe/aoedev.c | 2 +- drivers/block/aoe/aoemain.c | 2 +- drivers/block/aoe/aoenet.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-)
drivers/block/aoe/aoe.h +1 -1
@@ -1,4 +1,4 @@ -/* Copyright (c) 2007 Coraid, Inc. See COPYING for GPL terms. */ +/* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */ #define VERSION "49"#define AOE_MAJOR 152#define DEVICE_NAME "aoe"
drivers/block/aoe/aoeblk.c +1 -1
@@ -1,4 +1,4 @@ -/* Copyright (c) 2007 Coraid, Inc. See COPYING for GPL terms. */ +/* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */ /* * aoeblk.c * block device routines
drivers/block/aoe/aoechr.c +1 -1
@@ -1,4 +1,4 @@ -/* Copyright (c) 2007 Coraid, Inc. See COPYING for GPL terms. */ +/* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */ /* * aoechr.c * AoE character device driver
drivers/block/aoe/aoecmd.c +1 -1
@@ -1,4 +1,4 @@ -/* Copyright (c) 2007 Coraid, Inc. See COPYING for GPL terms. */ +/* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */ /* * aoecmd.c * Filesystem request handling methods
drivers/block/aoe/aoedev.c +1 -1
@@ -1,4 +1,4 @@ -/* Copyright (c) 2007 Coraid, Inc. See COPYING for GPL terms. */ +/* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */ /* * aoedev.c * AoE device utility functions; maintains device list.
drivers/block/aoe/aoemain.c +1 -1
@@ -1,4 +1,4 @@ -/* Copyright (c) 2007 Coraid, Inc. See COPYING for GPL terms. */ +/* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */ /* * aoemain.c * Module initialization routines, discover timer
drivers/block/aoe/aoenet.c +1 -1
@@ -1,4 +1,4 @@ -/* Copyright (c) 2007 Coraid, Inc. See COPYING for GPL terms. */ +/* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */ /* * aoenet.c * Ethernet portion of AoE driver
Signature · 1 line
1.7.2.5
PATCH 14/14 aoe: update documentation with new URL and VM settings reference
In reply to Ed CashinThe old area has a new URL. Also, now that the driver can perform better, it is worth mentioning the VM settings that help aoe to sink dirty pages out early, avoiding unecessary memory pressure when much I/O is going on.
--- Documentation/aoe/aoe.txt | 9 ++++++--- MAINTAINERS | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-)
Documentation/aoe/aoe.txt +6 -3
@@ -1,8 +1,11 @@ -The EtherDrive (R) HOWTO for users of 2.6 kernels is found at ... +The EtherDrive (R) HOWTO for 2.6 and 3.x kernels is found at ... - http://www.coraid.com/SUPPORT/EtherDrive-HBA + http://support.coraid.com/support/linux/EtherDrive-2.6-HOWTO.html - It has many tips and hints! +It has many tips and hints! Please see, especially, recommended +tunings for virtual memory: + + http://support.coraid.com/support/linux/EtherDrive-2.6-HOWTO-5.html#ss5.19 The aoetools are userland programs that are designed to work with this driver. The aoetools are on sourceforge.
MAINTAINERS +1 -1
@@ -1250,7 +1250,7 @@ F: include/linux/i2c/at24.h ATA OVER ETHERNET (AOE) DRIVER M: "Ed L. Cashin" <[email protected]> -W: http://www.coraid.com/support/linux +W: http://support.coraid.com/support/linux S: Supported F: Documentation/aoe/ F: drivers/block/aoe/
Signature · 1 line
1.7.2.5
[second send after HTML part made vger reject my first email]
Quoted 4 lines · Ed Cashin
These patches go a long way to updating the in-kernel aoe driver with the changes that have been in the coraid.com-distributed version, bringing it from (aoe internal) version 47 to version 49. They apply to commit
23dcfa61bac244e1of the mainline git tree.
Just a heads up: A colleague found a list_del corruption warning using 3.5.2 with these patches, but the warning also occurs without these patches, so I plan to do a git bisect to find out when the regression occurred. The warning appears to be for the events of the bdi->completions when blk_cleanup_queue is called during "rmmod aoe".
Signature · 1 line
Ed