aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-12 19:13:41 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-12 19:13:41 -0400
commite0ea4045bce3cee84e35746fb98946ca36781248 (patch)
tree71409476f4b9acb0b441de1bdb51bf035f1fc5ad
parent48efe453e6b29561f78a1df55c7f58375259cb8c (diff)
parent08474ed639e971e9d5a877cf7aba7ef91d847ae9 (diff)
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()
-rw-r--r--fs/xfs/kmem.c15
-rw-r--r--fs/xfs/kmem.h9
-rw-r--r--fs/xfs/xfs_acl.c12
-rw-r--r--fs/xfs/xfs_bmap.c2
-rw-r--r--fs/xfs/xfs_bmap_btree.c44
-rw-r--r--fs/xfs/xfs_bmap_btree.h4
-rw-r--r--fs/xfs/xfs_bmap_util.c69
-rw-r--r--fs/xfs/xfs_btree.c170
-rw-r--r--fs/xfs/xfs_btree.h19
-rw-r--r--fs/xfs/xfs_buf_item.c24
-rw-r--r--fs/xfs/xfs_da_btree.c1
-rw-r--r--fs/xfs/xfs_dir2_leaf.c20
-rw-r--r--fs/xfs/xfs_dquot_item.c3
-rw-r--r--fs/xfs/xfs_extent_busy.c3
-rw-r--r--fs/xfs/xfs_icache.c4
-rw-r--r--fs/xfs/xfs_icache.h4
-rw-r--r--fs/xfs/xfs_inode_buf.c10
-rw-r--r--fs/xfs/xfs_inode_buf.h18
-rw-r--r--fs/xfs/xfs_ioctl.c36
-rw-r--r--fs/xfs/xfs_ioctl32.c18
-rw-r--r--fs/xfs/xfs_itable.c7
-rw-r--r--fs/xfs/xfs_log.c3
-rw-r--r--fs/xfs/xfs_log_format.h8
-rw-r--r--fs/xfs/xfs_log_recover.c122
-rw-r--r--fs/xfs/xfs_symlink.c2
25 files changed, 461 insertions, 166 deletions
diff --git a/fs/xfs/kmem.c b/fs/xfs/kmem.c
index 4a7286c1dc80..a02cfb9e3bce 100644
--- a/fs/xfs/kmem.c
+++ b/fs/xfs/kmem.c
@@ -27,8 +27,6 @@
27 27
28/* 28/*
29 * Greedy allocation. May fail and may return vmalloced memory. 29 * Greedy allocation. May fail and may return vmalloced memory.
30 *
31 * Must be freed using kmem_free_large.
32 */ 30 */
33void * 31void *
34kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize) 32kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize)
@@ -36,7 +34,7 @@ kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize)
36 void *ptr; 34 void *ptr;
37 size_t kmsize = maxsize; 35 size_t kmsize = maxsize;
38 36
39 while (!(ptr = kmem_zalloc_large(kmsize))) { 37 while (!(ptr = vzalloc(kmsize))) {
40 if ((kmsize >>= 1) <= minsize) 38 if ((kmsize >>= 1) <= minsize)
41 kmsize = minsize; 39 kmsize = minsize;
42 } 40 }
@@ -75,6 +73,17 @@ kmem_zalloc(size_t size, xfs_km_flags_t flags)
75 return ptr; 73 return ptr;
76} 74}
77 75
76void *
77kmem_zalloc_large(size_t size, xfs_km_flags_t flags)
78{
79 void *ptr;
80
81 ptr = kmem_zalloc(size, flags | KM_MAYFAIL);
82 if (ptr)
83 return ptr;
84 return vzalloc(size);
85}
86
78void 87void
79kmem_free(const void *ptr) 88kmem_free(const void *ptr)
80{ 89{
diff --git a/fs/xfs/kmem.h b/fs/xfs/kmem.h
index b2f2620f9a87..3a7371cab508 100644
--- a/fs/xfs/kmem.h
+++ b/fs/xfs/kmem.h
@@ -57,17 +57,10 @@ kmem_flags_convert(xfs_km_flags_t flags)
57 57
58extern void *kmem_alloc(size_t, xfs_km_flags_t); 58extern void *kmem_alloc(size_t, xfs_km_flags_t);
59extern void *kmem_zalloc(size_t, xfs_km_flags_t); 59extern void *kmem_zalloc(size_t, xfs_km_flags_t);
60extern void *kmem_zalloc_large(size_t size, xfs_km_flags_t);
60extern void *kmem_realloc(const void *, size_t, size_t, xfs_km_flags_t); 61extern void *kmem_realloc(const void *, size_t, size_t, xfs_km_flags_t);
61extern void kmem_free(const void *); 62extern void kmem_free(const void *);
62 63
63static inline void *kmem_zalloc_large(size_t size)
64{
65 return vzalloc(size);
66}
67static inline void kmem_free_large(void *ptr)
68{
69 vfree(ptr);
70}
71 64
72extern void *kmem_zalloc_greedy(size_t *, size_t, size_t); 65extern void *kmem_zalloc_greedy(size_t *, size_t, size_t);
73 66
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 69518960b2ba..0e2f37efedd0 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -152,7 +152,7 @@ xfs_get_acl(struct inode *inode, int type)
152 * go out to the disk. 152 * go out to the disk.
153 */ 153 */
154 len = XFS_ACL_MAX_SIZE(ip->i_mount); 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 if (!xfs_acl) 156 if (!xfs_acl)
157 return ERR_PTR(-ENOMEM); 157 return ERR_PTR(-ENOMEM);
158 158
@@ -175,10 +175,10 @@ xfs_get_acl(struct inode *inode, int type)
175 if (IS_ERR(acl)) 175 if (IS_ERR(acl))
176 goto out; 176 goto out;
177 177
178 out_update_cache: 178out_update_cache:
179 set_cached_acl(inode, type, acl); 179 set_cached_acl(inode, type, acl);
180 out: 180out:
181 kfree(xfs_acl); 181 kmem_free(xfs_acl);
182 return acl; 182 return acl;
183} 183}
184 184
@@ -209,7 +209,7 @@ xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
209 struct xfs_acl *xfs_acl; 209 struct xfs_acl *xfs_acl;
210 int len = XFS_ACL_MAX_SIZE(ip->i_mount); 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 if (!xfs_acl) 213 if (!xfs_acl)
214 return -ENOMEM; 214 return -ENOMEM;
215 215
@@ -222,7 +222,7 @@ xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
222 error = -xfs_attr_set(ip, ea_name, (unsigned char *)xfs_acl, 222 error = -xfs_attr_set(ip, ea_name, (unsigned char *)xfs_acl,
223 len, ATTR_ROOT); 223 len, ATTR_ROOT);
224 224
225 kfree(xfs_acl); 225 kmem_free(xfs_acl);
226 } else { 226 } else {
227 /* 227 /*
228 * A NULL ACL argument means we want to remove the ACL. 228 * A NULL ACL argument means we want to remove the ACL.
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 92b830901d60..f47e65c30be6 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -4450,7 +4450,7 @@ xfs_bmapi_write(
4450{ 4450{
4451 struct xfs_mount *mp = ip->i_mount; 4451 struct xfs_mount *mp = ip->i_mount;
4452 struct xfs_ifork *ifp; 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 xfs_fileoff_t end; /* end of mapped file region */ 4454 xfs_fileoff_t end; /* end of mapped file region */
4455 int eof; /* after the end of extents */ 4455 int eof; /* after the end of extents */
4456 int error; /* error return */ 4456 int error; /* error return */
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index cf3bc76710c3..bb8de8e399c4 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -925,3 +925,47 @@ xfs_bmdr_maxrecs(
925 return blocklen / sizeof(xfs_bmdr_rec_t); 925 return blocklen / sizeof(xfs_bmdr_rec_t);
926 return blocklen / (sizeof(xfs_bmdr_key_t) + sizeof(xfs_bmdr_ptr_t)); 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 */
946int
947xfs_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}
diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h
index 1b726d626941..e367461a638e 100644
--- a/fs/xfs/xfs_bmap_btree.h
+++ b/fs/xfs/xfs_bmap_btree.h
@@ -236,6 +236,10 @@ extern int xfs_bmbt_get_maxrecs(struct xfs_btree_cur *, int level);
236extern int xfs_bmdr_maxrecs(struct xfs_mount *, int blocklen, int leaf); 236extern int xfs_bmdr_maxrecs(struct xfs_mount *, int blocklen, int leaf);
237extern int xfs_bmbt_maxrecs(struct xfs_mount *, int blocklen, int leaf); 237extern int xfs_bmbt_maxrecs(struct xfs_mount *, int blocklen, int leaf);
238 238
239extern 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
239extern struct xfs_btree_cur *xfs_bmbt_init_cursor(struct xfs_mount *, 243extern struct xfs_btree_cur *xfs_bmbt_init_cursor(struct xfs_mount *,
240 struct xfs_trans *, struct xfs_inode *, int); 244 struct xfs_trans *, struct xfs_inode *, int);
241 245
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 541d59f5e658..97f952caea74 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -612,13 +612,9 @@ xfs_getbmap(
612 612
613 if (bmv->bmv_count > ULONG_MAX / sizeof(struct getbmapx)) 613 if (bmv->bmv_count > ULONG_MAX / sizeof(struct getbmapx))
614 return XFS_ERROR(ENOMEM); 614 return XFS_ERROR(ENOMEM);
615 out = kmem_zalloc(bmv->bmv_count * sizeof(struct getbmapx), KM_MAYFAIL); 615 out = kmem_zalloc_large(bmv->bmv_count * sizeof(struct getbmapx), 0);
616 if (!out) { 616 if (!out)
617 out = kmem_zalloc_large(bmv->bmv_count * 617 return XFS_ERROR(ENOMEM);
618 sizeof(struct getbmapx));
619 if (!out)
620 return XFS_ERROR(ENOMEM);
621 }
622 618
623 xfs_ilock(ip, XFS_IOLOCK_SHARED); 619 xfs_ilock(ip, XFS_IOLOCK_SHARED);
624 if (whichfork == XFS_DATA_FORK && !(iflags & BMV_IF_DELALLOC)) { 620 if (whichfork == XFS_DATA_FORK && !(iflags & BMV_IF_DELALLOC)) {
@@ -754,10 +750,7 @@ xfs_getbmap(
754 break; 750 break;
755 } 751 }
756 752
757 if (is_vmalloc_addr(out)) 753 kmem_free(out);
758 kmem_free_large(out);
759 else
760 kmem_free(out);
761 return error; 754 return error;
762} 755}
763 756
@@ -1789,14 +1782,6 @@ xfs_swap_extents(
1789 int taforkblks = 0; 1782 int taforkblks = 0;
1790 __uint64_t tmp; 1783 __uint64_t tmp;
1791 1784
1792 /*
1793 * We have no way of updating owner information in the BMBT blocks for
1794 * each inode on CRC enabled filesystems, so to avoid corrupting the
1795 * this metadata we simply don't allow extent swaps to occur.
1796 */
1797 if (xfs_sb_version_hascrc(&mp->m_sb))
1798 return XFS_ERROR(EINVAL);
1799
1800 tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL); 1785 tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL);
1801 if (!tempifp) { 1786 if (!tempifp) {
1802 error = XFS_ERROR(ENOMEM); 1787 error = XFS_ERROR(ENOMEM);
@@ -1920,6 +1905,42 @@ xfs_swap_extents(
1920 goto out_trans_cancel; 1905 goto out_trans_cancel;
1921 } 1906 }
1922 1907
1908 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
1909 xfs_trans_ijoin(tp, tip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
1910
1911 /*
1912 * Before we've swapped the forks, lets set the owners of the forks
1913 * appropriately. We have to do this as we are demand paging the btree
1914 * buffers, and so the validation done on read will expect the owner
1915 * field to be correctly set. Once we change the owners, we can swap the
1916 * inode forks.
1917 *
1918 * Note the trickiness in setting the log flags - we set the owner log
1919 * flag on the opposite inode (i.e. the inode we are setting the new
1920 * owner to be) because once we swap the forks and log that, log
1921 * recovery is going to see the fork as owned by the swapped inode,
1922 * not the pre-swapped inodes.
1923 */
1924 src_log_flags = XFS_ILOG_CORE;
1925 target_log_flags = XFS_ILOG_CORE;
1926 if (ip->i_d.di_version == 3 &&
1927 ip->i_d.di_format == XFS_DINODE_FMT_BTREE) {
1928 target_log_flags |= XFS_ILOG_DOWNER;
1929 error = xfs_bmbt_change_owner(tp, ip, XFS_DATA_FORK,
1930 tip->i_ino, NULL);
1931 if (error)
1932 goto out_trans_cancel;
1933 }
1934
1935 if (tip->i_d.di_version == 3 &&
1936 tip->i_d.di_format == XFS_DINODE_FMT_BTREE) {
1937 src_log_flags |= XFS_ILOG_DOWNER;
1938 error = xfs_bmbt_change_owner(tp, tip, XFS_DATA_FORK,
1939 ip->i_ino, NULL);
1940 if (error)
1941 goto out_trans_cancel;
1942 }
1943
1923 /* 1944 /*
1924 * Swap the data forks of the inodes 1945 * Swap the data forks of the inodes
1925 */ 1946 */
@@ -1957,7 +1978,6 @@ xfs_swap_extents(
1957 tip->i_delayed_blks = ip->i_delayed_blks; 1978 tip->i_delayed_blks = ip->i_delayed_blks;
1958 ip->i_delayed_blks = 0; 1979 ip->i_delayed_blks = 0;
1959 1980
1960 src_log_flags = XFS_ILOG_CORE;
1961 switch (ip->i_d.di_format) { 1981 switch (ip->i_d.di_format) {
1962 case XFS_DINODE_FMT_EXTENTS: 1982 case XFS_DINODE_FMT_EXTENTS:
1963 /* If the extents fit in the inode, fix the 1983 /* If the extents fit in the inode, fix the
@@ -1971,11 +1991,12 @@ xfs_swap_extents(
1971 src_log_flags |= XFS_ILOG_DEXT; 1991 src_log_flags |= XFS_ILOG_DEXT;
1972 break; 1992 break;
1973 case XFS_DINODE_FMT_BTREE: 1993 case XFS_DINODE_FMT_BTREE:
1994 ASSERT(ip->i_d.di_version < 3 ||
1995 (src_log_flags & XFS_ILOG_DOWNER));
1974 src_log_flags |= XFS_ILOG_DBROOT; 1996 src_log_flags |= XFS_ILOG_DBROOT;
1975 break; 1997 break;
1976 } 1998 }
1977 1999
1978 target_log_flags = XFS_ILOG_CORE;
1979 switch (tip->i_d.di_format) { 2000 switch (tip->i_d.di_format) {
1980 case XFS_DINODE_FMT_EXTENTS: 2001 case XFS_DINODE_FMT_EXTENTS:
1981 /* If the extents fit in the inode, fix the 2002 /* If the extents fit in the inode, fix the
@@ -1990,13 +2011,11 @@ xfs_swap_extents(
1990 break; 2011 break;
1991 case XFS_DINODE_FMT_BTREE: 2012 case XFS_DINODE_FMT_BTREE:
1992 target_log_flags |= XFS_ILOG_DBROOT; 2013 target_log_flags |= XFS_ILOG_DBROOT;
2014 ASSERT(tip->i_d.di_version < 3 ||
2015 (target_log_flags & XFS_ILOG_DOWNER));
1993 break; 2016 break;
1994 } 2017 }
1995 2018
1996
1997 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
1998 xfs_trans_ijoin(tp, tip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
1999
2000 xfs_trans_log_inode(tp, ip, src_log_flags); 2019 xfs_trans_log_inode(tp, ip, src_log_flags);
2001 xfs_trans_log_inode(tp, tip, target_log_flags); 2020 xfs_trans_log_inode(tp, tip, target_log_flags);
2002 2021
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c
index 7a2b4da3c0db..5690e102243d 100644
--- a/fs/xfs/xfs_btree.c
+++ b/fs/xfs/xfs_btree.c
@@ -855,6 +855,41 @@ xfs_btree_readahead(
855 return xfs_btree_readahead_sblock(cur, lr, block); 855 return xfs_btree_readahead_sblock(cur, lr, block);
856} 856}
857 857
858STATIC xfs_daddr_t
859xfs_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 */
882STATIC void
883xfs_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 * Set the buffer for level "lev" in the cursor to bp, releasing 894 * Set the buffer for level "lev" in the cursor to bp, releasing
860 * any previous buffer. 895 * any previous buffer.
@@ -1073,24 +1108,6 @@ xfs_btree_buf_to_ptr(
1073 } 1108 }
1074} 1109}
1075 1110
1076STATIC xfs_daddr_t
1077xfs_btree_ptr_to_daddr(
1078 struct xfs_btree_cur *cur,
1079 union xfs_btree_ptr *ptr)
1080{
1081 if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
1082 ASSERT(ptr->l != cpu_to_be64(NULLDFSBNO));
1083
1084 return XFS_FSB_TO_DADDR(cur->bc_mp, be64_to_cpu(ptr->l));
1085 } else {
1086 ASSERT(cur->bc_private.a.agno != NULLAGNUMBER);
1087 ASSERT(ptr->s != cpu_to_be32(NULLAGBLOCK));
1088
1089 return XFS_AGB_TO_DADDR(cur->bc_mp, cur->bc_private.a.agno,
1090 be32_to_cpu(ptr->s));
1091 }
1092}
1093
1094STATIC void 1111STATIC void
1095xfs_btree_set_refs( 1112xfs_btree_set_refs(
1096 struct xfs_btree_cur *cur, 1113 struct xfs_btree_cur *cur,
@@ -3869,3 +3886,120 @@ xfs_btree_get_rec(
3869 *stat = 1; 3886 *stat = 1;
3870 return 0; 3887 return 0;
3871} 3888}
3889
3890/*
3891 * Change the owner of a btree.
3892 *
3893 * The mechanism we use here is ordered buffer logging. Because we don't know
3894 * how many buffers were are going to need to modify, we don't really want to
3895 * have to make transaction reservations for the worst case of every buffer in a
3896 * full size btree as that may be more space that we can fit in the log....
3897 *
3898 * We do the btree walk in the most optimal manner possible - we have sibling
3899 * pointers so we can just walk all the blocks on each level from left to right
3900 * in a single pass, and then move to the next level and do the same. We can
3901 * also do readahead on the sibling pointers to get IO moving more quickly,
3902 * though for slow disks this is unlikely to make much difference to performance
3903 * as the amount of CPU work we have to do before moving to the next block is
3904 * relatively small.
3905 *
3906 * For each btree block that we load, modify the owner appropriately, set the
3907 * buffer as an ordered buffer and log it appropriately. We need to ensure that
3908 * we mark the region we change dirty so that if the buffer is relogged in
3909 * a subsequent transaction the changes we make here as an ordered buffer are
3910 * correctly relogged in that transaction. If we are in recovery context, then
3911 * just queue the modified buffer as delayed write buffer so the transaction
3912 * recovery completion writes the changes to disk.
3913 */
3914static int
3915xfs_btree_block_change_owner(
3916 struct xfs_btree_cur *cur,
3917 int level,
3918 __uint64_t new_owner,
3919 struct list_head *buffer_list)
3920{
3921 struct xfs_btree_block *block;
3922 struct xfs_buf *bp;
3923 union xfs_btree_ptr rptr;
3924
3925 /* do right sibling readahead */
3926 xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA);
3927
3928 /* modify the owner */
3929 block = xfs_btree_get_block(cur, level, &bp);
3930 if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
3931 block->bb_u.l.bb_owner = cpu_to_be64(new_owner);
3932 else
3933 block->bb_u.s.bb_owner = cpu_to_be32(new_owner);
3934
3935 /*
3936 * If the block is a root block hosted in an inode, we might not have a
3937 * buffer pointer here and we shouldn't attempt to log the change as the
3938 * information is already held in the inode and discarded when the root
3939 * block is formatted into the on-disk inode fork. We still change it,
3940 * though, so everything is consistent in memory.
3941 */
3942 if (bp) {
3943 if (cur->bc_tp) {
3944 xfs_trans_ordered_buf(cur->bc_tp, bp);
3945 xfs_btree_log_block(cur, bp, XFS_BB_OWNER);
3946 } else {
3947 xfs_buf_delwri_queue(bp, buffer_list);
3948 }
3949 } else {
3950 ASSERT(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE);
3951 ASSERT(level == cur->bc_nlevels - 1);
3952 }
3953
3954 /* now read rh sibling block for next iteration */
3955 xfs_btree_get_sibling(cur, block, &rptr, XFS_BB_RIGHTSIB);
3956 if (xfs_btree_ptr_is_null(cur, &rptr))
3957 return ENOENT;
3958
3959 return xfs_btree_lookup_get_block(cur, level, &rptr, &block);
3960}
3961
3962int
3963xfs_btree_change_owner(
3964 struct xfs_btree_cur *cur,
3965 __uint64_t new_owner,
3966 struct list_head *buffer_list)
3967{
3968 union xfs_btree_ptr lptr;
3969 int level;
3970 struct xfs_btree_block *block = NULL;
3971 int error = 0;
3972
3973 cur->bc_ops->init_ptr_from_cur(cur, &lptr);
3974
3975 /* for each level */
3976 for (level = cur->bc_nlevels - 1; level >= 0; level--) {
3977 /* grab the left hand block */
3978 error = xfs_btree_lookup_get_block(cur, level, &lptr, &block);
3979 if (error)
3980 return error;
3981
3982 /* readahead the left most block for the next level down */
3983 if (level > 0) {
3984 union xfs_btree_ptr *ptr;
3985
3986 ptr = xfs_btree_ptr_addr(cur, 1, block);
3987 xfs_btree_readahead_ptr(cur, ptr, 1);
3988
3989 /* save for the next iteration of the loop */
3990 lptr = *ptr;
3991 }
3992
3993 /* for each buffer in the level */
3994 do {
3995 error = xfs_btree_block_change_owner(cur, level,
3996 new_owner,
3997 buffer_list);
3998 } while (!error);
3999
4000 if (error != ENOENT)
4001 return error;
4002 }
4003
4004 return 0;
4005}
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h
index c8473c7ef45e..06729b67ad58 100644
--- a/fs/xfs/xfs_btree.h
+++ b/fs/xfs/xfs_btree.h
@@ -121,15 +121,18 @@ union xfs_btree_rec {
121/* 121/*
122 * For logging record fields. 122 * For logging record fields.
123 */ 123 */
124#define XFS_BB_MAGIC 0x01 124#define XFS_BB_MAGIC (1 << 0)
125#define XFS_BB_LEVEL 0x02 125#define XFS_BB_LEVEL (1 << 1)
126#define XFS_BB_NUMRECS 0x04 126#define XFS_BB_NUMRECS (1 << 2)
127#define XFS_BB_LEFTSIB 0x08 127#define XFS_BB_LEFTSIB (1 << 3)
128#define XFS_BB_RIGHTSIB 0x10 128#define XFS_BB_RIGHTSIB (1 << 4)
129#define XFS_BB_BLKNO 0x20 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#define XFS_BB_NUM_BITS 5 133#define XFS_BB_NUM_BITS 5
131#define XFS_BB_ALL_BITS ((1 << XFS_BB_NUM_BITS) - 1) 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#define XFS_BB_ALL_BITS_CRC ((1 << XFS_BB_NUM_BITS_CRC) - 1) 136#define XFS_BB_ALL_BITS_CRC ((1 << XFS_BB_NUM_BITS_CRC) - 1)
134 137
135/* 138/*
@@ -442,6 +445,8 @@ int xfs_btree_new_iroot(struct xfs_btree_cur *, int *, int *);
442int xfs_btree_insert(struct xfs_btree_cur *, int *); 445int xfs_btree_insert(struct xfs_btree_cur *, int *);
443int xfs_btree_delete(struct xfs_btree_cur *, int *); 446int xfs_btree_delete(struct xfs_btree_cur *, int *);
444int xfs_btree_get_rec(struct xfs_btree_cur *, union xfs_btree_rec **, int *); 447int xfs_btree_get_rec(struct xfs_btree_cur *, union xfs_btree_rec **, int *);
448int xfs_btree_change_owner(struct xfs_btree_cur *cur, __uint64_t new_owner,
449 struct list_head *buffer_list);
445 450
446/* 451/*
447 * btree block CRC helpers 452 * btree block CRC helpers
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 3a944b198e35..88c5ea75ebf6 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -613,13 +613,27 @@ xfs_buf_item_unlock(
613 } 613 }
614 } 614 }
615 } 615 }
616 if (clean || aborted) { 616
617 if (atomic_dec_and_test(&bip->bli_refcount)) { 617 /*
618 ASSERT(!aborted || XFS_FORCED_SHUTDOWN(lip->li_mountp)); 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 xfs_buf_item_relse(bp); 634 xfs_buf_item_relse(bp);
620 } 635 }
621 } else 636 }
622 atomic_dec(&bip->bli_refcount);
623 637
624 if (!(flags & XFS_BLI_HOLD)) 638 if (!(flags & XFS_BLI_HOLD))
625 xfs_buf_relse(bp); 639 xfs_buf_relse(bp);
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index d4e59a4ff59f..069537c845e5 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -635,6 +635,7 @@ xfs_da3_root_split(
635 xfs_trans_log_buf(tp, bp, 0, size - 1); 635 xfs_trans_log_buf(tp, bp, 0, size - 1);
636 636
637 bp->b_ops = blk1->bp->b_ops; 637 bp->b_ops = blk1->bp->b_ops;
638 xfs_trans_buf_copy_type(bp, blk1->bp);
638 blk1->bp = bp; 639 blk1->bp = bp;
639 blk1->blkno = blkno; 640 blk1->blkno = blkno;
640 641
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index 08984eeee159..1021c8356d08 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -180,6 +180,11 @@ xfs_dir3_leaf_check_int(
180 return true; 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 */
183static bool 188static bool
184xfs_dir3_leaf_verify( 189xfs_dir3_leaf_verify(
185 struct xfs_buf *bp, 190 struct xfs_buf *bp,
@@ -191,24 +196,25 @@ xfs_dir3_leaf_verify(
191 196
192 ASSERT(magic == XFS_DIR2_LEAF1_MAGIC || magic == XFS_DIR2_LEAFN_MAGIC); 197 ASSERT(magic == XFS_DIR2_LEAF1_MAGIC || magic == XFS_DIR2_LEAFN_MAGIC);
193 198
194 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
195 if (xfs_sb_version_hascrc(&mp->m_sb)) { 199 if (xfs_sb_version_hascrc(&mp->m_sb)) {
196 struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr; 200 struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr;
201 __uint16_t magic3;
197 202
198 if ((magic == XFS_DIR2_LEAF1_MAGIC && 203 magic3 = (magic == XFS_DIR2_LEAF1_MAGIC) ? XFS_DIR3_LEAF1_MAGIC
199 leafhdr.magic != XFS_DIR3_LEAF1_MAGIC) || 204 : XFS_DIR3_LEAFN_MAGIC;
200 (magic == XFS_DIR2_LEAFN_MAGIC &&
201 leafhdr.magic != XFS_DIR3_LEAFN_MAGIC))
202 return false;
203 205
206 if (leaf3->info.hdr.magic != cpu_to_be16(magic3))
207 return false;
204 if (!uuid_equal(&leaf3->info.uuid, &mp->m_sb.sb_uuid)) 208 if (!uuid_equal(&leaf3->info.uuid, &mp->m_sb.sb_uuid))
205 return false; 209 return false;
206 if (be64_to_cpu(leaf3->info.blkno) != bp->b_bn) 210 if (be64_to_cpu(leaf3->info.blkno) != bp->b_bn)
207 return false; 211 return false;
208 } else { 212 } else {
209 if (leafhdr.magic != magic) 213 if (leaf->hdr.info.magic != cpu_to_be16(magic))
210 return false; 214 return false;
211 } 215 }
216
217 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
212 return xfs_dir3_leaf_check_int(mp, &leafhdr, leaf); 218 return xfs_dir3_leaf_check_int(mp, &leafhdr, leaf);
213} 219}
214 220
diff --git a/fs/xfs/xfs_dquot_item.c b/fs/xfs/xfs_dquot_item.c
index 60c6e1f12695..e838d84b4e85 100644
--- a/fs/xfs/xfs_dquot_item.c
+++ b/fs/xfs/xfs_dquot_item.c
@@ -142,7 +142,8 @@ xfs_qm_dqunpin_wait(
142STATIC uint 142STATIC uint
143xfs_qm_dquot_logitem_push( 143xfs_qm_dquot_logitem_push(
144 struct xfs_log_item *lip, 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 struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot; 148 struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot;
148 struct xfs_buf *bp = NULL; 149 struct xfs_buf *bp = NULL;
diff --git a/fs/xfs/xfs_extent_busy.c b/fs/xfs/xfs_extent_busy.c
index 86f559f6e5d3..e43708e2f080 100644
--- a/fs/xfs/xfs_extent_busy.c
+++ b/fs/xfs/xfs_extent_busy.c
@@ -160,7 +160,8 @@ xfs_extent_busy_update_extent(
160 struct xfs_extent_busy *busyp, 160 struct xfs_extent_busy *busyp,
161 xfs_agblock_t fbno, 161 xfs_agblock_t fbno,
162 xfs_extlen_t flen, 162 xfs_extlen_t flen,
163 bool userdata) 163 bool userdata) __releases(&pag->pagb_lock)
164 __acquires(&pag->pagb_lock)
164{ 165{
165 xfs_agblock_t fend = fbno + flen; 166 xfs_agblock_t fend = fbno + flen;
166 xfs_agblock_t bbno = busyp->bno; 167 xfs_agblock_t bbno = busyp->bno;
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 73b62a24ceac..193206ba4358 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -48,7 +48,7 @@ STATIC void __xfs_inode_clear_reclaim_tag(struct xfs_mount *mp,
48/* 48/*
49 * Allocate and initialise an xfs_inode. 49 * Allocate and initialise an xfs_inode.
50 */ 50 */
51STATIC struct xfs_inode * 51struct xfs_inode *
52xfs_inode_alloc( 52xfs_inode_alloc(
53 struct xfs_mount *mp, 53 struct xfs_mount *mp,
54 xfs_ino_t ino) 54 xfs_ino_t ino)
@@ -98,7 +98,7 @@ xfs_inode_free_callback(
98 kmem_zone_free(xfs_inode_zone, ip); 98 kmem_zone_free(xfs_inode_zone, ip);
99} 99}
100 100
101STATIC void 101void
102xfs_inode_free( 102xfs_inode_free(
103 struct xfs_inode *ip) 103 struct xfs_inode *ip)
104{ 104{
diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h
index 456f0144e1b6..9ed68bb750f5 100644
--- a/fs/xfs/xfs_icache.h
+++ b/fs/xfs/xfs_icache.h
@@ -42,6 +42,10 @@ struct xfs_eofblocks {
42int xfs_iget(struct xfs_mount *mp, struct xfs_trans *tp, xfs_ino_t ino, 42int xfs_iget(struct xfs_mount *mp, struct xfs_trans *tp, xfs_ino_t ino,
43 uint flags, uint lock_flags, xfs_inode_t **ipp); 43 uint flags, uint lock_flags, xfs_inode_t **ipp);
44 44
45/* recovery needs direct inode allocation capability */
46struct xfs_inode * xfs_inode_alloc(struct xfs_mount *mp, xfs_ino_t ino);
47void xfs_inode_free(struct xfs_inode *ip);
48
45void xfs_reclaim_worker(struct work_struct *work); 49void xfs_reclaim_worker(struct work_struct *work);
46 50
47int xfs_reclaim_inodes(struct xfs_mount *mp, int mode); 51int xfs_reclaim_inodes(struct xfs_mount *mp, int mode);
diff --git a/fs/xfs/xfs_inode_buf.c b/fs/xfs/xfs_inode_buf.c
index e011d597f12f..63382d37f565 100644
--- a/fs/xfs/xfs_inode_buf.c
+++ b/fs/xfs/xfs_inode_buf.c
@@ -53,9 +53,8 @@ xfs_inobp_check(
53 i * mp->m_sb.sb_inodesize); 53 i * mp->m_sb.sb_inodesize);
54 if (!dip->di_next_unlinked) { 54 if (!dip->di_next_unlinked) {
55 xfs_alert(mp, 55 xfs_alert(mp,
56 "Detected bogus zero next_unlinked field in incore inode buffer 0x%p.", 56 "Detected bogus zero next_unlinked field in inode %d buffer 0x%llx.",
57 bp); 57 i, (long long)bp->b_bn);
58 ASSERT(dip->di_next_unlinked);
59 } 58 }
60 } 59 }
61} 60}
@@ -106,11 +105,10 @@ xfs_inode_buf_verify(
106 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_HIGH, 105 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_HIGH,
107 mp, dip); 106 mp, dip);
108#ifdef DEBUG 107#ifdef DEBUG
109 xfs_emerg(mp, 108 xfs_alert(mp,
110 "bad inode magic/vsn daddr %lld #%d (magic=%x)", 109 "bad inode magic/vsn daddr %lld #%d (magic=%x)",
111 (unsigned long long)bp->b_bn, i, 110 (unsigned long long)bp->b_bn, i,
112 be16_to_cpu(dip->di_magic)); 111 be16_to_cpu(dip->di_magic));
113 ASSERT(0);
114#endif 112#endif
115 } 113 }
116 } 114 }
@@ -196,7 +194,7 @@ xfs_imap_to_bp(
196 return 0; 194 return 0;
197} 195}
198 196
199STATIC void 197void
200xfs_dinode_from_disk( 198xfs_dinode_from_disk(
201 xfs_icdinode_t *to, 199 xfs_icdinode_t *to,
202 xfs_dinode_t *from) 200 xfs_dinode_t *from)
diff --git a/fs/xfs/xfs_inode_buf.h b/fs/xfs/xfs_inode_buf.h
index 599e6c0ca2a9..abba0ae8cf2d 100644
--- a/fs/xfs/xfs_inode_buf.h
+++ b/fs/xfs/xfs_inode_buf.h
@@ -32,17 +32,17 @@ struct xfs_imap {
32 ushort im_boffset; /* inode offset in block in bytes */ 32 ushort im_boffset; /* inode offset in block in bytes */
33}; 33};
34 34
35int xfs_imap_to_bp(struct xfs_mount *, struct xfs_trans *, 35int xfs_imap_to_bp(struct xfs_mount *, struct xfs_trans *,
36 struct xfs_imap *, struct xfs_dinode **, 36 struct xfs_imap *, struct xfs_dinode **,
37 struct xfs_buf **, uint, uint); 37 struct xfs_buf **, uint, uint);
38int xfs_iread(struct xfs_mount *, struct xfs_trans *, 38int xfs_iread(struct xfs_mount *, struct xfs_trans *,
39 struct xfs_inode *, uint); 39 struct xfs_inode *, uint);
40void xfs_dinode_calc_crc(struct xfs_mount *, struct xfs_dinode *); 40void xfs_dinode_calc_crc(struct xfs_mount *, struct xfs_dinode *);
41void xfs_dinode_to_disk(struct xfs_dinode *, 41void xfs_dinode_to_disk(struct xfs_dinode *to, struct xfs_icdinode *from);
42 struct xfs_icdinode *); 42void xfs_dinode_from_disk(struct xfs_icdinode *to, struct xfs_dinode *from);
43 43
44#if defined(DEBUG) 44#if defined(DEBUG)
45void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *); 45void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *);
46#else 46#else
47#define xfs_inobp_check(mp, bp) 47#define xfs_inobp_check(mp, bp)
48#endif /* DEBUG */ 48#endif /* DEBUG */
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index bdebc21078d7..668e8f4ccf5e 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -71,7 +71,7 @@ xfs_find_handle(
71 int hsize; 71 int hsize;
72 xfs_handle_t handle; 72 xfs_handle_t handle;
73 struct inode *inode; 73 struct inode *inode;
74 struct fd f = {0}; 74 struct fd f = {NULL};
75 struct path path; 75 struct path path;
76 int error; 76 int error;
77 struct xfs_inode *ip; 77 struct xfs_inode *ip;
@@ -456,12 +456,9 @@ xfs_attrlist_by_handle(
456 if (IS_ERR(dentry)) 456 if (IS_ERR(dentry))
457 return PTR_ERR(dentry); 457 return PTR_ERR(dentry);
458 458
459 kbuf = kmem_zalloc(al_hreq.buflen, KM_SLEEP | KM_MAYFAIL); 459 kbuf = kmem_zalloc_large(al_hreq.buflen, KM_SLEEP);
460 if (!kbuf) { 460 if (!kbuf)
461 kbuf = kmem_zalloc_large(al_hreq.buflen); 461 goto out_dput;
462 if (!kbuf)
463 goto out_dput;
464 }
465 462
466 cursor = (attrlist_cursor_kern_t *)&al_hreq.pos; 463 cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
467 error = -xfs_attr_list(XFS_I(dentry->d_inode), kbuf, al_hreq.buflen, 464 error = -xfs_attr_list(XFS_I(dentry->d_inode), kbuf, al_hreq.buflen,
@@ -472,12 +469,9 @@ xfs_attrlist_by_handle(
472 if (copy_to_user(al_hreq.buffer, kbuf, al_hreq.buflen)) 469 if (copy_to_user(al_hreq.buffer, kbuf, al_hreq.buflen))
473 error = -EFAULT; 470 error = -EFAULT;
474 471
475 out_kfree: 472out_kfree:
476 if (is_vmalloc_addr(kbuf)) 473 kmem_free(kbuf);
477 kmem_free_large(kbuf); 474out_dput:
478 else
479 kmem_free(kbuf);
480 out_dput:
481 dput(dentry); 475 dput(dentry);
482 return error; 476 return error;
483} 477}
@@ -495,12 +489,9 @@ xfs_attrmulti_attr_get(
495 489
496 if (*len > XATTR_SIZE_MAX) 490 if (*len > XATTR_SIZE_MAX)
497 return EINVAL; 491 return EINVAL;
498 kbuf = kmem_zalloc(*len, KM_SLEEP | KM_MAYFAIL); 492 kbuf = kmem_zalloc_large(*len, KM_SLEEP);
499 if (!kbuf) { 493 if (!kbuf)
500 kbuf = kmem_zalloc_large(*len); 494 return ENOMEM;
501 if (!kbuf)
502 return ENOMEM;
503 }
504 495
505 error = xfs_attr_get(XFS_I(inode), name, kbuf, (int *)len, flags); 496 error = xfs_attr_get(XFS_I(inode), name, kbuf, (int *)len, flags);
506 if (error) 497 if (error)
@@ -509,11 +500,8 @@ xfs_attrmulti_attr_get(
509 if (copy_to_user(ubuf, kbuf, *len)) 500 if (copy_to_user(ubuf, kbuf, *len))
510 error = EFAULT; 501 error = EFAULT;
511 502
512 out_kfree: 503out_kfree:
513 if (is_vmalloc_addr(kbuf)) 504 kmem_free(kbuf);
514 kmem_free_large(kbuf);
515 else
516 kmem_free(kbuf);
517 return error; 505 return error;
518} 506}
519 507
diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
index d3ab9534307f..f671f7e472ac 100644
--- a/fs/xfs/xfs_ioctl32.c
+++ b/fs/xfs/xfs_ioctl32.c
@@ -371,12 +371,9 @@ xfs_compat_attrlist_by_handle(
371 return PTR_ERR(dentry); 371 return PTR_ERR(dentry);
372 372
373 error = -ENOMEM; 373 error = -ENOMEM;
374 kbuf = kmem_zalloc(al_hreq.buflen, KM_SLEEP | KM_MAYFAIL); 374 kbuf = kmem_zalloc_large(al_hreq.buflen, KM_SLEEP);
375 if (!kbuf) { 375 if (!kbuf)
376 kbuf = kmem_zalloc_large(al_hreq.buflen); 376 goto out_dput;
377 if (!kbuf)
378 goto out_dput;
379 }
380 377
381 cursor = (attrlist_cursor_kern_t *)&al_hreq.pos; 378 cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
382 error = -xfs_attr_list(XFS_I(dentry->d_inode), kbuf, al_hreq.buflen, 379 error = -xfs_attr_list(XFS_I(dentry->d_inode), kbuf, al_hreq.buflen,
@@ -387,12 +384,9 @@ xfs_compat_attrlist_by_handle(
387 if (copy_to_user(compat_ptr(al_hreq.buffer), kbuf, al_hreq.buflen)) 384 if (copy_to_user(compat_ptr(al_hreq.buffer), kbuf, al_hreq.buflen))
388 error = -EFAULT; 385 error = -EFAULT;
389 386
390 out_kfree: 387out_kfree:
391 if (is_vmalloc_addr(kbuf)) 388 kmem_free(kbuf);
392 kmem_free_large(kbuf); 389out_dput:
393 else
394 kmem_free(kbuf);
395 out_dput:
396 dput(dentry); 390 dput(dentry);
397 return error; 391 return error;
398} 392}
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index b93e14b86754..084b3e1741fd 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -495,7 +495,7 @@ xfs_bulkstat(
495 /* 495 /*
496 * Done, we're either out of filesystem or space to put the data. 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 *ubcountp = ubelem; 499 *ubcountp = ubelem;
500 /* 500 /*
501 * Found some inodes, return them now and return the error next time. 501 * Found some inodes, return them now and return the error next time.
@@ -541,8 +541,9 @@ xfs_bulkstat_single(
541 * at the expense of the error case. 541 * at the expense of the error case.
542 */ 542 */
543 543
544 ino = (xfs_ino_t)*lastinop; 544 ino = *lastinop;
545 error = xfs_bulkstat_one(mp, ino, buffer, sizeof(xfs_bstat_t), 0, &res); 545 error = xfs_bulkstat_one(mp, ino, buffer, sizeof(xfs_bstat_t),
546 NULL, &res);
546 if (error) { 547 if (error) {
547 /* 548 /*
548 * Special case way failed, do it the "long" way 549 * Special case way failed, do it the "long" way
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 5372d58ef93a..a2dea108071a 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -257,7 +257,8 @@ xlog_grant_head_wait(
257 struct xlog *log, 257 struct xlog *log,
258 struct xlog_grant_head *head, 258 struct xlog_grant_head *head,
259 struct xlog_ticket *tic, 259 struct xlog_ticket *tic,
260 int need_bytes) 260 int need_bytes) __releases(&head->lock)
261 __acquires(&head->lock)
261{ 262{
262 list_add_tail(&tic->t_queue, &head->waiters); 263 list_add_tail(&tic->t_queue, &head->waiters);
263 264
diff --git a/fs/xfs/xfs_log_format.h b/fs/xfs/xfs_log_format.h
index 31e3a06c4644..ca7e28a8ed31 100644
--- a/fs/xfs/xfs_log_format.h
+++ b/fs/xfs/xfs_log_format.h
@@ -474,6 +474,8 @@ typedef struct xfs_inode_log_format_64 {
474#define XFS_ILOG_ADATA 0x040 /* log i_af.if_data */ 474#define XFS_ILOG_ADATA 0x040 /* log i_af.if_data */
475#define XFS_ILOG_AEXT 0x080 /* log i_af.if_extents */ 475#define XFS_ILOG_AEXT 0x080 /* log i_af.if_extents */
476#define XFS_ILOG_ABROOT 0x100 /* log i_af.i_broot */ 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/*
@@ -487,7 +489,8 @@ typedef struct xfs_inode_log_format_64 {
487#define XFS_ILOG_NONCORE (XFS_ILOG_DDATA | XFS_ILOG_DEXT | \ 489#define XFS_ILOG_NONCORE (XFS_ILOG_DDATA | XFS_ILOG_DEXT | \
488 XFS_ILOG_DBROOT | XFS_ILOG_DEV | \ 490 XFS_ILOG_DBROOT | XFS_ILOG_DEV | \
489 XFS_ILOG_UUID | XFS_ILOG_ADATA | \ 491 XFS_ILOG_UUID | XFS_ILOG_ADATA | \
490 XFS_ILOG_AEXT | XFS_ILOG_ABROOT) 492 XFS_ILOG_AEXT | XFS_ILOG_ABROOT | \
493 XFS_ILOG_DOWNER | XFS_ILOG_AOWNER)
491 494
492#define XFS_ILOG_DFORK (XFS_ILOG_DDATA | XFS_ILOG_DEXT | \ 495#define XFS_ILOG_DFORK (XFS_ILOG_DDATA | XFS_ILOG_DEXT | \
493 XFS_ILOG_DBROOT) 496 XFS_ILOG_DBROOT)
@@ -499,7 +502,8 @@ typedef struct xfs_inode_log_format_64 {
499 XFS_ILOG_DEXT | XFS_ILOG_DBROOT | \ 502 XFS_ILOG_DEXT | XFS_ILOG_DBROOT | \
500 XFS_ILOG_DEV | XFS_ILOG_UUID | \ 503 XFS_ILOG_DEV | XFS_ILOG_UUID | \
501 XFS_ILOG_ADATA | XFS_ILOG_AEXT | \ 504 XFS_ILOG_ADATA | XFS_ILOG_AEXT | \
502 XFS_ILOG_ABROOT | XFS_ILOG_TIMESTAMP) 505 XFS_ILOG_ABROOT | XFS_ILOG_TIMESTAMP | \
506 XFS_ILOG_DOWNER | XFS_ILOG_AOWNER)
503 507
504static inline int xfs_ilog_fbroot(int w) 508static inline int xfs_ilog_fbroot(int w)
505{ 509{
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 7c0c1fdc728b..dabda9521b4b 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -2014,7 +2014,7 @@ xlog_recover_get_buf_lsn(
2014 case XFS_ATTR3_RMT_MAGIC: 2014 case XFS_ATTR3_RMT_MAGIC:
2015 return be64_to_cpu(((struct xfs_attr3_rmt_hdr *)blk)->rm_lsn); 2015 return be64_to_cpu(((struct xfs_attr3_rmt_hdr *)blk)->rm_lsn);
2016 case XFS_SB_MAGIC: 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 default: 2018 default:
2019 break; 2019 break;
2020 } 2020 }
@@ -2629,6 +2629,82 @@ out_release:
2629 return error; 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
2662STATIC int
2663xfs_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
2703out_free_ip:
2704 xfs_inode_free(ip);
2705 return error;
2706}
2707
2632STATIC int 2708STATIC int
2633xlog_recover_inode_pass2( 2709xlog_recover_inode_pass2(
2634 struct xlog *log, 2710 struct xlog *log,
@@ -2681,8 +2757,7 @@ xlog_recover_inode_pass2(
2681 error = bp->b_error; 2757 error = bp->b_error;
2682 if (error) { 2758 if (error) {
2683 xfs_buf_ioerror_alert(bp, "xlog_recover_do..(read#2)"); 2759 xfs_buf_ioerror_alert(bp, "xlog_recover_do..(read#2)");
2684 xfs_buf_relse(bp); 2760 goto out_release;
2685 goto error;
2686 } 2761 }
2687 ASSERT(in_f->ilf_fields & XFS_ILOG_CORE); 2762 ASSERT(in_f->ilf_fields & XFS_ILOG_CORE);
2688 dip = (xfs_dinode_t *)xfs_buf_offset(bp, in_f->ilf_boffset); 2763 dip = (xfs_dinode_t *)xfs_buf_offset(bp, in_f->ilf_boffset);
@@ -2692,30 +2767,31 @@ xlog_recover_inode_pass2(
2692 * like an inode! 2767 * like an inode!
2693 */ 2768 */
2694 if (unlikely(dip->di_magic != cpu_to_be16(XFS_DINODE_MAGIC))) { 2769 if (unlikely(dip->di_magic != cpu_to_be16(XFS_DINODE_MAGIC))) {
2695 xfs_buf_relse(bp);
2696 xfs_alert(mp, 2770 xfs_alert(mp,
2697 "%s: Bad inode magic number, dip = 0x%p, dino bp = 0x%p, ino = %Ld", 2771 "%s: Bad inode magic number, dip = 0x%p, dino bp = 0x%p, ino = %Ld",
2698 __func__, dip, bp, in_f->ilf_ino); 2772 __func__, dip, bp, in_f->ilf_ino);
2699 XFS_ERROR_REPORT("xlog_recover_inode_pass2(1)", 2773 XFS_ERROR_REPORT("xlog_recover_inode_pass2(1)",
2700 XFS_ERRLEVEL_LOW, mp); 2774 XFS_ERRLEVEL_LOW, mp);
2701 error = EFSCORRUPTED; 2775 error = EFSCORRUPTED;
2702 goto error; 2776 goto out_release;
2703 } 2777 }
2704 dicp = item->ri_buf[1].i_addr; 2778 dicp = item->ri_buf[1].i_addr;
2705 if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) { 2779 if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) {
2706 xfs_buf_relse(bp);
2707 xfs_alert(mp, 2780 xfs_alert(mp,
2708 "%s: Bad inode log record, rec ptr 0x%p, ino %Ld", 2781 "%s: Bad inode log record, rec ptr 0x%p, ino %Ld",
2709 __func__, item, in_f->ilf_ino); 2782 __func__, item, in_f->ilf_ino);
2710 XFS_ERROR_REPORT("xlog_recover_inode_pass2(2)", 2783 XFS_ERROR_REPORT("xlog_recover_inode_pass2(2)",
2711 XFS_ERRLEVEL_LOW, mp); 2784 XFS_ERRLEVEL_LOW, mp);
2712 error = EFSCORRUPTED; 2785 error = EFSCORRUPTED;
2713 goto error; 2786 goto out_release;
2714 } 2787 }
2715 2788
2716 /* 2789 /*
2717 * If the inode has an LSN in it, recover the inode only if it's less 2790 * If the inode has an LSN in it, recover the inode only if it's less
2718 * than the lsn of the transaction we are replaying. 2791 * than the lsn of the transaction we are replaying. Note: we still
2792 * need to replay an owner change even though the inode is more recent
2793 * than the transaction as there is no guarantee that all the btree
2794 * blocks are more recent than this transaction, too.
2719 */ 2795 */
2720 if (dip->di_version >= 3) { 2796 if (dip->di_version >= 3) {
2721 xfs_lsn_t lsn = be64_to_cpu(dip->di_lsn); 2797 xfs_lsn_t lsn = be64_to_cpu(dip->di_lsn);
@@ -2723,7 +2799,7 @@ xlog_recover_inode_pass2(
2723 if (lsn && lsn != -1 && XFS_LSN_CMP(lsn, current_lsn) >= 0) { 2799 if (lsn && lsn != -1 && XFS_LSN_CMP(lsn, current_lsn) >= 0) {
2724 trace_xfs_log_recover_inode_skip(log, in_f); 2800 trace_xfs_log_recover_inode_skip(log, in_f);
2725 error = 0; 2801 error = 0;
2726 goto out_release; 2802 goto out_owner_change;
2727 } 2803 }
2728 } 2804 }
2729 2805
@@ -2745,10 +2821,9 @@ xlog_recover_inode_pass2(
2745 dicp->di_flushiter < (DI_MAX_FLUSH >> 1)) { 2821 dicp->di_flushiter < (DI_MAX_FLUSH >> 1)) {
2746 /* do nothing */ 2822 /* do nothing */
2747 } else { 2823 } else {
2748 xfs_buf_relse(bp);
2749 trace_xfs_log_recover_inode_skip(log, in_f); 2824 trace_xfs_log_recover_inode_skip(log, in_f);
2750 error = 0; 2825 error = 0;
2751 goto error; 2826 goto out_release;
2752 } 2827 }
2753 } 2828 }
2754 2829
@@ -2760,13 +2835,12 @@ xlog_recover_inode_pass2(
2760 (dicp->di_format != XFS_DINODE_FMT_BTREE)) { 2835 (dicp->di_format != XFS_DINODE_FMT_BTREE)) {
2761 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(3)", 2836 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(3)",
2762 XFS_ERRLEVEL_LOW, mp, dicp); 2837 XFS_ERRLEVEL_LOW, mp, dicp);
2763 xfs_buf_relse(bp);
2764 xfs_alert(mp, 2838 xfs_alert(mp,
2765 "%s: Bad regular inode log record, rec ptr 0x%p, " 2839 "%s: Bad regular inode log record, rec ptr 0x%p, "
2766 "ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", 2840 "ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
2767 __func__, item, dip, bp, in_f->ilf_ino); 2841 __func__, item, dip, bp, in_f->ilf_ino);
2768 error = EFSCORRUPTED; 2842 error = EFSCORRUPTED;
2769 goto error; 2843 goto out_release;
2770 } 2844 }
2771 } else if (unlikely(S_ISDIR(dicp->di_mode))) { 2845 } else if (unlikely(S_ISDIR(dicp->di_mode))) {
2772 if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) && 2846 if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) &&
@@ -2774,19 +2848,17 @@ xlog_recover_inode_pass2(
2774 (dicp->di_format != XFS_DINODE_FMT_LOCAL)) { 2848 (dicp->di_format != XFS_DINODE_FMT_LOCAL)) {
2775 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(4)", 2849 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(4)",
2776 XFS_ERRLEVEL_LOW, mp, dicp); 2850 XFS_ERRLEVEL_LOW, mp, dicp);
2777 xfs_buf_relse(bp);
2778 xfs_alert(mp, 2851 xfs_alert(mp,
2779 "%s: Bad dir inode log record, rec ptr 0x%p, " 2852 "%s: Bad dir inode log record, rec ptr 0x%p, "
2780 "ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", 2853 "ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
2781 __func__, item, dip, bp, in_f->ilf_ino); 2854 __func__, item, dip, bp, in_f->ilf_ino);
2782 error = EFSCORRUPTED; 2855 error = EFSCORRUPTED;
2783 goto error; 2856 goto out_release;
2784 } 2857 }
2785 } 2858 }
2786 if (unlikely(dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks)){ 2859 if (unlikely(dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks)){
2787 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(5)", 2860 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(5)",
2788 XFS_ERRLEVEL_LOW, mp, dicp); 2861 XFS_ERRLEVEL_LOW, mp, dicp);
2789 xfs_buf_relse(bp);
2790 xfs_alert(mp, 2862 xfs_alert(mp,
2791 "%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, " 2863 "%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, "
2792 "dino bp 0x%p, ino %Ld, total extents = %d, nblocks = %Ld", 2864 "dino bp 0x%p, ino %Ld, total extents = %d, nblocks = %Ld",
@@ -2794,29 +2866,27 @@ xlog_recover_inode_pass2(
2794 dicp->di_nextents + dicp->di_anextents, 2866 dicp->di_nextents + dicp->di_anextents,
2795 dicp->di_nblocks); 2867 dicp->di_nblocks);
2796 error = EFSCORRUPTED; 2868 error = EFSCORRUPTED;
2797 goto error; 2869 goto out_release;
2798 } 2870 }
2799 if (unlikely(dicp->di_forkoff > mp->m_sb.sb_inodesize)) { 2871 if (unlikely(dicp->di_forkoff > mp->m_sb.sb_inodesize)) {
2800 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(6)", 2872 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(6)",
2801 XFS_ERRLEVEL_LOW, mp, dicp); 2873 XFS_ERRLEVEL_LOW, mp, dicp);
2802 xfs_buf_relse(bp);
2803 xfs_alert(mp, 2874 xfs_alert(mp,
2804 "%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, " 2875 "%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, "
2805 "dino bp 0x%p, ino %Ld, forkoff 0x%x", __func__, 2876 "dino bp 0x%p, ino %Ld, forkoff 0x%x", __func__,
2806 item, dip, bp, in_f->ilf_ino, dicp->di_forkoff); 2877 item, dip, bp, in_f->ilf_ino, dicp->di_forkoff);
2807 error = EFSCORRUPTED; 2878 error = EFSCORRUPTED;
2808 goto error; 2879 goto out_release;
2809 } 2880 }
2810 isize = xfs_icdinode_size(dicp->di_version); 2881 isize = xfs_icdinode_size(dicp->di_version);
2811 if (unlikely(item->ri_buf[1].i_len > isize)) { 2882 if (unlikely(item->ri_buf[1].i_len > isize)) {
2812 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(7)", 2883 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(7)",
2813 XFS_ERRLEVEL_LOW, mp, dicp); 2884 XFS_ERRLEVEL_LOW, mp, dicp);
2814 xfs_buf_relse(bp);
2815 xfs_alert(mp, 2885 xfs_alert(mp,
2816 "%s: Bad inode log record length %d, rec ptr 0x%p", 2886 "%s: Bad inode log record length %d, rec ptr 0x%p",
2817 __func__, item->ri_buf[1].i_len, item); 2887 __func__, item->ri_buf[1].i_len, item);
2818 error = EFSCORRUPTED; 2888 error = EFSCORRUPTED;
2819 goto error; 2889 goto out_release;
2820 } 2890 }
2821 2891
2822 /* The core is in in-core format */ 2892 /* The core is in in-core format */
@@ -2842,7 +2912,7 @@ xlog_recover_inode_pass2(
2842 } 2912 }
2843 2913
2844 if (in_f->ilf_size == 2) 2914 if (in_f->ilf_size == 2)
2845 goto write_inode_buffer; 2915 goto out_owner_change;
2846 len = item->ri_buf[2].i_len; 2916 len = item->ri_buf[2].i_len;
2847 src = item->ri_buf[2].i_addr; 2917 src = item->ri_buf[2].i_addr;
2848 ASSERT(in_f->ilf_size <= 4); 2918 ASSERT(in_f->ilf_size <= 4);
@@ -2903,13 +2973,15 @@ xlog_recover_inode_pass2(
2903 default: 2973 default:
2904 xfs_warn(log->l_mp, "%s: Invalid flag", __func__); 2974 xfs_warn(log->l_mp, "%s: Invalid flag", __func__);
2905 ASSERT(0); 2975 ASSERT(0);
2906 xfs_buf_relse(bp);
2907 error = EIO; 2976 error = EIO;
2908 goto error; 2977 goto out_release;
2909 } 2978 }
2910 } 2979 }
2911 2980
2912write_inode_buffer: 2981out_owner_change:
2982 if (in_f->ilf_fields & (XFS_ILOG_DOWNER|XFS_ILOG_AOWNER))
2983 error = xfs_recover_inode_owner_change(mp, dip, in_f,
2984 buffer_list);
2913 /* re-generate the checksum. */ 2985 /* re-generate the checksum. */
2914 xfs_dinode_calc_crc(log->l_mp, dip); 2986 xfs_dinode_calc_crc(log->l_mp, dip);
2915 2987
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
index 2f2a7c005be2..f622a97a7e33 100644
--- a/fs/xfs/xfs_symlink.c
+++ b/fs/xfs/xfs_symlink.c
@@ -41,6 +41,7 @@
41#include "xfs_trans_space.h" 41#include "xfs_trans_space.h"
42#include "xfs_trace.h" 42#include "xfs_trace.h"
43#include "xfs_symlink.h" 43#include "xfs_symlink.h"
44#include "xfs_buf_item.h"
44 45
45/* ----- Kernel only functions below ----- */ 46/* ----- Kernel only functions below ----- */
46STATIC int 47STATIC int
@@ -363,6 +364,7 @@ xfs_symlink(
363 pathlen -= byte_cnt; 364 pathlen -= byte_cnt;
364 offset += byte_cnt; 365 offset += byte_cnt;
365 366
367 xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SYMLINK_BUF);
366 xfs_trans_log_buf(tp, bp, 0, (buf + byte_cnt - 1) - 368 xfs_trans_log_buf(tp, bp, 0, (buf + byte_cnt - 1) -
367 (char *)bp->b_addr); 369 (char *)bp->b_addr);
368 } 370 }