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

Configure Feed

Select the types of activity you want to include in your feed.

xfs: remove the leftover xfs_{set,clear}_li_failed infrastructure

Marking a log item as failed kept a buffer reference around for
resubmission of inode and dquote items.

For inode items commit 298f7bec503f3 ("xfs: pin inode backing buffer to
the inode log item") started pinning the inode item buffers
unconditionally and removed the need for this. Later commit acc8f8628c37
("xfs: attach dquot buffer to dquot log item buffer") did the same for
dquot items but didn't fully clean up the xfs_clear_li_failed side
for them. Stop adding the extra pin for dquot items and remove the
helpers.

This happens to fix a call to xfs_buf_free with the AIL lock held,
which would be incorrect for the unlikely case freeing the buffer
ends up calling vfree.

Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>

authored by

Christoph Hellwig and committed by
Carlos Maiolino
b73e0528 8ffd015d

+3 -39
+1 -2
fs/xfs/xfs_dquot.c
··· 1186 1186 if (test_bit(XFS_LI_IN_AIL, &lip->li_flags) && 1187 1187 (lip->li_lsn == qlip->qli_flush_lsn || 1188 1188 test_bit(XFS_LI_FAILED, &lip->li_flags))) { 1189 - 1190 1189 spin_lock(&ailp->ail_lock); 1191 - xfs_clear_li_failed(lip); 1190 + clear_bit(XFS_LI_FAILED, &lip->li_flags); 1192 1191 if (lip->li_lsn == qlip->qli_flush_lsn) { 1193 1192 /* xfs_ail_update_finish() drops the AIL lock */ 1194 1193 tail_lsn = xfs_ail_delete_one(ailp, lip);
-6
fs/xfs/xfs_inode_item.c
··· 1089 1089 * state. Whilst the inode is in the AIL, it should have a valid buffer 1090 1090 * pointer for push operations to access - it is only safe to remove the 1091 1091 * inode from the buffer once it has been removed from the AIL. 1092 - * 1093 - * We also clear the failed bit before removing the item from the AIL 1094 - * as xfs_trans_ail_delete()->xfs_clear_li_failed() will release buffer 1095 - * references the inode item owns and needs to hold until we've fully 1096 - * aborted the inode log item and detached it from the buffer. 1097 1092 */ 1098 - clear_bit(XFS_LI_FAILED, &iip->ili_item.li_flags); 1099 1093 xfs_trans_ail_delete(&iip->ili_item, 0); 1100 1094 1101 1095 /*
+2 -3
fs/xfs/xfs_trans_ail.c
··· 909 909 return; 910 910 } 911 911 912 - /* xfs_ail_update_finish() drops the AIL lock */ 913 - xfs_clear_li_failed(lip); 912 + clear_bit(XFS_LI_FAILED, &lip->li_flags); 914 913 tail_lsn = xfs_ail_delete_one(ailp, lip); 915 - xfs_ail_update_finish(ailp, tail_lsn); 914 + xfs_ail_update_finish(ailp, tail_lsn); /* drops the AIL lock */ 916 915 } 917 916 918 917 int
-28
fs/xfs/xfs_trans_priv.h
··· 167 167 } 168 168 #endif 169 169 170 - static inline void 171 - xfs_clear_li_failed( 172 - struct xfs_log_item *lip) 173 - { 174 - struct xfs_buf *bp = lip->li_buf; 175 - 176 - ASSERT(test_bit(XFS_LI_IN_AIL, &lip->li_flags)); 177 - lockdep_assert_held(&lip->li_ailp->ail_lock); 178 - 179 - if (test_and_clear_bit(XFS_LI_FAILED, &lip->li_flags)) { 180 - lip->li_buf = NULL; 181 - xfs_buf_rele(bp); 182 - } 183 - } 184 - 185 - static inline void 186 - xfs_set_li_failed( 187 - struct xfs_log_item *lip, 188 - struct xfs_buf *bp) 189 - { 190 - lockdep_assert_held(&lip->li_ailp->ail_lock); 191 - 192 - if (!test_and_set_bit(XFS_LI_FAILED, &lip->li_flags)) { 193 - xfs_buf_hold(bp); 194 - lip->li_buf = bp; 195 - } 196 - } 197 - 198 170 #endif /* __XFS_TRANS_PRIV_H__ */