Module Name: src
Committed By: reinoud
Date: Thu Jul 2 16:56:35 UTC 2009
Modified Files:
src/sys/fs/udf: udf_strat_rmw.c
Log Message:
Enhance dumping on buffer screwup. Also prevent races or invalid combinations
to exist for ecclines.
To generate a diff of this commit:
cvs rdiff -u -r1.19 -r1.20 src/sys/fs/udf/udf_strat_rmw.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/fs/udf/udf_strat_rmw.c
diff -u src/sys/fs/udf/udf_strat_rmw.c:1.19 src/sys/fs/udf/udf_strat_rmw.c:1.20
--- src/sys/fs/udf/udf_strat_rmw.c:1.19 Wed May 20 15:30:26 2009
+++ src/sys/fs/udf/udf_strat_rmw.c Thu Jul 2 16:56:35 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: udf_strat_rmw.c,v 1.19 2009/05/20 15:30:26 reinoud Exp $ */
+/* $NetBSD: udf_strat_rmw.c,v 1.20 2009/07/02 16:56:35 reinoud Exp $ */
/*
* Copyright (c) 2006, 2008 Reinoud Zandijk
@@ -28,7 +28,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__KERNEL_RCSID(0, "$NetBSD: udf_strat_rmw.c,v 1.19 2009/05/20 15:30:26 reinoud Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udf_strat_rmw.c,v 1.20 2009/07/02 16:56:35 reinoud Exp $");
#endif /* not lint */
@@ -242,22 +242,26 @@
if (curqueue) {
ret = bufq_cancel(priv->queues[curqueue], eccline->buf);
- DPRINTF(PARANOIA, ("push_eccline bufq_cancel returned %p when "
- "requested to remove %p from queue %d\n", ret,
- eccline->buf, curqueue));
#ifdef DIAGNOSTIC
if (ret == NULL) {
int i;
printf("udf_push_eccline: bufq_cancel can't find "
- "buffer; dumping queues\n");
+ "buffer %p on queue %d; "
+ "dumping queues\n", eccline->buf, curqueue);
for (i = 1; i < UDF_SHED_MAX; i++) {
printf("queue %d\n\t", i);
ret = bufq_get(priv->queues[i]);
while (ret) {
printf("%p ", ret);
+ if (BTOE(ret)->queued_on != i)
+ printf("WRONGQ ");
if (ret == eccline->buf)
printf("[<-] ");
+ if (ret == bufq_peek(priv->queues[i])) {
+ printf("LOOP ");
+ break;
+ }
ret = bufq_get(priv->queues[i]);
}
printf("\n");
@@ -275,9 +279,9 @@
eccline->buf->b_blkno = eccline->start_sector;
eccline->buf->b_rawblkno = eccline->start_sector;
- bufq_put(priv->queues[newqueue], eccline->buf);
eccline->queued_on = newqueue;
priv->num_queued[newqueue]++;
+ bufq_put(priv->queues[newqueue], eccline->buf);
vfs_timestamp(&priv->last_queued[newqueue]);
if (eccline->flags & ECC_FLOATING) {
@@ -300,7 +304,7 @@
KASSERT(mutex_owned(&priv->discstrat_mutex));
buf = bufq_get(priv->queues[queued_on]);
- if (!buf) {
+ if (buf == NULL) {
KASSERT(priv->num_queued[queued_on] == 0);
return NULL;
}
@@ -390,9 +394,11 @@
&priv->discstrat_mutex, hz/8);
goto retry;
}
- /* push back line if we're waiting for it */
- if (eccline->flags & ECC_WANTED) {
- udf_push_eccline(eccline, UDF_SHED_IDLE);
+
+ /* push back line if we're waiting for it or its locked */
+ if (eccline->flags & (ECC_WANTED | ECC_LOCKED)) {
+ /* XXX what were they doing on the free list anyway? */
+ udf_push_eccline(eccline, UDF_SHED_WAITING);
goto retry;
}
@@ -1002,6 +1008,7 @@
*/
udf_puteccline(eccline);
+
DPRINTF(ECCLINE, ("read callback finished\n"));
}
@@ -1014,7 +1021,7 @@
uint64_t bit;
int error, i, len;
- DPRINTF(ECCLINE, ("write callback called\n"));
+ DPRINTF(ECCLINE, ("write callback called buf %p\n", buf));
/* post process write action */
error = buf->b_error;
for (i = 0; i < ump->packet_size; i++) {
@@ -1179,16 +1186,18 @@
new_queue = UDF_SHED_READING;
}
}
+ if (eccline->flags & ECC_LOCKED)
+ new_queue = UDF_SHED_WAITING;
udf_push_eccline(eccline, new_queue);
cnt++;
}
- /* maintenance: free exess ecclines */
+ /* maintenance: free excess ecclines */
while (priv->num_queued[UDF_SHED_FREE] > UDF_ECCLINE_MAXFREE) {
eccline = udf_pop_eccline(priv, UDF_SHED_FREE);
KASSERT(eccline);
KASSERT(eccline->refcnt == 0);
- if (eccline->flags & ECC_WANTED) {
+ if (eccline->flags & (ECC_WANTED | ECC_LOCKED)) {
udf_push_eccline(eccline, UDF_SHED_IDLE);
DPRINTF(ECCLINE, ("Tried removing, pushed back to free list\n"));
} else {