18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * linux/fs/jfs/ioctl.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2006 Herbert Poetzl 68c2ecf20Sopenharmony_ci * adapted from Remy Card's ext2/ioctl.c 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/fs.h> 108c2ecf20Sopenharmony_ci#include <linux/ctype.h> 118c2ecf20Sopenharmony_ci#include <linux/capability.h> 128c2ecf20Sopenharmony_ci#include <linux/mount.h> 138c2ecf20Sopenharmony_ci#include <linux/time.h> 148c2ecf20Sopenharmony_ci#include <linux/sched.h> 158c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 168c2ecf20Sopenharmony_ci#include <asm/current.h> 178c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include "jfs_filsys.h" 208c2ecf20Sopenharmony_ci#include "jfs_debug.h" 218c2ecf20Sopenharmony_ci#include "jfs_incore.h" 228c2ecf20Sopenharmony_ci#include "jfs_dinode.h" 238c2ecf20Sopenharmony_ci#include "jfs_inode.h" 248c2ecf20Sopenharmony_ci#include "jfs_dmap.h" 258c2ecf20Sopenharmony_ci#include "jfs_discard.h" 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic struct { 288c2ecf20Sopenharmony_ci long jfs_flag; 298c2ecf20Sopenharmony_ci long ext2_flag; 308c2ecf20Sopenharmony_ci} jfs_map[] = { 318c2ecf20Sopenharmony_ci {JFS_NOATIME_FL, FS_NOATIME_FL}, 328c2ecf20Sopenharmony_ci {JFS_DIRSYNC_FL, FS_DIRSYNC_FL}, 338c2ecf20Sopenharmony_ci {JFS_SYNC_FL, FS_SYNC_FL}, 348c2ecf20Sopenharmony_ci {JFS_SECRM_FL, FS_SECRM_FL}, 358c2ecf20Sopenharmony_ci {JFS_UNRM_FL, FS_UNRM_FL}, 368c2ecf20Sopenharmony_ci {JFS_APPEND_FL, FS_APPEND_FL}, 378c2ecf20Sopenharmony_ci {JFS_IMMUTABLE_FL, FS_IMMUTABLE_FL}, 388c2ecf20Sopenharmony_ci {0, 0}, 398c2ecf20Sopenharmony_ci}; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_cistatic long jfs_map_ext2(unsigned long flags, int from) 428c2ecf20Sopenharmony_ci{ 438c2ecf20Sopenharmony_ci int index=0; 448c2ecf20Sopenharmony_ci long mapped=0; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci while (jfs_map[index].jfs_flag) { 478c2ecf20Sopenharmony_ci if (from) { 488c2ecf20Sopenharmony_ci if (jfs_map[index].ext2_flag & flags) 498c2ecf20Sopenharmony_ci mapped |= jfs_map[index].jfs_flag; 508c2ecf20Sopenharmony_ci } else { 518c2ecf20Sopenharmony_ci if (jfs_map[index].jfs_flag & flags) 528c2ecf20Sopenharmony_ci mapped |= jfs_map[index].ext2_flag; 538c2ecf20Sopenharmony_ci } 548c2ecf20Sopenharmony_ci index++; 558c2ecf20Sopenharmony_ci } 568c2ecf20Sopenharmony_ci return mapped; 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cilong jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 618c2ecf20Sopenharmony_ci{ 628c2ecf20Sopenharmony_ci struct inode *inode = file_inode(filp); 638c2ecf20Sopenharmony_ci struct jfs_inode_info *jfs_inode = JFS_IP(inode); 648c2ecf20Sopenharmony_ci unsigned int flags; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci switch (cmd) { 678c2ecf20Sopenharmony_ci case JFS_IOC_GETFLAGS: 688c2ecf20Sopenharmony_ci flags = jfs_inode->mode2 & JFS_FL_USER_VISIBLE; 698c2ecf20Sopenharmony_ci flags = jfs_map_ext2(flags, 0); 708c2ecf20Sopenharmony_ci return put_user(flags, (int __user *) arg); 718c2ecf20Sopenharmony_ci case JFS_IOC_SETFLAGS: { 728c2ecf20Sopenharmony_ci unsigned int oldflags; 738c2ecf20Sopenharmony_ci int err; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci err = mnt_want_write_file(filp); 768c2ecf20Sopenharmony_ci if (err) 778c2ecf20Sopenharmony_ci return err; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci if (!inode_owner_or_capable(inode)) { 808c2ecf20Sopenharmony_ci err = -EACCES; 818c2ecf20Sopenharmony_ci goto setflags_out; 828c2ecf20Sopenharmony_ci } 838c2ecf20Sopenharmony_ci if (get_user(flags, (int __user *) arg)) { 848c2ecf20Sopenharmony_ci err = -EFAULT; 858c2ecf20Sopenharmony_ci goto setflags_out; 868c2ecf20Sopenharmony_ci } 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci flags = jfs_map_ext2(flags, 1); 898c2ecf20Sopenharmony_ci if (!S_ISDIR(inode->i_mode)) 908c2ecf20Sopenharmony_ci flags &= ~JFS_DIRSYNC_FL; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci /* Is it quota file? Do not allow user to mess with it */ 938c2ecf20Sopenharmony_ci if (IS_NOQUOTA(inode)) { 948c2ecf20Sopenharmony_ci err = -EPERM; 958c2ecf20Sopenharmony_ci goto setflags_out; 968c2ecf20Sopenharmony_ci } 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci /* Lock against other parallel changes of flags */ 998c2ecf20Sopenharmony_ci inode_lock(inode); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci oldflags = jfs_map_ext2(jfs_inode->mode2 & JFS_FL_USER_VISIBLE, 1028c2ecf20Sopenharmony_ci 0); 1038c2ecf20Sopenharmony_ci err = vfs_ioc_setflags_prepare(inode, oldflags, flags); 1048c2ecf20Sopenharmony_ci if (err) { 1058c2ecf20Sopenharmony_ci inode_unlock(inode); 1068c2ecf20Sopenharmony_ci goto setflags_out; 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci flags = flags & JFS_FL_USER_MODIFIABLE; 1108c2ecf20Sopenharmony_ci flags |= jfs_inode->mode2 & ~JFS_FL_USER_MODIFIABLE; 1118c2ecf20Sopenharmony_ci jfs_inode->mode2 = flags; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci jfs_set_inode_flags(inode); 1148c2ecf20Sopenharmony_ci inode_unlock(inode); 1158c2ecf20Sopenharmony_ci inode->i_ctime = current_time(inode); 1168c2ecf20Sopenharmony_ci mark_inode_dirty(inode); 1178c2ecf20Sopenharmony_cisetflags_out: 1188c2ecf20Sopenharmony_ci mnt_drop_write_file(filp); 1198c2ecf20Sopenharmony_ci return err; 1208c2ecf20Sopenharmony_ci } 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci case FITRIM: 1238c2ecf20Sopenharmony_ci { 1248c2ecf20Sopenharmony_ci struct super_block *sb = inode->i_sb; 1258c2ecf20Sopenharmony_ci struct request_queue *q = bdev_get_queue(sb->s_bdev); 1268c2ecf20Sopenharmony_ci struct fstrim_range range; 1278c2ecf20Sopenharmony_ci s64 ret = 0; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci if (!capable(CAP_SYS_ADMIN)) 1308c2ecf20Sopenharmony_ci return -EPERM; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci if (!blk_queue_discard(q)) { 1338c2ecf20Sopenharmony_ci jfs_warn("FITRIM not supported on device"); 1348c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 1358c2ecf20Sopenharmony_ci } 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci if (copy_from_user(&range, (struct fstrim_range __user *)arg, 1388c2ecf20Sopenharmony_ci sizeof(range))) 1398c2ecf20Sopenharmony_ci return -EFAULT; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci range.minlen = max_t(unsigned int, range.minlen, 1428c2ecf20Sopenharmony_ci q->limits.discard_granularity); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci ret = jfs_ioc_trim(inode, &range); 1458c2ecf20Sopenharmony_ci if (ret < 0) 1468c2ecf20Sopenharmony_ci return ret; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci if (copy_to_user((struct fstrim_range __user *)arg, &range, 1498c2ecf20Sopenharmony_ci sizeof(range))) 1508c2ecf20Sopenharmony_ci return -EFAULT; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci return 0; 1538c2ecf20Sopenharmony_ci } 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci default: 1568c2ecf20Sopenharmony_ci return -ENOTTY; 1578c2ecf20Sopenharmony_ci } 1588c2ecf20Sopenharmony_ci} 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT 1618c2ecf20Sopenharmony_cilong jfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci /* While these ioctl numbers defined with 'long' and have different 1648c2ecf20Sopenharmony_ci * numbers than the 64bit ABI, 1658c2ecf20Sopenharmony_ci * the actual implementation only deals with ints and is compatible. 1668c2ecf20Sopenharmony_ci */ 1678c2ecf20Sopenharmony_ci switch (cmd) { 1688c2ecf20Sopenharmony_ci case JFS_IOC_GETFLAGS32: 1698c2ecf20Sopenharmony_ci cmd = JFS_IOC_GETFLAGS; 1708c2ecf20Sopenharmony_ci break; 1718c2ecf20Sopenharmony_ci case JFS_IOC_SETFLAGS32: 1728c2ecf20Sopenharmony_ci cmd = JFS_IOC_SETFLAGS; 1738c2ecf20Sopenharmony_ci break; 1748c2ecf20Sopenharmony_ci } 1758c2ecf20Sopenharmony_ci return jfs_ioctl(filp, cmd, arg); 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci#endif 178