Skip to content

Commit

Permalink
ext3: Add FITRIM handling
Browse files Browse the repository at this point in the history
The ioctl takes fstrim_range structure (defined in include/linux/fs.h) as an
argument specifying a range of filesystem to trim and the minimum size of an
continguous extent to trim. After the FITRIM is done, the number of bytes
passed from the filesystem down the block stack to the device for potential
discard is stored in fstrim_range.len.  This number is a maximum discard amount
from the storage device's perspective, because FITRIM called repeatedly will
keep sending the same sectors for discard.  fstrim_range.len will report the
same potential discard bytes each time, but only sectors which had been written
to between the discards would actually be discarded by the storage device.
Further, the kernel block layer reserves the right to adjust the discard ranges
to fit raid stripe geometry, non-trim capable devices in a LVM setup, etc.
These reductions would not be reflected in fstrim_range.len.

Thus fstrim_range.len can give the user better insight on how much storage
space has potentially been released for wear-leveling, but it needs to be one
of only one criteria the userspace tools take into account when trying to
optimize calls to FITRIM.

Thanks to Greg Freemyer <greg.freemyer@gmail.com> for better commit message.

Signed-off-by: Lukas Czerner <lczerner@redhat.com>
Signed-off-by: Jan Kara <jack@suse.cz>
  • Loading branch information
Lukas Czerner authored and Jan Kara committed Jan 10, 2011
1 parent b853b96 commit 9c52749
Showing 1 changed file with 22 additions and 0 deletions.
22 changes: 22 additions & 0 deletions fs/ext3/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,29 @@ long ext3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
mnt_drop_write(filp->f_path.mnt);
return err;
}
case FITRIM: {

struct super_block *sb = inode->i_sb;
struct fstrim_range range;
int ret = 0;

if (!capable(CAP_SYS_ADMIN))
return -EPERM;

if (copy_from_user(&range, (struct fstrim_range *)arg,
sizeof(range)))
return -EFAULT;

ret = ext3_trim_fs(sb, &range);
if (ret < 0)
return ret;

if (copy_to_user((struct fstrim_range *)arg, &range,
sizeof(range)))
return -EFAULT;

return 0;
}

default:
return -ENOTTY;
Expand Down

0 comments on commit 9c52749

Please sign in to comment.