Commit 9f7b640f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'xfs-5.14-merge-6' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux

Pull xfs updates from Darrick Wong:
 "Most of the work this cycle has been on refactoring various parts of
  the codebase. The biggest non-cleanup changes are (1) reducing the
  number of cache flushes sent when writing the log; (2) a substantial
  number of log recovery fixes; and (3) I started accepting pull
  requests from contributors if the commits in their branches match
  what's been sent to the list.

  For a week or so I /had/ staged a major cleanup of the logging code
  from Dave Chinner, but it exposed so many lurking bugs in other parts
  of the logging and log recovery code that I decided to defer that
  patchset until we can address those latent bugs.

  Larger cleanups this time include walking the incore inode cache (me)
  and rework of the extended attribute code (Allison) to prepare it for
  adding logged xattr updates (and directory tree parent pointers) in
  future releases.

  Summary:

   - Refactor the buffer cache to use bulk page allocation

   - Convert agnumber-based AG iteration to walk per-AG structures

   - Clean up some unit conversions and other code warts

   - Reduce spinlock contention in the directio fastpath

   - Collapse all the inode cache walks into a single function

   - Remove indirect function calls from the inode cache walk code

   - Dramatically reduce the number of cache flushes sent when writing
     log buffers

   - Preserve inode sickness reports for longer

   - Rename xfs_eofblocks since it controls inode cache walks

   - Refactor the extended attribute code to prepare it for the addition
     of log intent items to make xattrs fully transactional

   - A few fixes to earlier large patchsets

   - Log recovery fixes so that we don't accidentally mark the log clean
     when log intent recovery fails

   - Fix some latent SOB errors

   - Clean up shutdown messages that get logged to dmesg

   - Fix a regression in the online shrink code

   - Fix a UAF in the buffer logging code if the fs goes offline

   - Fix uninitialized error variables

   - Fix a UAF in the CIL when commited log item callbacks race with a
     shutdown

   - Fix a bug where the CIL could hang trying to push part of the log
     ring buffer that hasn't been filled yet"

* tag 'xfs-5.14-merge-6' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: (102 commits)
  xfs: don't wait on future iclogs when pushing the CIL
  xfs: Fix a CIL UAF by getting get rid of the iclog callback lock
  xfs: remove callback dequeue loop from xlog_state_do_iclog_callbacks
  xfs: don't nest icloglock inside ic_callback_lock
  xfs: Initialize error in xfs_attr_remove_iter
  xfs: fix endianness issue in xfs_ag_shrink_space
  xfs: remove dead stale buf unpin handling code
  xfs: hold buffer across unpin and potential shutdown processing
  xfs: force the log offline when log intent item recovery fails
  xfs: fix log intent recovery ENOSPC shutdowns when inactivating inodes
  xfs: shorten the shutdown messages to a single line
  xfs: print name of function causing fs shutdown instead of hex pointer
  xfs: fix type mismatches in the inode reclaim functions
  xfs: separate primary inode selection criteria in xfs_iget_cache_hit
  xfs: refactor the inode recycling code
  xfs: add iclog state trace events
  xfs: xfs_log_force_lsn isn't passed a LSN
  xfs: Fix CIL throttle hang when CIL space used going backwards
  xfs: journal IO cache flush reductions
  xfs: remove need_start_rec parameter from xlog_write()
  ...
parents e4aa67b0 1effb72a
...@@ -27,6 +27,276 @@ ...@@ -27,6 +27,276 @@
#include "xfs_defer.h" #include "xfs_defer.h"
#include "xfs_log_format.h" #include "xfs_log_format.h"
#include "xfs_trans.h" #include "xfs_trans.h"
#include "xfs_trace.h"
#include "xfs_inode.h"
#include "xfs_icache.h"
/*
* Passive reference counting access wrappers to the perag structures. If the
* per-ag structure is to be freed, the freeing code is responsible for cleaning
* up objects with passive references before freeing the structure. This is
* things like cached buffers.
*/
struct xfs_perag *
xfs_perag_get(
struct xfs_mount *mp,
xfs_agnumber_t agno)
{
struct xfs_perag *pag;
int ref = 0;
rcu_read_lock();
pag = radix_tree_lookup(&mp->m_perag_tree, agno);
if (pag) {
ASSERT(atomic_read(&pag->pag_ref) >= 0);
ref = atomic_inc_return(&pag->pag_ref);
}
rcu_read_unlock();
trace_xfs_perag_get(mp, agno, ref, _RET_IP_);
return pag;
}
/*
* search from @first to find the next perag with the given tag set.
*/
struct xfs_perag *
xfs_perag_get_tag(
struct xfs_mount *mp,
xfs_agnumber_t first,
unsigned int tag)
{
struct xfs_perag *pag;
int found;
int ref;
rcu_read_lock();
found = radix_tree_gang_lookup_tag(&mp->m_perag_tree,
(void **)&pag, first, 1, tag);
if (found <= 0) {
rcu_read_unlock();
return NULL;
}
ref = atomic_inc_return(&pag->pag_ref);
rcu_read_unlock();
trace_xfs_perag_get_tag(mp, pag->pag_agno, ref, _RET_IP_);
return pag;
}
void
xfs_perag_put(
struct xfs_perag *pag)
{
int ref;
ASSERT(atomic_read(&pag->pag_ref) > 0);
ref = atomic_dec_return(&pag->pag_ref);
trace_xfs_perag_put(pag->pag_mount, pag->pag_agno, ref, _RET_IP_);
}
/*
* xfs_initialize_perag_data
*
* Read in each per-ag structure so we can count up the number of
* allocated inodes, free inodes and used filesystem blocks as this
* information is no longer persistent in the superblock. Once we have
* this information, write it into the in-core superblock structure.
*/
int
xfs_initialize_perag_data(
struct xfs_mount *mp,
xfs_agnumber_t agcount)
{
xfs_agnumber_t index;
struct xfs_perag *pag;
struct xfs_sb *sbp = &mp->m_sb;
uint64_t ifree = 0;
uint64_t ialloc = 0;
uint64_t bfree = 0;
uint64_t bfreelst = 0;
uint64_t btree = 0;
uint64_t fdblocks;
int error = 0;
for (index = 0; index < agcount; index++) {
/*
* read the agf, then the agi. This gets us
* all the information we need and populates the
* per-ag structures for us.
*/
error = xfs_alloc_pagf_init(mp, NULL, index, 0);
if (error)
return error;
error = xfs_ialloc_pagi_init(mp, NULL, index);
if (error)
return error;
pag = xfs_perag_get(mp, index);
ifree += pag->pagi_freecount;
ialloc += pag->pagi_count;
bfree += pag->pagf_freeblks;
bfreelst += pag->pagf_flcount;
btree += pag->pagf_btreeblks;
xfs_perag_put(pag);
}
fdblocks = bfree + bfreelst + btree;
/*
* If the new summary counts are obviously incorrect, fail the
* mount operation because that implies the AGFs are also corrupt.
* Clear FS_COUNTERS so that we don't unmount with a dirty log, which
* will prevent xfs_repair from fixing anything.
*/
if (fdblocks > sbp->sb_dblocks || ifree > ialloc) {
xfs_alert(mp, "AGF corruption. Please run xfs_repair.");
error = -EFSCORRUPTED;
goto out;
}
/* Overwrite incore superblock counters with just-read data */
spin_lock(&mp->m_sb_lock);
sbp->sb_ifree = ifree;
sbp->sb_icount = ialloc;
sbp->sb_fdblocks = fdblocks;
spin_unlock(&mp->m_sb_lock);
xfs_reinit_percpu_counters(mp);
out:
xfs_fs_mark_healthy(mp, XFS_SICK_FS_COUNTERS);
return error;
}
STATIC void
__xfs_free_perag(
struct rcu_head *head)
{
struct xfs_perag *pag = container_of(head, struct xfs_perag, rcu_head);
ASSERT(!delayed_work_pending(&pag->pag_blockgc_work));
ASSERT(atomic_read(&pag->pag_ref) == 0);
kmem_free(pag);
}
/*
* Free up the per-ag resources associated with the mount structure.
*/
void
xfs_free_perag(
struct xfs_mount *mp)
{
struct xfs_perag *pag;
xfs_agnumber_t agno;
for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
spin_lock(&mp->m_perag_lock);
pag = radix_tree_delete(&mp->m_perag_tree, agno);
spin_unlock(&mp->m_perag_lock);
ASSERT(pag);
ASSERT(atomic_read(&pag->pag_ref) == 0);
cancel_delayed_work_sync(&pag->pag_blockgc_work);
xfs_iunlink_destroy(pag);
xfs_buf_hash_destroy(pag);
call_rcu(&pag->rcu_head, __xfs_free_perag);
}
}
int
xfs_initialize_perag(
struct xfs_mount *mp,
xfs_agnumber_t agcount,
xfs_agnumber_t *maxagi)
{
struct xfs_perag *pag;
xfs_agnumber_t index;
xfs_agnumber_t first_initialised = NULLAGNUMBER;
int error;
/*
* Walk the current per-ag tree so we don't try to initialise AGs
* that already exist (growfs case). Allocate and insert all the
* AGs we don't find ready for initialisation.
*/
for (index = 0; index < agcount; index++) {
pag = xfs_perag_get(mp, index);
if (pag) {
xfs_perag_put(pag);
continue;
}
pag = kmem_zalloc(sizeof(*pag), KM_MAYFAIL);
if (!pag) {
error = -ENOMEM;
goto out_unwind_new_pags;
}
pag->pag_agno = index;
pag->pag_mount = mp;
error = radix_tree_preload(GFP_NOFS);
if (error)
goto out_free_pag;
spin_lock(&mp->m_perag_lock);
if (radix_tree_insert(&mp->m_perag_tree, index, pag)) {
WARN_ON_ONCE(1);
spin_unlock(&mp->m_perag_lock);
radix_tree_preload_end();
error = -EEXIST;
goto out_free_pag;
}
spin_unlock(&mp->m_perag_lock);
radix_tree_preload_end();
/* Place kernel structure only init below this point. */
spin_lock_init(&pag->pag_ici_lock);
spin_lock_init(&pag->pagb_lock);
spin_lock_init(&pag->pag_state_lock);
INIT_DELAYED_WORK(&pag->pag_blockgc_work, xfs_blockgc_worker);
INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);
init_waitqueue_head(&pag->pagb_wait);
pag->pagb_count = 0;
pag->pagb_tree = RB_ROOT;
error = xfs_buf_hash_init(pag);
if (error)
goto out_remove_pag;
error = xfs_iunlink_init(pag);
if (error)
goto out_hash_destroy;
/* first new pag is fully initialized */
if (first_initialised == NULLAGNUMBER)
first_initialised = index;
}
index = xfs_set_inode_alloc(mp, agcount);
if (maxagi)
*maxagi = index;
mp->m_ag_prealloc_blocks = xfs_prealloc_blocks(mp);
return 0;
out_hash_destroy:
xfs_buf_hash_destroy(pag);
out_remove_pag:
radix_tree_delete(&mp->m_perag_tree, index);
out_free_pag:
kmem_free(pag);
out_unwind_new_pags:
/* unwind any prior newly initialized pags */
for (index = first_initialised; index < agcount; index++) {
pag = radix_tree_delete(&mp->m_perag_tree, index);
if (!pag)
break;
xfs_buf_hash_destroy(pag);
xfs_iunlink_destroy(pag);
kmem_free(pag);
}
return error;
}
static int static int
xfs_get_aghdr_buf( xfs_get_aghdr_buf(
...@@ -43,7 +313,6 @@ xfs_get_aghdr_buf( ...@@ -43,7 +313,6 @@ xfs_get_aghdr_buf(
if (error) if (error)
return error; return error;
xfs_buf_zero(bp, 0, BBTOB(bp->b_length));
bp->b_bn = blkno; bp->b_bn = blkno;
bp->b_maps[0].bm_bn = blkno; bp->b_maps[0].bm_bn = blkno;
bp->b_ops = ops; bp->b_ops = ops;
...@@ -510,6 +779,7 @@ xfs_ag_shrink_space( ...@@ -510,6 +779,7 @@ xfs_ag_shrink_space(
struct xfs_buf *agibp, *agfbp; struct xfs_buf *agibp, *agfbp;
struct xfs_agi *agi; struct xfs_agi *agi;
struct xfs_agf *agf; struct xfs_agf *agf;
xfs_agblock_t aglen;
int error, err2; int error, err2;
ASSERT(agno == mp->m_sb.sb_agcount - 1); ASSERT(agno == mp->m_sb.sb_agcount - 1);
...@@ -524,14 +794,14 @@ xfs_ag_shrink_space( ...@@ -524,14 +794,14 @@ xfs_ag_shrink_space(
return error; return error;
agf = agfbp->b_addr; agf = agfbp->b_addr;
aglen = be32_to_cpu(agi->agi_length);
/* some extra paranoid checks before we shrink the ag */ /* some extra paranoid checks before we shrink the ag */
if (XFS_IS_CORRUPT(mp, agf->agf_length != agi->agi_length)) if (XFS_IS_CORRUPT(mp, agf->agf_length != agi->agi_length))
return -EFSCORRUPTED; return -EFSCORRUPTED;
if (delta >= agi->agi_length) if (delta >= aglen)
return -EINVAL; return -EINVAL;
args.fsbno = XFS_AGB_TO_FSB(mp, agno, args.fsbno = XFS_AGB_TO_FSB(mp, agno, aglen - delta);
be32_to_cpu(agi->agi_length) - delta);
/* /*
* Disable perag reservations so it doesn't cause the allocation request * Disable perag reservations so it doesn't cause the allocation request
...@@ -646,7 +916,7 @@ xfs_ag_extend_space( ...@@ -646,7 +916,7 @@ xfs_ag_extend_space(
* XFS_RMAP_OINFO_SKIP_UPDATE is used here to tell the rmap btree that * XFS_RMAP_OINFO_SKIP_UPDATE is used here to tell the rmap btree that
* this doesn't actually exist in the rmap btree. * this doesn't actually exist in the rmap btree.
*/ */
error = xfs_rmap_free(tp, bp, id->agno, error = xfs_rmap_free(tp, bp, bp->b_pag,
be32_to_cpu(agf->agf_length) - len, be32_to_cpu(agf->agf_length) - len,
len, &XFS_RMAP_OINFO_SKIP_UPDATE); len, &XFS_RMAP_OINFO_SKIP_UPDATE);
if (error) if (error)
......
...@@ -9,6 +9,142 @@ ...@@ -9,6 +9,142 @@
struct xfs_mount; struct xfs_mount;
struct xfs_trans; struct xfs_trans;
struct xfs_perag;
/*
* Per-ag infrastructure
*/
/* per-AG block reservation data structures*/
struct xfs_ag_resv {
/* number of blocks originally reserved here */
xfs_extlen_t ar_orig_reserved;
/* number of blocks reserved here */
xfs_extlen_t ar_reserved;
/* number of blocks originally asked for */
xfs_extlen_t ar_asked;
};
/*
* Per-ag incore structure, copies of information in agf and agi, to improve the
* performance of allocation group selection.
*/
struct xfs_perag {
struct xfs_mount *pag_mount; /* owner filesystem */
xfs_agnumber_t pag_agno; /* AG this structure belongs to */
atomic_t pag_ref; /* perag reference count */
char pagf_init; /* this agf's entry is initialized */
char pagi_init; /* this agi's entry is initialized */
char pagf_metadata; /* the agf is preferred to be metadata */
char pagi_inodeok; /* The agi is ok for inodes */
uint8_t pagf_levels[XFS_BTNUM_AGF];
/* # of levels in bno & cnt btree */
bool pagf_agflreset; /* agfl requires reset before use */
uint32_t pagf_flcount; /* count of blocks in freelist */
xfs_extlen_t pagf_freeblks; /* total free blocks */
xfs_extlen_t pagf_longest; /* longest free space */
uint32_t pagf_btreeblks; /* # of blocks held in AGF btrees */
xfs_agino_t pagi_freecount; /* number of free inodes */
xfs_agino_t pagi_count; /* number of allocated inodes */
/*
* Inode allocation search lookup optimisation.
* If the pagino matches, the search for new inodes
* doesn't need to search the near ones again straight away
*/
xfs_agino_t pagl_pagino;
xfs_agino_t pagl_leftrec;
xfs_agino_t pagl_rightrec;
int pagb_count; /* pagb slots in use */
uint8_t pagf_refcount_level; /* recount btree height */
/* Blocks reserved for all kinds of metadata. */
struct xfs_ag_resv pag_meta_resv;
/* Blocks reserved for the reverse mapping btree. */
struct xfs_ag_resv pag_rmapbt_resv;
/* -- kernel only structures below this line -- */
/*
* Bitsets of per-ag metadata that have been checked and/or are sick.
* Callers should hold pag_state_lock before accessing this field.
*/
uint16_t pag_checked;
uint16_t pag_sick;
spinlock_t pag_state_lock;
spinlock_t pagb_lock; /* lock for pagb_tree */
struct rb_root pagb_tree; /* ordered tree of busy extents */
unsigned int pagb_gen; /* generation count for pagb_tree */
wait_queue_head_t pagb_wait; /* woken when pagb_gen changes */
atomic_t pagf_fstrms; /* # of filestreams active in this AG */
spinlock_t pag_ici_lock; /* incore inode cache lock */
struct radix_tree_root pag_ici_root; /* incore inode cache root */
int pag_ici_reclaimable; /* reclaimable inodes */
unsigned long pag_ici_reclaim_cursor; /* reclaim restart point */
/* buffer cache index */
spinlock_t pag_buf_lock; /* lock for pag_buf_hash */
struct rhashtable pag_buf_hash;
/* for rcu-safe freeing */
struct rcu_head rcu_head;
/* background prealloc block trimming */
struct delayed_work pag_blockgc_work;
/*
* Unlinked inode information. This incore information reflects
* data stored in the AGI, so callers must hold the AGI buffer lock
* or have some other means to control concurrency.
*/
struct rhashtable pagi_unlinked_hash;
};
int xfs_initialize_perag(struct xfs_mount *mp, xfs_agnumber_t agcount,
xfs_agnumber_t *maxagi);
int xfs_initialize_perag_data(struct xfs_mount *mp, xfs_agnumber_t agno);
void xfs_free_perag(struct xfs_mount *mp);
struct xfs_perag *xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno);
struct xfs_perag *xfs_perag_get_tag(struct xfs_mount *mp, xfs_agnumber_t agno,
unsigned int tag);
void xfs_perag_put(struct xfs_perag *pag);
/*
* Perag iteration APIs
*
* XXX: for_each_perag_range() usage really needs an iterator to clean up when
* we terminate at end_agno because we may have taken a reference to the perag
* beyond end_agno. Right now callers have to be careful to catch and clean that
* up themselves. This is not necessary for the callers of for_each_perag() and
* for_each_perag_from() because they terminate at sb_agcount where there are
* no perag structures in tree beyond end_agno.
*/
#define for_each_perag_range(mp, next_agno, end_agno, pag) \
for ((pag) = xfs_perag_get((mp), (next_agno)); \
(pag) != NULL && (next_agno) <= (end_agno); \
(next_agno) = (pag)->pag_agno + 1, \
xfs_perag_put(pag), \
(pag) = xfs_perag_get((mp), (next_agno)))
#define for_each_perag_from(mp, next_agno, pag) \
for_each_perag_range((mp), (next_agno), (mp)->m_sb.sb_agcount, (pag))
#define for_each_perag(mp, agno, pag) \
(agno) = 0; \
for_each_perag_from((mp), (agno), (pag))
#define for_each_perag_tag(mp, agno, pag, tag) \
for ((agno) = 0, (pag) = xfs_perag_get_tag((mp), 0, (tag)); \
(pag) != NULL; \
(agno) = (pag)->pag_agno + 1, \
xfs_perag_put(pag), \
(pag) = xfs_perag_get_tag((mp), (agno), (tag)))
struct aghdr_init_data { struct aghdr_init_data {
/* per ag data */ /* per ag data */
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#include "xfs_btree.h" #include "xfs_btree.h"
#include "xfs_refcount_btree.h" #include "xfs_refcount_btree.h"
#include "xfs_ialloc_btree.h" #include "xfs_ialloc_btree.h"
#include "xfs_sb.h" #include "xfs_ag.h"
#include "xfs_ag_resv.h" #include "xfs_ag_resv.h"
/* /*
...@@ -250,7 +250,6 @@ xfs_ag_resv_init( ...@@ -250,7 +250,6 @@ xfs_ag_resv_init(
struct xfs_trans *tp) struct xfs_trans *tp)
{ {
struct xfs_mount *mp = pag->pag_mount; struct xfs_mount *mp = pag->pag_mount;
xfs_agnumber_t agno = pag->pag_agno;
xfs_extlen_t ask; xfs_extlen_t ask;
xfs_extlen_t used; xfs_extlen_t used;
int error = 0, error2; int error = 0, error2;
...@@ -260,11 +259,11 @@ xfs_ag_resv_init( ...@@ -260,11 +259,11 @@ xfs_ag_resv_init(
if (pag->pag_meta_resv.ar_asked == 0) { if (pag->pag_meta_resv.ar_asked == 0) {
ask = used = 0; ask = used = 0;
error = xfs_refcountbt_calc_reserves(mp, tp, agno, &ask, &used); error = xfs_refcountbt_calc_reserves(mp, tp, pag, &ask, &used);
if (error) if (error)
goto out; goto out;
error = xfs_finobt_calc_reserves(mp, tp, agno, &ask, &used); error = xfs_finobt_calc_reserves(mp, tp, pag, &ask, &used);
if (error) if (error)
goto out; goto out;
...@@ -282,7 +281,7 @@ xfs_ag_resv_init( ...@@ -282,7 +281,7 @@ xfs_ag_resv_init(
mp->m_finobt_nores = true; mp->m_finobt_nores = true;
error = xfs_refcountbt_calc_reserves(mp, tp, agno, &ask, error = xfs_refcountbt_calc_reserves(mp, tp, pag, &ask,
&used); &used);
if (error) if (error)
goto out; goto out;
...@@ -300,7 +299,7 @@ xfs_ag_resv_init( ...@@ -300,7 +299,7 @@ xfs_ag_resv_init(
if (pag->pag_rmapbt_resv.ar_asked == 0) { if (pag->pag_rmapbt_resv.ar_asked == 0) {
ask = used = 0; ask = used = 0;
error = xfs_rmapbt_calc_reserves(mp, tp, agno, &ask, &used); error = xfs_rmapbt_calc_reserves(mp, tp, pag, &ask, &used);
if (error) if (error)
goto out; goto out;
......
...@@ -18,6 +18,21 @@ void xfs_ag_resv_alloc_extent(struct xfs_perag *pag, enum xfs_ag_resv_type type, ...@@ -18,6 +18,21 @@ void xfs_ag_resv_alloc_extent(struct xfs_perag *pag, enum xfs_ag_resv_type type,
void xfs_ag_resv_free_extent(struct xfs_perag *pag, enum xfs_ag_resv_type type, void xfs_ag_resv_free_extent(struct xfs_perag *pag, enum xfs_ag_resv_type type,
struct xfs_trans *tp, xfs_extlen_t len); struct xfs_trans *tp, xfs_extlen_t len);
static inline struct xfs_ag_resv *
xfs_perag_resv(
struct xfs_perag *pag,
enum xfs_ag_resv_type type)
{
switch (type) {
case XFS_AG_RESV_METADATA:
return &pag->pag_meta_resv;
case XFS_AG_RESV_RMAPBT:
return &pag->pag_rmapbt_resv;
default:
return NULL;
}
}
/* /*
* RMAPBT reservation accounting wrappers. Since rmapbt blocks are sourced from * RMAPBT reservation accounting wrappers. Since rmapbt blocks are sourced from
* the AGFL, they are allocated one at a time and the reservation updates don't * the AGFL, they are allocated one at a time and the reservation updates don't
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#include "xfs_shared.h" #include "xfs_shared.h"
#include "xfs_trans_resv.h" #include "xfs_trans_resv.h"
#include "xfs_bit.h" #include "xfs_bit.h"
#include "xfs_sb.h"
#include "xfs_mount.h" #include "xfs_mount.h"
#include "xfs_defer.h" #include "xfs_defer.h"
#include "xfs_btree.h" #include "xfs_btree.h"
...@@ -24,6 +23,7 @@ ...@@ -24,6 +23,7 @@
#include "xfs_trans.h" #include "xfs_trans.h"
#include "xfs_buf_item.h" #include "xfs_buf_item.h"
#include "xfs_log.h" #include "xfs_log.h"
#include "xfs_ag.h"
#include "xfs_ag_resv.h" #include "xfs_ag_resv.h"
#include "xfs_bmap.h" #include "xfs_bmap.h"
...@@ -230,7 +230,7 @@ xfs_alloc_get_rec( ...@@ -230,7 +230,7 @@ xfs_alloc_get_rec(
int *stat) /* output: success/failure */ int *stat) /* output: success/failure */
{ {
struct xfs_mount *mp = cur->bc_mp; struct xfs_mount *mp = cur->bc_mp;
xfs_agnumber_t agno = cur->bc_ag.agno; xfs_agnumber_t agno = cur->bc_ag.pag->pag_agno;
union xfs_btree_rec *rec; union xfs_btree_rec *rec;
int error; int error;
...@@ -776,7 +776,7 @@ xfs_alloc_cur_setup( ...@@ -776,7 +776,7 @@ xfs_alloc_cur_setup(
*/ */
if (!acur->cnt) if (!acur->cnt)
acur->cnt = xfs_allocbt_init_cursor(args->mp, args->tp, acur->cnt = xfs_allocbt_init_cursor(args->mp, args->tp,
args->agbp, args->agno, XFS_BTNUM_CNT); args->agbp, args->pag, XFS_BTNUM_CNT);
error = xfs_alloc_lookup_ge(acur->cnt, 0, args->maxlen, &i); error = xfs_alloc_lookup_ge(acur->cnt, 0, args->maxlen, &i);
if (error) if (error)
return error; return error;
...@@ -786,10 +786,10 @@ xfs_alloc_cur_setup( ...@@ -786,10 +786,10 @@ xfs_alloc_cur_setup(
*/ */
if (!acur->bnolt) if (!acur->bnolt)
acur->bnolt = xfs_allocbt_init_cursor(args->mp, args->tp, acur->bnolt = xfs_allocbt_init_cursor(args->mp, args->tp,
args->agbp, args->agno, XFS_BTNUM_BNO); args->agbp, args->pag, XFS_BTNUM_BNO);
if (!acur->bnogt) if (!acur->bnogt)
acur->bnogt = xfs_allocbt_init_cursor(args->mp, args->tp, acur->bnogt = xfs_allocbt_init_cursor(args->mp, args->tp,
args->agbp, args->agno, XFS_BTNUM_BNO); args->agbp, args->pag, XFS_BTNUM_BNO);
return i == 1 ? 0 : -ENOSPC; return i == 1 ? 0 : -ENOSPC;
} }
...@@ -1063,7 +1063,7 @@ xfs_alloc_ag_vextent_small( ...@@ -1063,7 +1063,7 @@ xfs_alloc_ag_vextent_small(
if (fbno == NULLAGBLOCK) if (fbno == NULLAGBLOCK)
goto out; goto out;
xfs_extent_busy_reuse(args->mp, args->agno, fbno, 1, xfs_extent_busy_reuse(args->mp, args->pag, fbno, 1,
(args->datatype & XFS_ALLOC_NOBUSY)); (args->datatype & XFS_ALLOC_NOBUSY));
if (args->datatype & XFS_ALLOC_USERDATA) { if (args->datatype & XFS_ALLOC_USERDATA) {
...@@ -1089,7 +1089,7 @@ xfs_alloc_ag_vextent_small( ...@@ -1089,7 +1089,7 @@ xfs_alloc_ag_vextent_small(
* If we're feeding an AGFL block to something that doesn't live in the * If we're feeding an AGFL block to something that doesn't live in the
* free space, we need to clear out the OWN_AG rmap. * free space, we need to clear out the OWN_AG rmap.
*/ */
error = xfs_rmap_free(args->tp, args->agbp, args->agno, fbno, 1, error = xfs_rmap_free(args->tp, args->agbp, args->pag, fbno, 1,
&XFS_RMAP_OINFO_AG); &XFS_RMAP_OINFO_AG);
if (error) if (error)
goto error; goto error;
...@@ -1166,7 +1166,7 @@ xfs_alloc_ag_vextent( ...@@ -1166,7 +1166,7 @@ xfs_alloc_ag_vextent(
/* if not file data, insert new block into the reverse map btree */ /* if not file data, insert new block into the reverse map btree */
if (!xfs_rmap_should_skip_owner_update(&args->oinfo)) { if (!xfs_rmap_should_skip_owner_update(&args->oinfo)) {
error = xfs_rmap_alloc(args->tp, args->agbp, args->agno, error = xfs_rmap_alloc(args->tp, args->agbp, args->pag,
args->agbno, args->len, &args->oinfo); args->agbno, args->len, &args->oinfo);
if (error) if (error)
return error; return error;
...@@ -1178,7 +1178,7 @@ xfs_alloc_ag_vextent( ...@@ -1178,7 +1178,7 @@ xfs_alloc_ag_vextent(
if (error) if (error)
return error; return error;
ASSERT(!xfs_extent_busy_search(args->mp, args->agno, ASSERT(!xfs_extent_busy_search(args->mp, args->pag,
args->agbno, args->len)); args->agbno, args->len));
} }
...@@ -1217,7 +1217,7 @@ xfs_alloc_ag_vextent_exact( ...@@ -1217,7 +1217,7 @@ xfs_alloc_ag_vextent_exact(
* Allocate/initialize a cursor for the by-number freespace btree. * Allocate/initialize a cursor for the by-number freespace btree.
*/ */
bno_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, bno_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp,
args->agno, XFS_BTNUM_BNO); args->pag, XFS_BTNUM_BNO);
/* /*
* Lookup bno and minlen in the btree (minlen is irrelevant, really). * Lookup bno and minlen in the btree (minlen is irrelevant, really).
...@@ -1277,7 +1277,7 @@ xfs_alloc_ag_vextent_exact( ...@@ -1277,7 +1277,7 @@ xfs_alloc_ag_vextent_exact(
* Allocate/initialize a cursor for the by-size btree. * Allocate/initialize a cursor for the by-size btree.
*/ */
cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp,
args->agno, XFS_BTNUM_CNT); args->pag, XFS_BTNUM_CNT);
ASSERT(args->agbno + args->len <= be32_to_cpu(agf->agf_length)); ASSERT(args->agbno + args->len <= be32_to_cpu(agf->agf_length));
error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen, args->agbno, error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen, args->agbno,
args->len, XFSA_FIXUP_BNO_OK); args->len, XFSA_FIXUP_BNO_OK);
...@@ -1674,9 +1674,8 @@ xfs_alloc_ag_vextent_size( ...@@ -1674,9 +1674,8 @@ xfs_alloc_ag_vextent_size(
* Allocate and initialize a cursor for the by-size btree. * Allocate and initialize a cursor for the by-size btree.
*/ */
cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp,
args->agno, XFS_BTNUM_CNT); args->pag, XFS_BTNUM_CNT);
bno_cur = NULL; bno_cur = NULL;
busy = false;
/* /*
* Look for an entry >= maxlen+alignment-1 blocks. * Look for an entry >= maxlen+alignment-1 blocks.
...@@ -1837,7 +1836,7 @@ xfs_alloc_ag_vextent_size( ...@@ -1837,7 +1836,7 @@ xfs_alloc_ag_vextent_size(
* Allocate and initialize a cursor for the by-block tree. * Allocate and initialize a cursor for the by-block tree.
*/ */
bno_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, bno_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp,
args->agno, XFS_BTNUM_BNO); args->pag, XFS_BTNUM_BNO);
if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen, if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen,
rbno, rlen, XFSA_FIXUP_CNT_OK))) rbno, rlen, XFSA_FIXUP_CNT_OK)))
goto error0; goto error0;
...@@ -1896,12 +1895,13 @@ xfs_free_ag_extent( ...@@ -1896,12 +1895,13 @@ xfs_free_ag_extent(
int haveright; /* have a right neighbor */ int haveright; /* have a right neighbor */
int i; int i;
int error; int error;
struct xfs_perag *pag = agbp->b_pag;
bno_cur = cnt_cur = NULL; bno_cur = cnt_cur = NULL;
mp = tp->t_mountp; mp = tp->t_mountp;
if (!xfs_rmap_should_skip_owner_update(oinfo)) { if (!xfs_rmap_should_skip_owner_update(oinfo)) {
error = xfs_rmap_free(tp, agbp, agno, bno, len, oinfo); error = xfs_rmap_free(tp, agbp, pag, bno, len, oinfo);
if (error) if (error)
goto error0; goto error0;
} }
...@@ -1909,7 +1909,7 @@ xfs_free_ag_extent( ...@@ -1909,7 +1909,7 @@ xfs_free_ag_extent(
/* /*
* Allocate and initialize a cursor for the by-block btree. * Allocate and initialize a cursor for the by-block btree.
*/ */
bno_cur = xfs_allocbt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_BNO); bno_cur = xfs_allocbt_init_cursor(mp, tp, agbp, pag, XFS_BTNUM_BNO);
/* /*
* Look for a neighboring block on the left (lower block numbers) * Look for a neighboring block on the left (lower block numbers)
* that is contiguous with this space. * that is contiguous with this space.
...@@ -1979,7 +1979,7 @@ xfs_free_ag_extent( ...@@ -1979,7 +1979,7 @@ xfs_free_ag_extent(
/* /*
* Now allocate and initialize a cursor for the by-size tree. * Now allocate and initialize a cursor for the by-size tree.
*/ */
cnt_cur = xfs_allocbt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_CNT); cnt_cur = xfs_allocbt_init_cursor(mp, tp, agbp, pag, XFS_BTNUM_CNT);
/* /*
* Have both left and right contiguous neighbors. * Have both left and right contiguous neighbors.
* Merge all three into a single free block. * Merge all three into a single free block.
...@@ -2490,7 +2490,7 @@ xfs_exact_minlen_extent_available( ...@@ -2490,7 +2490,7 @@ xfs_exact_minlen_extent_available(
int error = 0; int error = 0;
cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, agbp, cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, agbp,
args->agno, XFS_BTNUM_CNT); args->pag, XFS_BTNUM_CNT);
error = xfs_alloc_lookup_ge(cnt_cur, 0, args->minlen, stat); error = xfs_alloc_lookup_ge(cnt_cur, 0, args->minlen, stat);
if (error) if (error)
goto out; goto out;
...@@ -2693,21 +2693,21 @@ xfs_alloc_fix_freelist( ...@@ -2693,21 +2693,21 @@ xfs_alloc_fix_freelist(
* Get a block from the freelist. * Get a block from the freelist.
* Returns with the buffer for the block gotten. * Returns with the buffer for the block gotten.
*/ */
int /* error */ int
xfs_alloc_get_freelist( xfs_alloc_get_freelist(
xfs_trans_t *tp, /* transaction pointer */ struct xfs_trans *tp,
struct xfs_buf *agbp, /* buffer containing the agf structure */ struct xfs_buf *agbp,
xfs_agblock_t *bnop, /* block address retrieved from freelist */ xfs_agblock_t *bnop,
int btreeblk) /* destination is a AGF btree */ int btreeblk)
{ {
struct xfs_agf *agf = agbp->b_addr; struct xfs_agf *agf = agbp->b_addr;
struct xfs_buf *agflbp;/* buffer for a.g. freelist structure */ struct xfs_buf *agflbp;
xfs_agblock_t bno; /* block number returned */ xfs_agblock_t bno;
__be32 *agfl_bno; __be32 *agfl_bno;
int error; int error;
int logflags; int logflags;
xfs_mount_t *mp = tp->t_mountp; struct xfs_mount *mp = tp->t_mountp;
xfs_perag_t *pag; /* per allocation group data */ struct xfs_perag *pag;
/* /*
* Freelist is empty, give up. * Freelist is empty, give up.
...@@ -2817,20 +2817,20 @@ xfs_alloc_pagf_init( ...@@ -2817,20 +2817,20 @@ xfs_alloc_pagf_init(
/* /*
* Put the block on the freelist for the allocation group. * Put the block on the freelist for the allocation group.
*/ */
int /* error */ int
xfs_alloc_put_freelist( xfs_alloc_put_freelist(
xfs_trans_t *tp, /* transaction pointer */ struct xfs_trans *tp,
struct xfs_buf *agbp, /* buffer for a.g. freelist header */ struct xfs_buf *agbp,
struct xfs_buf *agflbp,/* buffer for a.g. free block array */ struct xfs_buf *agflbp,
xfs_agblock_t bno, /* block being freed */ xfs_agblock_t bno,
int btreeblk) /* block came from a AGF btree */ int btreeblk)
{ {
struct xfs_mount *mp = tp->t_mountp; struct xfs_mount *mp = tp->t_mountp;
struct xfs_agf *agf = agbp->b_addr; struct xfs_agf *agf = agbp->b_addr;
__be32 *blockp;/* pointer to array entry */ struct xfs_perag *pag;
__be32 *blockp;
int error; int error;
int logflags; int logflags;
xfs_perag_t *pag; /* per allocation group data */
__be32 *agfl_bno; __be32 *agfl_bno;
int startoff; int startoff;
...@@ -3292,7 +3292,7 @@ xfs_alloc_vextent( ...@@ -3292,7 +3292,7 @@ xfs_alloc_vextent(
int int
xfs_free_extent_fix_freelist( xfs_free_extent_fix_freelist(
struct xfs_trans *tp, struct xfs_trans *tp,
xfs_agnumber_t agno, struct xfs_perag *pag,
struct xfs_buf **agbp) struct xfs_buf **agbp)
{ {
struct xfs_alloc_arg args; struct xfs_alloc_arg args;
...@@ -3301,7 +3301,8 @@ xfs_free_extent_fix_freelist( ...@@ -3301,7 +3301,8 @@ xfs_free_extent_fix_freelist(
memset(&args, 0, sizeof(struct xfs_alloc_arg)); memset(&args, 0, sizeof(struct xfs_alloc_arg));
args.tp = tp; args.tp = tp;
args.mp = tp->t_mountp; args.mp = tp->t_mountp;
args.agno = agno; args.agno = pag->pag_agno;
args.pag = pag;
/* /*
* validate that the block number is legal - the enables us to detect * validate that the block number is legal - the enables us to detect
...@@ -3310,17 +3311,12 @@ xfs_free_extent_fix_freelist( ...@@ -3310,17 +3311,12 @@ xfs_free_extent_fix_freelist(
if (args.agno >= args.mp->m_sb.sb_agcount) if (args.agno >= args.mp->m_sb.sb_agcount)
return -EFSCORRUPTED; return -EFSCORRUPTED;
args.pag = xfs_perag_get(args.mp, args.agno);
ASSERT(args.pag);
error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING); error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING);
if (error) if (error)
goto out; return error;
*agbp = args.agbp; *agbp = args.agbp;
out: return 0;
xfs_perag_put(args.pag);
return error;
} }
/* /*
...@@ -3344,6 +3340,7 @@ __xfs_free_extent( ...@@ -3344,6 +3340,7 @@ __xfs_free_extent(
struct xfs_agf *agf; struct xfs_agf *agf;
int error; int error;
unsigned int busy_flags = 0; unsigned int busy_flags = 0;
struct xfs_perag *pag;
ASSERT(len != 0); ASSERT(len != 0);
ASSERT(type != XFS_AG_RESV_AGFL); ASSERT(type != XFS_AG_RESV_AGFL);
...@@ -3352,33 +3349,37 @@ __xfs_free_extent( ...@@ -3352,33 +3349,37 @@ __xfs_free_extent(
XFS_ERRTAG_FREE_EXTENT)) XFS_ERRTAG_FREE_EXTENT))
return -EIO; return -EIO;
error = xfs_free_extent_fix_freelist(tp, agno, &agbp); pag = xfs_perag_get(mp, agno);
error = xfs_free_extent_fix_freelist(tp, pag, &agbp);
if (error) if (error)
return error; goto err;
agf = agbp->b_addr; agf = agbp->b_addr;
if (XFS_IS_CORRUPT(mp, agbno >= mp->m_sb.sb_agblocks)) { if (XFS_IS_CORRUPT(mp, agbno >= mp->m_sb.sb_agblocks)) {
error = -EFSCORRUPTED; error = -EFSCORRUPTED;
goto err; goto err_release;
} }
/* validate the extent size is legal now we have the agf locked */ /* validate the extent size is legal now we have the agf locked */
if (XFS_IS_CORRUPT(mp, agbno + len > be32_to_cpu(agf->agf_length))) { if (XFS_IS_CORRUPT(mp, agbno + len > be32_to_cpu(agf->agf_length))) {
error = -EFSCORRUPTED; error = -EFSCORRUPTED;
goto err; goto err_release;
} }
error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, oinfo, type); error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, oinfo, type);
if (error) if (error)
goto err; goto err_release;
if (skip_discard) if (skip_discard)
busy_flags |= XFS_EXTENT_BUSY_SKIP_DISCARD; busy_flags |= XFS_EXTENT_BUSY_SKIP_DISCARD;
xfs_extent_busy_insert(tp, agno, agbno, len, busy_flags); xfs_extent_busy_insert(tp, pag, agbno, len, busy_flags);
xfs_perag_put(pag);
return 0; return 0;
err: err_release:
xfs_trans_brelse(tp, agbp); xfs_trans_brelse(tp, agbp);
err:
xfs_perag_put(pag);
return error; return error;
} }
......
...@@ -214,7 +214,7 @@ int xfs_alloc_read_agfl(struct xfs_mount *mp, struct xfs_trans *tp, ...@@ -214,7 +214,7 @@ int xfs_alloc_read_agfl(struct xfs_mount *mp, struct xfs_trans *tp,
int xfs_free_agfl_block(struct xfs_trans *, xfs_agnumber_t, xfs_agblock_t, int xfs_free_agfl_block(struct xfs_trans *, xfs_agnumber_t, xfs_agblock_t,
struct xfs_buf *, struct xfs_owner_info *); struct xfs_buf *, struct xfs_owner_info *);
int xfs_alloc_fix_freelist(struct xfs_alloc_arg *args, int flags); int xfs_alloc_fix_freelist(struct xfs_alloc_arg *args, int flags);
int xfs_free_extent_fix_freelist(struct xfs_trans *tp, xfs_agnumber_t agno, int xfs_free_extent_fix_freelist(struct xfs_trans *tp, struct xfs_perag *pag,
struct xfs_buf **agbp); struct xfs_buf **agbp);
xfs_extlen_t xfs_prealloc_blocks(struct xfs_mount *mp); xfs_extlen_t xfs_prealloc_blocks(struct xfs_mount *mp);
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include "xfs_format.h" #include "xfs_format.h"
#include "xfs_log_format.h" #include "xfs_log_format.h"
#include "xfs_trans_resv.h" #include "xfs_trans_resv.h"
#include "xfs_sb.h"
#include "xfs_mount.h" #include "xfs_mount.h"
#include "xfs_btree.h" #include "xfs_btree.h"
#include "xfs_btree_staging.h" #include "xfs_btree_staging.h"
...@@ -19,6 +18,7 @@ ...@@ -19,6 +18,7 @@
#include "xfs_error.h" #include "xfs_error.h"
#include "xfs_trace.h" #include "xfs_trace.h"
#include "xfs_trans.h" #include "xfs_trans.h"
#include "xfs_ag.h"
STATIC struct xfs_btree_cur * STATIC struct xfs_btree_cur *
...@@ -26,8 +26,7 @@ xfs_allocbt_dup_cursor( ...@@ -26,8 +26,7 @@ xfs_allocbt_dup_cursor(
struct xfs_btree_cur *cur) struct xfs_btree_cur *cur)
{ {
return xfs_allocbt_init_cursor(cur->bc_mp, cur->bc_tp, return xfs_allocbt_init_cursor(cur->bc_mp, cur->bc_tp,
cur->bc_ag.agbp, cur->bc_ag.agno, cur->bc_ag.agbp, cur->bc_ag.pag, cur->bc_btnum);
cur->bc_btnum);
} }
STATIC void STATIC void
...@@ -39,13 +38,12 @@ xfs_allocbt_set_root( ...@@ -39,13 +38,12 @@ xfs_allocbt_set_root(
struct xfs_buf *agbp = cur->bc_ag.agbp; struct xfs_buf *agbp = cur->bc_ag.agbp;
struct xfs_agf *agf = agbp->b_addr; struct xfs_agf *agf = agbp->b_addr;
int btnum = cur->bc_btnum; int btnum = cur->bc_btnum;
struct xfs_perag *pag = agbp->b_pag;
ASSERT(ptr->s != 0); ASSERT(ptr->s != 0);
agf->agf_roots[btnum] = ptr->s; agf->agf_roots[btnum] = ptr->s;
be32_add_cpu(&agf->agf_levels[btnum], inc); be32_add_cpu(&agf->agf_levels[btnum], inc);
pag->pagf_levels[btnum] += inc; cur->bc_ag.pag->pagf_levels[btnum] += inc;
xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS); xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS);
} }
...@@ -72,7 +70,7 @@ xfs_allocbt_alloc_block( ...@@ -72,7 +70,7 @@ xfs_allocbt_alloc_block(
} }
atomic64_inc(&cur->bc_mp->m_allocbt_blks); atomic64_inc(&cur->bc_mp->m_allocbt_blks);
xfs_extent_busy_reuse(cur->bc_mp, cur->bc_ag.agno, bno, 1, false); xfs_extent_busy_reuse(cur->bc_mp, cur->bc_ag.agbp->b_pag, bno, 1, false);
new->s = cpu_to_be32(bno); new->s = cpu_to_be32(bno);
...@@ -86,7 +84,6 @@ xfs_allocbt_free_block( ...@@ -86,7 +84,6 @@ xfs_allocbt_free_block(
struct xfs_buf *bp) struct xfs_buf *bp)
{ {
struct xfs_buf *agbp = cur->bc_ag.agbp; struct xfs_buf *agbp = cur->bc_ag.agbp;
struct xfs_agf *agf = agbp->b_addr;
xfs_agblock_t bno; xfs_agblock_t bno;
int error; int error;
...@@ -96,7 +93,7 @@ xfs_allocbt_free_block( ...@@ -96,7 +93,7 @@ xfs_allocbt_free_block(
return error; return error;
atomic64_dec(&cur->bc_mp->m_allocbt_blks); atomic64_dec(&cur->bc_mp->m_allocbt_blks);
xfs_extent_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1, xfs_extent_busy_insert(cur->bc_tp, agbp->b_pag, bno, 1,
XFS_EXTENT_BUSY_SKIP_DISCARD); XFS_EXTENT_BUSY_SKIP_DISCARD);
return 0; return 0;
} }
...@@ -225,7 +222,7 @@ xfs_allocbt_init_ptr_from_cur( ...@@ -225,7 +222,7 @@ xfs_allocbt_init_ptr_from_cur(
{ {
struct xfs_agf *agf = cur->bc_ag.agbp->b_addr; struct xfs_agf *agf = cur->bc_ag.agbp->b_addr;
ASSERT(cur->bc_ag.agno == be32_to_cpu(agf->agf_seqno)); ASSERT(cur->bc_ag.pag->pag_agno == be32_to_cpu(agf->agf_seqno));
ptr->s = agf->agf_roots[cur->bc_btnum]; ptr->s = agf->agf_roots[cur->bc_btnum];
} }
...@@ -473,7 +470,7 @@ STATIC struct xfs_btree_cur * ...@@ -473,7 +470,7 @@ STATIC struct xfs_btree_cur *
xfs_allocbt_init_common( xfs_allocbt_init_common(
struct xfs_mount *mp, struct xfs_mount *mp,
struct xfs_trans *tp, struct xfs_trans *tp,
xfs_agnumber_t agno, struct xfs_perag *pag,
xfs_btnum_t btnum) xfs_btnum_t btnum)
{ {
struct xfs_btree_cur *cur; struct xfs_btree_cur *cur;
...@@ -486,6 +483,7 @@ xfs_allocbt_init_common( ...@@ -486,6 +483,7 @@ xfs_allocbt_init_common(
cur->bc_mp = mp; cur->bc_mp = mp;
cur->bc_btnum = btnum; cur->bc_btnum = btnum;
cur->bc_blocklog = mp->m_sb.sb_blocklog; cur->bc_blocklog = mp->m_sb.sb_blocklog;
cur->bc_ag.abt.active = false;
if (btnum == XFS_BTNUM_CNT) { if (btnum == XFS_BTNUM_CNT) {
cur->bc_ops = &xfs_cntbt_ops; cur->bc_ops = &xfs_cntbt_ops;
...@@ -496,8 +494,9 @@ xfs_allocbt_init_common( ...@@ -496,8 +494,9 @@ xfs_allocbt_init_common(
cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_abtb_2); cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_abtb_2);
} }
cur->bc_ag.agno = agno; /* take a reference for the cursor */
cur->bc_ag.abt.active = false; atomic_inc(&pag->pag_ref);
cur->bc_ag.pag = pag;
if (xfs_sb_version_hascrc(&mp->m_sb)) if (xfs_sb_version_hascrc(&mp->m_sb))
cur->bc_flags |= XFS_BTREE_CRC_BLOCKS; cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
...@@ -513,13 +512,13 @@ xfs_allocbt_init_cursor( ...@@ -513,13 +512,13 @@ xfs_allocbt_init_cursor(
struct xfs_mount *mp, /* file system mount point */ struct xfs_mount *mp, /* file system mount point */
struct xfs_trans *tp, /* transaction pointer */ struct xfs_trans *tp, /* transaction pointer */
struct xfs_buf *agbp, /* buffer for agf structure */ struct xfs_buf *agbp, /* buffer for agf structure */
xfs_agnumber_t agno, /* allocation group number */ struct xfs_perag *pag,
xfs_btnum_t btnum) /* btree identifier */ xfs_btnum_t btnum) /* btree identifier */
{ {
struct xfs_agf *agf = agbp->b_addr; struct xfs_agf *agf = agbp->b_addr;
struct xfs_btree_cur *cur; struct xfs_btree_cur *cur;
cur = xfs_allocbt_init_common(mp, tp, agno, btnum); cur = xfs_allocbt_init_common(mp, tp, pag, btnum);
if (btnum == XFS_BTNUM_CNT) if (btnum == XFS_BTNUM_CNT)
cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]); cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]);
else else
...@@ -535,12 +534,12 @@ struct xfs_btree_cur * ...@@ -535,12 +534,12 @@ struct xfs_btree_cur *
xfs_allocbt_stage_cursor( xfs_allocbt_stage_cursor(
struct xfs_mount *mp, struct xfs_mount *mp,
struct xbtree_afakeroot *afake, struct xbtree_afakeroot *afake,
xfs_agnumber_t agno, struct xfs_perag *pag,
xfs_btnum_t btnum) xfs_btnum_t btnum)
{ {
struct xfs_btree_cur *cur; struct xfs_btree_cur *cur;
cur = xfs_allocbt_init_common(mp, NULL, agno, btnum); cur = xfs_allocbt_init_common(mp, NULL, pag, btnum);
xfs_btree_stage_afakeroot(cur, afake); xfs_btree_stage_afakeroot(cur, afake);
return cur; return cur;
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
struct xfs_buf; struct xfs_buf;
struct xfs_btree_cur; struct xfs_btree_cur;
struct xfs_mount; struct xfs_mount;
struct xfs_perag;
struct xbtree_afakeroot; struct xbtree_afakeroot;
/* /*
...@@ -46,11 +47,11 @@ struct xbtree_afakeroot; ...@@ -46,11 +47,11 @@ struct xbtree_afakeroot;
(maxrecs) * sizeof(xfs_alloc_key_t) + \ (maxrecs) * sizeof(xfs_alloc_key_t) + \
((index) - 1) * sizeof(xfs_alloc_ptr_t))) ((index) - 1) * sizeof(xfs_alloc_ptr_t)))
extern struct xfs_btree_cur *xfs_allocbt_init_cursor(struct xfs_mount *, extern struct xfs_btree_cur *xfs_allocbt_init_cursor(struct xfs_mount *mp,
struct xfs_trans *, struct xfs_buf *, struct xfs_trans *tp, struct xfs_buf *bp,
xfs_agnumber_t, xfs_btnum_t); struct xfs_perag *pag, xfs_btnum_t btnum);
struct xfs_btree_cur *xfs_allocbt_stage_cursor(struct xfs_mount *mp, struct xfs_btree_cur *xfs_allocbt_stage_cursor(struct xfs_mount *mp,
struct xbtree_afakeroot *afake, xfs_agnumber_t agno, struct xbtree_afakeroot *afake, struct xfs_perag *pag,
xfs_btnum_t btnum); xfs_btnum_t btnum);
extern int xfs_allocbt_maxrecs(struct xfs_mount *, int, int); extern int xfs_allocbt_maxrecs(struct xfs_mount *, int, int);
extern xfs_extlen_t xfs_allocbt_calc_size(struct xfs_mount *mp, extern xfs_extlen_t xfs_allocbt_calc_size(struct xfs_mount *mp,
......
This diff is collapsed.
This diff is collapsed.
...@@ -19,14 +19,15 @@ ...@@ -19,14 +19,15 @@
#include "xfs_bmap_btree.h" #include "xfs_bmap_btree.h"
#include "xfs_bmap.h" #include "xfs_bmap.h"
#include "xfs_attr_sf.h" #include "xfs_attr_sf.h"
#include "xfs_attr_remote.h"
#include "xfs_attr.h" #include "xfs_attr.h"
#include "xfs_attr_remote.h"
#include "xfs_attr_leaf.h" #include "xfs_attr_leaf.h"
#include "xfs_error.h" #include "xfs_error.h"
#include "xfs_trace.h" #include "xfs_trace.h"
#include "xfs_buf_item.h" #include "xfs_buf_item.h"
#include "xfs_dir2.h" #include "xfs_dir2.h"
#include "xfs_log.h" #include "xfs_log.h"
#include "xfs_ag.h"
/* /*
...@@ -773,7 +774,7 @@ xfs_attr_fork_remove( ...@@ -773,7 +774,7 @@ xfs_attr_fork_remove(
* Remove an attribute from the shortform attribute list structure. * Remove an attribute from the shortform attribute list structure.
*/ */
int int
xfs_attr_shortform_remove( xfs_attr_sf_removename(
struct xfs_da_args *args) struct xfs_da_args *args)
{ {
struct xfs_attr_shortform *sf; struct xfs_attr_shortform *sf;
......
...@@ -51,7 +51,7 @@ int xfs_attr_shortform_lookup(struct xfs_da_args *args); ...@@ -51,7 +51,7 @@ int xfs_attr_shortform_lookup(struct xfs_da_args *args);
int xfs_attr_shortform_getvalue(struct xfs_da_args *args); int xfs_attr_shortform_getvalue(struct xfs_da_args *args);
int xfs_attr_shortform_to_leaf(struct xfs_da_args *args, int xfs_attr_shortform_to_leaf(struct xfs_da_args *args,
struct xfs_buf **leaf_bp); struct xfs_buf **leaf_bp);
int xfs_attr_shortform_remove(struct xfs_da_args *args); int xfs_attr_sf_removename(struct xfs_da_args *args);
int xfs_attr_sf_findname(struct xfs_da_args *args, int xfs_attr_sf_findname(struct xfs_da_args *args,
struct xfs_attr_sf_entry **sfep, struct xfs_attr_sf_entry **sfep,
unsigned int *basep); unsigned int *basep);
......
...@@ -439,9 +439,9 @@ xfs_attr_rmtval_get( ...@@ -439,9 +439,9 @@ xfs_attr_rmtval_get(
/* /*
* Find a "hole" in the attribute address space large enough for us to drop the * Find a "hole" in the attribute address space large enough for us to drop the
* new attribute's value into * new attributes value into
*/ */
STATIC int int
xfs_attr_rmt_find_hole( xfs_attr_rmt_find_hole(
struct xfs_da_args *args) struct xfs_da_args *args)
{ {
...@@ -468,7 +468,7 @@ xfs_attr_rmt_find_hole( ...@@ -468,7 +468,7 @@ xfs_attr_rmt_find_hole(
return 0; return 0;
} }
STATIC int int
xfs_attr_rmtval_set_value( xfs_attr_rmtval_set_value(
struct xfs_da_args *args) struct xfs_da_args *args)
{ {
...@@ -562,69 +562,66 @@ xfs_attr_rmtval_stale( ...@@ -562,69 +562,66 @@ xfs_attr_rmtval_stale(
} }
/* /*
* Write the value associated with an attribute into the out-of-line buffer * Find a hole for the attr and store it in the delayed attr context. This
* that we have defined for it. * initializes the context to roll through allocating an attr extent for a
* delayed attr operation
*/ */
int int
xfs_attr_rmtval_set( xfs_attr_rmtval_find_space(
struct xfs_da_args *args) struct xfs_delattr_context *dac)
{ {
struct xfs_inode *dp = args->dp; struct xfs_da_args *args = dac->da_args;
struct xfs_bmbt_irec map; struct xfs_bmbt_irec *map = &dac->map;
xfs_dablk_t lblkno; int error;
int blkcnt;
int nmap;
int error;
trace_xfs_attr_rmtval_set(args); dac->lblkno = 0;
dac->blkcnt = 0;
args->rmtblkcnt = 0;
args->rmtblkno = 0;
memset(map, 0, sizeof(struct xfs_bmbt_irec));
error = xfs_attr_rmt_find_hole(args); error = xfs_attr_rmt_find_hole(args);
if (error) if (error)
return error; return error;
blkcnt = args->rmtblkcnt; dac->blkcnt = args->rmtblkcnt;
lblkno = (xfs_dablk_t)args->rmtblkno; dac->lblkno = args->rmtblkno;
/*
* Roll through the "value", allocating blocks on disk as required.
*/
while (blkcnt > 0) {
/*
* Allocate a single extent, up to the size of the value.
*
* Note that we have to consider this a data allocation as we
* write the remote attribute without logging the contents.
* Hence we must ensure that we aren't using blocks that are on
* the busy list so that we don't overwrite blocks which have
* recently been freed but their transactions are not yet
* committed to disk. If we overwrite the contents of a busy
* extent and then crash then the block may not contain the
* correct metadata after log recovery occurs.
*/
nmap = 1;
error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno,
blkcnt, XFS_BMAPI_ATTRFORK, args->total, &map,
&nmap);
if (error)
return error;
error = xfs_defer_finish(&args->trans);
if (error)
return error;
ASSERT(nmap == 1); return 0;
ASSERT((map.br_startblock != DELAYSTARTBLOCK) && }
(map.br_startblock != HOLESTARTBLOCK));
lblkno += map.br_blockcount;
blkcnt -= map.br_blockcount;
/* /*
* Start the next trans in the chain. * Write one block of the value associated with an attribute into the
*/ * out-of-line buffer that we have defined for it. This is similar to a subset
error = xfs_trans_roll_inode(&args->trans, dp); * of xfs_attr_rmtval_set, but records the current block to the delayed attr
if (error) * context, and leaves transaction handling to the caller.
return error; */
} int
xfs_attr_rmtval_set_blk(
struct xfs_delattr_context *dac)
{
struct xfs_da_args *args = dac->da_args;
struct xfs_inode *dp = args->dp;
struct xfs_bmbt_irec *map = &dac->map;
int nmap;
int error;
nmap = 1;
error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)dac->lblkno,
dac->blkcnt, XFS_BMAPI_ATTRFORK, args->total,
map, &nmap);
if (error)
return error;
ASSERT(nmap == 1);
ASSERT((map->br_startblock != DELAYSTARTBLOCK) &&
(map->br_startblock != HOLESTARTBLOCK));
return xfs_attr_rmtval_set_value(args); /* roll attribute extent map forwards */
dac->lblkno += map->br_blockcount;
dac->blkcnt -= map->br_blockcount;
return 0;
} }
/* /*
...@@ -668,48 +665,18 @@ xfs_attr_rmtval_invalidate( ...@@ -668,48 +665,18 @@ xfs_attr_rmtval_invalidate(
return 0; return 0;
} }
/*
* Remove the value associated with an attribute by deleting the
* out-of-line buffer that it is stored on.
*/
int
xfs_attr_rmtval_remove(
struct xfs_da_args *args)
{
int error;
int retval;
trace_xfs_attr_rmtval_remove(args);
/*
* Keep de-allocating extents until the remote-value region is gone.
*/
do {
retval = __xfs_attr_rmtval_remove(args);
if (retval && retval != -EAGAIN)
return retval;
/*
* Close out trans and start the next one in the chain.
*/
error = xfs_trans_roll_inode(&args->trans, args->dp);
if (error)
return error;
} while (retval == -EAGAIN);
return 0;
}
/* /*
* Remove the value associated with an attribute by deleting the out-of-line * Remove the value associated with an attribute by deleting the out-of-line
* buffer that it is stored on. Returns EAGAIN for the caller to refresh the * buffer that it is stored on. Returns -EAGAIN for the caller to refresh the
* transaction and re-call the function * transaction and re-call the function. Callers should keep calling this
* routine until it returns something other than -EAGAIN.
*/ */
int int
__xfs_attr_rmtval_remove( __xfs_attr_rmtval_remove(
struct xfs_da_args *args) struct xfs_delattr_context *dac)
{ {
int error, done; struct xfs_da_args *args = dac->da_args;
int error, done;
/* /*
* Unmap value blocks for this attr. * Unmap value blocks for this attr.
...@@ -719,12 +686,20 @@ __xfs_attr_rmtval_remove( ...@@ -719,12 +686,20 @@ __xfs_attr_rmtval_remove(
if (error) if (error)
return error; return error;
error = xfs_defer_finish(&args->trans); /*
if (error) * We don't need an explicit state here to pick up where we left off. We
return error; * can figure it out using the !done return code. The actual value of
* attr->xattri_dela_state may be some value reminiscent of the calling
if (!done) * function, but it's value is irrelevant with in the context of this
* function. Once we are done here, the next state is set as needed by
* the parent
*/
if (!done) {
dac->flags |= XFS_DAC_DEFER_FINISH;
return -EAGAIN; return -EAGAIN;
}
return error; args->rmtblkno = 0;
args->rmtblkcnt = 0;
return 0;
} }
...@@ -9,10 +9,12 @@ ...@@ -9,10 +9,12 @@
int xfs_attr3_rmt_blocks(struct xfs_mount *mp, int attrlen); int xfs_attr3_rmt_blocks(struct xfs_mount *mp, int attrlen);
int xfs_attr_rmtval_get(struct xfs_da_args *args); int xfs_attr_rmtval_get(struct xfs_da_args *args);
int xfs_attr_rmtval_set(struct xfs_da_args *args);
int xfs_attr_rmtval_remove(struct xfs_da_args *args);
int xfs_attr_rmtval_stale(struct xfs_inode *ip, struct xfs_bmbt_irec *map, int xfs_attr_rmtval_stale(struct xfs_inode *ip, struct xfs_bmbt_irec *map,
xfs_buf_flags_t incore_flags); xfs_buf_flags_t incore_flags);
int xfs_attr_rmtval_invalidate(struct xfs_da_args *args); int xfs_attr_rmtval_invalidate(struct xfs_da_args *args);
int __xfs_attr_rmtval_remove(struct xfs_da_args *args); int __xfs_attr_rmtval_remove(struct xfs_delattr_context *dac);
int xfs_attr_rmt_find_hole(struct xfs_da_args *args);
int xfs_attr_rmtval_set_value(struct xfs_da_args *args);
int xfs_attr_rmtval_set_blk(struct xfs_delattr_context *dac);
int xfs_attr_rmtval_find_space(struct xfs_delattr_context *dac);
#endif /* __XFS_ATTR_REMOTE_H__ */ #endif /* __XFS_ATTR_REMOTE_H__ */
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "xfs_attr_leaf.h" #include "xfs_attr_leaf.h"
#include "xfs_filestream.h" #include "xfs_filestream.h"
#include "xfs_rmap.h" #include "xfs_rmap.h"
#include "xfs_ag.h"
#include "xfs_ag_resv.h" #include "xfs_ag_resv.h"
#include "xfs_refcount.h" #include "xfs_refcount.h"
#include "xfs_icache.h" #include "xfs_icache.h"
...@@ -1028,7 +1029,7 @@ xfs_bmap_add_attrfork_local( ...@@ -1028,7 +1029,7 @@ xfs_bmap_add_attrfork_local(
/* /*
* Set an inode attr fork offset based on the format of the data fork. * Set an inode attr fork offset based on the format of the data fork.
*/ */
int static int
xfs_bmap_set_attrforkoff( xfs_bmap_set_attrforkoff(
struct xfs_inode *ip, struct xfs_inode *ip,
int size, int size,
......
...@@ -187,7 +187,6 @@ void xfs_trim_extent(struct xfs_bmbt_irec *irec, xfs_fileoff_t bno, ...@@ -187,7 +187,6 @@ void xfs_trim_extent(struct xfs_bmbt_irec *irec, xfs_fileoff_t bno,
xfs_filblks_t len); xfs_filblks_t len);
unsigned int xfs_bmap_compute_attr_offset(struct xfs_mount *mp); unsigned int xfs_bmap_compute_attr_offset(struct xfs_mount *mp);
int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd); int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd);
int xfs_bmap_set_attrforkoff(struct xfs_inode *ip, int size, int *version);
void xfs_bmap_local_to_extents_empty(struct xfs_trans *tp, void xfs_bmap_local_to_extents_empty(struct xfs_trans *tp,
struct xfs_inode *ip, int whichfork); struct xfs_inode *ip, int whichfork);
void __xfs_bmap_add_free(struct xfs_trans *tp, xfs_fsblock_t bno, void __xfs_bmap_add_free(struct xfs_trans *tp, xfs_fsblock_t bno,
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "xfs_alloc.h" #include "xfs_alloc.h"
#include "xfs_log.h" #include "xfs_log.h"
#include "xfs_btree_staging.h" #include "xfs_btree_staging.h"
#include "xfs_ag.h"
/* /*
* Cursor allocation zone. * Cursor allocation zone.
...@@ -215,7 +216,7 @@ xfs_btree_check_sptr( ...@@ -215,7 +216,7 @@ xfs_btree_check_sptr(
{ {
if (level <= 0) if (level <= 0)
return false; return false;
return xfs_verify_agbno(cur->bc_mp, cur->bc_ag.agno, agbno); return xfs_verify_agbno(cur->bc_mp, cur->bc_ag.pag->pag_agno, agbno);
} }
/* /*
...@@ -244,7 +245,7 @@ xfs_btree_check_ptr( ...@@ -244,7 +245,7 @@ xfs_btree_check_ptr(
return 0; return 0;
xfs_err(cur->bc_mp, xfs_err(cur->bc_mp,
"AG %u: Corrupt btree %d pointer at level %d index %d.", "AG %u: Corrupt btree %d pointer at level %d index %d.",
cur->bc_ag.agno, cur->bc_btnum, cur->bc_ag.pag->pag_agno, cur->bc_btnum,
level, index); level, index);
} }
...@@ -376,6 +377,8 @@ xfs_btree_del_cursor( ...@@ -376,6 +377,8 @@ xfs_btree_del_cursor(
XFS_FORCED_SHUTDOWN(cur->bc_mp)); XFS_FORCED_SHUTDOWN(cur->bc_mp));
if (unlikely(cur->bc_flags & XFS_BTREE_STAGING)) if (unlikely(cur->bc_flags & XFS_BTREE_STAGING))
kmem_free(cur->bc_ops); kmem_free(cur->bc_ops);
if (!(cur->bc_flags & XFS_BTREE_LONG_PTRS) && cur->bc_ag.pag)
xfs_perag_put(cur->bc_ag.pag);
kmem_cache_free(xfs_btree_cur_zone, cur); kmem_cache_free(xfs_btree_cur_zone, cur);
} }
...@@ -885,13 +888,13 @@ xfs_btree_readahead_sblock( ...@@ -885,13 +888,13 @@ xfs_btree_readahead_sblock(
if ((lr & XFS_BTCUR_LEFTRA) && left != NULLAGBLOCK) { if ((lr & XFS_BTCUR_LEFTRA) && left != NULLAGBLOCK) {
xfs_btree_reada_bufs(cur->bc_mp, cur->bc_ag.agno, xfs_btree_reada_bufs(cur->bc_mp, cur->bc_ag.pag->pag_agno,
left, 1, cur->bc_ops->buf_ops); left, 1, cur->bc_ops->buf_ops);
rval++; rval++;
} }
if ((lr & XFS_BTCUR_RIGHTRA) && right != NULLAGBLOCK) { if ((lr & XFS_BTCUR_RIGHTRA) && right != NULLAGBLOCK) {
xfs_btree_reada_bufs(cur->bc_mp, cur->bc_ag.agno, xfs_btree_reada_bufs(cur->bc_mp, cur->bc_ag.pag->pag_agno,
right, 1, cur->bc_ops->buf_ops); right, 1, cur->bc_ops->buf_ops);
rval++; rval++;
} }
...@@ -949,7 +952,7 @@ xfs_btree_ptr_to_daddr( ...@@ -949,7 +952,7 @@ xfs_btree_ptr_to_daddr(
*daddr = XFS_FSB_TO_DADDR(cur->bc_mp, fsbno); *daddr = XFS_FSB_TO_DADDR(cur->bc_mp, fsbno);
} else { } else {
agbno = be32_to_cpu(ptr->s); agbno = be32_to_cpu(ptr->s);
*daddr = XFS_AGB_TO_DADDR(cur->bc_mp, cur->bc_ag.agno, *daddr = XFS_AGB_TO_DADDR(cur->bc_mp, cur->bc_ag.pag->pag_agno,
agbno); agbno);
} }
...@@ -1150,7 +1153,7 @@ xfs_btree_init_block_cur( ...@@ -1150,7 +1153,7 @@ xfs_btree_init_block_cur(
if (cur->bc_flags & XFS_BTREE_LONG_PTRS) if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
owner = cur->bc_ino.ip->i_ino; owner = cur->bc_ino.ip->i_ino;
else else
owner = cur->bc_ag.agno; owner = cur->bc_ag.pag->pag_agno;
xfs_btree_init_block_int(cur->bc_mp, XFS_BUF_TO_BLOCK(bp), bp->b_bn, xfs_btree_init_block_int(cur->bc_mp, XFS_BUF_TO_BLOCK(bp), bp->b_bn,
cur->bc_btnum, level, numrecs, cur->bc_btnum, level, numrecs,
......
...@@ -11,6 +11,7 @@ struct xfs_inode; ...@@ -11,6 +11,7 @@ struct xfs_inode;
struct xfs_mount; struct xfs_mount;
struct xfs_trans; struct xfs_trans;
struct xfs_ifork; struct xfs_ifork;
struct xfs_perag;
extern kmem_zone_t *xfs_btree_cur_zone; extern kmem_zone_t *xfs_btree_cur_zone;
...@@ -180,11 +181,11 @@ union xfs_btree_irec { ...@@ -180,11 +181,11 @@ union xfs_btree_irec {
/* Per-AG btree information. */ /* Per-AG btree information. */
struct xfs_btree_cur_ag { struct xfs_btree_cur_ag {
struct xfs_perag *pag;
union { union {
struct xfs_buf *agbp; struct xfs_buf *agbp;
struct xbtree_afakeroot *afake; /* for staging cursor */ struct xbtree_afakeroot *afake; /* for staging cursor */
}; };
xfs_agnumber_t agno;
union { union {
struct { struct {
unsigned long nr_ops; /* # record updates */ unsigned long nr_ops; /* # record updates */
...@@ -231,6 +232,13 @@ typedef struct xfs_btree_cur ...@@ -231,6 +232,13 @@ typedef struct xfs_btree_cur
uint8_t bc_blocklog; /* log2(blocksize) of btree blocks */ uint8_t bc_blocklog; /* log2(blocksize) of btree blocks */
xfs_btnum_t bc_btnum; /* identifies which btree type */ xfs_btnum_t bc_btnum; /* identifies which btree type */
int bc_statoff; /* offset of btre stats array */ int bc_statoff; /* offset of btre stats array */
/*
* Short btree pointers need an agno to be able to turn the pointers
* into physical addresses for IO, so the btree cursor switches between
* bc_ino and bc_ag based on whether XFS_BTREE_LONG_PTRS is set for the
* cursor.
*/
union { union {
struct xfs_btree_cur_ag bc_ag; struct xfs_btree_cur_ag bc_ag;
struct xfs_btree_cur_ino bc_ino; struct xfs_btree_cur_ino bc_ino;
......
This diff is collapsed.
...@@ -33,42 +33,14 @@ xfs_make_iptr(struct xfs_mount *mp, struct xfs_buf *b, int o) ...@@ -33,42 +33,14 @@ xfs_make_iptr(struct xfs_mount *mp, struct xfs_buf *b, int o)
} }
/* /*
* Allocate an inode on disk. * Allocate an inode on disk. Mode is used to tell whether the new inode will
* Mode is used to tell whether the new inode will need space, and whether * need space, and whether it is a directory.
* it is a directory.
*
* There are two phases to inode allocation: selecting an AG and ensuring
* that it contains free inodes, followed by allocating one of the free
* inodes. xfs_dialloc_select_ag() does the former and returns a locked AGI
* to the caller, ensuring that followup call to xfs_dialloc_ag() will
* have free inodes to allocate from. xfs_dialloc_ag() will return the inode
* number of the free inode we allocated.
*/ */
int /* error */ int xfs_dialloc(struct xfs_trans **tpp, xfs_ino_t parent, umode_t mode,
xfs_dialloc_select_ag( xfs_ino_t *new_ino);
struct xfs_trans **tpp, /* double pointer of transaction */
xfs_ino_t parent, /* parent inode (directory) */
umode_t mode, /* mode bits for new inode */
struct xfs_buf **IO_agbp);
int
xfs_dialloc_ag(
struct xfs_trans *tp,
struct xfs_buf *agbp,
xfs_ino_t parent,
xfs_ino_t *inop);
/* int xfs_difree(struct xfs_trans *tp, struct xfs_perag *pag,
* Free disk inode. Carefully avoids touching the incore inode, all xfs_ino_t ino, struct xfs_icluster *ifree);
* manipulations incore are the caller's responsibility.
* The on-disk inode is not changed by this operation, only the
* btree (free inode mask) is changed.
*/
int /* error */
xfs_difree(
struct xfs_trans *tp, /* transaction pointer */
xfs_ino_t inode, /* inode to be freed */
struct xfs_icluster *ifree); /* cluster info if deleted */
/* /*
* Return the location of the inode in imap, for mapping it into a buffer. * Return the location of the inode in imap, for mapping it into a buffer.
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "xfs_trace.h" #include "xfs_trace.h"
#include "xfs_trans.h" #include "xfs_trans.h"
#include "xfs_rmap.h" #include "xfs_rmap.h"
#include "xfs_ag.h"
STATIC int STATIC int
xfs_inobt_get_minrecs( xfs_inobt_get_minrecs(
...@@ -34,8 +35,7 @@ xfs_inobt_dup_cursor( ...@@ -34,8 +35,7 @@ xfs_inobt_dup_cursor(
struct xfs_btree_cur *cur) struct xfs_btree_cur *cur)
{ {
return xfs_inobt_init_cursor(cur->bc_mp, cur->bc_tp, return xfs_inobt_init_cursor(cur->bc_mp, cur->bc_tp,
cur->bc_ag.agbp, cur->bc_ag.agno, cur->bc_ag.agbp, cur->bc_ag.pag, cur->bc_btnum);
cur->bc_btnum);
} }
STATIC void STATIC void
...@@ -102,7 +102,7 @@ __xfs_inobt_alloc_block( ...@@ -102,7 +102,7 @@ __xfs_inobt_alloc_block(
args.tp = cur->bc_tp; args.tp = cur->bc_tp;
args.mp = cur->bc_mp; args.mp = cur->bc_mp;
args.oinfo = XFS_RMAP_OINFO_INOBT; args.oinfo = XFS_RMAP_OINFO_INOBT;
args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_ag.agno, sbno); args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_ag.pag->pag_agno, sbno);
args.minlen = 1; args.minlen = 1;
args.maxlen = 1; args.maxlen = 1;
args.prod = 1; args.prod = 1;
...@@ -235,7 +235,7 @@ xfs_inobt_init_ptr_from_cur( ...@@ -235,7 +235,7 @@ xfs_inobt_init_ptr_from_cur(
{ {
struct xfs_agi *agi = cur->bc_ag.agbp->b_addr; struct xfs_agi *agi = cur->bc_ag.agbp->b_addr;
ASSERT(cur->bc_ag.agno == be32_to_cpu(agi->agi_seqno)); ASSERT(cur->bc_ag.pag->pag_agno == be32_to_cpu(agi->agi_seqno));
ptr->s = agi->agi_root; ptr->s = agi->agi_root;
} }
...@@ -247,7 +247,7 @@ xfs_finobt_init_ptr_from_cur( ...@@ -247,7 +247,7 @@ xfs_finobt_init_ptr_from_cur(
{ {
struct xfs_agi *agi = cur->bc_ag.agbp->b_addr; struct xfs_agi *agi = cur->bc_ag.agbp->b_addr;
ASSERT(cur->bc_ag.agno == be32_to_cpu(agi->agi_seqno)); ASSERT(cur->bc_ag.pag->pag_agno == be32_to_cpu(agi->agi_seqno));
ptr->s = agi->agi_free_root; ptr->s = agi->agi_free_root;
} }
...@@ -427,7 +427,7 @@ static struct xfs_btree_cur * ...@@ -427,7 +427,7 @@ static struct xfs_btree_cur *
xfs_inobt_init_common( xfs_inobt_init_common(
struct xfs_mount *mp, /* file system mount point */ struct xfs_mount *mp, /* file system mount point */
struct xfs_trans *tp, /* transaction pointer */ struct xfs_trans *tp, /* transaction pointer */
xfs_agnumber_t agno, /* allocation group number */ struct xfs_perag *pag,
xfs_btnum_t btnum) /* ialloc or free ino btree */ xfs_btnum_t btnum) /* ialloc or free ino btree */
{ {
struct xfs_btree_cur *cur; struct xfs_btree_cur *cur;
...@@ -449,7 +449,9 @@ xfs_inobt_init_common( ...@@ -449,7 +449,9 @@ xfs_inobt_init_common(
if (xfs_sb_version_hascrc(&mp->m_sb)) if (xfs_sb_version_hascrc(&mp->m_sb))
cur->bc_flags |= XFS_BTREE_CRC_BLOCKS; cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
cur->bc_ag.agno = agno; /* take a reference for the cursor */
atomic_inc(&pag->pag_ref);
cur->bc_ag.pag = pag;
return cur; return cur;
} }
...@@ -459,13 +461,13 @@ xfs_inobt_init_cursor( ...@@ -459,13 +461,13 @@ xfs_inobt_init_cursor(
struct xfs_mount *mp, struct xfs_mount *mp,
struct xfs_trans *tp, struct xfs_trans *tp,
struct xfs_buf *agbp, struct xfs_buf *agbp,
xfs_agnumber_t agno, struct xfs_perag *pag,
xfs_btnum_t btnum) xfs_btnum_t btnum)
{ {
struct xfs_btree_cur *cur; struct xfs_btree_cur *cur;
struct xfs_agi *agi = agbp->b_addr; struct xfs_agi *agi = agbp->b_addr;
cur = xfs_inobt_init_common(mp, tp, agno, btnum); cur = xfs_inobt_init_common(mp, tp, pag, btnum);
if (btnum == XFS_BTNUM_INO) if (btnum == XFS_BTNUM_INO)
cur->bc_nlevels = be32_to_cpu(agi->agi_level); cur->bc_nlevels = be32_to_cpu(agi->agi_level);
else else
...@@ -479,12 +481,12 @@ struct xfs_btree_cur * ...@@ -479,12 +481,12 @@ struct xfs_btree_cur *
xfs_inobt_stage_cursor( xfs_inobt_stage_cursor(
struct xfs_mount *mp, struct xfs_mount *mp,
struct xbtree_afakeroot *afake, struct xbtree_afakeroot *afake,
xfs_agnumber_t agno, struct xfs_perag *pag,
xfs_btnum_t btnum) xfs_btnum_t btnum)
{ {
struct xfs_btree_cur *cur; struct xfs_btree_cur *cur;
cur = xfs_inobt_init_common(mp, NULL, agno, btnum); cur = xfs_inobt_init_common(mp, NULL, pag, btnum);
xfs_btree_stage_afakeroot(cur, afake); xfs_btree_stage_afakeroot(cur, afake);
return cur; return cur;
} }
...@@ -656,7 +658,7 @@ int ...@@ -656,7 +658,7 @@ int
xfs_inobt_cur( xfs_inobt_cur(
struct xfs_mount *mp, struct xfs_mount *mp,
struct xfs_trans *tp, struct xfs_trans *tp,
xfs_agnumber_t agno, struct xfs_perag *pag,
xfs_btnum_t which, xfs_btnum_t which,
struct xfs_btree_cur **curpp, struct xfs_btree_cur **curpp,
struct xfs_buf **agi_bpp) struct xfs_buf **agi_bpp)
...@@ -667,11 +669,11 @@ xfs_inobt_cur( ...@@ -667,11 +669,11 @@ xfs_inobt_cur(
ASSERT(*agi_bpp == NULL); ASSERT(*agi_bpp == NULL);
ASSERT(*curpp == NULL); ASSERT(*curpp == NULL);
error = xfs_ialloc_read_agi(mp, tp, agno, agi_bpp); error = xfs_ialloc_read_agi(mp, tp, pag->pag_agno, agi_bpp);
if (error) if (error)
return error; return error;
cur = xfs_inobt_init_cursor(mp, tp, *agi_bpp, agno, which); cur = xfs_inobt_init_cursor(mp, tp, *agi_bpp, pag, which);
*curpp = cur; *curpp = cur;
return 0; return 0;
} }
...@@ -680,7 +682,7 @@ static int ...@@ -680,7 +682,7 @@ static int
xfs_inobt_count_blocks( xfs_inobt_count_blocks(
struct xfs_mount *mp, struct xfs_mount *mp,
struct xfs_trans *tp, struct xfs_trans *tp,
xfs_agnumber_t agno, struct xfs_perag *pag,
xfs_btnum_t btnum, xfs_btnum_t btnum,
xfs_extlen_t *tree_blocks) xfs_extlen_t *tree_blocks)
{ {
...@@ -688,7 +690,7 @@ xfs_inobt_count_blocks( ...@@ -688,7 +690,7 @@ xfs_inobt_count_blocks(
struct xfs_btree_cur *cur = NULL; struct xfs_btree_cur *cur = NULL;
int error; int error;
error = xfs_inobt_cur(mp, tp, agno, btnum, &cur, &agbp); error = xfs_inobt_cur(mp, tp, pag, btnum, &cur, &agbp);
if (error) if (error)
return error; return error;
...@@ -704,14 +706,14 @@ static int ...@@ -704,14 +706,14 @@ static int
xfs_finobt_read_blocks( xfs_finobt_read_blocks(
struct xfs_mount *mp, struct xfs_mount *mp,
struct xfs_trans *tp, struct xfs_trans *tp,
xfs_agnumber_t agno, struct xfs_perag *pag,
xfs_extlen_t *tree_blocks) xfs_extlen_t *tree_blocks)
{ {
struct xfs_buf *agbp; struct xfs_buf *agbp;
struct xfs_agi *agi; struct xfs_agi *agi;
int error; int error;
error = xfs_ialloc_read_agi(mp, tp, agno, &agbp); error = xfs_ialloc_read_agi(mp, tp, pag->pag_agno, &agbp);
if (error) if (error)
return error; return error;
...@@ -728,7 +730,7 @@ int ...@@ -728,7 +730,7 @@ int
xfs_finobt_calc_reserves( xfs_finobt_calc_reserves(
struct xfs_mount *mp, struct xfs_mount *mp,
struct xfs_trans *tp, struct xfs_trans *tp,
xfs_agnumber_t agno, struct xfs_perag *pag,
xfs_extlen_t *ask, xfs_extlen_t *ask,
xfs_extlen_t *used) xfs_extlen_t *used)
{ {
...@@ -739,14 +741,14 @@ xfs_finobt_calc_reserves( ...@@ -739,14 +741,14 @@ xfs_finobt_calc_reserves(
return 0; return 0;
if (xfs_sb_version_hasinobtcounts(&mp->m_sb)) if (xfs_sb_version_hasinobtcounts(&mp->m_sb))
error = xfs_finobt_read_blocks(mp, tp, agno, &tree_len); error = xfs_finobt_read_blocks(mp, tp, pag, &tree_len);
else else
error = xfs_inobt_count_blocks(mp, tp, agno, XFS_BTNUM_FINO, error = xfs_inobt_count_blocks(mp, tp, pag, XFS_BTNUM_FINO,
&tree_len); &tree_len);
if (error) if (error)
return error; return error;
*ask += xfs_inobt_max_size(mp, agno); *ask += xfs_inobt_max_size(mp, pag->pag_agno);
*used += tree_len; *used += tree_len;
return 0; return 0;
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
struct xfs_buf; struct xfs_buf;
struct xfs_btree_cur; struct xfs_btree_cur;
struct xfs_mount; struct xfs_mount;
struct xfs_perag;
/* /*
* Btree block header size depends on a superblock flag. * Btree block header size depends on a superblock flag.
...@@ -45,11 +46,11 @@ struct xfs_mount; ...@@ -45,11 +46,11 @@ struct xfs_mount;
(maxrecs) * sizeof(xfs_inobt_key_t) + \ (maxrecs) * sizeof(xfs_inobt_key_t) + \
((index) - 1) * sizeof(xfs_inobt_ptr_t))) ((index) - 1) * sizeof(xfs_inobt_ptr_t)))
extern struct xfs_btree_cur *xfs_inobt_init_cursor(struct xfs_mount *, extern struct xfs_btree_cur *xfs_inobt_init_cursor(struct xfs_mount *mp,
struct xfs_trans *, struct xfs_buf *, xfs_agnumber_t, struct xfs_trans *tp, struct xfs_buf *agbp,
xfs_btnum_t); struct xfs_perag *pag, xfs_btnum_t btnum);
struct xfs_btree_cur *xfs_inobt_stage_cursor(struct xfs_mount *mp, struct xfs_btree_cur *xfs_inobt_stage_cursor(struct xfs_mount *mp,
struct xbtree_afakeroot *afake, xfs_agnumber_t agno, struct xbtree_afakeroot *afake, struct xfs_perag *pag,
xfs_btnum_t btnum); xfs_btnum_t btnum);
extern int xfs_inobt_maxrecs(struct xfs_mount *, int, int); extern int xfs_inobt_maxrecs(struct xfs_mount *, int, int);
...@@ -64,11 +65,11 @@ int xfs_inobt_rec_check_count(struct xfs_mount *, ...@@ -64,11 +65,11 @@ int xfs_inobt_rec_check_count(struct xfs_mount *,
#endif /* DEBUG */ #endif /* DEBUG */
int xfs_finobt_calc_reserves(struct xfs_mount *mp, struct xfs_trans *tp, int xfs_finobt_calc_reserves(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_agnumber_t agno, xfs_extlen_t *ask, xfs_extlen_t *used); struct xfs_perag *pag, xfs_extlen_t *ask, xfs_extlen_t *used);
extern xfs_extlen_t xfs_iallocbt_calc_size(struct xfs_mount *mp, extern xfs_extlen_t xfs_iallocbt_calc_size(struct xfs_mount *mp,
unsigned long long len); unsigned long long len);
int xfs_inobt_cur(struct xfs_mount *mp, struct xfs_trans *tp, int xfs_inobt_cur(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_agnumber_t agno, xfs_btnum_t btnum, struct xfs_perag *pag, xfs_btnum_t btnum,
struct xfs_btree_cur **curpp, struct xfs_buf **agi_bpp); struct xfs_btree_cur **curpp, struct xfs_buf **agi_bpp);
void xfs_inobt_commit_staged_btree(struct xfs_btree_cur *cur, void xfs_inobt_commit_staged_btree(struct xfs_btree_cur *cur,
......
...@@ -612,7 +612,7 @@ xfs_inode_validate_extsize( ...@@ -612,7 +612,7 @@ xfs_inode_validate_extsize(
*/ */
if (rt_flag) if (rt_flag)
blocksize_bytes = mp->m_sb.sb_rextsize << mp->m_sb.sb_blocklog; blocksize_bytes = XFS_FSB_TO_B(mp, mp->m_sb.sb_rextsize);
else else
blocksize_bytes = mp->m_sb.sb_blocksize; blocksize_bytes = mp->m_sb.sb_blocksize;
......
...@@ -34,9 +34,6 @@ typedef uint32_t xlog_tid_t; ...@@ -34,9 +34,6 @@ typedef uint32_t xlog_tid_t;
#define XLOG_MIN_RECORD_BSHIFT 14 /* 16384 == 1 << 14 */ #define XLOG_MIN_RECORD_BSHIFT 14 /* 16384 == 1 << 14 */
#define XLOG_BIG_RECORD_BSHIFT 15 /* 32k == 1 << 15 */ #define XLOG_BIG_RECORD_BSHIFT 15 /* 32k == 1 << 15 */
#define XLOG_MAX_RECORD_BSHIFT 18 /* 256k == 1 << 18 */ #define XLOG_MAX_RECORD_BSHIFT 18 /* 256k == 1 << 18 */
#define XLOG_BTOLSUNIT(log, b) (((b)+(log)->l_mp->m_sb.sb_logsunit-1) / \
(log)->l_mp->m_sb.sb_logsunit)
#define XLOG_LSUNITTOB(log, su) ((su) * (log)->l_mp->m_sb.sb_logsunit)
#define XLOG_HEADER_SIZE 512 #define XLOG_HEADER_SIZE 512
......
This diff is collapsed.
...@@ -6,6 +6,13 @@ ...@@ -6,6 +6,13 @@
#ifndef __XFS_REFCOUNT_H__ #ifndef __XFS_REFCOUNT_H__
#define __XFS_REFCOUNT_H__ #define __XFS_REFCOUNT_H__
struct xfs_trans;
struct xfs_mount;
struct xfs_perag;
struct xfs_btree_cur;
struct xfs_bmbt_irec;
struct xfs_refcount_irec;
extern int xfs_refcount_lookup_le(struct xfs_btree_cur *cur, extern int xfs_refcount_lookup_le(struct xfs_btree_cur *cur,
xfs_agblock_t bno, int *stat); xfs_agblock_t bno, int *stat);
extern int xfs_refcount_lookup_ge(struct xfs_btree_cur *cur, extern int xfs_refcount_lookup_ge(struct xfs_btree_cur *cur,
...@@ -50,7 +57,7 @@ void xfs_refcount_alloc_cow_extent(struct xfs_trans *tp, xfs_fsblock_t fsb, ...@@ -50,7 +57,7 @@ void xfs_refcount_alloc_cow_extent(struct xfs_trans *tp, xfs_fsblock_t fsb,
void xfs_refcount_free_cow_extent(struct xfs_trans *tp, xfs_fsblock_t fsb, void xfs_refcount_free_cow_extent(struct xfs_trans *tp, xfs_fsblock_t fsb,
xfs_extlen_t len); xfs_extlen_t len);
extern int xfs_refcount_recover_cow_leftovers(struct xfs_mount *mp, extern int xfs_refcount_recover_cow_leftovers(struct xfs_mount *mp,
xfs_agnumber_t agno); struct xfs_perag *pag);
/* /*
* While we're adjusting the refcounts records of an extent, we have * While we're adjusting the refcounts records of an extent, we have
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include "xfs_format.h" #include "xfs_format.h"
#include "xfs_log_format.h" #include "xfs_log_format.h"
#include "xfs_trans_resv.h" #include "xfs_trans_resv.h"
#include "xfs_sb.h"
#include "xfs_mount.h" #include "xfs_mount.h"
#include "xfs_btree.h" #include "xfs_btree.h"
#include "xfs_btree_staging.h" #include "xfs_btree_staging.h"
...@@ -20,13 +19,14 @@ ...@@ -20,13 +19,14 @@
#include "xfs_trans.h" #include "xfs_trans.h"
#include "xfs_bit.h" #include "xfs_bit.h"
#include "xfs_rmap.h" #include "xfs_rmap.h"
#include "xfs_ag.h"
static struct xfs_btree_cur * static struct xfs_btree_cur *
xfs_refcountbt_dup_cursor( xfs_refcountbt_dup_cursor(
struct xfs_btree_cur *cur) struct xfs_btree_cur *cur)
{ {
return xfs_refcountbt_init_cursor(cur->bc_mp, cur->bc_tp, return xfs_refcountbt_init_cursor(cur->bc_mp, cur->bc_tp,
cur->bc_ag.agbp, cur->bc_ag.agno); cur->bc_ag.agbp, cur->bc_ag.pag);
} }
STATIC void STATIC void
...@@ -65,7 +65,7 @@ xfs_refcountbt_alloc_block( ...@@ -65,7 +65,7 @@ xfs_refcountbt_alloc_block(
args.tp = cur->bc_tp; args.tp = cur->bc_tp;
args.mp = cur->bc_mp; args.mp = cur->bc_mp;
args.type = XFS_ALLOCTYPE_NEAR_BNO; args.type = XFS_ALLOCTYPE_NEAR_BNO;
args.fsbno = XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_ag.agno, args.fsbno = XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_ag.pag->pag_agno,
xfs_refc_block(args.mp)); xfs_refc_block(args.mp));
args.oinfo = XFS_RMAP_OINFO_REFC; args.oinfo = XFS_RMAP_OINFO_REFC;
args.minlen = args.maxlen = args.prod = 1; args.minlen = args.maxlen = args.prod = 1;
...@@ -74,13 +74,13 @@ xfs_refcountbt_alloc_block( ...@@ -74,13 +74,13 @@ xfs_refcountbt_alloc_block(
error = xfs_alloc_vextent(&args); error = xfs_alloc_vextent(&args);
if (error) if (error)
goto out_error; goto out_error;
trace_xfs_refcountbt_alloc_block(cur->bc_mp, cur->bc_ag.agno, trace_xfs_refcountbt_alloc_block(cur->bc_mp, cur->bc_ag.pag->pag_agno,
args.agbno, 1); args.agbno, 1);
if (args.fsbno == NULLFSBLOCK) { if (args.fsbno == NULLFSBLOCK) {
*stat = 0; *stat = 0;
return 0; return 0;
} }
ASSERT(args.agno == cur->bc_ag.agno); ASSERT(args.agno == cur->bc_ag.pag->pag_agno);
ASSERT(args.len == 1); ASSERT(args.len == 1);
new->s = cpu_to_be32(args.agbno); new->s = cpu_to_be32(args.agbno);
...@@ -105,7 +105,7 @@ xfs_refcountbt_free_block( ...@@ -105,7 +105,7 @@ xfs_refcountbt_free_block(
xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp)); xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp));
int error; int error;
trace_xfs_refcountbt_free_block(cur->bc_mp, cur->bc_ag.agno, trace_xfs_refcountbt_free_block(cur->bc_mp, cur->bc_ag.pag->pag_agno,
XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno), 1); XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno), 1);
be32_add_cpu(&agf->agf_refcount_blocks, -1); be32_add_cpu(&agf->agf_refcount_blocks, -1);
xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_REFCOUNT_BLOCKS); xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_REFCOUNT_BLOCKS);
...@@ -170,7 +170,7 @@ xfs_refcountbt_init_ptr_from_cur( ...@@ -170,7 +170,7 @@ xfs_refcountbt_init_ptr_from_cur(
{ {
struct xfs_agf *agf = cur->bc_ag.agbp->b_addr; struct xfs_agf *agf = cur->bc_ag.agbp->b_addr;
ASSERT(cur->bc_ag.agno == be32_to_cpu(agf->agf_seqno)); ASSERT(cur->bc_ag.pag->pag_agno == be32_to_cpu(agf->agf_seqno));
ptr->s = agf->agf_refcount_root; ptr->s = agf->agf_refcount_root;
} }
...@@ -316,12 +316,11 @@ static struct xfs_btree_cur * ...@@ -316,12 +316,11 @@ static struct xfs_btree_cur *
xfs_refcountbt_init_common( xfs_refcountbt_init_common(
struct xfs_mount *mp, struct xfs_mount *mp,
struct xfs_trans *tp, struct xfs_trans *tp,
xfs_agnumber_t agno) struct xfs_perag *pag)
{ {
struct xfs_btree_cur *cur; struct xfs_btree_cur *cur;
ASSERT(agno != NULLAGNUMBER); ASSERT(pag->pag_agno < mp->m_sb.sb_agcount);
ASSERT(agno < mp->m_sb.sb_agcount);
cur = kmem_cache_zalloc(xfs_btree_cur_zone, GFP_NOFS | __GFP_NOFAIL); cur = kmem_cache_zalloc(xfs_btree_cur_zone, GFP_NOFS | __GFP_NOFAIL);
cur->bc_tp = tp; cur->bc_tp = tp;
...@@ -330,9 +329,12 @@ xfs_refcountbt_init_common( ...@@ -330,9 +329,12 @@ xfs_refcountbt_init_common(
cur->bc_blocklog = mp->m_sb.sb_blocklog; cur->bc_blocklog = mp->m_sb.sb_blocklog;
cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_refcbt_2); cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_refcbt_2);
cur->bc_ag.agno = agno;
cur->bc_flags |= XFS_BTREE_CRC_BLOCKS; cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
/* take a reference for the cursor */
atomic_inc(&pag->pag_ref);
cur->bc_ag.pag = pag;
cur->bc_ag.refc.nr_ops = 0; cur->bc_ag.refc.nr_ops = 0;
cur->bc_ag.refc.shape_changes = 0; cur->bc_ag.refc.shape_changes = 0;
cur->bc_ops = &xfs_refcountbt_ops; cur->bc_ops = &xfs_refcountbt_ops;
...@@ -345,12 +347,12 @@ xfs_refcountbt_init_cursor( ...@@ -345,12 +347,12 @@ xfs_refcountbt_init_cursor(
struct xfs_mount *mp, struct xfs_mount *mp,
struct xfs_trans *tp, struct xfs_trans *tp,
struct xfs_buf *agbp, struct xfs_buf *agbp,
xfs_agnumber_t agno) struct xfs_perag *pag)
{ {
struct xfs_agf *agf = agbp->b_addr; struct xfs_agf *agf = agbp->b_addr;
struct xfs_btree_cur *cur; struct xfs_btree_cur *cur;
cur = xfs_refcountbt_init_common(mp, tp, agno); cur = xfs_refcountbt_init_common(mp, tp, pag);
cur->bc_nlevels = be32_to_cpu(agf->agf_refcount_level); cur->bc_nlevels = be32_to_cpu(agf->agf_refcount_level);
cur->bc_ag.agbp = agbp; cur->bc_ag.agbp = agbp;
return cur; return cur;
...@@ -361,11 +363,11 @@ struct xfs_btree_cur * ...@@ -361,11 +363,11 @@ struct xfs_btree_cur *
xfs_refcountbt_stage_cursor( xfs_refcountbt_stage_cursor(
struct xfs_mount *mp, struct xfs_mount *mp,
struct xbtree_afakeroot *afake, struct xbtree_afakeroot *afake,
xfs_agnumber_t agno) struct xfs_perag *pag)
{ {
struct xfs_btree_cur *cur; struct xfs_btree_cur *cur;
cur = xfs_refcountbt_init_common(mp, NULL, agno); cur = xfs_refcountbt_init_common(mp, NULL, pag);
xfs_btree_stage_afakeroot(cur, afake); xfs_btree_stage_afakeroot(cur, afake);
return cur; return cur;
} }
...@@ -450,7 +452,7 @@ int ...@@ -450,7 +452,7 @@ int
xfs_refcountbt_calc_reserves( xfs_refcountbt_calc_reserves(
struct xfs_mount *mp, struct xfs_mount *mp,
struct xfs_trans *tp, struct xfs_trans *tp,
xfs_agnumber_t agno, struct xfs_perag *pag,
xfs_extlen_t *ask, xfs_extlen_t *ask,
xfs_extlen_t *used) xfs_extlen_t *used)
{ {
...@@ -463,8 +465,7 @@ xfs_refcountbt_calc_reserves( ...@@ -463,8 +465,7 @@ xfs_refcountbt_calc_reserves(
if (!xfs_sb_version_hasreflink(&mp->m_sb)) if (!xfs_sb_version_hasreflink(&mp->m_sb))
return 0; return 0;
error = xfs_alloc_read_agf(mp, tp, pag->pag_agno, 0, &agbp);
error = xfs_alloc_read_agf(mp, tp, agno, 0, &agbp);
if (error) if (error)
return error; return error;
...@@ -479,7 +480,7 @@ xfs_refcountbt_calc_reserves( ...@@ -479,7 +480,7 @@ xfs_refcountbt_calc_reserves(
* expansion. We therefore can pretend the space isn't there. * expansion. We therefore can pretend the space isn't there.
*/ */
if (mp->m_sb.sb_logstart && if (mp->m_sb.sb_logstart &&
XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart) == agno) XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart) == pag->pag_agno)
agblocks -= mp->m_sb.sb_logblocks; agblocks -= mp->m_sb.sb_logblocks;
*ask += xfs_refcountbt_max_size(mp, agblocks); *ask += xfs_refcountbt_max_size(mp, agblocks);
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
struct xfs_buf; struct xfs_buf;
struct xfs_btree_cur; struct xfs_btree_cur;
struct xfs_mount; struct xfs_mount;
struct xfs_perag;
struct xbtree_afakeroot; struct xbtree_afakeroot;
/* /*
...@@ -46,9 +47,9 @@ struct xbtree_afakeroot; ...@@ -46,9 +47,9 @@ struct xbtree_afakeroot;
extern struct xfs_btree_cur *xfs_refcountbt_init_cursor(struct xfs_mount *mp, extern struct xfs_btree_cur *xfs_refcountbt_init_cursor(struct xfs_mount *mp,
struct xfs_trans *tp, struct xfs_buf *agbp, struct xfs_trans *tp, struct xfs_buf *agbp,
xfs_agnumber_t agno); struct xfs_perag *pag);
struct xfs_btree_cur *xfs_refcountbt_stage_cursor(struct xfs_mount *mp, struct xfs_btree_cur *xfs_refcountbt_stage_cursor(struct xfs_mount *mp,
struct xbtree_afakeroot *afake, xfs_agnumber_t agno); struct xbtree_afakeroot *afake, struct xfs_perag *pag);
extern int xfs_refcountbt_maxrecs(int blocklen, bool leaf); extern int xfs_refcountbt_maxrecs(int blocklen, bool leaf);
extern void xfs_refcountbt_compute_maxlevels(struct xfs_mount *mp); extern void xfs_refcountbt_compute_maxlevels(struct xfs_mount *mp);
...@@ -58,7 +59,7 @@ extern xfs_extlen_t xfs_refcountbt_max_size(struct xfs_mount *mp, ...@@ -58,7 +59,7 @@ extern xfs_extlen_t xfs_refcountbt_max_size(struct xfs_mount *mp,
xfs_agblock_t agblocks); xfs_agblock_t agblocks);
extern int xfs_refcountbt_calc_reserves(struct xfs_mount *mp, extern int xfs_refcountbt_calc_reserves(struct xfs_mount *mp,
struct xfs_trans *tp, xfs_agnumber_t agno, xfs_extlen_t *ask, struct xfs_trans *tp, struct xfs_perag *pag, xfs_extlen_t *ask,
xfs_extlen_t *used); xfs_extlen_t *used);
void xfs_refcountbt_commit_staged_btree(struct xfs_btree_cur *cur, void xfs_refcountbt_commit_staged_btree(struct xfs_btree_cur *cur,
......
This diff is collapsed.
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#ifndef __XFS_RMAP_H__ #ifndef __XFS_RMAP_H__
#define __XFS_RMAP_H__ #define __XFS_RMAP_H__
struct xfs_perag;
static inline void static inline void
xfs_rmap_ino_bmbt_owner( xfs_rmap_ino_bmbt_owner(
struct xfs_owner_info *oi, struct xfs_owner_info *oi,
...@@ -113,10 +115,10 @@ xfs_owner_info_pack( ...@@ -113,10 +115,10 @@ xfs_owner_info_pack(
} }
int xfs_rmap_alloc(struct xfs_trans *tp, struct xfs_buf *agbp, int xfs_rmap_alloc(struct xfs_trans *tp, struct xfs_buf *agbp,
xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, struct xfs_perag *pag, xfs_agblock_t bno, xfs_extlen_t len,
const struct xfs_owner_info *oinfo); const struct xfs_owner_info *oinfo);
int xfs_rmap_free(struct xfs_trans *tp, struct xfs_buf *agbp, int xfs_rmap_free(struct xfs_trans *tp, struct xfs_buf *agbp,
xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, struct xfs_perag *pag, xfs_agblock_t bno, xfs_extlen_t len,
const struct xfs_owner_info *oinfo); const struct xfs_owner_info *oinfo);
int xfs_rmap_lookup_le(struct xfs_btree_cur *cur, xfs_agblock_t bno, int xfs_rmap_lookup_le(struct xfs_btree_cur *cur, xfs_agblock_t bno,
......
This diff is collapsed.
...@@ -43,9 +43,9 @@ struct xbtree_afakeroot; ...@@ -43,9 +43,9 @@ struct xbtree_afakeroot;
struct xfs_btree_cur *xfs_rmapbt_init_cursor(struct xfs_mount *mp, struct xfs_btree_cur *xfs_rmapbt_init_cursor(struct xfs_mount *mp,
struct xfs_trans *tp, struct xfs_buf *bp, struct xfs_trans *tp, struct xfs_buf *bp,
xfs_agnumber_t agno); struct xfs_perag *pag);
struct xfs_btree_cur *xfs_rmapbt_stage_cursor(struct xfs_mount *mp, struct xfs_btree_cur *xfs_rmapbt_stage_cursor(struct xfs_mount *mp,
struct xbtree_afakeroot *afake, xfs_agnumber_t agno); struct xbtree_afakeroot *afake, struct xfs_perag *pag);
void xfs_rmapbt_commit_staged_btree(struct xfs_btree_cur *cur, void xfs_rmapbt_commit_staged_btree(struct xfs_btree_cur *cur,
struct xfs_trans *tp, struct xfs_buf *agbp); struct xfs_trans *tp, struct xfs_buf *agbp);
int xfs_rmapbt_maxrecs(int blocklen, int leaf); int xfs_rmapbt_maxrecs(int blocklen, int leaf);
...@@ -57,6 +57,6 @@ extern xfs_extlen_t xfs_rmapbt_max_size(struct xfs_mount *mp, ...@@ -57,6 +57,6 @@ extern xfs_extlen_t xfs_rmapbt_max_size(struct xfs_mount *mp,
xfs_agblock_t agblocks); xfs_agblock_t agblocks);
extern int xfs_rmapbt_calc_reserves(struct xfs_mount *mp, struct xfs_trans *tp, extern int xfs_rmapbt_calc_reserves(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_agnumber_t agno, xfs_extlen_t *ask, xfs_extlen_t *used); struct xfs_perag *pag, xfs_extlen_t *ask, xfs_extlen_t *used);
#endif /* __XFS_RMAP_BTREE_H__ */ #endif /* __XFS_RMAP_BTREE_H__ */
This diff is collapsed.
...@@ -13,15 +13,6 @@ struct xfs_trans; ...@@ -13,15 +13,6 @@ struct xfs_trans;
struct xfs_fsop_geom; struct xfs_fsop_geom;
struct xfs_perag; struct xfs_perag;
/*
* perag get/put wrappers for ref counting
*/
extern struct xfs_perag *xfs_perag_get(struct xfs_mount *, xfs_agnumber_t);
extern struct xfs_perag *xfs_perag_get_tag(struct xfs_mount *, xfs_agnumber_t,
int tag);
extern void xfs_perag_put(struct xfs_perag *pag);
extern int xfs_initialize_perag_data(struct xfs_mount *, xfs_agnumber_t);
extern void xfs_log_sb(struct xfs_trans *tp); extern void xfs_log_sb(struct xfs_trans *tp);
extern int xfs_sync_sb(struct xfs_mount *mp, bool wait); extern int xfs_sync_sb(struct xfs_mount *mp, bool wait);
extern int xfs_sync_sb_buf(struct xfs_mount *mp); extern int xfs_sync_sb_buf(struct xfs_mount *mp);
......
This diff is collapsed.
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "xfs_trans_resv.h" #include "xfs_trans_resv.h"
#include "xfs_bit.h" #include "xfs_bit.h"
#include "xfs_mount.h" #include "xfs_mount.h"
#include "xfs_ag.h"
/* Find the size of the AG, in blocks. */ /* Find the size of the AG, in blocks. */
inline xfs_agblock_t inline xfs_agblock_t
...@@ -222,12 +223,13 @@ xfs_icount_range( ...@@ -222,12 +223,13 @@ xfs_icount_range(
unsigned long long *max) unsigned long long *max)
{ {
unsigned long long nr_inos = 0; unsigned long long nr_inos = 0;
struct xfs_perag *pag;
xfs_agnumber_t agno; xfs_agnumber_t agno;
/* root, rtbitmap, rtsum all live in the first chunk */ /* root, rtbitmap, rtsum all live in the first chunk */
*min = XFS_INODES_PER_CHUNK; *min = XFS_INODES_PER_CHUNK;
for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { for_each_perag(mp, agno, pag) {
xfs_agino_t first, last; xfs_agino_t first, last;
xfs_agino_range(mp, agno, &first, &last); xfs_agino_range(mp, agno, &first, &last);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment