1b40c2e66STino Reichardt /* 2b40c2e66STino Reichardt * Copyright (C) Tino Reichardt, 2012 3b40c2e66STino Reichardt * 4b40c2e66STino Reichardt * This program is free software; you can redistribute it and/or modify 5b40c2e66STino Reichardt * it under the terms of the GNU General Public License as published by 6b40c2e66STino Reichardt * the Free Software Foundation; either version 2 of the License, or 7b40c2e66STino Reichardt * (at your option) any later version. 8b40c2e66STino Reichardt * 9b40c2e66STino Reichardt * This program is distributed in the hope that it will be useful, 10b40c2e66STino Reichardt * but WITHOUT ANY WARRANTY; without even the implied warranty of 11b40c2e66STino Reichardt * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12b40c2e66STino Reichardt * the GNU General Public License for more details. 13b40c2e66STino Reichardt * 14b40c2e66STino Reichardt * You should have received a copy of the GNU General Public License 15b40c2e66STino Reichardt * along with this program; if not, write to the Free Software 16b40c2e66STino Reichardt * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17b40c2e66STino Reichardt */ 18b40c2e66STino Reichardt 19b40c2e66STino Reichardt #include <linux/fs.h> 20b40c2e66STino Reichardt #include <linux/slab.h> 21b40c2e66STino Reichardt #include <linux/blkdev.h> 22b40c2e66STino Reichardt 23b40c2e66STino Reichardt #include "jfs_incore.h" 24b40c2e66STino Reichardt #include "jfs_superblock.h" 25b40c2e66STino Reichardt #include "jfs_discard.h" 26b40c2e66STino Reichardt #include "jfs_dmap.h" 27b40c2e66STino Reichardt #include "jfs_debug.h" 28b40c2e66STino Reichardt 29b40c2e66STino Reichardt 30b40c2e66STino Reichardt /* 31b40c2e66STino Reichardt * NAME: jfs_issue_discard() 32b40c2e66STino Reichardt * 33b40c2e66STino Reichardt * FUNCTION: TRIM the specified block range on device, if supported 34b40c2e66STino Reichardt * 35b40c2e66STino Reichardt * PARAMETERS: 36b40c2e66STino Reichardt * ip - pointer to in-core inode 37b40c2e66STino Reichardt * blkno - starting block number to be trimmed (0..N) 38b40c2e66STino Reichardt * nblocks - number of blocks to be trimmed 39b40c2e66STino Reichardt * 40b40c2e66STino Reichardt * RETURN VALUES: 41b40c2e66STino Reichardt * none 42b40c2e66STino Reichardt * 43b40c2e66STino Reichardt * serialization: IREAD_LOCK(ipbmap) held on entry/exit; 44b40c2e66STino Reichardt */ 45b40c2e66STino Reichardt void jfs_issue_discard(struct inode *ip, u64 blkno, u64 nblocks) 46b40c2e66STino Reichardt { 47b40c2e66STino Reichardt struct super_block *sb = ip->i_sb; 48b40c2e66STino Reichardt int r = 0; 49b40c2e66STino Reichardt 50b40c2e66STino Reichardt r = sb_issue_discard(sb, blkno, nblocks, GFP_NOFS, 0); 51b40c2e66STino Reichardt if (unlikely(r != 0)) { 52b40c2e66STino Reichardt jfs_err("JFS: sb_issue_discard" \ 53b40c2e66STino Reichardt "(%p, %llu, %llu, GFP_NOFS, 0) = %d => failed!\n", 54b40c2e66STino Reichardt sb, (unsigned long long)blkno, 55b40c2e66STino Reichardt (unsigned long long)nblocks, r); 56b40c2e66STino Reichardt } 57b40c2e66STino Reichardt 58b40c2e66STino Reichardt jfs_info("JFS: sb_issue_discard" \ 59b40c2e66STino Reichardt "(%p, %llu, %llu, GFP_NOFS, 0) = %d\n", 60b40c2e66STino Reichardt sb, (unsigned long long)blkno, 61b40c2e66STino Reichardt (unsigned long long)nblocks, r); 62b40c2e66STino Reichardt 63b40c2e66STino Reichardt return; 64b40c2e66STino Reichardt } 65b40c2e66STino Reichardt 66b40c2e66STino Reichardt /* 67b40c2e66STino Reichardt * NAME: jfs_ioc_trim() 68b40c2e66STino Reichardt * 69b40c2e66STino Reichardt * FUNCTION: attempt to discard (TRIM) all free blocks from the 70b40c2e66STino Reichardt * filesystem. 71b40c2e66STino Reichardt * 72b40c2e66STino Reichardt * PARAMETERS: 73b40c2e66STino Reichardt * ip - pointer to in-core inode; 74b40c2e66STino Reichardt * range - the range, given by user space 75b40c2e66STino Reichardt * 76b40c2e66STino Reichardt * RETURN VALUES: 77b40c2e66STino Reichardt * 0 - success 78b40c2e66STino Reichardt * -EIO - i/o error 79b40c2e66STino Reichardt */ 80b40c2e66STino Reichardt int jfs_ioc_trim(struct inode *ip, struct fstrim_range *range) 81b40c2e66STino Reichardt { 82b40c2e66STino Reichardt struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap; 83b40c2e66STino Reichardt struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap; 84b40c2e66STino Reichardt struct super_block *sb = ipbmap->i_sb; 85b40c2e66STino Reichardt int agno, agno_end; 86*4e7a4b01SLukas Czerner u64 start, end, minlen; 87b40c2e66STino Reichardt u64 trimmed = 0; 88b40c2e66STino Reichardt 89b40c2e66STino Reichardt /** 90b40c2e66STino Reichardt * convert byte values to block size of filesystem: 91b40c2e66STino Reichardt * start: First Byte to trim 92b40c2e66STino Reichardt * len: number of Bytes to trim from start 93b40c2e66STino Reichardt * minlen: minimum extent length in Bytes 94b40c2e66STino Reichardt */ 95b40c2e66STino Reichardt start = range->start >> sb->s_blocksize_bits; 96b40c2e66STino Reichardt end = start + (range->len >> sb->s_blocksize_bits) - 1; 97*4e7a4b01SLukas Czerner minlen = range->minlen >> sb->s_blocksize_bits; 98*4e7a4b01SLukas Czerner if (minlen == 0) 99*4e7a4b01SLukas Czerner minlen = 1; 100*4e7a4b01SLukas Czerner 101*4e7a4b01SLukas Czerner if (minlen > bmp->db_agsize || 102*4e7a4b01SLukas Czerner start >= bmp->db_mapsize || 103*4e7a4b01SLukas Czerner range->len < sb->s_blocksize) 104*4e7a4b01SLukas Czerner return -EINVAL; 105*4e7a4b01SLukas Czerner 106b40c2e66STino Reichardt if (end >= bmp->db_mapsize) 107b40c2e66STino Reichardt end = bmp->db_mapsize - 1; 108b40c2e66STino Reichardt 109b40c2e66STino Reichardt /** 110b40c2e66STino Reichardt * we trim all ag's within the range 111b40c2e66STino Reichardt */ 112b40c2e66STino Reichardt agno = BLKTOAG(start, JFS_SBI(ip->i_sb)); 113b40c2e66STino Reichardt agno_end = BLKTOAG(end, JFS_SBI(ip->i_sb)); 114b40c2e66STino Reichardt while (agno <= agno_end) { 115b40c2e66STino Reichardt trimmed += dbDiscardAG(ip, agno, minlen); 116b40c2e66STino Reichardt agno++; 117b40c2e66STino Reichardt } 118b40c2e66STino Reichardt range->len = trimmed << sb->s_blocksize_bits; 119b40c2e66STino Reichardt 120b40c2e66STino Reichardt return 0; 121b40c2e66STino Reichardt } 122