Use the lowest two bits in current->journal_info to encode when we're holding a glock and when an operation holding a glock needs to be retried. Signed-off-by: Andreas Gruenbacher <agruenba@xxxxxxxxxx> --- fs/gfs2/incore.h | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index aa8d1a23132d..e32433df119c 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -871,14 +871,45 @@ static inline unsigned gfs2_max_stuffed_size(const struct gfs2_inode *ip) return GFS2_SB(&ip->i_inode)->sd_sb.sb_bsize - sizeof(struct gfs2_dinode); } +/* + * Transactions are always memory aligned, so we use bit 0 of + * current->journal_info to indicate when we're holding a glock and so taking + * random additional glocks might deadlock, and bit 1 to indicate when such an + * operation needs to be retried after dropping and re-acquiring that "outer" + * glock. + */ + static inline struct gfs2_trans *current_trans(void) { - return current->journal_info; + return (void *)((long)current->journal_info & ~3); } static inline void set_current_trans(struct gfs2_trans *tr) { - current->journal_info = tr; + long flags = (long)current->journal_info & 3; + current->journal_info = (void *)((long)tr | flags); +} + +static inline bool current_holds_glock(void) +{ + return (long)current->journal_info & 1; +} + +static inline bool current_needs_retry(void) +{ + return (long)current->journal_info & 2; +} + +static inline void set_current_holds_glock(bool b) +{ + current->journal_info = + (void *)(((long)current->journal_info & ~1) | b); +} + +static inline void set_current_needs_retry(bool b) +{ + current->journal_info = + (void *)(((long)current->journal_info & ~2) | (b << 1)); } #endif /* __INCORE_DOT_H__ */ -- 2.26.3