1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2d9e90266SHerbert Poetzl /*
3d9e90266SHerbert Poetzl * linux/fs/jfs/ioctl.c
4d9e90266SHerbert Poetzl *
5d9e90266SHerbert Poetzl * Copyright (C) 2006 Herbert Poetzl
6d9e90266SHerbert Poetzl * adapted from Remy Card's ext2/ioctl.c
7d9e90266SHerbert Poetzl */
8d9e90266SHerbert Poetzl
9d9e90266SHerbert Poetzl #include <linux/fs.h>
10d9e90266SHerbert Poetzl #include <linux/ctype.h>
11d9e90266SHerbert Poetzl #include <linux/capability.h>
1242a74f20SDave Hansen #include <linux/mount.h>
13d9e90266SHerbert Poetzl #include <linux/time.h>
14914e2637SAl Viro #include <linux/sched.h>
15b40c2e66STino Reichardt #include <linux/blkdev.h>
16d9e90266SHerbert Poetzl #include <asm/current.h>
177c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
182ca58e30SMiklos Szeredi #include <linux/fileattr.h>
19d9e90266SHerbert Poetzl
20b40c2e66STino Reichardt #include "jfs_filsys.h"
21b40c2e66STino Reichardt #include "jfs_debug.h"
22d9e90266SHerbert Poetzl #include "jfs_incore.h"
23d9e90266SHerbert Poetzl #include "jfs_dinode.h"
24d9e90266SHerbert Poetzl #include "jfs_inode.h"
25b40c2e66STino Reichardt #include "jfs_dmap.h"
26b40c2e66STino Reichardt #include "jfs_discard.h"
27d9e90266SHerbert Poetzl
28d9e90266SHerbert Poetzl static struct {
29d9e90266SHerbert Poetzl long jfs_flag;
30d9e90266SHerbert Poetzl long ext2_flag;
31d9e90266SHerbert Poetzl } jfs_map[] = {
3236695673SDavid Howells {JFS_NOATIME_FL, FS_NOATIME_FL},
3336695673SDavid Howells {JFS_DIRSYNC_FL, FS_DIRSYNC_FL},
3436695673SDavid Howells {JFS_SYNC_FL, FS_SYNC_FL},
3536695673SDavid Howells {JFS_SECRM_FL, FS_SECRM_FL},
3636695673SDavid Howells {JFS_UNRM_FL, FS_UNRM_FL},
3736695673SDavid Howells {JFS_APPEND_FL, FS_APPEND_FL},
3836695673SDavid Howells {JFS_IMMUTABLE_FL, FS_IMMUTABLE_FL},
39d9e90266SHerbert Poetzl {0, 0},
40d9e90266SHerbert Poetzl };
41d9e90266SHerbert Poetzl
jfs_map_ext2(unsigned long flags,int from)42d9e90266SHerbert Poetzl static long jfs_map_ext2(unsigned long flags, int from)
43d9e90266SHerbert Poetzl {
44d9e90266SHerbert Poetzl int index=0;
45d9e90266SHerbert Poetzl long mapped=0;
46d9e90266SHerbert Poetzl
47d9e90266SHerbert Poetzl while (jfs_map[index].jfs_flag) {
48d9e90266SHerbert Poetzl if (from) {
49d9e90266SHerbert Poetzl if (jfs_map[index].ext2_flag & flags)
50d9e90266SHerbert Poetzl mapped |= jfs_map[index].jfs_flag;
51d9e90266SHerbert Poetzl } else {
52d9e90266SHerbert Poetzl if (jfs_map[index].jfs_flag & flags)
53d9e90266SHerbert Poetzl mapped |= jfs_map[index].ext2_flag;
54d9e90266SHerbert Poetzl }
55d9e90266SHerbert Poetzl index++;
56d9e90266SHerbert Poetzl }
57d9e90266SHerbert Poetzl return mapped;
58d9e90266SHerbert Poetzl }
59d9e90266SHerbert Poetzl
jfs_fileattr_get(struct dentry * dentry,struct fileattr * fa)602ca58e30SMiklos Szeredi int jfs_fileattr_get(struct dentry *dentry, struct fileattr *fa)
61d9e90266SHerbert Poetzl {
622ca58e30SMiklos Szeredi struct jfs_inode_info *jfs_inode = JFS_IP(d_inode(dentry));
632ca58e30SMiklos Szeredi unsigned int flags = jfs_inode->mode2 & JFS_FL_USER_VISIBLE;
642ca58e30SMiklos Szeredi
652ca58e30SMiklos Szeredi if (d_is_special(dentry))
662ca58e30SMiklos Szeredi return -ENOTTY;
672ca58e30SMiklos Szeredi
682ca58e30SMiklos Szeredi fileattr_fill_flags(fa, jfs_map_ext2(flags, 0));
692ca58e30SMiklos Szeredi
702ca58e30SMiklos Szeredi return 0;
712ca58e30SMiklos Szeredi }
722ca58e30SMiklos Szeredi
jfs_fileattr_set(struct mnt_idmap * idmap,struct dentry * dentry,struct fileattr * fa)738782a9aeSChristian Brauner int jfs_fileattr_set(struct mnt_idmap *idmap,
742ca58e30SMiklos Szeredi struct dentry *dentry, struct fileattr *fa)
752ca58e30SMiklos Szeredi {
762ca58e30SMiklos Szeredi struct inode *inode = d_inode(dentry);
77d9e90266SHerbert Poetzl struct jfs_inode_info *jfs_inode = JFS_IP(inode);
78d9e90266SHerbert Poetzl unsigned int flags;
79d9e90266SHerbert Poetzl
802ca58e30SMiklos Szeredi if (d_is_special(dentry))
812ca58e30SMiklos Szeredi return -ENOTTY;
82d9e90266SHerbert Poetzl
832ca58e30SMiklos Szeredi if (fileattr_has_fsx(fa))
842ca58e30SMiklos Szeredi return -EOPNOTSUPP;
85d9e90266SHerbert Poetzl
862ca58e30SMiklos Szeredi flags = jfs_map_ext2(fa->flags, 1);
87d9e90266SHerbert Poetzl if (!S_ISDIR(inode->i_mode))
88d9e90266SHerbert Poetzl flags &= ~JFS_DIRSYNC_FL;
89d9e90266SHerbert Poetzl
90e47776a0SJan Kara /* Is it quota file? Do not allow user to mess with it */
912ca58e30SMiklos Szeredi if (IS_NOQUOTA(inode))
922ca58e30SMiklos Szeredi return -EPERM;
93d9e90266SHerbert Poetzl
94d9e90266SHerbert Poetzl flags = flags & JFS_FL_USER_MODIFIABLE;
955aca2842SDarrick J. Wong flags |= jfs_inode->mode2 & ~JFS_FL_USER_MODIFIABLE;
96d9e90266SHerbert Poetzl jfs_inode->mode2 = flags;
97d9e90266SHerbert Poetzl
98d9e90266SHerbert Poetzl jfs_set_inode_flags(inode);
99*ad9dc5dfSJeff Layton inode_set_ctime_current(inode);
100d9e90266SHerbert Poetzl mark_inode_dirty(inode);
1012ca58e30SMiklos Szeredi
1022ca58e30SMiklos Szeredi return 0;
103d9e90266SHerbert Poetzl }
104b40c2e66STino Reichardt
jfs_ioctl(struct file * filp,unsigned int cmd,unsigned long arg)1052ca58e30SMiklos Szeredi long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
1062ca58e30SMiklos Szeredi {
1072ca58e30SMiklos Szeredi struct inode *inode = file_inode(filp);
1082ca58e30SMiklos Szeredi
1092ca58e30SMiklos Szeredi switch (cmd) {
110b40c2e66STino Reichardt case FITRIM:
111b40c2e66STino Reichardt {
112b40c2e66STino Reichardt struct super_block *sb = inode->i_sb;
113b40c2e66STino Reichardt struct fstrim_range range;
114b40c2e66STino Reichardt s64 ret = 0;
115b40c2e66STino Reichardt
116b40c2e66STino Reichardt if (!capable(CAP_SYS_ADMIN))
117b40c2e66STino Reichardt return -EPERM;
118b40c2e66STino Reichardt
11970200574SChristoph Hellwig if (!bdev_max_discard_sectors(sb->s_bdev)) {
120b40c2e66STino Reichardt jfs_warn("FITRIM not supported on device");
121b40c2e66STino Reichardt return -EOPNOTSUPP;
122b40c2e66STino Reichardt }
123b40c2e66STino Reichardt
124b40c2e66STino Reichardt if (copy_from_user(&range, (struct fstrim_range __user *)arg,
125b40c2e66STino Reichardt sizeof(range)))
126b40c2e66STino Reichardt return -EFAULT;
127b40c2e66STino Reichardt
128b40c2e66STino Reichardt range.minlen = max_t(unsigned int, range.minlen,
1297b47ef52SChristoph Hellwig bdev_discard_granularity(sb->s_bdev));
130b40c2e66STino Reichardt
131b40c2e66STino Reichardt ret = jfs_ioc_trim(inode, &range);
132b40c2e66STino Reichardt if (ret < 0)
133b40c2e66STino Reichardt return ret;
134b40c2e66STino Reichardt
135b40c2e66STino Reichardt if (copy_to_user((struct fstrim_range __user *)arg, &range,
136b40c2e66STino Reichardt sizeof(range)))
137b40c2e66STino Reichardt return -EFAULT;
138b40c2e66STino Reichardt
139b40c2e66STino Reichardt return 0;
140b40c2e66STino Reichardt }
141b40c2e66STino Reichardt
142d9e90266SHerbert Poetzl default:
143d9e90266SHerbert Poetzl return -ENOTTY;
144d9e90266SHerbert Poetzl }
145d9e90266SHerbert Poetzl }
146