701882ce602450e8c2643df0f89be893193ddb56
[linux-block.git] / fs / bcachefs / fs-ioctl.c
1 // SPDX-License-Identifier: GPL-2.0
2 #ifndef NO_BCACHEFS_FS
3
4 #include "bcachefs.h"
5 #include "chardev.h"
6 #include "fs.h"
7 #include "fs-ioctl.h"
8 #include "quota.h"
9
10 #include <linux/compat.h>
11 #include <linux/mount.h>
12
13 #define FS_IOC_GOINGDOWN             _IOR('X', 125, __u32)
14
15 struct flags_set {
16         unsigned                mask;
17         unsigned                flags;
18
19         unsigned                projid;
20 };
21
22 static int bch2_inode_flags_set(struct bch_inode_info *inode,
23                                 struct bch_inode_unpacked *bi,
24                                 void *p)
25 {
26         struct bch_fs *c = inode->v.i_sb->s_fs_info;
27         /*
28          * We're relying on btree locking here for exclusion with other ioctl
29          * calls - use the flags in the btree (@bi), not inode->i_flags:
30          */
31         struct flags_set *s = p;
32         unsigned newflags = s->flags;
33         unsigned oldflags = bi->bi_flags & s->mask;
34
35         if (((newflags ^ oldflags) & (BCH_INODE_APPEND|BCH_INODE_IMMUTABLE)) &&
36             !capable(CAP_LINUX_IMMUTABLE))
37                 return -EPERM;
38
39         if (!S_ISREG(bi->bi_mode) &&
40             !S_ISDIR(bi->bi_mode) &&
41             (newflags & (BCH_INODE_NODUMP|BCH_INODE_NOATIME)) != newflags)
42                 return -EINVAL;
43
44         bi->bi_flags &= ~s->mask;
45         bi->bi_flags |= newflags;
46
47         bi->bi_ctime = timespec_to_bch2_time(c, current_time(&inode->v));
48         return 0;
49 }
50
51 static int bch2_ioc_getflags(struct bch_inode_info *inode, int __user *arg)
52 {
53         unsigned flags = map_flags(bch_flags_to_uflags, inode->ei_inode.bi_flags);
54
55         return put_user(flags, arg);
56 }
57
58 static int bch2_ioc_setflags(struct bch_fs *c,
59                              struct file *file,
60                              struct bch_inode_info *inode,
61                              void __user *arg)
62 {
63         struct flags_set s = { .mask = map_defined(bch_flags_to_uflags) };
64         unsigned uflags;
65         int ret;
66
67         if (get_user(uflags, (int __user *) arg))
68                 return -EFAULT;
69
70         s.flags = map_flags_rev(bch_flags_to_uflags, uflags);
71         if (uflags)
72                 return -EOPNOTSUPP;
73
74         ret = mnt_want_write_file(file);
75         if (ret)
76                 return ret;
77
78         inode_lock(&inode->v);
79         if (!inode_owner_or_capable(file_mnt_idmap(file), &inode->v)) {
80                 ret = -EACCES;
81                 goto setflags_out;
82         }
83
84         mutex_lock(&inode->ei_update_lock);
85         ret = bch2_write_inode(c, inode, bch2_inode_flags_set, &s,
86                                ATTR_CTIME);
87         mutex_unlock(&inode->ei_update_lock);
88
89 setflags_out:
90         inode_unlock(&inode->v);
91         mnt_drop_write_file(file);
92         return ret;
93 }
94
95 static int bch2_ioc_fsgetxattr(struct bch_inode_info *inode,
96                                struct fsxattr __user *arg)
97 {
98         struct fsxattr fa = { 0 };
99
100         fa.fsx_xflags = map_flags(bch_flags_to_xflags, inode->ei_inode.bi_flags);
101         fa.fsx_projid = inode->ei_qid.q[QTYP_PRJ];
102
103         return copy_to_user(arg, &fa, sizeof(fa));
104 }
105
106 static int bch2_set_projid(struct bch_fs *c,
107                            struct bch_inode_info *inode,
108                            u32 projid)
109 {
110         struct bch_qid qid = inode->ei_qid;
111
112         qid.q[QTYP_PRJ] = projid;
113
114         return bch2_fs_quota_transfer(c, inode, qid,
115                                       1 << QTYP_PRJ,
116                                       KEY_TYPE_QUOTA_PREALLOC);
117 }
118
119 static int fssetxattr_inode_update_fn(struct bch_inode_info *inode,
120                                       struct bch_inode_unpacked *bi,
121                                       void *p)
122 {
123         struct flags_set *s = p;
124
125         bi->bi_project = s->projid;
126
127         return bch2_inode_flags_set(inode, bi, p);
128 }
129
130 static int bch2_ioc_fssetxattr(struct bch_fs *c,
131                                struct file *file,
132                                struct bch_inode_info *inode,
133                                struct fsxattr __user *arg)
134 {
135         struct flags_set s = { .mask = map_defined(bch_flags_to_xflags) };
136         struct fsxattr fa;
137         int ret;
138
139         if (copy_from_user(&fa, arg, sizeof(fa)))
140                 return -EFAULT;
141
142         s.flags = map_flags_rev(bch_flags_to_xflags, fa.fsx_xflags);
143         if (fa.fsx_xflags)
144                 return -EOPNOTSUPP;
145
146         s.projid = fa.fsx_projid;
147
148         ret = mnt_want_write_file(file);
149         if (ret)
150                 return ret;
151
152         inode_lock(&inode->v);
153         if (!inode_owner_or_capable(file_mnt_idmap(file), &inode->v)) {
154                 ret = -EACCES;
155                 goto err;
156         }
157
158         mutex_lock(&inode->ei_update_lock);
159         ret = bch2_set_projid(c, inode, fa.fsx_projid);
160         if (ret)
161                 goto err_unlock;
162
163         ret = bch2_write_inode(c, inode, fssetxattr_inode_update_fn, &s,
164                                ATTR_CTIME);
165 err_unlock:
166         mutex_unlock(&inode->ei_update_lock);
167 err:
168         inode_unlock(&inode->v);
169         mnt_drop_write_file(file);
170         return ret;
171 }
172
173 long bch2_fs_file_ioctl(struct file *file, unsigned cmd, unsigned long arg)
174 {
175         struct bch_inode_info *inode = file_bch_inode(file);
176         struct super_block *sb = inode->v.i_sb;
177         struct bch_fs *c = sb->s_fs_info;
178
179         switch (cmd) {
180         case FS_IOC_GETFLAGS:
181                 return bch2_ioc_getflags(inode, (int __user *) arg);
182
183         case FS_IOC_SETFLAGS:
184                 return bch2_ioc_setflags(c, file, inode, (int __user *) arg);
185
186         case FS_IOC_FSGETXATTR:
187                 return bch2_ioc_fsgetxattr(inode, (void __user *) arg);
188         case FS_IOC_FSSETXATTR:
189                 return bch2_ioc_fssetxattr(c, file, inode, (void __user *) arg);
190
191         case FS_IOC_GETVERSION:
192                 return -ENOTTY;
193         case FS_IOC_SETVERSION:
194                 return -ENOTTY;
195
196         case FS_IOC_GOINGDOWN:
197                 if (!capable(CAP_SYS_ADMIN))
198                         return -EPERM;
199
200                 down_write(&sb->s_umount);
201                 sb->s_flags |= SB_RDONLY;
202                 bch2_fs_emergency_read_only(c);
203                 up_write(&sb->s_umount);
204                 return 0;
205
206         default:
207                 return bch2_fs_ioctl(c, cmd, (void __user *) arg);
208         }
209 }
210
211 #ifdef CONFIG_COMPAT
212 long bch2_compat_fs_ioctl(struct file *file, unsigned cmd, unsigned long arg)
213 {
214         /* These are just misnamed, they actually get/put from/to user an int */
215         switch (cmd) {
216         case FS_IOC_GETFLAGS:
217                 cmd = FS_IOC_GETFLAGS;
218                 break;
219         case FS_IOC32_SETFLAGS:
220                 cmd = FS_IOC_SETFLAGS;
221                 break;
222         default:
223                 return -ENOIOCTLCMD;
224         }
225         return bch2_fs_file_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
226 }
227 #endif
228
229 #endif /* NO_BCACHEFS_FS */