struct address_space_operations *aops = mapping->a_ops;
pgoff_t index;
unsigned offset, bv_offs;
- int len, ret = 0;
+ int len, ret;
- down(&mapping->host->i_sem);
+ mutex_lock(&mapping->host->i_mutex);
index = pos >> PAGE_CACHE_SHIFT;
offset = pos & ((pgoff_t)PAGE_CACHE_SIZE - 1);
bv_offs = bvec->bv_offset;
page = grab_cache_page(mapping, index);
if (unlikely(!page))
goto fail;
- if (unlikely(aops->prepare_write(file, page, offset,
- offset + size)))
+ ret = aops->prepare_write(file, page, offset,
+ offset + size);
+ if (unlikely(ret)) {
+ if (ret == AOP_TRUNCATED_PAGE) {
+ page_cache_release(page);
+ continue;
+ }
goto unlock;
+ }
transfer_result = lo_do_transfer(lo, WRITE, page, offset,
bvec->bv_page, bv_offs, size, IV);
if (unlikely(transfer_result)) {
kunmap_atomic(kaddr, KM_USER0);
}
flush_dcache_page(page);
- if (unlikely(aops->commit_write(file, page, offset,
- offset + size)))
+ ret = aops->commit_write(file, page, offset,
+ offset + size);
+ if (unlikely(ret)) {
+ if (ret == AOP_TRUNCATED_PAGE) {
+ page_cache_release(page);
+ continue;
+ }
goto unlock;
+ }
if (unlikely(transfer_result))
goto unlock;
bv_offs += size;
unlock_page(page);
page_cache_release(page);
}
+ ret = 0;
out:
- up(&mapping->host->i_sem);
+ mutex_unlock(&mapping->host->i_mutex);
return ret;
unlock:
unlock_page(page);
* This helper just factors out common code between do_lo_send_direct_write()
* and do_lo_send_write().
*/
-static inline int __do_lo_send_write(struct file *file,
+static int __do_lo_send_write(struct file *file,
u8 __user *buf, const int len, loff_t pos)
{
ssize_t bw;
lo->lo_pending++;
loop_add_bio(lo, old_bio);
spin_unlock_irq(&lo->lo_lock);
- up(&lo->lo_bh_mutex);
+ complete(&lo->lo_bh_done);
return 0;
out:
if (lo->lo_pending == 0)
- up(&lo->lo_bh_mutex);
+ complete(&lo->lo_bh_done);
spin_unlock_irq(&lo->lo_lock);
bio_io_error(old_bio, old_bio->bi_size);
return 0;
lo->lo_pending = 1;
/*
- * up sem, we are running
+ * complete it, we are running
*/
- up(&lo->lo_sem);
+ complete(&lo->lo_done);
for (;;) {
int pending;
- /*
- * interruptible just to not contribute to load avg
- */
- if (down_interruptible(&lo->lo_bh_mutex))
+ if (wait_for_completion_interruptible(&lo->lo_bh_done))
continue;
spin_lock_irq(&lo->lo_lock);
/*
- * could be upped because of tear-down, not pending work
+ * could be completed because of tear-down, not pending work
*/
if (unlikely(!lo->lo_pending)) {
spin_unlock_irq(&lo->lo_lock);
break;
}
- up(&lo->lo_sem);
+ complete(&lo->lo_done);
return 0;
}
set_blocksize(bdev, lo_blocksize);
- kernel_thread(loop_thread, lo, CLONE_KERNEL);
- down(&lo->lo_sem);
+ error = kernel_thread(loop_thread, lo, CLONE_KERNEL);
+ if (error < 0)
+ goto out_putf;
+ wait_for_completion(&lo->lo_done);
return 0;
out_putf:
lo->lo_state = Lo_rundown;
lo->lo_pending--;
if (!lo->lo_pending)
- up(&lo->lo_bh_mutex);
+ complete(&lo->lo_bh_done);
spin_unlock_irq(&lo->lo_lock);
- down(&lo->lo_sem);
+ wait_for_completion(&lo->lo_done);
lo->lo_backing_file = NULL;
struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
int err;
- down(&lo->lo_ctl_mutex);
+ mutex_lock(&lo->lo_ctl_mutex);
switch (cmd) {
case LOOP_SET_FD:
err = loop_set_fd(lo, file, inode->i_bdev, arg);
default:
err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL;
}
- up(&lo->lo_ctl_mutex);
+ mutex_unlock(&lo->lo_ctl_mutex);
return err;
}
{
struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
- down(&lo->lo_ctl_mutex);
+ mutex_lock(&lo->lo_ctl_mutex);
lo->lo_refcnt++;
- up(&lo->lo_ctl_mutex);
+ mutex_unlock(&lo->lo_ctl_mutex);
return 0;
}
{
struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
- down(&lo->lo_ctl_mutex);
+ mutex_lock(&lo->lo_ctl_mutex);
--lo->lo_refcnt;
- up(&lo->lo_ctl_mutex);
+ mutex_unlock(&lo->lo_ctl_mutex);
return 0;
}
xfer_funcs[n] = NULL;
for (lo = &loop_dev[0]; lo < &loop_dev[max_loop]; lo++) {
- down(&lo->lo_ctl_mutex);
+ mutex_lock(&lo->lo_ctl_mutex);
if (lo->lo_encryption == xfer)
loop_release_xfer(lo);
- up(&lo->lo_ctl_mutex);
+ mutex_unlock(&lo->lo_ctl_mutex);
}
return 0;
lo->lo_queue = blk_alloc_queue(GFP_KERNEL);
if (!lo->lo_queue)
goto out_mem4;
- init_MUTEX(&lo->lo_ctl_mutex);
- init_MUTEX_LOCKED(&lo->lo_sem);
- init_MUTEX_LOCKED(&lo->lo_bh_mutex);
+ mutex_init(&lo->lo_ctl_mutex);
+ init_completion(&lo->lo_done);
+ init_completion(&lo->lo_bh_done);
lo->lo_number = i;
spin_lock_init(&lo->lo_lock);
disk->major = LOOP_MAJOR;
out_mem4:
while (i--)
- blk_put_queue(loop_dev[i].lo_queue);
+ blk_cleanup_queue(loop_dev[i].lo_queue);
devfs_remove("loop");
i = max_loop;
out_mem3:
for (i = 0; i < max_loop; i++) {
del_gendisk(disks[i]);
- blk_put_queue(loop_dev[i].lo_queue);
+ blk_cleanup_queue(loop_dev[i].lo_queue);
put_disk(disks[i]);
}
devfs_remove("loop");