summaryrefslogtreecommitdiffstats
path: root/fs/xfs/libxfs
diff options
context:
space:
mode:
authorDave Chinner <david@fromorbit.com>2016-12-07 01:42:30 -0500
committerDave Chinner <david@fromorbit.com>2016-12-07 01:42:30 -0500
commita444d72e609062a040ed95a50e8fccfa1d58281b (patch)
treec57054f0e2674a9a80097e48a266c505c0cddca6 /fs/xfs/libxfs
parent5f1c6d28cfcd11c9df67dad45992fd523727fe1e (diff)
parent6031e73a5b3f85ec45cac08ef90995b2d3f941c7 (diff)
Merge branch 'xfs-4.10-misc-fixes-3' into for-next
Diffstat (limited to 'fs/xfs/libxfs')
-rw-r--r--fs/xfs/libxfs/xfs_alloc.c10
-rw-r--r--fs/xfs/libxfs/xfs_alloc_btree.c4
-rw-r--r--fs/xfs/libxfs/xfs_attr_leaf.h2
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c14
-rw-r--r--fs/xfs/libxfs/xfs_bmap_btree.c1
-rw-r--r--fs/xfs/libxfs/xfs_btree.c20
-rw-r--r--fs/xfs/libxfs/xfs_btree.h43
-rw-r--r--fs/xfs/libxfs/xfs_cksum.h26
-rw-r--r--fs/xfs/libxfs/xfs_dir2_data.c2
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.c13
-rw-r--r--fs/xfs/libxfs/xfs_ialloc_btree.c2
-rw-r--r--fs/xfs/libxfs/xfs_inode_buf.c10
-rw-r--r--fs/xfs/libxfs/xfs_refcount_btree.c1
-rw-r--r--fs/xfs/libxfs/xfs_rmap_btree.c1
14 files changed, 93 insertions, 56 deletions
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index effb64cf714f..5050056a0b06 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -2455,12 +2455,15 @@ xfs_agf_verify(
2455 be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp))) 2455 be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp)))
2456 return false; 2456 return false;
2457 2457
2458 if (be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]) > XFS_BTREE_MAXLEVELS || 2458 if (be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]) < 1 ||
2459 be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]) < 1 ||
2460 be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]) > XFS_BTREE_MAXLEVELS ||
2459 be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]) > XFS_BTREE_MAXLEVELS) 2461 be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]) > XFS_BTREE_MAXLEVELS)
2460 return false; 2462 return false;
2461 2463
2462 if (xfs_sb_version_hasrmapbt(&mp->m_sb) && 2464 if (xfs_sb_version_hasrmapbt(&mp->m_sb) &&
2463 be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]) > XFS_BTREE_MAXLEVELS) 2465 (be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]) < 1 ||
2466 be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]) > XFS_BTREE_MAXLEVELS))
2464 return false; 2467 return false;
2465 2468
2466 /* 2469 /*
@@ -2477,7 +2480,8 @@ xfs_agf_verify(
2477 return false; 2480 return false;
2478 2481
2479 if (xfs_sb_version_hasreflink(&mp->m_sb) && 2482 if (xfs_sb_version_hasreflink(&mp->m_sb) &&
2480 be32_to_cpu(agf->agf_refcount_level) > XFS_BTREE_MAXLEVELS) 2483 (be32_to_cpu(agf->agf_refcount_level) < 1 ||
2484 be32_to_cpu(agf->agf_refcount_level) > XFS_BTREE_MAXLEVELS))
2481 return false; 2485 return false;
2482 2486
2483 return true;; 2487 return true;;
diff --git a/fs/xfs/libxfs/xfs_alloc_btree.c b/fs/xfs/libxfs/xfs_alloc_btree.c
index 5ba2dac5e67c..44cfcd03c451 100644
--- a/fs/xfs/libxfs/xfs_alloc_btree.c
+++ b/fs/xfs/libxfs/xfs_alloc_btree.c
@@ -428,6 +428,10 @@ xfs_allocbt_init_cursor(
428 cur->bc_btnum = btnum; 428 cur->bc_btnum = btnum;
429 cur->bc_blocklog = mp->m_sb.sb_blocklog; 429 cur->bc_blocklog = mp->m_sb.sb_blocklog;
430 cur->bc_ops = &xfs_allocbt_ops; 430 cur->bc_ops = &xfs_allocbt_ops;
431 if (btnum == XFS_BTNUM_BNO)
432 cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_abtb_2);
433 else
434 cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_abtc_2);
431 435
432 if (btnum == XFS_BTNUM_CNT) { 436 if (btnum == XFS_BTNUM_CNT) {
433 cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]); 437 cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]);
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.h b/fs/xfs/libxfs/xfs_attr_leaf.h
index 8ef420a16f08..f7dda0c237b0 100644
--- a/fs/xfs/libxfs/xfs_attr_leaf.h
+++ b/fs/xfs/libxfs/xfs_attr_leaf.h
@@ -77,7 +77,7 @@ int xfs_attr3_leaf_add(struct xfs_buf *leaf_buffer,
77 struct xfs_da_args *args); 77 struct xfs_da_args *args);
78int xfs_attr3_leaf_remove(struct xfs_buf *leaf_buffer, 78int xfs_attr3_leaf_remove(struct xfs_buf *leaf_buffer,
79 struct xfs_da_args *args); 79 struct xfs_da_args *args);
80int xfs_attr3_leaf_list_int(struct xfs_buf *bp, 80void xfs_attr3_leaf_list_int(struct xfs_buf *bp,
81 struct xfs_attr_list_context *context); 81 struct xfs_attr_list_context *context);
82 82
83/* 83/*
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 6f2881430c84..2760bc3b2536 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -518,7 +518,7 @@ void
518xfs_bmap_trace_exlist( 518xfs_bmap_trace_exlist(
519 xfs_inode_t *ip, /* incore inode pointer */ 519 xfs_inode_t *ip, /* incore inode pointer */
520 xfs_extnum_t cnt, /* count of entries in the list */ 520 xfs_extnum_t cnt, /* count of entries in the list */
521 int whichfork, /* data or attr fork */ 521 int whichfork, /* data or attr or cow fork */
522 unsigned long caller_ip) 522 unsigned long caller_ip)
523{ 523{
524 xfs_extnum_t idx; /* extent record index */ 524 xfs_extnum_t idx; /* extent record index */
@@ -527,11 +527,13 @@ xfs_bmap_trace_exlist(
527 527
528 if (whichfork == XFS_ATTR_FORK) 528 if (whichfork == XFS_ATTR_FORK)
529 state |= BMAP_ATTRFORK; 529 state |= BMAP_ATTRFORK;
530 else if (whichfork == XFS_COW_FORK)
531 state |= BMAP_COWFORK;
530 532
531 ifp = XFS_IFORK_PTR(ip, whichfork); 533 ifp = XFS_IFORK_PTR(ip, whichfork);
532 ASSERT(cnt == xfs_iext_count(ifp)); 534 ASSERT(cnt == xfs_iext_count(ifp));
533 for (idx = 0; idx < cnt; idx++) 535 for (idx = 0; idx < cnt; idx++)
534 trace_xfs_extlist(ip, idx, whichfork, caller_ip); 536 trace_xfs_extlist(ip, idx, state, caller_ip);
535} 537}
536 538
537/* 539/*
@@ -1151,6 +1153,10 @@ xfs_bmap_add_attrfork(
1151 goto trans_cancel; 1153 goto trans_cancel;
1152 if (XFS_IFORK_Q(ip)) 1154 if (XFS_IFORK_Q(ip))
1153 goto trans_cancel; 1155 goto trans_cancel;
1156 if (ip->i_d.di_anextents != 0) {
1157 error = -EFSCORRUPTED;
1158 goto trans_cancel;
1159 }
1154 if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS) { 1160 if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS) {
1155 /* 1161 /*
1156 * For inodes coming from pre-6.2 filesystems. 1162 * For inodes coming from pre-6.2 filesystems.
@@ -1158,7 +1164,6 @@ xfs_bmap_add_attrfork(
1158 ASSERT(ip->i_d.di_aformat == 0); 1164 ASSERT(ip->i_d.di_aformat == 0);
1159 ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS; 1165 ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
1160 } 1166 }
1161 ASSERT(ip->i_d.di_anextents == 0);
1162 1167
1163 xfs_trans_ijoin(tp, ip, 0); 1168 xfs_trans_ijoin(tp, ip, 0);
1164 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); 1169 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
@@ -1375,8 +1380,9 @@ xfs_bmap_read_extents(
1375 return error; 1380 return error;
1376 block = XFS_BUF_TO_BLOCK(bp); 1381 block = XFS_BUF_TO_BLOCK(bp);
1377 } 1382 }
1383 if (i != XFS_IFORK_NEXTENTS(ip, whichfork))
1384 return -EFSCORRUPTED;
1378 ASSERT(i == xfs_iext_count(ifp)); 1385 ASSERT(i == xfs_iext_count(ifp));
1379 ASSERT(i == XFS_IFORK_NEXTENTS(ip, whichfork));
1380 XFS_BMAP_TRACE_EXLIST(ip, i, whichfork); 1386 XFS_BMAP_TRACE_EXLIST(ip, i, whichfork);
1381 return 0; 1387 return 0;
1382error0: 1388error0:
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c
index 8007d2ba9aef..94ad31d372ab 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.c
+++ b/fs/xfs/libxfs/xfs_bmap_btree.c
@@ -803,6 +803,7 @@ xfs_bmbt_init_cursor(
803 cur->bc_nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1; 803 cur->bc_nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1;
804 cur->bc_btnum = XFS_BTNUM_BMAP; 804 cur->bc_btnum = XFS_BTNUM_BMAP;
805 cur->bc_blocklog = mp->m_sb.sb_blocklog; 805 cur->bc_blocklog = mp->m_sb.sb_blocklog;
806 cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_bmbt_2);
806 807
807 cur->bc_ops = &xfs_bmbt_ops; 808 cur->bc_ops = &xfs_bmbt_ops;
808 cur->bc_flags = XFS_BTREE_LONG_PTRS | XFS_BTREE_ROOT_IN_INODE; 809 cur->bc_flags = XFS_BTREE_LONG_PTRS | XFS_BTREE_ROOT_IN_INODE;
diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c
index 0e80993c8a59..21e6a6ab6b9a 100644
--- a/fs/xfs/libxfs/xfs_btree.c
+++ b/fs/xfs/libxfs/xfs_btree.c
@@ -1769,8 +1769,28 @@ xfs_btree_lookup_get_block(
1769 if (error) 1769 if (error)
1770 return error; 1770 return error;
1771 1771
1772 /* Check the inode owner since the verifiers don't. */
1773 if (xfs_sb_version_hascrc(&cur->bc_mp->m_sb) &&
1774 (cur->bc_flags & XFS_BTREE_LONG_PTRS) &&
1775 be64_to_cpu((*blkp)->bb_u.l.bb_owner) !=
1776 cur->bc_private.b.ip->i_ino)
1777 goto out_bad;
1778
1779 /* Did we get the level we were looking for? */
1780 if (be16_to_cpu((*blkp)->bb_level) != level)
1781 goto out_bad;
1782
1783 /* Check that internal nodes have at least one record. */
1784 if (level != 0 && be16_to_cpu((*blkp)->bb_numrecs) == 0)
1785 goto out_bad;
1786
1772 xfs_btree_setbuf(cur, level, bp); 1787 xfs_btree_setbuf(cur, level, bp);
1773 return 0; 1788 return 0;
1789
1790out_bad:
1791 *blkp = NULL;
1792 xfs_trans_brelse(cur->bc_tp, bp);
1793 return -EFSCORRUPTED;
1774} 1794}
1775 1795
1776/* 1796/*
diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h
index c2b01d1c79ee..b69b947c4c1b 100644
--- a/fs/xfs/libxfs/xfs_btree.h
+++ b/fs/xfs/libxfs/xfs_btree.h
@@ -96,46 +96,10 @@ union xfs_btree_rec {
96/* 96/*
97 * Generic stats interface 97 * Generic stats interface
98 */ 98 */
99#define __XFS_BTREE_STATS_INC(mp, type, stat) \
100 XFS_STATS_INC(mp, xs_ ## type ## _2_ ## stat)
101#define XFS_BTREE_STATS_INC(cur, stat) \ 99#define XFS_BTREE_STATS_INC(cur, stat) \
102do { \ 100 XFS_STATS_INC_OFF((cur)->bc_mp, (cur)->bc_statoff + __XBTS_ ## stat)
103 struct xfs_mount *__mp = cur->bc_mp; \ 101#define XFS_BTREE_STATS_ADD(cur, stat, val) \
104 switch (cur->bc_btnum) { \ 102 XFS_STATS_ADD_OFF((cur)->bc_mp, (cur)->bc_statoff + __XBTS_ ## stat, val)
105 case XFS_BTNUM_BNO: __XFS_BTREE_STATS_INC(__mp, abtb, stat); break; \
106 case XFS_BTNUM_CNT: __XFS_BTREE_STATS_INC(__mp, abtc, stat); break; \
107 case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_INC(__mp, bmbt, stat); break; \
108 case XFS_BTNUM_INO: __XFS_BTREE_STATS_INC(__mp, ibt, stat); break; \
109 case XFS_BTNUM_FINO: __XFS_BTREE_STATS_INC(__mp, fibt, stat); break; \
110 case XFS_BTNUM_RMAP: __XFS_BTREE_STATS_INC(__mp, rmap, stat); break; \
111 case XFS_BTNUM_REFC: __XFS_BTREE_STATS_INC(__mp, refcbt, stat); break; \
112 case XFS_BTNUM_MAX: ASSERT(0); /* fucking gcc */ ; break; \
113 } \
114} while (0)
115
116#define __XFS_BTREE_STATS_ADD(mp, type, stat, val) \
117 XFS_STATS_ADD(mp, xs_ ## type ## _2_ ## stat, val)
118#define XFS_BTREE_STATS_ADD(cur, stat, val) \
119do { \
120 struct xfs_mount *__mp = cur->bc_mp; \
121 switch (cur->bc_btnum) { \
122 case XFS_BTNUM_BNO: \
123 __XFS_BTREE_STATS_ADD(__mp, abtb, stat, val); break; \
124 case XFS_BTNUM_CNT: \
125 __XFS_BTREE_STATS_ADD(__mp, abtc, stat, val); break; \
126 case XFS_BTNUM_BMAP: \
127 __XFS_BTREE_STATS_ADD(__mp, bmbt, stat, val); break; \
128 case XFS_BTNUM_INO: \
129 __XFS_BTREE_STATS_ADD(__mp, ibt, stat, val); break; \
130 case XFS_BTNUM_FINO: \
131 __XFS_BTREE_STATS_ADD(__mp, fibt, stat, val); break; \
132 case XFS_BTNUM_RMAP: \
133 __XFS_BTREE_STATS_ADD(__mp, rmap, stat, val); break; \
134 case XFS_BTNUM_REFC: \
135 __XFS_BTREE_STATS_ADD(__mp, refcbt, stat, val); break; \
136 case XFS_BTNUM_MAX: ASSERT(0); /* fucking gcc */ ; break; \
137 } \
138} while (0)
139 103
140#define XFS_BTREE_MAXLEVELS 9 /* max of all btrees */ 104#define XFS_BTREE_MAXLEVELS 9 /* max of all btrees */
141 105
@@ -253,6 +217,7 @@ typedef struct xfs_btree_cur
253 __uint8_t bc_nlevels; /* number of levels in the tree */ 217 __uint8_t bc_nlevels; /* number of levels in the tree */
254 __uint8_t bc_blocklog; /* log2(blocksize) of btree blocks */ 218 __uint8_t bc_blocklog; /* log2(blocksize) of btree blocks */
255 xfs_btnum_t bc_btnum; /* identifies which btree type */ 219 xfs_btnum_t bc_btnum; /* identifies which btree type */
220 int bc_statoff; /* offset of btre stats array */
256 union { 221 union {
257 struct { /* needed for BNO, CNT, INO */ 222 struct { /* needed for BNO, CNT, INO */
258 struct xfs_buf *agbp; /* agf/agi buffer pointer */ 223 struct xfs_buf *agbp; /* agf/agi buffer pointer */
diff --git a/fs/xfs/libxfs/xfs_cksum.h b/fs/xfs/libxfs/xfs_cksum.h
index fad1676ad8cd..a416c7cb23ea 100644
--- a/fs/xfs/libxfs/xfs_cksum.h
+++ b/fs/xfs/libxfs/xfs_cksum.h
@@ -6,10 +6,11 @@
6/* 6/*
7 * Calculate the intermediate checksum for a buffer that has the CRC field 7 * Calculate the intermediate checksum for a buffer that has the CRC field
8 * inside it. The offset of the 32bit crc fields is passed as the 8 * inside it. The offset of the 32bit crc fields is passed as the
9 * cksum_offset parameter. 9 * cksum_offset parameter. We do not modify the buffer during verification,
10 * hence we have to split the CRC calculation across the cksum_offset.
10 */ 11 */
11static inline __uint32_t 12static inline __uint32_t
12xfs_start_cksum(char *buffer, size_t length, unsigned long cksum_offset) 13xfs_start_cksum_safe(char *buffer, size_t length, unsigned long cksum_offset)
13{ 14{
14 __uint32_t zero = 0; 15 __uint32_t zero = 0;
15 __uint32_t crc; 16 __uint32_t crc;
@@ -26,6 +27,20 @@ xfs_start_cksum(char *buffer, size_t length, unsigned long cksum_offset)
26} 27}
27 28
28/* 29/*
30 * Fast CRC method where the buffer is modified. Callers must have exclusive
31 * access to the buffer while the calculation takes place.
32 */
33static inline __uint32_t
34xfs_start_cksum_update(char *buffer, size_t length, unsigned long cksum_offset)
35{
36 /* zero the CRC field */
37 *(__le32 *)(buffer + cksum_offset) = 0;
38
39 /* single pass CRC calculation for the entire buffer */
40 return crc32c(XFS_CRC_SEED, buffer, length);
41}
42
43/*
29 * Convert the intermediate checksum to the final ondisk format. 44 * Convert the intermediate checksum to the final ondisk format.
30 * 45 *
31 * The CRC32c calculation uses LE format even on BE machines, but returns the 46 * The CRC32c calculation uses LE format even on BE machines, but returns the
@@ -40,11 +55,14 @@ xfs_end_cksum(__uint32_t crc)
40 55
41/* 56/*
42 * Helper to generate the checksum for a buffer. 57 * Helper to generate the checksum for a buffer.
58 *
59 * This modifies the buffer temporarily - callers must have exclusive
60 * access to the buffer while the calculation takes place.
43 */ 61 */
44static inline void 62static inline void
45xfs_update_cksum(char *buffer, size_t length, unsigned long cksum_offset) 63xfs_update_cksum(char *buffer, size_t length, unsigned long cksum_offset)
46{ 64{
47 __uint32_t crc = xfs_start_cksum(buffer, length, cksum_offset); 65 __uint32_t crc = xfs_start_cksum_update(buffer, length, cksum_offset);
48 66
49 *(__le32 *)(buffer + cksum_offset) = xfs_end_cksum(crc); 67 *(__le32 *)(buffer + cksum_offset) = xfs_end_cksum(crc);
50} 68}
@@ -55,7 +73,7 @@ xfs_update_cksum(char *buffer, size_t length, unsigned long cksum_offset)
55static inline int 73static inline int
56xfs_verify_cksum(char *buffer, size_t length, unsigned long cksum_offset) 74xfs_verify_cksum(char *buffer, size_t length, unsigned long cksum_offset)
57{ 75{
58 __uint32_t crc = xfs_start_cksum(buffer, length, cksum_offset); 76 __uint32_t crc = xfs_start_cksum_safe(buffer, length, cksum_offset);
59 77
60 return *(__le32 *)(buffer + cksum_offset) == xfs_end_cksum(crc); 78 return *(__le32 *)(buffer + cksum_offset) == xfs_end_cksum(crc);
61} 79}
diff --git a/fs/xfs/libxfs/xfs_dir2_data.c b/fs/xfs/libxfs/xfs_dir2_data.c
index cd75ab9f3bf8..d478065b9544 100644
--- a/fs/xfs/libxfs/xfs_dir2_data.c
+++ b/fs/xfs/libxfs/xfs_dir2_data.c
@@ -329,7 +329,7 @@ xfs_dir3_data_read(
329 329
330 err = xfs_da_read_buf(tp, dp, bno, mapped_bno, bpp, 330 err = xfs_da_read_buf(tp, dp, bno, mapped_bno, bpp,
331 XFS_DATA_FORK, &xfs_dir3_data_buf_ops); 331 XFS_DATA_FORK, &xfs_dir3_data_buf_ops);
332 if (!err && tp) 332 if (!err && tp && *bpp)
333 xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_DATA_BUF); 333 xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_DATA_BUF);
334 return err; 334 return err;
335} 335}
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index c507c1b17ca1..f272abff11e1 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -2451,8 +2451,6 @@ xfs_ialloc_log_agi(
2451 ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC)); 2451 ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC));
2452#endif 2452#endif
2453 2453
2454 xfs_trans_buf_set_type(tp, bp, XFS_BLFT_AGI_BUF);
2455
2456 /* 2454 /*
2457 * Compute byte offsets for the first and last fields in the first 2455 * Compute byte offsets for the first and last fields in the first
2458 * region and log the agi buffer. This only logs up through 2456 * region and log the agi buffer. This only logs up through
@@ -2513,8 +2511,15 @@ xfs_agi_verify(
2513 if (!XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum))) 2511 if (!XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum)))
2514 return false; 2512 return false;
2515 2513
2516 if (be32_to_cpu(agi->agi_level) > XFS_BTREE_MAXLEVELS) 2514 if (be32_to_cpu(agi->agi_level) < 1 ||
2515 be32_to_cpu(agi->agi_level) > XFS_BTREE_MAXLEVELS)
2516 return false;
2517
2518 if (xfs_sb_version_hasfinobt(&mp->m_sb) &&
2519 (be32_to_cpu(agi->agi_free_level) < 1 ||
2520 be32_to_cpu(agi->agi_free_level) > XFS_BTREE_MAXLEVELS))
2517 return false; 2521 return false;
2522
2518 /* 2523 /*
2519 * during growfs operations, the perag is not fully initialised, 2524 * during growfs operations, the perag is not fully initialised,
2520 * so we can't use it for any useful checking. growfs ensures we can't 2525 * so we can't use it for any useful checking. growfs ensures we can't
@@ -2593,6 +2598,8 @@ xfs_read_agi(
2593 XFS_FSS_TO_BB(mp, 1), 0, bpp, &xfs_agi_buf_ops); 2598 XFS_FSS_TO_BB(mp, 1), 0, bpp, &xfs_agi_buf_ops);
2594 if (error) 2599 if (error)
2595 return error; 2600 return error;
2601 if (tp)
2602 xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_AGI_BUF);
2596 2603
2597 xfs_buf_set_ref(*bpp, XFS_AGI_REF); 2604 xfs_buf_set_ref(*bpp, XFS_AGI_REF);
2598 return 0; 2605 return 0;
diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c
index eab68ae2e011..e7ff8ef0e5a7 100644
--- a/fs/xfs/libxfs/xfs_ialloc_btree.c
+++ b/fs/xfs/libxfs/xfs_ialloc_btree.c
@@ -365,9 +365,11 @@ xfs_inobt_init_cursor(
365 if (btnum == XFS_BTNUM_INO) { 365 if (btnum == XFS_BTNUM_INO) {
366 cur->bc_nlevels = be32_to_cpu(agi->agi_level); 366 cur->bc_nlevels = be32_to_cpu(agi->agi_level);
367 cur->bc_ops = &xfs_inobt_ops; 367 cur->bc_ops = &xfs_inobt_ops;
368 cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_ibt_2);
368 } else { 369 } else {
369 cur->bc_nlevels = be32_to_cpu(agi->agi_free_level); 370 cur->bc_nlevels = be32_to_cpu(agi->agi_free_level);
370 cur->bc_ops = &xfs_finobt_ops; 371 cur->bc_ops = &xfs_finobt_ops;
372 cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_fibt_2);
371 } 373 }
372 374
373 cur->bc_blocklog = mp->m_sb.sb_blocklog; 375 cur->bc_blocklog = mp->m_sb.sb_blocklog;
diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
index 54817f82212c..dd483e2767f7 100644
--- a/fs/xfs/libxfs/xfs_inode_buf.c
+++ b/fs/xfs/libxfs/xfs_inode_buf.c
@@ -392,6 +392,14 @@ xfs_dinode_verify(
392 if (dip->di_magic != cpu_to_be16(XFS_DINODE_MAGIC)) 392 if (dip->di_magic != cpu_to_be16(XFS_DINODE_MAGIC))
393 return false; 393 return false;
394 394
395 /* don't allow invalid i_size */
396 if (be64_to_cpu(dip->di_size) & (1ULL << 63))
397 return false;
398
399 /* No zero-length symlinks. */
400 if (S_ISLNK(be16_to_cpu(dip->di_mode)) && dip->di_size == 0)
401 return false;
402
395 /* only version 3 or greater inodes are extensively verified here */ 403 /* only version 3 or greater inodes are extensively verified here */
396 if (dip->di_version < 3) 404 if (dip->di_version < 3)
397 return true; 405 return true;
@@ -436,7 +444,7 @@ xfs_dinode_calc_crc(
436 return; 444 return;
437 445
438 ASSERT(xfs_sb_version_hascrc(&mp->m_sb)); 446 ASSERT(xfs_sb_version_hascrc(&mp->m_sb));
439 crc = xfs_start_cksum((char *)dip, mp->m_sb.sb_inodesize, 447 crc = xfs_start_cksum_update((char *)dip, mp->m_sb.sb_inodesize,
440 XFS_DINODE_CRC_OFF); 448 XFS_DINODE_CRC_OFF);
441 dip->di_crc = xfs_end_cksum(crc); 449 dip->di_crc = xfs_end_cksum(crc);
442} 450}
diff --git a/fs/xfs/libxfs/xfs_refcount_btree.c b/fs/xfs/libxfs/xfs_refcount_btree.c
index 453bb2757ec2..6fb2215f8ff7 100644
--- a/fs/xfs/libxfs/xfs_refcount_btree.c
+++ b/fs/xfs/libxfs/xfs_refcount_btree.c
@@ -354,6 +354,7 @@ xfs_refcountbt_init_cursor(
354 cur->bc_btnum = XFS_BTNUM_REFC; 354 cur->bc_btnum = XFS_BTNUM_REFC;
355 cur->bc_blocklog = mp->m_sb.sb_blocklog; 355 cur->bc_blocklog = mp->m_sb.sb_blocklog;
356 cur->bc_ops = &xfs_refcountbt_ops; 356 cur->bc_ops = &xfs_refcountbt_ops;
357 cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_refcbt_2);
357 358
358 cur->bc_nlevels = be32_to_cpu(agf->agf_refcount_level); 359 cur->bc_nlevels = be32_to_cpu(agf->agf_refcount_level);
359 360
diff --git a/fs/xfs/libxfs/xfs_rmap_btree.c b/fs/xfs/libxfs/xfs_rmap_btree.c
index 83e672ff7577..de25771764ba 100644
--- a/fs/xfs/libxfs/xfs_rmap_btree.c
+++ b/fs/xfs/libxfs/xfs_rmap_btree.c
@@ -484,6 +484,7 @@ xfs_rmapbt_init_cursor(
484 cur->bc_blocklog = mp->m_sb.sb_blocklog; 484 cur->bc_blocklog = mp->m_sb.sb_blocklog;
485 cur->bc_ops = &xfs_rmapbt_ops; 485 cur->bc_ops = &xfs_rmapbt_ops;
486 cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]); 486 cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]);
487 cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_rmap_2);
487 488
488 cur->bc_private.a.agbp = agbp; 489 cur->bc_private.a.agbp = agbp;
489 cur->bc_private.a.agno = agno; 490 cur->bc_private.a.agno = agno;