Skip to content

Commit 7a4a866

Browse files
author
Kent Overstreet
committed
bcachefs: Implement fileattr_(get|set)
inode_operations.fileattr_(get|set) didn't exist when the various flag ioctls where implemented - but they do now, which means we can delete a bunch of ioctl code in favor of standard VFS level wrappers. Closes: https://lore.kernel.org/linux-bcachefs/7ltgrgqgfummyrlvw7hnfhnu42rfiamoq3lpcvrjnlyytldmzp@yazbhusnztqn/ Cc: Petr Vorel <[email protected]> Cc: Andrea Cervesato <[email protected]> Cc: Dave Chinner <[email protected]> Signed-off-by: Kent Overstreet <[email protected]>
1 parent 4ede80a commit 7a4a866

File tree

4 files changed

+211
-292
lines changed

4 files changed

+211
-292
lines changed

fs/bcachefs/fs-ioctl.c

Lines changed: 0 additions & 217 deletions
Original file line numberDiff line numberDiff line change
@@ -21,206 +21,6 @@
2121
#define FSOP_GOING_FLAGS_LOGFLUSH 0x1 /* flush log but not data */
2222
#define FSOP_GOING_FLAGS_NOLOGFLUSH 0x2 /* don't flush log nor data */
2323

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-
22424
static int bch2_reinherit_attrs_fn(struct btree_trans *trans,
22525
struct bch_inode_info *inode,
22626
struct bch_inode_unpacked *bi,
@@ -558,23 +358,6 @@ long bch2_fs_file_ioctl(struct file *file, unsigned cmd, unsigned long arg)
558358
long ret;
559359

560360
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-
578361
case BCHFS_IOC_REINHERIT_ATTRS:
579362
ret = bch2_ioc_reinherit_attrs(c, file, inode,
580363
(void __user *) arg);

fs/bcachefs/fs-ioctl.h

Lines changed: 0 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -2,81 +2,6 @@
22
#ifndef _BCACHEFS_FS_IOCTL_H
33
#define _BCACHEFS_FS_IOCTL_H
44

5-
/* Inode flags: */
6-
7-
/* bcachefs inode flags -> vfs inode flags: */
8-
static const __maybe_unused unsigned bch_flags_to_vfs[] = {
9-
[__BCH_INODE_sync] = S_SYNC,
10-
[__BCH_INODE_immutable] = S_IMMUTABLE,
11-
[__BCH_INODE_append] = S_APPEND,
12-
[__BCH_INODE_noatime] = S_NOATIME,
13-
[__BCH_INODE_casefolded] = S_CASEFOLD,
14-
};
15-
16-
/* bcachefs inode flags -> FS_IOC_GETFLAGS: */
17-
static const __maybe_unused unsigned bch_flags_to_uflags[] = {
18-
[__BCH_INODE_sync] = FS_SYNC_FL,
19-
[__BCH_INODE_immutable] = FS_IMMUTABLE_FL,
20-
[__BCH_INODE_append] = FS_APPEND_FL,
21-
[__BCH_INODE_nodump] = FS_NODUMP_FL,
22-
[__BCH_INODE_noatime] = FS_NOATIME_FL,
23-
[__BCH_INODE_casefolded] = FS_CASEFOLD_FL,
24-
};
25-
26-
/* bcachefs inode flags -> FS_IOC_FSGETXATTR: */
27-
static const __maybe_unused unsigned bch_flags_to_xflags[] = {
28-
[__BCH_INODE_sync] = FS_XFLAG_SYNC,
29-
[__BCH_INODE_immutable] = FS_XFLAG_IMMUTABLE,
30-
[__BCH_INODE_append] = FS_XFLAG_APPEND,
31-
[__BCH_INODE_nodump] = FS_XFLAG_NODUMP,
32-
[__BCH_INODE_noatime] = FS_XFLAG_NOATIME,
33-
//[__BCH_INODE_PROJINHERIT] = FS_XFLAG_PROJINHERIT;
34-
};
35-
36-
#define set_flags(_map, _in, _out) \
37-
do { \
38-
unsigned _i; \
39-
\
40-
for (_i = 0; _i < ARRAY_SIZE(_map); _i++) \
41-
if ((_in) & (1 << _i)) \
42-
(_out) |= _map[_i]; \
43-
else \
44-
(_out) &= ~_map[_i]; \
45-
} while (0)
46-
47-
#define map_flags(_map, _in) \
48-
({ \
49-
unsigned _out = 0; \
50-
\
51-
set_flags(_map, _in, _out); \
52-
_out; \
53-
})
54-
55-
#define map_flags_rev(_map, _in) \
56-
({ \
57-
unsigned _i, _out = 0; \
58-
\
59-
for (_i = 0; _i < ARRAY_SIZE(_map); _i++) \
60-
if ((_in) & _map[_i]) { \
61-
(_out) |= 1 << _i; \
62-
(_in) &= ~_map[_i]; \
63-
} \
64-
(_out); \
65-
})
66-
67-
#define map_defined(_map) \
68-
({ \
69-
unsigned _in = ~0; \
70-
\
71-
map_flags_rev(_map, _in); \
72-
})
73-
74-
/* Set VFS inode flags from bcachefs inode: */
75-
static inline void bch2_inode_flags_to_vfs(struct bch_inode_info *inode)
76-
{
77-
set_flags(bch_flags_to_vfs, inode->ei_inode.bi_flags, inode->v.i_flags);
78-
}
79-
805
long bch2_fs_file_ioctl(struct file *, unsigned, unsigned long);
816
long bch2_compat_fs_ioctl(struct file *, unsigned, unsigned long);
827

0 commit comments

Comments
 (0)