xfs: log new xattr values for NVREPLACEXXX operations
For NVREPLACEXXX operations, make it possible to log the old and new
attr values, since this variant does VLOOKUP operations.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
index 95b11ec..3c7fb09 100644
--- a/libxfs/xfs_attr.c
+++ b/libxfs/xfs_attr.c
@@ -430,13 +430,15 @@
/*
* NVREPLACE operations require the caller to set the old and new names
- * explicitly.
+ * and values explicitly.
*/
ASSERT(args->new_namelen > 0);
args->name = args->new_name;
args->namelen = args->new_namelen;
args->hashval = xfs_da_hashname(args->name, args->namelen);
+ args->value = args->new_value;
+ args->valuelen = args->new_valuelen;
return replace_state;
}
diff --git a/libxfs/xfs_da_btree.h b/libxfs/xfs_da_btree.h
index 6132787..3f3313a 100644
--- a/libxfs/xfs_da_btree.h
+++ b/libxfs/xfs_da_btree.h
@@ -60,7 +60,9 @@
int new_namelen; /* new attr name len */
uint8_t filetype; /* filetype of inode for directories */
void *value; /* set of bytes (maybe contain NULLs) */
+ void *new_value; /* new xattr value (may contain NULLs) */
int valuelen; /* length of value */
+ int new_valuelen; /* length of new value */
unsigned int attr_filter; /* XFS_ATTR_{ROOT,SECURE,INCOMPLETE} */
unsigned int attr_flags; /* XATTR_{CREATE,REPLACE} */
xfs_dahash_t hashval; /* hash value of name */
diff --git a/libxfs/xfs_log_format.h b/libxfs/xfs_log_format.h
index a1581dc..711654f 100644
--- a/libxfs/xfs_log_format.h
+++ b/libxfs/xfs_log_format.h
@@ -115,11 +115,11 @@
#define XLOG_REG_TYPE_BUD_FORMAT 26
#define XLOG_REG_TYPE_ATTRI_FORMAT 27
#define XLOG_REG_TYPE_ATTRD_FORMAT 28
-#define XLOG_REG_TYPE_ATTR_NAME 29
+#define XLOG_REG_TYPE_ATTR_NAME 29
#define XLOG_REG_TYPE_ATTR_VALUE 30
#define XLOG_REG_TYPE_ATTR_NEWNAME 31
-#define XLOG_REG_TYPE_MAX 31
-
+#define XLOG_REG_TYPE_ATTR_NEWVALUE 32
+#define XLOG_REG_TYPE_MAX 32
/*
* Flags to log operation header
@@ -980,7 +980,13 @@
struct xfs_attri_log_format {
uint16_t alfi_type; /* attri log item type */
uint16_t alfi_size; /* size of this item */
- uint32_t __pad; /* pad to 64 bit aligned */
+
+ /*
+ * For NVREPLACEXXX, this is the length of the new xattr value.
+ * alfi_value_len contains the length of the old xattr value.
+ */
+ uint32_t alfi_newvalue_len;
+
uint64_t alfi_id; /* attri identifier */
uint64_t alfi_ino; /* the inode for this attr operation */
uint32_t alfi_op_flags; /* marks the op as a set or remove */
diff --git a/logprint/log_redo.c b/logprint/log_redo.c
index af6c62b..c705bb1 100644
--- a/logprint/log_redo.c
+++ b/logprint/log_redo.c
@@ -700,18 +700,22 @@
const void *newname_ptr,
unsigned int newname_len,
const void *value_ptr,
- unsigned int value_len)
+ unsigned int value_len,
+ const void *newvalue_ptr,
+ unsigned int newvalue_len)
{
if (newname_ptr && name_ptr) {
dump_pptr("OLDNAME", name_ptr, name_len, value_ptr, value_len);
- dump_pptr("NEWNAME", newname_ptr, newname_len, "", 0);
+ dump_pptr("NEWNAME", newname_ptr, newname_len, newvalue_ptr,
+ newvalue_len);
return;
}
if (name_ptr)
dump_pptr("NAME", name_ptr, name_len, value_ptr, value_len);
if (newname_ptr)
- dump_pptr("NNAME", newname_ptr, newname_len, NULL, 0);
+ dump_pptr("NNAME", newname_ptr, newname_len, newvalue_ptr,
+ newvalue_len);
}
static inline unsigned int
@@ -729,9 +733,10 @@
struct xfs_attri_log_format *src_f = NULL;
xlog_op_header_t *head = NULL;
void *name_ptr = NULL, *newname_ptr = NULL;
- void *value_ptr = NULL;
+ void *value_ptr = NULL, *newvalue_ptr = NULL;
uint dst_len;
unsigned int name_len, newname_len = 0;
+ unsigned int value_len = 0, newvalue_len = 0;
int error = 0;
dst_len = sizeof(struct xfs_attri_log_format);
@@ -757,21 +762,26 @@
if (xfs_attr_log_item_op(src_f) == XFS_ATTRI_OP_FLAGS_NVREPLACEXXX) {
name_len = src_f->alfi_oldname_len;
newname_len = src_f->alfi_newname_len;
+ value_len = src_f->alfi_value_len;
+ newvalue_len = src_f->alfi_newvalue_len;
} else if (xfs_attr_log_item_op(src_f) == XFS_ATTRI_OP_FLAGS_NVREPLACE) {
name_len = src_f->alfi_oldname_len;
newname_len = src_f->alfi_newname_len;
+ value_len = src_f->alfi_value_len;
} else {
name_len = src_f->alfi_name_len;
+ value_len = src_f->alfi_value_len;
}
- printf(_("ATTRI: #regs: %d f: 0x%x, ino: 0x%llx, attr_filter: 0x%x, name_len: %d, newname_len: %d, value_len: %d id: 0x%llx\n"),
+ printf(_("ATTRI: #regs: %d f: 0x%x, ino: 0x%llx, attr_filter: 0x%x, name_len: %d, newname_len: %d, value_len: %d, newvalue_len: %d id: 0x%llx\n"),
src_f->alfi_size,
src_f->alfi_op_flags,
(unsigned long long)src_f->alfi_ino,
src_f->alfi_attr_filter,
name_len,
newname_len,
- src_f->alfi_value_len,
+ value_len,
+ newvalue_len,
(unsigned long long)src_f->alfi_id);
if (name_len > 0) {
@@ -798,14 +808,27 @@
goto error;
}
- if (src_f->alfi_value_len > 0) {
+ if (value_len > 0) {
printf(_("\n"));
(*i)++;
head = (xlog_op_header_t *)*ptr;
xlog_print_op_header(head, *i, ptr);
value_ptr = *ptr;
- error = xlog_print_trans_attri_value(ptr, be32_to_cpu(head->oh_len),
- src_f->alfi_value_len);
+ error = xlog_print_trans_attri_value(ptr,
+ be32_to_cpu(head->oh_len), value_len, "value");
+ if (error)
+ goto error;
+ }
+
+ if (newvalue_len > 0) {
+ printf(_("\n"));
+ (*i)++;
+ head = (xlog_op_header_t *)*ptr;
+ xlog_print_op_header(head, *i, ptr);
+ newvalue_ptr = *ptr;
+ error = xlog_print_trans_attri_value(ptr,
+ be32_to_cpu(head->oh_len), newvalue_len,
+ "newvalue");
if (error)
goto error;
}
@@ -813,7 +836,8 @@
if (src_f->alfi_attr_filter & XFS_ATTR_PARENT)
dump_pptr_update(name_ptr, name_len,
newname_ptr, newname_len,
- value_ptr, src_f->alfi_value_len);
+ value_ptr, value_len,
+ newvalue_ptr, newvalue_len);
error:
free(src_f);
@@ -838,17 +862,18 @@
xlog_print_trans_attri_value(
char **ptr,
uint src_len,
- int value_len)
+ unsigned int value_len,
+ const char *tag)
{
int len = min(value_len, src_len);
- printf(_("ATTRI: value len:%u\n"), value_len);
+ printf(_("ATTRI: %s len: %u\n"), tag, value_len);
print_or_dump(*ptr, len);
*ptr += src_len;
return 0;
-} /* xlog_print_trans_attri_value */
+}
void
xlog_recover_print_attri(
@@ -857,8 +882,9 @@
struct xfs_attri_log_format *f, *src_f = NULL;
uint src_len, dst_len;
void *name_ptr = NULL, *newname_ptr = NULL;
- void *value_ptr = NULL;
+ void *value_ptr = NULL, *newvalue_ptr = NULL;
unsigned int name_len, newname_len = 0;
+ unsigned int value_len = 0, newvalue_len = 0;
int region = 0;
src_f = (struct xfs_attri_log_format *)item->ri_buf[0].i_addr;
@@ -881,21 +907,26 @@
if (xfs_attr_log_item_op(f) == XFS_ATTRI_OP_FLAGS_NVREPLACEXXX) {
name_len = f->alfi_oldname_len;
newname_len = f->alfi_newname_len;
+ value_len = f->alfi_value_len;
+ newvalue_len = f->alfi_newvalue_len;
} else if (xfs_attr_log_item_op(f) == XFS_ATTRI_OP_FLAGS_NVREPLACE) {
name_len = f->alfi_oldname_len;
newname_len = f->alfi_newname_len;
+ value_len = f->alfi_value_len;
} else {
name_len = f->alfi_name_len;
+ value_len = f->alfi_value_len;
}
- printf(_("ATTRI: #regs: %d f: 0x%x, ino: 0x%llx, attr_filter: 0x%x, name_len: %d, newname_len:%d, value_len: %d id: 0x%llx\n"),
+ printf(_("ATTRI: #regs: %d f: 0x%x, ino: 0x%llx, attr_filter: 0x%x, name_len: %d, newname_len:%d, value_len: %d, newvalue_len: %d id: 0x%llx\n"),
f->alfi_size,
f->alfi_op_flags,
(unsigned long long)f->alfi_ino,
f->alfi_attr_filter,
name_len,
newname_len,
- f->alfi_value_len,
+ value_len,
+ newvalue_len,
(unsigned long long)f->alfi_id);
if (name_len > 0) {
@@ -913,22 +944,29 @@
newname_ptr = item->ri_buf[region].i_addr;
}
- if (f->alfi_value_len > 0) {
- int len = f->alfi_value_len;
-
- if (len > MAX_ATTR_VAL_PRINT)
- len = MAX_ATTR_VAL_PRINT;
+ if (value_len > 0) {
+ int len = min(MAX_ATTR_VAL_PRINT, value_len);
region++;
- printf(_("ATTRI: value len:%u\n"), f->alfi_value_len);
+ printf(_("ATTRI: value len:%u\n"), value_len);
print_or_dump((char *)item->ri_buf[region].i_addr, len);
value_ptr = item->ri_buf[region].i_addr;
}
+ if (newvalue_len > 0) {
+ int len = min(MAX_ATTR_VAL_PRINT, newvalue_len);
+
+ region++;
+ printf(_("ATTRI: newvalue len:%u\n"), newvalue_len);
+ print_or_dump((char *)item->ri_buf[region].i_addr, len);
+ newvalue_ptr = item->ri_buf[region].i_addr;
+ }
+
if (src_f->alfi_attr_filter & XFS_ATTR_PARENT)
dump_pptr_update(name_ptr, name_len,
newname_ptr, newname_len,
- value_ptr, src_f->alfi_value_len);
+ value_ptr, value_len,
+ newvalue_ptr, newvalue_len);
out:
free(f);
diff --git a/logprint/logprint.h b/logprint/logprint.h
index 067226f..51ba061 100644
--- a/logprint/logprint.h
+++ b/logprint/logprint.h
@@ -60,7 +60,8 @@
extern int xlog_print_trans_attri(char **ptr, uint src_len, int *i);
extern int xlog_print_trans_attri_name(char **ptr, uint src_len, const char *tag);
-extern int xlog_print_trans_attri_value(char **ptr, uint src_len, int value_len);
+extern int xlog_print_trans_attri_value(char **ptr, uint src_len,
+ unsigned int value_len, const char *tag);
extern void xlog_recover_print_attri(struct xlog_recover_item *item);
extern int xlog_print_trans_attrd(char **ptr, uint len);
extern void xlog_recover_print_attrd(struct xlog_recover_item *item);