@@ -832,6 +832,39 @@ xfs_calc_sb_reservation(
return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
}
+int
+xfs_trans_resv_ext_cnt(
+ struct xfs_inode *ip,
+ int whichfork,
+ int nr_to_add)
+{
+ struct xfs_ifork *ifp;
+ uint64_t max_exts = 0;
+ uint64_t nr_exts;
+
+ switch (whichfork) {
+ case XFS_DATA_FORK:
+ max_exts = MAXEXTNUM;
+ break;
+
+ case XFS_ATTR_FORK:
+ max_exts = MAXAEXTNUM;
+ break;
+
+ default:
+ ASSERT(0);
+ break;
+ }
+
+ ifp = XFS_IFORK_PTR(ip, whichfork);
+ nr_exts = ifp->if_nextents + nr_to_add;
+
+ if (nr_exts > max_exts)
+ return -EFBIG;
+
+ return 0;
+}
+
void
xfs_trans_resv_calc(
struct xfs_mount *mp,
@@ -93,5 +93,6 @@ struct xfs_trans_resv {
void xfs_trans_resv_calc(struct xfs_mount *mp, struct xfs_trans_resv *resp);
uint xfs_allocfree_log_count(struct xfs_mount *mp, uint num_ops);
+int xfs_trans_resv_ext_cnt(struct xfs_inode *ip, int whichfork, int nr_exts);
#endif /* __XFS_TRANS_RESV_H__ */
XFS does not check for possible overflow of per-inode extent counter fields when adding extents to either data or attr fork. For e.g. 1. Insert 5 million xattrs (each having a value size of 255 bytes) and then delete 50% of them in an alternating manner. 2. On a 4k block sized XFS filesystem instance, the above causes 98511 extents to be created in the attr fork of the inode. xfsaild/loop0 2035 [003] 9643.390490: probe:xfs_iflush_int: (ffffffffac6225c0) if_nextents=98511 inode=131 3. The incore inode fork extent counter is a signed 32-bit quantity. However the on-disk extent counter is an unsigned 16-bit quantity and hence cannot hold 98511 extents. 4. The following incorrect value is stored in the attr extent counter, # xfs_db -f -c 'inode 131' -c 'print core.naextents' /dev/loop0 core.naextents = -32561 This commit adds a new helper function (i.e. xfs_trans_resv_ext_cnt()) to check for overflow of the per-inode data and xattr extent counters. A future patch will use this function to make sure that a transaction will not cause the extent counter to overflow. Suggested-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Chandan Babu R <chandanrlinux@gmail.com> --- fs/xfs/libxfs/xfs_trans_resv.c | 33 +++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_trans_resv.h | 1 + 2 files changed, 34 insertions(+)