Skip to content

Commit 33f29fc

Browse files
fs/ntfs3: add fileattr support
Implement fileattr_get() and fileattr_set() to fix a problem found during the internal testing. This allows ntfs3 to expose and modify inode flags through the generic file attribute interface used by FS_IOC_GETFLAGS and FS_IOC_SETFLAGS. Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
1 parent e8ed78f commit 33f29fc

4 files changed

Lines changed: 91 additions & 0 deletions

File tree

fs/ntfs3/file.c

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,80 @@ static int ntfs_ioctl_fitrim(struct ntfs_sb_info *sbi, unsigned long arg)
8989
return 0;
9090
}
9191

92+
/*
93+
* ntfs_fileattr_get - inode_operations::fileattr_get
94+
*/
95+
int ntfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
96+
{
97+
struct inode *inode = d_inode(dentry);
98+
struct ntfs_inode *ni = ntfs_i(inode);
99+
u32 flags = 0;
100+
101+
/* Avoid any operation if inode is bad. */
102+
if (unlikely(is_bad_ni(ni)))
103+
return -EINVAL;
104+
105+
if (inode->i_flags & S_IMMUTABLE)
106+
flags |= FS_IMMUTABLE_FL;
107+
108+
if (inode->i_flags & S_APPEND)
109+
flags |= FS_APPEND_FL;
110+
111+
if (is_compressed(ni))
112+
flags |= FS_COMPR_FL;
113+
114+
if (is_encrypted(ni))
115+
flags |= FS_ENCRYPT_FL;
116+
117+
if (ni->nodump)
118+
flags |= FS_NODUMP_FL;
119+
120+
fileattr_fill_flags(fa, flags);
121+
122+
return 0;
123+
}
124+
125+
/*
126+
* ntfs_fileattr_set - inode_operations::fileattr_set
127+
*/
128+
int ntfs_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry,
129+
struct file_kattr *fa)
130+
{
131+
struct inode *inode = d_inode(dentry);
132+
struct ntfs_inode *ni = ntfs_i(inode);
133+
u32 flags = fa->flags;
134+
unsigned int new_fl = 0;
135+
136+
/* Avoid any operation if inode is bad. */
137+
if (unlikely(is_bad_ni(ni)))
138+
return -EINVAL;
139+
140+
if (fileattr_has_fsx(fa))
141+
return -EOPNOTSUPP;
142+
143+
if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL))
144+
return -EOPNOTSUPP;
145+
146+
if (flags & FS_IMMUTABLE_FL)
147+
new_fl |= S_IMMUTABLE;
148+
149+
if (flags & FS_APPEND_FL)
150+
new_fl |= S_APPEND;
151+
152+
inode_set_flags(inode, new_fl, S_IMMUTABLE | S_APPEND);
153+
154+
/* Save nodump flag to return in ntfs_getattr. */
155+
if (flags & FS_NODUMP_FL)
156+
ni->nodump = 1;
157+
else
158+
ni->nodump = 0;
159+
160+
inode_set_ctime_current(inode);
161+
mark_inode_dirty(inode);
162+
163+
return 0;
164+
}
165+
92166
static int ntfs_ioctl_get_volume_label(struct ntfs_sb_info *sbi, u8 __user *buf)
93167
{
94168
if (copy_to_user(buf, sbi->volume.label, FSLABEL_MAX))
@@ -203,6 +277,9 @@ int ntfs_getattr(struct mnt_idmap *idmap, const struct path *path,
203277
if (inode->i_flags & S_APPEND)
204278
stat->attributes |= STATX_ATTR_APPEND;
205279

280+
if (ni->nodump)
281+
stat->attributes |= STATX_ATTR_NODUMP;
282+
206283
if (is_compressed(ni))
207284
stat->attributes |= STATX_ATTR_COMPRESSED;
208285

@@ -1547,6 +1624,8 @@ const struct inode_operations ntfs_file_inode_operations = {
15471624
.get_acl = ntfs_get_acl,
15481625
.set_acl = ntfs_set_acl,
15491626
.fiemap = ntfs_fiemap,
1627+
.fileattr_get = ntfs_fileattr_get,
1628+
.fileattr_set = ntfs_fileattr_set,
15501629
};
15511630

15521631
const struct file_operations ntfs_file_operations = {

fs/ntfs3/inode.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2095,6 +2095,8 @@ const struct inode_operations ntfs_link_inode_operations = {
20952095
.get_link = ntfs_get_link,
20962096
.setattr = ntfs_setattr,
20972097
.listxattr = ntfs_listxattr,
2098+
.fileattr_get = ntfs_fileattr_get,
2099+
.fileattr_set = ntfs_fileattr_set,
20982100
};
20992101

21002102
const struct address_space_operations ntfs_aops = {

fs/ntfs3/namei.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,8 @@ const struct inode_operations ntfs_dir_inode_operations = {
518518
.getattr = ntfs_getattr,
519519
.listxattr = ntfs_listxattr,
520520
.fiemap = ntfs_fiemap,
521+
.fileattr_get = ntfs_fileattr_get,
522+
.fileattr_set = ntfs_fileattr_set,
521523
};
522524

523525
const struct inode_operations ntfs_special_inode_operations = {
@@ -526,6 +528,8 @@ const struct inode_operations ntfs_special_inode_operations = {
526528
.listxattr = ntfs_listxattr,
527529
.get_acl = ntfs_get_acl,
528530
.set_acl = ntfs_set_acl,
531+
.fileattr_get = ntfs_fileattr_get,
532+
.fileattr_set = ntfs_fileattr_set,
529533
};
530534

531535
const struct dentry_operations ntfs_dentry_ops = {

fs/ntfs3/ntfs_fs.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,9 @@ struct ntfs_inode {
392392
*/
393393
u8 ni_bad;
394394

395+
/* Keep track of FS_NODUMP_FL. */
396+
u8 nodump;
397+
395398
union {
396399
struct ntfs_index dir;
397400
struct {
@@ -529,6 +532,9 @@ bool dir_is_empty(struct inode *dir);
529532
extern const struct file_operations ntfs_dir_operations;
530533

531534
/* Globals from file.c */
535+
int ntfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa);
536+
int ntfs_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry,
537+
struct file_kattr *fa);
532538
int ntfs_getattr(struct mnt_idmap *idmap, const struct path *path,
533539
struct kstat *stat, u32 request_mask, u32 flags);
534540
int ntfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,

0 commit comments

Comments
 (0)