|
@@ -35,6 +35,8 @@ enum {
|
|
|
Maxconf = 4*1024, /* max length for config */
|
|
|
Ndevs = 32, /* max. inner devs per command */
|
|
|
Nfsdevs = 128, /* max. created devs, total */
|
|
|
+ Maxretries = 3, /* max. retries of i/o errors */
|
|
|
+ Retrypause = 5000, /* ms. to pause between retries */
|
|
|
};
|
|
|
|
|
|
#define Cfgstr "fsdev:\n"
|
|
@@ -567,7 +569,11 @@ mread(Chan *c, void *a, long n, vlong off)
|
|
|
print("#k/%s: retry %d read for byte %,lld "
|
|
|
"count %ld: %s\n", mp->name, retry, off,
|
|
|
n, (up && up->errstr? up->errstr: ""));
|
|
|
- tsleep(&up->sleep, return0, 0, 2000);
|
|
|
+ /*
|
|
|
+ * pause before retrying in case it's due to
|
|
|
+ * a transient bus or controller problem.
|
|
|
+ */
|
|
|
+ tsleep(&up->sleep, return0, 0, Retrypause);
|
|
|
}
|
|
|
for (i = 0; i < mp->ndevs; i++){
|
|
|
if (waserror())
|
|
@@ -580,7 +586,7 @@ mread(Chan *c, void *a, long n, vlong off)
|
|
|
break; /* read a good copy */
|
|
|
}
|
|
|
}
|
|
|
- } while (i == mp->ndevs && ++retry < 2);
|
|
|
+ } while (i == mp->ndevs && ++retry <= Maxretries);
|
|
|
if (i == mp->ndevs) {
|
|
|
/* no mirror had a good copy of the block */
|
|
|
print("#k/%s: byte %,lld count %ld: CAN'T READ "
|
|
@@ -639,7 +645,11 @@ mwrite(Chan *c, void *a, long n, vlong off)
|
|
|
print("#k/%s: retry %d write for byte %,lld "
|
|
|
"count %ld: %s\n", mp->name, retry, off,
|
|
|
n, (up && up->errstr? up->errstr: ""));
|
|
|
- tsleep(&up->sleep, return0, 0, 2000);
|
|
|
+ /*
|
|
|
+ * pause before retrying in case it's due to
|
|
|
+ * a transient bus or controller problem.
|
|
|
+ */
|
|
|
+ tsleep(&up->sleep, return0, 0, Retrypause);
|
|
|
}
|
|
|
allbad = 1;
|
|
|
anybad = 0;
|
|
@@ -658,7 +668,7 @@ mwrite(Chan *c, void *a, long n, vlong off)
|
|
|
else
|
|
|
anybad = 1;
|
|
|
}
|
|
|
- } while (anybad && ++retry < 2);
|
|
|
+ } while (anybad && ++retry <= Maxretries);
|
|
|
if (allbad) {
|
|
|
/* no mirror took a good copy of the block */
|
|
|
print("#k/%s: byte %,lld count %ld: CAN'T WRITE "
|