Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'xfs-for-linus-v3.12-rc1-2' of git://oss.sgi.com/xfs/xfs

Pull xfs update #2 from Ben Myers:
"Here we have defrag support for v5 superblock, a number of bugfixes
and a cleanup or two.

- defrag support for CRC filesystems
- fix endian worning in xlog_recover_get_buf_lsn
- fixes for sparse warnings
- fix for assert in xfs_dir3_leaf_hdr_from_disk
- fix for log recovery of remote symlinks
- fix for log recovery of btree root splits
- fixes formemory allocation failures with ACLs
- fix for assert in xfs_buf_item_relse
- fix for assert in xfs_inode_buf_verify
- fix an assignment in an assert that should be a test in
xfs_bmbt_change_owner
- remove dead code in xlog_recover_inode_pass2"

* tag 'xfs-for-linus-v3.12-rc1-2' of git://oss.sgi.com/xfs/xfs:
xfs: remove dead code from xlog_recover_inode_pass2
xfs: = vs == typo in ASSERT()
xfs: don't assert fail on bad inode numbers
xfs: aborted buf items can be in the AIL.
xfs: factor all the kmalloc-or-vmalloc fallback allocations
xfs: fix memory allocation failures with ACLs
xfs: ensure we copy buffer type in da btree root splits
xfs: set remote symlink buffer type for recovery
xfs: recovery of swap extents operations for CRC filesystems
xfs: swap extents operations for CRC filesystems
xfs: check magic numbers in dir3 leaf verifier first
xfs: fix some minor sparse warnings
xfs: fix endian warning in xlog_recover_get_buf_lsn()

+461 -166
+12 -3
fs/xfs/kmem.c
··· 27 27 28 28 /* 29 29 * Greedy allocation. May fail and may return vmalloced memory. 30 - * 31 - * Must be freed using kmem_free_large. 32 30 */ 33 31 void * 34 32 kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize) ··· 34 36 void *ptr; 35 37 size_t kmsize = maxsize; 36 38 37 - while (!(ptr = kmem_zalloc_large(kmsize))) { 39 + while (!(ptr = vzalloc(kmsize))) { 38 40 if ((kmsize >>= 1) <= minsize) 39 41 kmsize = minsize; 40 42 } ··· 71 73 if (ptr) 72 74 memset((char *)ptr, 0, (int)size); 73 75 return ptr; 76 + } 77 + 78 + void * 79 + kmem_zalloc_large(size_t size, xfs_km_flags_t flags) 80 + { 81 + void *ptr; 82 + 83 + ptr = kmem_zalloc(size, flags | KM_MAYFAIL); 84 + if (ptr) 85 + return ptr; 86 + return vzalloc(size); 74 87 } 75 88 76 89 void
+1 -8
fs/xfs/kmem.h
··· 57 57 58 58 extern void *kmem_alloc(size_t, xfs_km_flags_t); 59 59 extern void *kmem_zalloc(size_t, xfs_km_flags_t); 60 + extern void *kmem_zalloc_large(size_t size, xfs_km_flags_t); 60 61 extern void *kmem_realloc(const void *, size_t, size_t, xfs_km_flags_t); 61 62 extern void kmem_free(const void *); 62 63 63 - static inline void *kmem_zalloc_large(size_t size) 64 - { 65 - return vzalloc(size); 66 - } 67 - static inline void kmem_free_large(void *ptr) 68 - { 69 - vfree(ptr); 70 - } 71 64 72 65 extern void *kmem_zalloc_greedy(size_t *, size_t, size_t); 73 66
+6 -6
fs/xfs/xfs_acl.c
··· 152 152 * go out to the disk. 153 153 */ 154 154 len = XFS_ACL_MAX_SIZE(ip->i_mount); 155 - xfs_acl = kzalloc(len, GFP_KERNEL); 155 + xfs_acl = kmem_zalloc_large(len, KM_SLEEP); 156 156 if (!xfs_acl) 157 157 return ERR_PTR(-ENOMEM); 158 158 ··· 175 175 if (IS_ERR(acl)) 176 176 goto out; 177 177 178 - out_update_cache: 178 + out_update_cache: 179 179 set_cached_acl(inode, type, acl); 180 - out: 181 - kfree(xfs_acl); 180 + out: 181 + kmem_free(xfs_acl); 182 182 return acl; 183 183 } 184 184 ··· 209 209 struct xfs_acl *xfs_acl; 210 210 int len = XFS_ACL_MAX_SIZE(ip->i_mount); 211 211 212 - xfs_acl = kzalloc(len, GFP_KERNEL); 212 + xfs_acl = kmem_zalloc_large(len, KM_SLEEP); 213 213 if (!xfs_acl) 214 214 return -ENOMEM; 215 215 ··· 222 222 error = -xfs_attr_set(ip, ea_name, (unsigned char *)xfs_acl, 223 223 len, ATTR_ROOT); 224 224 225 - kfree(xfs_acl); 225 + kmem_free(xfs_acl); 226 226 } else { 227 227 /* 228 228 * A NULL ACL argument means we want to remove the ACL.
+1 -1
fs/xfs/xfs_bmap.c
··· 4450 4450 { 4451 4451 struct xfs_mount *mp = ip->i_mount; 4452 4452 struct xfs_ifork *ifp; 4453 - struct xfs_bmalloca bma = { 0 }; /* args for xfs_bmap_alloc */ 4453 + struct xfs_bmalloca bma = { NULL }; /* args for xfs_bmap_alloc */ 4454 4454 xfs_fileoff_t end; /* end of mapped file region */ 4455 4455 int eof; /* after the end of extents */ 4456 4456 int error; /* error return */
+44
fs/xfs/xfs_bmap_btree.c
··· 925 925 return blocklen / sizeof(xfs_bmdr_rec_t); 926 926 return blocklen / (sizeof(xfs_bmdr_key_t) + sizeof(xfs_bmdr_ptr_t)); 927 927 } 928 + 929 + /* 930 + * Change the owner of a btree format fork fo the inode passed in. Change it to 931 + * the owner of that is passed in so that we can change owners before or after 932 + * we switch forks between inodes. The operation that the caller is doing will 933 + * determine whether is needs to change owner before or after the switch. 934 + * 935 + * For demand paged transactional modification, the fork switch should be done 936 + * after reading in all the blocks, modifying them and pinning them in the 937 + * transaction. For modification when the buffers are already pinned in memory, 938 + * the fork switch can be done before changing the owner as we won't need to 939 + * validate the owner until the btree buffers are unpinned and writes can occur 940 + * again. 941 + * 942 + * For recovery based ownership change, there is no transactional context and 943 + * so a buffer list must be supplied so that we can record the buffers that we 944 + * modified for the caller to issue IO on. 945 + */ 946 + int 947 + xfs_bmbt_change_owner( 948 + struct xfs_trans *tp, 949 + struct xfs_inode *ip, 950 + int whichfork, 951 + xfs_ino_t new_owner, 952 + struct list_head *buffer_list) 953 + { 954 + struct xfs_btree_cur *cur; 955 + int error; 956 + 957 + ASSERT(tp || buffer_list); 958 + ASSERT(!(tp && buffer_list)); 959 + if (whichfork == XFS_DATA_FORK) 960 + ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_BTREE); 961 + else 962 + ASSERT(ip->i_d.di_aformat == XFS_DINODE_FMT_BTREE); 963 + 964 + cur = xfs_bmbt_init_cursor(ip->i_mount, tp, ip, whichfork); 965 + if (!cur) 966 + return ENOMEM; 967 + 968 + error = xfs_btree_change_owner(cur, new_owner, buffer_list); 969 + xfs_btree_del_cursor(cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); 970 + return error; 971 + }
+4
fs/xfs/xfs_bmap_btree.h
··· 236 236 extern int xfs_bmdr_maxrecs(struct xfs_mount *, int blocklen, int leaf); 237 237 extern int xfs_bmbt_maxrecs(struct xfs_mount *, int blocklen, int leaf); 238 238 239 + extern int xfs_bmbt_change_owner(struct xfs_trans *tp, struct xfs_inode *ip, 240 + int whichfork, xfs_ino_t new_owner, 241 + struct list_head *buffer_list); 242 + 239 243 extern struct xfs_btree_cur *xfs_bmbt_init_cursor(struct xfs_mount *, 240 244 struct xfs_trans *, struct xfs_inode *, int); 241 245
+44 -25
fs/xfs/xfs_bmap_util.c
··· 612 612 613 613 if (bmv->bmv_count > ULONG_MAX / sizeof(struct getbmapx)) 614 614 return XFS_ERROR(ENOMEM); 615 - out = kmem_zalloc(bmv->bmv_count * sizeof(struct getbmapx), KM_MAYFAIL); 616 - if (!out) { 617 - out = kmem_zalloc_large(bmv->bmv_count * 618 - sizeof(struct getbmapx)); 619 - if (!out) 620 - return XFS_ERROR(ENOMEM); 621 - } 615 + out = kmem_zalloc_large(bmv->bmv_count * sizeof(struct getbmapx), 0); 616 + if (!out) 617 + return XFS_ERROR(ENOMEM); 622 618 623 619 xfs_ilock(ip, XFS_IOLOCK_SHARED); 624 620 if (whichfork == XFS_DATA_FORK && !(iflags & BMV_IF_DELALLOC)) { ··· 750 754 break; 751 755 } 752 756 753 - if (is_vmalloc_addr(out)) 754 - kmem_free_large(out); 755 - else 756 - kmem_free(out); 757 + kmem_free(out); 757 758 return error; 758 759 } 759 760 ··· 1782 1789 int taforkblks = 0; 1783 1790 __uint64_t tmp; 1784 1791 1785 - /* 1786 - * We have no way of updating owner information in the BMBT blocks for 1787 - * each inode on CRC enabled filesystems, so to avoid corrupting the 1788 - * this metadata we simply don't allow extent swaps to occur. 1789 - */ 1790 - if (xfs_sb_version_hascrc(&mp->m_sb)) 1791 - return XFS_ERROR(EINVAL); 1792 - 1793 1792 tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL); 1794 1793 if (!tempifp) { 1795 1794 error = XFS_ERROR(ENOMEM); ··· 1905 1920 goto out_trans_cancel; 1906 1921 } 1907 1922 1923 + xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); 1924 + xfs_trans_ijoin(tp, tip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); 1925 + 1926 + /* 1927 + * Before we've swapped the forks, lets set the owners of the forks 1928 + * appropriately. We have to do this as we are demand paging the btree 1929 + * buffers, and so the validation done on read will expect the owner 1930 + * field to be correctly set. Once we change the owners, we can swap the 1931 + * inode forks. 1932 + * 1933 + * Note the trickiness in setting the log flags - we set the owner log 1934 + * flag on the opposite inode (i.e. the inode we are setting the new 1935 + * owner to be) because once we swap the forks and log that, log 1936 + * recovery is going to see the fork as owned by the swapped inode, 1937 + * not the pre-swapped inodes. 1938 + */ 1939 + src_log_flags = XFS_ILOG_CORE; 1940 + target_log_flags = XFS_ILOG_CORE; 1941 + if (ip->i_d.di_version == 3 && 1942 + ip->i_d.di_format == XFS_DINODE_FMT_BTREE) { 1943 + target_log_flags |= XFS_ILOG_DOWNER; 1944 + error = xfs_bmbt_change_owner(tp, ip, XFS_DATA_FORK, 1945 + tip->i_ino, NULL); 1946 + if (error) 1947 + goto out_trans_cancel; 1948 + } 1949 + 1950 + if (tip->i_d.di_version == 3 && 1951 + tip->i_d.di_format == XFS_DINODE_FMT_BTREE) { 1952 + src_log_flags |= XFS_ILOG_DOWNER; 1953 + error = xfs_bmbt_change_owner(tp, tip, XFS_DATA_FORK, 1954 + ip->i_ino, NULL); 1955 + if (error) 1956 + goto out_trans_cancel; 1957 + } 1958 + 1908 1959 /* 1909 1960 * Swap the data forks of the inodes 1910 1961 */ ··· 1978 1957 tip->i_delayed_blks = ip->i_delayed_blks; 1979 1958 ip->i_delayed_blks = 0; 1980 1959 1981 - src_log_flags = XFS_ILOG_CORE; 1982 1960 switch (ip->i_d.di_format) { 1983 1961 case XFS_DINODE_FMT_EXTENTS: 1984 1962 /* If the extents fit in the inode, fix the ··· 1991 1971 src_log_flags |= XFS_ILOG_DEXT; 1992 1972 break; 1993 1973 case XFS_DINODE_FMT_BTREE: 1974 + ASSERT(ip->i_d.di_version < 3 || 1975 + (src_log_flags & XFS_ILOG_DOWNER)); 1994 1976 src_log_flags |= XFS_ILOG_DBROOT; 1995 1977 break; 1996 1978 } 1997 1979 1998 - target_log_flags = XFS_ILOG_CORE; 1999 1980 switch (tip->i_d.di_format) { 2000 1981 case XFS_DINODE_FMT_EXTENTS: 2001 1982 /* If the extents fit in the inode, fix the ··· 2011 1990 break; 2012 1991 case XFS_DINODE_FMT_BTREE: 2013 1992 target_log_flags |= XFS_ILOG_DBROOT; 1993 + ASSERT(tip->i_d.di_version < 3 || 1994 + (target_log_flags & XFS_ILOG_DOWNER)); 2014 1995 break; 2015 1996 } 2016 - 2017 - 2018 - xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); 2019 - xfs_trans_ijoin(tp, tip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); 2020 1997 2021 1998 xfs_trans_log_inode(tp, ip, src_log_flags); 2022 1999 xfs_trans_log_inode(tp, tip, target_log_flags);
+152 -18
fs/xfs/xfs_btree.c
··· 855 855 return xfs_btree_readahead_sblock(cur, lr, block); 856 856 } 857 857 858 + STATIC xfs_daddr_t 859 + xfs_btree_ptr_to_daddr( 860 + struct xfs_btree_cur *cur, 861 + union xfs_btree_ptr *ptr) 862 + { 863 + if (cur->bc_flags & XFS_BTREE_LONG_PTRS) { 864 + ASSERT(ptr->l != cpu_to_be64(NULLDFSBNO)); 865 + 866 + return XFS_FSB_TO_DADDR(cur->bc_mp, be64_to_cpu(ptr->l)); 867 + } else { 868 + ASSERT(cur->bc_private.a.agno != NULLAGNUMBER); 869 + ASSERT(ptr->s != cpu_to_be32(NULLAGBLOCK)); 870 + 871 + return XFS_AGB_TO_DADDR(cur->bc_mp, cur->bc_private.a.agno, 872 + be32_to_cpu(ptr->s)); 873 + } 874 + } 875 + 876 + /* 877 + * Readahead @count btree blocks at the given @ptr location. 878 + * 879 + * We don't need to care about long or short form btrees here as we have a 880 + * method of converting the ptr directly to a daddr available to us. 881 + */ 882 + STATIC void 883 + xfs_btree_readahead_ptr( 884 + struct xfs_btree_cur *cur, 885 + union xfs_btree_ptr *ptr, 886 + xfs_extlen_t count) 887 + { 888 + xfs_buf_readahead(cur->bc_mp->m_ddev_targp, 889 + xfs_btree_ptr_to_daddr(cur, ptr), 890 + cur->bc_mp->m_bsize * count, cur->bc_ops->buf_ops); 891 + } 892 + 858 893 /* 859 894 * Set the buffer for level "lev" in the cursor to bp, releasing 860 895 * any previous buffer. ··· 1105 1070 else { 1106 1071 ptr->s = cpu_to_be32(xfs_daddr_to_agbno(cur->bc_mp, 1107 1072 XFS_BUF_ADDR(bp))); 1108 - } 1109 - } 1110 - 1111 - STATIC xfs_daddr_t 1112 - xfs_btree_ptr_to_daddr( 1113 - struct xfs_btree_cur *cur, 1114 - union xfs_btree_ptr *ptr) 1115 - { 1116 - if (cur->bc_flags & XFS_BTREE_LONG_PTRS) { 1117 - ASSERT(ptr->l != cpu_to_be64(NULLDFSBNO)); 1118 - 1119 - return XFS_FSB_TO_DADDR(cur->bc_mp, be64_to_cpu(ptr->l)); 1120 - } else { 1121 - ASSERT(cur->bc_private.a.agno != NULLAGNUMBER); 1122 - ASSERT(ptr->s != cpu_to_be32(NULLAGBLOCK)); 1123 - 1124 - return XFS_AGB_TO_DADDR(cur->bc_mp, cur->bc_private.a.agno, 1125 - be32_to_cpu(ptr->s)); 1126 1073 } 1127 1074 } 1128 1075 ··· 3884 3867 */ 3885 3868 *recp = xfs_btree_rec_addr(cur, ptr, block); 3886 3869 *stat = 1; 3870 + return 0; 3871 + } 3872 + 3873 + /* 3874 + * Change the owner of a btree. 3875 + * 3876 + * The mechanism we use here is ordered buffer logging. Because we don't know 3877 + * how many buffers were are going to need to modify, we don't really want to 3878 + * have to make transaction reservations for the worst case of every buffer in a 3879 + * full size btree as that may be more space that we can fit in the log.... 3880 + * 3881 + * We do the btree walk in the most optimal manner possible - we have sibling 3882 + * pointers so we can just walk all the blocks on each level from left to right 3883 + * in a single pass, and then move to the next level and do the same. We can 3884 + * also do readahead on the sibling pointers to get IO moving more quickly, 3885 + * though for slow disks this is unlikely to make much difference to performance 3886 + * as the amount of CPU work we have to do before moving to the next block is 3887 + * relatively small. 3888 + * 3889 + * For each btree block that we load, modify the owner appropriately, set the 3890 + * buffer as an ordered buffer and log it appropriately. We need to ensure that 3891 + * we mark the region we change dirty so that if the buffer is relogged in 3892 + * a subsequent transaction the changes we make here as an ordered buffer are 3893 + * correctly relogged in that transaction. If we are in recovery context, then 3894 + * just queue the modified buffer as delayed write buffer so the transaction 3895 + * recovery completion writes the changes to disk. 3896 + */ 3897 + static int 3898 + xfs_btree_block_change_owner( 3899 + struct xfs_btree_cur *cur, 3900 + int level, 3901 + __uint64_t new_owner, 3902 + struct list_head *buffer_list) 3903 + { 3904 + struct xfs_btree_block *block; 3905 + struct xfs_buf *bp; 3906 + union xfs_btree_ptr rptr; 3907 + 3908 + /* do right sibling readahead */ 3909 + xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA); 3910 + 3911 + /* modify the owner */ 3912 + block = xfs_btree_get_block(cur, level, &bp); 3913 + if (cur->bc_flags & XFS_BTREE_LONG_PTRS) 3914 + block->bb_u.l.bb_owner = cpu_to_be64(new_owner); 3915 + else 3916 + block->bb_u.s.bb_owner = cpu_to_be32(new_owner); 3917 + 3918 + /* 3919 + * If the block is a root block hosted in an inode, we might not have a 3920 + * buffer pointer here and we shouldn't attempt to log the change as the 3921 + * information is already held in the inode and discarded when the root 3922 + * block is formatted into the on-disk inode fork. We still change it, 3923 + * though, so everything is consistent in memory. 3924 + */ 3925 + if (bp) { 3926 + if (cur->bc_tp) { 3927 + xfs_trans_ordered_buf(cur->bc_tp, bp); 3928 + xfs_btree_log_block(cur, bp, XFS_BB_OWNER); 3929 + } else { 3930 + xfs_buf_delwri_queue(bp, buffer_list); 3931 + } 3932 + } else { 3933 + ASSERT(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE); 3934 + ASSERT(level == cur->bc_nlevels - 1); 3935 + } 3936 + 3937 + /* now read rh sibling block for next iteration */ 3938 + xfs_btree_get_sibling(cur, block, &rptr, XFS_BB_RIGHTSIB); 3939 + if (xfs_btree_ptr_is_null(cur, &rptr)) 3940 + return ENOENT; 3941 + 3942 + return xfs_btree_lookup_get_block(cur, level, &rptr, &block); 3943 + } 3944 + 3945 + int 3946 + xfs_btree_change_owner( 3947 + struct xfs_btree_cur *cur, 3948 + __uint64_t new_owner, 3949 + struct list_head *buffer_list) 3950 + { 3951 + union xfs_btree_ptr lptr; 3952 + int level; 3953 + struct xfs_btree_block *block = NULL; 3954 + int error = 0; 3955 + 3956 + cur->bc_ops->init_ptr_from_cur(cur, &lptr); 3957 + 3958 + /* for each level */ 3959 + for (level = cur->bc_nlevels - 1; level >= 0; level--) { 3960 + /* grab the left hand block */ 3961 + error = xfs_btree_lookup_get_block(cur, level, &lptr, &block); 3962 + if (error) 3963 + return error; 3964 + 3965 + /* readahead the left most block for the next level down */ 3966 + if (level > 0) { 3967 + union xfs_btree_ptr *ptr; 3968 + 3969 + ptr = xfs_btree_ptr_addr(cur, 1, block); 3970 + xfs_btree_readahead_ptr(cur, ptr, 1); 3971 + 3972 + /* save for the next iteration of the loop */ 3973 + lptr = *ptr; 3974 + } 3975 + 3976 + /* for each buffer in the level */ 3977 + do { 3978 + error = xfs_btree_block_change_owner(cur, level, 3979 + new_owner, 3980 + buffer_list); 3981 + } while (!error); 3982 + 3983 + if (error != ENOENT) 3984 + return error; 3985 + } 3986 + 3887 3987 return 0; 3888 3988 }
+12 -7
fs/xfs/xfs_btree.h
··· 121 121 /* 122 122 * For logging record fields. 123 123 */ 124 - #define XFS_BB_MAGIC 0x01 125 - #define XFS_BB_LEVEL 0x02 126 - #define XFS_BB_NUMRECS 0x04 127 - #define XFS_BB_LEFTSIB 0x08 128 - #define XFS_BB_RIGHTSIB 0x10 129 - #define XFS_BB_BLKNO 0x20 124 + #define XFS_BB_MAGIC (1 << 0) 125 + #define XFS_BB_LEVEL (1 << 1) 126 + #define XFS_BB_NUMRECS (1 << 2) 127 + #define XFS_BB_LEFTSIB (1 << 3) 128 + #define XFS_BB_RIGHTSIB (1 << 4) 129 + #define XFS_BB_BLKNO (1 << 5) 130 + #define XFS_BB_LSN (1 << 6) 131 + #define XFS_BB_UUID (1 << 7) 132 + #define XFS_BB_OWNER (1 << 8) 130 133 #define XFS_BB_NUM_BITS 5 131 134 #define XFS_BB_ALL_BITS ((1 << XFS_BB_NUM_BITS) - 1) 132 - #define XFS_BB_NUM_BITS_CRC 8 135 + #define XFS_BB_NUM_BITS_CRC 9 133 136 #define XFS_BB_ALL_BITS_CRC ((1 << XFS_BB_NUM_BITS_CRC) - 1) 134 137 135 138 /* ··· 445 442 int xfs_btree_insert(struct xfs_btree_cur *, int *); 446 443 int xfs_btree_delete(struct xfs_btree_cur *, int *); 447 444 int xfs_btree_get_rec(struct xfs_btree_cur *, union xfs_btree_rec **, int *); 445 + int xfs_btree_change_owner(struct xfs_btree_cur *cur, __uint64_t new_owner, 446 + struct list_head *buffer_list); 448 447 449 448 /* 450 449 * btree block CRC helpers
+19 -5
fs/xfs/xfs_buf_item.c
··· 613 613 } 614 614 } 615 615 } 616 - if (clean || aborted) { 617 - if (atomic_dec_and_test(&bip->bli_refcount)) { 618 - ASSERT(!aborted || XFS_FORCED_SHUTDOWN(lip->li_mountp)); 616 + 617 + /* 618 + * Clean buffers, by definition, cannot be in the AIL. However, aborted 619 + * buffers may be dirty and hence in the AIL. Therefore if we are 620 + * aborting a buffer and we've just taken the last refernce away, we 621 + * have to check if it is in the AIL before freeing it. We need to free 622 + * it in this case, because an aborted transaction has already shut the 623 + * filesystem down and this is the last chance we will have to do so. 624 + */ 625 + if (atomic_dec_and_test(&bip->bli_refcount)) { 626 + if (clean) 627 + xfs_buf_item_relse(bp); 628 + else if (aborted) { 629 + ASSERT(XFS_FORCED_SHUTDOWN(lip->li_mountp)); 630 + if (lip->li_flags & XFS_LI_IN_AIL) { 631 + xfs_trans_ail_delete(lip->li_ailp, lip, 632 + SHUTDOWN_LOG_IO_ERROR); 633 + } 619 634 xfs_buf_item_relse(bp); 620 635 } 621 - } else 622 - atomic_dec(&bip->bli_refcount); 636 + } 623 637 624 638 if (!(flags & XFS_BLI_HOLD)) 625 639 xfs_buf_relse(bp);
+1
fs/xfs/xfs_da_btree.c
··· 635 635 xfs_trans_log_buf(tp, bp, 0, size - 1); 636 636 637 637 bp->b_ops = blk1->bp->b_ops; 638 + xfs_trans_buf_copy_type(bp, blk1->bp); 638 639 blk1->bp = bp; 639 640 blk1->blkno = blkno; 640 641
+13 -7
fs/xfs/xfs_dir2_leaf.c
··· 180 180 return true; 181 181 } 182 182 183 + /* 184 + * We verify the magic numbers before decoding the leaf header so that on debug 185 + * kernels we don't get assertion failures in xfs_dir3_leaf_hdr_from_disk() due 186 + * to incorrect magic numbers. 187 + */ 183 188 static bool 184 189 xfs_dir3_leaf_verify( 185 190 struct xfs_buf *bp, ··· 196 191 197 192 ASSERT(magic == XFS_DIR2_LEAF1_MAGIC || magic == XFS_DIR2_LEAFN_MAGIC); 198 193 199 - xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); 200 194 if (xfs_sb_version_hascrc(&mp->m_sb)) { 201 195 struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr; 196 + __uint16_t magic3; 202 197 203 - if ((magic == XFS_DIR2_LEAF1_MAGIC && 204 - leafhdr.magic != XFS_DIR3_LEAF1_MAGIC) || 205 - (magic == XFS_DIR2_LEAFN_MAGIC && 206 - leafhdr.magic != XFS_DIR3_LEAFN_MAGIC)) 198 + magic3 = (magic == XFS_DIR2_LEAF1_MAGIC) ? XFS_DIR3_LEAF1_MAGIC 199 + : XFS_DIR3_LEAFN_MAGIC; 200 + 201 + if (leaf3->info.hdr.magic != cpu_to_be16(magic3)) 207 202 return false; 208 - 209 203 if (!uuid_equal(&leaf3->info.uuid, &mp->m_sb.sb_uuid)) 210 204 return false; 211 205 if (be64_to_cpu(leaf3->info.blkno) != bp->b_bn) 212 206 return false; 213 207 } else { 214 - if (leafhdr.magic != magic) 208 + if (leaf->hdr.info.magic != cpu_to_be16(magic)) 215 209 return false; 216 210 } 211 + 212 + xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); 217 213 return xfs_dir3_leaf_check_int(mp, &leafhdr, leaf); 218 214 } 219 215
+2 -1
fs/xfs/xfs_dquot_item.c
··· 142 142 STATIC uint 143 143 xfs_qm_dquot_logitem_push( 144 144 struct xfs_log_item *lip, 145 - struct list_head *buffer_list) 145 + struct list_head *buffer_list) __releases(&lip->li_ailp->xa_lock) 146 + __acquires(&lip->li_ailp->xa_lock) 146 147 { 147 148 struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot; 148 149 struct xfs_buf *bp = NULL;
+2 -1
fs/xfs/xfs_extent_busy.c
··· 160 160 struct xfs_extent_busy *busyp, 161 161 xfs_agblock_t fbno, 162 162 xfs_extlen_t flen, 163 - bool userdata) 163 + bool userdata) __releases(&pag->pagb_lock) 164 + __acquires(&pag->pagb_lock) 164 165 { 165 166 xfs_agblock_t fend = fbno + flen; 166 167 xfs_agblock_t bbno = busyp->bno;
+2 -2
fs/xfs/xfs_icache.c
··· 48 48 /* 49 49 * Allocate and initialise an xfs_inode. 50 50 */ 51 - STATIC struct xfs_inode * 51 + struct xfs_inode * 52 52 xfs_inode_alloc( 53 53 struct xfs_mount *mp, 54 54 xfs_ino_t ino) ··· 98 98 kmem_zone_free(xfs_inode_zone, ip); 99 99 } 100 100 101 - STATIC void 101 + void 102 102 xfs_inode_free( 103 103 struct xfs_inode *ip) 104 104 {
+4
fs/xfs/xfs_icache.h
··· 42 42 int xfs_iget(struct xfs_mount *mp, struct xfs_trans *tp, xfs_ino_t ino, 43 43 uint flags, uint lock_flags, xfs_inode_t **ipp); 44 44 45 + /* recovery needs direct inode allocation capability */ 46 + struct xfs_inode * xfs_inode_alloc(struct xfs_mount *mp, xfs_ino_t ino); 47 + void xfs_inode_free(struct xfs_inode *ip); 48 + 45 49 void xfs_reclaim_worker(struct work_struct *work); 46 50 47 51 int xfs_reclaim_inodes(struct xfs_mount *mp, int mode);
+4 -6
fs/xfs/xfs_inode_buf.c
··· 53 53 i * mp->m_sb.sb_inodesize); 54 54 if (!dip->di_next_unlinked) { 55 55 xfs_alert(mp, 56 - "Detected bogus zero next_unlinked field in incore inode buffer 0x%p.", 57 - bp); 58 - ASSERT(dip->di_next_unlinked); 56 + "Detected bogus zero next_unlinked field in inode %d buffer 0x%llx.", 57 + i, (long long)bp->b_bn); 59 58 } 60 59 } 61 60 } ··· 105 106 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_HIGH, 106 107 mp, dip); 107 108 #ifdef DEBUG 108 - xfs_emerg(mp, 109 + xfs_alert(mp, 109 110 "bad inode magic/vsn daddr %lld #%d (magic=%x)", 110 111 (unsigned long long)bp->b_bn, i, 111 112 be16_to_cpu(dip->di_magic)); 112 - ASSERT(0); 113 113 #endif 114 114 } 115 115 } ··· 194 196 return 0; 195 197 } 196 198 197 - STATIC void 199 + void 198 200 xfs_dinode_from_disk( 199 201 xfs_icdinode_t *to, 200 202 xfs_dinode_t *from)
+9 -9
fs/xfs/xfs_inode_buf.h
··· 32 32 ushort im_boffset; /* inode offset in block in bytes */ 33 33 }; 34 34 35 - int xfs_imap_to_bp(struct xfs_mount *, struct xfs_trans *, 36 - struct xfs_imap *, struct xfs_dinode **, 37 - struct xfs_buf **, uint, uint); 38 - int xfs_iread(struct xfs_mount *, struct xfs_trans *, 39 - struct xfs_inode *, uint); 40 - void xfs_dinode_calc_crc(struct xfs_mount *, struct xfs_dinode *); 41 - void xfs_dinode_to_disk(struct xfs_dinode *, 42 - struct xfs_icdinode *); 35 + int xfs_imap_to_bp(struct xfs_mount *, struct xfs_trans *, 36 + struct xfs_imap *, struct xfs_dinode **, 37 + struct xfs_buf **, uint, uint); 38 + int xfs_iread(struct xfs_mount *, struct xfs_trans *, 39 + struct xfs_inode *, uint); 40 + void xfs_dinode_calc_crc(struct xfs_mount *, struct xfs_dinode *); 41 + void xfs_dinode_to_disk(struct xfs_dinode *to, struct xfs_icdinode *from); 42 + void xfs_dinode_from_disk(struct xfs_icdinode *to, struct xfs_dinode *from); 43 43 44 44 #if defined(DEBUG) 45 - void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *); 45 + void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *); 46 46 #else 47 47 #define xfs_inobp_check(mp, bp) 48 48 #endif /* DEBUG */
+12 -24
fs/xfs/xfs_ioctl.c
··· 71 71 int hsize; 72 72 xfs_handle_t handle; 73 73 struct inode *inode; 74 - struct fd f = {0}; 74 + struct fd f = {NULL}; 75 75 struct path path; 76 76 int error; 77 77 struct xfs_inode *ip; ··· 456 456 if (IS_ERR(dentry)) 457 457 return PTR_ERR(dentry); 458 458 459 - kbuf = kmem_zalloc(al_hreq.buflen, KM_SLEEP | KM_MAYFAIL); 460 - if (!kbuf) { 461 - kbuf = kmem_zalloc_large(al_hreq.buflen); 462 - if (!kbuf) 463 - goto out_dput; 464 - } 459 + kbuf = kmem_zalloc_large(al_hreq.buflen, KM_SLEEP); 460 + if (!kbuf) 461 + goto out_dput; 465 462 466 463 cursor = (attrlist_cursor_kern_t *)&al_hreq.pos; 467 464 error = -xfs_attr_list(XFS_I(dentry->d_inode), kbuf, al_hreq.buflen, ··· 469 472 if (copy_to_user(al_hreq.buffer, kbuf, al_hreq.buflen)) 470 473 error = -EFAULT; 471 474 472 - out_kfree: 473 - if (is_vmalloc_addr(kbuf)) 474 - kmem_free_large(kbuf); 475 - else 476 - kmem_free(kbuf); 477 - out_dput: 475 + out_kfree: 476 + kmem_free(kbuf); 477 + out_dput: 478 478 dput(dentry); 479 479 return error; 480 480 } ··· 489 495 490 496 if (*len > XATTR_SIZE_MAX) 491 497 return EINVAL; 492 - kbuf = kmem_zalloc(*len, KM_SLEEP | KM_MAYFAIL); 493 - if (!kbuf) { 494 - kbuf = kmem_zalloc_large(*len); 495 - if (!kbuf) 496 - return ENOMEM; 497 - } 498 + kbuf = kmem_zalloc_large(*len, KM_SLEEP); 499 + if (!kbuf) 500 + return ENOMEM; 498 501 499 502 error = xfs_attr_get(XFS_I(inode), name, kbuf, (int *)len, flags); 500 503 if (error) ··· 500 509 if (copy_to_user(ubuf, kbuf, *len)) 501 510 error = EFAULT; 502 511 503 - out_kfree: 504 - if (is_vmalloc_addr(kbuf)) 505 - kmem_free_large(kbuf); 506 - else 507 - kmem_free(kbuf); 512 + out_kfree: 513 + kmem_free(kbuf); 508 514 return error; 509 515 } 510 516
+6 -12
fs/xfs/xfs_ioctl32.c
··· 371 371 return PTR_ERR(dentry); 372 372 373 373 error = -ENOMEM; 374 - kbuf = kmem_zalloc(al_hreq.buflen, KM_SLEEP | KM_MAYFAIL); 375 - if (!kbuf) { 376 - kbuf = kmem_zalloc_large(al_hreq.buflen); 377 - if (!kbuf) 378 - goto out_dput; 379 - } 374 + kbuf = kmem_zalloc_large(al_hreq.buflen, KM_SLEEP); 375 + if (!kbuf) 376 + goto out_dput; 380 377 381 378 cursor = (attrlist_cursor_kern_t *)&al_hreq.pos; 382 379 error = -xfs_attr_list(XFS_I(dentry->d_inode), kbuf, al_hreq.buflen, ··· 384 387 if (copy_to_user(compat_ptr(al_hreq.buffer), kbuf, al_hreq.buflen)) 385 388 error = -EFAULT; 386 389 387 - out_kfree: 388 - if (is_vmalloc_addr(kbuf)) 389 - kmem_free_large(kbuf); 390 - else 391 - kmem_free(kbuf); 392 - out_dput: 390 + out_kfree: 391 + kmem_free(kbuf); 392 + out_dput: 393 393 dput(dentry); 394 394 return error; 395 395 }
+4 -3
fs/xfs/xfs_itable.c
··· 495 495 /* 496 496 * Done, we're either out of filesystem or space to put the data. 497 497 */ 498 - kmem_free_large(irbuf); 498 + kmem_free(irbuf); 499 499 *ubcountp = ubelem; 500 500 /* 501 501 * Found some inodes, return them now and return the error next time. ··· 541 541 * at the expense of the error case. 542 542 */ 543 543 544 - ino = (xfs_ino_t)*lastinop; 545 - error = xfs_bulkstat_one(mp, ino, buffer, sizeof(xfs_bstat_t), 0, &res); 544 + ino = *lastinop; 545 + error = xfs_bulkstat_one(mp, ino, buffer, sizeof(xfs_bstat_t), 546 + NULL, &res); 546 547 if (error) { 547 548 /* 548 549 * Special case way failed, do it the "long" way
+2 -1
fs/xfs/xfs_log.c
··· 257 257 struct xlog *log, 258 258 struct xlog_grant_head *head, 259 259 struct xlog_ticket *tic, 260 - int need_bytes) 260 + int need_bytes) __releases(&head->lock) 261 + __acquires(&head->lock) 261 262 { 262 263 list_add_tail(&tic->t_queue, &head->waiters); 263 264
+6 -2
fs/xfs/xfs_log_format.h
··· 474 474 #define XFS_ILOG_ADATA 0x040 /* log i_af.if_data */ 475 475 #define XFS_ILOG_AEXT 0x080 /* log i_af.if_extents */ 476 476 #define XFS_ILOG_ABROOT 0x100 /* log i_af.i_broot */ 477 + #define XFS_ILOG_DOWNER 0x200 /* change the data fork owner on replay */ 478 + #define XFS_ILOG_AOWNER 0x400 /* change the attr fork owner on replay */ 477 479 478 480 479 481 /* ··· 489 487 #define XFS_ILOG_NONCORE (XFS_ILOG_DDATA | XFS_ILOG_DEXT | \ 490 488 XFS_ILOG_DBROOT | XFS_ILOG_DEV | \ 491 489 XFS_ILOG_UUID | XFS_ILOG_ADATA | \ 492 - XFS_ILOG_AEXT | XFS_ILOG_ABROOT) 490 + XFS_ILOG_AEXT | XFS_ILOG_ABROOT | \ 491 + XFS_ILOG_DOWNER | XFS_ILOG_AOWNER) 493 492 494 493 #define XFS_ILOG_DFORK (XFS_ILOG_DDATA | XFS_ILOG_DEXT | \ 495 494 XFS_ILOG_DBROOT) ··· 502 499 XFS_ILOG_DEXT | XFS_ILOG_DBROOT | \ 503 500 XFS_ILOG_DEV | XFS_ILOG_UUID | \ 504 501 XFS_ILOG_ADATA | XFS_ILOG_AEXT | \ 505 - XFS_ILOG_ABROOT | XFS_ILOG_TIMESTAMP) 502 + XFS_ILOG_ABROOT | XFS_ILOG_TIMESTAMP | \ 503 + XFS_ILOG_DOWNER | XFS_ILOG_AOWNER) 506 504 507 505 static inline int xfs_ilog_fbroot(int w) 508 506 {
+97 -25
fs/xfs/xfs_log_recover.c
··· 2014 2014 case XFS_ATTR3_RMT_MAGIC: 2015 2015 return be64_to_cpu(((struct xfs_attr3_rmt_hdr *)blk)->rm_lsn); 2016 2016 case XFS_SB_MAGIC: 2017 - return be64_to_cpu(((struct xfs_sb *)blk)->sb_lsn); 2017 + return be64_to_cpu(((struct xfs_dsb *)blk)->sb_lsn); 2018 2018 default: 2019 2019 break; 2020 2020 } ··· 2629 2629 return error; 2630 2630 } 2631 2631 2632 + /* 2633 + * Inode fork owner changes 2634 + * 2635 + * If we have been told that we have to reparent the inode fork, it's because an 2636 + * extent swap operation on a CRC enabled filesystem has been done and we are 2637 + * replaying it. We need to walk the BMBT of the appropriate fork and change the 2638 + * owners of it. 2639 + * 2640 + * The complexity here is that we don't have an inode context to work with, so 2641 + * after we've replayed the inode we need to instantiate one. This is where the 2642 + * fun begins. 2643 + * 2644 + * We are in the middle of log recovery, so we can't run transactions. That 2645 + * means we cannot use cache coherent inode instantiation via xfs_iget(), as 2646 + * that will result in the corresponding iput() running the inode through 2647 + * xfs_inactive(). If we've just replayed an inode core that changes the link 2648 + * count to zero (i.e. it's been unlinked), then xfs_inactive() will run 2649 + * transactions (bad!). 2650 + * 2651 + * So, to avoid this, we instantiate an inode directly from the inode core we've 2652 + * just recovered. We have the buffer still locked, and all we really need to 2653 + * instantiate is the inode core and the forks being modified. We can do this 2654 + * manually, then run the inode btree owner change, and then tear down the 2655 + * xfs_inode without having to run any transactions at all. 2656 + * 2657 + * Also, because we don't have a transaction context available here but need to 2658 + * gather all the buffers we modify for writeback so we pass the buffer_list 2659 + * instead for the operation to use. 2660 + */ 2661 + 2662 + STATIC int 2663 + xfs_recover_inode_owner_change( 2664 + struct xfs_mount *mp, 2665 + struct xfs_dinode *dip, 2666 + struct xfs_inode_log_format *in_f, 2667 + struct list_head *buffer_list) 2668 + { 2669 + struct xfs_inode *ip; 2670 + int error; 2671 + 2672 + ASSERT(in_f->ilf_fields & (XFS_ILOG_DOWNER|XFS_ILOG_AOWNER)); 2673 + 2674 + ip = xfs_inode_alloc(mp, in_f->ilf_ino); 2675 + if (!ip) 2676 + return ENOMEM; 2677 + 2678 + /* instantiate the inode */ 2679 + xfs_dinode_from_disk(&ip->i_d, dip); 2680 + ASSERT(ip->i_d.di_version >= 3); 2681 + 2682 + error = xfs_iformat_fork(ip, dip); 2683 + if (error) 2684 + goto out_free_ip; 2685 + 2686 + 2687 + if (in_f->ilf_fields & XFS_ILOG_DOWNER) { 2688 + ASSERT(in_f->ilf_fields & XFS_ILOG_DBROOT); 2689 + error = xfs_bmbt_change_owner(NULL, ip, XFS_DATA_FORK, 2690 + ip->i_ino, buffer_list); 2691 + if (error) 2692 + goto out_free_ip; 2693 + } 2694 + 2695 + if (in_f->ilf_fields & XFS_ILOG_AOWNER) { 2696 + ASSERT(in_f->ilf_fields & XFS_ILOG_ABROOT); 2697 + error = xfs_bmbt_change_owner(NULL, ip, XFS_ATTR_FORK, 2698 + ip->i_ino, buffer_list); 2699 + if (error) 2700 + goto out_free_ip; 2701 + } 2702 + 2703 + out_free_ip: 2704 + xfs_inode_free(ip); 2705 + return error; 2706 + } 2707 + 2632 2708 STATIC int 2633 2709 xlog_recover_inode_pass2( 2634 2710 struct xlog *log, ··· 2757 2681 error = bp->b_error; 2758 2682 if (error) { 2759 2683 xfs_buf_ioerror_alert(bp, "xlog_recover_do..(read#2)"); 2760 - xfs_buf_relse(bp); 2761 - goto error; 2684 + goto out_release; 2762 2685 } 2763 2686 ASSERT(in_f->ilf_fields & XFS_ILOG_CORE); 2764 2687 dip = (xfs_dinode_t *)xfs_buf_offset(bp, in_f->ilf_boffset); ··· 2767 2692 * like an inode! 2768 2693 */ 2769 2694 if (unlikely(dip->di_magic != cpu_to_be16(XFS_DINODE_MAGIC))) { 2770 - xfs_buf_relse(bp); 2771 2695 xfs_alert(mp, 2772 2696 "%s: Bad inode magic number, dip = 0x%p, dino bp = 0x%p, ino = %Ld", 2773 2697 __func__, dip, bp, in_f->ilf_ino); 2774 2698 XFS_ERROR_REPORT("xlog_recover_inode_pass2(1)", 2775 2699 XFS_ERRLEVEL_LOW, mp); 2776 2700 error = EFSCORRUPTED; 2777 - goto error; 2701 + goto out_release; 2778 2702 } 2779 2703 dicp = item->ri_buf[1].i_addr; 2780 2704 if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) { 2781 - xfs_buf_relse(bp); 2782 2705 xfs_alert(mp, 2783 2706 "%s: Bad inode log record, rec ptr 0x%p, ino %Ld", 2784 2707 __func__, item, in_f->ilf_ino); 2785 2708 XFS_ERROR_REPORT("xlog_recover_inode_pass2(2)", 2786 2709 XFS_ERRLEVEL_LOW, mp); 2787 2710 error = EFSCORRUPTED; 2788 - goto error; 2711 + goto out_release; 2789 2712 } 2790 2713 2791 2714 /* 2792 2715 * If the inode has an LSN in it, recover the inode only if it's less 2793 - * than the lsn of the transaction we are replaying. 2716 + * than the lsn of the transaction we are replaying. Note: we still 2717 + * need to replay an owner change even though the inode is more recent 2718 + * than the transaction as there is no guarantee that all the btree 2719 + * blocks are more recent than this transaction, too. 2794 2720 */ 2795 2721 if (dip->di_version >= 3) { 2796 2722 xfs_lsn_t lsn = be64_to_cpu(dip->di_lsn); ··· 2799 2723 if (lsn && lsn != -1 && XFS_LSN_CMP(lsn, current_lsn) >= 0) { 2800 2724 trace_xfs_log_recover_inode_skip(log, in_f); 2801 2725 error = 0; 2802 - goto out_release; 2726 + goto out_owner_change; 2803 2727 } 2804 2728 } 2805 2729 ··· 2821 2745 dicp->di_flushiter < (DI_MAX_FLUSH >> 1)) { 2822 2746 /* do nothing */ 2823 2747 } else { 2824 - xfs_buf_relse(bp); 2825 2748 trace_xfs_log_recover_inode_skip(log, in_f); 2826 2749 error = 0; 2827 - goto error; 2750 + goto out_release; 2828 2751 } 2829 2752 } 2830 2753 ··· 2835 2760 (dicp->di_format != XFS_DINODE_FMT_BTREE)) { 2836 2761 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(3)", 2837 2762 XFS_ERRLEVEL_LOW, mp, dicp); 2838 - xfs_buf_relse(bp); 2839 2763 xfs_alert(mp, 2840 2764 "%s: Bad regular inode log record, rec ptr 0x%p, " 2841 2765 "ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", 2842 2766 __func__, item, dip, bp, in_f->ilf_ino); 2843 2767 error = EFSCORRUPTED; 2844 - goto error; 2768 + goto out_release; 2845 2769 } 2846 2770 } else if (unlikely(S_ISDIR(dicp->di_mode))) { 2847 2771 if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) && ··· 2848 2774 (dicp->di_format != XFS_DINODE_FMT_LOCAL)) { 2849 2775 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(4)", 2850 2776 XFS_ERRLEVEL_LOW, mp, dicp); 2851 - xfs_buf_relse(bp); 2852 2777 xfs_alert(mp, 2853 2778 "%s: Bad dir inode log record, rec ptr 0x%p, " 2854 2779 "ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", 2855 2780 __func__, item, dip, bp, in_f->ilf_ino); 2856 2781 error = EFSCORRUPTED; 2857 - goto error; 2782 + goto out_release; 2858 2783 } 2859 2784 } 2860 2785 if (unlikely(dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks)){ 2861 2786 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(5)", 2862 2787 XFS_ERRLEVEL_LOW, mp, dicp); 2863 - xfs_buf_relse(bp); 2864 2788 xfs_alert(mp, 2865 2789 "%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, " 2866 2790 "dino bp 0x%p, ino %Ld, total extents = %d, nblocks = %Ld", ··· 2866 2794 dicp->di_nextents + dicp->di_anextents, 2867 2795 dicp->di_nblocks); 2868 2796 error = EFSCORRUPTED; 2869 - goto error; 2797 + goto out_release; 2870 2798 } 2871 2799 if (unlikely(dicp->di_forkoff > mp->m_sb.sb_inodesize)) { 2872 2800 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(6)", 2873 2801 XFS_ERRLEVEL_LOW, mp, dicp); 2874 - xfs_buf_relse(bp); 2875 2802 xfs_alert(mp, 2876 2803 "%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, " 2877 2804 "dino bp 0x%p, ino %Ld, forkoff 0x%x", __func__, 2878 2805 item, dip, bp, in_f->ilf_ino, dicp->di_forkoff); 2879 2806 error = EFSCORRUPTED; 2880 - goto error; 2807 + goto out_release; 2881 2808 } 2882 2809 isize = xfs_icdinode_size(dicp->di_version); 2883 2810 if (unlikely(item->ri_buf[1].i_len > isize)) { 2884 2811 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(7)", 2885 2812 XFS_ERRLEVEL_LOW, mp, dicp); 2886 - xfs_buf_relse(bp); 2887 2813 xfs_alert(mp, 2888 2814 "%s: Bad inode log record length %d, rec ptr 0x%p", 2889 2815 __func__, item->ri_buf[1].i_len, item); 2890 2816 error = EFSCORRUPTED; 2891 - goto error; 2817 + goto out_release; 2892 2818 } 2893 2819 2894 2820 /* The core is in in-core format */ ··· 2912 2842 } 2913 2843 2914 2844 if (in_f->ilf_size == 2) 2915 - goto write_inode_buffer; 2845 + goto out_owner_change; 2916 2846 len = item->ri_buf[2].i_len; 2917 2847 src = item->ri_buf[2].i_addr; 2918 2848 ASSERT(in_f->ilf_size <= 4); ··· 2973 2903 default: 2974 2904 xfs_warn(log->l_mp, "%s: Invalid flag", __func__); 2975 2905 ASSERT(0); 2976 - xfs_buf_relse(bp); 2977 2906 error = EIO; 2978 - goto error; 2907 + goto out_release; 2979 2908 } 2980 2909 } 2981 2910 2982 - write_inode_buffer: 2911 + out_owner_change: 2912 + if (in_f->ilf_fields & (XFS_ILOG_DOWNER|XFS_ILOG_AOWNER)) 2913 + error = xfs_recover_inode_owner_change(mp, dip, in_f, 2914 + buffer_list); 2983 2915 /* re-generate the checksum. */ 2984 2916 xfs_dinode_calc_crc(log->l_mp, dip); 2985 2917
+2
fs/xfs/xfs_symlink.c
··· 41 41 #include "xfs_trans_space.h" 42 42 #include "xfs_trace.h" 43 43 #include "xfs_symlink.h" 44 + #include "xfs_buf_item.h" 44 45 45 46 /* ----- Kernel only functions below ----- */ 46 47 STATIC int ··· 364 363 pathlen -= byte_cnt; 365 364 offset += byte_cnt; 366 365 366 + xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SYMLINK_BUF); 367 367 xfs_trans_log_buf(tp, bp, 0, (buf + byte_cnt - 1) - 368 368 (char *)bp->b_addr); 369 369 }