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