Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 110454
b: refs/heads/master
c: d30a260
h: refs/heads/master
v: v3
  • Loading branch information
David Woodhouse authored and Jens Axboe committed Oct 9, 2008
1 parent 3968429 commit 59ec6ef
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2ebca85abcfcbaaf1c0b242e39fc88ad3da90090
refs/heads/master: d30a2605be9d5132d95944916e8f578fcfe4f976
1 change: 1 addition & 0 deletions trunk/block/compat_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,7 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
return compat_hdio_getgeo(disk, bdev, compat_ptr(arg));
case BLKFLSBUF:
case BLKROSET:
case BLKDISCARD:
/*
* the ones below are implemented in blkdev_locked_ioctl,
* but we call blkdev_ioctl, which gets the lock for us
Expand Down
76 changes: 76 additions & 0 deletions trunk/block/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,69 @@ static int blkdev_reread_part(struct block_device *bdev)
return res;
}

static void blk_ioc_discard_endio(struct bio *bio, int err)
{
if (err) {
if (err == -EOPNOTSUPP)
set_bit(BIO_EOPNOTSUPP, &bio->bi_flags);
clear_bit(BIO_UPTODATE, &bio->bi_flags);
}
complete(bio->bi_private);
}

static int blk_ioctl_discard(struct block_device *bdev, uint64_t start,
uint64_t len)
{
struct request_queue *q = bdev_get_queue(bdev);
int ret = 0;

if (start & 511)
return -EINVAL;
if (len & 511)
return -EINVAL;
start >>= 9;
len >>= 9;

if (start + len > (bdev->bd_inode->i_size >> 9))
return -EINVAL;

if (!q->prepare_discard_fn)
return -EOPNOTSUPP;

while (len && !ret) {
DECLARE_COMPLETION_ONSTACK(wait);
struct bio *bio;

bio = bio_alloc(GFP_KERNEL, 0);
if (!bio)
return -ENOMEM;

bio->bi_end_io = blk_ioc_discard_endio;
bio->bi_bdev = bdev;
bio->bi_private = &wait;
bio->bi_sector = start;

if (len > q->max_hw_sectors) {
bio->bi_size = q->max_hw_sectors << 9;
len -= q->max_hw_sectors;
start += q->max_hw_sectors;
} else {
bio->bi_size = len << 9;
len = 0;
}
submit_bio(WRITE_DISCARD, bio);

wait_for_completion(&wait);

if (bio_flagged(bio, BIO_EOPNOTSUPP))
ret = -EOPNOTSUPP;
else if (!bio_flagged(bio, BIO_UPTODATE))
ret = -EIO;
bio_put(bio);
}
return ret;
}

static int put_ushort(unsigned long arg, unsigned short val)
{
return put_user(val, (unsigned short __user *)arg);
Expand Down Expand Up @@ -258,6 +321,19 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
set_device_ro(bdev, n);
unlock_kernel();
return 0;

case BLKDISCARD: {
uint64_t range[2];

if (!(file->f_mode & FMODE_WRITE))
return -EBADF;

if (copy_from_user(range, (void __user *)arg, sizeof(range)))
return -EFAULT;

return blk_ioctl_discard(bdev, range[0], range[1]);
}

case HDIO_GETGEO: {
struct hd_geometry geo;

Expand Down
1 change: 1 addition & 0 deletions trunk/include/linux/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ extern int dir_notify_enable;
#define BLKTRACESTART _IO(0x12,116)
#define BLKTRACESTOP _IO(0x12,117)
#define BLKTRACETEARDOWN _IO(0x12,118)
#define BLKDISCARD _IO(0x12,119)

#define BMAP_IOCTL 1 /* obsolete - kept for compatibility */
#define FIBMAP _IO(0x00,1) /* bmap access */
Expand Down

0 comments on commit 59ec6ef

Please sign in to comment.