hc
2024-05-10 9999e48639b3cecb08ffb37358bcba3b48161b29
kernel/fs/xfs/xfs_ioctl.c
....@@ -11,9 +11,8 @@
1111 #include "xfs_trans_resv.h"
1212 #include "xfs_mount.h"
1313 #include "xfs_inode.h"
14
-#include "xfs_ioctl.h"
15
-#include "xfs_alloc.h"
1614 #include "xfs_rtalloc.h"
15
+#include "xfs_iwalk.h"
1716 #include "xfs_itable.h"
1817 #include "xfs_error.h"
1918 #include "xfs_attr.h"
....@@ -25,7 +24,6 @@
2524 #include "xfs_export.h"
2625 #include "xfs_trace.h"
2726 #include "xfs_icache.h"
28
-#include "xfs_symlink.h"
2927 #include "xfs_trans.h"
3028 #include "xfs_acl.h"
3129 #include "xfs_btree.h"
....@@ -33,15 +31,15 @@
3331 #include "xfs_fsmap.h"
3432 #include "scrub/xfs_scrub.h"
3533 #include "xfs_sb.h"
34
+#include "xfs_ag.h"
35
+#include "xfs_health.h"
36
+#include "xfs_reflink.h"
37
+#include "xfs_ioctl.h"
38
+#include "xfs_da_format.h"
39
+#include "xfs_da_btree.h"
3640
37
-#include <linux/capability.h>
38
-#include <linux/cred.h>
39
-#include <linux/dcache.h>
4041 #include <linux/mount.h>
4142 #include <linux/namei.h>
42
-#include <linux/pagemap.h>
43
-#include <linux/slab.h>
44
-#include <linux/exportfs.h>
4543
4644 /*
4745 * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to
....@@ -73,7 +71,7 @@
7371 return -EBADF;
7472 inode = file_inode(f.file);
7573 } else {
76
- error = user_lpath((const char __user *)hreq->path, &path);
74
+ error = user_path_at(AT_FDCWD, hreq->path, 0, &path);
7775 if (error)
7876 return error;
7977 inode = d_inode(path.dentry);
....@@ -296,138 +294,173 @@
296294 return error;
297295 }
298296
299
-int
300
-xfs_set_dmattrs(
301
- xfs_inode_t *ip,
302
- uint evmask,
303
- uint16_t state)
297
+/*
298
+ * Format an attribute and copy it out to the user's buffer.
299
+ * Take care to check values and protect against them changing later,
300
+ * we may be reading them directly out of a user buffer.
301
+ */
302
+static void
303
+xfs_ioc_attr_put_listent(
304
+ struct xfs_attr_list_context *context,
305
+ int flags,
306
+ unsigned char *name,
307
+ int namelen,
308
+ int valuelen)
304309 {
305
- xfs_mount_t *mp = ip->i_mount;
306
- xfs_trans_t *tp;
307
- int error;
310
+ struct xfs_attrlist *alist = context->buffer;
311
+ struct xfs_attrlist_ent *aep;
312
+ int arraytop;
308313
309
- if (!capable(CAP_SYS_ADMIN))
310
- return -EPERM;
314
+ ASSERT(!context->seen_enough);
315
+ ASSERT(context->count >= 0);
316
+ ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
317
+ ASSERT(context->firstu >= sizeof(*alist));
318
+ ASSERT(context->firstu <= context->bufsize);
311319
312
- if (XFS_FORCED_SHUTDOWN(mp))
313
- return -EIO;
320
+ /*
321
+ * Only list entries in the right namespace.
322
+ */
323
+ if (context->attr_filter != (flags & XFS_ATTR_NSP_ONDISK_MASK))
324
+ return;
314325
315
- error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp);
316
- if (error)
317
- return error;
326
+ arraytop = sizeof(*alist) +
327
+ context->count * sizeof(alist->al_offset[0]);
318328
319
- xfs_ilock(ip, XFS_ILOCK_EXCL);
320
- xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
329
+ /* decrement by the actual bytes used by the attr */
330
+ context->firstu -= round_up(offsetof(struct xfs_attrlist_ent, a_name) +
331
+ namelen + 1, sizeof(uint32_t));
332
+ if (context->firstu < arraytop) {
333
+ trace_xfs_attr_list_full(context);
334
+ alist->al_more = 1;
335
+ context->seen_enough = 1;
336
+ return;
337
+ }
321338
322
- ip->i_d.di_dmevmask = evmask;
323
- ip->i_d.di_dmstate = state;
324
-
325
- xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
326
- error = xfs_trans_commit(tp);
327
-
328
- return error;
339
+ aep = context->buffer + context->firstu;
340
+ aep->a_valuelen = valuelen;
341
+ memcpy(aep->a_name, name, namelen);
342
+ aep->a_name[namelen] = 0;
343
+ alist->al_offset[context->count++] = context->firstu;
344
+ alist->al_count = context->count;
345
+ trace_xfs_attr_list_add(context);
329346 }
330347
331
-STATIC int
332
-xfs_fssetdm_by_handle(
333
- struct file *parfilp,
334
- void __user *arg)
348
+static unsigned int
349
+xfs_attr_filter(
350
+ u32 ioc_flags)
335351 {
336
- int error;
337
- struct fsdmidata fsd;
338
- xfs_fsop_setdm_handlereq_t dmhreq;
339
- struct dentry *dentry;
352
+ if (ioc_flags & XFS_IOC_ATTR_ROOT)
353
+ return XFS_ATTR_ROOT;
354
+ if (ioc_flags & XFS_IOC_ATTR_SECURE)
355
+ return XFS_ATTR_SECURE;
356
+ return 0;
357
+}
340358
341
- if (!capable(CAP_MKNOD))
342
- return -EPERM;
343
- if (copy_from_user(&dmhreq, arg, sizeof(xfs_fsop_setdm_handlereq_t)))
359
+static unsigned int
360
+xfs_attr_flags(
361
+ u32 ioc_flags)
362
+{
363
+ if (ioc_flags & XFS_IOC_ATTR_CREATE)
364
+ return XATTR_CREATE;
365
+ if (ioc_flags & XFS_IOC_ATTR_REPLACE)
366
+ return XATTR_REPLACE;
367
+ return 0;
368
+}
369
+
370
+int
371
+xfs_ioc_attr_list(
372
+ struct xfs_inode *dp,
373
+ void __user *ubuf,
374
+ size_t bufsize,
375
+ int flags,
376
+ struct xfs_attrlist_cursor __user *ucursor)
377
+{
378
+ struct xfs_attr_list_context context = { };
379
+ struct xfs_attrlist *alist;
380
+ void *buffer;
381
+ int error;
382
+
383
+ if (bufsize < sizeof(struct xfs_attrlist) ||
384
+ bufsize > XFS_XATTR_LIST_MAX)
385
+ return -EINVAL;
386
+
387
+ /*
388
+ * Reject flags, only allow namespaces.
389
+ */
390
+ if (flags & ~(XFS_IOC_ATTR_ROOT | XFS_IOC_ATTR_SECURE))
391
+ return -EINVAL;
392
+ if (flags == (XFS_IOC_ATTR_ROOT | XFS_IOC_ATTR_SECURE))
393
+ return -EINVAL;
394
+
395
+ /*
396
+ * Validate the cursor.
397
+ */
398
+ if (copy_from_user(&context.cursor, ucursor, sizeof(context.cursor)))
344399 return -EFAULT;
400
+ if (context.cursor.pad1 || context.cursor.pad2)
401
+ return -EINVAL;
402
+ if (!context.cursor.initted &&
403
+ (context.cursor.hashval || context.cursor.blkno ||
404
+ context.cursor.offset))
405
+ return -EINVAL;
345406
346
- error = mnt_want_write_file(parfilp);
407
+ buffer = kvzalloc(bufsize, GFP_KERNEL);
408
+ if (!buffer)
409
+ return -ENOMEM;
410
+
411
+ /*
412
+ * Initialize the output buffer.
413
+ */
414
+ context.dp = dp;
415
+ context.resynch = 1;
416
+ context.attr_filter = xfs_attr_filter(flags);
417
+ context.buffer = buffer;
418
+ context.bufsize = round_down(bufsize, sizeof(uint32_t));
419
+ context.firstu = context.bufsize;
420
+ context.put_listent = xfs_ioc_attr_put_listent;
421
+
422
+ alist = context.buffer;
423
+ alist->al_count = 0;
424
+ alist->al_more = 0;
425
+ alist->al_offset[0] = context.bufsize;
426
+
427
+ error = xfs_attr_list(&context);
347428 if (error)
348
- return error;
429
+ goto out_free;
349430
350
- dentry = xfs_handlereq_to_dentry(parfilp, &dmhreq.hreq);
351
- if (IS_ERR(dentry)) {
352
- mnt_drop_write_file(parfilp);
353
- return PTR_ERR(dentry);
354
- }
355
-
356
- if (IS_IMMUTABLE(d_inode(dentry)) || IS_APPEND(d_inode(dentry))) {
357
- error = -EPERM;
358
- goto out;
359
- }
360
-
361
- if (copy_from_user(&fsd, dmhreq.data, sizeof(fsd))) {
431
+ if (copy_to_user(ubuf, buffer, bufsize) ||
432
+ copy_to_user(ucursor, &context.cursor, sizeof(context.cursor)))
362433 error = -EFAULT;
363
- goto out;
364
- }
365
-
366
- error = xfs_set_dmattrs(XFS_I(d_inode(dentry)), fsd.fsd_dmevmask,
367
- fsd.fsd_dmstate);
368
-
369
- out:
370
- mnt_drop_write_file(parfilp);
371
- dput(dentry);
434
+out_free:
435
+ kmem_free(buffer);
372436 return error;
373437 }
374438
375439 STATIC int
376440 xfs_attrlist_by_handle(
377441 struct file *parfilp,
378
- void __user *arg)
442
+ struct xfs_fsop_attrlist_handlereq __user *p)
379443 {
380
- int error = -ENOMEM;
381
- attrlist_cursor_kern_t *cursor;
382
- struct xfs_fsop_attrlist_handlereq __user *p = arg;
383
- xfs_fsop_attrlist_handlereq_t al_hreq;
444
+ struct xfs_fsop_attrlist_handlereq al_hreq;
384445 struct dentry *dentry;
385
- char *kbuf;
446
+ int error = -ENOMEM;
386447
387448 if (!capable(CAP_SYS_ADMIN))
388449 return -EPERM;
389
- if (copy_from_user(&al_hreq, arg, sizeof(xfs_fsop_attrlist_handlereq_t)))
450
+ if (copy_from_user(&al_hreq, p, sizeof(al_hreq)))
390451 return -EFAULT;
391
- if (al_hreq.buflen < sizeof(struct attrlist) ||
392
- al_hreq.buflen > XFS_XATTR_LIST_MAX)
393
- return -EINVAL;
394
-
395
- /*
396
- * Reject flags, only allow namespaces.
397
- */
398
- if (al_hreq.flags & ~(ATTR_ROOT | ATTR_SECURE))
399
- return -EINVAL;
400452
401453 dentry = xfs_handlereq_to_dentry(parfilp, &al_hreq.hreq);
402454 if (IS_ERR(dentry))
403455 return PTR_ERR(dentry);
404456
405
- kbuf = kmem_zalloc_large(al_hreq.buflen, KM_SLEEP);
406
- if (!kbuf)
407
- goto out_dput;
408
-
409
- cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
410
- error = xfs_attr_list(XFS_I(d_inode(dentry)), kbuf, al_hreq.buflen,
411
- al_hreq.flags, cursor);
412
- if (error)
413
- goto out_kfree;
414
-
415
- if (copy_to_user(&p->pos, cursor, sizeof(attrlist_cursor_kern_t))) {
416
- error = -EFAULT;
417
- goto out_kfree;
418
- }
419
-
420
- if (copy_to_user(al_hreq.buffer, kbuf, al_hreq.buflen))
421
- error = -EFAULT;
422
-
423
-out_kfree:
424
- kmem_free(kbuf);
425
-out_dput:
457
+ error = xfs_ioc_attr_list(XFS_I(d_inode(dentry)), al_hreq.buffer,
458
+ al_hreq.buflen, al_hreq.flags, &p->pos);
426459 dput(dentry);
427460 return error;
428461 }
429462
430
-int
463
+static int
431464 xfs_attrmulti_attr_get(
432465 struct inode *inode,
433466 unsigned char *name,
....@@ -435,28 +468,33 @@
435468 uint32_t *len,
436469 uint32_t flags)
437470 {
438
- unsigned char *kbuf;
439
- int error = -EFAULT;
471
+ struct xfs_da_args args = {
472
+ .dp = XFS_I(inode),
473
+ .attr_filter = xfs_attr_filter(flags),
474
+ .attr_flags = xfs_attr_flags(flags),
475
+ .name = name,
476
+ .namelen = strlen(name),
477
+ .valuelen = *len,
478
+ };
479
+ int error;
440480
441481 if (*len > XFS_XATTR_SIZE_MAX)
442482 return -EINVAL;
443
- kbuf = kmem_zalloc_large(*len, KM_SLEEP);
444
- if (!kbuf)
445
- return -ENOMEM;
446483
447
- error = xfs_attr_get(XFS_I(inode), name, kbuf, (int *)len, flags);
484
+ error = xfs_attr_get(&args);
448485 if (error)
449486 goto out_kfree;
450487
451
- if (copy_to_user(ubuf, kbuf, *len))
488
+ *len = args.valuelen;
489
+ if (copy_to_user(ubuf, args.value, args.valuelen))
452490 error = -EFAULT;
453491
454492 out_kfree:
455
- kmem_free(kbuf);
493
+ kmem_free(args.value);
456494 return error;
457495 }
458496
459
-int
497
+static int
460498 xfs_attrmulti_attr_set(
461499 struct inode *inode,
462500 unsigned char *name,
....@@ -464,38 +502,75 @@
464502 uint32_t len,
465503 uint32_t flags)
466504 {
467
- unsigned char *kbuf;
505
+ struct xfs_da_args args = {
506
+ .dp = XFS_I(inode),
507
+ .attr_filter = xfs_attr_filter(flags),
508
+ .attr_flags = xfs_attr_flags(flags),
509
+ .name = name,
510
+ .namelen = strlen(name),
511
+ };
468512 int error;
469513
470514 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
471515 return -EPERM;
472
- if (len > XFS_XATTR_SIZE_MAX)
473
- return -EINVAL;
474516
475
- kbuf = memdup_user(ubuf, len);
476
- if (IS_ERR(kbuf))
477
- return PTR_ERR(kbuf);
517
+ if (ubuf) {
518
+ if (len > XFS_XATTR_SIZE_MAX)
519
+ return -EINVAL;
520
+ args.value = memdup_user(ubuf, len);
521
+ if (IS_ERR(args.value))
522
+ return PTR_ERR(args.value);
523
+ args.valuelen = len;
524
+ }
478525
479
- error = xfs_attr_set(XFS_I(inode), name, kbuf, len, flags);
480
- if (!error)
481
- xfs_forget_acl(inode, name, flags);
482
- kfree(kbuf);
526
+ error = xfs_attr_set(&args);
527
+ if (!error && (flags & XFS_IOC_ATTR_ROOT))
528
+ xfs_forget_acl(inode, name);
529
+ kfree(args.value);
483530 return error;
484531 }
485532
486533 int
487
-xfs_attrmulti_attr_remove(
534
+xfs_ioc_attrmulti_one(
535
+ struct file *parfilp,
488536 struct inode *inode,
489
- unsigned char *name,
537
+ uint32_t opcode,
538
+ void __user *uname,
539
+ void __user *value,
540
+ uint32_t *len,
490541 uint32_t flags)
491542 {
543
+ unsigned char *name;
492544 int error;
493545
494
- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
495
- return -EPERM;
496
- error = xfs_attr_remove(XFS_I(inode), name, flags);
497
- if (!error)
498
- xfs_forget_acl(inode, name, flags);
546
+ if ((flags & XFS_IOC_ATTR_ROOT) && (flags & XFS_IOC_ATTR_SECURE))
547
+ return -EINVAL;
548
+
549
+ name = strndup_user(uname, MAXNAMELEN);
550
+ if (IS_ERR(name))
551
+ return PTR_ERR(name);
552
+
553
+ switch (opcode) {
554
+ case ATTR_OP_GET:
555
+ error = xfs_attrmulti_attr_get(inode, name, value, len, flags);
556
+ break;
557
+ case ATTR_OP_REMOVE:
558
+ value = NULL;
559
+ *len = 0;
560
+ /* fall through */
561
+ case ATTR_OP_SET:
562
+ error = mnt_want_write_file(parfilp);
563
+ if (error)
564
+ break;
565
+ error = xfs_attrmulti_attr_set(inode, name, value, *len, flags);
566
+ mnt_drop_write_file(parfilp);
567
+ break;
568
+ default:
569
+ error = -EINVAL;
570
+ break;
571
+ }
572
+
573
+ kfree(name);
499574 return error;
500575 }
501576
....@@ -509,7 +584,6 @@
509584 xfs_fsop_attrmulti_handlereq_t am_hreq;
510585 struct dentry *dentry;
511586 unsigned int i, size;
512
- unsigned char *attr_name;
513587
514588 if (!capable(CAP_SYS_ADMIN))
515589 return -EPERM;
....@@ -535,56 +609,17 @@
535609 goto out_dput;
536610 }
537611
538
- error = -ENOMEM;
539
- attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL);
540
- if (!attr_name)
541
- goto out_kfree_ops;
542
-
543612 error = 0;
544613 for (i = 0; i < am_hreq.opcount; i++) {
545
- ops[i].am_error = strncpy_from_user((char *)attr_name,
546
- ops[i].am_attrname, MAXNAMELEN);
547
- if (ops[i].am_error == 0 || ops[i].am_error == MAXNAMELEN)
548
- error = -ERANGE;
549
- if (ops[i].am_error < 0)
550
- break;
551
-
552
- switch (ops[i].am_opcode) {
553
- case ATTR_OP_GET:
554
- ops[i].am_error = xfs_attrmulti_attr_get(
555
- d_inode(dentry), attr_name,
556
- ops[i].am_attrvalue, &ops[i].am_length,
557
- ops[i].am_flags);
558
- break;
559
- case ATTR_OP_SET:
560
- ops[i].am_error = mnt_want_write_file(parfilp);
561
- if (ops[i].am_error)
562
- break;
563
- ops[i].am_error = xfs_attrmulti_attr_set(
564
- d_inode(dentry), attr_name,
565
- ops[i].am_attrvalue, ops[i].am_length,
566
- ops[i].am_flags);
567
- mnt_drop_write_file(parfilp);
568
- break;
569
- case ATTR_OP_REMOVE:
570
- ops[i].am_error = mnt_want_write_file(parfilp);
571
- if (ops[i].am_error)
572
- break;
573
- ops[i].am_error = xfs_attrmulti_attr_remove(
574
- d_inode(dentry), attr_name,
575
- ops[i].am_flags);
576
- mnt_drop_write_file(parfilp);
577
- break;
578
- default:
579
- ops[i].am_error = -EINVAL;
580
- }
614
+ ops[i].am_error = xfs_ioc_attrmulti_one(parfilp,
615
+ d_inode(dentry), ops[i].am_opcode,
616
+ ops[i].am_attrname, ops[i].am_attrvalue,
617
+ &ops[i].am_length, ops[i].am_flags);
581618 }
582619
583620 if (copy_to_user(am_hreq.ops, ops, size))
584621 error = -EFAULT;
585622
586
- kfree(attr_name);
587
- out_kfree_ops:
588623 kfree(ops);
589624 out_dput:
590625 dput(dentry);
....@@ -594,23 +629,14 @@
594629 int
595630 xfs_ioc_space(
596631 struct file *filp,
597
- unsigned int cmd,
598632 xfs_flock64_t *bf)
599633 {
600634 struct inode *inode = file_inode(filp);
601635 struct xfs_inode *ip = XFS_I(inode);
602636 struct iattr iattr;
603
- enum xfs_prealloc_flags flags = 0;
637
+ enum xfs_prealloc_flags flags = XFS_PREALLOC_CLEAR;
604638 uint iolock = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL;
605639 int error;
606
-
607
- /*
608
- * Only allow the sys admin to reserve space unless
609
- * unwritten extents are enabled.
610
- */
611
- if (!xfs_sb_version_hasextflgbit(&ip->i_mount->m_sb) &&
612
- !capable(CAP_SYS_ADMIN))
613
- return -EPERM;
614640
615641 if (inode->i_flags & (S_IMMUTABLE|S_APPEND))
616642 return -EPERM;
....@@ -620,6 +646,9 @@
620646
621647 if (!S_ISREG(inode->i_mode))
622648 return -EINVAL;
649
+
650
+ if (xfs_is_always_cow_inode(ip))
651
+ return -EOPNOTSUPP;
623652
624653 if (filp->f_flags & O_DSYNC)
625654 flags |= XFS_PREALLOC_SYNC;
....@@ -634,6 +663,7 @@
634663 error = xfs_break_layouts(inode, &iolock, BREAK_UNMAP);
635664 if (error)
636665 goto out_unlock;
666
+ inode_dio_wait(inode);
637667
638668 switch (bf->l_whence) {
639669 case 0: /*SEEK_SET*/
....@@ -649,74 +679,22 @@
649679 goto out_unlock;
650680 }
651681
652
- /*
653
- * length of <= 0 for resv/unresv/zero is invalid. length for
654
- * alloc/free is ignored completely and we have no idea what userspace
655
- * might have set it to, so set it to zero to allow range
656
- * checks to pass.
657
- */
658
- switch (cmd) {
659
- case XFS_IOC_ZERO_RANGE:
660
- case XFS_IOC_RESVSP:
661
- case XFS_IOC_RESVSP64:
662
- case XFS_IOC_UNRESVSP:
663
- case XFS_IOC_UNRESVSP64:
664
- if (bf->l_len <= 0) {
665
- error = -EINVAL;
666
- goto out_unlock;
667
- }
668
- break;
669
- default:
670
- bf->l_len = 0;
671
- break;
672
- }
673
-
674
- if (bf->l_start < 0 ||
675
- bf->l_start > inode->i_sb->s_maxbytes ||
676
- bf->l_start + bf->l_len < 0 ||
677
- bf->l_start + bf->l_len >= inode->i_sb->s_maxbytes) {
682
+ if (bf->l_start < 0 || bf->l_start > inode->i_sb->s_maxbytes) {
678683 error = -EINVAL;
679684 goto out_unlock;
680685 }
681686
682
- switch (cmd) {
683
- case XFS_IOC_ZERO_RANGE:
684
- flags |= XFS_PREALLOC_SET;
685
- error = xfs_zero_file_space(ip, bf->l_start, bf->l_len);
686
- break;
687
- case XFS_IOC_RESVSP:
688
- case XFS_IOC_RESVSP64:
689
- flags |= XFS_PREALLOC_SET;
690
- error = xfs_alloc_file_space(ip, bf->l_start, bf->l_len,
691
- XFS_BMAPI_PREALLOC);
692
- break;
693
- case XFS_IOC_UNRESVSP:
694
- case XFS_IOC_UNRESVSP64:
695
- error = xfs_free_file_space(ip, bf->l_start, bf->l_len);
696
- break;
697
- case XFS_IOC_ALLOCSP:
698
- case XFS_IOC_ALLOCSP64:
699
- case XFS_IOC_FREESP:
700
- case XFS_IOC_FREESP64:
701
- flags |= XFS_PREALLOC_CLEAR;
702
- if (bf->l_start > XFS_ISIZE(ip)) {
703
- error = xfs_alloc_file_space(ip, XFS_ISIZE(ip),
704
- bf->l_start - XFS_ISIZE(ip),
705
- XFS_BMAPI_PREALLOC);
706
- if (error)
707
- goto out_unlock;
708
- }
709
-
710
- iattr.ia_valid = ATTR_SIZE;
711
- iattr.ia_size = bf->l_start;
712
-
713
- error = xfs_vn_setattr_size(file_dentry(filp), &iattr);
714
- break;
715
- default:
716
- ASSERT(0);
717
- error = -EINVAL;
687
+ if (bf->l_start > XFS_ISIZE(ip)) {
688
+ error = xfs_alloc_file_space(ip, XFS_ISIZE(ip),
689
+ bf->l_start - XFS_ISIZE(ip),
690
+ XFS_BMAPI_PREALLOC);
691
+ if (error)
692
+ goto out_unlock;
718693 }
719694
695
+ iattr.ia_valid = ATTR_SIZE;
696
+ iattr.ia_size = bf->l_start;
697
+ error = xfs_vn_setattr_size(file_dentry(filp), &iattr);
720698 if (error)
721699 goto out_unlock;
722700
....@@ -728,16 +706,45 @@
728706 return error;
729707 }
730708
709
+/* Return 0 on success or positive error */
710
+int
711
+xfs_fsbulkstat_one_fmt(
712
+ struct xfs_ibulk *breq,
713
+ const struct xfs_bulkstat *bstat)
714
+{
715
+ struct xfs_bstat bs1;
716
+
717
+ xfs_bulkstat_to_bstat(breq->mp, &bs1, bstat);
718
+ if (copy_to_user(breq->ubuffer, &bs1, sizeof(bs1)))
719
+ return -EFAULT;
720
+ return xfs_ibulk_advance(breq, sizeof(struct xfs_bstat));
721
+}
722
+
723
+int
724
+xfs_fsinumbers_fmt(
725
+ struct xfs_ibulk *breq,
726
+ const struct xfs_inumbers *igrp)
727
+{
728
+ struct xfs_inogrp ig1;
729
+
730
+ xfs_inumbers_to_inogrp(&ig1, igrp);
731
+ if (copy_to_user(breq->ubuffer, &ig1, sizeof(struct xfs_inogrp)))
732
+ return -EFAULT;
733
+ return xfs_ibulk_advance(breq, sizeof(struct xfs_inogrp));
734
+}
735
+
731736 STATIC int
732
-xfs_ioc_bulkstat(
737
+xfs_ioc_fsbulkstat(
733738 xfs_mount_t *mp,
734739 unsigned int cmd,
735740 void __user *arg)
736741 {
737
- xfs_fsop_bulkreq_t bulkreq;
738
- int count; /* # of records returned */
739
- xfs_ino_t inlast; /* last inode number */
740
- int done;
742
+ struct xfs_fsop_bulkreq bulkreq;
743
+ struct xfs_ibulk breq = {
744
+ .mp = mp,
745
+ .ocount = 0,
746
+ };
747
+ xfs_ino_t lastino;
741748 int error;
742749
743750 /* done = 1 if there are more stats to get and if bulkstat */
....@@ -749,79 +756,291 @@
749756 if (XFS_FORCED_SHUTDOWN(mp))
750757 return -EIO;
751758
752
- if (copy_from_user(&bulkreq, arg, sizeof(xfs_fsop_bulkreq_t)))
759
+ if (copy_from_user(&bulkreq, arg, sizeof(struct xfs_fsop_bulkreq)))
753760 return -EFAULT;
754761
755
- if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64)))
762
+ if (copy_from_user(&lastino, bulkreq.lastip, sizeof(__s64)))
756763 return -EFAULT;
757764
758
- if ((count = bulkreq.icount) <= 0)
765
+ if (bulkreq.icount <= 0)
759766 return -EINVAL;
760767
761768 if (bulkreq.ubuffer == NULL)
762769 return -EINVAL;
763770
764
- if (cmd == XFS_IOC_FSINUMBERS)
765
- error = xfs_inumbers(mp, &inlast, &count,
766
- bulkreq.ubuffer, xfs_inumbers_fmt);
767
- else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE)
768
- error = xfs_bulkstat_one(mp, inlast, bulkreq.ubuffer,
769
- sizeof(xfs_bstat_t), NULL, &done);
770
- else /* XFS_IOC_FSBULKSTAT */
771
- error = xfs_bulkstat(mp, &inlast, &count, xfs_bulkstat_one,
772
- sizeof(xfs_bstat_t), bulkreq.ubuffer,
773
- &done);
771
+ breq.ubuffer = bulkreq.ubuffer;
772
+ breq.icount = bulkreq.icount;
773
+
774
+ /*
775
+ * FSBULKSTAT_SINGLE expects that *lastip contains the inode number
776
+ * that we want to stat. However, FSINUMBERS and FSBULKSTAT expect
777
+ * that *lastip contains either zero or the number of the last inode to
778
+ * be examined by the previous call and return results starting with
779
+ * the next inode after that. The new bulk request back end functions
780
+ * take the inode to start with, so we have to compute the startino
781
+ * parameter from lastino to maintain correct function. lastino == 0
782
+ * is a special case because it has traditionally meant "first inode
783
+ * in filesystem".
784
+ */
785
+ if (cmd == XFS_IOC_FSINUMBERS) {
786
+ breq.startino = lastino ? lastino + 1 : 0;
787
+ error = xfs_inumbers(&breq, xfs_fsinumbers_fmt);
788
+ lastino = breq.startino - 1;
789
+ } else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE) {
790
+ breq.startino = lastino;
791
+ breq.icount = 1;
792
+ error = xfs_bulkstat_one(&breq, xfs_fsbulkstat_one_fmt);
793
+ } else { /* XFS_IOC_FSBULKSTAT */
794
+ breq.startino = lastino ? lastino + 1 : 0;
795
+ error = xfs_bulkstat(&breq, xfs_fsbulkstat_one_fmt);
796
+ lastino = breq.startino - 1;
797
+ }
774798
775799 if (error)
776800 return error;
777801
778
- if (bulkreq.ocount != NULL) {
779
- if (copy_to_user(bulkreq.lastip, &inlast,
780
- sizeof(xfs_ino_t)))
781
- return -EFAULT;
802
+ if (bulkreq.lastip != NULL &&
803
+ copy_to_user(bulkreq.lastip, &lastino, sizeof(xfs_ino_t)))
804
+ return -EFAULT;
782805
783
- if (copy_to_user(bulkreq.ocount, &count, sizeof(count)))
784
- return -EFAULT;
806
+ if (bulkreq.ocount != NULL &&
807
+ copy_to_user(bulkreq.ocount, &breq.ocount, sizeof(__s32)))
808
+ return -EFAULT;
809
+
810
+ return 0;
811
+}
812
+
813
+/* Return 0 on success or positive error */
814
+static int
815
+xfs_bulkstat_fmt(
816
+ struct xfs_ibulk *breq,
817
+ const struct xfs_bulkstat *bstat)
818
+{
819
+ if (copy_to_user(breq->ubuffer, bstat, sizeof(struct xfs_bulkstat)))
820
+ return -EFAULT;
821
+ return xfs_ibulk_advance(breq, sizeof(struct xfs_bulkstat));
822
+}
823
+
824
+/*
825
+ * Check the incoming bulk request @hdr from userspace and initialize the
826
+ * internal @breq bulk request appropriately. Returns 0 if the bulk request
827
+ * should proceed; -ECANCELED if there's nothing to do; or the usual
828
+ * negative error code.
829
+ */
830
+static int
831
+xfs_bulk_ireq_setup(
832
+ struct xfs_mount *mp,
833
+ struct xfs_bulk_ireq *hdr,
834
+ struct xfs_ibulk *breq,
835
+ void __user *ubuffer)
836
+{
837
+ if (hdr->icount == 0 ||
838
+ (hdr->flags & ~XFS_BULK_IREQ_FLAGS_ALL) ||
839
+ memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
840
+ return -EINVAL;
841
+
842
+ breq->startino = hdr->ino;
843
+ breq->ubuffer = ubuffer;
844
+ breq->icount = hdr->icount;
845
+ breq->ocount = 0;
846
+ breq->flags = 0;
847
+
848
+ /*
849
+ * The @ino parameter is a special value, so we must look it up here.
850
+ * We're not allowed to have IREQ_AGNO, and we only return one inode
851
+ * worth of data.
852
+ */
853
+ if (hdr->flags & XFS_BULK_IREQ_SPECIAL) {
854
+ if (hdr->flags & XFS_BULK_IREQ_AGNO)
855
+ return -EINVAL;
856
+
857
+ switch (hdr->ino) {
858
+ case XFS_BULK_IREQ_SPECIAL_ROOT:
859
+ hdr->ino = mp->m_sb.sb_rootino;
860
+ break;
861
+ default:
862
+ return -EINVAL;
863
+ }
864
+ breq->icount = 1;
785865 }
866
+
867
+ /*
868
+ * The IREQ_AGNO flag means that we only want results from a given AG.
869
+ * If @hdr->ino is zero, we start iterating in that AG. If @hdr->ino is
870
+ * beyond the specified AG then we return no results.
871
+ */
872
+ if (hdr->flags & XFS_BULK_IREQ_AGNO) {
873
+ if (hdr->agno >= mp->m_sb.sb_agcount)
874
+ return -EINVAL;
875
+
876
+ if (breq->startino == 0)
877
+ breq->startino = XFS_AGINO_TO_INO(mp, hdr->agno, 0);
878
+ else if (XFS_INO_TO_AGNO(mp, breq->startino) < hdr->agno)
879
+ return -EINVAL;
880
+
881
+ breq->flags |= XFS_IBULK_SAME_AG;
882
+
883
+ /* Asking for an inode past the end of the AG? We're done! */
884
+ if (XFS_INO_TO_AGNO(mp, breq->startino) > hdr->agno)
885
+ return -ECANCELED;
886
+ } else if (hdr->agno)
887
+ return -EINVAL;
888
+
889
+ /* Asking for an inode past the end of the FS? We're done! */
890
+ if (XFS_INO_TO_AGNO(mp, breq->startino) >= mp->m_sb.sb_agcount)
891
+ return -ECANCELED;
892
+
893
+ return 0;
894
+}
895
+
896
+/*
897
+ * Update the userspace bulk request @hdr to reflect the end state of the
898
+ * internal bulk request @breq.
899
+ */
900
+static void
901
+xfs_bulk_ireq_teardown(
902
+ struct xfs_bulk_ireq *hdr,
903
+ struct xfs_ibulk *breq)
904
+{
905
+ hdr->ino = breq->startino;
906
+ hdr->ocount = breq->ocount;
907
+}
908
+
909
+/* Handle the v5 bulkstat ioctl. */
910
+STATIC int
911
+xfs_ioc_bulkstat(
912
+ struct xfs_mount *mp,
913
+ unsigned int cmd,
914
+ struct xfs_bulkstat_req __user *arg)
915
+{
916
+ struct xfs_bulk_ireq hdr;
917
+ struct xfs_ibulk breq = {
918
+ .mp = mp,
919
+ };
920
+ int error;
921
+
922
+ if (!capable(CAP_SYS_ADMIN))
923
+ return -EPERM;
924
+
925
+ if (XFS_FORCED_SHUTDOWN(mp))
926
+ return -EIO;
927
+
928
+ if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))
929
+ return -EFAULT;
930
+
931
+ error = xfs_bulk_ireq_setup(mp, &hdr, &breq, arg->bulkstat);
932
+ if (error == -ECANCELED)
933
+ goto out_teardown;
934
+ if (error < 0)
935
+ return error;
936
+
937
+ error = xfs_bulkstat(&breq, xfs_bulkstat_fmt);
938
+ if (error)
939
+ return error;
940
+
941
+out_teardown:
942
+ xfs_bulk_ireq_teardown(&hdr, &breq);
943
+ if (copy_to_user(&arg->hdr, &hdr, sizeof(hdr)))
944
+ return -EFAULT;
786945
787946 return 0;
788947 }
789948
790949 STATIC int
791
-xfs_ioc_fsgeometry_v1(
792
- xfs_mount_t *mp,
793
- void __user *arg)
950
+xfs_inumbers_fmt(
951
+ struct xfs_ibulk *breq,
952
+ const struct xfs_inumbers *igrp)
794953 {
795
- xfs_fsop_geom_t fsgeo;
796
- int error;
954
+ if (copy_to_user(breq->ubuffer, igrp, sizeof(struct xfs_inumbers)))
955
+ return -EFAULT;
956
+ return xfs_ibulk_advance(breq, sizeof(struct xfs_inumbers));
957
+}
797958
798
- error = xfs_fs_geometry(&mp->m_sb, &fsgeo, 3);
959
+/* Handle the v5 inumbers ioctl. */
960
+STATIC int
961
+xfs_ioc_inumbers(
962
+ struct xfs_mount *mp,
963
+ unsigned int cmd,
964
+ struct xfs_inumbers_req __user *arg)
965
+{
966
+ struct xfs_bulk_ireq hdr;
967
+ struct xfs_ibulk breq = {
968
+ .mp = mp,
969
+ };
970
+ int error;
971
+
972
+ if (!capable(CAP_SYS_ADMIN))
973
+ return -EPERM;
974
+
975
+ if (XFS_FORCED_SHUTDOWN(mp))
976
+ return -EIO;
977
+
978
+ if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))
979
+ return -EFAULT;
980
+
981
+ error = xfs_bulk_ireq_setup(mp, &hdr, &breq, arg->inumbers);
982
+ if (error == -ECANCELED)
983
+ goto out_teardown;
984
+ if (error < 0)
985
+ return error;
986
+
987
+ error = xfs_inumbers(&breq, xfs_inumbers_fmt);
799988 if (error)
800989 return error;
801990
802
- /*
803
- * Caller should have passed an argument of type
804
- * xfs_fsop_geom_v1_t. This is a proper subset of the
805
- * xfs_fsop_geom_t that xfs_fs_geometry() fills in.
806
- */
807
- if (copy_to_user(arg, &fsgeo, sizeof(xfs_fsop_geom_v1_t)))
991
+out_teardown:
992
+ xfs_bulk_ireq_teardown(&hdr, &breq);
993
+ if (copy_to_user(&arg->hdr, &hdr, sizeof(hdr)))
808994 return -EFAULT;
995
+
809996 return 0;
810997 }
811998
812999 STATIC int
8131000 xfs_ioc_fsgeometry(
814
- xfs_mount_t *mp,
1001
+ struct xfs_mount *mp,
1002
+ void __user *arg,
1003
+ int struct_version)
1004
+{
1005
+ struct xfs_fsop_geom fsgeo;
1006
+ size_t len;
1007
+
1008
+ xfs_fs_geometry(&mp->m_sb, &fsgeo, struct_version);
1009
+
1010
+ if (struct_version <= 3)
1011
+ len = sizeof(struct xfs_fsop_geom_v1);
1012
+ else if (struct_version == 4)
1013
+ len = sizeof(struct xfs_fsop_geom_v4);
1014
+ else {
1015
+ xfs_fsop_geom_health(mp, &fsgeo);
1016
+ len = sizeof(fsgeo);
1017
+ }
1018
+
1019
+ if (copy_to_user(arg, &fsgeo, len))
1020
+ return -EFAULT;
1021
+ return 0;
1022
+}
1023
+
1024
+STATIC int
1025
+xfs_ioc_ag_geometry(
1026
+ struct xfs_mount *mp,
8151027 void __user *arg)
8161028 {
817
- xfs_fsop_geom_t fsgeo;
1029
+ struct xfs_ag_geometry ageo;
8181030 int error;
8191031
820
- error = xfs_fs_geometry(&mp->m_sb, &fsgeo, 4);
1032
+ if (copy_from_user(&ageo, arg, sizeof(ageo)))
1033
+ return -EFAULT;
1034
+ if (ageo.ag_flags)
1035
+ return -EINVAL;
1036
+ if (memchr_inv(&ageo.ag_reserved, 0, sizeof(ageo.ag_reserved)))
1037
+ return -EINVAL;
1038
+
1039
+ error = xfs_ag_get_geometry(mp, ageo.ag_number, &ageo);
8211040 if (error)
8221041 return error;
8231042
824
- if (copy_to_user(arg, &fsgeo, sizeof(fsgeo)))
1043
+ if (copy_to_user(arg, &ageo, sizeof(ageo)))
8251044 return -EFAULT;
8261045 return 0;
8271046 }
....@@ -857,13 +1076,18 @@
8571076 xflags |= FS_XFLAG_NODUMP;
8581077 else
8591078 xflags &= ~FS_XFLAG_NODUMP;
1079
+ if (flags & FS_DAX_FL)
1080
+ xflags |= FS_XFLAG_DAX;
1081
+ else
1082
+ xflags &= ~FS_XFLAG_DAX;
8601083
8611084 return xflags;
8621085 }
8631086
8641087 STATIC unsigned int
8651088 xfs_di2lxflags(
866
- uint16_t di_flags)
1089
+ uint16_t di_flags,
1090
+ uint64_t di_flags2)
8671091 {
8681092 unsigned int flags = 0;
8691093
....@@ -877,7 +1101,29 @@
8771101 flags |= FS_NOATIME_FL;
8781102 if (di_flags & XFS_DIFLAG_NODUMP)
8791103 flags |= FS_NODUMP_FL;
1104
+ if (di_flags2 & XFS_DIFLAG2_DAX) {
1105
+ flags |= FS_DAX_FL;
1106
+ }
8801107 return flags;
1108
+}
1109
+
1110
+static void
1111
+xfs_fill_fsxattr(
1112
+ struct xfs_inode *ip,
1113
+ bool attr,
1114
+ struct fsxattr *fa)
1115
+{
1116
+ struct xfs_ifork *ifp = attr ? ip->i_afp : &ip->i_df;
1117
+
1118
+ simple_fill_fsxattr(fa, xfs_ip2xflags(ip));
1119
+ fa->fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
1120
+ fa->fsx_cowextsize = ip->i_d.di_cowextsize <<
1121
+ ip->i_mount->m_sb.sb_blocklog;
1122
+ fa->fsx_projid = ip->i_d.di_projid;
1123
+ if (ifp && (ifp->if_flags & XFS_IFEXTENTS))
1124
+ fa->fsx_nextents = xfs_iext_count(ifp);
1125
+ else
1126
+ fa->fsx_nextents = xfs_ifork_nextents(ifp);
8811127 }
8821128
8831129 STATIC int
....@@ -888,29 +1134,8 @@
8881134 {
8891135 struct fsxattr fa;
8901136
891
- memset(&fa, 0, sizeof(struct fsxattr));
892
-
8931137 xfs_ilock(ip, XFS_ILOCK_SHARED);
894
- fa.fsx_xflags = xfs_ip2xflags(ip);
895
- fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
896
- fa.fsx_cowextsize = ip->i_d.di_cowextsize <<
897
- ip->i_mount->m_sb.sb_blocklog;
898
- fa.fsx_projid = xfs_get_projid(ip);
899
-
900
- if (attr) {
901
- if (ip->i_afp) {
902
- if (ip->i_afp->if_flags & XFS_IFEXTENTS)
903
- fa.fsx_nextents = xfs_iext_count(ip->i_afp);
904
- else
905
- fa.fsx_nextents = ip->i_d.di_anextents;
906
- } else
907
- fa.fsx_nextents = 0;
908
- } else {
909
- if (ip->i_df.if_flags & XFS_IFEXTENTS)
910
- fa.fsx_nextents = xfs_iext_count(&ip->i_df);
911
- else
912
- fa.fsx_nextents = ip->i_d.di_nextents;
913
- }
1138
+ xfs_fill_fsxattr(ip, attr, &fa);
9141139 xfs_iunlock(ip, XFS_ILOCK_SHARED);
9151140
9161141 if (copy_to_user(arg, &fa, sizeof(fa)))
....@@ -966,7 +1191,8 @@
9661191 unsigned int xflags)
9671192 {
9681193 uint64_t di_flags2 =
969
- (ip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK);
1194
+ (ip->i_d.di_flags2 & (XFS_DIFLAG2_REFLINK |
1195
+ XFS_DIFLAG2_BIGTIME));
9701196
9711197 if (xflags & FS_XFLAG_DAX)
9721198 di_flags2 |= XFS_DIFLAG2_DAX;
....@@ -974,37 +1200,6 @@
9741200 di_flags2 |= XFS_DIFLAG2_COWEXTSIZE;
9751201
9761202 return di_flags2;
977
-}
978
-
979
-STATIC void
980
-xfs_diflags_to_linux(
981
- struct xfs_inode *ip)
982
-{
983
- struct inode *inode = VFS_I(ip);
984
- unsigned int xflags = xfs_ip2xflags(ip);
985
-
986
- if (xflags & FS_XFLAG_IMMUTABLE)
987
- inode->i_flags |= S_IMMUTABLE;
988
- else
989
- inode->i_flags &= ~S_IMMUTABLE;
990
- if (xflags & FS_XFLAG_APPEND)
991
- inode->i_flags |= S_APPEND;
992
- else
993
- inode->i_flags &= ~S_APPEND;
994
- if (xflags & FS_XFLAG_SYNC)
995
- inode->i_flags |= S_SYNC;
996
- else
997
- inode->i_flags &= ~S_SYNC;
998
- if (xflags & FS_XFLAG_NOATIME)
999
- inode->i_flags |= S_NOATIME;
1000
- else
1001
- inode->i_flags &= ~S_NOATIME;
1002
-#if 0 /* disabled until the flag switching races are sorted out */
1003
- if (xflags & FS_XFLAG_DAX)
1004
- inode->i_flags |= S_DAX;
1005
- else
1006
- inode->i_flags &= ~S_DAX;
1007
-#endif
10081203 }
10091204
10101205 static int
....@@ -1017,7 +1212,7 @@
10171212 uint64_t di_flags2;
10181213
10191214 /* Can't change realtime flag if any extents are allocated. */
1020
- if ((ip->i_d.di_nextents || ip->i_delayed_blks) &&
1215
+ if ((ip->i_df.if_nextents || ip->i_delayed_blks) &&
10211216 XFS_IS_REALTIME_INODE(ip) != (fa->fsx_xflags & FS_XFLAG_REALTIME))
10221217 return -EINVAL;
10231218
....@@ -1036,90 +1231,41 @@
10361231 if ((fa->fsx_xflags & FS_XFLAG_DAX) && xfs_is_reflink_inode(ip))
10371232 return -EINVAL;
10381233
1039
- /*
1040
- * Can't modify an immutable/append-only file unless
1041
- * we have appropriate permission.
1042
- */
1043
- if (((ip->i_d.di_flags & (XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND)) ||
1044
- (fa->fsx_xflags & (FS_XFLAG_IMMUTABLE | FS_XFLAG_APPEND))) &&
1045
- !capable(CAP_LINUX_IMMUTABLE))
1046
- return -EPERM;
1047
-
10481234 /* diflags2 only valid for v3 inodes. */
10491235 di_flags2 = xfs_flags2diflags2(ip, fa->fsx_xflags);
1050
- if (di_flags2 && ip->i_d.di_version < 3)
1236
+ if (di_flags2 && !xfs_sb_version_has_v3inode(&mp->m_sb))
10511237 return -EINVAL;
10521238
10531239 ip->i_d.di_flags = xfs_flags2diflags(ip, fa->fsx_xflags);
10541240 ip->i_d.di_flags2 = di_flags2;
10551241
1056
- xfs_diflags_to_linux(ip);
1242
+ xfs_diflags_to_iflags(ip, false);
10571243 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
10581244 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
10591245 XFS_STATS_INC(mp, xs_ig_attrchg);
10601246 return 0;
10611247 }
10621248
1063
-/*
1064
- * If we are changing DAX flags, we have to ensure the file is clean and any
1065
- * cached objects in the address space are invalidated and removed. This
1066
- * requires us to lock out other IO and page faults similar to a truncate
1067
- * operation. The locks need to be held until the transaction has been committed
1068
- * so that the cache invalidation is atomic with respect to the DAX flag
1069
- * manipulation.
1070
- */
1071
-static int
1072
-xfs_ioctl_setattr_dax_invalidate(
1249
+static void
1250
+xfs_ioctl_setattr_prepare_dax(
10731251 struct xfs_inode *ip,
1074
- struct fsxattr *fa,
1075
- int *join_flags)
1252
+ struct fsxattr *fa)
10761253 {
1077
- struct inode *inode = VFS_I(ip);
1078
- struct super_block *sb = inode->i_sb;
1079
- int error;
1080
-
1081
- *join_flags = 0;
1082
-
1083
- /*
1084
- * It is only valid to set the DAX flag on regular files and
1085
- * directories on filesystems where the block size is equal to the page
1086
- * size. On directories it serves as an inherited hint so we don't
1087
- * have to check the device for dax support or flush pagecache.
1088
- */
1089
- if (fa->fsx_xflags & FS_XFLAG_DAX) {
1090
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
1091
- return -EINVAL;
1092
- if (S_ISREG(inode->i_mode) &&
1093
- !bdev_dax_supported(xfs_find_bdev_for_inode(VFS_I(ip)),
1094
- sb->s_blocksize))
1095
- return -EINVAL;
1096
- }
1097
-
1098
- /* If the DAX state is not changing, we have nothing to do here. */
1099
- if ((fa->fsx_xflags & FS_XFLAG_DAX) && IS_DAX(inode))
1100
- return 0;
1101
- if (!(fa->fsx_xflags & FS_XFLAG_DAX) && !IS_DAX(inode))
1102
- return 0;
1254
+ struct xfs_mount *mp = ip->i_mount;
1255
+ struct inode *inode = VFS_I(ip);
11031256
11041257 if (S_ISDIR(inode->i_mode))
1105
- return 0;
1258
+ return;
11061259
1107
- /* lock, flush and invalidate mapping in preparation for flag change */
1108
- xfs_ilock(ip, XFS_MMAPLOCK_EXCL | XFS_IOLOCK_EXCL);
1109
- error = filemap_write_and_wait(inode->i_mapping);
1110
- if (error)
1111
- goto out_unlock;
1112
- error = invalidate_inode_pages2(inode->i_mapping);
1113
- if (error)
1114
- goto out_unlock;
1260
+ if ((mp->m_flags & XFS_MOUNT_DAX_ALWAYS) ||
1261
+ (mp->m_flags & XFS_MOUNT_DAX_NEVER))
1262
+ return;
11151263
1116
- *join_flags = XFS_MMAPLOCK_EXCL | XFS_IOLOCK_EXCL;
1117
- return 0;
1118
-
1119
-out_unlock:
1120
- xfs_iunlock(ip, XFS_MMAPLOCK_EXCL | XFS_IOLOCK_EXCL);
1121
- return error;
1122
-
1264
+ if (((fa->fsx_xflags & FS_XFLAG_DAX) &&
1265
+ !(ip->i_d.di_flags2 & XFS_DIFLAG2_DAX)) ||
1266
+ (!(fa->fsx_xflags & FS_XFLAG_DAX) &&
1267
+ (ip->i_d.di_flags2 & XFS_DIFLAG2_DAX)))
1268
+ d_mark_dontcache(inode);
11231269 }
11241270
11251271 /*
....@@ -1127,17 +1273,10 @@
11271273 * have permission to do so. On success, return a clean transaction and the
11281274 * inode locked exclusively ready for further operation specific checks. On
11291275 * failure, return an error without modifying or locking the inode.
1130
- *
1131
- * The inode might already be IO locked on call. If this is the case, it is
1132
- * indicated in @join_flags and we take full responsibility for ensuring they
1133
- * are unlocked from now on. Hence if we have an error here, we still have to
1134
- * unlock them. Otherwise, once they are joined to the transaction, they will
1135
- * be unlocked on commit/cancel.
11361276 */
11371277 static struct xfs_trans *
11381278 xfs_ioctl_setattr_get_trans(
1139
- struct xfs_inode *ip,
1140
- int join_flags)
1279
+ struct xfs_inode *ip)
11411280 {
11421281 struct xfs_mount *mp = ip->i_mount;
11431282 struct xfs_trans *tp;
....@@ -1151,11 +1290,10 @@
11511290
11521291 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp);
11531292 if (error)
1154
- return ERR_PTR(error);
1293
+ goto out_unlock;
11551294
11561295 xfs_ilock(ip, XFS_ILOCK_EXCL);
1157
- xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL | join_flags);
1158
- join_flags = 0;
1296
+ xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
11591297
11601298 /*
11611299 * CAP_FOWNER overrides the following restrictions:
....@@ -1176,8 +1314,6 @@
11761314 out_cancel:
11771315 xfs_trans_cancel(tp);
11781316 out_unlock:
1179
- if (join_flags)
1180
- xfs_iunlock(ip, join_flags);
11811317 return ERR_PTR(error);
11821318 }
11831319
....@@ -1203,39 +1339,31 @@
12031339 struct fsxattr *fa)
12041340 {
12051341 struct xfs_mount *mp = ip->i_mount;
1342
+ xfs_extlen_t size;
1343
+ xfs_fsblock_t extsize_fsb;
12061344
1207
- if ((fa->fsx_xflags & FS_XFLAG_EXTSIZE) && !S_ISREG(VFS_I(ip)->i_mode))
1208
- return -EINVAL;
1209
-
1210
- if ((fa->fsx_xflags & FS_XFLAG_EXTSZINHERIT) &&
1211
- !S_ISDIR(VFS_I(ip)->i_mode))
1212
- return -EINVAL;
1213
-
1214
- if (S_ISREG(VFS_I(ip)->i_mode) && ip->i_d.di_nextents &&
1345
+ if (S_ISREG(VFS_I(ip)->i_mode) && ip->i_df.if_nextents &&
12151346 ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) != fa->fsx_extsize))
12161347 return -EINVAL;
12171348
1218
- if (fa->fsx_extsize != 0) {
1219
- xfs_extlen_t size;
1220
- xfs_fsblock_t extsize_fsb;
1349
+ if (fa->fsx_extsize == 0)
1350
+ return 0;
12211351
1222
- extsize_fsb = XFS_B_TO_FSB(mp, fa->fsx_extsize);
1223
- if (extsize_fsb > MAXEXTLEN)
1352
+ extsize_fsb = XFS_B_TO_FSB(mp, fa->fsx_extsize);
1353
+ if (extsize_fsb > MAXEXTLEN)
1354
+ return -EINVAL;
1355
+
1356
+ if (XFS_IS_REALTIME_INODE(ip) ||
1357
+ (fa->fsx_xflags & FS_XFLAG_REALTIME)) {
1358
+ size = mp->m_sb.sb_rextsize << mp->m_sb.sb_blocklog;
1359
+ } else {
1360
+ size = mp->m_sb.sb_blocksize;
1361
+ if (extsize_fsb > mp->m_sb.sb_agblocks / 2)
12241362 return -EINVAL;
1363
+ }
12251364
1226
- if (XFS_IS_REALTIME_INODE(ip) ||
1227
- (fa->fsx_xflags & FS_XFLAG_REALTIME)) {
1228
- size = mp->m_sb.sb_rextsize << mp->m_sb.sb_blocklog;
1229
- } else {
1230
- size = mp->m_sb.sb_blocksize;
1231
- if (extsize_fsb > mp->m_sb.sb_agblocks / 2)
1232
- return -EINVAL;
1233
- }
1234
-
1235
- if (fa->fsx_extsize % size)
1236
- return -EINVAL;
1237
- } else
1238
- fa->fsx_xflags &= ~(FS_XFLAG_EXTSIZE | FS_XFLAG_EXTSZINHERIT);
1365
+ if (fa->fsx_extsize % size)
1366
+ return -EINVAL;
12391367
12401368 return 0;
12411369 }
....@@ -1261,33 +1389,28 @@
12611389 struct fsxattr *fa)
12621390 {
12631391 struct xfs_mount *mp = ip->i_mount;
1392
+ xfs_extlen_t size;
1393
+ xfs_fsblock_t cowextsize_fsb;
12641394
12651395 if (!(fa->fsx_xflags & FS_XFLAG_COWEXTSIZE))
12661396 return 0;
12671397
1268
- if (!xfs_sb_version_hasreflink(&ip->i_mount->m_sb) ||
1269
- ip->i_d.di_version != 3)
1398
+ if (!xfs_sb_version_hasreflink(&ip->i_mount->m_sb))
12701399 return -EINVAL;
12711400
1272
- if (!S_ISREG(VFS_I(ip)->i_mode) && !S_ISDIR(VFS_I(ip)->i_mode))
1401
+ if (fa->fsx_cowextsize == 0)
1402
+ return 0;
1403
+
1404
+ cowextsize_fsb = XFS_B_TO_FSB(mp, fa->fsx_cowextsize);
1405
+ if (cowextsize_fsb > MAXEXTLEN)
12731406 return -EINVAL;
12741407
1275
- if (fa->fsx_cowextsize != 0) {
1276
- xfs_extlen_t size;
1277
- xfs_fsblock_t cowextsize_fsb;
1408
+ size = mp->m_sb.sb_blocksize;
1409
+ if (cowextsize_fsb > mp->m_sb.sb_agblocks / 2)
1410
+ return -EINVAL;
12781411
1279
- cowextsize_fsb = XFS_B_TO_FSB(mp, fa->fsx_cowextsize);
1280
- if (cowextsize_fsb > MAXEXTLEN)
1281
- return -EINVAL;
1282
-
1283
- size = mp->m_sb.sb_blocksize;
1284
- if (cowextsize_fsb > mp->m_sb.sb_agblocks / 2)
1285
- return -EINVAL;
1286
-
1287
- if (fa->fsx_cowextsize % size)
1288
- return -EINVAL;
1289
- } else
1290
- fa->fsx_xflags &= ~FS_XFLAG_COWEXTSIZE;
1412
+ if (fa->fsx_cowextsize % size)
1413
+ return -EINVAL;
12911414
12921415 return 0;
12931416 }
....@@ -1301,21 +1424,6 @@
13011424 if (fa->fsx_projid > (uint16_t)-1 &&
13021425 !xfs_sb_version_hasprojid32bit(&ip->i_mount->m_sb))
13031426 return -EINVAL;
1304
-
1305
- /*
1306
- * Project Quota ID state is only allowed to change from within the init
1307
- * namespace. Enforce that restriction only if we are trying to change
1308
- * the quota ID state. Everything else is allowed in user namespaces.
1309
- */
1310
- if (current_user_ns() == &init_user_ns)
1311
- return 0;
1312
-
1313
- if (xfs_get_projid(ip) != fa->fsx_projid)
1314
- return -EINVAL;
1315
- if ((fa->fsx_xflags & FS_XFLAG_PROJINHERIT) !=
1316
- (ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT))
1317
- return -EINVAL;
1318
-
13191427 return 0;
13201428 }
13211429
....@@ -1324,13 +1432,12 @@
13241432 xfs_inode_t *ip,
13251433 struct fsxattr *fa)
13261434 {
1435
+ struct fsxattr old_fa;
13271436 struct xfs_mount *mp = ip->i_mount;
13281437 struct xfs_trans *tp;
1329
- struct xfs_dquot *udqp = NULL;
13301438 struct xfs_dquot *pdqp = NULL;
13311439 struct xfs_dquot *olddquot = NULL;
13321440 int code;
1333
- int join_flags = 0;
13341441
13351442 trace_xfs_ioctl_setattr(ip);
13361443
....@@ -1347,38 +1454,33 @@
13471454 * because the i_*dquot fields will get updated anyway.
13481455 */
13491456 if (XFS_IS_QUOTA_ON(mp)) {
1350
- code = xfs_qm_vop_dqalloc(ip, ip->i_d.di_uid,
1351
- ip->i_d.di_gid, fa->fsx_projid,
1352
- XFS_QMOPT_PQUOTA, &udqp, NULL, &pdqp);
1457
+ code = xfs_qm_vop_dqalloc(ip, VFS_I(ip)->i_uid,
1458
+ VFS_I(ip)->i_gid, fa->fsx_projid,
1459
+ XFS_QMOPT_PQUOTA, NULL, NULL, &pdqp);
13531460 if (code)
13541461 return code;
13551462 }
13561463
1357
- /*
1358
- * Changing DAX config may require inode locking for mapping
1359
- * invalidation. These need to be held all the way to transaction commit
1360
- * or cancel time, so need to be passed through to
1361
- * xfs_ioctl_setattr_get_trans() so it can apply them to the join call
1362
- * appropriately.
1363
- */
1364
- code = xfs_ioctl_setattr_dax_invalidate(ip, fa, &join_flags);
1365
- if (code)
1366
- goto error_free_dquots;
1464
+ xfs_ioctl_setattr_prepare_dax(ip, fa);
13671465
1368
- tp = xfs_ioctl_setattr_get_trans(ip, join_flags);
1466
+ tp = xfs_ioctl_setattr_get_trans(ip);
13691467 if (IS_ERR(tp)) {
13701468 code = PTR_ERR(tp);
13711469 goto error_free_dquots;
13721470 }
13731471
1374
-
13751472 if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp) &&
1376
- xfs_get_projid(ip) != fa->fsx_projid) {
1377
- code = xfs_qm_vop_chown_reserve(tp, ip, udqp, NULL, pdqp,
1473
+ ip->i_d.di_projid != fa->fsx_projid) {
1474
+ code = xfs_qm_vop_chown_reserve(tp, ip, NULL, NULL, pdqp,
13781475 capable(CAP_FOWNER) ? XFS_QMOPT_FORCE_RES : 0);
13791476 if (code) /* out of quota */
13801477 goto error_trans_cancel;
13811478 }
1479
+
1480
+ xfs_fill_fsxattr(ip, false, &old_fa);
1481
+ code = vfs_ioc_fssetxattr_check(VFS_I(ip), &old_fa, fa);
1482
+ if (code)
1483
+ goto error_trans_cancel;
13821484
13831485 code = xfs_ioctl_setattr_check_extsize(ip, fa);
13841486 if (code)
....@@ -1405,13 +1507,12 @@
14051507 VFS_I(ip)->i_mode &= ~(S_ISUID|S_ISGID);
14061508
14071509 /* Change the ownerships and register project quota modifications */
1408
- if (xfs_get_projid(ip) != fa->fsx_projid) {
1510
+ if (ip->i_d.di_projid != fa->fsx_projid) {
14091511 if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) {
14101512 olddquot = xfs_qm_vop_chown(tp, ip,
14111513 &ip->i_pdquot, pdqp);
14121514 }
1413
- ASSERT(ip->i_d.di_version > 1);
1414
- xfs_set_projid(ip, fa->fsx_projid);
1515
+ ip->i_d.di_projid = fa->fsx_projid;
14151516 }
14161517
14171518 /*
....@@ -1423,7 +1524,7 @@
14231524 ip->i_d.di_extsize = fa->fsx_extsize >> mp->m_sb.sb_blocklog;
14241525 else
14251526 ip->i_d.di_extsize = 0;
1426
- if (ip->i_d.di_version == 3 &&
1527
+ if (xfs_sb_version_has_v3inode(&mp->m_sb) &&
14271528 (ip->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE))
14281529 ip->i_d.di_cowextsize = fa->fsx_cowextsize >>
14291530 mp->m_sb.sb_blocklog;
....@@ -1436,7 +1537,6 @@
14361537 * Release any dquot(s) the inode had kept before chown.
14371538 */
14381539 xfs_qm_dqrele(olddquot);
1439
- xfs_qm_dqrele(udqp);
14401540 xfs_qm_dqrele(pdqp);
14411541
14421542 return code;
....@@ -1444,7 +1544,6 @@
14441544 error_trans_cancel:
14451545 xfs_trans_cancel(tp);
14461546 error_free_dquots:
1447
- xfs_qm_dqrele(udqp);
14481547 xfs_qm_dqrele(pdqp);
14491548 return code;
14501549 }
....@@ -1476,7 +1575,7 @@
14761575 {
14771576 unsigned int flags;
14781577
1479
- flags = xfs_di2lxflags(ip->i_d.di_flags);
1578
+ flags = xfs_di2lxflags(ip->i_d.di_flags, ip->i_d.di_flags2);
14801579 if (copy_to_user(arg, &flags, sizeof(flags)))
14811580 return -EFAULT;
14821581 return 0;
....@@ -1490,8 +1589,8 @@
14901589 {
14911590 struct xfs_trans *tp;
14921591 struct fsxattr fa;
1592
+ struct fsxattr old_fa;
14931593 unsigned int flags;
1494
- int join_flags = 0;
14951594 int error;
14961595
14971596 if (copy_from_user(&flags, arg, sizeof(flags)))
....@@ -1499,7 +1598,7 @@
14991598
15001599 if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
15011600 FS_NOATIME_FL | FS_NODUMP_FL | \
1502
- FS_SYNC_FL))
1601
+ FS_SYNC_FL | FS_DAX_FL))
15031602 return -EOPNOTSUPP;
15041603
15051604 fa.fsx_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip));
....@@ -1508,20 +1607,18 @@
15081607 if (error)
15091608 return error;
15101609
1511
- /*
1512
- * Changing DAX config may require inode locking for mapping
1513
- * invalidation. These need to be held all the way to transaction commit
1514
- * or cancel time, so need to be passed through to
1515
- * xfs_ioctl_setattr_get_trans() so it can apply them to the join call
1516
- * appropriately.
1517
- */
1518
- error = xfs_ioctl_setattr_dax_invalidate(ip, &fa, &join_flags);
1519
- if (error)
1520
- goto out_drop_write;
1610
+ xfs_ioctl_setattr_prepare_dax(ip, &fa);
15211611
1522
- tp = xfs_ioctl_setattr_get_trans(ip, join_flags);
1612
+ tp = xfs_ioctl_setattr_get_trans(ip);
15231613 if (IS_ERR(tp)) {
15241614 error = PTR_ERR(tp);
1615
+ goto out_drop_write;
1616
+ }
1617
+
1618
+ xfs_fill_fsxattr(ip, false, &old_fa);
1619
+ error = vfs_ioc_fssetxattr_check(VFS_I(ip), &old_fa, &fa);
1620
+ if (error) {
1621
+ xfs_trans_cancel(tp);
15251622 goto out_drop_write;
15261623 }
15271624
....@@ -1592,10 +1689,10 @@
15921689
15931690 if (bmx.bmv_count < 2)
15941691 return -EINVAL;
1595
- if (bmx.bmv_count > ULONG_MAX / recsize)
1692
+ if (bmx.bmv_count >= INT_MAX / recsize)
15961693 return -ENOMEM;
15971694
1598
- buf = kmem_zalloc_large(bmx.bmv_count * sizeof(*buf), 0);
1695
+ buf = kvzalloc(bmx.bmv_count * sizeof(*buf), GFP_KERNEL);
15991696 if (!buf)
16001697 return -ENOMEM;
16011698
....@@ -1620,39 +1717,17 @@
16201717 return error;
16211718 }
16221719
1623
-struct getfsmap_info {
1624
- struct xfs_mount *mp;
1625
- struct fsmap_head __user *data;
1626
- unsigned int idx;
1627
- __u32 last_flags;
1628
-};
1629
-
1630
-STATIC int
1631
-xfs_getfsmap_format(struct xfs_fsmap *xfm, void *priv)
1632
-{
1633
- struct getfsmap_info *info = priv;
1634
- struct fsmap fm;
1635
-
1636
- trace_xfs_getfsmap_mapping(info->mp, xfm);
1637
-
1638
- info->last_flags = xfm->fmr_flags;
1639
- xfs_fsmap_from_internal(&fm, xfm);
1640
- if (copy_to_user(&info->data->fmh_recs[info->idx++], &fm,
1641
- sizeof(struct fsmap)))
1642
- return -EFAULT;
1643
-
1644
- return 0;
1645
-}
1646
-
16471720 STATIC int
16481721 xfs_ioc_getfsmap(
16491722 struct xfs_inode *ip,
16501723 struct fsmap_head __user *arg)
16511724 {
1652
- struct getfsmap_info info = { NULL };
16531725 struct xfs_fsmap_head xhead = {0};
16541726 struct fsmap_head head;
1655
- bool aborted = false;
1727
+ struct fsmap *recs;
1728
+ unsigned int count;
1729
+ __u32 last_flags = 0;
1730
+ bool done = false;
16561731 int error;
16571732
16581733 if (copy_from_user(&head, arg, sizeof(struct fsmap_head)))
....@@ -1664,38 +1739,112 @@
16641739 sizeof(head.fmh_keys[1].fmr_reserved)))
16651740 return -EINVAL;
16661741
1742
+ /*
1743
+ * Use an internal memory buffer so that we don't have to copy fsmap
1744
+ * data to userspace while holding locks. Start by trying to allocate
1745
+ * up to 128k for the buffer, but fall back to a single page if needed.
1746
+ */
1747
+ count = min_t(unsigned int, head.fmh_count,
1748
+ 131072 / sizeof(struct fsmap));
1749
+ recs = kvzalloc(count * sizeof(struct fsmap), GFP_KERNEL);
1750
+ if (!recs) {
1751
+ count = min_t(unsigned int, head.fmh_count,
1752
+ PAGE_SIZE / sizeof(struct fsmap));
1753
+ recs = kvzalloc(count * sizeof(struct fsmap), GFP_KERNEL);
1754
+ if (!recs)
1755
+ return -ENOMEM;
1756
+ }
1757
+
16671758 xhead.fmh_iflags = head.fmh_iflags;
1668
- xhead.fmh_count = head.fmh_count;
16691759 xfs_fsmap_to_internal(&xhead.fmh_keys[0], &head.fmh_keys[0]);
16701760 xfs_fsmap_to_internal(&xhead.fmh_keys[1], &head.fmh_keys[1]);
16711761
16721762 trace_xfs_getfsmap_low_key(ip->i_mount, &xhead.fmh_keys[0]);
16731763 trace_xfs_getfsmap_high_key(ip->i_mount, &xhead.fmh_keys[1]);
16741764
1675
- info.mp = ip->i_mount;
1676
- info.data = arg;
1677
- error = xfs_getfsmap(ip->i_mount, &xhead, xfs_getfsmap_format, &info);
1678
- if (error == XFS_BTREE_QUERY_RANGE_ABORT) {
1679
- error = 0;
1680
- aborted = true;
1681
- } else if (error)
1682
- return error;
1765
+ head.fmh_entries = 0;
1766
+ do {
1767
+ struct fsmap __user *user_recs;
1768
+ struct fsmap *last_rec;
16831769
1684
- /* If we didn't abort, set the "last" flag in the last fmx */
1685
- if (!aborted && info.idx) {
1686
- info.last_flags |= FMR_OF_LAST;
1687
- if (copy_to_user(&info.data->fmh_recs[info.idx - 1].fmr_flags,
1688
- &info.last_flags, sizeof(info.last_flags)))
1689
- return -EFAULT;
1770
+ user_recs = &arg->fmh_recs[head.fmh_entries];
1771
+ xhead.fmh_entries = 0;
1772
+ xhead.fmh_count = min_t(unsigned int, count,
1773
+ head.fmh_count - head.fmh_entries);
1774
+
1775
+ /* Run query, record how many entries we got. */
1776
+ error = xfs_getfsmap(ip->i_mount, &xhead, recs);
1777
+ switch (error) {
1778
+ case 0:
1779
+ /*
1780
+ * There are no more records in the result set. Copy
1781
+ * whatever we got to userspace and break out.
1782
+ */
1783
+ done = true;
1784
+ break;
1785
+ case -ECANCELED:
1786
+ /*
1787
+ * The internal memory buffer is full. Copy whatever
1788
+ * records we got to userspace and go again if we have
1789
+ * not yet filled the userspace buffer.
1790
+ */
1791
+ error = 0;
1792
+ break;
1793
+ default:
1794
+ goto out_free;
1795
+ }
1796
+ head.fmh_entries += xhead.fmh_entries;
1797
+ head.fmh_oflags = xhead.fmh_oflags;
1798
+
1799
+ /*
1800
+ * If the caller wanted a record count or there aren't any
1801
+ * new records to return, we're done.
1802
+ */
1803
+ if (head.fmh_count == 0 || xhead.fmh_entries == 0)
1804
+ break;
1805
+
1806
+ /* Copy all the records we got out to userspace. */
1807
+ if (copy_to_user(user_recs, recs,
1808
+ xhead.fmh_entries * sizeof(struct fsmap))) {
1809
+ error = -EFAULT;
1810
+ goto out_free;
1811
+ }
1812
+
1813
+ /* Remember the last record flags we copied to userspace. */
1814
+ last_rec = &recs[xhead.fmh_entries - 1];
1815
+ last_flags = last_rec->fmr_flags;
1816
+
1817
+ /* Set up the low key for the next iteration. */
1818
+ xfs_fsmap_to_internal(&xhead.fmh_keys[0], last_rec);
1819
+ trace_xfs_getfsmap_low_key(ip->i_mount, &xhead.fmh_keys[0]);
1820
+ } while (!done && head.fmh_entries < head.fmh_count);
1821
+
1822
+ /*
1823
+ * If there are no more records in the query result set and we're not
1824
+ * in counting mode, mark the last record returned with the LAST flag.
1825
+ */
1826
+ if (done && head.fmh_count > 0 && head.fmh_entries > 0) {
1827
+ struct fsmap __user *user_rec;
1828
+
1829
+ last_flags |= FMR_OF_LAST;
1830
+ user_rec = &arg->fmh_recs[head.fmh_entries - 1];
1831
+
1832
+ if (copy_to_user(&user_rec->fmr_flags, &last_flags,
1833
+ sizeof(last_flags))) {
1834
+ error = -EFAULT;
1835
+ goto out_free;
1836
+ }
16901837 }
16911838
16921839 /* copy back header */
1693
- head.fmh_entries = xhead.fmh_entries;
1694
- head.fmh_oflags = xhead.fmh_oflags;
1695
- if (copy_to_user(arg, &head, sizeof(struct fsmap_head)))
1696
- return -EFAULT;
1840
+ if (copy_to_user(arg, &head, sizeof(struct fsmap_head))) {
1841
+ error = -EFAULT;
1842
+ goto out_free;
1843
+ }
16971844
1698
- return 0;
1845
+out_free:
1846
+ kmem_free(recs);
1847
+ return error;
16991848 }
17001849
17011850 STATIC int
....@@ -1884,6 +2033,41 @@
18842033 return error;
18852034 }
18862035
2036
+static inline int
2037
+xfs_fs_eofblocks_from_user(
2038
+ struct xfs_fs_eofblocks *src,
2039
+ struct xfs_eofblocks *dst)
2040
+{
2041
+ if (src->eof_version != XFS_EOFBLOCKS_VERSION)
2042
+ return -EINVAL;
2043
+
2044
+ if (src->eof_flags & ~XFS_EOF_FLAGS_VALID)
2045
+ return -EINVAL;
2046
+
2047
+ if (memchr_inv(&src->pad32, 0, sizeof(src->pad32)) ||
2048
+ memchr_inv(src->pad64, 0, sizeof(src->pad64)))
2049
+ return -EINVAL;
2050
+
2051
+ dst->eof_flags = src->eof_flags;
2052
+ dst->eof_prid = src->eof_prid;
2053
+ dst->eof_min_file_size = src->eof_min_file_size;
2054
+
2055
+ dst->eof_uid = INVALID_UID;
2056
+ if (src->eof_flags & XFS_EOF_FLAGS_UID) {
2057
+ dst->eof_uid = make_kuid(current_user_ns(), src->eof_uid);
2058
+ if (!uid_valid(dst->eof_uid))
2059
+ return -EINVAL;
2060
+ }
2061
+
2062
+ dst->eof_gid = INVALID_GID;
2063
+ if (src->eof_flags & XFS_EOF_FLAGS_GID) {
2064
+ dst->eof_gid = make_kgid(current_user_ns(), src->eof_gid);
2065
+ if (!gid_valid(dst->eof_gid))
2066
+ return -EINVAL;
2067
+ }
2068
+ return 0;
2069
+}
2070
+
18872071 /*
18882072 * Note: some of the ioctl's return positive numbers as a
18892073 * byte count indicating success, such as readlink_by_handle.
....@@ -1913,24 +2097,17 @@
19132097 return xfs_ioc_setlabel(filp, mp, arg);
19142098 case XFS_IOC_ALLOCSP:
19152099 case XFS_IOC_FREESP:
1916
- case XFS_IOC_RESVSP:
1917
- case XFS_IOC_UNRESVSP:
19182100 case XFS_IOC_ALLOCSP64:
1919
- case XFS_IOC_FREESP64:
1920
- case XFS_IOC_RESVSP64:
1921
- case XFS_IOC_UNRESVSP64:
1922
- case XFS_IOC_ZERO_RANGE: {
2101
+ case XFS_IOC_FREESP64: {
19232102 xfs_flock64_t bf;
19242103
19252104 if (copy_from_user(&bf, arg, sizeof(bf)))
19262105 return -EFAULT;
1927
- return xfs_ioc_space(filp, cmd, &bf);
2106
+ return xfs_ioc_space(filp, &bf);
19282107 }
19292108 case XFS_IOC_DIOINFO: {
1930
- struct dioattr da;
1931
- xfs_buftarg_t *target =
1932
- XFS_IS_REALTIME_INODE(ip) ?
1933
- mp->m_rtdev_targp : mp->m_ddev_targp;
2109
+ struct xfs_buftarg *target = xfs_inode_buftarg(ip);
2110
+ struct dioattr da;
19342111
19352112 da.d_mem = da.d_miniosz = target->bt_logical_sectorsize;
19362113 da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1);
....@@ -1943,13 +2120,22 @@
19432120 case XFS_IOC_FSBULKSTAT_SINGLE:
19442121 case XFS_IOC_FSBULKSTAT:
19452122 case XFS_IOC_FSINUMBERS:
2123
+ return xfs_ioc_fsbulkstat(mp, cmd, arg);
2124
+
2125
+ case XFS_IOC_BULKSTAT:
19462126 return xfs_ioc_bulkstat(mp, cmd, arg);
2127
+ case XFS_IOC_INUMBERS:
2128
+ return xfs_ioc_inumbers(mp, cmd, arg);
19472129
19482130 case XFS_IOC_FSGEOMETRY_V1:
1949
- return xfs_ioc_fsgeometry_v1(mp, arg);
1950
-
2131
+ return xfs_ioc_fsgeometry(mp, arg, 3);
2132
+ case XFS_IOC_FSGEOMETRY_V4:
2133
+ return xfs_ioc_fsgeometry(mp, arg, 4);
19512134 case XFS_IOC_FSGEOMETRY:
1952
- return xfs_ioc_fsgeometry(mp, arg);
2135
+ return xfs_ioc_fsgeometry(mp, arg, 5);
2136
+
2137
+ case XFS_IOC_AG_GEOMETRY:
2138
+ return xfs_ioc_ag_geometry(mp, arg);
19532139
19542140 case XFS_IOC_GETVERSION:
19552141 return put_user(inode->i_generation, (int __user *)arg);
....@@ -1964,22 +2150,6 @@
19642150 return xfs_ioc_getxflags(ip, arg);
19652151 case XFS_IOC_SETXFLAGS:
19662152 return xfs_ioc_setxflags(ip, filp, arg);
1967
-
1968
- case XFS_IOC_FSSETDM: {
1969
- struct fsdmidata dmi;
1970
-
1971
- if (copy_from_user(&dmi, arg, sizeof(dmi)))
1972
- return -EFAULT;
1973
-
1974
- error = mnt_want_write_file(filp);
1975
- if (error)
1976
- return error;
1977
-
1978
- error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask,
1979
- dmi.fsd_dmstate);
1980
- mnt_drop_write_file(filp);
1981
- return error;
1982
- }
19832153
19842154 case XFS_IOC_GETBMAP:
19852155 case XFS_IOC_GETBMAPA:
....@@ -2008,8 +2178,6 @@
20082178 return -EFAULT;
20092179 return xfs_open_by_handle(filp, &hreq);
20102180 }
2011
- case XFS_IOC_FSSETDM_BY_HANDLE:
2012
- return xfs_fssetdm_by_handle(filp, arg);
20132181
20142182 case XFS_IOC_READLINK_BY_HANDLE: {
20152183 xfs_fsop_handlereq_t hreq;
....@@ -2040,9 +2208,7 @@
20402208 case XFS_IOC_FSCOUNTS: {
20412209 xfs_fsop_counts_t out;
20422210
2043
- error = xfs_fs_counts(mp, &out);
2044
- if (error)
2045
- return error;
2211
+ xfs_fs_counts(mp, &out);
20462212
20472213 if (copy_to_user(arg, &out, sizeof(out)))
20482214 return -EFAULT;