[PATCH] Re: Help with a loop device bug

From: Andries Brouwer (aeb@veritas.com)
Date: Wed Jun 07 2000 - 20:45:06 EST


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