Whamcloud - gitweb
LU-13004 modules: replace lnet_kiov_t with struct bio_vec
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / rhel7.5 / ext4-projid-xfs-ioctls.patch
1 Index: linux-stage/fs/ext4/ext4.h
2 ===================================================================
3 --- linux-stage.orig/fs/ext4/ext4.h
4 +++ linux-stage/fs/ext4/ext4.h
5 @@ -397,6 +397,13 @@ struct flex_groups {
6  #define EXT4_FL_USER_VISIBLE           0x304BDFFF /* User visible flags */
7  #define EXT4_FL_USER_MODIFIABLE                0x204380FF /* User modifiable flags */
8  
9 +#define EXT4_FL_XFLAG_VISIBLE          (EXT4_SYNC_FL | \
10 +                                        EXT4_IMMUTABLE_FL | \
11 +                                        EXT4_APPEND_FL | \
12 +                                        EXT4_NODUMP_FL | \
13 +                                        EXT4_NOATIME_FL | \
14 +                                        EXT4_PROJINHERIT_FL)
15 +
16  /* Flags that should be inherited by new inodes from their parent. */
17  #define EXT4_FL_INHERITED (EXT4_SECRM_FL | EXT4_UNRM_FL | EXT4_COMPR_FL |\
18                            EXT4_SYNC_FL | EXT4_NODUMP_FL | EXT4_NOATIME_FL |\
19 @@ -622,6 +629,44 @@ enum {
20  #define EXT4_IOC_SWAP_BOOT             _IO('f', 17)
21  #define EXT4_IOC_PRECACHE_EXTENTS      _IO('f', 18)
22  
23 +#ifndef FS_IOC_FSGETXATTR
24 +/* Until the uapi changes get merged for project quota... */
25 +#define FS_IOC_FSGETXATTR               _IOR('X', 31, struct fsxattr)
26 +#define FS_IOC_FSSETXATTR               _IOW('X', 32, struct fsxattr)
27 +/*
28 + * Structure for FS_IOC_FSGETXATTR and FS_IOC_FSSETXATTR.
29 + */
30 +struct fsxattr {
31 +       __u32           fsx_xflags;     /* xflags field value (get/set) */
32 +       __u32           fsx_extsize;    /* extsize field value (get/set)*/
33 +       __u32           fsx_nextents;   /* nextents field value (get)   */
34 +       __u32           fsx_projid;     /* project identifier (get/set) */
35 +       unsigned char   fsx_pad[12];
36 +};
37 +
38 +/*
39 + * Flags for the fsx_xflags field
40 + */
41 +#define FS_XFLAG_REALTIME      0x00000001      /* data in realtime volume */
42 +#define FS_XFLAG_PREALLOC      0x00000002      /* preallocated file extents */
43 +#define FS_XFLAG_IMMUTABLE     0x00000008      /* file cannot be modified */
44 +#define FS_XFLAG_APPEND                0x00000010      /* all writes append */
45 +#define FS_XFLAG_SYNC          0x00000020      /* all writes synchronous */
46 +#define FS_XFLAG_NOATIME       0x00000040      /* do not update access time */
47 +#define FS_XFLAG_NODUMP                0x00000080      /* do not include in backups */
48 +#define FS_XFLAG_RTINHERIT     0x00000100      /* create with rt bit set */
49 +#define FS_XFLAG_PROJINHERIT   0x00000200      /* create with parents projid */
50 +#define FS_XFLAG_NOSYMLINKS    0x00000400      /* disallow symlink creation */
51 +#define FS_XFLAG_EXTSIZE       0x00000800      /* extent size allocator hint */
52 +#define FS_XFLAG_EXTSZINHERIT  0x00001000      /* inherit inode extent size */
53 +#define FS_XFLAG_NODEFRAG      0x00002000      /* do not defragment */
54 +#define FS_XFLAG_FILESTREAM    0x00004000      /* use filestream allocator */
55 +#define FS_XFLAG_HASATTR       0x80000000      /* no DIFLAG for this */
56 +#endif /* !defined(FS_IOC_FSGETXATTR) */
57 +
58 +#define EXT4_IOC_FSGETXATTR            FS_IOC_FSGETXATTR
59 +#define EXT4_IOC_FSSETXATTR            FS_IOC_FSSETXATTR
60 +
61  #if defined(__KERNEL__) && defined(CONFIG_COMPAT)
62  /*
63   * ioctl commands in 32 bit emulation
64 Index: linux-stage/fs/ext4/ioctl.c
65 ===================================================================
66 --- linux-stage.orig/fs/ext4/ioctl.c
67 +++ linux-stage/fs/ext4/ioctl.c
68 @@ -16,6 +16,7 @@
69  #include <linux/file.h>
70  #include <linux/uuid.h>
71  #include <asm/uaccess.h>
72 +#include <linux/quotaops.h>
73  #include "ext4_jbd2.h"
74  #include "ext4.h"
75  
76 @@ -199,6 +200,251 @@ journal_err_out:
77         return err;
78  }
79  
80 +static int ext4_ioctl_setflags(struct inode *inode,
81 +                              unsigned int flags)
82 +{
83 +       struct ext4_inode_info *ei = EXT4_I(inode);
84 +       handle_t *handle = NULL;
85 +       int err = EPERM, migrate = 0;
86 +       struct ext4_iloc iloc;
87 +       unsigned int oldflags, mask, i;
88 +       unsigned int jflag;
89 +
90 +       /* Is it quota file? Do not allow user to mess with it */
91 +       if (IS_NOQUOTA(inode))
92 +               goto flags_out;
93 +
94 +       oldflags = ei->i_flags;
95 +
96 +       /* The JOURNAL_DATA flag is modifiable only by root */
97 +       jflag = flags & EXT4_JOURNAL_DATA_FL;
98 +
99 +       /*
100 +        * The IMMUTABLE and APPEND_ONLY flags can only be changed by
101 +        * the relevant capability.
102 +        *
103 +        * This test looks nicer. Thanks to Pauline Middelink
104 +        */
105 +       if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) {
106 +               if (!capable(CAP_LINUX_IMMUTABLE))
107 +                       goto flags_out;
108 +       }
109 +
110 +       /*
111 +        * The JOURNAL_DATA flag can only be changed by
112 +        * the relevant capability.
113 +        */
114 +       if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) {
115 +               if (!capable(CAP_SYS_RESOURCE))
116 +                       goto flags_out;
117 +       }
118 +       if ((flags ^ oldflags) & EXT4_EXTENTS_FL)
119 +               migrate = 1;
120 +
121 +       if (flags & EXT4_EOFBLOCKS_FL) {
122 +               /* we don't support adding EOFBLOCKS flag */
123 +               if (!(oldflags & EXT4_EOFBLOCKS_FL)) {
124 +                       err = -EOPNOTSUPP;
125 +                       goto flags_out;
126 +               }
127 +       } else if (oldflags & EXT4_EOFBLOCKS_FL)
128 +               ext4_truncate(inode);
129 +
130 +       handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);
131 +       if (IS_ERR(handle)) {
132 +               err = PTR_ERR(handle);
133 +               goto flags_out;
134 +       }
135 +       if (IS_SYNC(inode))
136 +               ext4_handle_sync(handle);
137 +       err = ext4_reserve_inode_write(handle, inode, &iloc);
138 +       if (err)
139 +               goto flags_err;
140 +
141 +       for (i = 0, mask = 1; i < 32; i++, mask <<= 1) {
142 +               if (!(mask & EXT4_FL_USER_MODIFIABLE))
143 +                       continue;
144 +               if (mask & flags)
145 +                       ext4_set_inode_flag(inode, i);
146 +               else
147 +                       ext4_clear_inode_flag(inode, i);
148 +       }
149 +
150 +       ext4_set_inode_flags(inode);
151 +       inode->i_ctime = ext4_current_time(inode);
152 +
153 +       err = ext4_mark_iloc_dirty(handle, inode, &iloc);
154 +flags_err:
155 +       ext4_journal_stop(handle);
156 +       if (err)
157 +               goto flags_out;
158 +
159 +       if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) {
160 +                        /*
161 +                         * Changes to the journaling mode can cause unsafe
162 +                         * changes to S_DAX if we are using the DAX mount option.
163 +                         */
164 +                        if (test_opt(inode->i_sb, DAX)) {
165 +                                err = -EBUSY;
166 +                                goto flags_out;
167 +                        }
168 +               err = ext4_change_inode_journal_flag(inode, jflag);
169 +       }
170 +       if (err)
171 +               goto flags_out;
172 +       if (migrate) {
173 +               if (flags & EXT4_EXTENTS_FL)
174 +                       err = ext4_ext_migrate(inode);
175 +               else
176 +                       err = ext4_ind_migrate(inode);
177 +       }
178 +
179 +flags_out:
180 +       return err;
181 +}
182 +
183 +#ifdef CONFIG_QUOTA
184 +static int ext4_ioctl_setproject(struct file *filp, __u32 projid)
185 +{
186 +       struct inode *inode = file_inode(filp);
187 +       struct super_block *sb = inode->i_sb;
188 +       struct ext4_inode_info *ei = EXT4_I(inode);
189 +       int err, rc;
190 +       handle_t *handle;
191 +       kprojid_t kprojid;
192 +       struct ext4_iloc iloc;
193 +       struct ext4_inode *raw_inode;
194 +       struct dquot *transfer_to[EXT4_MAXQUOTAS] = { };
195 +
196 +       if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
197 +                       EXT4_FEATURE_RO_COMPAT_PROJECT)) {
198 +               BUG_ON(__kprojid_val(EXT4_I(inode)->i_projid)
199 +                      != EXT4_DEF_PROJID);
200 +               if (projid != EXT4_DEF_PROJID)
201 +                       return -EOPNOTSUPP;
202 +               else
203 +                       return 0;
204 +       }
205 +
206 +       if (EXT4_INODE_SIZE(sb) <= EXT4_GOOD_OLD_INODE_SIZE)
207 +               return -EOPNOTSUPP;
208 +
209 +       kprojid = make_kprojid(&init_user_ns, (projid_t)projid);
210 +
211 +       if (projid_eq(kprojid, EXT4_I(inode)->i_projid))
212 +               return 0;
213 +
214 +       err = mnt_want_write_file(filp);
215 +       if (err)
216 +               return err;
217 +
218 +       err = -EPERM;
219 +       mutex_lock(&inode->i_mutex);
220 +       /* Is it quota file? Do not allow user to mess with it */
221 +       if (IS_NOQUOTA(inode))
222 +               goto out_unlock;
223 +
224 +       err = ext4_get_inode_loc(inode, &iloc);
225 +       if (err)
226 +               goto out_unlock;
227 +
228 +       raw_inode = ext4_raw_inode(&iloc);
229 +       if (!EXT4_FITS_IN_INODE(raw_inode, ei, i_projid)) {
230 +               err = -EOVERFLOW;
231 +               brelse(iloc.bh);
232 +               goto out_unlock;
233 +       }
234 +       brelse(iloc.bh);
235 +
236 +       dquot_initialize(inode);
237 +
238 +       handle = ext4_journal_start(inode, EXT4_HT_QUOTA,
239 +               EXT4_QUOTA_INIT_BLOCKS(sb) +
240 +               EXT4_QUOTA_DEL_BLOCKS(sb) + 3);
241 +       if (IS_ERR(handle)) {
242 +               err = PTR_ERR(handle);
243 +               goto out_unlock;
244 +       }
245 +
246 +       err = ext4_reserve_inode_write(handle, inode, &iloc);
247 +       if (err)
248 +               goto out_stop;
249 +
250 +       transfer_to[PRJQUOTA] = dqget(sb, make_kqid_projid(kprojid));
251 +       if (transfer_to[PRJQUOTA]) {
252 +               err = __dquot_transfer(inode, transfer_to);
253 +               dqput(transfer_to[PRJQUOTA]);
254 +               if (err)
255 +                       goto out_dirty;
256 +       }
257 +
258 +       EXT4_I(inode)->i_projid = kprojid;
259 +       inode->i_ctime = ext4_current_time(inode);
260 +out_dirty:
261 +       rc = ext4_mark_iloc_dirty(handle, inode, &iloc);
262 +       if (!err)
263 +               err = rc;
264 +out_stop:
265 +       ext4_journal_stop(handle);
266 +out_unlock:
267 +       mutex_unlock(&inode->i_mutex);
268 +       mnt_drop_write_file(filp);
269 +       return err;
270 +
271 +
272 +}
273 +
274 +#else
275 +static int ext4_ioctl_setproject(struct file *filp, __u32 projid)
276 +{
277 +       if (projid != EXT4_DEF_PROJID)
278 +               return -EOPNOTSUPP;
279 +       return 0;
280 +}
281 +#endif
282 +
283 +
284 +/* Transfer internal flags to xflags */
285 +static inline __u32 ext4_iflags_to_xflags(unsigned long iflags)
286 +{
287 +       __u32 xflags = 0;
288 +
289 +       if (iflags & EXT4_SYNC_FL)
290 +               xflags |= FS_XFLAG_SYNC;
291 +       if (iflags & EXT4_IMMUTABLE_FL)
292 +               xflags |= FS_XFLAG_IMMUTABLE;
293 +       if (iflags & EXT4_APPEND_FL)
294 +               xflags |= FS_XFLAG_APPEND;
295 +       if (iflags & EXT4_NODUMP_FL)
296 +               xflags |= FS_XFLAG_NODUMP;
297 +       if (iflags & EXT4_NOATIME_FL)
298 +               xflags |= FS_XFLAG_NOATIME;
299 +       if (iflags & EXT4_PROJINHERIT_FL)
300 +               xflags |= FS_XFLAG_PROJINHERIT;
301 +       return xflags;
302 +}
303 +
304 +/* Transfer xflags flags to internal */
305 +static inline unsigned long ext4_xflags_to_iflags(__u32 xflags)
306 +{
307 +       unsigned long iflags = 0;
308 +
309 +       if (xflags & FS_XFLAG_SYNC)
310 +               iflags |= EXT4_SYNC_FL;
311 +       if (xflags & FS_XFLAG_IMMUTABLE)
312 +               iflags |= EXT4_IMMUTABLE_FL;
313 +       if (xflags & FS_XFLAG_APPEND)
314 +               iflags |= EXT4_APPEND_FL;
315 +       if (xflags & FS_XFLAG_NODUMP)
316 +               iflags |= EXT4_NODUMP_FL;
317 +       if (xflags & FS_XFLAG_NOATIME)
318 +               iflags |= EXT4_NOATIME_FL;
319 +       if (xflags & FS_XFLAG_PROJINHERIT)
320 +               iflags |= EXT4_PROJINHERIT_FL;
321 +
322 +       return iflags;
323 +}
324 +
325  long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
326  {
327         struct inode *inode = file_inode(filp);
328 @@ -214,11 +512,7 @@ long ext4_ioctl(struct file *filp, unsig
329                 flags = ei->i_flags & EXT4_FL_USER_VISIBLE;
330                 return put_user(flags, (int __user *) arg);
331         case EXT4_IOC_SETFLAGS: {
332 -               handle_t *handle = NULL;
333 -               int err, migrate = 0;
334 -               struct ext4_iloc iloc;
335 -               unsigned int oldflags, mask, i;
336 -               unsigned int jflag;
337 +               int err;
338  
339                 if (!inode_owner_or_capable(inode))
340                         return -EACCES;
341 @@ -232,98 +526,8 @@ long ext4_ioctl(struct file *filp, unsig
342  
343                 flags = ext4_mask_flags(inode->i_mode, flags);
344  
345 -               err = -EPERM;
346                 mutex_lock(&inode->i_mutex);
347 -               /* Is it quota file? Do not allow user to mess with it */
348 -               if (IS_NOQUOTA(inode))
349 -                       goto flags_out;
350 -
351 -               oldflags = ei->i_flags;
352 -
353 -               /* The JOURNAL_DATA flag is modifiable only by root */
354 -               jflag = flags & EXT4_JOURNAL_DATA_FL;
355 -
356 -               /*
357 -                * The IMMUTABLE and APPEND_ONLY flags can only be changed by
358 -                * the relevant capability.
359 -                *
360 -                * This test looks nicer. Thanks to Pauline Middelink
361 -                */
362 -               if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) {
363 -                       if (!capable(CAP_LINUX_IMMUTABLE))
364 -                               goto flags_out;
365 -               }
366 -
367 -               /*
368 -                * The JOURNAL_DATA flag can only be changed by
369 -                * the relevant capability.
370 -                */
371 -               if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) {
372 -                       if (!capable(CAP_SYS_RESOURCE))
373 -                               goto flags_out;
374 -               }
375 -               if ((flags ^ oldflags) & EXT4_EXTENTS_FL)
376 -                       migrate = 1;
377 -
378 -               if (flags & EXT4_EOFBLOCKS_FL) {
379 -                       /* we don't support adding EOFBLOCKS flag */
380 -                       if (!(oldflags & EXT4_EOFBLOCKS_FL)) {
381 -                               err = -EOPNOTSUPP;
382 -                               goto flags_out;
383 -                       }
384 -               } else if (oldflags & EXT4_EOFBLOCKS_FL)
385 -                       ext4_truncate(inode);
386 -
387 -               handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);
388 -               if (IS_ERR(handle)) {
389 -                       err = PTR_ERR(handle);
390 -                       goto flags_out;
391 -               }
392 -               if (IS_SYNC(inode))
393 -                       ext4_handle_sync(handle);
394 -               err = ext4_reserve_inode_write(handle, inode, &iloc);
395 -               if (err)
396 -                       goto flags_err;
397 -
398 -               for (i = 0, mask = 1; i < 32; i++, mask <<= 1) {
399 -                       if (!(mask & EXT4_FL_USER_MODIFIABLE))
400 -                               continue;
401 -                       if (mask & flags)
402 -                               ext4_set_inode_flag(inode, i);
403 -                       else
404 -                               ext4_clear_inode_flag(inode, i);
405 -               }
406 -
407 -               ext4_set_inode_flags(inode);
408 -               inode->i_ctime = ext4_current_time(inode);
409 -
410 -               err = ext4_mark_iloc_dirty(handle, inode, &iloc);
411 -flags_err:
412 -               ext4_journal_stop(handle);
413 -               if (err)
414 -                       goto flags_out;
415 -
416 -               if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) {
417 -                       /*
418 -                        * Changes to the journaling mode can cause unsafe
419 -                        * changes to S_DAX if we are using the DAX mount option.
420 -                        */
421 -                       if (test_opt(inode->i_sb, DAX)) {
422 -                               err = -EBUSY;
423 -                               goto flags_out;
424 -                       }
425 -                       err = ext4_change_inode_journal_flag(inode, jflag);
426 -                       if (err)
427 -                               goto flags_out;
428 -               }
429 -               if (migrate) {
430 -                       if (flags & EXT4_EXTENTS_FL)
431 -                               err = ext4_ext_migrate(inode);
432 -                       else
433 -                               err = ext4_ind_migrate(inode);
434 -               }
435 -
436 -flags_out:
437 +               err = ext4_ioctl_setflags(inode, flags);
438                 mutex_unlock(&inode->i_mutex);
439                 mnt_drop_write_file(filp);
440                 return err;
441 @@ -632,6 +836,62 @@ resizefs_out:
442         }
443         case EXT4_IOC_PRECACHE_EXTENTS:
444                 return ext4_ext_precache(inode);
445 +       case EXT4_IOC_FSGETXATTR:
446 +       {
447 +               struct fsxattr fa;
448 +               unsigned int flags;
449 +
450 +               memset(&fa, 0, sizeof(struct fsxattr));
451 +               ext4_get_inode_flags(ei);
452 +               flags = ei->i_flags & EXT4_FL_USER_VISIBLE;
453 +               fa.fsx_xflags = ext4_iflags_to_xflags(flags);
454 +
455 +               if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
456 +                               EXT4_FEATURE_RO_COMPAT_PROJECT)) {
457 +                       fa.fsx_projid = (__u32)from_kprojid(&init_user_ns,
458 +                               EXT4_I(inode)->i_projid);
459 +               }
460 +
461 +               if (copy_to_user((struct fsxattr __user *)arg,
462 +                                &fa, sizeof(fa)))
463 +                       return -EFAULT;
464 +               return 0;
465 +       }
466 +       case EXT4_IOC_FSSETXATTR:
467 +       {
468 +               struct fsxattr fa;
469 +               int err;
470 +
471 +               if (copy_from_user(&fa, (struct fsxattr __user *)arg,
472 +                                  sizeof(fa)))
473 +                       return -EFAULT;
474 +
475 +               /* Make sure caller has proper permission */
476 +               if (!inode_owner_or_capable(inode))
477 +                       return -EACCES;
478 +
479 +               err = mnt_want_write_file(filp);
480 +               if (err)
481 +                       return err;
482 +
483 +               flags = ext4_xflags_to_iflags(fa.fsx_xflags);
484 +               flags = ext4_mask_flags(inode->i_mode, flags);
485 +
486 +               mutex_lock(&inode->i_mutex);
487 +               flags = (ei->i_flags & ~EXT4_FL_XFLAG_VISIBLE) |
488 +                        (flags & EXT4_FL_XFLAG_VISIBLE);
489 +               err = ext4_ioctl_setflags(inode, flags);
490 +               mutex_unlock(&inode->i_mutex);
491 +               mnt_drop_write_file(filp);
492 +               if (err)
493 +                       return err;
494 +
495 +               err = ext4_ioctl_setproject(filp, fa.fsx_projid);
496 +               if (err)
497 +                       return err;
498 +
499 +               return 0;
500 +       }
501  
502         default:
503                 return -ENOTTY;