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