* [PATCH 1/2] xfsprogs: Pass xattr name and value length explicitly to xfs_attr_leaf_newentsize
@ 2020-01-10 4:30 Chandan Rajendra
2020-01-10 4:30 ` [PATCH 2/2] xfsprogs: Fix log reservation calculation for xattr insert operation Chandan Rajendra
0 siblings, 1 reply; 2+ messages in thread
From: Chandan Rajendra @ 2020-01-10 4:30 UTC (permalink / raw)
Cc: Chandan Rajendra, david, chandan, darrick.wong, linux-xfs
This commit changes xfs_attr_leaf_newentsize() to explicitly accept name and
value length instead of a pointer to struct xfs_da_args. The next commit will
need to invoke xfs_attr_leaf_newentsize() from functions that do not have
a struct xfs_da_args to pass in.
Signed-off-by: Chandan Rajendra <chandanrlinux@gmail.com>
---
libxfs/xfs_attr.c | 3 ++-
libxfs/xfs_attr_leaf.c | 33 +++++++++++++++++++++++----------
libxfs/xfs_attr_leaf.h | 3 ++-
3 files changed, 27 insertions(+), 12 deletions(-)
diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
index ada1b5f4..2a0050f4 100644
--- a/libxfs/xfs_attr.c
+++ b/libxfs/xfs_attr.c
@@ -198,7 +198,8 @@ xfs_attr_calc_size(
* Determine space new attribute will use, and if it would be
* "local" or "remote" (note: local != inline).
*/
- size = xfs_attr_leaf_newentsize(args, local);
+ size = xfs_attr_leaf_newentsize(mp, args->namelen, args->valuelen,
+ local);
nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
if (*local) {
if (size > (args->geo->blksize / 2)) {
diff --git a/libxfs/xfs_attr_leaf.c b/libxfs/xfs_attr_leaf.c
index 0249a0a9..ca7f6761 100644
--- a/libxfs/xfs_attr_leaf.c
+++ b/libxfs/xfs_attr_leaf.c
@@ -1272,7 +1272,8 @@ xfs_attr3_leaf_add(
leaf = bp->b_addr;
xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
ASSERT(args->index >= 0 && args->index <= ichdr.count);
- entsize = xfs_attr_leaf_newentsize(args, NULL);
+ entsize = xfs_attr_leaf_newentsize(args->dp->i_mount, args->namelen,
+ args->valuelen, NULL);
/*
* Search through freemap for first-fit on new name length.
@@ -1374,11 +1375,14 @@ xfs_attr3_leaf_add_work(
ASSERT(ichdr->freemap[mapindex].base < args->geo->blksize);
ASSERT((ichdr->freemap[mapindex].base & 0x3) == 0);
ASSERT(ichdr->freemap[mapindex].size >=
- xfs_attr_leaf_newentsize(args, NULL));
+ xfs_attr_leaf_newentsize(mp, args->namelen,
+ args->valuelen, NULL));
ASSERT(ichdr->freemap[mapindex].size < args->geo->blksize);
ASSERT((ichdr->freemap[mapindex].size & 0x3) == 0);
- ichdr->freemap[mapindex].size -= xfs_attr_leaf_newentsize(args, &tmp);
+ ichdr->freemap[mapindex].size -=
+ xfs_attr_leaf_newentsize(mp, args->namelen, args->valuelen,
+ &tmp);
entry->nameidx = cpu_to_be16(ichdr->freemap[mapindex].base +
ichdr->freemap[mapindex].size);
@@ -1763,6 +1767,7 @@ xfs_attr3_leaf_figure_balance(
struct xfs_attr_leafblock *leaf1 = blk1->bp->b_addr;
struct xfs_attr_leafblock *leaf2 = blk2->bp->b_addr;
struct xfs_attr_leaf_entry *entry;
+ struct xfs_da_args *args;
int count;
int max;
int index;
@@ -1772,6 +1777,7 @@ xfs_attr3_leaf_figure_balance(
int foundit = 0;
int tmp;
+ args = state->args;
/*
* Examine entries until we reduce the absolute difference in
* byte usage between the two blocks to a minimum.
@@ -1779,7 +1785,8 @@ xfs_attr3_leaf_figure_balance(
max = ichdr1->count + ichdr2->count;
half = (max + 1) * sizeof(*entry);
half += ichdr1->usedbytes + ichdr2->usedbytes +
- xfs_attr_leaf_newentsize(state->args, NULL);
+ xfs_attr_leaf_newentsize(state->mp, args->namelen,
+ args->valuelen, NULL);
half /= 2;
lastdelta = state->args->geo->blksize;
entry = xfs_attr3_leaf_entryp(leaf1);
@@ -1791,7 +1798,10 @@ xfs_attr3_leaf_figure_balance(
*/
if (count == blk1->index) {
tmp = totallen + sizeof(*entry) +
- xfs_attr_leaf_newentsize(state->args, NULL);
+ xfs_attr_leaf_newentsize(state->mp,
+ args->namelen,
+ args->valuelen,
+ NULL);
if (XFS_ATTR_ABS(half - tmp) > lastdelta)
break;
lastdelta = XFS_ATTR_ABS(half - tmp);
@@ -1827,7 +1837,8 @@ xfs_attr3_leaf_figure_balance(
totallen -= count * sizeof(*entry);
if (foundit) {
totallen -= sizeof(*entry) +
- xfs_attr_leaf_newentsize(state->args, NULL);
+ xfs_attr_leaf_newentsize(state->mp, args->namelen,
+ args->valuelen, NULL);
}
*countarg = count;
@@ -2613,20 +2624,22 @@ xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index)
*/
int
xfs_attr_leaf_newentsize(
- struct xfs_da_args *args,
+ struct xfs_mount *mp,
+ int namelen,
+ int valuelen,
int *local)
{
int size;
- size = xfs_attr_leaf_entsize_local(args->namelen, args->valuelen);
- if (size < xfs_attr_leaf_entsize_local_max(args->geo->blksize)) {
+ size = xfs_attr_leaf_entsize_local(namelen, valuelen);
+ if (size < xfs_attr_leaf_entsize_local_max(mp->m_attr_geo->blksize)) {
if (local)
*local = 1;
return size;
}
if (local)
*local = 0;
- return xfs_attr_leaf_entsize_remote(args->namelen);
+ return xfs_attr_leaf_entsize_remote(namelen);
}
diff --git a/libxfs/xfs_attr_leaf.h b/libxfs/xfs_attr_leaf.h
index 7b74e18b..7334d43a 100644
--- a/libxfs/xfs_attr_leaf.h
+++ b/libxfs/xfs_attr_leaf.h
@@ -83,7 +83,8 @@ void xfs_attr3_leaf_unbalance(struct xfs_da_state *state,
xfs_dahash_t xfs_attr_leaf_lasthash(struct xfs_buf *bp, int *count);
int xfs_attr_leaf_order(struct xfs_buf *leaf1_bp,
struct xfs_buf *leaf2_bp);
-int xfs_attr_leaf_newentsize(struct xfs_da_args *args, int *local);
+int xfs_attr_leaf_newentsize(struct xfs_mount *mp, int namelen,
+ int valuelen, int *local);
int xfs_attr3_leaf_read(struct xfs_trans *tp, struct xfs_inode *dp,
xfs_dablk_t bno, xfs_daddr_t mappedbno,
struct xfs_buf **bpp);
--
2.19.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* [PATCH 2/2] xfsprogs: Fix log reservation calculation for xattr insert operation
2020-01-10 4:30 [PATCH 1/2] xfsprogs: Pass xattr name and value length explicitly to xfs_attr_leaf_newentsize Chandan Rajendra
@ 2020-01-10 4:30 ` Chandan Rajendra
0 siblings, 0 replies; 2+ messages in thread
From: Chandan Rajendra @ 2020-01-10 4:30 UTC (permalink / raw)
Cc: Chandan Rajendra, david, chandan, darrick.wong, linux-xfs
Log space reservation for xattr insert operation can be divided into two
parts,
1. Mount time
- Inode
- Superblock for accounting space allocations
- AGF for accounting space used be count, block number, rmapbt and refcnt
btrees.
2. The remaining log space can only be calculated at run time because,
- A local xattr can be large enough to cause a double split of the dabtree.
- The value of the xattr can be large enough to be stored in remote
blocks. The contents of the remote blocks are not logged.
The log space reservation would be,
- 2 * XFS_DA_NODE_MAXDEPTH number of blocks. Additional XFS_DA_NODE_MAXDEPTH
number of blocks are required if xattr is large enough to cause another
split of the dabtree path from root to leaf block.
- BMBT blocks for storing (2 * XFS_DA_NODE_MAXDEPTH) record
entries. Additional XFS_DA_NODE_MAXDEPTH number of blocks are required in
case of a double split of the dabtree path from root to leaf blocks.
- Space for logging blocks of count, block number, rmap and refcnt btrees.
This commit refactors xfs_attr_calc_size() to calculate the log reservation
space and also the FS reservation space. It then replaces the erroneous
calculation inside xfs_log_calc_max_attrsetm_res() with an invocation of
xfs_attr_calc_size().
Signed-off-by: Chandan Rajendra <chandanrlinux@gmail.com>
---
libxfs/xfs_attr.c | 106 +++++++++++++++++++++++++---------------
libxfs/xfs_attr.h | 4 +-
libxfs/xfs_log_rlimit.c | 13 ++---
libxfs/xfs_trans_resv.c | 34 +++----------
libxfs/xfs_trans_resv.h | 2 +
5 files changed, 84 insertions(+), 75 deletions(-)
diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
index 2a0050f4..36b3bde4 100644
--- a/libxfs/xfs_attr.c
+++ b/libxfs/xfs_attr.c
@@ -182,43 +182,6 @@ xfs_attr_get(
return 0;
}
-/*
- * Calculate how many blocks we need for the new attribute,
- */
-STATIC int
-xfs_attr_calc_size(
- struct xfs_da_args *args,
- int *local)
-{
- struct xfs_mount *mp = args->dp->i_mount;
- int size;
- int nblks;
-
- /*
- * Determine space new attribute will use, and if it would be
- * "local" or "remote" (note: local != inline).
- */
- size = xfs_attr_leaf_newentsize(mp, args->namelen, args->valuelen,
- local);
- nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
- if (*local) {
- if (size > (args->geo->blksize / 2)) {
- /* Double split possible */
- nblks *= 2;
- }
- } else {
- /*
- * Out of line attribute, cannot double split, but
- * make room for the attribute value itself.
- */
- uint dblocks = xfs_attr3_rmt_blocks(mp, args->valuelen);
- nblks += dblocks;
- nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
- }
-
- return nblks;
-}
-
STATIC int
xfs_attr_try_sf_addname(
struct xfs_inode *dp,
@@ -247,6 +210,68 @@ xfs_attr_try_sf_addname(
return error ? error : error2;
}
+/*
+ * Calculate how many blocks we need for the new attribute,
+ */
+void
+xfs_attr_calc_size(
+ struct xfs_mount *mp,
+ int namelen,
+ int valuelen,
+ int *local,
+ unsigned int *log_blks,
+ unsigned int *total_blks)
+{
+ unsigned int blksize;
+ int dabtree_blks;
+ int bmbt_blks;
+ int size;
+ int dblks;
+
+ blksize = mp->m_dir_geo->blksize;
+ dblks = 0;
+ *log_blks = 0;
+ *total_blks = 0;
+
+ /*
+ * Determine space new attribute will use, and if it would be
+ * "local" or "remote" (note: local != inline).
+ */
+ size = xfs_attr_leaf_newentsize(mp, namelen, valuelen, local);
+ dabtree_blks = XFS_DAENTER_BLOCKS(mp, XFS_ATTR_FORK);
+ bmbt_blks = XFS_DAENTER_BMAPS(mp, XFS_ATTR_FORK);
+
+ *log_blks = xfs_calc_buf_res(2 * dabtree_blks, blksize);
+ *log_blks += xfs_calc_buf_res(2 * bmbt_blks, XFS_FSB_TO_B(mp, 1));
+
+ if (*local) {
+ if (size > (blksize / 2)) {
+ /* Double split possible */
+ *log_blks += xfs_calc_buf_res(dabtree_blks, blksize);
+ *log_blks += xfs_calc_buf_res(bmbt_blks,
+ XFS_FSB_TO_B(mp, 1));
+
+ dabtree_blks *= 2;
+ bmbt_blks *= 2;
+ }
+ } else {
+ /*
+ * Out of line attribute, cannot double split, but
+ * make room for the attribute value itself.
+ */
+ dblks = xfs_attr3_rmt_blocks(mp, valuelen);
+ bmbt_blks += XFS_NEXTENTADD_SPACE_RES(mp, dblks, XFS_ATTR_FORK);
+ *log_blks += xfs_calc_buf_res(bmbt_blks, XFS_FSB_TO_B(mp, 1));
+ }
+
+ *log_blks += xfs_calc_buf_res(xfs_allocfree_log_count(mp, dabtree_blks),
+ XFS_FSB_TO_B(mp, 1));
+ *log_blks += xfs_calc_buf_res(xfs_allocfree_log_count(mp, dblks),
+ XFS_FSB_TO_B(mp, 1));
+
+ *total_blks = dabtree_blks + bmbt_blks + dblks;
+}
+
/*
* Set the attribute specified in @args.
*/
@@ -346,6 +371,7 @@ xfs_attr_set(
struct xfs_da_args args;
struct xfs_trans_res tres;
int rsvd = (flags & ATTR_ROOT) != 0;
+ unsigned int log_blks;
int error, local;
XFS_STATS_INC(mp, xs_attr_set);
@@ -360,7 +386,8 @@ xfs_attr_set(
args.value = value;
args.valuelen = valuelen;
args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
- args.total = xfs_attr_calc_size(&args, &local);
+ xfs_attr_calc_size(mp, args.namelen, args.valuelen, &local,
+ &log_blks, &args.total);
error = xfs_qm_dqattach(dp);
if (error)
@@ -379,8 +406,7 @@ xfs_attr_set(
return error;
}
- tres.tr_logres = M_RES(mp)->tr_attrsetm.tr_logres +
- M_RES(mp)->tr_attrsetrt.tr_logres * args.total;
+ tres.tr_logres = M_RES(mp)->tr_attrsetm.tr_logres + log_blks;
tres.tr_logcount = XFS_ATTRSET_LOG_COUNT;
tres.tr_logflags = XFS_TRANS_PERM_LOG_RES;
diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h
index 94badfa1..9c9b301d 100644
--- a/libxfs/xfs_attr.h
+++ b/libxfs/xfs_attr.h
@@ -154,5 +154,7 @@ int xfs_attr_remove_args(struct xfs_da_args *args);
int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
int flags, struct attrlist_cursor_kern *cursor);
bool xfs_attr_namecheck(const void *name, size_t length);
-
+void xfs_attr_calc_size(struct xfs_mount *mp, int namelen, int valuelen,
+ int *local, unsigned int *log_blks,
+ unsigned int *total_blks);
#endif /* __XFS_ATTR_H__ */
diff --git a/libxfs/xfs_log_rlimit.c b/libxfs/xfs_log_rlimit.c
index c8398b7d..2eebbece 100644
--- a/libxfs/xfs_log_rlimit.c
+++ b/libxfs/xfs_log_rlimit.c
@@ -10,6 +10,7 @@
#include "xfs_log_format.h"
#include "xfs_trans_resv.h"
#include "xfs_mount.h"
+#include "xfs_attr.h"
#include "xfs_da_format.h"
#include "xfs_trans_space.h"
#include "xfs_da_btree.h"
@@ -24,16 +25,16 @@ xfs_log_calc_max_attrsetm_res(
struct xfs_mount *mp)
{
int size;
- int nblks;
+ int local;
+ unsigned int total_blks;
+ unsigned int log_blks;
size = xfs_attr_leaf_entsize_local_max(mp->m_attr_geo->blksize) -
MAXNAMELEN - 1;
- nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
- nblks += XFS_B_TO_FSB(mp, size);
- nblks += XFS_NEXTENTADD_SPACE_RES(mp, size, XFS_ATTR_FORK);
+ xfs_attr_calc_size(mp, size, 0, &local, &log_blks, &total_blks);
+ ASSERT(local == 1);
- return M_RES(mp)->tr_attrsetm.tr_logres +
- M_RES(mp)->tr_attrsetrt.tr_logres * nblks;
+ return M_RES(mp)->tr_attrsetm.tr_logres + log_blks;
}
/*
diff --git a/libxfs/xfs_trans_resv.c b/libxfs/xfs_trans_resv.c
index 270e92a3..dfcc0157 100644
--- a/libxfs/xfs_trans_resv.c
+++ b/libxfs/xfs_trans_resv.c
@@ -28,7 +28,7 @@
* to a multiple of 128 bytes so that we don't change the historical
* reservation that has been used for this overhead.
*/
-STATIC uint
+uint
xfs_buf_log_overhead(void)
{
return round_up(sizeof(struct xlog_op_header) +
@@ -42,7 +42,7 @@ xfs_buf_log_overhead(void)
* will be changed in a transaction. size is used to tell how many
* bytes should be reserved per item.
*/
-STATIC uint
+uint
xfs_calc_buf_res(
uint nbufs,
uint size)
@@ -641,12 +641,10 @@ xfs_calc_attrinval_reservation(
* Setting an attribute at mount time.
* the inode getting the attribute
* the superblock for allocations
- * the agfs extents are allocated from
- * the attribute btree * max depth
- * the inode allocation btree
+ * the agf extents are allocated from
* Since attribute transaction space is dependent on the size of the attribute,
* the calculation is done partially at mount time and partially at runtime(see
- * below).
+ * xfs_attr_calc_size()).
*/
STATIC uint
xfs_calc_attrsetm_reservation(
@@ -654,27 +652,7 @@ xfs_calc_attrsetm_reservation(
{
return XFS_DQUOT_LOGRES(mp) +
xfs_calc_inode_res(mp, 1) +
- xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
- xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH, XFS_FSB_TO_B(mp, 1));
-}
-
-/*
- * Setting an attribute at runtime, transaction space unit per block.
- * the superblock for allocations: sector size
- * the inode bmap btree could join or split: max depth * block size
- * Since the runtime attribute transaction space is dependent on the total
- * blocks needed for the 1st bmap, here we calculate out the space unit for
- * one block so that the caller could figure out the total space according
- * to the attibute extent length in blocks by:
- * ext * M_RES(mp)->tr_attrsetrt.tr_logres
- */
-STATIC uint
-xfs_calc_attrsetrt_reservation(
- struct xfs_mount *mp)
-{
- return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
- xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK),
- XFS_FSB_TO_B(mp, 1));
+ xfs_calc_buf_res(2, mp->m_sb.sb_sectsize);
}
/*
@@ -882,7 +860,7 @@ xfs_trans_resv_calc(
resp->tr_ichange.tr_logres = xfs_calc_ichange_reservation(mp);
resp->tr_fsyncts.tr_logres = xfs_calc_swrite_reservation(mp);
resp->tr_writeid.tr_logres = xfs_calc_writeid_reservation(mp);
- resp->tr_attrsetrt.tr_logres = xfs_calc_attrsetrt_reservation(mp);
+ resp->tr_attrsetrt.tr_logres = 0;
resp->tr_clearagi.tr_logres = xfs_calc_clear_agi_bucket_reservation(mp);
resp->tr_growrtzero.tr_logres = xfs_calc_growrtzero_reservation(mp);
resp->tr_growrtfree.tr_logres = xfs_calc_growrtfree_reservation(mp);
diff --git a/libxfs/xfs_trans_resv.h b/libxfs/xfs_trans_resv.h
index 7241ab28..9a7af411 100644
--- a/libxfs/xfs_trans_resv.h
+++ b/libxfs/xfs_trans_resv.h
@@ -91,6 +91,8 @@ struct xfs_trans_resv {
#define XFS_ATTRSET_LOG_COUNT 3
#define XFS_ATTRRM_LOG_COUNT 3
+uint xfs_buf_log_overhead(void);
+uint xfs_calc_buf_res(uint nbufs, uint size);
void xfs_trans_resv_calc(struct xfs_mount *mp, struct xfs_trans_resv *resp);
uint xfs_allocfree_log_count(struct xfs_mount *mp, uint num_ops);
--
2.19.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2020-01-10 4:28 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-01-10 4:30 [PATCH 1/2] xfsprogs: Pass xattr name and value length explicitly to xfs_attr_leaf_newentsize Chandan Rajendra
2020-01-10 4:30 ` [PATCH 2/2] xfsprogs: Fix log reservation calculation for xattr insert operation Chandan Rajendra
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox