]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
1da177e4 LT |
2 | /* |
3 | * linux/fs/ext2/ioctl.c | |
4 | * | |
5 | * Copyright (C) 1993, 1994, 1995 | |
6 | * Remy Card ([email protected]) | |
7 | * Laboratoire MASI - Institut Blaise Pascal | |
8 | * Universite Pierre et Marie Curie (Paris VI) | |
9 | */ | |
10 | ||
11 | #include "ext2.h" | |
16f7e0fe | 12 | #include <linux/capability.h> |
1da177e4 LT |
13 | #include <linux/time.h> |
14 | #include <linux/sched.h> | |
e322ff07 | 15 | #include <linux/compat.h> |
42a74f20 | 16 | #include <linux/mount.h> |
1da177e4 | 17 | #include <asm/current.h> |
7c0f6ba6 | 18 | #include <linux/uaccess.h> |
aba405e3 | 19 | #include <linux/fileattr.h> |
1da177e4 | 20 | |
aba405e3 | 21 | int ext2_fileattr_get(struct dentry *dentry, struct fileattr *fa) |
1da177e4 | 22 | { |
aba405e3 | 23 | struct ext2_inode_info *ei = EXT2_I(d_inode(dentry)); |
1da177e4 | 24 | |
aba405e3 | 25 | fileattr_fill_flags(fa, ei->i_flags & EXT2_FL_USER_VISIBLE); |
1da177e4 | 26 | |
aba405e3 MS |
27 | return 0; |
28 | } | |
1da177e4 | 29 | |
8782a9ae | 30 | int ext2_fileattr_set(struct mnt_idmap *idmap, |
aba405e3 MS |
31 | struct dentry *dentry, struct fileattr *fa) |
32 | { | |
33 | struct inode *inode = d_inode(dentry); | |
34 | struct ext2_inode_info *ei = EXT2_I(inode); | |
1da177e4 | 35 | |
aba405e3 MS |
36 | if (fileattr_has_fsx(fa)) |
37 | return -EOPNOTSUPP; | |
1da177e4 | 38 | |
aba405e3 MS |
39 | /* Is it quota file? Do not allow user to mess with it */ |
40 | if (IS_NOQUOTA(inode)) | |
41 | return -EPERM; | |
1da177e4 | 42 | |
aba405e3 MS |
43 | ei->i_flags = (ei->i_flags & ~EXT2_FL_USER_MODIFIABLE) | |
44 | (fa->flags & EXT2_FL_USER_MODIFIABLE); | |
1da177e4 | 45 | |
aba405e3 | 46 | ext2_set_inode_flags(inode); |
fc4eed64 | 47 | inode_set_ctime_current(inode); |
aba405e3 | 48 | mark_inode_dirty(inode); |
1da177e4 | 49 | |
aba405e3 MS |
50 | return 0; |
51 | } | |
1da177e4 | 52 | |
1da177e4 | 53 | |
aba405e3 MS |
54 | long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
55 | { | |
56 | struct inode *inode = file_inode(filp); | |
57 | struct ext2_inode_info *ei = EXT2_I(inode); | |
58 | unsigned short rsv_window_size; | |
59 | int ret; | |
34b07840 | 60 | |
aba405e3 MS |
61 | ext2_debug ("cmd = %u, arg = %lu\n", cmd, arg); |
62 | ||
63 | switch (cmd) { | |
1da177e4 LT |
64 | case EXT2_IOC_GETVERSION: |
65 | return put_user(inode->i_generation, (int __user *) arg); | |
34b07840 DH |
66 | case EXT2_IOC_SETVERSION: { |
67 | __u32 generation; | |
68 | ||
01beba79 | 69 | if (!inode_owner_or_capable(&nop_mnt_idmap, inode)) |
1da177e4 | 70 | return -EPERM; |
a561be71 | 71 | ret = mnt_want_write_file(filp); |
42a74f20 DH |
72 | if (ret) |
73 | return ret; | |
34b07840 | 74 | if (get_user(generation, (int __user *) arg)) { |
42a74f20 | 75 | ret = -EFAULT; |
34b07840 | 76 | goto setversion_out; |
42a74f20 | 77 | } |
34b07840 | 78 | |
5955102c | 79 | inode_lock(inode); |
fc4eed64 | 80 | inode_set_ctime_current(inode); |
34b07840 | 81 | inode->i_generation = generation; |
5955102c | 82 | inode_unlock(inode); |
34b07840 DH |
83 | |
84 | mark_inode_dirty(inode); | |
85 | setversion_out: | |
2a79f17e | 86 | mnt_drop_write_file(filp); |
42a74f20 | 87 | return ret; |
34b07840 | 88 | } |
a686cd89 MB |
89 | case EXT2_IOC_GETRSVSZ: |
90 | if (test_opt(inode->i_sb, RESERVATION) | |
91 | && S_ISREG(inode->i_mode) | |
92 | && ei->i_block_alloc_info) { | |
93 | rsv_window_size = ei->i_block_alloc_info->rsv_window_node.rsv_goal_size; | |
94 | return put_user(rsv_window_size, (int __user *)arg); | |
95 | } | |
96 | return -ENOTTY; | |
97 | case EXT2_IOC_SETRSVSZ: { | |
98 | ||
99 | if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode)) | |
100 | return -ENOTTY; | |
101 | ||
01beba79 | 102 | if (!inode_owner_or_capable(&nop_mnt_idmap, inode)) |
a686cd89 MB |
103 | return -EACCES; |
104 | ||
105 | if (get_user(rsv_window_size, (int __user *)arg)) | |
106 | return -EFAULT; | |
107 | ||
a561be71 | 108 | ret = mnt_want_write_file(filp); |
42a74f20 DH |
109 | if (ret) |
110 | return ret; | |
111 | ||
a686cd89 MB |
112 | if (rsv_window_size > EXT2_MAX_RESERVE_BLOCKS) |
113 | rsv_window_size = EXT2_MAX_RESERVE_BLOCKS; | |
114 | ||
115 | /* | |
116 | * need to allocate reservation structure for this inode | |
117 | * before set the window size | |
118 | */ | |
119 | /* | |
120 | * XXX What lock should protect the rsv_goal_size? | |
121 | * Accessed in ext2_get_block only. ext3 uses i_truncate. | |
122 | */ | |
123 | mutex_lock(&ei->truncate_mutex); | |
124 | if (!ei->i_block_alloc_info) | |
125 | ext2_init_block_alloc_info(inode); | |
126 | ||
127 | if (ei->i_block_alloc_info){ | |
128 | struct ext2_reserve_window_node *rsv = &ei->i_block_alloc_info->rsv_window_node; | |
129 | rsv->rsv_goal_size = rsv_window_size; | |
acd1f046 CX |
130 | } else { |
131 | ret = -ENOMEM; | |
a686cd89 | 132 | } |
acd1f046 | 133 | |
a686cd89 | 134 | mutex_unlock(&ei->truncate_mutex); |
2a79f17e | 135 | mnt_drop_write_file(filp); |
acd1f046 | 136 | return ret; |
a686cd89 | 137 | } |
1da177e4 LT |
138 | default: |
139 | return -ENOTTY; | |
140 | } | |
141 | } | |
e322ff07 DH |
142 | |
143 | #ifdef CONFIG_COMPAT | |
144 | long ext2_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |
145 | { | |
e322ff07 DH |
146 | /* These are just misnamed, they actually get/put from/to user an int */ |
147 | switch (cmd) { | |
e322ff07 DH |
148 | case EXT2_IOC32_GETVERSION: |
149 | cmd = EXT2_IOC_GETVERSION; | |
150 | break; | |
151 | case EXT2_IOC32_SETVERSION: | |
152 | cmd = EXT2_IOC_SETVERSION; | |
153 | break; | |
154 | default: | |
155 | return -ENOIOCTLCMD; | |
156 | } | |
14f9f7b2 | 157 | return ext2_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); |
e322ff07 DH |
158 | } |
159 | #endif |