summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2026-09-30 11:58:27 +0100
committerMark Brown <broonie@kernel.org>2026-09-30 11:58:27 +0100
commitf60deca1c3741ab8fcf318a7bb82a3d026ea7c49 (patch)
tree5eb96f4fa7204519a1ecc1a1d8f5cd2c82fa0405
parentba3167caf21347320ad8017bd302ac4b62a40864 (diff)
parentb4787e7b9730d52f33cf8dd23b3c42f1237f9753 (diff)
downloadlinux-next-f60deca1c3741ab8fcf318a7bb82a3d026ea7c49.tar.gz
linux-next-f60deca1c3741ab8fcf318a7bb82a3d026ea7c49.zip
Merge branch 'for-next' of https://git.kernel.org/pub/scm/fs/xfs/xfs-linux.git
-rw-r--r--Documentation/filesystems/xfs/xfs-online-fsck-design.rst13
-rw-r--r--fs/xfs/libxfs/xfs_attr.c14
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c5
-rw-r--r--fs/xfs/libxfs/xfs_bmap.h2
-rw-r--r--fs/xfs/libxfs/xfs_btree.c10
-rw-r--r--fs/xfs/libxfs/xfs_btree_mem.c6
-rw-r--r--fs/xfs/libxfs/xfs_dquot_buf.c13
-rw-r--r--fs/xfs/libxfs/xfs_exchmaps.c1
-rw-r--r--fs/xfs/libxfs/xfs_exchmaps.h3
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.c2
-rw-r--r--fs/xfs/libxfs/xfs_ialloc_btree.c1
-rw-r--r--fs/xfs/libxfs/xfs_ialloc_btree.h5
-rw-r--r--fs/xfs/libxfs/xfs_inode_fork.c4
-rw-r--r--fs/xfs/libxfs/xfs_metadir.c32
-rw-r--r--fs/xfs/libxfs/xfs_metadir.h5
-rw-r--r--fs/xfs/libxfs/xfs_parent.h1
-rw-r--r--fs/xfs/libxfs/xfs_refcount_btree.c16
-rw-r--r--fs/xfs/libxfs/xfs_refcount_btree.h26
-rw-r--r--fs/xfs/libxfs/xfs_rmap.c13
-rw-r--r--fs/xfs/libxfs/xfs_rmap_btree.c16
-rw-r--r--fs/xfs/libxfs/xfs_rmap_btree.h26
-rw-r--r--fs/xfs/libxfs/xfs_rtrefcount_btree.c121
-rw-r--r--fs/xfs/libxfs/xfs_rtrefcount_btree.h5
-rw-r--r--fs/xfs/libxfs/xfs_rtrmap_btree.c236
-rw-r--r--fs/xfs/libxfs/xfs_rtrmap_btree.h3
-rw-r--r--fs/xfs/libxfs/xfs_sb.c40
-rw-r--r--fs/xfs/libxfs/xfs_sb.h1
-rw-r--r--fs/xfs/libxfs/xfs_symlink_remote.c8
-rw-r--r--fs/xfs/libxfs/xfs_symlink_remote.h2
-rw-r--r--fs/xfs/libxfs/xfs_trans_resv.c45
-rw-r--r--fs/xfs/libxfs/xfs_trans_space.c6
-rw-r--r--fs/xfs/libxfs/xfs_types.c7
-rw-r--r--fs/xfs/libxfs/xfs_types.h7
-rw-r--r--fs/xfs/scrub/alloc_repair.c15
-rw-r--r--fs/xfs/scrub/bmap.c11
-rw-r--r--fs/xfs/scrub/bmap_repair.c4
-rw-r--r--fs/xfs/scrub/inode_repair.c32
-rw-r--r--fs/xfs/scrub/orphanage.c2
-rw-r--r--fs/xfs/scrub/quota.c2
-rw-r--r--fs/xfs/scrub/quota_repair.c9
-rw-r--r--fs/xfs/scrub/quotacheck_repair.c54
-rw-r--r--fs/xfs/scrub/rtrefcount_repair.c3
-rw-r--r--fs/xfs/scrub/rtrmap_repair.c2
-rw-r--r--fs/xfs/scrub/xfarray.c201
-rw-r--r--fs/xfs/scrub/xfarray.h9
-rw-r--r--fs/xfs/xfs_bmap_item.c2
-rw-r--r--fs/xfs/xfs_dquot.c20
-rw-r--r--fs/xfs/xfs_dquot.h2
-rw-r--r--fs/xfs/xfs_exchmaps_item.c4
-rw-r--r--fs/xfs/xfs_exchrange.c2
-rw-r--r--fs/xfs/xfs_file.c22
-rw-r--r--fs/xfs/xfs_handle.c2
-rw-r--r--fs/xfs/xfs_inode.c20
-rw-r--r--fs/xfs/xfs_ioctl.c425
-rw-r--r--fs/xfs/xfs_ioctl.h4
-rw-r--r--fs/xfs/xfs_ioctl32.c188
-rw-r--r--fs/xfs/xfs_qm.c6
-rw-r--r--fs/xfs/xfs_rmap_item.c2
-rw-r--r--fs/xfs/xfs_rtalloc.h49
-rw-r--r--fs/xfs/xfs_super.c2
-rw-r--r--fs/xfs/xfs_symlink.c4
-rw-r--r--fs/xfs/xfs_trace.h28
-rw-r--r--fs/xfs/xfs_trans_dquot.c6
63 files changed, 883 insertions, 944 deletions
diff --git a/Documentation/filesystems/xfs/xfs-online-fsck-design.rst b/Documentation/filesystems/xfs/xfs-online-fsck-design.rst
index 3d9233f403db..14767ce9fad4 100644
--- a/Documentation/filesystems/xfs/xfs-online-fsck-design.rst
+++ b/Documentation/filesystems/xfs/xfs-online-fsck-design.rst
@@ -1973,8 +1973,7 @@ provide loading and storing of array elements at arbitrary array indices.
Gaps are defined to be null records, and null records are defined to be a
sequence of all zero bytes.
Null records are detected by calling ``xfarray_element_is_null``.
-They are created either by calling ``xfarray_unset`` to null out an existing
-record or by never storing anything to an array index.
+They are created by never storing anything to an array index.
The second type of caller handles records that are not indexed by position
and do not require multiple updates to a record.
@@ -1991,9 +1990,7 @@ The typical use case here is constructing space extent reference counts from
reverse mapping information.
Records can be put in the bag in any order, they can be removed from the bag
at any time, and uniqueness of records is left to callers.
-The ``xfarray_store_anywhere`` function is used to insert a record in any
-null record slot in the bag; and the ``xfarray_unset`` function removes a
-record from the bag.
+Note: Bags are now implemented with in-memory btrees for faster access.
Iterating Array Elements
^^^^^^^^^^^^^^^^^^^^^^^^
@@ -2643,11 +2640,7 @@ generate refcount information from reverse mapping records.
refcount record associating the block number range that we just walked to
the size of the bag.
-The bag-like structure in this case is a type 2 xfarray as discussed in the
-:ref:`xfarray access patterns<xfarray_access_patterns>` section.
-Reverse mappings are added to the bag using ``xfarray_store_anywhere`` and
-removed via ``xfarray_unset``.
-Bag members are examined through ``xfarray_iter`` loops.
+The bag-like structure in this case is an in-memory btree.
Case Study: Rebuilding File Fork Mapping Indices
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
index b3f7b2c34ad7..c4bb59633ce8 100644
--- a/fs/xfs/libxfs/xfs_attr.c
+++ b/fs/xfs/libxfs/xfs_attr.c
@@ -59,8 +59,7 @@ STATIC void xfs_attr_restore_rmt_blk(struct xfs_da_args *args);
static int xfs_attr_node_try_addname(struct xfs_attr_intent *attr);
STATIC int xfs_attr_node_addname_find_attr(struct xfs_attr_intent *attr);
STATIC int xfs_attr_node_remove_attr(struct xfs_attr_intent *attr);
-STATIC int xfs_attr_node_lookup(struct xfs_da_args *args,
- struct xfs_da_state *state);
+STATIC int xfs_attr_node_lookup(struct xfs_da_state *state);
int
xfs_inode_hasattr(
@@ -709,7 +708,7 @@ int xfs_attr_node_removename_setup(
int error;
xfs_attr_item_init_da_state(attr);
- error = xfs_attr_node_lookup(args, attr->xattri_da_state);
+ error = xfs_attr_node_lookup(attr->xattri_da_state);
if (error != -EEXIST)
goto out;
error = 0;
@@ -985,7 +984,7 @@ xfs_attr_lookup(
}
state = xfs_da_state_alloc(args);
- error = xfs_attr_node_lookup(args, state);
+ error = xfs_attr_node_lookup(state);
xfs_da_state_free(state);
return error;
}
@@ -1014,7 +1013,7 @@ xfs_attr_add_fork(
if (xfs_inode_has_attr_fork(ip))
goto trans_cancel;
- error = xfs_bmap_add_attrfork(tp, ip, size, rsvd);
+ error = xfs_bmap_add_attrfork(tp, ip, size);
if (error)
goto trans_cancel;
@@ -1386,7 +1385,6 @@ xfs_attr_leaf_get(
/* Return EEXIST if attr is found, or ENOATTR if not. */
STATIC int
xfs_attr_node_lookup(
- struct xfs_da_args *args,
struct xfs_da_state *state)
{
int retval, error;
@@ -1417,7 +1415,7 @@ xfs_attr_node_addname_find_attr(
* to where it should go.
*/
xfs_attr_item_init_da_state(attr);
- error = xfs_attr_node_lookup(args, attr->xattri_da_state);
+ error = xfs_attr_node_lookup(attr->xattri_da_state);
switch (error) {
case -ENOATTR:
if (args->op_flags & XFS_DA_OP_REPLACE)
@@ -1588,7 +1586,7 @@ xfs_attr_node_get(
* Search to see if name exists, and get back a pointer to it.
*/
state = xfs_da_state_alloc(args);
- error = xfs_attr_node_lookup(args, state);
+ error = xfs_attr_node_lookup(state);
if (error != -EEXIST)
goto out_release;
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index d64defeda645..ae91f63455c5 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -1026,8 +1026,7 @@ int /* error code */
xfs_bmap_add_attrfork(
struct xfs_trans *tp,
struct xfs_inode *ip, /* incore inode pointer */
- int size, /* space new attribute needs */
- int rsvd) /* xact may use reserved blks */
+ int size) /* space new attribute needs */
{
struct xfs_mount *mp = tp->t_mountp;
int logflags; /* logging flags */
@@ -6088,7 +6087,7 @@ xfs_bmap_validate_extent_raw(
int whichfork,
struct xfs_bmbt_irec *irec)
{
- if (!xfs_verify_fileext(mp, irec->br_startoff, irec->br_blockcount))
+ if (!xfs_verify_fileext(irec->br_startoff, irec->br_blockcount))
return __this_address;
if (rtfile && whichfork == XFS_DATA_FORK) {
diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h
index d5f2729305fa..60f6df4ce057 100644
--- a/fs/xfs/libxfs/xfs_bmap.h
+++ b/fs/xfs/libxfs/xfs_bmap.h
@@ -181,7 +181,7 @@ void xfs_trim_extent(struct xfs_bmbt_irec *irec, xfs_fileoff_t bno,
xfs_filblks_t len);
unsigned int xfs_bmap_compute_attr_offset(struct xfs_mount *mp);
int xfs_bmap_add_attrfork(struct xfs_trans *tp, struct xfs_inode *ip,
- int size, int rsvd);
+ int size);
void xfs_bmap_local_to_extents_empty(struct xfs_trans *tp,
struct xfs_inode *ip, int whichfork);
int xfs_bmap_local_to_extents(struct xfs_trans *tp, struct xfs_inode *ip,
diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c
index 60ef7f08b1d3..7effebe297ea 100644
--- a/fs/xfs/libxfs/xfs_btree.c
+++ b/fs/xfs/libxfs/xfs_btree.c
@@ -3010,6 +3010,7 @@ xfs_btree_split_worker(
struct xfs_btree_split_args, work);
unsigned long pflags;
unsigned long new_pflags = 0;
+ unsigned int nofs_flags;
/*
* we are in a transaction context here, but may also be doing work
@@ -3021,12 +3022,17 @@ xfs_btree_split_worker(
new_pflags |= PF_MEMALLOC | PF_KSWAPD;
current_set_flags_nested(&pflags, new_pflags);
- xfs_trans_set_context(args->cur->bc_tp);
+
+ /*
+ * Don't use xfs_trans_set_context() here: it would overwrite the
+ * caller's saved NOFS state in tp->t_pflags. Use a local scope.
+ */
+ nofs_flags = memalloc_nofs_save();
args->result = __xfs_btree_split(args->cur, args->level, args->ptrp,
args->key, args->curp, args->stat);
- xfs_trans_clear_context(args->cur->bc_tp);
+ memalloc_nofs_restore(nofs_flags);
current_restore_flags_nested(&pflags, new_pflags);
/*
diff --git a/fs/xfs/libxfs/xfs_btree_mem.c b/fs/xfs/libxfs/xfs_btree_mem.c
index 1d83a4251cee..3d5c7a014d4f 100644
--- a/fs/xfs/libxfs/xfs_btree_mem.c
+++ b/fs/xfs/libxfs/xfs_btree_mem.c
@@ -73,9 +73,7 @@ xfbtree_destroy(
/* Compute the number of bytes available for records. */
static inline unsigned int
-xfbtree_rec_bytes(
- struct xfs_mount *mp,
- const struct xfs_btree_ops *ops)
+xfbtree_rec_bytes(void)
{
return XMBUF_BLOCKSIZE - XFS_BTREE_LBLOCK_CRC_LEN;
}
@@ -118,7 +116,7 @@ xfbtree_init(
const struct xfs_btree_ops *ops)
{
unsigned long long owner = xfbt->owner;
- unsigned int blocklen = xfbtree_rec_bytes(mp, ops);
+ unsigned int blocklen = xfbtree_rec_bytes();
unsigned int keyptr_len;
int error;
diff --git a/fs/xfs/libxfs/xfs_dquot_buf.c b/fs/xfs/libxfs/xfs_dquot_buf.c
index 77954d1d924c..6c8a9afdfb1c 100644
--- a/fs/xfs/libxfs/xfs_dquot_buf.c
+++ b/fs/xfs/libxfs/xfs_dquot_buf.c
@@ -454,19 +454,8 @@ xfs_dqinode_metadir_link(
.path = xfs_dqinode_path(type),
.ip = ip,
};
- int error;
- error = xfs_metadir_start_link(&upd);
- if (error)
- return error;
-
- error = xfs_metadir_link(&upd);
- if (error)
- return error;
-
- xfs_trans_log_inode(upd.tp, upd.ip, XFS_ILOG_CORE);
-
- return xfs_metadir_commit(&upd);
+ return xfs_metadir_link_file(&upd);
}
#endif /* __KERNEL__ */
diff --git a/fs/xfs/libxfs/xfs_exchmaps.c b/fs/xfs/libxfs/xfs_exchmaps.c
index 6a66b6075e0a..ccb97da3765f 100644
--- a/fs/xfs/libxfs/xfs_exchmaps.c
+++ b/fs/xfs/libxfs/xfs_exchmaps.c
@@ -135,7 +135,6 @@ xmi_has_postop_work(const struct xfs_exchmaps_intent *xmi)
/* Check all mappings to make sure we can actually exchange them. */
int
xfs_exchmaps_check_forks(
- struct xfs_mount *mp,
const struct xfs_exchmaps_req *req)
{
struct xfs_ifork *ifp1, *ifp2;
diff --git a/fs/xfs/libxfs/xfs_exchmaps.h b/fs/xfs/libxfs/xfs_exchmaps.h
index fa822dff202a..055b8dbabd5b 100644
--- a/fs/xfs/libxfs/xfs_exchmaps.h
+++ b/fs/xfs/libxfs/xfs_exchmaps.h
@@ -115,8 +115,7 @@ void xfs_exchmaps_upgrade_extent_counts(struct xfs_trans *tp,
int xfs_exchmaps_finish_one(struct xfs_trans *tp,
struct xfs_exchmaps_intent *xmi);
-int xfs_exchmaps_check_forks(struct xfs_mount *mp,
- const struct xfs_exchmaps_req *req);
+int xfs_exchmaps_check_forks(const struct xfs_exchmaps_req *req);
void xfs_exchange_mappings(struct xfs_trans *tp,
const struct xfs_exchmaps_req *req);
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index 58dac4d505ba..19b513b11692 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -615,7 +615,7 @@ xfs_inobt_insert_sprec(
trace_xfs_irec_merge_post(pag, nrec);
- error = xfs_inobt_rec_check_count(mp, nrec);
+ error = xfs_inobt_rec_check_count(nrec);
if (error)
goto error;
diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c
index 1376e8630449..1f0bace2f144 100644
--- a/fs/xfs/libxfs/xfs_ialloc_btree.c
+++ b/fs/xfs/libxfs/xfs_ialloc_btree.c
@@ -687,7 +687,6 @@ xfs_inobt_irec_to_allocmask(
*/
int
xfs_inobt_rec_check_count(
- struct xfs_mount *mp,
struct xfs_inobt_rec_incore *rec)
{
int inocount = 0;
diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.h b/fs/xfs/libxfs/xfs_ialloc_btree.h
index 300edf5bc009..e04c63c66f39 100644
--- a/fs/xfs/libxfs/xfs_ialloc_btree.h
+++ b/fs/xfs/libxfs/xfs_ialloc_btree.h
@@ -57,10 +57,9 @@ unsigned int xfs_inobt_maxrecs(struct xfs_mount *mp, unsigned int blocklen,
uint64_t xfs_inobt_irec_to_allocmask(const struct xfs_inobt_rec_incore *irec);
#if defined(DEBUG) || defined(XFS_WARN)
-int xfs_inobt_rec_check_count(struct xfs_mount *,
- struct xfs_inobt_rec_incore *);
+int xfs_inobt_rec_check_count(struct xfs_inobt_rec_incore *);
#else
-#define xfs_inobt_rec_check_count(mp, rec) 0
+#define xfs_inobt_rec_check_count(rec) 0
#endif /* DEBUG */
int xfs_finobt_calc_reserves(struct xfs_perag *perag, struct xfs_trans *tp,
diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
index 606a36526ce2..486fe7ab8b61 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.c
+++ b/fs/xfs/libxfs/xfs_inode_fork.c
@@ -683,9 +683,7 @@ xfs_ifork_verify_local_data(
break;
}
case S_IFLNK: {
- struct xfs_ifork *ifp = xfs_ifork_ptr(ip, XFS_DATA_FORK);
-
- fa = xfs_symlink_shortform_verify(ifp->if_data, ifp->if_bytes);
+ fa = xfs_symlink_shortform_verify(ip);
break;
}
default:
diff --git a/fs/xfs/libxfs/xfs_metadir.c b/fs/xfs/libxfs/xfs_metadir.c
index 7c6b086b73db..79b37cb27273 100644
--- a/fs/xfs/libxfs/xfs_metadir.c
+++ b/fs/xfs/libxfs/xfs_metadir.c
@@ -163,7 +163,7 @@ xfs_metadir_teardown(
trace_xfs_metadir_teardown(upd, error);
if (upd->ppargs) {
- xfs_parent_finish(upd->dp->i_mount, upd->ppargs);
+ xfs_parent_finish(upd->ppargs);
upd->ppargs = NULL;
}
@@ -317,7 +317,7 @@ xfs_metadir_create(
* Begin the process of linking a metadata file by allocating transactions
* and locking whatever resources we're going to need.
*/
-int
+static int
xfs_metadir_start_link(
struct xfs_metadir_update *upd)
{
@@ -364,7 +364,7 @@ out_teardown:
* The path (up to the final component) must already exist, but the final
* component must not already exist.
*/
-int
+static int
xfs_metadir_link(
struct xfs_metadir_update *upd)
{
@@ -409,7 +409,7 @@ xfs_metadir_link(
#endif /* ! __KERNEL__ */
/* Commit a metadir update and unlock/drop all resources. */
-int
+static int
xfs_metadir_commit(
struct xfs_metadir_update *upd)
{
@@ -499,3 +499,27 @@ xfs_metadir_mkdir(
return xfs_metadir_create_file(&upd, S_IFDIR, NULL, NULL, ipp);
}
+
+#ifndef __KERNEL__
+/* Link a metadata file into a metadata directory. */
+int
+xfs_metadir_link_file(
+ struct xfs_metadir_update *upd)
+{
+ int error;
+
+ error = xfs_metadir_start_link(upd);
+ if (error)
+ return error;
+
+ error = xfs_metadir_link(upd);
+ if (error) {
+ xfs_metadir_cancel(upd, error);
+ return error;
+ }
+
+ xfs_trans_log_inode(upd->tp, upd->ip, XFS_ILOG_CORE);
+
+ return xfs_metadir_commit(upd);
+}
+#endif /* ! __KERNEL__ */
diff --git a/fs/xfs/libxfs/xfs_metadir.h b/fs/xfs/libxfs/xfs_metadir.h
index e434b9d1c932..b64f9fc5ca78 100644
--- a/fs/xfs/libxfs/xfs_metadir.h
+++ b/fs/xfs/libxfs/xfs_metadir.h
@@ -38,10 +38,7 @@ int xfs_metadir_create_file(struct xfs_metadir_update *upd, umode_t mode,
xfs_metadir_createfn create, void *priv,
struct xfs_inode **ipp);
-int xfs_metadir_start_link(struct xfs_metadir_update *upd);
-int xfs_metadir_link(struct xfs_metadir_update *upd);
-
-int xfs_metadir_commit(struct xfs_metadir_update *upd);
+int xfs_metadir_link_file(struct xfs_metadir_update *upd);
int xfs_metadir_mkdir(struct xfs_inode *dp, const char *path,
struct xfs_inode **ipp);
diff --git a/fs/xfs/libxfs/xfs_parent.h b/fs/xfs/libxfs/xfs_parent.h
index 8eb4de9c5f1a..1dd3968a78b1 100644
--- a/fs/xfs/libxfs/xfs_parent.h
+++ b/fs/xfs/libxfs/xfs_parent.h
@@ -72,7 +72,6 @@ xfs_parent_start(
/* Finish a parent pointer update by freeing the context object. */
static inline void
xfs_parent_finish(
- struct xfs_mount *mp,
struct xfs_parent_args *ppargs)
{
if (ppargs)
diff --git a/fs/xfs/libxfs/xfs_refcount_btree.c b/fs/xfs/libxfs/xfs_refcount_btree.c
index 7e5f92c1ac56..2c6148a97994 100644
--- a/fs/xfs/libxfs/xfs_refcount_btree.c
+++ b/fs/xfs/libxfs/xfs_refcount_btree.c
@@ -127,7 +127,7 @@ xfs_refcountbt_get_maxrecs(
return cur->bc_mp->m_refc_mxr[level != 0];
}
-STATIC void
+void
xfs_refcountbt_init_key_from_rec(
union xfs_btree_key *key,
const union xfs_btree_rec *rec)
@@ -135,7 +135,7 @@ xfs_refcountbt_init_key_from_rec(
key->refc.rc_startblock = rec->refc.rc_startblock;
}
-STATIC void
+void
xfs_refcountbt_init_high_key_from_rec(
union xfs_btree_key *key,
const union xfs_btree_rec *rec)
@@ -147,7 +147,7 @@ xfs_refcountbt_init_high_key_from_rec(
key->refc.rc_startblock = cpu_to_be32(x);
}
-STATIC void
+void
xfs_refcountbt_init_rec_from_cur(
struct xfs_btree_cur *cur,
union xfs_btree_rec *rec)
@@ -174,7 +174,7 @@ xfs_refcountbt_init_ptr_from_cur(
ptr->s = agf->agf_refcount_root;
}
-STATIC int
+int
xfs_refcountbt_cmp_key_with_cur(
struct xfs_btree_cur *cur,
const union xfs_btree_key *key)
@@ -188,7 +188,7 @@ xfs_refcountbt_cmp_key_with_cur(
return cmp_int(be32_to_cpu(kp->rc_startblock), start);
}
-STATIC int
+int
xfs_refcountbt_cmp_two_keys(
struct xfs_btree_cur *cur,
const union xfs_btree_key *k1,
@@ -283,7 +283,7 @@ const struct xfs_buf_ops xfs_refcountbt_buf_ops = {
.verify_struct = xfs_refcountbt_verify,
};
-STATIC int
+int
xfs_refcountbt_keys_inorder(
struct xfs_btree_cur *cur,
const union xfs_btree_key *k1,
@@ -293,7 +293,7 @@ xfs_refcountbt_keys_inorder(
be32_to_cpu(k2->refc.rc_startblock);
}
-STATIC int
+int
xfs_refcountbt_recs_inorder(
struct xfs_btree_cur *cur,
const union xfs_btree_rec *r1,
@@ -304,7 +304,7 @@ xfs_refcountbt_recs_inorder(
be32_to_cpu(r2->refc.rc_startblock);
}
-STATIC enum xbtree_key_contig
+enum xbtree_key_contig
xfs_refcountbt_keys_contiguous(
struct xfs_btree_cur *cur,
const union xfs_btree_key *key1,
diff --git a/fs/xfs/libxfs/xfs_refcount_btree.h b/fs/xfs/libxfs/xfs_refcount_btree.h
index beb93bef6a81..40eedfae6846 100644
--- a/fs/xfs/libxfs/xfs_refcount_btree.h
+++ b/fs/xfs/libxfs/xfs_refcount_btree.h
@@ -15,6 +15,8 @@ struct xfs_btree_cur;
struct xfs_mount;
struct xfs_perag;
struct xbtree_afakeroot;
+union xfs_btree_key;
+union xfs_btree_rec;
/*
* Btree block header size
@@ -69,4 +71,28 @@ unsigned int xfs_refcountbt_maxlevels_ondisk(void);
int __init xfs_refcountbt_init_cur_cache(void);
void xfs_refcountbt_destroy_cur_cache(void);
+/*
+ * Key and record btree ops. The refcount on-disk key/record format is
+ * identical for the AG refcount btree and the realtime refcount btree, so
+ * these are shared by both.
+ */
+void xfs_refcountbt_init_key_from_rec(union xfs_btree_key *key,
+ const union xfs_btree_rec *rec);
+void xfs_refcountbt_init_high_key_from_rec(union xfs_btree_key *key,
+ const union xfs_btree_rec *rec);
+void xfs_refcountbt_init_rec_from_cur(struct xfs_btree_cur *cur,
+ union xfs_btree_rec *rec);
+int xfs_refcountbt_cmp_key_with_cur(struct xfs_btree_cur *cur,
+ const union xfs_btree_key *key);
+int xfs_refcountbt_cmp_two_keys(struct xfs_btree_cur *cur,
+ const union xfs_btree_key *k1, const union xfs_btree_key *k2,
+ const union xfs_btree_key *mask);
+int xfs_refcountbt_keys_inorder(struct xfs_btree_cur *cur,
+ const union xfs_btree_key *k1, const union xfs_btree_key *k2);
+int xfs_refcountbt_recs_inorder(struct xfs_btree_cur *cur,
+ const union xfs_btree_rec *r1, const union xfs_btree_rec *r2);
+enum xbtree_key_contig xfs_refcountbt_keys_contiguous(struct xfs_btree_cur *cur,
+ const union xfs_btree_key *key1, const union xfs_btree_key *key2,
+ const union xfs_btree_key *mask);
+
#endif /* __XFS_REFCOUNT_BTREE_H__ */
diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c
index 34d218de21a9..14aef87837a9 100644
--- a/fs/xfs/libxfs/xfs_rmap.c
+++ b/fs/xfs/libxfs/xfs_rmap.c
@@ -260,7 +260,7 @@ xfs_rmap_check_irec(
/* Check for a valid fork offset, if applicable. */
if (is_inode && !is_bmbt &&
- !xfs_verify_fileext(mp, irec->rm_offset, irec->rm_blockcount))
+ !xfs_verify_fileext(irec->rm_offset, irec->rm_blockcount))
return __this_address;
return NULL;
@@ -310,7 +310,7 @@ xfs_rtrmap_check_inode_irec(
return __this_address;
if (!xfs_verify_rgbext(rtg, irec->rm_startblock, irec->rm_blockcount))
return __this_address;
- if (!xfs_verify_fileext(mp, irec->rm_offset, irec->rm_blockcount))
+ if (!xfs_verify_fileext(irec->rm_offset, irec->rm_blockcount))
return __this_address;
return NULL;
}
@@ -904,7 +904,6 @@ xfs_rmap_hook_enable(void)
/* Call downstream hooks for a reverse mapping update. */
static inline void
xfs_rmap_update_hook(
- struct xfs_trans *tp,
struct xfs_group *xg,
enum xfs_rmap_intent_type op,
xfs_agblock_t startblock,
@@ -952,7 +951,7 @@ xfs_rmap_hook_setup(
xfs_hook_setup(&hook->rmap_hook, mod_fn);
}
#else
-# define xfs_rmap_update_hook(t, p, o, s, b, u, oi) do { } while (0)
+# define xfs_rmap_update_hook(p, o, s, b, u, oi) do { } while (0)
#endif /* CONFIG_XFS_LIVE_HOOKS */
/*
@@ -975,7 +974,7 @@ xfs_rmap_free(
return 0;
cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
- xfs_rmap_update_hook(tp, pag_group(pag), XFS_RMAP_UNMAP, bno, len,
+ xfs_rmap_update_hook(pag_group(pag), XFS_RMAP_UNMAP, bno, len,
false, oinfo);
error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
@@ -1220,7 +1219,7 @@ xfs_rmap_alloc(
return 0;
cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
- xfs_rmap_update_hook(tp, pag_group(pag), XFS_RMAP_MAP, bno, len, false,
+ xfs_rmap_update_hook(pag_group(pag), XFS_RMAP_MAP, bno, len, false,
oinfo);
error = xfs_rmap_map(cur, bno, len, false, oinfo);
@@ -2721,7 +2720,7 @@ xfs_rmap_finish_one(
if (error)
return error;
- xfs_rmap_update_hook(tp, ri->ri_group, ri->ri_type, bno,
+ xfs_rmap_update_hook(ri->ri_group, ri->ri_type, bno,
ri->ri_bmap.br_blockcount, unwritten, &oinfo);
return 0;
}
diff --git a/fs/xfs/libxfs/xfs_rmap_btree.c b/fs/xfs/libxfs/xfs_rmap_btree.c
index 10b3272238eb..5b283a5ddd13 100644
--- a/fs/xfs/libxfs/xfs_rmap_btree.c
+++ b/fs/xfs/libxfs/xfs_rmap_btree.c
@@ -170,7 +170,7 @@ static inline __be64 ondisk_rec_offset_to_key(const union xfs_btree_rec *rec)
return rec->rmap.rm_offset & ~cpu_to_be64(XFS_RMAP_OFF_UNWRITTEN);
}
-STATIC void
+void
xfs_rmapbt_init_key_from_rec(
union xfs_btree_key *key,
const union xfs_btree_rec *rec)
@@ -187,7 +187,7 @@ xfs_rmapbt_init_key_from_rec(
* the startblock for all records, and if the record is for a data/attr
* fork mapping, we add blockcount-1 to the offset too.
*/
-STATIC void
+void
xfs_rmapbt_init_high_key_from_rec(
union xfs_btree_key *key,
const union xfs_btree_rec *rec)
@@ -209,7 +209,7 @@ xfs_rmapbt_init_high_key_from_rec(
key->rmap.rm_offset = cpu_to_be64(off);
}
-STATIC void
+void
xfs_rmapbt_init_rec_from_cur(
struct xfs_btree_cur *cur,
union xfs_btree_rec *rec)
@@ -243,7 +243,7 @@ static inline uint64_t offset_keymask(uint64_t offset)
return offset & ~XFS_RMAP_OFF_UNWRITTEN;
}
-STATIC int
+int
xfs_rmapbt_cmp_key_with_cur(
struct xfs_btree_cur *cur,
const union xfs_btree_key *key)
@@ -257,7 +257,7 @@ xfs_rmapbt_cmp_key_with_cur(
offset_keymask(xfs_rmap_irec_offset_pack(rec)));
}
-STATIC int
+int
xfs_rmapbt_cmp_two_keys(
struct xfs_btree_cur *cur,
const union xfs_btree_key *k1,
@@ -390,7 +390,7 @@ const struct xfs_buf_ops xfs_rmapbt_buf_ops = {
.verify_struct = xfs_rmapbt_verify,
};
-STATIC int
+int
xfs_rmapbt_keys_inorder(
struct xfs_btree_cur *cur,
const union xfs_btree_key *k1,
@@ -420,7 +420,7 @@ xfs_rmapbt_keys_inorder(
return 0;
}
-STATIC int
+int
xfs_rmapbt_recs_inorder(
struct xfs_btree_cur *cur,
const union xfs_btree_rec *r1,
@@ -450,7 +450,7 @@ xfs_rmapbt_recs_inorder(
return 0;
}
-STATIC enum xbtree_key_contig
+enum xbtree_key_contig
xfs_rmapbt_keys_contiguous(
struct xfs_btree_cur *cur,
const union xfs_btree_key *key1,
diff --git a/fs/xfs/libxfs/xfs_rmap_btree.h b/fs/xfs/libxfs/xfs_rmap_btree.h
index 119b1567cd0e..7071dac745e1 100644
--- a/fs/xfs/libxfs/xfs_rmap_btree.h
+++ b/fs/xfs/libxfs/xfs_rmap_btree.h
@@ -11,6 +11,8 @@ struct xfs_btree_cur;
struct xfs_mount;
struct xbtree_afakeroot;
struct xfbtree;
+union xfs_btree_key;
+union xfs_btree_rec;
/* rmaps only exist on crc enabled filesystems */
#define XFS_RMAP_BLOCK_LEN XFS_BTREE_SBLOCK_CRC_LEN
@@ -69,4 +71,28 @@ struct xfs_btree_cur *xfs_rmapbt_mem_cursor(struct xfs_perag *pag,
int xfs_rmapbt_mem_init(struct xfs_mount *mp, struct xfbtree *xfbtree,
struct xfs_buftarg *btp, xfs_agnumber_t agno);
+/*
+ * Key and record btree ops. The rmap on-disk key/record format is identical
+ * for the AG rmap btree and the realtime rmap btree, so these are shared by
+ * both.
+ */
+void xfs_rmapbt_init_key_from_rec(union xfs_btree_key *key,
+ const union xfs_btree_rec *rec);
+void xfs_rmapbt_init_high_key_from_rec(union xfs_btree_key *key,
+ const union xfs_btree_rec *rec);
+void xfs_rmapbt_init_rec_from_cur(struct xfs_btree_cur *cur,
+ union xfs_btree_rec *rec);
+int xfs_rmapbt_cmp_key_with_cur(struct xfs_btree_cur *cur,
+ const union xfs_btree_key *key);
+int xfs_rmapbt_cmp_two_keys(struct xfs_btree_cur *cur,
+ const union xfs_btree_key *k1, const union xfs_btree_key *k2,
+ const union xfs_btree_key *mask);
+int xfs_rmapbt_keys_inorder(struct xfs_btree_cur *cur,
+ const union xfs_btree_key *k1, const union xfs_btree_key *k2);
+int xfs_rmapbt_recs_inorder(struct xfs_btree_cur *cur,
+ const union xfs_btree_rec *r1, const union xfs_btree_rec *r2);
+enum xbtree_key_contig xfs_rmapbt_keys_contiguous(struct xfs_btree_cur *cur,
+ const union xfs_btree_key *key1, const union xfs_btree_key *key2,
+ const union xfs_btree_key *mask);
+
#endif /* __XFS_RMAP_BTREE_H__ */
diff --git a/fs/xfs/libxfs/xfs_rtrefcount_btree.c b/fs/xfs/libxfs/xfs_rtrefcount_btree.c
index dcc89b8e149b..697f5e622685 100644
--- a/fs/xfs/libxfs/xfs_rtrefcount_btree.c
+++ b/fs/xfs/libxfs/xfs_rtrefcount_btree.c
@@ -20,6 +20,7 @@
#include "xfs_btree_staging.h"
#include "xfs_rtrefcount_btree.h"
#include "xfs_refcount.h"
+#include "xfs_refcount_btree.h"
#include "xfs_trace.h"
#include "xfs_cksum.h"
#include "xfs_error.h"
@@ -114,41 +115,6 @@ xfs_rtrefcountbt_get_dmaxrecs(
}
STATIC void
-xfs_rtrefcountbt_init_key_from_rec(
- union xfs_btree_key *key,
- const union xfs_btree_rec *rec)
-{
- key->refc.rc_startblock = rec->refc.rc_startblock;
-}
-
-STATIC void
-xfs_rtrefcountbt_init_high_key_from_rec(
- union xfs_btree_key *key,
- const union xfs_btree_rec *rec)
-{
- __u32 x;
-
- x = be32_to_cpu(rec->refc.rc_startblock);
- x += be32_to_cpu(rec->refc.rc_blockcount) - 1;
- key->refc.rc_startblock = cpu_to_be32(x);
-}
-
-STATIC void
-xfs_rtrefcountbt_init_rec_from_cur(
- struct xfs_btree_cur *cur,
- union xfs_btree_rec *rec)
-{
- const struct xfs_refcount_irec *irec = &cur->bc_rec.rc;
- uint32_t start;
-
- start = xfs_refcount_encode_startblock(irec->rc_startblock,
- irec->rc_domain);
- rec->refc.rc_startblock = cpu_to_be32(start);
- rec->refc.rc_blockcount = cpu_to_be32(cur->bc_rec.rc.rc_blockcount);
- rec->refc.rc_refcount = cpu_to_be32(cur->bc_rec.rc.rc_refcount);
-}
-
-STATIC void
xfs_rtrefcountbt_init_ptr_from_cur(
struct xfs_btree_cur *cur,
union xfs_btree_ptr *ptr)
@@ -156,33 +122,6 @@ xfs_rtrefcountbt_init_ptr_from_cur(
ptr->l = 0;
}
-STATIC int
-xfs_rtrefcountbt_cmp_key_with_cur(
- struct xfs_btree_cur *cur,
- const union xfs_btree_key *key)
-{
- const struct xfs_refcount_key *kp = &key->refc;
- const struct xfs_refcount_irec *irec = &cur->bc_rec.rc;
- uint32_t start;
-
- start = xfs_refcount_encode_startblock(irec->rc_startblock,
- irec->rc_domain);
- return cmp_int(be32_to_cpu(kp->rc_startblock), start);
-}
-
-STATIC int
-xfs_rtrefcountbt_cmp_two_keys(
- struct xfs_btree_cur *cur,
- const union xfs_btree_key *k1,
- const union xfs_btree_key *k2,
- const union xfs_btree_key *mask)
-{
- ASSERT(!mask || mask->refc.rc_startblock);
-
- return cmp_int(be32_to_cpu(k1->refc.rc_startblock),
- be32_to_cpu(k2->refc.rc_startblock));
-}
-
static xfs_failaddr_t
xfs_rtrefcountbt_verify(
struct xfs_buf *bp)
@@ -249,40 +188,6 @@ const struct xfs_buf_ops xfs_rtrefcountbt_buf_ops = {
.verify_struct = xfs_rtrefcountbt_verify,
};
-STATIC int
-xfs_rtrefcountbt_keys_inorder(
- struct xfs_btree_cur *cur,
- const union xfs_btree_key *k1,
- const union xfs_btree_key *k2)
-{
- return be32_to_cpu(k1->refc.rc_startblock) <
- be32_to_cpu(k2->refc.rc_startblock);
-}
-
-STATIC int
-xfs_rtrefcountbt_recs_inorder(
- struct xfs_btree_cur *cur,
- const union xfs_btree_rec *r1,
- const union xfs_btree_rec *r2)
-{
- return be32_to_cpu(r1->refc.rc_startblock) +
- be32_to_cpu(r1->refc.rc_blockcount) <=
- be32_to_cpu(r2->refc.rc_startblock);
-}
-
-STATIC enum xbtree_key_contig
-xfs_rtrefcountbt_keys_contiguous(
- struct xfs_btree_cur *cur,
- const union xfs_btree_key *key1,
- const union xfs_btree_key *key2,
- const union xfs_btree_key *mask)
-{
- ASSERT(!mask || mask->refc.rc_startblock);
-
- return xbtree_key_contig(be32_to_cpu(key1->refc.rc_startblock),
- be32_to_cpu(key2->refc.rc_startblock));
-}
-
static inline void
xfs_rtrefcountbt_move_ptrs(
struct xfs_mount *mp,
@@ -311,7 +216,7 @@ xfs_rtrefcountbt_broot_realloc(
unsigned int old_size = ifp->if_broot_bytes;
const unsigned int level = cur->bc_nlevels - 1;
- new_size = xfs_rtrefcount_broot_space_calc(mp, level, new_numrecs);
+ new_size = xfs_rtrefcount_broot_space_calc(level, new_numrecs);
/* Handle the nop case quietly. */
if (new_size == old_size)
@@ -383,16 +288,16 @@ const struct xfs_btree_ops xfs_rtrefcountbt_ops = {
.get_minrecs = xfs_rtrefcountbt_get_minrecs,
.get_maxrecs = xfs_rtrefcountbt_get_maxrecs,
.get_dmaxrecs = xfs_rtrefcountbt_get_dmaxrecs,
- .init_key_from_rec = xfs_rtrefcountbt_init_key_from_rec,
- .init_high_key_from_rec = xfs_rtrefcountbt_init_high_key_from_rec,
- .init_rec_from_cur = xfs_rtrefcountbt_init_rec_from_cur,
+ .init_key_from_rec = xfs_refcountbt_init_key_from_rec,
+ .init_high_key_from_rec = xfs_refcountbt_init_high_key_from_rec,
+ .init_rec_from_cur = xfs_refcountbt_init_rec_from_cur,
.init_ptr_from_cur = xfs_rtrefcountbt_init_ptr_from_cur,
- .cmp_key_with_cur = xfs_rtrefcountbt_cmp_key_with_cur,
+ .cmp_key_with_cur = xfs_refcountbt_cmp_key_with_cur,
.buf_ops = &xfs_rtrefcountbt_buf_ops,
- .cmp_two_keys = xfs_rtrefcountbt_cmp_two_keys,
- .keys_inorder = xfs_rtrefcountbt_keys_inorder,
- .recs_inorder = xfs_rtrefcountbt_recs_inorder,
- .keys_contiguous = xfs_rtrefcountbt_keys_contiguous,
+ .cmp_two_keys = xfs_refcountbt_cmp_two_keys,
+ .keys_inorder = xfs_refcountbt_keys_inorder,
+ .recs_inorder = xfs_refcountbt_recs_inorder,
+ .keys_contiguous = xfs_refcountbt_keys_contiguous,
.broot_realloc = xfs_rtrefcountbt_broot_realloc,
};
@@ -602,7 +507,7 @@ xfs_rtrefcountbt_from_disk(
unsigned int maxrecs;
unsigned int rblocklen;
- rblocklen = xfs_rtrefcount_broot_space(mp, dblock);
+ rblocklen = xfs_rtrefcount_broot_space(dblock);
xfs_btree_init_block(mp, rblock, &xfs_rtrefcountbt_ops, 0, 0,
I_INO(ip));
@@ -661,7 +566,7 @@ xfs_iformat_rtrefcount(
}
broot = xfs_broot_alloc(xfs_ifork_ptr(ip, XFS_DATA_FORK),
- xfs_rtrefcount_broot_space_calc(mp, level, numrecs));
+ xfs_rtrefcount_broot_space_calc(level, numrecs));
if (broot)
xfs_rtrefcountbt_from_disk(ip, dfp, dsize, broot);
return 0;
@@ -751,7 +656,7 @@ xfs_rtrefcountbt_create(
/* Initialize the empty incore btree root. */
broot = xfs_broot_realloc(ifp,
- xfs_rtrefcount_broot_space_calc(mp, 0, 0));
+ xfs_rtrefcount_broot_space_calc(0, 0));
if (broot)
xfs_btree_init_block(mp, broot, &xfs_rtrefcountbt_ops, 0, 0,
I_INO(ip));
diff --git a/fs/xfs/libxfs/xfs_rtrefcount_btree.h b/fs/xfs/libxfs/xfs_rtrefcount_btree.h
index a99b7a8aec86..9ab6ecf90ba5 100644
--- a/fs/xfs/libxfs/xfs_rtrefcount_btree.h
+++ b/fs/xfs/libxfs/xfs_rtrefcount_btree.h
@@ -129,7 +129,6 @@ xfs_rtrefcount_broot_ptr_addr(
*/
static inline size_t
xfs_rtrefcount_broot_space_calc(
- struct xfs_mount *mp,
unsigned int level,
unsigned int nrecs)
{
@@ -146,9 +145,9 @@ xfs_rtrefcount_broot_space_calc(
* btree root block.
*/
static inline size_t
-xfs_rtrefcount_broot_space(struct xfs_mount *mp, struct xfs_rtrefcount_root *bb)
+xfs_rtrefcount_broot_space(struct xfs_rtrefcount_root *bb)
{
- return xfs_rtrefcount_broot_space_calc(mp, be16_to_cpu(bb->bb_level),
+ return xfs_rtrefcount_broot_space_calc(be16_to_cpu(bb->bb_level),
be16_to_cpu(bb->bb_numrecs));
}
diff --git a/fs/xfs/libxfs/xfs_rtrmap_btree.c b/fs/xfs/libxfs/xfs_rtrmap_btree.c
index a15e460a1ec7..2f00d0698ae1 100644
--- a/fs/xfs/libxfs/xfs_rtrmap_btree.c
+++ b/fs/xfs/libxfs/xfs_rtrmap_btree.c
@@ -20,6 +20,7 @@
#include "xfs_btree_staging.h"
#include "xfs_metafile.h"
#include "xfs_rmap.h"
+#include "xfs_rmap_btree.h"
#include "xfs_rtrmap_btree.h"
#include "xfs_trace.h"
#include "xfs_cksum.h"
@@ -113,60 +114,6 @@ xfs_rtrmapbt_get_dmaxrecs(
return xfs_rtrmapbt_droot_maxrecs(cur->bc_ino.forksize, level == 0);
}
-/*
- * Convert the ondisk record's offset field into the ondisk key's offset field.
- * Fork and bmbt are significant parts of the rmap record key, but written
- * status is merely a record attribute.
- */
-static inline __be64 ondisk_rec_offset_to_key(const union xfs_btree_rec *rec)
-{
- return rec->rmap.rm_offset & ~cpu_to_be64(XFS_RMAP_OFF_UNWRITTEN);
-}
-
-STATIC void
-xfs_rtrmapbt_init_key_from_rec(
- union xfs_btree_key *key,
- const union xfs_btree_rec *rec)
-{
- key->rmap.rm_startblock = rec->rmap.rm_startblock;
- key->rmap.rm_owner = rec->rmap.rm_owner;
- key->rmap.rm_offset = ondisk_rec_offset_to_key(rec);
-}
-
-STATIC void
-xfs_rtrmapbt_init_high_key_from_rec(
- union xfs_btree_key *key,
- const union xfs_btree_rec *rec)
-{
- uint64_t off;
- int adj;
-
- adj = be32_to_cpu(rec->rmap.rm_blockcount) - 1;
-
- key->rmap.rm_startblock = rec->rmap.rm_startblock;
- be32_add_cpu(&key->rmap.rm_startblock, adj);
- key->rmap.rm_owner = rec->rmap.rm_owner;
- key->rmap.rm_offset = ondisk_rec_offset_to_key(rec);
- if (XFS_RMAP_NON_INODE_OWNER(be64_to_cpu(rec->rmap.rm_owner)) ||
- XFS_RMAP_IS_BMBT_BLOCK(be64_to_cpu(rec->rmap.rm_offset)))
- return;
- off = be64_to_cpu(key->rmap.rm_offset);
- off = (XFS_RMAP_OFF(off) + adj) | (off & ~XFS_RMAP_OFF_MASK);
- key->rmap.rm_offset = cpu_to_be64(off);
-}
-
-STATIC void
-xfs_rtrmapbt_init_rec_from_cur(
- struct xfs_btree_cur *cur,
- union xfs_btree_rec *rec)
-{
- rec->rmap.rm_startblock = cpu_to_be32(cur->bc_rec.r.rm_startblock);
- rec->rmap.rm_blockcount = cpu_to_be32(cur->bc_rec.r.rm_blockcount);
- rec->rmap.rm_owner = cpu_to_be64(cur->bc_rec.r.rm_owner);
- rec->rmap.rm_offset = cpu_to_be64(
- xfs_rmap_irec_offset_pack(&cur->bc_rec.r));
-}
-
STATIC void
xfs_rtrmapbt_init_ptr_from_cur(
struct xfs_btree_cur *cur,
@@ -175,69 +122,6 @@ xfs_rtrmapbt_init_ptr_from_cur(
ptr->l = 0;
}
-/*
- * Mask the appropriate parts of the ondisk key field for a key comparison.
- * Fork and bmbt are significant parts of the rmap record key, but written
- * status is merely a record attribute.
- */
-static inline uint64_t offset_keymask(uint64_t offset)
-{
- return offset & ~XFS_RMAP_OFF_UNWRITTEN;
-}
-
-STATIC int
-xfs_rtrmapbt_cmp_key_with_cur(
- struct xfs_btree_cur *cur,
- const union xfs_btree_key *key)
-{
- struct xfs_rmap_irec *rec = &cur->bc_rec.r;
- const struct xfs_rmap_key *kp = &key->rmap;
-
- return cmp_int(be32_to_cpu(kp->rm_startblock), rec->rm_startblock) ?:
- cmp_int(be64_to_cpu(kp->rm_owner), rec->rm_owner) ?:
- cmp_int(offset_keymask(be64_to_cpu(kp->rm_offset)),
- offset_keymask(xfs_rmap_irec_offset_pack(rec)));
-}
-
-STATIC int
-xfs_rtrmapbt_cmp_two_keys(
- struct xfs_btree_cur *cur,
- const union xfs_btree_key *k1,
- const union xfs_btree_key *k2,
- const union xfs_btree_key *mask)
-{
- const struct xfs_rmap_key *kp1 = &k1->rmap;
- const struct xfs_rmap_key *kp2 = &k2->rmap;
- int d;
-
- /* Doesn't make sense to mask off the physical space part */
- ASSERT(!mask || mask->rmap.rm_startblock);
-
- d = cmp_int(be32_to_cpu(kp1->rm_startblock),
- be32_to_cpu(kp2->rm_startblock));
- if (d)
- return d;
-
- if (!mask || mask->rmap.rm_owner) {
- d = cmp_int(be64_to_cpu(kp1->rm_owner),
- be64_to_cpu(kp2->rm_owner));
- if (d)
- return d;
- }
-
- if (!mask || mask->rmap.rm_offset) {
- /* Doesn't make sense to allow offset but not owner */
- ASSERT(!mask || mask->rmap.rm_owner);
-
- d = cmp_int(offset_keymask(be64_to_cpu(kp1->rm_offset)),
- offset_keymask(be64_to_cpu(kp2->rm_offset)));
- if (d)
- return d;
- }
-
- return 0;
-}
-
static xfs_failaddr_t
xfs_rtrmapbt_verify(
struct xfs_buf *bp)
@@ -304,86 +188,6 @@ const struct xfs_buf_ops xfs_rtrmapbt_buf_ops = {
.verify_struct = xfs_rtrmapbt_verify,
};
-STATIC int
-xfs_rtrmapbt_keys_inorder(
- struct xfs_btree_cur *cur,
- const union xfs_btree_key *k1,
- const union xfs_btree_key *k2)
-{
- uint32_t x;
- uint32_t y;
- uint64_t a;
- uint64_t b;
-
- x = be32_to_cpu(k1->rmap.rm_startblock);
- y = be32_to_cpu(k2->rmap.rm_startblock);
- if (x < y)
- return 1;
- else if (x > y)
- return 0;
- a = be64_to_cpu(k1->rmap.rm_owner);
- b = be64_to_cpu(k2->rmap.rm_owner);
- if (a < b)
- return 1;
- else if (a > b)
- return 0;
- a = offset_keymask(be64_to_cpu(k1->rmap.rm_offset));
- b = offset_keymask(be64_to_cpu(k2->rmap.rm_offset));
- if (a <= b)
- return 1;
- return 0;
-}
-
-STATIC int
-xfs_rtrmapbt_recs_inorder(
- struct xfs_btree_cur *cur,
- const union xfs_btree_rec *r1,
- const union xfs_btree_rec *r2)
-{
- uint32_t x;
- uint32_t y;
- uint64_t a;
- uint64_t b;
-
- x = be32_to_cpu(r1->rmap.rm_startblock);
- y = be32_to_cpu(r2->rmap.rm_startblock);
- if (x < y)
- return 1;
- else if (x > y)
- return 0;
- a = be64_to_cpu(r1->rmap.rm_owner);
- b = be64_to_cpu(r2->rmap.rm_owner);
- if (a < b)
- return 1;
- else if (a > b)
- return 0;
- a = offset_keymask(be64_to_cpu(r1->rmap.rm_offset));
- b = offset_keymask(be64_to_cpu(r2->rmap.rm_offset));
- if (a <= b)
- return 1;
- return 0;
-}
-
-STATIC enum xbtree_key_contig
-xfs_rtrmapbt_keys_contiguous(
- struct xfs_btree_cur *cur,
- const union xfs_btree_key *key1,
- const union xfs_btree_key *key2,
- const union xfs_btree_key *mask)
-{
- ASSERT(!mask || mask->rmap.rm_startblock);
-
- /*
- * We only support checking contiguity of the physical space component.
- * If any callers ever need more specificity than that, they'll have to
- * implement it here.
- */
- ASSERT(!mask || (!mask->rmap.rm_owner && !mask->rmap.rm_offset));
-
- return xbtree_key_contig(be32_to_cpu(key1->rmap.rm_startblock),
- be32_to_cpu(key2->rmap.rm_startblock));
-}
-
static inline void
xfs_rtrmapbt_move_ptrs(
struct xfs_mount *mp,
@@ -412,7 +216,7 @@ xfs_rtrmapbt_broot_realloc(
unsigned int old_size = ifp->if_broot_bytes;
const unsigned int level = cur->bc_nlevels - 1;
- new_size = xfs_rtrmap_broot_space_calc(mp, level, new_numrecs);
+ new_size = xfs_rtrmap_broot_space_calc(level, new_numrecs);
/* Handle the nop case quietly. */
if (new_size == old_size)
@@ -486,16 +290,16 @@ const struct xfs_btree_ops xfs_rtrmapbt_ops = {
.get_minrecs = xfs_rtrmapbt_get_minrecs,
.get_maxrecs = xfs_rtrmapbt_get_maxrecs,
.get_dmaxrecs = xfs_rtrmapbt_get_dmaxrecs,
- .init_key_from_rec = xfs_rtrmapbt_init_key_from_rec,
- .init_high_key_from_rec = xfs_rtrmapbt_init_high_key_from_rec,
- .init_rec_from_cur = xfs_rtrmapbt_init_rec_from_cur,
+ .init_key_from_rec = xfs_rmapbt_init_key_from_rec,
+ .init_high_key_from_rec = xfs_rmapbt_init_high_key_from_rec,
+ .init_rec_from_cur = xfs_rmapbt_init_rec_from_cur,
.init_ptr_from_cur = xfs_rtrmapbt_init_ptr_from_cur,
- .cmp_key_with_cur = xfs_rtrmapbt_cmp_key_with_cur,
+ .cmp_key_with_cur = xfs_rmapbt_cmp_key_with_cur,
.buf_ops = &xfs_rtrmapbt_buf_ops,
- .cmp_two_keys = xfs_rtrmapbt_cmp_two_keys,
- .keys_inorder = xfs_rtrmapbt_keys_inorder,
- .recs_inorder = xfs_rtrmapbt_recs_inorder,
- .keys_contiguous = xfs_rtrmapbt_keys_contiguous,
+ .cmp_two_keys = xfs_rmapbt_cmp_two_keys,
+ .keys_inorder = xfs_rmapbt_keys_inorder,
+ .recs_inorder = xfs_rmapbt_recs_inorder,
+ .keys_contiguous = xfs_rmapbt_keys_contiguous,
.broot_realloc = xfs_rtrmapbt_broot_realloc,
};
@@ -595,16 +399,16 @@ const struct xfs_btree_ops xfs_rtrmapbt_mem_ops = {
.free_block = xfbtree_free_block,
.get_minrecs = xfbtree_get_minrecs,
.get_maxrecs = xfbtree_get_maxrecs,
- .init_key_from_rec = xfs_rtrmapbt_init_key_from_rec,
- .init_high_key_from_rec = xfs_rtrmapbt_init_high_key_from_rec,
- .init_rec_from_cur = xfs_rtrmapbt_init_rec_from_cur,
+ .init_key_from_rec = xfs_rmapbt_init_key_from_rec,
+ .init_high_key_from_rec = xfs_rmapbt_init_high_key_from_rec,
+ .init_rec_from_cur = xfs_rmapbt_init_rec_from_cur,
.init_ptr_from_cur = xfbtree_init_ptr_from_cur,
- .cmp_key_with_cur = xfs_rtrmapbt_cmp_key_with_cur,
+ .cmp_key_with_cur = xfs_rmapbt_cmp_key_with_cur,
.buf_ops = &xfs_rtrmapbt_mem_buf_ops,
- .cmp_two_keys = xfs_rtrmapbt_cmp_two_keys,
- .keys_inorder = xfs_rtrmapbt_keys_inorder,
- .recs_inorder = xfs_rtrmapbt_recs_inorder,
- .keys_contiguous = xfs_rtrmapbt_keys_contiguous,
+ .cmp_two_keys = xfs_rmapbt_cmp_two_keys,
+ .keys_inorder = xfs_rmapbt_keys_inorder,
+ .recs_inorder = xfs_rmapbt_recs_inorder,
+ .keys_contiguous = xfs_rmapbt_keys_contiguous,
};
/* Create a cursor for an in-memory btree. */
@@ -895,7 +699,7 @@ xfs_iformat_rtrmap(
}
broot = xfs_broot_alloc(xfs_ifork_ptr(ip, XFS_DATA_FORK),
- xfs_rtrmap_broot_space_calc(mp, level, numrecs));
+ xfs_rtrmap_broot_space_calc(level, numrecs));
if (broot)
xfs_rtrmapbt_from_disk(ip, dfp, dsize, broot);
return 0;
@@ -980,7 +784,7 @@ xfs_rtrmapbt_create(
ASSERT(ifp->if_bytes == 0);
/* Initialize the empty incore btree root. */
- broot = xfs_broot_realloc(ifp, xfs_rtrmap_broot_space_calc(mp, 0, 0));
+ broot = xfs_broot_realloc(ifp, xfs_rtrmap_broot_space_calc(0, 0));
if (broot)
xfs_btree_init_block(mp, broot, &xfs_rtrmapbt_ops, 0, 0,
I_INO(ip));
diff --git a/fs/xfs/libxfs/xfs_rtrmap_btree.h b/fs/xfs/libxfs/xfs_rtrmap_btree.h
index e328fd62a149..c59a144b4bbf 100644
--- a/fs/xfs/libxfs/xfs_rtrmap_btree.h
+++ b/fs/xfs/libxfs/xfs_rtrmap_btree.h
@@ -140,7 +140,6 @@ xfs_rtrmap_broot_ptr_addr(
*/
static inline size_t
xfs_rtrmap_broot_space_calc(
- struct xfs_mount *mp,
unsigned int level,
unsigned int nrecs)
{
@@ -159,7 +158,7 @@ xfs_rtrmap_broot_space_calc(
static inline size_t
xfs_rtrmap_broot_space(struct xfs_mount *mp, struct xfs_rtrmap_root *bb)
{
- return xfs_rtrmap_broot_space_calc(mp, be16_to_cpu(bb->bb_level),
+ return xfs_rtrmap_broot_space_calc(be16_to_cpu(bb->bb_level),
be16_to_cpu(bb->bb_numrecs));
}
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
index f0341adbb879..d2ef7b20a49f 100644
--- a/fs/xfs/libxfs/xfs_sb.c
+++ b/fs/xfs/libxfs/xfs_sb.c
@@ -1460,46 +1460,6 @@ xfs_update_secondary_sbs(
return saved_error ? saved_error : error;
}
-/*
- * Same behavior as xfs_sync_sb, except that it is always synchronous and it
- * also writes the superblock buffer to disk sector 0 immediately.
- */
-int
-xfs_sync_sb_buf(
- struct xfs_mount *mp,
- bool update_rtsb)
-{
- struct xfs_trans *tp;
- int error;
-
- error = xfs_trans_alloc(mp, &M_RES(mp)->tr_sb, 0, 0, 0, &tp);
- if (error)
- return error;
-
- xfs_log_sb(tp);
- if (update_rtsb)
- xfs_log_rtsb(tp, xfs_trans_getsb(tp));
- xfs_trans_set_sync(tp);
- error = xfs_trans_commit(tp);
- if (error)
- return error;
-
- /* Re-acquire and write the sb and rtsb to disk. */
- xfs_buf_lock(mp->m_sb_bp);
- error = xfs_bwrite(mp->m_sb_bp);
- xfs_buf_unlock(mp->m_sb_bp);
- if (error)
- return error;
-
- if (update_rtsb && mp->m_rtsb_bp) {
- xfs_buf_lock(mp->m_rtsb_bp);
- error = xfs_bwrite(mp->m_rtsb_bp);
- xfs_buf_unlock(mp->m_rtsb_bp);
- }
-
- return error;
-}
-
void
xfs_fs_geometry(
struct xfs_mount *mp,
diff --git a/fs/xfs/libxfs/xfs_sb.h b/fs/xfs/libxfs/xfs_sb.h
index 34d0dd374e9b..77de65922213 100644
--- a/fs/xfs/libxfs/xfs_sb.h
+++ b/fs/xfs/libxfs/xfs_sb.h
@@ -15,7 +15,6 @@ struct xfs_perag;
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_buf(struct xfs_mount *mp, bool update_rtsb);
extern void xfs_sb_mount_common(struct xfs_mount *mp, struct xfs_sb *sbp);
void xfs_sb_mount_rextsize(struct xfs_mount *mp, struct xfs_sb *sbp);
void xfs_mount_sb_set_rextsize(struct xfs_mount *mp,
diff --git a/fs/xfs/libxfs/xfs_symlink_remote.c b/fs/xfs/libxfs/xfs_symlink_remote.c
index b0dc3888bf1b..0201a3d59b1a 100644
--- a/fs/xfs/libxfs/xfs_symlink_remote.c
+++ b/fs/xfs/libxfs/xfs_symlink_remote.c
@@ -208,11 +208,15 @@ xfs_symlink_local_to_remote(
*/
xfs_failaddr_t
xfs_symlink_shortform_verify(
- void *sfp,
- int64_t size)
+ struct xfs_inode *ip)
{
+ struct xfs_ifork *ifp = xfs_ifork_ptr(ip, XFS_DATA_FORK);
+ char *sfp = (char *)ifp->if_data;
+ int size = ifp->if_bytes;
char *endp = sfp + size;
+ ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
+
/*
* Zero length symlinks should never occur in memory as they are
* never allowed to exist on disk.
diff --git a/fs/xfs/libxfs/xfs_symlink_remote.h b/fs/xfs/libxfs/xfs_symlink_remote.h
index c1672fe1f17b..3f6590602473 100644
--- a/fs/xfs/libxfs/xfs_symlink_remote.h
+++ b/fs/xfs/libxfs/xfs_symlink_remote.h
@@ -18,7 +18,7 @@ bool xfs_symlink_hdr_ok(xfs_ino_t ino, uint32_t offset,
void xfs_symlink_local_to_remote(struct xfs_trans *tp, struct xfs_buf *bp,
struct xfs_inode *ip, struct xfs_ifork *ifp,
void *priv);
-xfs_failaddr_t xfs_symlink_shortform_verify(void *sfp, int64_t size);
+xfs_failaddr_t xfs_symlink_shortform_verify(struct xfs_inode *ip);
int xfs_symlink_remote_read(struct xfs_inode *ip, char *link);
int xfs_symlink_write_target(struct xfs_trans *tp, struct xfs_inode *ip,
xfs_ino_t owner, const char *target_path, int pathlen,
diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c
index 3151e97ca8ff..b09c88aec185 100644
--- a/fs/xfs/libxfs/xfs_trans_resv.c
+++ b/fs/xfs/libxfs/xfs_trans_resv.c
@@ -606,10 +606,10 @@ static inline unsigned int xfs_calc_pptr_replace_overhead(void)
*/
STATIC uint
xfs_calc_rename_reservation(
- struct xfs_mount *mp)
+ struct xfs_mount *mp,
+ struct xfs_trans_resv *resp)
{
unsigned int overhead = XFS_DQUOT_LOGRES;
- struct xfs_trans_resv *resp = M_RES(mp);
unsigned int t1, t2, t3 = 0;
t1 = xfs_calc_inode_res(mp, 5) +
@@ -715,10 +715,10 @@ xfs_link_log_count(
*/
STATIC uint
xfs_calc_link_reservation(
- struct xfs_mount *mp)
+ struct xfs_mount *mp,
+ struct xfs_trans_resv *resp)
{
unsigned int overhead = XFS_DQUOT_LOGRES;
- struct xfs_trans_resv *resp = M_RES(mp);
unsigned int t1, t2, t3 = 0;
overhead += xfs_calc_iunlink_remove_reservation(mp);
@@ -777,10 +777,10 @@ xfs_remove_log_count(
*/
STATIC uint
xfs_calc_remove_reservation(
- struct xfs_mount *mp)
+ struct xfs_mount *mp,
+ struct xfs_trans_resv *resp)
{
unsigned int overhead = XFS_DQUOT_LOGRES;
- struct xfs_trans_resv *resp = M_RES(mp);
unsigned int t1, t2, t3 = 0;
overhead += xfs_calc_iunlink_add_reservation(mp);
@@ -862,9 +862,9 @@ xfs_icreate_log_count(
STATIC uint
xfs_calc_icreate_reservation(
- struct xfs_mount *mp)
+ struct xfs_mount *mp,
+ struct xfs_trans_resv *resp)
{
- struct xfs_trans_resv *resp = M_RES(mp);
unsigned int overhead = XFS_DQUOT_LOGRES;
unsigned int t1, t2, t3 = 0;
@@ -911,9 +911,10 @@ xfs_mkdir_log_count(
*/
STATIC uint
xfs_calc_mkdir_reservation(
- struct xfs_mount *mp)
+ struct xfs_mount *mp,
+ struct xfs_trans_resv *resp)
{
- return xfs_calc_icreate_reservation(mp);
+ return xfs_calc_icreate_reservation(mp, resp);
}
static inline unsigned int
@@ -940,9 +941,10 @@ xfs_symlink_log_count(
*/
STATIC uint
xfs_calc_symlink_reservation(
- struct xfs_mount *mp)
+ struct xfs_mount *mp,
+ struct xfs_trans_resv *resp)
{
- return xfs_calc_icreate_reservation(mp) +
+ return xfs_calc_icreate_reservation(mp, resp) +
xfs_calc_buf_res(1, XFS_SYMLINK_MAXLEN);
}
@@ -1265,34 +1267,33 @@ xfs_calc_namespace_reservations(
{
ASSERT(resp->tr_attrsetm.tr_logres > 0);
- resp->tr_rename.tr_logres = xfs_calc_rename_reservation(mp);
+ resp->tr_rename.tr_logres = xfs_calc_rename_reservation(mp, resp);
resp->tr_rename.tr_logcount = xfs_rename_log_count(mp, resp);
resp->tr_rename.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
- resp->tr_link.tr_logres = xfs_calc_link_reservation(mp);
+ resp->tr_link.tr_logres = xfs_calc_link_reservation(mp, resp);
resp->tr_link.tr_logcount = xfs_link_log_count(mp, resp);
resp->tr_link.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
- resp->tr_remove.tr_logres = xfs_calc_remove_reservation(mp);
+ resp->tr_remove.tr_logres = xfs_calc_remove_reservation(mp, resp);
resp->tr_remove.tr_logcount = xfs_remove_log_count(mp, resp);
resp->tr_remove.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
- resp->tr_symlink.tr_logres = xfs_calc_symlink_reservation(mp);
+ resp->tr_symlink.tr_logres = xfs_calc_symlink_reservation(mp, resp);
resp->tr_symlink.tr_logcount = xfs_symlink_log_count(mp, resp);
resp->tr_symlink.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
- resp->tr_create.tr_logres = xfs_calc_icreate_reservation(mp);
+ resp->tr_create.tr_logres = xfs_calc_icreate_reservation(mp, resp);
resp->tr_create.tr_logcount = xfs_icreate_log_count(mp, resp);
resp->tr_create.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
- resp->tr_mkdir.tr_logres = xfs_calc_mkdir_reservation(mp);
+ resp->tr_mkdir.tr_logres = xfs_calc_mkdir_reservation(mp, resp);
resp->tr_mkdir.tr_logcount = xfs_mkdir_log_count(mp, resp);
resp->tr_mkdir.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
}
STATIC void
xfs_calc_default_atomic_ioend_reservation(
- struct xfs_mount *mp,
struct xfs_trans_resv *resp)
{
/* Pick a default that will scale reasonably for the log size. */
@@ -1398,7 +1399,7 @@ xfs_trans_resv_calc(
* Now that we've finished computing the static reservations, we can
* compute the dynamic reservation for atomic writes.
*/
- xfs_calc_default_atomic_ioend_reservation(mp, resp);
+ xfs_calc_default_atomic_ioend_reservation(resp);
}
/*
@@ -1508,7 +1509,7 @@ xfs_calc_atomic_write_log_geometry(
ASSERT(blockcount > 0);
- xfs_calc_default_atomic_ioend_reservation(mp, M_RES(mp));
+ xfs_calc_default_atomic_ioend_reservation(M_RES(mp));
per_intent = xfs_calc_atomic_write_ioend_geometry(mp, &step_size);
@@ -1545,7 +1546,7 @@ xfs_calc_atomic_write_reservation(
* use the defaults.
*/
if (blockcount == 0) {
- xfs_calc_default_atomic_ioend_reservation(mp, M_RES(mp));
+ xfs_calc_default_atomic_ioend_reservation(M_RES(mp));
return 0;
}
diff --git a/fs/xfs/libxfs/xfs_trans_space.c b/fs/xfs/libxfs/xfs_trans_space.c
index c4cd547033e5..7edd0d86f0bd 100644
--- a/fs/xfs/libxfs/xfs_trans_space.c
+++ b/fs/xfs/libxfs/xfs_trans_space.c
@@ -127,10 +127,10 @@ xfs_rename_space_res(
if (has_whiteout)
ret += xfs_parent_calc_space_res(mp, src_namelen);
ret += 2 * xfs_parent_calc_space_res(mp, target_namelen);
- }
- if (target_exists)
- ret += xfs_parent_calc_space_res(mp, target_namelen);
+ if (target_exists)
+ ret += xfs_parent_calc_space_res(mp, target_namelen);
+ }
return ret;
}
diff --git a/fs/xfs/libxfs/xfs_types.c b/fs/xfs/libxfs/xfs_types.c
index 67c947a47f14..f195a04dbf66 100644
--- a/fs/xfs/libxfs/xfs_types.c
+++ b/fs/xfs/libxfs/xfs_types.c
@@ -222,7 +222,6 @@ xfs_verify_icount(
/* Sanity-checking of dir/attr block offsets. */
bool
xfs_verify_dablk(
- struct xfs_mount *mp,
xfs_fileoff_t dabno)
{
xfs_dablk_t max_dablk = -1U;
@@ -233,7 +232,6 @@ xfs_verify_dablk(
/* Check that a file block offset does not exceed the maximum. */
bool
xfs_verify_fileoff(
- struct xfs_mount *mp,
xfs_fileoff_t off)
{
return off <= XFS_MAX_FILEOFF;
@@ -242,15 +240,14 @@ xfs_verify_fileoff(
/* Check that a range of file block offsets do not exceed the maximum. */
bool
xfs_verify_fileext(
- struct xfs_mount *mp,
xfs_fileoff_t off,
xfs_fileoff_t len)
{
if (off + len <= off)
return false;
- if (!xfs_verify_fileoff(mp, off))
+ if (!xfs_verify_fileoff(off))
return false;
- return xfs_verify_fileoff(mp, off + len - 1);
+ return xfs_verify_fileoff(off + len - 1);
}
diff --git a/fs/xfs/libxfs/xfs_types.h b/fs/xfs/libxfs/xfs_types.h
index f6f4f2d4b5db..19dd5e7c8b12 100644
--- a/fs/xfs/libxfs/xfs_types.h
+++ b/fs/xfs/libxfs/xfs_types.h
@@ -277,11 +277,10 @@ bool xfs_verify_rtbno(struct xfs_mount *mp, xfs_rtblock_t rtbno);
bool xfs_verify_rtbext(struct xfs_mount *mp, xfs_rtblock_t rtbno,
xfs_filblks_t len);
bool xfs_verify_icount(struct xfs_mount *mp, unsigned long long icount);
-bool xfs_verify_dablk(struct xfs_mount *mp, xfs_fileoff_t off);
+bool xfs_verify_dablk(xfs_fileoff_t off);
void xfs_icount_range(struct xfs_mount *mp, unsigned long long *min,
unsigned long long *max);
-bool xfs_verify_fileoff(struct xfs_mount *mp, xfs_fileoff_t off);
-bool xfs_verify_fileext(struct xfs_mount *mp, xfs_fileoff_t off,
- xfs_fileoff_t len);
+bool xfs_verify_fileoff(xfs_fileoff_t off);
+bool xfs_verify_fileext(xfs_fileoff_t off, xfs_fileoff_t len);
#endif /* __XFS_TYPES_H__ */
diff --git a/fs/xfs/scrub/alloc_repair.c b/fs/xfs/scrub/alloc_repair.c
index 2398e3819597..6e8352405361 100644
--- a/fs/xfs/scrub/alloc_repair.c
+++ b/fs/xfs/scrub/alloc_repair.c
@@ -108,9 +108,6 @@ struct xrep_abt {
struct xfs_scrub *sc;
- /* Number of non-null records in @free_records. */
- uint64_t nr_real_records;
-
/* get_records()'s position in the free space record array. */
xfarray_idx_t array_cur;
@@ -403,7 +400,6 @@ xrep_abt_find_freespace(
if (error)
goto err_agfl;
- ra->nr_real_records = xfarray_length(ra->free_records);
err_agfl:
xfs_trans_brelse(sc->tp, agfl_bp);
err:
@@ -446,15 +442,17 @@ xrep_abt_reserve_space(
uint64_t required;
unsigned int desired;
unsigned int len;
+ const uint64_t nr_records =
+ xfarray_length(ra->free_records);
/* Compute how many blocks we'll need. */
error = xfs_btree_bload_compute_geometry(cnt_cur,
- &ra->new_cntbt.bload, ra->nr_real_records);
+ &ra->new_cntbt.bload, nr_records);
if (error)
break;
error = xfs_btree_bload_compute_geometry(bno_cur,
- &ra->new_bnobt.bload, ra->nr_real_records);
+ &ra->new_bnobt.bload, nr_records);
if (error)
break;
@@ -470,7 +468,7 @@ xrep_abt_reserve_space(
desired = required - allocated;
/* We need space but there's none left; bye! */
- if (ra->nr_real_records == 0) {
+ if (nr_records == 0) {
error = -ENOSPC;
break;
}
@@ -517,10 +515,9 @@ xrep_abt_reserve_space(
* records (but doesn't break the sorting order), so we must
* go around the loop once more to re-run _bload_init.
*/
- error = xfarray_unset(ra->free_records, record_nr);
+ error = xfarray_trim(ra->free_records, 1);
if (error)
break;
- ra->nr_real_records--;
record_nr--;
} while (1);
diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
index 4f3c7f681bd9..c190590bc562 100644
--- a/fs/xfs/scrub/bmap.c
+++ b/fs/xfs/scrub/bmap.c
@@ -453,18 +453,17 @@ xchk_bmap_dirattr_extent(
struct xchk_bmap_info *info,
struct xfs_bmbt_irec *irec)
{
- struct xfs_mount *mp = ip->i_mount;
xfs_fileoff_t off;
if (!S_ISDIR(VFS_I(ip)->i_mode) && info->whichfork != XFS_ATTR_FORK)
return;
- if (!xfs_verify_dablk(mp, irec->br_startoff))
+ if (!xfs_verify_dablk(irec->br_startoff))
xchk_fblock_set_corrupt(info->sc, info->whichfork,
irec->br_startoff);
off = irec->br_startoff + irec->br_blockcount - 1;
- if (!xfs_verify_dablk(mp, off))
+ if (!xfs_verify_dablk(off))
xchk_fblock_set_corrupt(info->sc, info->whichfork, off);
}
@@ -486,7 +485,7 @@ xchk_bmap_iextent(
xchk_fblock_set_corrupt(info->sc, info->whichfork,
irec->br_startoff);
- if (!xfs_verify_fileext(mp, irec->br_startoff, irec->br_blockcount))
+ if (!xfs_verify_fileext(irec->br_startoff, irec->br_blockcount))
xchk_fblock_set_corrupt(info->sc, info->whichfork,
irec->br_startoff);
@@ -877,8 +876,6 @@ xchk_bmap_iextent_delalloc(
struct xchk_bmap_info *info,
struct xfs_bmbt_irec *irec)
{
- struct xfs_mount *mp = info->sc->mp;
-
/*
* Check for out-of-order extents. This record could have come
* from the incore list, for which there is no ordering check.
@@ -888,7 +885,7 @@ xchk_bmap_iextent_delalloc(
xchk_fblock_set_corrupt(info->sc, info->whichfork,
irec->br_startoff);
- if (!xfs_verify_fileext(mp, irec->br_startoff, irec->br_blockcount))
+ if (!xfs_verify_fileext(irec->br_startoff, irec->br_blockcount))
xchk_fblock_set_corrupt(info->sc, info->whichfork,
irec->br_startoff);
diff --git a/fs/xfs/scrub/bmap_repair.c b/fs/xfs/scrub/bmap_repair.c
index eabffba47776..03af6cb92fcf 100644
--- a/fs/xfs/scrub/bmap_repair.c
+++ b/fs/xfs/scrub/bmap_repair.c
@@ -211,7 +211,7 @@ xrep_bmap_check_fork_rmap(
/* Check the file offset range. */
if (!(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
- !xfs_verify_fileext(sc->mp, rec->rm_offset, rec->rm_blockcount))
+ !xfs_verify_fileext(rec->rm_offset, rec->rm_blockcount))
return -EFSCORRUPTED;
/* No contradictory flags. */
@@ -389,7 +389,7 @@ xrep_bmap_check_rtfork_rmap(
return -EFSCORRUPTED;
/* Check the file offsets and physical extents. */
- if (!xfs_verify_fileext(sc->mp, rec->rm_offset, rec->rm_blockcount))
+ if (!xfs_verify_fileext(rec->rm_offset, rec->rm_blockcount))
return -EFSCORRUPTED;
/* Check that this is within the rtgroup. */
diff --git a/fs/xfs/scrub/inode_repair.c b/fs/xfs/scrub/inode_repair.c
index b87c22146233..c65912d87659 100644
--- a/fs/xfs/scrub/inode_repair.c
+++ b/fs/xfs/scrub/inode_repair.c
@@ -933,7 +933,7 @@ xrep_dinode_bad_bmbt_fork(
fkp = xfs_bmdr_key_addr(dfp, i);
fileoff = be64_to_cpu(fkp->br_startoff);
- if (!xfs_verify_fileoff(sc->mp, fileoff))
+ if (!xfs_verify_fileoff(fileoff))
return true;
fpp = xfs_bmdr_ptr_addr(dfp, i, dmxr);
@@ -1024,6 +1024,30 @@ xrep_dinode_bad_metabt_fork(
return false;
}
+static xfs_failaddr_t
+xrep_symlink_shortform_verify(
+ void *sfp,
+ int64_t size)
+{
+ /*
+ * Zero length symlinks should never occur in memory as they are
+ * never allowed to exist on disk.
+ */
+ if (!size)
+ return __this_address;
+
+ /* No negative sizes or overly long symlink targets. */
+ if (size < 0 || size > XFS_SYMLINK_MAXLEN)
+ return __this_address;
+
+ /* No NULLs in the target either. */
+ if (memchr(sfp, 0, size))
+ return __this_address;
+
+ /* ondisk symlink target isn't null terminated, unlike incore */
+ return NULL;
+}
+
/*
* Check the data fork for things that will fail the ifork verifiers or the
* ifork formatters.
@@ -1099,7 +1123,7 @@ xrep_dinode_check_dfork(
return true;
/* symlink structure must pass verification. */
if (S_ISLNK(mode) &&
- xfs_symlink_shortform_verify(dfork_ptr, data_size) != NULL)
+ xrep_symlink_shortform_verify(dfork_ptr, data_size) != NULL)
return true;
break;
case XFS_DINODE_FMT_EXTENTS:
@@ -1405,7 +1429,7 @@ xrep_dinode_ensure_forkoff(
break;
case XFS_METAFILE_RTREFCOUNT:
rcdr = XFS_DFORK_PTR(dip, XFS_DATA_FORK);
- dfork_min = xfs_rtrefcount_broot_space(sc->mp, rcdr);
+ dfork_min = xfs_rtrefcount_broot_space(rcdr);
break;
default:
dfork_min = 0;
@@ -1949,7 +1973,7 @@ xrep_inode_pptr(
return 0;
return xfs_bmap_add_attrfork(sc->tp, ip,
- sizeof(struct xfs_attr_sf_hdr), true);
+ sizeof(struct xfs_attr_sf_hdr));
}
/* Fix COW extent size hint problems. */
diff --git a/fs/xfs/scrub/orphanage.c b/fs/xfs/scrub/orphanage.c
index 21e31eeaa042..d8e1457f0d5e 100644
--- a/fs/xfs/scrub/orphanage.c
+++ b/fs/xfs/scrub/orphanage.c
@@ -550,7 +550,7 @@ xrep_adoption_move(
if (!xfs_inode_has_attr_fork(sc->ip) && xfs_has_parent(sc->mp)) {
int sf_size = xrep_adoption_attr_sizeof(adopt);
- error = xfs_bmap_add_attrfork(sc->tp, sc->ip, sf_size, true);
+ error = xfs_bmap_add_attrfork(sc->tp, sc->ip, sf_size);
if (error)
return error;
}
diff --git a/fs/xfs/scrub/quota.c b/fs/xfs/scrub/quota.c
index 222812fe202c..8c6ba1240fd5 100644
--- a/fs/xfs/scrub/quota.c
+++ b/fs/xfs/scrub/quota.c
@@ -89,7 +89,7 @@ xchk_quota_item_bmap(
int nmaps = 1;
int error;
- if (!xfs_verify_fileoff(mp, offset)) {
+ if (!xfs_verify_fileoff(offset)) {
xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset);
return 0;
}
diff --git a/fs/xfs/scrub/quota_repair.c b/fs/xfs/scrub/quota_repair.c
index 59302e8afc7e..40bb85e8f909 100644
--- a/fs/xfs/scrub/quota_repair.c
+++ b/fs/xfs/scrub/quota_repair.c
@@ -116,8 +116,8 @@ xrep_quota_item_bmap(
int error;
/* The computed file offset should always be valid. */
- if (!xfs_verify_fileoff(mp, offset)) {
- ASSERT(xfs_verify_fileoff(mp, offset));
+ if (!xfs_verify_fileoff(offset)) {
+ ASSERT(xfs_verify_fileoff(offset));
return -EFSCORRUPTED;
}
dq->q_fileoffset = offset;
@@ -248,10 +248,7 @@ xrep_quota_item(
dq->q_flags |= XFS_DQFLAG_DIRTY;
xfs_trans_dqjoin(sc->tp, dq);
- if (dq->q_id) {
- xfs_qm_adjust_dqlimits(dq);
- xfs_qm_adjust_dqtimers(dq);
- }
+ xfs_qm_adjust_dqenforcement(dq);
xfs_trans_log_dquot(sc->tp, dq);
return xfs_trans_roll(&sc->tp);
diff --git a/fs/xfs/scrub/quotacheck_repair.c b/fs/xfs/scrub/quotacheck_repair.c
index dbb522e1513b..b8334edf380c 100644
--- a/fs/xfs/scrub/quotacheck_repair.c
+++ b/fs/xfs/scrub/quotacheck_repair.c
@@ -39,6 +39,54 @@
* dquot is locked.
*/
+static bool
+xqcheck_dqres_force_dirty(
+ const struct xfs_dquot_res *res,
+ const struct xfs_quota_limits *qlim)
+{
+ /* zero limits mean that we should set the default limits */
+ if (res->softlimit == 0 && qlim->soft != 0)
+ return true;
+ if (res->hardlimit == 0 && qlim->hard != 0)
+ return true;
+
+ /* do we need to adjust the timer setting? */
+ if ((res->softlimit && res->count > res->softlimit) ||
+ (res->hardlimit && res->count > res->hardlimit)) {
+ if (!res->timer)
+ return true;
+ } else {
+ if (res->timer)
+ return true;
+ }
+
+ return false;
+}
+
+/* Decide if we need to adjust the dquot limits or timers */
+static bool
+xqcheck_dquot_force_dirty(
+ const struct xfs_dquot *dq)
+{
+ struct xfs_quotainfo *qi = dq->q_mount->m_quotainfo;
+ struct xfs_def_quota *defq;
+
+ /* root dquot does not enforce limits */
+ if (dq->q_id == 0)
+ return false;
+
+ defq = xfs_get_defquota(qi, xfs_dquot_type(dq));
+
+ if (xqcheck_dqres_force_dirty(&dq->q_blk, &defq->blk))
+ return true;
+ if (xqcheck_dqres_force_dirty(&dq->q_ino, &defq->ino))
+ return true;
+ if (xqcheck_dqres_force_dirty(&dq->q_rtb, &defq->rtb))
+ return true;
+
+ return false;
+}
+
/* Commit new counters to a dquot. */
static int
xqcheck_commit_dquot(
@@ -91,6 +139,9 @@ xqcheck_commit_dquot(
dirty = true;
}
+ if (!dirty && xqcheck_dquot_force_dirty(dq))
+ dirty = true;
+
xcdq.flags |= (XQCHECK_DQUOT_REPAIR_SCANNED | XQCHECK_DQUOT_WRITTEN);
error = xfarray_store(counts, dq->q_id, &xcdq);
if (error == -EFBIG) {
@@ -110,8 +161,7 @@ xqcheck_commit_dquot(
/* Commit the dirty dquot to disk. */
dq->q_flags |= XFS_DQFLAG_DIRTY;
- if (dq->q_id)
- xfs_qm_adjust_dqtimers(dq);
+ xfs_qm_adjust_dqenforcement(dq);
xfs_trans_log_dquot(xqc->sc->tp, dq);
return xrep_trans_commit(xqc->sc);
diff --git a/fs/xfs/scrub/rtrefcount_repair.c b/fs/xfs/scrub/rtrefcount_repair.c
index 2b939960c7dd..c78a6d2990c5 100644
--- a/fs/xfs/scrub/rtrefcount_repair.c
+++ b/fs/xfs/scrub/rtrefcount_repair.c
@@ -596,8 +596,7 @@ xrep_rtrefc_iroot_size(
unsigned int nr_this_level,
void *priv)
{
- return xfs_rtrefcount_broot_space_calc(cur->bc_mp, level,
- nr_this_level);
+ return xfs_rtrefcount_broot_space_calc(level, nr_this_level);
}
/*
diff --git a/fs/xfs/scrub/rtrmap_repair.c b/fs/xfs/scrub/rtrmap_repair.c
index a2b72e61edf5..5cfa4470c57c 100644
--- a/fs/xfs/scrub/rtrmap_repair.c
+++ b/fs/xfs/scrub/rtrmap_repair.c
@@ -693,7 +693,7 @@ xrep_rtrmap_iroot_size(
unsigned int nr_this_level,
void *priv)
{
- return xfs_rtrmap_broot_space_calc(cur->bc_mp, level, nr_this_level);
+ return xfs_rtrmap_broot_space_calc(level, nr_this_level);
}
/*
diff --git a/fs/xfs/scrub/xfarray.c b/fs/xfs/scrub/xfarray.c
index 2ce24bfe4c0f..c94f35560779 100644
--- a/fs/xfs/scrub/xfarray.c
+++ b/fs/xfs/scrub/xfarray.c
@@ -140,55 +140,23 @@ xfarray_load(
xfarray_pos(array, idx));
}
-/* Is this array element potentially unset? */
-static inline bool
-xfarray_is_unset(
- struct xfarray *array,
- loff_t pos)
-{
- void *temp = xfarray_scratch(array);
- int error;
-
- if (array->unset_slots == 0)
- return false;
-
- error = xfile_load(array->xfile, temp, array->obj_size, pos);
- if (!error && xfarray_element_is_null(array, temp))
- return true;
-
- return false;
-}
-
-/*
- * Unset an array element. If @idx is the last element in the array, the
- * array will be truncated. Otherwise, the entry will be zeroed.
- */
+/* Remove the elements at the end of an array. */
int
-xfarray_unset(
- struct xfarray *array,
- xfarray_idx_t idx)
+xfarray_trim(
+ struct xfarray *array,
+ unsigned long long nr)
{
- void *temp = xfarray_scratch(array);
- loff_t pos = xfarray_pos(array, idx);
- int error;
+ loff_t new_eof;
- if (idx >= array->nr)
+ if (nr > array->nr)
return -ENODATA;
- if (idx == array->nr - 1) {
- array->nr--;
- return 0;
- }
-
- if (xfarray_is_unset(array, pos))
- return 0;
-
- memset(temp, 0, array->obj_size);
- error = xfile_store(array->xfile, temp, array->obj_size, pos);
- if (error)
- return error;
+ array->nr -= nr;
+ if (!array->nr)
+ array->possibly_sparse = false;
- array->unset_slots++;
+ new_eof = xfarray_pos(array, array->nr);
+ xfile_discard(array->xfile, new_eof, MAX_LFS_FILESIZE - new_eof);
return 0;
}
@@ -214,6 +182,8 @@ xfarray_store(
if (ret)
return ret;
+ if (idx > array->nr)
+ array->possibly_sparse = true;
array->nr = max(array->nr, idx + 1);
return 0;
}
@@ -227,43 +197,6 @@ xfarray_element_is_null(
return !memchr_inv(ptr, 0, array->obj_size);
}
-/*
- * Store an element anywhere in the array that is unset. If there are no
- * unset slots, append the element to the array.
- */
-int
-xfarray_store_anywhere(
- struct xfarray *array,
- const void *ptr)
-{
- void *temp = xfarray_scratch(array);
- loff_t endpos = xfarray_pos(array, array->nr);
- loff_t pos;
- int error;
-
- /* Find an unset slot to put it in. */
- for (pos = 0;
- pos < endpos && array->unset_slots > 0;
- pos += array->obj_size) {
- error = xfile_load(array->xfile, temp, array->obj_size,
- pos);
- if (error || !xfarray_element_is_null(array, temp))
- continue;
-
- error = xfile_store(array->xfile, ptr, array->obj_size,
- pos);
- if (error)
- return error;
-
- array->unset_slots--;
- return 0;
- }
-
- /* No unset slots found; attach it on the end. */
- array->unset_slots = 0;
- return xfarray_append(array, ptr);
-}
-
/* Return length of array. */
uint64_t
xfarray_length(
@@ -677,26 +610,10 @@ xfarray_qsort_pivot(
/* Load the selected xfarray records into the pivot array. */
for (i = 0; i < XFARRAY_QSORT_PIVOT_NR; i++) {
- xfarray_idx_t idx;
-
recp = xfarray_pivot_array_rec(parray, pivot_rec_sz, i);
idxp = xfarray_pivot_array_idx(parray, pivot_rec_sz, i);
- /* No unset records; load directly into the array. */
- if (likely(si->array->unset_slots == 0)) {
- error = xfarray_sort_load(si, *idxp, recp);
- if (error)
- return error;
- continue;
- }
-
- /*
- * Load non-null records into the scratchpad without changing
- * the xfarray_idx_t in the pivot array.
- */
- idx = *idxp;
- xfarray_sort_bump_loads(si);
- error = xfarray_load_next(si->array, &idx, recp);
+ error = xfarray_sort_load(si, *idxp, recp);
if (error)
return error;
}
@@ -765,6 +682,18 @@ xfarray_qsort_push(
return -EFSCORRUPTED;
}
+ /*
+ * Avoid the integer underflow below in (lo - 1). This shouldn't
+ * be possible because the pivot is the median of nine distinct
+ * filesystem metadata records, so at least four records will be less
+ * than the pivot, which means the pivot will not be in the low end of
+ * the range by the time we get here.
+ */
+ if (lo == 0) {
+ ASSERT(lo != 0);
+ return -EFSCORRUPTED;
+ }
+
si->max_stack_used = max_t(uint8_t, si->max_stack_used,
si->stack_depth + 2);
@@ -794,6 +723,46 @@ xfarray_sort_scan_done(
si->folio = NULL;
}
+static int
+xfarray_sort_load_folio(
+ struct xfarray_sortinfo *si,
+ xfarray_idx_t idx,
+ loff_t idx_pos)
+{
+ struct folio *folio;
+ loff_t next_pos;
+
+ folio = xfile_get_folio(si->array->xfile, idx_pos, si->array->obj_size,
+ XFILE_ALLOC);
+ if (IS_ERR(folio))
+ return PTR_ERR(folio);
+ si->folio = folio;
+
+ /* No folio? Get the caller to read into the scratchpad. */
+ if (!si->folio)
+ return 0;
+
+ si->first_folio_idx = xfarray_idx(si->array,
+ folio_pos(si->folio) + si->array->obj_size - 1);
+
+ next_pos = folio_next_pos(si->folio);
+ si->last_folio_idx = xfarray_idx(si->array, next_pos - 1);
+ if (xfarray_pos(si->array, si->last_folio_idx + 1) > next_pos)
+ si->last_folio_idx--;
+
+ /*
+ * If this folio still doesn't cover the desired element, it must cross
+ * a folio boundary. Get the caller to read into the scratchpad.
+ */
+ if (idx < si->first_folio_idx || idx > si->last_folio_idx) {
+ xfarray_sort_scan_done(si);
+ return 0;
+ }
+
+ trace_xfarray_sort_scan(si, idx);
+ return 0;
+}
+
/*
* Cache the folio backing the start of the given array element. If the array
* element is contained entirely within the folio, return a pointer to the
@@ -819,33 +788,18 @@ xfarray_sort_scan(
(idx < si->first_folio_idx || idx > si->last_folio_idx))
xfarray_sort_scan_done(si);
- /* Grab the first folio that backs this array element. */
+ /* Grab the folio that backs this array element. */
if (!si->folio) {
- struct folio *folio;
- loff_t next_pos;
-
- folio = xfile_get_folio(si->array->xfile, idx_pos,
- si->array->obj_size, XFILE_ALLOC);
- if (IS_ERR(folio))
- return PTR_ERR(folio);
- si->folio = folio;
-
- si->first_folio_idx = xfarray_idx(si->array,
- folio_pos(si->folio) + si->array->obj_size - 1);
-
- next_pos = folio_next_pos(si->folio);
- si->last_folio_idx = xfarray_idx(si->array, next_pos - 1);
- if (xfarray_pos(si->array, si->last_folio_idx + 1) > next_pos)
- si->last_folio_idx--;
-
- trace_xfarray_sort_scan(si, idx);
+ error = xfarray_sort_load_folio(si, idx, idx_pos);
+ if (error)
+ return error;
}
/*
- * If this folio still doesn't cover the desired element, it must cross
- * a folio boundary. Read into the scratchpad and we're done.
+ * If we don't have a folio mapping the entire array element, read into
+ * the scratchpad and we're done.
*/
- if (idx < si->first_folio_idx || idx > si->last_folio_idx) {
+ if (!si->folio) {
void *temp = xfarray_scratch(si->array);
error = xfile_load(si->array->xfile, temp, si->array->obj_size,
@@ -916,6 +870,14 @@ xfarray_sort(
return 0;
if (array->nr >= QSORT_MAX_RECS)
return -E2BIG;
+ if (array->possibly_sparse) {
+ /*
+ * What does it mean to sort an array with holes in it?
+ * Currently none of the users need this ability.
+ */
+ ASSERT(!array->possibly_sparse);
+ return -EINVAL;
+ }
error = xfarray_sortinfo_alloc(array, cmp_fn, flags, &si);
if (error)
@@ -1069,4 +1031,5 @@ xfarray_truncate(
{
xfile_discard(array->xfile, 0, MAX_LFS_FILESIZE);
array->nr = 0;
+ array->possibly_sparse = false;
}
diff --git a/fs/xfs/scrub/xfarray.h b/fs/xfs/scrub/xfarray.h
index 5eeeeed13ae2..05ff65b09fcf 100644
--- a/fs/xfs/scrub/xfarray.h
+++ b/fs/xfs/scrub/xfarray.h
@@ -27,23 +27,22 @@ struct xfarray {
/* Maximum possible array size. */
xfarray_idx_t max_nr;
- /* Number of unset slots in the array below @nr. */
- uint64_t unset_slots;
-
/* Size of an array element. */
size_t obj_size;
/* log2 of array element size, if possible. */
int obj_size_log;
+
+ /* Might there be sparse holes in this array? */
+ bool possibly_sparse;
};
int xfarray_create(const char *descr, unsigned long long required_capacity,
size_t obj_size, struct xfarray **arrayp);
void xfarray_destroy(struct xfarray *array);
int xfarray_load(struct xfarray *array, xfarray_idx_t idx, void *ptr);
-int xfarray_unset(struct xfarray *array, xfarray_idx_t idx);
+int xfarray_trim(struct xfarray *array, unsigned long long nr);
int xfarray_store(struct xfarray *array, xfarray_idx_t idx, const void *ptr);
-int xfarray_store_anywhere(struct xfarray *array, const void *ptr);
bool xfarray_element_is_null(struct xfarray *array, const void *ptr);
void xfarray_truncate(struct xfarray *array);
unsigned long long xfarray_bytes(struct xfarray *array);
diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
index aa5b41629747..62be62342fea 100644
--- a/fs/xfs/xfs_bmap_item.c
+++ b/fs/xfs/xfs_bmap_item.c
@@ -442,7 +442,7 @@ xfs_bui_validate(
if (!xfs_verify_ino(mp, map->me_owner))
return false;
- if (!xfs_verify_fileext(mp, map->me_startoff, map->me_len))
+ if (!xfs_verify_fileext(map->me_startoff, map->me_len))
return false;
if (map->me_flags & XFS_BMAP_EXTENT_REALTIME)
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index e696ee36c2e8..6d22ead562da 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -115,18 +115,15 @@ xfs_qm_dqdestroy(
* We overwrite the dquot limits only if they are zero and this
* is not the root dquot.
*/
-void
+static void
xfs_qm_adjust_dqlimits(
struct xfs_dquot *dq)
{
struct xfs_mount *mp = dq->q_mount;
struct xfs_quotainfo *q = mp->m_quotainfo;
- struct xfs_def_quota *defq;
+ struct xfs_def_quota *defq = xfs_get_defquota(q, xfs_dquot_type(dq));
int prealloc = 0;
- ASSERT(dq->q_id);
- defq = xfs_get_defquota(q, xfs_dquot_type(dq));
-
if (!dq->q_blk.softlimit) {
dq->q_blk.softlimit = defq->blk.soft;
prealloc = 1;
@@ -223,6 +220,19 @@ xfs_qm_adjust_dqtimers(
xfs_qm_adjust_res_timer(dq->q_mount, &dq->q_rtb, &defq->rtb);
}
+/* Adjust enforcement limits and timers after a change in usage. */
+void
+xfs_qm_adjust_dqenforcement(
+ struct xfs_dquot *dq)
+{
+ if (dq->q_id == 0)
+ return;
+
+ xfs_qm_adjust_dqlimits(dq);
+ xfs_qm_adjust_dqtimers(dq);
+ dq->q_flags |= XFS_DQFLAG_DIRTY;
+}
+
/*
* initialize a buffer full of dquots and log the whole thing
*/
diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
index bbb824adca82..28c09704acc2 100644
--- a/fs/xfs/xfs_dquot.h
+++ b/fs/xfs/xfs_dquot.h
@@ -205,7 +205,7 @@ void xfs_qm_dqdestroy(struct xfs_dquot *dqp);
int xfs_qm_dqflush(struct xfs_dquot *dqp, struct xfs_buf *bp);
void xfs_qm_dqunpin_wait(struct xfs_dquot *dqp);
void xfs_qm_adjust_dqtimers(struct xfs_dquot *d);
-void xfs_qm_adjust_dqlimits(struct xfs_dquot *d);
+void xfs_qm_adjust_dqenforcement(struct xfs_dquot *d);
xfs_dqid_t xfs_qm_id_for_quotatype(struct xfs_inode *ip,
xfs_dqtype_t type);
int xfs_qm_dqget(struct xfs_mount *mp, xfs_dqid_t id,
diff --git a/fs/xfs/xfs_exchmaps_item.c b/fs/xfs/xfs_exchmaps_item.c
index dd5d92ca1010..dd104bf778ba 100644
--- a/fs/xfs/xfs_exchmaps_item.c
+++ b/fs/xfs/xfs_exchmaps_item.c
@@ -341,10 +341,10 @@ xfs_xmi_validate(
!xfs_verify_ino(mp, xlf->xmi_inode2))
return false;
- if (!xfs_verify_fileext(mp, xlf->xmi_startoff1, xlf->xmi_blockcount))
+ if (!xfs_verify_fileext(xlf->xmi_startoff1, xlf->xmi_blockcount))
return false;
- if (!xfs_verify_fileext(mp, xlf->xmi_startoff2, xlf->xmi_blockcount))
+ if (!xfs_verify_fileext(xlf->xmi_startoff2, xlf->xmi_blockcount))
return false;
if (xlf->xmi_flags & XFS_EXCHMAPS_SET_SIZES) {
diff --git a/fs/xfs/xfs_exchrange.c b/fs/xfs/xfs_exchrange.c
index fafb4e3f065c..a1001315d4a7 100644
--- a/fs/xfs/xfs_exchrange.c
+++ b/fs/xfs/xfs_exchrange.c
@@ -238,7 +238,7 @@ retry:
trace_xfs_exchrange_before(ip2, 2);
trace_xfs_exchrange_before(ip1, 1);
- error = xfs_exchmaps_check_forks(mp, &req);
+ error = xfs_exchmaps_check_forks(&req);
if (error)
goto out_trans_cancel;
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index d8202da15aca..dd6d2e08faff 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -1872,17 +1872,21 @@ xfs_file_release(
return 0;
/*
- * If we can't get the iolock just skip truncating the blocks past EOF
- * because we could deadlock with the mmap_lock otherwise. We'll get
- * another chance to drop them once the last reference to the inode is
- * dropped, so we'll never leak blocks permanently.
+ * If we can't get the iolock or if the filesystem is frozen, just skip
+ * truncating the blocks past EOF because we could deadlock with the
+ * mmap_lock or hang the close() call. We'll get another chance to drop
+ * them once the last reference to the inode is dropped, so we'll never
+ * leak blocks permanently.
*/
if (!xfs_iflags_test(ip, XFS_EOFBLOCKS_RELEASED) &&
- xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) {
- if (xfs_can_free_eofblocks(ip) &&
- !xfs_iflags_test_and_set(ip, XFS_EOFBLOCKS_RELEASED))
- xfs_free_eofblocks(ip);
- xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+ sb_start_write_trylock(mp->m_super)) {
+ if (xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) {
+ if (xfs_can_free_eofblocks(ip) &&
+ !xfs_iflags_test_and_set(ip, XFS_EOFBLOCKS_RELEASED))
+ xfs_free_eofblocks(ip);
+ xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+ }
+ sb_end_write(mp->m_super);
}
return 0;
diff --git a/fs/xfs/xfs_handle.c b/fs/xfs/xfs_handle.c
index 0689cade8f74..fd9d4d8258ff 100644
--- a/fs/xfs/xfs_handle.c
+++ b/fs/xfs/xfs_handle.c
@@ -409,7 +409,7 @@ xfs_ioc_attr_list(
void *buffer;
int error;
- if (bufsize < sizeof(struct xfs_attrlist) ||
+ if (bufsize < struct_size(alist, al_offset, 1) ||
bufsize > XFS_XATTR_LIST_MAX)
return -EINVAL;
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 621513d7215e..15b62574b8d4 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -755,7 +755,7 @@ xfs_create(
*ipp = du.ip;
xfs_iunlock(du.ip, XFS_ILOCK_EXCL);
xfs_iunlock(dp, XFS_ILOCK_EXCL);
- xfs_parent_finish(mp, du.ppargs);
+ xfs_parent_finish(du.ppargs);
return 0;
out_trans_cancel:
@@ -772,7 +772,7 @@ xfs_create(
xfs_irele(du.ip);
}
out_parent:
- xfs_parent_finish(mp, du.ppargs);
+ xfs_parent_finish(du.ppargs);
out_release_dquots:
xfs_qm_dqrele(udqp);
xfs_qm_dqrele(gdqp);
@@ -972,7 +972,7 @@ xfs_link(
error = xfs_trans_commit(tp);
xfs_iunlock(tdp, XFS_ILOCK_EXCL);
xfs_iunlock(sip, XFS_ILOCK_EXCL);
- xfs_parent_finish(mp, du.ppargs);
+ xfs_parent_finish(du.ppargs);
return error;
error_return:
@@ -980,7 +980,7 @@ xfs_link(
xfs_iunlock(tdp, XFS_ILOCK_EXCL);
xfs_iunlock(sip, XFS_ILOCK_EXCL);
out_parent:
- xfs_parent_finish(mp, du.ppargs);
+ xfs_parent_finish(du.ppargs);
std_return:
if (error == -ENOSPC && nospace_error)
error = nospace_error;
@@ -1064,7 +1064,7 @@ xfs_itruncate_extents_flags(
* the page cache can't scale that far.
*/
first_unmap_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)new_size);
- if (!xfs_verify_fileoff(mp, first_unmap_block)) {
+ if (!xfs_verify_fileoff(first_unmap_block)) {
WARN_ON_ONCE(first_unmap_block > XFS_MAX_FILEOFF);
return 0;
}
@@ -1985,7 +1985,7 @@ xfs_remove(
xfs_iunlock(ip, XFS_ILOCK_EXCL);
xfs_iunlock(dp, XFS_ILOCK_EXCL);
- xfs_parent_finish(mp, du.ppargs);
+ xfs_parent_finish(du.ppargs);
return 0;
out_trans_cancel:
@@ -1994,7 +1994,7 @@ xfs_remove(
xfs_iunlock(ip, XFS_ILOCK_EXCL);
xfs_iunlock(dp, XFS_ILOCK_EXCL);
out_parent:
- xfs_parent_finish(mp, du.ppargs);
+ xfs_parent_finish(du.ppargs);
std_return:
return error;
}
@@ -2357,11 +2357,11 @@ out_trans_cancel:
out_unlock:
xfs_iunlock_rename(inodes, num_inodes);
out_tgt_ppargs:
- xfs_parent_finish(mp, du_tgt.ppargs);
+ xfs_parent_finish(du_tgt.ppargs);
out_wip_ppargs:
- xfs_parent_finish(mp, du_wip.ppargs);
+ xfs_parent_finish(du_wip.ppargs);
out_src_ppargs:
- xfs_parent_finish(mp, du_src.ppargs);
+ xfs_parent_finish(du_src.ppargs);
out_release_wip:
if (du_wip.ip)
xfs_irele(du_wip.ip);
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 96ca3e480cb9..c0fc9b34f393 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -962,10 +962,10 @@ out_free_buf:
}
int
-xfs_ioc_swapext(
- xfs_swapext_t *sxp)
+xfs_swapext(
+ struct xfs_swapext *sxp)
{
- xfs_inode_t *ip, *tip;
+ struct xfs_inode *ip, *tip;
/* Pull information for the target fd */
CLASS(fd, f)((int)sxp->sx_fdtarget);
@@ -1035,6 +1035,46 @@ xfs_ioc_getlabel(
return 0;
}
+/*
+ * Same behavior as xfs_sync_sb, except that it is always synchronous and it
+ * also writes the superblock buffer to disk sector 0 immediately.
+ */
+static int
+xfs_sync_sb_buf(
+ struct xfs_mount *mp,
+ bool update_rtsb)
+{
+ struct xfs_trans *tp;
+ int error;
+
+ error = xfs_trans_alloc(mp, &M_RES(mp)->tr_sb, 0, 0, 0, &tp);
+ if (error)
+ return error;
+
+ xfs_log_sb(tp);
+ if (update_rtsb)
+ xfs_log_rtsb(tp, xfs_trans_getsb(tp));
+ xfs_trans_set_sync(tp);
+ error = xfs_trans_commit(tp);
+ if (error)
+ return error;
+
+ /* Re-acquire and write the sb and rtsb to disk. */
+ xfs_buf_lock(mp->m_sb_bp);
+ error = xfs_bwrite(mp->m_sb_bp);
+ xfs_buf_unlock(mp->m_sb_bp);
+ if (error)
+ return error;
+
+ if (update_rtsb && mp->m_rtsb_bp) {
+ xfs_buf_lock(mp->m_rtsb_bp);
+ error = xfs_bwrite(mp->m_rtsb_bp);
+ xfs_buf_unlock(mp->m_rtsb_bp);
+ }
+
+ return error;
+}
+
static int
xfs_ioc_setlabel(
struct file *filp,
@@ -1144,7 +1184,7 @@ xfs_fs_eofblocks_from_user(
}
static int
-xfs_ioctl_getset_resblocks(
+xfs_ioc_getset_resblocks(
struct file *filp,
unsigned int cmd,
void __user *arg)
@@ -1183,7 +1223,7 @@ xfs_ioctl_getset_resblocks(
}
static int
-xfs_ioctl_fs_counts(
+xfs_ioc_fs_counts(
struct xfs_mount *mp,
struct xfs_fsop_counts __user *uarg)
{
@@ -1200,6 +1240,202 @@ xfs_ioctl_fs_counts(
return 0;
}
+static int
+xfs_ioc_dioinfo(
+ struct file *file,
+ void __user *arg)
+{
+ struct kstat st;
+ struct dioattr da;
+ int error;
+
+ error = vfs_getattr(&file->f_path, &st, STATX_DIOALIGN, 0);
+ if (error)
+ return error;
+
+ /*
+ * Some userspace directly feeds the return value to posix_memalign,
+ * which fails for values that are smaller than the pointer size.
+ * Round up the value to not break userspace.
+ */
+ da.d_mem = roundup(st.dio_mem_align, sizeof(void *));
+ da.d_miniosz = st.dio_offset_align;
+ da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1);
+ if (copy_to_user(arg, &da, sizeof(da)))
+ return -EFAULT;
+ return 0;
+}
+
+static int
+xfs_ioc_find_handle(
+ unsigned int cmd,
+ void __user *arg)
+{
+ struct xfs_fsop_handlereq hreq;
+
+ if (copy_from_user(&hreq, arg, sizeof(hreq)))
+ return -EFAULT;
+ return xfs_find_handle(cmd, &hreq);
+}
+
+static int
+xfs_ioc_open_by_handle(
+ struct file *file,
+ void __user *arg)
+{
+ struct xfs_fsop_handlereq hreq;
+
+ if (copy_from_user(&hreq, arg, sizeof(hreq)))
+ return -EFAULT;
+ return xfs_open_by_handle(file, &hreq);
+}
+
+static int
+xfs_ioc_readlink_by_handle(
+ struct file *file,
+ void __user *arg)
+{
+ struct xfs_fsop_handlereq hreq;
+
+ if (copy_from_user(&hreq, arg, sizeof(hreq)))
+ return -EFAULT;
+ return xfs_readlink_by_handle(file, &hreq);
+}
+
+static int
+xfs_ioc_swapext(
+ struct file *file,
+ void __user *arg)
+{
+ struct xfs_swapext sxp;
+ int error;
+
+ if (copy_from_user(&sxp, arg, sizeof(sxp)))
+ return -EFAULT;
+
+ error = mnt_want_write_file(file);
+ if (error)
+ return error;
+ error = xfs_swapext(&sxp);
+ mnt_drop_write_file(file);
+ return error;
+}
+
+static int
+xfs_ioc_growfs_data(
+ struct file *file,
+ struct xfs_mount *mp,
+ void __user *arg)
+{
+ struct xfs_growfs_data in;
+ int error;
+
+ if (copy_from_user(&in, arg, sizeof(in)))
+ return -EFAULT;
+
+ error = mnt_want_write_file(file);
+ if (error)
+ return error;
+ error = xfs_growfs_data(mp, &in);
+ mnt_drop_write_file(file);
+ return error;
+}
+
+static int
+xfs_ioc_growfs_log(
+ struct file *file,
+ struct xfs_mount *mp,
+ void __user *arg)
+{
+ struct xfs_growfs_log in;
+ int error;
+
+ if (copy_from_user(&in, arg, sizeof(in)))
+ return -EFAULT;
+
+ error = mnt_want_write_file(file);
+ if (error)
+ return error;
+ error = xfs_growfs_log(mp, &in);
+ mnt_drop_write_file(file);
+ return error;
+}
+
+static int
+xfs_ioc_growfs_rt(
+ struct file *file,
+ struct xfs_mount *mp,
+ void __user *arg)
+{
+ struct xfs_growfs_rt in;
+ int error;
+
+ if (copy_from_user(&in, arg, sizeof(in)))
+ return -EFAULT;
+
+ error = mnt_want_write_file(file);
+ if (error)
+ return error;
+ error = xfs_growfs_rt(mp, &in);
+ mnt_drop_write_file(file);
+ return error;
+}
+
+static int
+xfs_ioc_goingdown(
+ struct xfs_mount *mp,
+ uint32_t __user *arg)
+{
+ uint32_t in;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (get_user(in, arg))
+ return -EFAULT;
+ return xfs_fs_goingdown(mp, in);
+}
+
+static int
+xfs_ioc_error_injection(
+ struct xfs_mount *mp,
+ struct xfs_error_injection __user *arg)
+{
+ struct xfs_error_injection in;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (copy_from_user(&in, arg, sizeof(in)))
+ return -EFAULT;
+ return xfs_errortag_add(mp, in.errtag);
+}
+
+static int
+xfs_ioc_free_eofblocks(
+ struct xfs_mount *mp,
+ struct xfs_fs_eofblocks __user *arg)
+{
+ struct xfs_fs_eofblocks eofb;
+ struct xfs_icwalk icw;
+ int error;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (xfs_is_readonly(mp))
+ return -EROFS;
+
+ if (copy_from_user(&eofb, arg, sizeof(eofb)))
+ return -EFAULT;
+
+ error = xfs_fs_eofblocks_from_user(&eofb, &icw);
+ if (error)
+ return error;
+
+ trace_xfs_ioc_free_eofblocks(mp, &icw, _RET_IP_);
+
+ guard(super_write)(mp->m_super);
+ return xfs_blockgc_free_space(mp, &icw);
+}
+
/*
* These long-unused ioctls were removed from the official ioctl API in 5.17,
* but retain these definitions so that we can log warnings about them.
@@ -1209,12 +1445,6 @@ xfs_ioctl_fs_counts(
#define XFS_IOC_ALLOCSP64 _IOW ('X', 36, struct xfs_flock64)
#define XFS_IOC_FREESP64 _IOW ('X', 37, struct xfs_flock64)
-/*
- * Note: some of the ioctl's return positive numbers as a
- * byte count indicating success, such as readlink_by_handle.
- * So we don't "sign flip" like most other routines. This means
- * true errors need to be returned as a negative value.
- */
long
xfs_file_ioctl(
struct file *filp,
@@ -1225,7 +1455,6 @@ xfs_file_ioctl(
struct xfs_inode *ip = XFS_I(inode);
struct xfs_mount *mp = ip->i_mount;
void __user *arg = (void __user *)p;
- int error;
trace_xfs_file_ioctl(ip);
@@ -1244,26 +1473,9 @@ xfs_file_ioctl(
"%s should use fallocate; XFS_IOC_{ALLOC,FREE}SP ioctl unsupported",
current->comm);
return -ENOTTY;
- case XFS_IOC_DIOINFO: {
- struct kstat st;
- struct dioattr da;
- error = vfs_getattr(&filp->f_path, &st, STATX_DIOALIGN, 0);
- if (error)
- return error;
-
- /*
- * Some userspace directly feeds the return value to
- * posix_memalign, which fails for values that are smaller than
- * the pointer size. Round up the value to not break userspace.
- */
- da.d_mem = roundup(st.dio_mem_align, sizeof(void *));
- da.d_miniosz = st.dio_offset_align;
- da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1);
- if (copy_to_user(arg, &da, sizeof(da)))
- return -EFAULT;
- return 0;
- }
+ case XFS_IOC_DIOINFO:
+ return xfs_ioc_dioinfo(filp, arg);
case XFS_IOC_FSBULKSTAT_SINGLE:
case XFS_IOC_FSBULKSTAT:
@@ -1311,148 +1523,45 @@ xfs_file_ioctl(
case XFS_IOC_FD_TO_HANDLE:
case XFS_IOC_PATH_TO_HANDLE:
- case XFS_IOC_PATH_TO_FSHANDLE: {
- xfs_fsop_handlereq_t hreq;
-
- if (copy_from_user(&hreq, arg, sizeof(hreq)))
- return -EFAULT;
- return xfs_find_handle(cmd, &hreq);
- }
- case XFS_IOC_OPEN_BY_HANDLE: {
- xfs_fsop_handlereq_t hreq;
-
- if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
- return -EFAULT;
- return xfs_open_by_handle(filp, &hreq);
- }
-
- case XFS_IOC_READLINK_BY_HANDLE: {
- xfs_fsop_handlereq_t hreq;
-
- if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
- return -EFAULT;
- return xfs_readlink_by_handle(filp, &hreq);
- }
+ case XFS_IOC_PATH_TO_FSHANDLE:
+ return xfs_ioc_find_handle(cmd, arg);
+ case XFS_IOC_OPEN_BY_HANDLE:
+ return xfs_ioc_open_by_handle(filp, arg);
+ case XFS_IOC_READLINK_BY_HANDLE:
+ return xfs_ioc_readlink_by_handle(filp, arg);
case XFS_IOC_ATTRLIST_BY_HANDLE:
return xfs_attrlist_by_handle(filp, arg);
-
case XFS_IOC_ATTRMULTI_BY_HANDLE:
return xfs_attrmulti_by_handle(filp, arg);
- case XFS_IOC_SWAPEXT: {
- struct xfs_swapext sxp;
-
- if (copy_from_user(&sxp, arg, sizeof(xfs_swapext_t)))
- return -EFAULT;
- error = mnt_want_write_file(filp);
- if (error)
- return error;
- error = xfs_ioc_swapext(&sxp);
- mnt_drop_write_file(filp);
- return error;
- }
+ case XFS_IOC_SWAPEXT:
+ return xfs_ioc_swapext(filp, arg);
case XFS_IOC_FSCOUNTS:
- return xfs_ioctl_fs_counts(mp, arg);
+ return xfs_ioc_fs_counts(mp, arg);
case XFS_IOC_SET_RESBLKS:
case XFS_IOC_GET_RESBLKS:
- return xfs_ioctl_getset_resblocks(filp, cmd, arg);
-
- case XFS_IOC_FSGROWFSDATA: {
- struct xfs_growfs_data in;
-
- if (copy_from_user(&in, arg, sizeof(in)))
- return -EFAULT;
-
- error = mnt_want_write_file(filp);
- if (error)
- return error;
- error = xfs_growfs_data(mp, &in);
- mnt_drop_write_file(filp);
- return error;
- }
-
- case XFS_IOC_FSGROWFSLOG: {
- struct xfs_growfs_log in;
-
- if (copy_from_user(&in, arg, sizeof(in)))
- return -EFAULT;
-
- error = mnt_want_write_file(filp);
- if (error)
- return error;
- error = xfs_growfs_log(mp, &in);
- mnt_drop_write_file(filp);
- return error;
- }
-
- case XFS_IOC_FSGROWFSRT: {
- xfs_growfs_rt_t in;
-
- if (copy_from_user(&in, arg, sizeof(in)))
- return -EFAULT;
-
- error = mnt_want_write_file(filp);
- if (error)
- return error;
- error = xfs_growfs_rt(mp, &in);
- mnt_drop_write_file(filp);
- return error;
- }
-
- case XFS_IOC_GOINGDOWN: {
- uint32_t in;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- if (get_user(in, (uint32_t __user *)arg))
- return -EFAULT;
-
- return xfs_fs_goingdown(mp, in);
- }
-
- case XFS_IOC_ERROR_INJECTION: {
- xfs_error_injection_t in;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- if (copy_from_user(&in, arg, sizeof(in)))
- return -EFAULT;
-
- return xfs_errortag_add(mp, in.errtag);
- }
-
+ return xfs_ioc_getset_resblocks(filp, cmd, arg);
+
+ case XFS_IOC_FSGROWFSDATA:
+ return xfs_ioc_growfs_data(filp, mp, arg);
+ case XFS_IOC_FSGROWFSLOG:
+ return xfs_ioc_growfs_log(filp, mp, arg);
+ case XFS_IOC_FSGROWFSRT:
+ return xfs_ioc_growfs_rt(filp, mp, arg);
+
+ case XFS_IOC_GOINGDOWN:
+ return xfs_ioc_goingdown(mp, arg);
+ case XFS_IOC_ERROR_INJECTION:
+ return xfs_ioc_error_injection(mp, arg);
case XFS_IOC_ERROR_CLEARALL:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
-
return xfs_errortag_clearall(mp);
- case XFS_IOC_FREE_EOFBLOCKS: {
- struct xfs_fs_eofblocks eofb;
- struct xfs_icwalk icw;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- if (xfs_is_readonly(mp))
- return -EROFS;
-
- if (copy_from_user(&eofb, arg, sizeof(eofb)))
- return -EFAULT;
-
- error = xfs_fs_eofblocks_from_user(&eofb, &icw);
- if (error)
- return error;
-
- trace_xfs_ioc_free_eofblocks(mp, &icw, _RET_IP_);
-
- guard(super_write)(mp->m_super);
- return xfs_blockgc_free_space(mp, &icw);
- }
+ case XFS_IOC_FREE_EOFBLOCKS:
+ return xfs_ioc_free_eofblocks(mp, arg);
case XFS_IOC_EXCHANGE_RANGE:
return xfs_ioc_exchange_range(filp, arg);
diff --git a/fs/xfs/xfs_ioctl.h b/fs/xfs/xfs_ioctl.h
index f5ed5cf9d3df..e57d8f5148bf 100644
--- a/fs/xfs/xfs_ioctl.h
+++ b/fs/xfs/xfs_ioctl.h
@@ -10,9 +10,7 @@ struct xfs_bstat;
struct xfs_ibulk;
struct xfs_inogrp;
-int
-xfs_ioc_swapext(
- xfs_swapext_t *sxp);
+int xfs_swapext(struct xfs_swapext *sxp);
extern int
xfs_fileattr_get(
diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
index c66e192448a8..f6875a2cc706 100644
--- a/fs/xfs/xfs_ioctl32.c
+++ b/fs/xfs/xfs_ioctl32.c
@@ -44,26 +44,46 @@ xfs_compat_ioc_fsgeometry_v1(
return 0;
}
-STATIC int
-xfs_compat_growfs_data_copyin(
- struct xfs_growfs_data *in,
- compat_xfs_growfs_data_t __user *arg32)
+static int
+xfs_compat_ioc_growfs_data(
+ struct file *file,
+ struct xfs_mount *mp,
+ struct compat_xfs_growfs_data __user *arg32)
{
- if (get_user(in->newblocks, &arg32->newblocks) ||
- get_user(in->imaxpct, &arg32->imaxpct))
+ struct xfs_growfs_data in = { };
+ int error;
+
+ if (get_user(in.newblocks, &arg32->newblocks) ||
+ get_user(in.imaxpct, &arg32->imaxpct))
return -EFAULT;
- return 0;
+
+ error = mnt_want_write_file(file);
+ if (error)
+ return error;
+ error = xfs_growfs_data(mp, &in);
+ mnt_drop_write_file(file);
+ return error;
}
-STATIC int
-xfs_compat_growfs_rt_copyin(
- struct xfs_growfs_rt *in,
- compat_xfs_growfs_rt_t __user *arg32)
+static int
+xfs_compat_ioc_growfs_rt(
+ struct file *file,
+ struct xfs_mount *mp,
+ struct compat_xfs_growfs_rt __user *arg32)
{
- if (get_user(in->newblocks, &arg32->newblocks) ||
- get_user(in->extsize, &arg32->extsize))
+ struct xfs_growfs_rt in = {};
+ int error;
+
+ if (get_user(in.newblocks, &arg32->newblocks) ||
+ get_user(in.extsize, &arg32->extsize))
return -EFAULT;
- return 0;
+
+ error = mnt_want_write_file(file);
+ if (error)
+ return error;
+ error = xfs_growfs_rt(mp, &in);
+ mnt_drop_write_file(file);
+ return error;
}
STATIC int
@@ -138,6 +158,27 @@ xfs_ioctl32_bstat_copyin(
return 0;
}
+static int
+xfs_compat_ioc_swapext(
+ struct file *file,
+ struct compat_xfs_swapext __user *sxu)
+{
+ struct xfs_swapext sxp;
+ int error;
+
+ /* Bulk copy in up to the sx_stat field, then copy bstat */
+ if (copy_from_user(&sxp, sxu, offsetof(struct xfs_swapext, sx_stat)) ||
+ xfs_ioctl32_bstat_copyin(&sxp.sx_stat, &sxu->sx_stat))
+ return -EFAULT;
+
+ error = mnt_want_write_file(file);
+ if (error)
+ return error;
+ error = xfs_swapext(&sxp);
+ mnt_drop_write_file(file);
+ return error;
+}
+
/* XFS_IOC_FSBULKSTAT and friends */
STATIC int
@@ -338,6 +379,43 @@ xfs_compat_handlereq_to_dentry(
compat_ptr(hreq->ihandle), hreq->ihandlen);
}
+static int
+xfs_compat_ioc_find_handle(
+ unsigned int cmd,
+ void __user *arg)
+{
+ struct xfs_fsop_handlereq hreq;
+
+ if (xfs_compat_handlereq_copyin(&hreq, arg))
+ return -EFAULT;
+ return xfs_find_handle(_NATIVE_IOC(cmd, struct xfs_fsop_handlereq),
+ &hreq);
+}
+
+static int
+xfs_compat_ioc_open_by_handle(
+ struct file *file,
+ void __user *arg)
+{
+ struct xfs_fsop_handlereq hreq;
+
+ if (xfs_compat_handlereq_copyin(&hreq, arg))
+ return -EFAULT;
+ return xfs_open_by_handle(file, &hreq);
+}
+
+static int
+xfs_compat_ioc_readlink_by_handle(
+ struct file *file,
+ void __user *arg)
+{
+ struct xfs_fsop_handlereq hreq;
+
+ if (xfs_compat_handlereq_copyin(&hreq, arg))
+ return -EFAULT;
+ return xfs_readlink_by_handle(file, &hreq);
+}
+
STATIC int
xfs_compat_attrlist_by_handle(
struct file *parfilp,
@@ -426,7 +504,6 @@ xfs_file_compat_ioctl(
struct inode *inode = file_inode(filp);
struct xfs_inode *ip = XFS_I(inode);
void __user *arg = compat_ptr(p);
- int error;
trace_xfs_file_compat_ioctl(ip);
@@ -434,85 +511,34 @@ xfs_file_compat_ioctl(
#if defined(BROKEN_X86_ALIGNMENT)
case XFS_IOC_FSGEOMETRY_V1_32:
return xfs_compat_ioc_fsgeometry_v1(ip->i_mount, arg);
- case XFS_IOC_FSGROWFSDATA_32: {
- struct xfs_growfs_data in;
-
- if (xfs_compat_growfs_data_copyin(&in, arg))
- return -EFAULT;
- error = mnt_want_write_file(filp);
- if (error)
- return error;
- error = xfs_growfs_data(ip->i_mount, &in);
- mnt_drop_write_file(filp);
- return error;
- }
- case XFS_IOC_FSGROWFSRT_32: {
- struct xfs_growfs_rt in;
-
- if (xfs_compat_growfs_rt_copyin(&in, arg))
- return -EFAULT;
- error = mnt_want_write_file(filp);
- if (error)
- return error;
- error = xfs_growfs_rt(ip->i_mount, &in);
- mnt_drop_write_file(filp);
- return error;
- }
+ case XFS_IOC_FSGROWFSDATA_32:
+ return xfs_compat_ioc_growfs_data(filp, ip->i_mount, arg);
+ case XFS_IOC_FSGROWFSRT_32:
+ return xfs_compat_ioc_growfs_rt(filp, ip->i_mount, arg);
#endif
- /* long changes size, but xfs only copiese out 32 bits */
case XFS_IOC_GETVERSION_32:
- cmd = _NATIVE_IOC(cmd, long);
- return xfs_file_ioctl(filp, cmd, p);
- case XFS_IOC_SWAPEXT_32: {
- struct xfs_swapext sxp;
- struct compat_xfs_swapext __user *sxu = arg;
-
- /* Bulk copy in up to the sx_stat field, then copy bstat */
- if (copy_from_user(&sxp, sxu,
- offsetof(struct xfs_swapext, sx_stat)) ||
- xfs_ioctl32_bstat_copyin(&sxp.sx_stat, &sxu->sx_stat))
- return -EFAULT;
- error = mnt_want_write_file(filp);
- if (error)
- return error;
- error = xfs_ioc_swapext(&sxp);
- mnt_drop_write_file(filp);
- return error;
- }
+ /* long changes size, but xfs only copies out 32 bits */
+ return xfs_file_ioctl(filp, _NATIVE_IOC(cmd, long), p);
+ case XFS_IOC_SWAPEXT_32:
+ return xfs_compat_ioc_swapext(filp, arg);
case XFS_IOC_FSBULKSTAT_32:
case XFS_IOC_FSBULKSTAT_SINGLE_32:
case XFS_IOC_FSINUMBERS_32:
return xfs_compat_ioc_fsbulkstat(filp, cmd, arg);
case XFS_IOC_FD_TO_HANDLE_32:
case XFS_IOC_PATH_TO_HANDLE_32:
- case XFS_IOC_PATH_TO_FSHANDLE_32: {
- struct xfs_fsop_handlereq hreq;
-
- if (xfs_compat_handlereq_copyin(&hreq, arg))
- return -EFAULT;
- cmd = _NATIVE_IOC(cmd, struct xfs_fsop_handlereq);
- return xfs_find_handle(cmd, &hreq);
- }
- case XFS_IOC_OPEN_BY_HANDLE_32: {
- struct xfs_fsop_handlereq hreq;
-
- if (xfs_compat_handlereq_copyin(&hreq, arg))
- return -EFAULT;
- return xfs_open_by_handle(filp, &hreq);
- }
- case XFS_IOC_READLINK_BY_HANDLE_32: {
- struct xfs_fsop_handlereq hreq;
-
- if (xfs_compat_handlereq_copyin(&hreq, arg))
- return -EFAULT;
- return xfs_readlink_by_handle(filp, &hreq);
- }
+ case XFS_IOC_PATH_TO_FSHANDLE_32:
+ return xfs_compat_ioc_find_handle(cmd, arg);
+ case XFS_IOC_OPEN_BY_HANDLE_32:
+ return xfs_compat_ioc_open_by_handle(filp, arg);
+ case XFS_IOC_READLINK_BY_HANDLE_32:
+ return xfs_compat_ioc_readlink_by_handle(filp, arg);
case XFS_IOC_ATTRLIST_BY_HANDLE_32:
return xfs_compat_attrlist_by_handle(filp, arg);
case XFS_IOC_ATTRMULTI_BY_HANDLE_32:
return xfs_compat_attrmulti_by_handle(filp, arg);
default:
/* try the native version */
- return xfs_file_ioctl(filp, cmd, (unsigned long)arg);
+ return xfs_file_ioctl(filp, cmd, p);
}
}
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index 54d00d543b51..008fed8624be 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -1294,11 +1294,7 @@ xfs_qm_quotacheck_dqadjust(
*
* There are no timers for the default values set in the root dquot.
*/
- if (dqp->q_id) {
- xfs_qm_adjust_dqlimits(dqp);
- xfs_qm_adjust_dqtimers(dqp);
- }
-
+ xfs_qm_adjust_dqenforcement(dqp);
dqp->q_flags |= XFS_DQFLAG_DIRTY;
out_unlock:
mutex_unlock(&dqp->q_qlock);
diff --git a/fs/xfs/xfs_rmap_item.c b/fs/xfs/xfs_rmap_item.c
index 000cff1ce324..be2d5d6fe863 100644
--- a/fs/xfs/xfs_rmap_item.c
+++ b/fs/xfs/xfs_rmap_item.c
@@ -494,7 +494,7 @@ xfs_rui_validate_map(
!xfs_verify_ino(mp, map->me_owner))
return false;
- if (!xfs_verify_fileext(mp, map->me_startoff, map->me_len))
+ if (!xfs_verify_fileext(map->me_startoff, map->me_len))
return false;
if (isrt)
diff --git a/fs/xfs/xfs_rtalloc.h b/fs/xfs/xfs_rtalloc.h
index 78a690b489ed..1d5108861acd 100644
--- a/fs/xfs/xfs_rtalloc.h
+++ b/fs/xfs/xfs_rtalloc.h
@@ -46,10 +46,34 @@ int xfs_rtalloc_reinit_frextents(struct xfs_mount *mp);
int xfs_growfs_check_rtgeom(const struct xfs_mount *mp, xfs_rfsblock_t dblocks,
xfs_rfsblock_t rblocks, xfs_agblock_t rextsize);
#else
-# define xfs_growfs_rt(mp,in) (-ENOSYS)
-# define xfs_rtalloc_reinit_frextents(m) (0)
-# define xfs_rtmount_readsb(mp) (0)
-# define xfs_rtmount_freesb(mp) ((void)0)
+static inline int
+xfs_growfs_rt(
+ struct xfs_mount *mp,
+ struct xfs_growfs_rt *in)
+{
+ return -ENOSYS;
+}
+
+static inline int
+xfs_rtalloc_reinit_frextents(
+ struct xfs_mount *mp)
+{
+ return 0;
+}
+
+static inline int
+xfs_rtmount_readsb(
+ struct xfs_mount *mp)
+{
+ return 0;
+}
+
+static inline void
+xfs_rtmount_freesb(
+ struct xfs_mount *mp)
+{
+}
+
static inline int /* error */
xfs_rtmount_init(
xfs_mount_t *mp) /* file system mount structure */
@@ -60,8 +84,21 @@ xfs_rtmount_init(
xfs_warn(mp, "Not built with CONFIG_XFS_RT");
return -ENOSYS;
}
-# define xfs_rtmount_inodes(m) (((mp)->m_sb.sb_rblocks == 0)? 0 : (-ENOSYS))
-# define xfs_rtunmount_inodes(m)
+
+static inline int
+xfs_rtmount_inodes(
+ struct xfs_mount *mp)
+{
+ if (mp->m_sb.sb_rblocks)
+ return -ENOSYS;
+ return 0;
+}
+
+static inline void
+xfs_rtunmount_inodes(
+ struct xfs_mount *mp)
+{
+}
static inline int
xfs_growfs_check_rtgeom(const struct xfs_mount *mp,
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index b24db75eaedc..2edc2a497883 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -1889,7 +1889,7 @@ xfs_fs_fill_super(
* Avoid integer overflow by comparing the maximum bmbt offset to the
* maximum pagecache offset in units of fs blocks.
*/
- if (!xfs_verify_fileoff(mp, XFS_B_TO_FSBT(mp, MAX_LFS_FILESIZE))) {
+ if (!xfs_verify_fileoff(XFS_B_TO_FSBT(mp, MAX_LFS_FILESIZE))) {
xfs_warn(mp,
"MAX_LFS_FILESIZE block offset (%llu) exceeds extent map maximum (%llu)!",
XFS_B_TO_FSBT(mp, MAX_LFS_FILESIZE),
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
index 5585ac7f4d16..cc13819df6f2 100644
--- a/fs/xfs/xfs_symlink.c
+++ b/fs/xfs/xfs_symlink.c
@@ -219,7 +219,7 @@ xfs_symlink(
*ipp = du.ip;
xfs_iunlock(du.ip, XFS_ILOCK_EXCL);
xfs_iunlock(dp, XFS_ILOCK_EXCL);
- xfs_parent_finish(mp, du.ppargs);
+ xfs_parent_finish(du.ppargs);
return 0;
out_trans_cancel:
@@ -236,7 +236,7 @@ out_release_inode:
xfs_irele(du.ip);
}
out_parent:
- xfs_parent_finish(mp, du.ppargs);
+ xfs_parent_finish(du.ppargs);
out_release_dquots:
xfs_qm_dqrele(udqp);
xfs_qm_dqrele(gdqp);
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 6aa379c2cf0c..0fc8927339b5 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -6030,32 +6030,54 @@ DEFINE_HEALTHMON_EVENT(xfs_healthmon_detach);
DEFINE_HEALTHMON_EVENT(xfs_healthmon_report_unmount);
#define XFS_HEALTHMON_TYPE_STRINGS \
+ { XFS_HEALTHMON_RUNNING, "run" }, \
{ XFS_HEALTHMON_LOST, "lost" }, \
{ XFS_HEALTHMON_UNMOUNT, "unmount" }, \
+ { XFS_HEALTHMON_SHUTDOWN, "shutdown" }, \
{ XFS_HEALTHMON_SICK, "sick" }, \
{ XFS_HEALTHMON_CORRUPT, "corrupt" }, \
{ XFS_HEALTHMON_HEALTHY, "healthy" }, \
- { XFS_HEALTHMON_SHUTDOWN, "shutdown" }
+ { XFS_HEALTHMON_MEDIA_ERROR, "media" }, \
+ { XFS_HEALTHMON_BUFREAD, "bufread" }, \
+ { XFS_HEALTHMON_BUFWRITE, "bufwrite" }, \
+ { XFS_HEALTHMON_DIOREAD, "dioread" }, \
+ { XFS_HEALTHMON_DIOWRITE, "diowrite" }, \
+ { XFS_HEALTHMON_DATALOST, "datalost" }
#define XFS_HEALTHMON_DOMAIN_STRINGS \
{ XFS_HEALTHMON_MOUNT, "mount" }, \
{ XFS_HEALTHMON_FS, "fs" }, \
{ XFS_HEALTHMON_AG, "ag" }, \
{ XFS_HEALTHMON_INODE, "inode" }, \
- { XFS_HEALTHMON_RTGROUP, "rtgroup" }
+ { XFS_HEALTHMON_RTGROUP, "rtgroup" }, \
+ { XFS_HEALTHMON_DATADEV, "datadev" }, \
+ { XFS_HEALTHMON_RTDEV, "rtdev" }, \
+ { XFS_HEALTHMON_LOGDEV, "logdev" }, \
+ { XFS_HEALTHMON_FILERANGE, "filerange" }
+TRACE_DEFINE_ENUM(XFS_HEALTHMON_RUNNING);
TRACE_DEFINE_ENUM(XFS_HEALTHMON_LOST);
-TRACE_DEFINE_ENUM(XFS_HEALTHMON_SHUTDOWN);
TRACE_DEFINE_ENUM(XFS_HEALTHMON_UNMOUNT);
+TRACE_DEFINE_ENUM(XFS_HEALTHMON_SHUTDOWN);
TRACE_DEFINE_ENUM(XFS_HEALTHMON_SICK);
TRACE_DEFINE_ENUM(XFS_HEALTHMON_CORRUPT);
TRACE_DEFINE_ENUM(XFS_HEALTHMON_HEALTHY);
+TRACE_DEFINE_ENUM(XFS_HEALTHMON_MEDIA_ERROR);
+TRACE_DEFINE_ENUM(XFS_HEALTHMON_BUFREAD);
+TRACE_DEFINE_ENUM(XFS_HEALTHMON_BUFWRITE);
+TRACE_DEFINE_ENUM(XFS_HEALTHMON_DIOREAD);
+TRACE_DEFINE_ENUM(XFS_HEALTHMON_DIOWRITE);
+TRACE_DEFINE_ENUM(XFS_HEALTHMON_DATALOST);
TRACE_DEFINE_ENUM(XFS_HEALTHMON_MOUNT);
TRACE_DEFINE_ENUM(XFS_HEALTHMON_FS);
TRACE_DEFINE_ENUM(XFS_HEALTHMON_AG);
TRACE_DEFINE_ENUM(XFS_HEALTHMON_INODE);
TRACE_DEFINE_ENUM(XFS_HEALTHMON_RTGROUP);
+TRACE_DEFINE_ENUM(XFS_HEALTHMON_DATADEV);
+TRACE_DEFINE_ENUM(XFS_HEALTHMON_RTDEV);
+TRACE_DEFINE_ENUM(XFS_HEALTHMON_LOGDEV);
+TRACE_DEFINE_ENUM(XFS_HEALTHMON_FILERANGE);
DECLARE_EVENT_CLASS(xfs_healthmon_event_class,
TP_PROTO(const struct xfs_healthmon *hm,
diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
index 1606c614f205..93ec876792cc 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -566,11 +566,7 @@ xfs_trans_apply_dquot_deltas(
* Get any default limits in use.
* Start/reset the timer(s) if needed.
*/
- if (dqp->q_id) {
- xfs_qm_adjust_dqlimits(dqp);
- xfs_qm_adjust_dqtimers(dqp);
- }
-
+ xfs_qm_adjust_dqenforcement(dqp);
dqp->q_flags |= XFS_DQFLAG_DIRTY;
/*
* add this to the list of items to get logged