11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2b40c2e66STino Reichardt /* 3b40c2e66STino Reichardt * Copyright (C) Tino Reichardt, 2012 4b40c2e66STino Reichardt */ 5b40c2e66STino Reichardt 6b40c2e66STino Reichardt #include <linux/fs.h> 7b40c2e66STino Reichardt #include <linux/slab.h> 8b40c2e66STino Reichardt #include <linux/blkdev.h> 9b40c2e66STino Reichardt 10b40c2e66STino Reichardt #include "jfs_incore.h" 11b40c2e66STino Reichardt #include "jfs_superblock.h" 12b40c2e66STino Reichardt #include "jfs_discard.h" 13b40c2e66STino Reichardt #include "jfs_dmap.h" 14b40c2e66STino Reichardt #include "jfs_debug.h" 15b40c2e66STino Reichardt 16b40c2e66STino Reichardt 17b40c2e66STino Reichardt /* 18b40c2e66STino Reichardt * NAME: jfs_issue_discard() 19b40c2e66STino Reichardt * 20b40c2e66STino Reichardt * FUNCTION: TRIM the specified block range on device, if supported 21b40c2e66STino Reichardt * 22b40c2e66STino Reichardt * PARAMETERS: 23b40c2e66STino Reichardt * ip - pointer to in-core inode 24b40c2e66STino Reichardt * blkno - starting block number to be trimmed (0..N) 25b40c2e66STino Reichardt * nblocks - number of blocks to be trimmed 26b40c2e66STino Reichardt * 27b40c2e66STino Reichardt * RETURN VALUES: 28b40c2e66STino Reichardt * none 29b40c2e66STino Reichardt * 30b40c2e66STino Reichardt * serialization: IREAD_LOCK(ipbmap) held on entry/exit; 31b40c2e66STino Reichardt */ 32b40c2e66STino Reichardt void jfs_issue_discard(struct inode *ip, u64 blkno, u64 nblocks) 33b40c2e66STino Reichardt { 34b40c2e66STino Reichardt struct super_block *sb = ip->i_sb; 35b40c2e66STino Reichardt int r = 0; 36b40c2e66STino Reichardt 37b40c2e66STino Reichardt r = sb_issue_discard(sb, blkno, nblocks, GFP_NOFS, 0); 38b40c2e66STino Reichardt if (unlikely(r != 0)) { 39aa575749SJoe Perches jfs_err("JFS: sb_issue_discard(%p, %llu, %llu, GFP_NOFS, 0) = %d => failed!", 40b40c2e66STino Reichardt sb, (unsigned long long)blkno, 41b40c2e66STino Reichardt (unsigned long long)nblocks, r); 42b40c2e66STino Reichardt } 43b40c2e66STino Reichardt 44aa575749SJoe Perches jfs_info("JFS: sb_issue_discard(%p, %llu, %llu, GFP_NOFS, 0) = %d", 45b40c2e66STino Reichardt sb, (unsigned long long)blkno, 46b40c2e66STino Reichardt (unsigned long long)nblocks, r); 47b40c2e66STino Reichardt 48b40c2e66STino Reichardt return; 49b40c2e66STino Reichardt } 50b40c2e66STino Reichardt 51b40c2e66STino Reichardt /* 52b40c2e66STino Reichardt * NAME: jfs_ioc_trim() 53b40c2e66STino Reichardt * 54b40c2e66STino Reichardt * FUNCTION: attempt to discard (TRIM) all free blocks from the 55b40c2e66STino Reichardt * filesystem. 56b40c2e66STino Reichardt * 57b40c2e66STino Reichardt * PARAMETERS: 58b40c2e66STino Reichardt * ip - pointer to in-core inode; 59b40c2e66STino Reichardt * range - the range, given by user space 60b40c2e66STino Reichardt * 61b40c2e66STino Reichardt * RETURN VALUES: 62b40c2e66STino Reichardt * 0 - success 63b40c2e66STino Reichardt * -EIO - i/o error 64b40c2e66STino Reichardt */ 65b40c2e66STino Reichardt int jfs_ioc_trim(struct inode *ip, struct fstrim_range *range) 66b40c2e66STino Reichardt { 67b40c2e66STino Reichardt struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap; 68*d6c1b359SEdward Adam Davis struct bmap *bmp; 69b40c2e66STino Reichardt struct super_block *sb = ipbmap->i_sb; 70b40c2e66STino Reichardt int agno, agno_end; 714e7a4b01SLukas Czerner u64 start, end, minlen; 72b40c2e66STino Reichardt u64 trimmed = 0; 73b40c2e66STino Reichardt 74b40c2e66STino Reichardt /** 75b40c2e66STino Reichardt * convert byte values to block size of filesystem: 76b40c2e66STino Reichardt * start: First Byte to trim 77b40c2e66STino Reichardt * len: number of Bytes to trim from start 78b40c2e66STino Reichardt * minlen: minimum extent length in Bytes 79b40c2e66STino Reichardt */ 80b40c2e66STino Reichardt start = range->start >> sb->s_blocksize_bits; 81b40c2e66STino Reichardt end = start + (range->len >> sb->s_blocksize_bits) - 1; 824e7a4b01SLukas Czerner minlen = range->minlen >> sb->s_blocksize_bits; 834e7a4b01SLukas Czerner if (minlen == 0) 844e7a4b01SLukas Czerner minlen = 1; 854e7a4b01SLukas Czerner 86*d6c1b359SEdward Adam Davis down_read(&sb->s_umount); 87*d6c1b359SEdward Adam Davis bmp = JFS_SBI(ip->i_sb)->bmap; 88*d6c1b359SEdward Adam Davis 894e7a4b01SLukas Czerner if (minlen > bmp->db_agsize || 904e7a4b01SLukas Czerner start >= bmp->db_mapsize || 91*d6c1b359SEdward Adam Davis range->len < sb->s_blocksize) { 92*d6c1b359SEdward Adam Davis up_read(&sb->s_umount); 934e7a4b01SLukas Czerner return -EINVAL; 94*d6c1b359SEdward Adam Davis } 954e7a4b01SLukas Czerner 96b40c2e66STino Reichardt if (end >= bmp->db_mapsize) 97b40c2e66STino Reichardt end = bmp->db_mapsize - 1; 98b40c2e66STino Reichardt 99b40c2e66STino Reichardt /** 100b40c2e66STino Reichardt * we trim all ag's within the range 101b40c2e66STino Reichardt */ 102b40c2e66STino Reichardt agno = BLKTOAG(start, JFS_SBI(ip->i_sb)); 103b40c2e66STino Reichardt agno_end = BLKTOAG(end, JFS_SBI(ip->i_sb)); 104b40c2e66STino Reichardt while (agno <= agno_end) { 105b40c2e66STino Reichardt trimmed += dbDiscardAG(ip, agno, minlen); 106b40c2e66STino Reichardt agno++; 107b40c2e66STino Reichardt } 108*d6c1b359SEdward Adam Davis 109*d6c1b359SEdward Adam Davis up_read(&sb->s_umount); 110b40c2e66STino Reichardt range->len = trimmed << sb->s_blocksize_bits; 111b40c2e66STino Reichardt 112b40c2e66STino Reichardt return 0; 113b40c2e66STino Reichardt } 114