patch-2.4.10 linux/drivers/block/loop.c
Next file: linux/drivers/block/nbd.c
Previous file: linux/drivers/block/ll_rw_blk.c
Back to the patch index
Back to the overall index
- Lines: 139
- Date:
Mon Sep 17 13:16:30 2001
- Orig file:
v2.4.9/linux/drivers/block/loop.c
- Orig date:
Tue Jul 3 17:08:19 2001
diff -u --recursive --new-file v2.4.9/linux/drivers/block/loop.c linux/drivers/block/loop.c
@@ -62,6 +62,7 @@
#include <linux/major.h>
#include <linux/wait.h>
#include <linux/blk.h>
+#include <linux/blkpg.h>
#include <linux/init.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/smp_lock.h>
@@ -86,10 +87,12 @@
static int transfer_none(struct loop_device *lo, int cmd, char *raw_buf,
char *loop_buf, int size, int real_block)
{
- if (cmd == READ)
- memcpy(loop_buf, raw_buf, size);
- else
- memcpy(raw_buf, loop_buf, size);
+ if (raw_buf != loop_buf) {
+ if (cmd == READ)
+ memcpy(loop_buf, raw_buf, size);
+ else
+ memcpy(raw_buf, loop_buf, size);
+ }
return 0;
}
@@ -117,6 +120,7 @@
static int none_status(struct loop_device *lo, struct loop_info *info)
{
+ lo->lo_flags |= LO_FLAGS_BH_REMAP;
return 0;
}
@@ -313,9 +317,13 @@
return ret;
}
+static void loop_end_io_transfer(struct buffer_head *bh, int uptodate);
static void loop_put_buffer(struct buffer_head *bh)
{
- if (bh) {
+ /*
+ * check b_end_io, may just be a remapped bh and not an allocated one
+ */
+ if (bh && bh->b_end_io == loop_end_io_transfer) {
__free_page(bh->b_page);
kmem_cache_free(bh_cachep, bh);
}
@@ -385,6 +393,14 @@
{
struct buffer_head *bh;
+ /*
+ * for xfer_funcs that can operate on the same bh, do that
+ */
+ if (lo->lo_flags & LO_FLAGS_BH_REMAP) {
+ bh = rbh;
+ goto out_bh;
+ }
+
do {
bh = kmem_cache_alloc(bh_cachep, SLAB_NOIO);
if (bh)
@@ -397,9 +413,6 @@
bh->b_size = rbh->b_size;
bh->b_dev = rbh->b_rdev;
- spin_lock_irq(&lo->lo_lock);
- bh->b_rdev = lo->lo_device;
- spin_unlock_irq(&lo->lo_lock);
bh->b_state = (1 << BH_Req) | (1 << BH_Mapped) | (1 << BH_Lock);
/*
@@ -418,9 +431,15 @@
bh->b_data = page_address(bh->b_page);
bh->b_end_io = loop_end_io_transfer;
- bh->b_rsector = rbh->b_rsector + (lo->lo_offset >> 9);
+ bh->b_private = rbh;
init_waitqueue_head(&bh->b_wait);
+out_bh:
+ bh->b_rsector = rbh->b_rsector + (lo->lo_offset >> 9);
+ spin_lock_irq(&lo->lo_lock);
+ bh->b_rdev = lo->lo_device;
+ spin_unlock_irq(&lo->lo_lock);
+
return bh;
}
@@ -475,8 +494,7 @@
* piggy old buffer on original, and submit for I/O
*/
bh = loop_get_buffer(lo, rbh);
- bh->b_private = rbh;
- IV = loop_get_iv(lo, bh->b_rsector);
+ IV = loop_get_iv(lo, rbh->b_rsector);
if (rw == WRITE) {
set_bit(BH_Dirty, &bh->b_state);
if (lo_do_transfer(lo, WRITE, bh->b_data, rbh->b_data,
@@ -600,7 +618,7 @@
error = -EBUSY;
if (lo->lo_state != Lo_unbound)
goto out;
-
+
error = -EBADF;
file = fget(arg);
if (!file)
@@ -620,7 +638,6 @@
* If we can't read - sorry. If we only can't write - well,
* it's going to be read-only.
*/
- error = -EINVAL;
if (!aops->readpage)
goto out_putf;
@@ -848,11 +865,18 @@
err = -ENXIO;
break;
}
- if (!arg) {
- err = -EINVAL;
+ err = put_user(loop_sizes[lo->lo_number] << 1, (long *) arg);
+ break;
+ case BLKGETSIZE64:
+ if (lo->lo_state != Lo_bound) {
+ err = -ENXIO;
break;
}
- err = put_user(loop_sizes[lo->lo_number] << 1, (long *) arg);
+ err = put_user((u64)loop_sizes[lo->lo_number] << 10, (u64*)arg);
+ break;
+ case BLKBSZGET:
+ case BLKBSZSET:
+ err = blk_ioctl(inode->i_rdev, cmd, arg);
break;
default:
err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)