|
21 | 21 | #define FSOP_GOING_FLAGS_LOGFLUSH 0x1 /* flush log but not data */
|
22 | 22 | #define FSOP_GOING_FLAGS_NOLOGFLUSH 0x2 /* don't flush log nor data */
|
23 | 23 |
|
24 |
| -struct flags_set { |
25 |
| - unsigned mask; |
26 |
| - unsigned flags; |
27 |
| - |
28 |
| - unsigned projid; |
29 |
| - |
30 |
| - bool set_projinherit; |
31 |
| - bool projinherit; |
32 |
| -}; |
33 |
| - |
34 |
| -static int bch2_inode_flags_set(struct btree_trans *trans, |
35 |
| - struct bch_inode_info *inode, |
36 |
| - struct bch_inode_unpacked *bi, |
37 |
| - void *p) |
38 |
| -{ |
39 |
| - struct bch_fs *c = inode->v.i_sb->s_fs_info; |
40 |
| - /* |
41 |
| - * We're relying on btree locking here for exclusion with other ioctl |
42 |
| - * calls - use the flags in the btree (@bi), not inode->i_flags: |
43 |
| - */ |
44 |
| - struct flags_set *s = p; |
45 |
| - unsigned newflags = s->flags; |
46 |
| - unsigned oldflags = bi->bi_flags & s->mask; |
47 |
| - |
48 |
| - if (((newflags ^ oldflags) & (BCH_INODE_append|BCH_INODE_immutable)) && |
49 |
| - !capable(CAP_LINUX_IMMUTABLE)) |
50 |
| - return -EPERM; |
51 |
| - |
52 |
| - if (!S_ISREG(bi->bi_mode) && |
53 |
| - !S_ISDIR(bi->bi_mode) && |
54 |
| - (newflags & (BCH_INODE_nodump|BCH_INODE_noatime)) != newflags) |
55 |
| - return -EINVAL; |
56 |
| - |
57 |
| - if ((newflags ^ oldflags) & BCH_INODE_casefolded) { |
58 |
| -#ifdef CONFIG_UNICODE |
59 |
| - int ret = 0; |
60 |
| - /* Not supported on individual files. */ |
61 |
| - if (!S_ISDIR(bi->bi_mode)) |
62 |
| - return -EOPNOTSUPP; |
63 |
| - |
64 |
| - /* |
65 |
| - * Make sure the dir is empty, as otherwise we'd need to |
66 |
| - * rehash everything and update the dirent keys. |
67 |
| - */ |
68 |
| - ret = bch2_empty_dir_trans(trans, inode_inum(inode)); |
69 |
| - if (ret < 0) |
70 |
| - return ret; |
71 |
| - |
72 |
| - ret = bch2_request_incompat_feature(c, bcachefs_metadata_version_casefolding); |
73 |
| - if (ret) |
74 |
| - return ret; |
75 |
| - |
76 |
| - bch2_check_set_feature(c, BCH_FEATURE_casefolding); |
77 |
| -#else |
78 |
| - printk(KERN_ERR "Cannot use casefolding on a kernel without CONFIG_UNICODE\n"); |
79 |
| - return -EOPNOTSUPP; |
80 |
| -#endif |
81 |
| - } |
82 |
| - |
83 |
| - if (s->set_projinherit) { |
84 |
| - bi->bi_fields_set &= ~(1 << Inode_opt_project); |
85 |
| - bi->bi_fields_set |= ((int) s->projinherit << Inode_opt_project); |
86 |
| - } |
87 |
| - |
88 |
| - bi->bi_flags &= ~s->mask; |
89 |
| - bi->bi_flags |= newflags; |
90 |
| - |
91 |
| - bi->bi_ctime = timespec_to_bch2_time(c, current_time(&inode->v)); |
92 |
| - return 0; |
93 |
| -} |
94 |
| - |
95 |
| -static int bch2_ioc_getflags(struct bch_inode_info *inode, int __user *arg) |
96 |
| -{ |
97 |
| - unsigned flags = map_flags(bch_flags_to_uflags, inode->ei_inode.bi_flags); |
98 |
| - |
99 |
| - return put_user(flags, arg); |
100 |
| -} |
101 |
| - |
102 |
| -static int bch2_ioc_setflags(struct bch_fs *c, |
103 |
| - struct file *file, |
104 |
| - struct bch_inode_info *inode, |
105 |
| - void __user *arg) |
106 |
| -{ |
107 |
| - struct flags_set s = { .mask = map_defined(bch_flags_to_uflags) }; |
108 |
| - unsigned uflags; |
109 |
| - int ret; |
110 |
| - |
111 |
| - if (get_user(uflags, (int __user *) arg)) |
112 |
| - return -EFAULT; |
113 |
| - |
114 |
| - s.flags = map_flags_rev(bch_flags_to_uflags, uflags); |
115 |
| - if (uflags) |
116 |
| - return -EOPNOTSUPP; |
117 |
| - |
118 |
| - ret = mnt_want_write_file(file); |
119 |
| - if (ret) |
120 |
| - return ret; |
121 |
| - |
122 |
| - inode_lock(&inode->v); |
123 |
| - if (!inode_owner_or_capable(file_mnt_idmap(file), &inode->v)) { |
124 |
| - ret = -EACCES; |
125 |
| - goto setflags_out; |
126 |
| - } |
127 |
| - |
128 |
| - mutex_lock(&inode->ei_update_lock); |
129 |
| - ret = bch2_subvol_is_ro(c, inode->ei_inum.subvol) ?: |
130 |
| - bch2_write_inode(c, inode, bch2_inode_flags_set, &s, |
131 |
| - ATTR_CTIME); |
132 |
| - mutex_unlock(&inode->ei_update_lock); |
133 |
| - |
134 |
| -setflags_out: |
135 |
| - inode_unlock(&inode->v); |
136 |
| - mnt_drop_write_file(file); |
137 |
| - return ret; |
138 |
| -} |
139 |
| - |
140 |
| -static int bch2_ioc_fsgetxattr(struct bch_inode_info *inode, |
141 |
| - struct fsxattr __user *arg) |
142 |
| -{ |
143 |
| - struct fsxattr fa = { 0 }; |
144 |
| - |
145 |
| - fa.fsx_xflags = map_flags(bch_flags_to_xflags, inode->ei_inode.bi_flags); |
146 |
| - |
147 |
| - if (inode->ei_inode.bi_fields_set & (1 << Inode_opt_project)) |
148 |
| - fa.fsx_xflags |= FS_XFLAG_PROJINHERIT; |
149 |
| - |
150 |
| - fa.fsx_projid = inode->ei_qid.q[QTYP_PRJ]; |
151 |
| - |
152 |
| - if (copy_to_user(arg, &fa, sizeof(fa))) |
153 |
| - return -EFAULT; |
154 |
| - |
155 |
| - return 0; |
156 |
| -} |
157 |
| - |
158 |
| -static int fssetxattr_inode_update_fn(struct btree_trans *trans, |
159 |
| - struct bch_inode_info *inode, |
160 |
| - struct bch_inode_unpacked *bi, |
161 |
| - void *p) |
162 |
| -{ |
163 |
| - struct flags_set *s = p; |
164 |
| - |
165 |
| - if (s->projid != bi->bi_project) { |
166 |
| - bi->bi_fields_set |= 1U << Inode_opt_project; |
167 |
| - bi->bi_project = s->projid; |
168 |
| - } |
169 |
| - |
170 |
| - return bch2_inode_flags_set(trans, inode, bi, p); |
171 |
| -} |
172 |
| - |
173 |
| -static int bch2_ioc_fssetxattr(struct bch_fs *c, |
174 |
| - struct file *file, |
175 |
| - struct bch_inode_info *inode, |
176 |
| - struct fsxattr __user *arg) |
177 |
| -{ |
178 |
| - struct flags_set s = { .mask = map_defined(bch_flags_to_xflags) }; |
179 |
| - struct fsxattr fa; |
180 |
| - int ret; |
181 |
| - |
182 |
| - if (copy_from_user(&fa, arg, sizeof(fa))) |
183 |
| - return -EFAULT; |
184 |
| - |
185 |
| - s.set_projinherit = true; |
186 |
| - s.projinherit = (fa.fsx_xflags & FS_XFLAG_PROJINHERIT) != 0; |
187 |
| - fa.fsx_xflags &= ~FS_XFLAG_PROJINHERIT; |
188 |
| - |
189 |
| - s.flags = map_flags_rev(bch_flags_to_xflags, fa.fsx_xflags); |
190 |
| - if (fa.fsx_xflags) |
191 |
| - return -EOPNOTSUPP; |
192 |
| - |
193 |
| - if (fa.fsx_projid >= U32_MAX) |
194 |
| - return -EINVAL; |
195 |
| - |
196 |
| - /* |
197 |
| - * inode fields accessible via the xattr interface are stored with a +1 |
198 |
| - * bias, so that 0 means unset: |
199 |
| - */ |
200 |
| - s.projid = fa.fsx_projid + 1; |
201 |
| - |
202 |
| - ret = mnt_want_write_file(file); |
203 |
| - if (ret) |
204 |
| - return ret; |
205 |
| - |
206 |
| - inode_lock(&inode->v); |
207 |
| - if (!inode_owner_or_capable(file_mnt_idmap(file), &inode->v)) { |
208 |
| - ret = -EACCES; |
209 |
| - goto err; |
210 |
| - } |
211 |
| - |
212 |
| - mutex_lock(&inode->ei_update_lock); |
213 |
| - ret = bch2_subvol_is_ro(c, inode->ei_inum.subvol) ?: |
214 |
| - bch2_set_projid(c, inode, fa.fsx_projid) ?: |
215 |
| - bch2_write_inode(c, inode, fssetxattr_inode_update_fn, &s, |
216 |
| - ATTR_CTIME); |
217 |
| - mutex_unlock(&inode->ei_update_lock); |
218 |
| -err: |
219 |
| - inode_unlock(&inode->v); |
220 |
| - mnt_drop_write_file(file); |
221 |
| - return ret; |
222 |
| -} |
223 |
| - |
224 | 24 | static int bch2_reinherit_attrs_fn(struct btree_trans *trans,
|
225 | 25 | struct bch_inode_info *inode,
|
226 | 26 | struct bch_inode_unpacked *bi,
|
@@ -558,23 +358,6 @@ long bch2_fs_file_ioctl(struct file *file, unsigned cmd, unsigned long arg)
|
558 | 358 | long ret;
|
559 | 359 |
|
560 | 360 | switch (cmd) {
|
561 |
| - case FS_IOC_GETFLAGS: |
562 |
| - ret = bch2_ioc_getflags(inode, (int __user *) arg); |
563 |
| - break; |
564 |
| - |
565 |
| - case FS_IOC_SETFLAGS: |
566 |
| - ret = bch2_ioc_setflags(c, file, inode, (int __user *) arg); |
567 |
| - break; |
568 |
| - |
569 |
| - case FS_IOC_FSGETXATTR: |
570 |
| - ret = bch2_ioc_fsgetxattr(inode, (void __user *) arg); |
571 |
| - break; |
572 |
| - |
573 |
| - case FS_IOC_FSSETXATTR: |
574 |
| - ret = bch2_ioc_fssetxattr(c, file, inode, |
575 |
| - (void __user *) arg); |
576 |
| - break; |
577 |
| - |
578 | 361 | case BCHFS_IOC_REINHERIT_ATTRS:
|
579 | 362 | ret = bch2_ioc_reinherit_attrs(c, file, inode,
|
580 | 363 | (void __user *) arg);
|
|
0 commit comments