diff options
author | Dave Airlie <airlied@redhat.com> | 2017-04-10 17:40:42 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2017-04-10 17:40:42 -0400 |
commit | b769fefb68cd70385d68220ae341e5a10723fbc0 (patch) | |
tree | a2881410c9dc5a3474619d155fac981cfbd4ee8f /fs/xfs | |
parent | 1420f63b8207e966f54caec26d08abdc2ff37193 (diff) | |
parent | 39da7c509acff13fc8cb12ec1bb20337c988ed36 (diff) |
Backmerge tag 'v4.11-rc6' into drm-next
Linux 4.11-rc6
drm-misc needs 4.11-rc5, may as well fix conflicts with rc6.
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/libxfs/xfs_dir2_priv.h | 3 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_dir2_sf.c | 63 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_inode_fork.c | 35 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_inode_fork.h | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_bmap_util.c | 10 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.c | 19 | ||||
-rw-r--r-- | fs/xfs/xfs_iops.c | 14 | ||||
-rw-r--r-- | fs/xfs/xfs_itable.c | 2 |
8 files changed, 90 insertions, 58 deletions
diff --git a/fs/xfs/libxfs/xfs_dir2_priv.h b/fs/xfs/libxfs/xfs_dir2_priv.h index eb00bc133bca..39f8604f764e 100644 --- a/fs/xfs/libxfs/xfs_dir2_priv.h +++ b/fs/xfs/libxfs/xfs_dir2_priv.h | |||
@@ -125,8 +125,7 @@ extern int xfs_dir2_sf_create(struct xfs_da_args *args, xfs_ino_t pino); | |||
125 | extern int xfs_dir2_sf_lookup(struct xfs_da_args *args); | 125 | extern int xfs_dir2_sf_lookup(struct xfs_da_args *args); |
126 | extern int xfs_dir2_sf_removename(struct xfs_da_args *args); | 126 | extern int xfs_dir2_sf_removename(struct xfs_da_args *args); |
127 | extern int xfs_dir2_sf_replace(struct xfs_da_args *args); | 127 | extern int xfs_dir2_sf_replace(struct xfs_da_args *args); |
128 | extern int xfs_dir2_sf_verify(struct xfs_mount *mp, struct xfs_dir2_sf_hdr *sfp, | 128 | extern int xfs_dir2_sf_verify(struct xfs_inode *ip); |
129 | int size); | ||
130 | 129 | ||
131 | /* xfs_dir2_readdir.c */ | 130 | /* xfs_dir2_readdir.c */ |
132 | extern int xfs_readdir(struct xfs_inode *dp, struct dir_context *ctx, | 131 | extern int xfs_readdir(struct xfs_inode *dp, struct dir_context *ctx, |
diff --git a/fs/xfs/libxfs/xfs_dir2_sf.c b/fs/xfs/libxfs/xfs_dir2_sf.c index 96b45cd6c63f..e84af093b2ab 100644 --- a/fs/xfs/libxfs/xfs_dir2_sf.c +++ b/fs/xfs/libxfs/xfs_dir2_sf.c | |||
@@ -632,36 +632,49 @@ xfs_dir2_sf_check( | |||
632 | /* Verify the consistency of an inline directory. */ | 632 | /* Verify the consistency of an inline directory. */ |
633 | int | 633 | int |
634 | xfs_dir2_sf_verify( | 634 | xfs_dir2_sf_verify( |
635 | struct xfs_mount *mp, | 635 | struct xfs_inode *ip) |
636 | struct xfs_dir2_sf_hdr *sfp, | ||
637 | int size) | ||
638 | { | 636 | { |
637 | struct xfs_mount *mp = ip->i_mount; | ||
638 | struct xfs_dir2_sf_hdr *sfp; | ||
639 | struct xfs_dir2_sf_entry *sfep; | 639 | struct xfs_dir2_sf_entry *sfep; |
640 | struct xfs_dir2_sf_entry *next_sfep; | 640 | struct xfs_dir2_sf_entry *next_sfep; |
641 | char *endp; | 641 | char *endp; |
642 | const struct xfs_dir_ops *dops; | 642 | const struct xfs_dir_ops *dops; |
643 | struct xfs_ifork *ifp; | ||
643 | xfs_ino_t ino; | 644 | xfs_ino_t ino; |
644 | int i; | 645 | int i; |
645 | int i8count; | 646 | int i8count; |
646 | int offset; | 647 | int offset; |
648 | int size; | ||
649 | int error; | ||
647 | __uint8_t filetype; | 650 | __uint8_t filetype; |
648 | 651 | ||
652 | ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_LOCAL); | ||
653 | /* | ||
654 | * xfs_iread calls us before xfs_setup_inode sets up ip->d_ops, | ||
655 | * so we can only trust the mountpoint to have the right pointer. | ||
656 | */ | ||
649 | dops = xfs_dir_get_ops(mp, NULL); | 657 | dops = xfs_dir_get_ops(mp, NULL); |
650 | 658 | ||
659 | ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); | ||
660 | sfp = (struct xfs_dir2_sf_hdr *)ifp->if_u1.if_data; | ||
661 | size = ifp->if_bytes; | ||
662 | |||
651 | /* | 663 | /* |
652 | * Give up if the directory is way too short. | 664 | * Give up if the directory is way too short. |
653 | */ | 665 | */ |
654 | XFS_WANT_CORRUPTED_RETURN(mp, size > | 666 | if (size <= offsetof(struct xfs_dir2_sf_hdr, parent) || |
655 | offsetof(struct xfs_dir2_sf_hdr, parent)); | 667 | size < xfs_dir2_sf_hdr_size(sfp->i8count)) |
656 | XFS_WANT_CORRUPTED_RETURN(mp, size >= | 668 | return -EFSCORRUPTED; |
657 | xfs_dir2_sf_hdr_size(sfp->i8count)); | ||
658 | 669 | ||
659 | endp = (char *)sfp + size; | 670 | endp = (char *)sfp + size; |
660 | 671 | ||
661 | /* Check .. entry */ | 672 | /* Check .. entry */ |
662 | ino = dops->sf_get_parent_ino(sfp); | 673 | ino = dops->sf_get_parent_ino(sfp); |
663 | i8count = ino > XFS_DIR2_MAX_SHORT_INUM; | 674 | i8count = ino > XFS_DIR2_MAX_SHORT_INUM; |
664 | XFS_WANT_CORRUPTED_RETURN(mp, !xfs_dir_ino_validate(mp, ino)); | 675 | error = xfs_dir_ino_validate(mp, ino); |
676 | if (error) | ||
677 | return error; | ||
665 | offset = dops->data_first_offset; | 678 | offset = dops->data_first_offset; |
666 | 679 | ||
667 | /* Check all reported entries */ | 680 | /* Check all reported entries */ |
@@ -672,12 +685,12 @@ xfs_dir2_sf_verify( | |||
672 | * Check the fixed-offset parts of the structure are | 685 | * Check the fixed-offset parts of the structure are |
673 | * within the data buffer. | 686 | * within the data buffer. |
674 | */ | 687 | */ |
675 | XFS_WANT_CORRUPTED_RETURN(mp, | 688 | if (((char *)sfep + sizeof(*sfep)) >= endp) |
676 | ((char *)sfep + sizeof(*sfep)) < endp); | 689 | return -EFSCORRUPTED; |
677 | 690 | ||
678 | /* Don't allow names with known bad length. */ | 691 | /* Don't allow names with known bad length. */ |
679 | XFS_WANT_CORRUPTED_RETURN(mp, sfep->namelen > 0); | 692 | if (sfep->namelen == 0) |
680 | XFS_WANT_CORRUPTED_RETURN(mp, sfep->namelen < MAXNAMELEN); | 693 | return -EFSCORRUPTED; |
681 | 694 | ||
682 | /* | 695 | /* |
683 | * Check that the variable-length part of the structure is | 696 | * Check that the variable-length part of the structure is |
@@ -685,33 +698,39 @@ xfs_dir2_sf_verify( | |||
685 | * name component, so nextentry is an acceptable test. | 698 | * name component, so nextentry is an acceptable test. |
686 | */ | 699 | */ |
687 | next_sfep = dops->sf_nextentry(sfp, sfep); | 700 | next_sfep = dops->sf_nextentry(sfp, sfep); |
688 | XFS_WANT_CORRUPTED_RETURN(mp, endp >= (char *)next_sfep); | 701 | if (endp < (char *)next_sfep) |
702 | return -EFSCORRUPTED; | ||
689 | 703 | ||
690 | /* Check that the offsets always increase. */ | 704 | /* Check that the offsets always increase. */ |
691 | XFS_WANT_CORRUPTED_RETURN(mp, | 705 | if (xfs_dir2_sf_get_offset(sfep) < offset) |
692 | xfs_dir2_sf_get_offset(sfep) >= offset); | 706 | return -EFSCORRUPTED; |
693 | 707 | ||
694 | /* Check the inode number. */ | 708 | /* Check the inode number. */ |
695 | ino = dops->sf_get_ino(sfp, sfep); | 709 | ino = dops->sf_get_ino(sfp, sfep); |
696 | i8count += ino > XFS_DIR2_MAX_SHORT_INUM; | 710 | i8count += ino > XFS_DIR2_MAX_SHORT_INUM; |
697 | XFS_WANT_CORRUPTED_RETURN(mp, !xfs_dir_ino_validate(mp, ino)); | 711 | error = xfs_dir_ino_validate(mp, ino); |
712 | if (error) | ||
713 | return error; | ||
698 | 714 | ||
699 | /* Check the file type. */ | 715 | /* Check the file type. */ |
700 | filetype = dops->sf_get_ftype(sfep); | 716 | filetype = dops->sf_get_ftype(sfep); |
701 | XFS_WANT_CORRUPTED_RETURN(mp, filetype < XFS_DIR3_FT_MAX); | 717 | if (filetype >= XFS_DIR3_FT_MAX) |
718 | return -EFSCORRUPTED; | ||
702 | 719 | ||
703 | offset = xfs_dir2_sf_get_offset(sfep) + | 720 | offset = xfs_dir2_sf_get_offset(sfep) + |
704 | dops->data_entsize(sfep->namelen); | 721 | dops->data_entsize(sfep->namelen); |
705 | 722 | ||
706 | sfep = next_sfep; | 723 | sfep = next_sfep; |
707 | } | 724 | } |
708 | XFS_WANT_CORRUPTED_RETURN(mp, i8count == sfp->i8count); | 725 | if (i8count != sfp->i8count) |
709 | XFS_WANT_CORRUPTED_RETURN(mp, (void *)sfep == (void *)endp); | 726 | return -EFSCORRUPTED; |
727 | if ((void *)sfep != (void *)endp) | ||
728 | return -EFSCORRUPTED; | ||
710 | 729 | ||
711 | /* Make sure this whole thing ought to be in local format. */ | 730 | /* Make sure this whole thing ought to be in local format. */ |
712 | XFS_WANT_CORRUPTED_RETURN(mp, offset + | 731 | if (offset + (sfp->count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t) + |
713 | (sfp->count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t) + | 732 | (uint)sizeof(xfs_dir2_block_tail_t) > mp->m_dir_geo->blksize) |
714 | (uint)sizeof(xfs_dir2_block_tail_t) <= mp->m_dir_geo->blksize); | 733 | return -EFSCORRUPTED; |
715 | 734 | ||
716 | return 0; | 735 | return 0; |
717 | } | 736 | } |
diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c index 9653e964eda4..8a37efe04de3 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.c +++ b/fs/xfs/libxfs/xfs_inode_fork.c | |||
@@ -212,6 +212,16 @@ xfs_iformat_fork( | |||
212 | if (error) | 212 | if (error) |
213 | return error; | 213 | return error; |
214 | 214 | ||
215 | /* Check inline dir contents. */ | ||
216 | if (S_ISDIR(VFS_I(ip)->i_mode) && | ||
217 | dip->di_format == XFS_DINODE_FMT_LOCAL) { | ||
218 | error = xfs_dir2_sf_verify(ip); | ||
219 | if (error) { | ||
220 | xfs_idestroy_fork(ip, XFS_DATA_FORK); | ||
221 | return error; | ||
222 | } | ||
223 | } | ||
224 | |||
215 | if (xfs_is_reflink_inode(ip)) { | 225 | if (xfs_is_reflink_inode(ip)) { |
216 | ASSERT(ip->i_cowfp == NULL); | 226 | ASSERT(ip->i_cowfp == NULL); |
217 | xfs_ifork_init_cow(ip); | 227 | xfs_ifork_init_cow(ip); |
@@ -322,8 +332,6 @@ xfs_iformat_local( | |||
322 | int whichfork, | 332 | int whichfork, |
323 | int size) | 333 | int size) |
324 | { | 334 | { |
325 | int error; | ||
326 | |||
327 | /* | 335 | /* |
328 | * If the size is unreasonable, then something | 336 | * If the size is unreasonable, then something |
329 | * is wrong and we just bail out rather than crash in | 337 | * is wrong and we just bail out rather than crash in |
@@ -339,14 +347,6 @@ xfs_iformat_local( | |||
339 | return -EFSCORRUPTED; | 347 | return -EFSCORRUPTED; |
340 | } | 348 | } |
341 | 349 | ||
342 | if (S_ISDIR(VFS_I(ip)->i_mode) && whichfork == XFS_DATA_FORK) { | ||
343 | error = xfs_dir2_sf_verify(ip->i_mount, | ||
344 | (struct xfs_dir2_sf_hdr *)XFS_DFORK_DPTR(dip), | ||
345 | size); | ||
346 | if (error) | ||
347 | return error; | ||
348 | } | ||
349 | |||
350 | xfs_init_local_fork(ip, whichfork, XFS_DFORK_PTR(dip, whichfork), size); | 350 | xfs_init_local_fork(ip, whichfork, XFS_DFORK_PTR(dip, whichfork), size); |
351 | return 0; | 351 | return 0; |
352 | } | 352 | } |
@@ -867,7 +867,7 @@ xfs_iextents_copy( | |||
867 | * In these cases, the format always takes precedence, because the | 867 | * In these cases, the format always takes precedence, because the |
868 | * format indicates the current state of the fork. | 868 | * format indicates the current state of the fork. |
869 | */ | 869 | */ |
870 | int | 870 | void |
871 | xfs_iflush_fork( | 871 | xfs_iflush_fork( |
872 | xfs_inode_t *ip, | 872 | xfs_inode_t *ip, |
873 | xfs_dinode_t *dip, | 873 | xfs_dinode_t *dip, |
@@ -877,7 +877,6 @@ xfs_iflush_fork( | |||
877 | char *cp; | 877 | char *cp; |
878 | xfs_ifork_t *ifp; | 878 | xfs_ifork_t *ifp; |
879 | xfs_mount_t *mp; | 879 | xfs_mount_t *mp; |
880 | int error; | ||
881 | static const short brootflag[2] = | 880 | static const short brootflag[2] = |
882 | { XFS_ILOG_DBROOT, XFS_ILOG_ABROOT }; | 881 | { XFS_ILOG_DBROOT, XFS_ILOG_ABROOT }; |
883 | static const short dataflag[2] = | 882 | static const short dataflag[2] = |
@@ -886,7 +885,7 @@ xfs_iflush_fork( | |||
886 | { XFS_ILOG_DEXT, XFS_ILOG_AEXT }; | 885 | { XFS_ILOG_DEXT, XFS_ILOG_AEXT }; |
887 | 886 | ||
888 | if (!iip) | 887 | if (!iip) |
889 | return 0; | 888 | return; |
890 | ifp = XFS_IFORK_PTR(ip, whichfork); | 889 | ifp = XFS_IFORK_PTR(ip, whichfork); |
891 | /* | 890 | /* |
892 | * This can happen if we gave up in iformat in an error path, | 891 | * This can happen if we gave up in iformat in an error path, |
@@ -894,19 +893,12 @@ xfs_iflush_fork( | |||
894 | */ | 893 | */ |
895 | if (!ifp) { | 894 | if (!ifp) { |
896 | ASSERT(whichfork == XFS_ATTR_FORK); | 895 | ASSERT(whichfork == XFS_ATTR_FORK); |
897 | return 0; | 896 | return; |
898 | } | 897 | } |
899 | cp = XFS_DFORK_PTR(dip, whichfork); | 898 | cp = XFS_DFORK_PTR(dip, whichfork); |
900 | mp = ip->i_mount; | 899 | mp = ip->i_mount; |
901 | switch (XFS_IFORK_FORMAT(ip, whichfork)) { | 900 | switch (XFS_IFORK_FORMAT(ip, whichfork)) { |
902 | case XFS_DINODE_FMT_LOCAL: | 901 | case XFS_DINODE_FMT_LOCAL: |
903 | if (S_ISDIR(VFS_I(ip)->i_mode) && whichfork == XFS_DATA_FORK) { | ||
904 | error = xfs_dir2_sf_verify(mp, | ||
905 | (struct xfs_dir2_sf_hdr *)ifp->if_u1.if_data, | ||
906 | ifp->if_bytes); | ||
907 | if (error) | ||
908 | return error; | ||
909 | } | ||
910 | if ((iip->ili_fields & dataflag[whichfork]) && | 902 | if ((iip->ili_fields & dataflag[whichfork]) && |
911 | (ifp->if_bytes > 0)) { | 903 | (ifp->if_bytes > 0)) { |
912 | ASSERT(ifp->if_u1.if_data != NULL); | 904 | ASSERT(ifp->if_u1.if_data != NULL); |
@@ -959,7 +951,6 @@ xfs_iflush_fork( | |||
959 | ASSERT(0); | 951 | ASSERT(0); |
960 | break; | 952 | break; |
961 | } | 953 | } |
962 | return 0; | ||
963 | } | 954 | } |
964 | 955 | ||
965 | /* | 956 | /* |
diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h index 132dc59fdde6..7fb8365326d1 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.h +++ b/fs/xfs/libxfs/xfs_inode_fork.h | |||
@@ -140,7 +140,7 @@ typedef struct xfs_ifork { | |||
140 | struct xfs_ifork *xfs_iext_state_to_fork(struct xfs_inode *ip, int state); | 140 | struct xfs_ifork *xfs_iext_state_to_fork(struct xfs_inode *ip, int state); |
141 | 141 | ||
142 | int xfs_iformat_fork(struct xfs_inode *, struct xfs_dinode *); | 142 | int xfs_iformat_fork(struct xfs_inode *, struct xfs_dinode *); |
143 | int xfs_iflush_fork(struct xfs_inode *, struct xfs_dinode *, | 143 | void xfs_iflush_fork(struct xfs_inode *, struct xfs_dinode *, |
144 | struct xfs_inode_log_item *, int); | 144 | struct xfs_inode_log_item *, int); |
145 | void xfs_idestroy_fork(struct xfs_inode *, int); | 145 | void xfs_idestroy_fork(struct xfs_inode *, int); |
146 | void xfs_idata_realloc(struct xfs_inode *, int, int); | 146 | void xfs_idata_realloc(struct xfs_inode *, int, int); |
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 8b75dcea5966..828532ce0adc 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c | |||
@@ -1311,8 +1311,16 @@ xfs_free_file_space( | |||
1311 | /* | 1311 | /* |
1312 | * Now that we've unmap all full blocks we'll have to zero out any | 1312 | * Now that we've unmap all full blocks we'll have to zero out any |
1313 | * partial block at the beginning and/or end. xfs_zero_range is | 1313 | * partial block at the beginning and/or end. xfs_zero_range is |
1314 | * smart enough to skip any holes, including those we just created. | 1314 | * smart enough to skip any holes, including those we just created, |
1315 | * but we must take care not to zero beyond EOF and enlarge i_size. | ||
1315 | */ | 1316 | */ |
1317 | |||
1318 | if (offset >= XFS_ISIZE(ip)) | ||
1319 | return 0; | ||
1320 | |||
1321 | if (offset + len > XFS_ISIZE(ip)) | ||
1322 | len = XFS_ISIZE(ip) - offset; | ||
1323 | |||
1316 | return xfs_zero_range(ip, offset, len, NULL); | 1324 | return xfs_zero_range(ip, offset, len, NULL); |
1317 | } | 1325 | } |
1318 | 1326 | ||
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index c7fe2c2123ab..7605d8396596 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include "xfs_log.h" | 50 | #include "xfs_log.h" |
51 | #include "xfs_bmap_btree.h" | 51 | #include "xfs_bmap_btree.h" |
52 | #include "xfs_reflink.h" | 52 | #include "xfs_reflink.h" |
53 | #include "xfs_dir2_priv.h" | ||
53 | 54 | ||
54 | kmem_zone_t *xfs_inode_zone; | 55 | kmem_zone_t *xfs_inode_zone; |
55 | 56 | ||
@@ -3475,7 +3476,6 @@ xfs_iflush_int( | |||
3475 | struct xfs_inode_log_item *iip = ip->i_itemp; | 3476 | struct xfs_inode_log_item *iip = ip->i_itemp; |
3476 | struct xfs_dinode *dip; | 3477 | struct xfs_dinode *dip; |
3477 | struct xfs_mount *mp = ip->i_mount; | 3478 | struct xfs_mount *mp = ip->i_mount; |
3478 | int error; | ||
3479 | 3479 | ||
3480 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)); | 3480 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)); |
3481 | ASSERT(xfs_isiflocked(ip)); | 3481 | ASSERT(xfs_isiflocked(ip)); |
@@ -3547,6 +3547,12 @@ xfs_iflush_int( | |||
3547 | if (ip->i_d.di_version < 3) | 3547 | if (ip->i_d.di_version < 3) |
3548 | ip->i_d.di_flushiter++; | 3548 | ip->i_d.di_flushiter++; |
3549 | 3549 | ||
3550 | /* Check the inline directory data. */ | ||
3551 | if (S_ISDIR(VFS_I(ip)->i_mode) && | ||
3552 | ip->i_d.di_format == XFS_DINODE_FMT_LOCAL && | ||
3553 | xfs_dir2_sf_verify(ip)) | ||
3554 | goto corrupt_out; | ||
3555 | |||
3550 | /* | 3556 | /* |
3551 | * Copy the dirty parts of the inode into the on-disk inode. We always | 3557 | * Copy the dirty parts of the inode into the on-disk inode. We always |
3552 | * copy out the core of the inode, because if the inode is dirty at all | 3558 | * copy out the core of the inode, because if the inode is dirty at all |
@@ -3558,14 +3564,9 @@ xfs_iflush_int( | |||
3558 | if (ip->i_d.di_flushiter == DI_MAX_FLUSH) | 3564 | if (ip->i_d.di_flushiter == DI_MAX_FLUSH) |
3559 | ip->i_d.di_flushiter = 0; | 3565 | ip->i_d.di_flushiter = 0; |
3560 | 3566 | ||
3561 | error = xfs_iflush_fork(ip, dip, iip, XFS_DATA_FORK); | 3567 | xfs_iflush_fork(ip, dip, iip, XFS_DATA_FORK); |
3562 | if (error) | 3568 | if (XFS_IFORK_Q(ip)) |
3563 | return error; | 3569 | xfs_iflush_fork(ip, dip, iip, XFS_ATTR_FORK); |
3564 | if (XFS_IFORK_Q(ip)) { | ||
3565 | error = xfs_iflush_fork(ip, dip, iip, XFS_ATTR_FORK); | ||
3566 | if (error) | ||
3567 | return error; | ||
3568 | } | ||
3569 | xfs_inobp_check(mp, bp); | 3570 | xfs_inobp_check(mp, bp); |
3570 | 3571 | ||
3571 | /* | 3572 | /* |
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 229cc6a6d8ef..ebfc13350f9a 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c | |||
@@ -516,6 +516,20 @@ xfs_vn_getattr( | |||
516 | stat->blocks = | 516 | stat->blocks = |
517 | XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks); | 517 | XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks); |
518 | 518 | ||
519 | if (ip->i_d.di_version == 3) { | ||
520 | if (request_mask & STATX_BTIME) { | ||
521 | stat->result_mask |= STATX_BTIME; | ||
522 | stat->btime.tv_sec = ip->i_d.di_crtime.t_sec; | ||
523 | stat->btime.tv_nsec = ip->i_d.di_crtime.t_nsec; | ||
524 | } | ||
525 | } | ||
526 | |||
527 | if (ip->i_d.di_flags & XFS_DIFLAG_IMMUTABLE) | ||
528 | stat->attributes |= STATX_ATTR_IMMUTABLE; | ||
529 | if (ip->i_d.di_flags & XFS_DIFLAG_APPEND) | ||
530 | stat->attributes |= STATX_ATTR_APPEND; | ||
531 | if (ip->i_d.di_flags & XFS_DIFLAG_NODUMP) | ||
532 | stat->attributes |= STATX_ATTR_NODUMP; | ||
519 | 533 | ||
520 | switch (inode->i_mode & S_IFMT) { | 534 | switch (inode->i_mode & S_IFMT) { |
521 | case S_IFBLK: | 535 | case S_IFBLK: |
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index 2a6d9b1558e0..26d67ce3c18d 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c | |||
@@ -583,7 +583,7 @@ xfs_inumbers( | |||
583 | return error; | 583 | return error; |
584 | 584 | ||
585 | bcount = MIN(left, (int)(PAGE_SIZE / sizeof(*buffer))); | 585 | bcount = MIN(left, (int)(PAGE_SIZE / sizeof(*buffer))); |
586 | buffer = kmem_alloc(bcount * sizeof(*buffer), KM_SLEEP); | 586 | buffer = kmem_zalloc(bcount * sizeof(*buffer), KM_SLEEP); |
587 | do { | 587 | do { |
588 | struct xfs_inobt_rec_incore r; | 588 | struct xfs_inobt_rec_incore r; |
589 | int stat; | 589 | int stat; |