xref: /openbmc/linux/fs/jfs/ioctl.c (revision ad9dc5df)
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