Whamcloud - gitweb
LU-15544 ldiskfs: SUSE 15 SP4 kernel 5.14.21 SUSE
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / linux-5.14 / ext4-projid-xattrs.patch
1 Subject: [PATCH] P: linux-5.14/ext4-projid-xattrs.patch
2
3 ---
4  fs/ext4/ext4.h  |  1 +
5  fs/ext4/ioctl.c |  4 +--
6  fs/ext4/xattr.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++
7  3 files changed, 87 insertions(+), 2 deletions(-)
8
9 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
10 index afca42d..9ba2e8b 100644
11 --- a/fs/ext4/ext4.h
12 +++ b/fs/ext4/ext4.h
13 @@ -3164,6 +3164,7 @@ extern int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
14                                  ext4_lblk_t start, ext4_lblk_t end);
15  
16  /* ioctl.c */
17 +extern int ext4_ioctl_setproject(struct inode *, __u32);
18  extern long ext4_ioctl(struct file *, unsigned int, unsigned long);
19  extern long ext4_compat_ioctl(struct file *, unsigned int, unsigned long);
20  int ext4_fileattr_set(struct user_namespace *mnt_userns,
21 diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
22 index 6eed617..88cb1fb 100644
23 --- a/fs/ext4/ioctl.c
24 +++ b/fs/ext4/ioctl.c
25 @@ -461,7 +461,7 @@ flags_out:
26  }
27  
28  #ifdef CONFIG_QUOTA
29 -static int ext4_ioctl_setproject(struct inode *inode, __u32 projid)
30 +int ext4_ioctl_setproject(struct inode *inode, __u32 projid)
31  {
32         struct super_block *sb = inode->i_sb;
33         struct ext4_inode_info *ei = EXT4_I(inode);
34 @@ -546,7 +546,7 @@ out_stop:
35         return err;
36  }
37  #else
38 -static int ext4_ioctl_setproject(struct inode *inode, __u32 projid)
39 +int ext4_ioctl_setproject(struct inode *inode, __u32 projid)
40  {
41         if (projid != EXT4_DEF_PROJID)
42                 return -EOPNOTSUPP;
43 diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
44 index aabc92e..442bfbd 100644
45 --- a/fs/ext4/xattr.c
46 +++ b/fs/ext4/xattr.c
47 @@ -62,6 +62,8 @@
48  #include "xattr.h"
49  #include "acl.h"
50  
51 +#define EXT4_XATTR_PROJID "projid"
52 +
53  #ifdef EXT4_XATTR_DEBUG
54  # define ea_idebug(inode, fmt, ...)                                    \
55         printk(KERN_DEBUG "inode %s:%lu: " fmt "\n",                    \
56 @@ -648,11 +650,30 @@ ext4_xattr_get(struct inode *inode, int name_index, const char *name,
57                 return -ERANGE;
58  
59         down_read(&EXT4_I(inode)->xattr_sem);
60 +       if (name_index == EXT4_XATTR_INDEX_TRUSTED &&
61 +           strncmp(name, EXT4_XATTR_PROJID, strlen(name)) == 0 &&
62 +           ext4_has_feature_project(inode->i_sb)) {
63 +               /* 10 chars to hold u32 in decimal, plus ending \0 */
64 +               char value[11];
65 +               __u32 projid = (__u32)from_kprojid(&init_user_ns,
66 +                                                  EXT4_I(inode)->i_projid);
67 +               error = snprintf(value, sizeof(value), "%u", projid);
68 +               if (buffer) {
69 +                       if (error > buffer_size) {
70 +                               error = -ERANGE;
71 +                               goto out;
72 +                       }
73 +                       memcpy(buffer, value, error);
74 +               }
75 +               goto out;
76 +       }
77 +
78         error = ext4_xattr_ibody_get(inode, name_index, name, buffer,
79                                      buffer_size);
80         if (error == -ENODATA)
81                 error = ext4_xattr_block_get(inode, name_index, name, buffer,
82                                              buffer_size);
83 +out:
84         up_read(&EXT4_I(inode)->xattr_sem);
85         return error;
86  }
87 @@ -775,7 +796,33 @@ ext4_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
88         ret = ext4_xattr_block_list(dentry, buffer, buffer_size);
89         if (ret < 0)
90                 goto errout;
91 +       if (buffer) {
92 +               buffer += ret;
93 +               buffer_size -= ret;
94 +       }
95         ret += ret2;
96 +       if (ext4_has_feature_project(dentry->d_sb)) {
97 +               size_t prefix_len = strlen(XATTR_TRUSTED_PREFIX);
98 +               size_t name_len = strlen(EXT4_XATTR_PROJID);
99 +               size_t size = prefix_len + name_len + 1;
100 +
101 +               if (__kprojid_val(EXT4_I(dentry->d_inode)->i_projid) ==
102 +                                                       EXT4_DEF_PROJID)
103 +                       goto errout;
104 +               if (buffer) {
105 +                       if (size > buffer_size) {
106 +                               ret = -ERANGE;
107 +                               goto errout;
108 +                       }
109 +                       strncpy(buffer, XATTR_TRUSTED_PREFIX, prefix_len);
110 +                       buffer += prefix_len;
111 +                       strncpy(buffer, EXT4_XATTR_PROJID, name_len);
112 +                       buffer += name_len;
113 +                       *buffer++ = 0;
114 +                       buffer_size -= size;
115 +               }
116 +               ret += size;
117 +       }
118  errout:
119         up_read(&EXT4_I(d_inode(dentry))->xattr_sem);
120         return ret;
121 @@ -2456,6 +2503,43 @@ ext4_xattr_set(struct inode *inode, int name_index, const char *name,
122         int error, retries = 0;
123         int credits;
124  
125 +       if (name_index == EXT4_XATTR_INDEX_TRUSTED &&
126 +           strncmp(name, EXT4_XATTR_PROJID, strlen(name)) == 0 &&
127 +           ext4_has_feature_project(inode->i_sb)) {
128 +               /* 10 chars to hold u32 in decimal, plus ending \0 */
129 +               char buffer[11];
130 +               __u32 projid;
131 +
132 +               /*
133 +                * Project Quota ID state is only allowed to change from within
134 +                * the init namespace.
135 +                */
136 +               if (current_user_ns() != &init_user_ns)
137 +                       return -EINVAL;
138 +
139 +               if (value && value_len) {
140 +                       if (value_len >= sizeof(buffer))
141 +                               return -EINVAL;
142 +                       memcpy(buffer, value, value_len);
143 +                       buffer[value_len] = '\0';
144 +                       error = kstrtouint(buffer, 0, &projid);
145 +                       if (error)
146 +                               return error;
147 +               } else {
148 +                       projid = EXT4_DEF_PROJID;
149 +               }
150 +
151 +               /*
152 +                * Caller is allowed to change the project ID. If it is being
153 +                * changed, make sure that the new value is valid.
154 +                */
155 +               if (!projid_valid(make_kprojid(&init_user_ns, projid)))
156 +                       return -EINVAL;
157 +
158 +               error = ext4_ioctl_setproject(inode, projid);
159 +               return error;
160 +       }
161 +
162         error = dquot_initialize(inode);
163         if (error)
164                 return error;
165 -- 
166 2.27.0
167