2009-04-03 13:06:23

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH] ps3vram: Fix error path (return -EIO) for short read/write

Signed-off-by: Geert Uytterhoeven <[email protected]>
---
drivers/block/ps3vram.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c
index 8eddef3..2e79d2c 100644
--- a/drivers/block/ps3vram.c
+++ b/drivers/block/ps3vram.c
@@ -585,6 +585,7 @@ static int ps3vram_make_request(struct request_queue *q, struct bio *bio)

if (retlen != len) {
dev_err(&dev->core, "Short %s\n", op);
+ error = -EIO;
goto out;
}

--
1.6.0.4


2009-04-03 13:05:52

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH] ps3vram: Use proc_create_data() instead of proc_create()

Use proc_create_data() to avoid race conditions.

Reported-by: Alexey Dobriyan <[email protected]>
Signed-off-by: Geert Uytterhoeven <[email protected]>
---
drivers/block/ps3vram.c | 8 +++-----
1 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c
index 2e79d2c..6e73868 100644
--- a/drivers/block/ps3vram.c
+++ b/drivers/block/ps3vram.c
@@ -546,12 +546,10 @@ static void __devinit ps3vram_proc_init(struct ps3_system_bus_device *dev)
struct ps3vram_priv *priv = dev->core.driver_data;
struct proc_dir_entry *pde;

- pde = proc_create(DEVICE_NAME, 0444, NULL, &ps3vram_proc_fops);
- if (!pde) {
+ pde = proc_create_data(DEVICE_NAME, 0444, NULL, &ps3vram_proc_fops,
+ priv);
+ if (!pde)
dev_warn(&dev->core, "failed to create /proc entry\n");
- return;
- }
- pde->data = priv;
}

static int ps3vram_make_request(struct request_queue *q, struct bio *bio)
--
1.6.0.4

2009-04-03 13:06:43

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH] ps3vram: Correct exchanged gotos in ps3vram_probe() error path

From: Jim Paris <[email protected]>

From: Jim Paris <[email protected]>

Signed-off-by: Geert Uytterhoeven <[email protected]>
---
drivers/block/ps3vram.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c
index 6e73868..3c9ad19 100644
--- a/drivers/block/ps3vram.c
+++ b/drivers/block/ps3vram.c
@@ -635,7 +635,7 @@ static int __devinit ps3vram_probe(struct ps3_system_bus_device *dev)
if (ps3_open_hv_device(dev)) {
dev_err(&dev->core, "ps3_open_hv_device failed\n");
error = -EAGAIN;
- goto out_close_gpu;
+ goto out_free_xdr_buf;
}

/* Request memory */
@@ -659,7 +659,7 @@ static int __devinit ps3vram_probe(struct ps3_system_bus_device *dev)
dev_err(&dev->core, "lv1_gpu_memory_allocate failed %d\n",
status);
error = -ENOMEM;
- goto out_free_xdr_buf;
+ goto out_close_gpu;
}

/* Request context */
--
1.6.0.4

2009-04-03 13:07:02

by Geert Uytterhoeven

[permalink] [raw]
Subject: [PATCH] ps3vram: Replace mutex by spinlock + list

Remove the mutex serializing access to the cache.
Instead, queue up new requests on a list if the driver is busy.

This improves sequential write performance by ca. 2%.

Signed-off-by: Geert Uytterhoeven <[email protected]>
---
drivers/block/ps3vram.c | 55 ++++++++++++++++++++++++++++++++++------------
1 files changed, 40 insertions(+), 15 deletions(-)

diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c
index 3c9ad19..1396038 100644
--- a/drivers/block/ps3vram.c
+++ b/drivers/block/ps3vram.c
@@ -81,8 +81,8 @@ struct ps3vram_priv {

struct ps3vram_cache cache;

- /* Used to serialize cache/DMA operations */
- struct mutex lock;
+ spinlock_t lock; /* protecting list of bios */
+ struct bio *tail;
};


@@ -449,8 +449,6 @@ static int ps3vram_read(struct ps3_system_bus_device *dev, loff_t from,
offset = (unsigned int) (from & (priv->cache.page_size - 1));
avail = priv->cache.page_size - offset;

- mutex_lock(&priv->lock);
-
entry = ps3vram_cache_match(dev, from);
cached = CACHE_OFFSET + entry * priv->cache.page_size + offset;

@@ -462,8 +460,6 @@ static int ps3vram_read(struct ps3_system_bus_device *dev, loff_t from,
avail = count;
memcpy(buf, priv->xdr_buf + cached, avail);

- mutex_unlock(&priv->lock);
-
buf += avail;
count -= avail;
from += avail;
@@ -494,8 +490,6 @@ static int ps3vram_write(struct ps3_system_bus_device *dev, loff_t to,
offset = (unsigned int) (to & (priv->cache.page_size - 1));
avail = priv->cache.page_size - offset;

- mutex_lock(&priv->lock);
-
entry = ps3vram_cache_match(dev, to);
cached = CACHE_OFFSET + entry * priv->cache.page_size + offset;

@@ -509,8 +503,6 @@ static int ps3vram_write(struct ps3_system_bus_device *dev, loff_t to,

priv->cache.tags[entry].flags |= CACHE_PAGE_DIRTY;

- mutex_unlock(&priv->lock);
-
buf += avail;
count -= avail;
to += avail;
@@ -552,17 +544,17 @@ static void __devinit ps3vram_proc_init(struct ps3_system_bus_device *dev)
dev_warn(&dev->core, "failed to create /proc entry\n");
}

-static int ps3vram_make_request(struct request_queue *q, struct bio *bio)
+static struct bio *ps3vram_do_bio(struct ps3_system_bus_device *dev,
+ struct bio *bio)
{
- struct ps3_system_bus_device *dev = q->queuedata;
+ struct ps3vram_priv *priv = dev->core.driver_data;
int write = bio_data_dir(bio) == WRITE;
const char *op = write ? "write" : "read";
loff_t offset = bio->bi_sector << 9;
int error = 0;
struct bio_vec *bvec;
unsigned int i;
-
- dev_dbg(&dev->core, "%s\n", __func__);
+ struct bio *next;

bio_for_each_segment(bvec, bio, i) {
/* PS3 is ppc64, so we don't handle highmem */
@@ -593,7 +585,40 @@ static int ps3vram_make_request(struct request_queue *q, struct bio *bio)
dev_dbg(&dev->core, "%s completed\n", op);

out:
+ spin_lock_irq(&priv->lock);
+ next = bio->bi_next;
+ if (!next)
+ priv->tail = NULL;
+ else
+ bio->bi_next = NULL;
+ spin_unlock_irq(&priv->lock);
+
bio_endio(bio, error);
+ return next;
+}
+
+static int ps3vram_make_request(struct request_queue *q, struct bio *bio)
+{
+ struct ps3_system_bus_device *dev = q->queuedata;
+ struct ps3vram_priv *priv = dev->core.driver_data;
+
+ dev_dbg(&dev->core, "%s\n", __func__);
+
+ spin_lock_irq(&priv->lock);
+ if (priv->tail) {
+ priv->tail->bi_next = bio;
+ priv->tail = bio;
+ spin_unlock_irq(&priv->lock);
+ return 0;
+ }
+
+ priv->tail = bio;
+ spin_unlock_irq(&priv->lock);
+
+ do {
+ bio = ps3vram_do_bio(dev, bio);
+ } while (bio);
+
return 0;
}

@@ -613,7 +638,7 @@ static int __devinit ps3vram_probe(struct ps3_system_bus_device *dev)
goto fail;
}

- mutex_init(&priv->lock);
+ spin_lock_init(&priv->lock);
dev->core.driver_data = priv;

priv = dev->core.driver_data;
--
1.6.0.4

2009-04-03 18:03:34

by Jens Axboe

[permalink] [raw]
Subject: Re: [PATCH] ps3vram: Replace mutex by spinlock + list

On Fri, Apr 03 2009, Geert Uytterhoeven wrote:
> Remove the mutex serializing access to the cache.
> Instead, queue up new requests on a list if the driver is busy.
>
> This improves sequential write performance by ca. 2%.

Great, precisely the method I wanted to see there! I've added your three
patches, thanks Geert.


--
Jens Axboe