0001
0002
0003
0004
0005
0006 #include <linux/fs.h>
0007 #include <linux/slab.h>
0008 #include <linux/blkdev.h>
0009
0010 #include "jfs_incore.h"
0011 #include "jfs_superblock.h"
0012 #include "jfs_discard.h"
0013 #include "jfs_dmap.h"
0014 #include "jfs_debug.h"
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 void jfs_issue_discard(struct inode *ip, u64 blkno, u64 nblocks)
0033 {
0034 struct super_block *sb = ip->i_sb;
0035 int r = 0;
0036
0037 r = sb_issue_discard(sb, blkno, nblocks, GFP_NOFS, 0);
0038 if (unlikely(r != 0)) {
0039 jfs_err("JFS: sb_issue_discard(%p, %llu, %llu, GFP_NOFS, 0) = %d => failed!",
0040 sb, (unsigned long long)blkno,
0041 (unsigned long long)nblocks, r);
0042 }
0043
0044 jfs_info("JFS: sb_issue_discard(%p, %llu, %llu, GFP_NOFS, 0) = %d",
0045 sb, (unsigned long long)blkno,
0046 (unsigned long long)nblocks, r);
0047
0048 return;
0049 }
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 int jfs_ioc_trim(struct inode *ip, struct fstrim_range *range)
0066 {
0067 struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap;
0068 struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap;
0069 struct super_block *sb = ipbmap->i_sb;
0070 int agno, agno_end;
0071 u64 start, end, minlen;
0072 u64 trimmed = 0;
0073
0074
0075
0076
0077
0078
0079
0080 start = range->start >> sb->s_blocksize_bits;
0081 end = start + (range->len >> sb->s_blocksize_bits) - 1;
0082 minlen = range->minlen >> sb->s_blocksize_bits;
0083 if (minlen == 0)
0084 minlen = 1;
0085
0086 if (minlen > bmp->db_agsize ||
0087 start >= bmp->db_mapsize ||
0088 range->len < sb->s_blocksize)
0089 return -EINVAL;
0090
0091 if (end >= bmp->db_mapsize)
0092 end = bmp->db_mapsize - 1;
0093
0094
0095
0096
0097 agno = BLKTOAG(start, JFS_SBI(ip->i_sb));
0098 agno_end = BLKTOAG(end, JFS_SBI(ip->i_sb));
0099 while (agno <= agno_end) {
0100 trimmed += dbDiscardAG(ip, agno, minlen);
0101 agno++;
0102 }
0103 range->len = trimmed << sb->s_blocksize_bits;
0104
0105 return 0;
0106 }