On 2/14/21 20:28, Hyeongseok Kim wrote:So, you mean that it would be better to be somethink like this, right?
+Reverse tree style for function variable declaration would be nice which you
+int exfat_trim_fs(struct inode *inode, struct fstrim_range *range)
+{
+ struct super_block *sb = inode->i_sb;
partially have it here.
I think case 3. could be possible, but I agree we don't need to handle -EOPNOTSUPP in other way,+ else {You are specifying the last argument as 0 to sb_issue_disacrd() i.e.
+ /* trim current range if it's larger than trim_minlen */
+ count = trim_end - trim_begin + 1;
+ if (count >= trim_minlen) {
+ err = sb_issue_discard(sb,
+ exfat_cluster_to_sector(sbi, trim_begin),
+ count * sbi->sect_per_clus, GFP_NOFS, 0);
flags == 0 this will propagate to :-
sb_issue_discard()
blkdev_issue_discard()
__blkdev__issue_discard()
Now blkdev_issue_disacrd() returns -ENOTSUPP in 3 cases :-
1. If flags arg is set to BLKDEV_DISCARD_SECURE and queue doesn't support
secure erase. In this case you have not set BLKDEV_DISCARD_SECURE that.
So it should not return -EOPNOTSUPP.
2. If queue doesn't support discard. In this case caller of this function
already set that. So it should not return -EOPNOTSUPP.
3. If q->limits.discard_granularity is not but LLD which I think caller of
this function already used that to calculate the range->minlen.
If above is true then err will not have value of -EOPNOTSUPP ?
I considered the case if there are no more used blocks or no more free blocks (no fragmentation)+ if (need_resched()) {sb_issue_discard() ->blkdev_issue_discard() will call cond_resced().
+ mutex_unlock(&EXFAT_SB(inode->i_sb)->s_lock);
1. The check for need_resched() will ever be true since
blkdev_issue_discard()
is already calling cond_sched() ?
2. If so do you still need to drop the mutex before calling
sb_issue_discard() ?
..+ cond_resched();
+ mutex_lock(&EXFAT_SB(inode->i_sb)->s_lock);
+ }
+
OK, I'll move it into the exfat_trim_fs().+Is {} really needed for switch case ?
switch (cmd) {
+ case FITRIM:
+ {
+ struct request_queue *q = bdev_get_queue(sb->s_bdev);
+ struct fstrim_range range;
+ int ret = 0;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (!blk_queue_discard(q))
+ return -EOPNOTSUPP;
+
+ if (copy_from_user(&range, (struct fstrim_range __user *)arg,
+ sizeof(range)))
+ return -EFAULT;
+
+ range.minlen = max_t(unsigned int, range.minlen,
+ q->limits.discard_granularity);
+
+ ret = exfat_trim_fs(inode, &range);
+ if (ret < 0)
+ return ret;
+
+ if (copy_to_user((struct fstrim_range __user *)arg, &range,
+ sizeof(range)))
+ return -EFAULT;
+
+ return 0;
+ }
+
Also, code related to FITRIM needs to be moved to a helper otherwise it
will bloat
the ioctl function, unless that is the objective here.
default:
return -ENOTTY;
}