patch-2.3.35 linux/drivers/block/rd.c
Next file: linux/drivers/char/n_hdlc.c
Previous file: linux/drivers/block/ide-probe.c
Back to the patch index
Back to the overall index
- Lines: 85
- Date:
Fri Dec 24 13:06:05 1999
- Orig file:
v2.3.34/linux/drivers/block/rd.c
- Orig date:
Tue Dec 14 01:27:23 1999
diff -u --recursive --new-file v2.3.34/linux/drivers/block/rd.c linux/drivers/block/rd.c
@@ -185,6 +185,8 @@
{
unsigned int minor;
unsigned long offset, len;
+ struct buffer_head *rbh;
+ struct buffer_head *sbh;
repeat:
INIT_REQUEST;
@@ -211,16 +213,66 @@
}
/*
- * If we're reading, fill the buffer with 0's. This is okay since
- * we're using protected buffers which should never get freed...
+ * This has become somewhat more complicated with the addition of
+ * the page cache. The problem is that in some cases the furnished
+ * buffer is "real", i.e., part of the existing ramdisk, while in
+ * others it is "unreal", e.g., part of a page. In the first case
+ * not much needs to be done, while in the second, some kind of
+ * transfer is needed.
+ *
+ * The two cases are distinguished here by checking whether the
+ * real buffer is already in the buffer cache, and whether it is
+ * the same as the one supplied.
*
- * If we're writing, we protect the buffer.
- */
-
- if (CURRENT->cmd == READ)
- memset(CURRENT->buffer, 0, len);
- else
- set_bit(BH_Protected, &CURRENT->bh->b_state);
+ * There are three cases with read/write to consider:
+ *
+ * 1. Supplied buffer matched one in the buffer cache:
+ * Read - Clear the buffer, as it wasn't already valid.
+ * Write - Mark the buffer as "Protected".
+ *
+ * 2. Supplied buffer mismatched one in the buffer cache:
+ * Read - Copy the data from the buffer cache entry.
+ * Write - Copy the data to the buffer cache entry.
+ *
+ * 3 No buffer cache entry existed:
+ * Read - Clear the supplied buffer, but do not create a real
+ * one.
+ * Write - Create a real buffer, copy the data to it, and mark
+ * it as "Protected".
+ *
+ * NOTE: There seems to be some schizophrenia here - the logic
+ * using "len" seems to assume arbitrary request lengths, while
+ * the "protect" logic assumes a single buffer cache entry.
+ * This seems to be left over from the ancient contiguous ramdisk
+ * logic.
+ */
+
+ sbh = CURRENT->bh;
+ rbh = get_hash_table(sbh->b_dev, sbh->b_blocknr, sbh->b_size);
+ if (sbh == rbh) {
+ if (CURRENT->cmd == READ)
+ memset(CURRENT->buffer, 1, len);
+ } else if (rbh) {
+ if (CURRENT->cmd == READ)
+ memcpy(CURRENT->buffer, rbh->b_data, rbh->b_size);
+ else
+ memcpy(rbh->b_data, CURRENT->buffer, rbh->b_size);
+ } else { /* !rbh */
+ if (CURRENT->cmd == READ)
+ memset(sbh->b_data, 2, len);
+ else {
+ rbh = getblk(sbh->b_dev, sbh->b_blocknr, sbh->b_size);
+ if (rbh)
+ memcpy(rbh->b_data, CURRENT->buffer,
+ rbh->b_size);
+ else
+ BUG(); /* No buffer, what to do here? */
+ }
+ }
+ if (rbh) {
+ set_bit(BH_Protected, &rbh->b_state);
+ brelse(rbh);
+ }
end_request(1);
goto repeat;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)