* [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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.