diff options
author | Ed L. Cashin <ecashin@coraid.com> | 2006-09-20 14:36:49 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-10-18 15:53:50 -0400 |
commit | e407a7f6cd143b3ab4eb3d7e1cf882e96b710eb5 (patch) | |
tree | a180d2a6ae40b1fe6773c93a24a5c469948fd59d /drivers/block/aoe/aoedev.c | |
parent | 2fdc0ea75b26e3009cfdf72e79901e4e16bb99bd (diff) |
aoe: zero copy write 1 of 2
Avoid memory copy on writes.
(This patch depends on fixes in patch 9 to follow.)
Although skb->len should not be set when working with linear skbuffs,
the skb->tail pointer maintained by skb_put/skb_trim is not relevant
to what happens when the skb_fill_page_desc function is called. This
issue was raised without comment in linux-kernel and netdev earlier
this month:
http://thread.gmane.org/gmane.linux.kernel/446474/
http://thread.gmane.org/gmane.linux.network/45444/
So until there is something analogous to skb_put that works for
zero-copy write skbuffs, we will do what the other callers of
skb_fill_page_desc are doing.
Signed-off-by: "Ed L. Cashin" <ecashin@coraid.com>
Acked-by: Alan Cox <alan@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/block/aoe/aoedev.c')
-rw-r--r-- | drivers/block/aoe/aoedev.c | 42 |
1 files changed, 30 insertions, 12 deletions
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index c7e05ed82512..abf1d3c073e3 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c | |||
@@ -63,22 +63,32 @@ aoedev_newdev(ulong nframes) | |||
63 | struct frame *f, *e; | 63 | struct frame *f, *e; |
64 | 64 | ||
65 | d = kzalloc(sizeof *d, GFP_ATOMIC); | 65 | d = kzalloc(sizeof *d, GFP_ATOMIC); |
66 | if (d == NULL) | ||
67 | return NULL; | ||
68 | f = kcalloc(nframes, sizeof *f, GFP_ATOMIC); | 66 | f = kcalloc(nframes, sizeof *f, GFP_ATOMIC); |
69 | if (f == NULL) { | 67 | switch (!d || !f) { |
70 | kfree(d); | 68 | case 0: |
69 | d->nframes = nframes; | ||
70 | d->frames = f; | ||
71 | e = f + nframes; | ||
72 | for (; f<e; f++) { | ||
73 | f->tag = FREETAG; | ||
74 | f->skb = new_skb(ETH_ZLEN); | ||
75 | if (!f->skb) | ||
76 | break; | ||
77 | } | ||
78 | if (f == e) | ||
79 | break; | ||
80 | while (f > d->frames) { | ||
81 | f--; | ||
82 | dev_kfree_skb(f->skb); | ||
83 | } | ||
84 | default: | ||
85 | if (f) | ||
86 | kfree(f); | ||
87 | if (d) | ||
88 | kfree(d); | ||
71 | return NULL; | 89 | return NULL; |
72 | } | 90 | } |
73 | |||
74 | INIT_WORK(&d->work, aoecmd_sleepwork, d); | 91 | INIT_WORK(&d->work, aoecmd_sleepwork, d); |
75 | |||
76 | d->nframes = nframes; | ||
77 | d->frames = f; | ||
78 | e = f + nframes; | ||
79 | for (; f<e; f++) | ||
80 | f->tag = FREETAG; | ||
81 | |||
82 | spin_lock_init(&d->lock); | 92 | spin_lock_init(&d->lock); |
83 | init_timer(&d->timer); | 93 | init_timer(&d->timer); |
84 | d->timer.data = (ulong) d; | 94 | d->timer.data = (ulong) d; |
@@ -160,11 +170,19 @@ aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt) | |||
160 | static void | 170 | static void |
161 | aoedev_freedev(struct aoedev *d) | 171 | aoedev_freedev(struct aoedev *d) |
162 | { | 172 | { |
173 | struct frame *f, *e; | ||
174 | |||
163 | if (d->gd) { | 175 | if (d->gd) { |
164 | aoedisk_rm_sysfs(d); | 176 | aoedisk_rm_sysfs(d); |
165 | del_gendisk(d->gd); | 177 | del_gendisk(d->gd); |
166 | put_disk(d->gd); | 178 | put_disk(d->gd); |
167 | } | 179 | } |
180 | f = d->frames; | ||
181 | e = f + d->nframes; | ||
182 | for (; f<e; f++) { | ||
183 | skb_shinfo(f->skb)->nr_frags = 0; | ||
184 | dev_kfree_skb(f->skb); | ||
185 | } | ||
168 | kfree(d->frames); | 186 | kfree(d->frames); |
169 | if (d->bufpool) | 187 | if (d->bufpool) |
170 | mempool_destroy(d->bufpool); | 188 | mempool_destroy(d->bufpool); |