linux/fs/xfs/xfs_trans_priv.h
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
   4 * All Rights Reserved.
   5 */
   6#ifndef __XFS_TRANS_PRIV_H__
   7#define __XFS_TRANS_PRIV_H__
   8
   9struct xfs_log_item;
  10struct xfs_mount;
  11struct xfs_trans;
  12struct xfs_ail;
  13struct xfs_log_vec;
  14
  15
  16void    xfs_trans_init(struct xfs_mount *);
  17void    xfs_trans_add_item(struct xfs_trans *, struct xfs_log_item *);
  18void    xfs_trans_del_item(struct xfs_log_item *);
  19void    xfs_trans_unreserve_and_mod_sb(struct xfs_trans *tp);
  20
  21void    xfs_trans_committed_bulk(struct xfs_ail *ailp, struct xfs_log_vec *lv,
  22                                xfs_lsn_t commit_lsn, bool aborted);
  23/*
  24 * AIL traversal cursor.
  25 *
  26 * Rather than using a generation number for detecting changes in the ail, use
  27 * a cursor that is protected by the ail lock. The aild cursor exists in the
  28 * struct xfs_ail, but other traversals can declare it on the stack and link it
  29 * to the ail list.
  30 *
  31 * When an object is deleted from or moved int the AIL, the cursor list is
  32 * searched to see if the object is a designated cursor item. If it is, it is
  33 * deleted from the cursor so that the next time the cursor is used traversal
  34 * will return to the start.
  35 *
  36 * This means a traversal colliding with a removal will cause a restart of the
  37 * list scan, rather than any insertion or deletion anywhere in the list. The
  38 * low bit of the item pointer is set if the cursor has been invalidated so
  39 * that we can tell the difference between invalidation and reaching the end
  40 * of the list to trigger traversal restarts.
  41 */
  42struct xfs_ail_cursor {
  43        struct list_head        list;
  44        struct xfs_log_item     *item;
  45};
  46
  47/*
  48 * Private AIL structures.
  49 *
  50 * Eventually we need to drive the locking in here as well.
  51 */
  52struct xfs_ail {
  53        struct xfs_mount        *ail_mount;
  54        struct task_struct      *ail_task;
  55        struct list_head        ail_head;
  56        xfs_lsn_t               ail_target;
  57        xfs_lsn_t               ail_target_prev;
  58        struct list_head        ail_cursors;
  59        spinlock_t              ail_lock;
  60        xfs_lsn_t               ail_last_pushed_lsn;
  61        int                     ail_log_flush;
  62        struct list_head        ail_buf_list;
  63        wait_queue_head_t       ail_empty;
  64};
  65
  66/*
  67 * From xfs_trans_ail.c
  68 */
  69void    xfs_trans_ail_update_bulk(struct xfs_ail *ailp,
  70                                struct xfs_ail_cursor *cur,
  71                                struct xfs_log_item **log_items, int nr_items,
  72                                xfs_lsn_t lsn) __releases(ailp->ail_lock);
  73/*
  74 * Return a pointer to the first item in the AIL.  If the AIL is empty, then
  75 * return NULL.
  76 */
  77static inline struct xfs_log_item *
  78xfs_ail_min(
  79        struct xfs_ail  *ailp)
  80{
  81        return list_first_entry_or_null(&ailp->ail_head, struct xfs_log_item,
  82                                        li_ail);
  83}
  84
  85static inline void
  86xfs_trans_ail_update(
  87        struct xfs_ail          *ailp,
  88        struct xfs_log_item     *lip,
  89        xfs_lsn_t               lsn) __releases(ailp->ail_lock)
  90{
  91        xfs_trans_ail_update_bulk(ailp, NULL, &lip, 1, lsn);
  92}
  93
  94bool xfs_ail_delete_one(struct xfs_ail *ailp, struct xfs_log_item *lip);
  95void xfs_trans_ail_delete(struct xfs_ail *ailp, struct xfs_log_item *lip,
  96                int shutdown_type) __releases(ailp->ail_lock);
  97
  98static inline void
  99xfs_trans_ail_remove(
 100        struct xfs_log_item     *lip,
 101        int                     shutdown_type)
 102{
 103        struct xfs_ail          *ailp = lip->li_ailp;
 104
 105        spin_lock(&ailp->ail_lock);
 106        /* xfs_trans_ail_delete() drops the AIL lock */
 107        if (test_bit(XFS_LI_IN_AIL, &lip->li_flags))
 108                xfs_trans_ail_delete(ailp, lip, shutdown_type);
 109        else
 110                spin_unlock(&ailp->ail_lock);
 111}
 112
 113void                    xfs_ail_push(struct xfs_ail *, xfs_lsn_t);
 114void                    xfs_ail_push_all(struct xfs_ail *);
 115void                    xfs_ail_push_all_sync(struct xfs_ail *);
 116struct xfs_log_item     *xfs_ail_min(struct xfs_ail  *ailp);
 117xfs_lsn_t               xfs_ail_min_lsn(struct xfs_ail *ailp);
 118
 119struct xfs_log_item *   xfs_trans_ail_cursor_first(struct xfs_ail *ailp,
 120                                        struct xfs_ail_cursor *cur,
 121                                        xfs_lsn_t lsn);
 122struct xfs_log_item *   xfs_trans_ail_cursor_last(struct xfs_ail *ailp,
 123                                        struct xfs_ail_cursor *cur,
 124                                        xfs_lsn_t lsn);
 125struct xfs_log_item *   xfs_trans_ail_cursor_next(struct xfs_ail *ailp,
 126                                        struct xfs_ail_cursor *cur);
 127void                    xfs_trans_ail_cursor_done(struct xfs_ail_cursor *cur);
 128
 129#if BITS_PER_LONG != 64
 130static inline void
 131xfs_trans_ail_copy_lsn(
 132        struct xfs_ail  *ailp,
 133        xfs_lsn_t       *dst,
 134        xfs_lsn_t       *src)
 135{
 136        ASSERT(sizeof(xfs_lsn_t) == 8); /* don't lock if it shrinks */
 137        spin_lock(&ailp->ail_lock);
 138        *dst = *src;
 139        spin_unlock(&ailp->ail_lock);
 140}
 141#else
 142static inline void
 143xfs_trans_ail_copy_lsn(
 144        struct xfs_ail  *ailp,
 145        xfs_lsn_t       *dst,
 146        xfs_lsn_t       *src)
 147{
 148        ASSERT(sizeof(xfs_lsn_t) == 8);
 149        *dst = *src;
 150}
 151#endif
 152
 153static inline void
 154xfs_clear_li_failed(
 155        struct xfs_log_item     *lip)
 156{
 157        struct xfs_buf  *bp = lip->li_buf;
 158
 159        ASSERT(test_bit(XFS_LI_IN_AIL, &lip->li_flags));
 160        lockdep_assert_held(&lip->li_ailp->ail_lock);
 161
 162        if (test_and_clear_bit(XFS_LI_FAILED, &lip->li_flags)) {
 163                lip->li_buf = NULL;
 164                xfs_buf_rele(bp);
 165        }
 166}
 167
 168static inline void
 169xfs_set_li_failed(
 170        struct xfs_log_item     *lip,
 171        struct xfs_buf          *bp)
 172{
 173        lockdep_assert_held(&lip->li_ailp->ail_lock);
 174
 175        if (!test_and_set_bit(XFS_LI_FAILED, &lip->li_flags)) {
 176                xfs_buf_hold(bp);
 177                lip->li_buf = bp;
 178        }
 179}
 180
 181#endif  /* __XFS_TRANS_PRIV_H__ */
 182