On Mon, Jun 05, 2000 at 11:29:34PM -0500, David Marshall wrote:
> The bug I'm not understanding is related to a -ETXTBSY which is
> returned from loop_clr_fd(). When I use losetup (yes, it's the
> included version) to attach a loop device to another file, then when I
> try to detach the loop device the kernel still thinks that the file is
> busy and will return -ETXTBSY the *next* time that get_write_access()
> is called.
>
> Example:
>
> # losetup -e none /dev/loop0 foobar
> # losetup -d /dev/loop0
> # losetup -e none /dev/loop0 foobar
> foobar: Text file busy
Yes. The problem is that losetup does get_write_access(),
and losetup -d does put_write_access(), but then the fput()
done afterwards again does put_write_access() (if FMODE_WRITE is set).
So, loop.c must only do the put_write_access() in case FMODE_WRITE
is not set. Below a patch (only one change, the rest is shortening
some lines that do not fit an 80-col screen).
Andries
--- ../linux-2.3.99p9/linux/drivers/block/loop.c Wed May 24 15:18:10 2000
+++ linux/drivers/block/loop.c Thu Jun 8 03:19:59 2000
@@ -238,7 +238,8 @@
kaddr = (char*)kmap(page);
if ((lo->transfer)(lo,READ,kaddr+offset,p->data,size,IV)) {
size = 0;
- printk(KERN_ERR "loop: transfer error block %ld\n",page->index);
+ printk(KERN_ERR "loop: transfer error block %ld\n",
+ page->index);
desc->error = -EINVAL;
}
kunmap(page);
@@ -345,9 +346,11 @@
}
}
- if ((lo->transfer)(lo, current_request->cmd, bh->b_data + offset,
- dest_addr, size, block)) {
- printk(KERN_ERR "loop: transfer error block %d\n", block);
+ if ((lo->transfer)(lo, current_request->cmd,
+ bh->b_data + offset,
+ dest_addr, size, block)) {
+ printk(KERN_ERR "loop: transfer error block %d\n",
+ block);
brelse(bh);
goto error_out_lock;
}
@@ -539,8 +542,10 @@
lo->lo_dentry = NULL;
if (lo->lo_backing_file != NULL) {
- put_write_access(lo->lo_backing_file->f_dentry->d_inode);
- fput(lo->lo_backing_file);
+ struct file *filp = lo->lo_backing_file;
+ if ((filp->f_mode & FMODE_WRITE) == 0)
+ put_write_access(filp->f_dentry->d_inode);
+ fput(filp);
lo->lo_backing_file = NULL;
} else {
dput(dentry);
@@ -636,7 +641,8 @@
if (!inode)
return -EINVAL;
if (MAJOR(inode->i_rdev) != MAJOR_NR) {
- printk(KERN_WARNING "lo_ioctl: pseudo-major != %d\n", MAJOR_NR);
+ printk(KERN_WARNING "lo_ioctl: pseudo-major != %d\n",
+ MAJOR_NR);
return -ENODEV;
}
dev = MINOR(inode->i_rdev);
@@ -698,7 +704,8 @@
if (!inode)
return 0;
if (MAJOR(inode->i_rdev) != MAJOR_NR) {
- printk(KERN_WARNING "lo_release: pseudo-major != %d\n", MAJOR_NR);
+ printk(KERN_WARNING "lo_release: pseudo-major != %d\n",
+ MAJOR_NR);
return 0;
}
dev = MINOR(inode->i_rdev);
@@ -706,7 +713,8 @@
return 0;
lo = &loop_dev[dev];
if (lo->lo_refcnt <= 0)
- printk(KERN_ERR "lo_release: refcount(%d) <= 0\n", lo->lo_refcnt);
+ printk(KERN_ERR "lo_release: refcount(%d) <= 0\n",
+ lo->lo_refcnt);
else {
int type = lo->lo_encrypt_type;
--lo->lo_refcnt;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Thu Jun 15 2000 - 21:00:15 EST