@@ -421,6 +421,12 @@ xfs_attr_complete_op(
args->op_flags &= ~XFS_DA_OP_REPLACE;
if (do_replace) {
args->attr_filter &= ~XFS_ATTR_INCOMPLETE;
+ if (args->new_namelen > 0) {
+ args->name = args->new_name;
+ args->namelen = args->new_namelen;
+ args->hashval = xfs_da_hashname(args->name,
+ args->namelen);
+ }
return replace_state;
}
return XFS_DAS_DONE;
@@ -920,9 +926,13 @@ xfs_attr_defer_replace(
struct xfs_da_args *args)
{
struct xfs_attr_intent *new;
+ int op_flag;
int error = 0;
- error = xfs_attr_intent_init(args, XFS_ATTRI_OP_FLAGS_REPLACE, &new);
+ op_flag = args->new_namelen == 0 ? XFS_ATTRI_OP_FLAGS_REPLACE :
+ XFS_ATTRI_OP_FLAGS_NVREPLACE;
+
+ error = xfs_attr_intent_init(args, op_flag, &new);
if (error)
return error;
@@ -510,8 +510,8 @@ struct xfs_attr_intent {
struct xfs_da_args *xattri_da_args;
/*
- * Shared buffer containing the attr name and value so that the logging
- * code can share large memory buffers between log items.
+ * Shared buffer containing the attr name, new name, and value so that
+ * the logging code can share large memory buffers between log items.
*/
struct xfs_attri_log_nameval *xattri_nameval;
@@ -55,7 +55,9 @@ enum xfs_dacmp {
typedef struct xfs_da_args {
struct xfs_da_geometry *geo; /* da block geometry */
const uint8_t *name; /* string (maybe not NULL terminated) */
+ const uint8_t *new_name; /* new attr name */
int namelen; /* length of string (maybe no NULL) */
+ int new_namelen; /* new attr name len */
uint8_t filetype; /* filetype of inode for directories */
void *value; /* set of bytes (maybe contain NULLs) */
int valuelen; /* length of value */
@@ -117,7 +117,8 @@ struct xfs_unmount_log_format {
#define XLOG_REG_TYPE_ATTRD_FORMAT 28
#define XLOG_REG_TYPE_ATTR_NAME 29
#define XLOG_REG_TYPE_ATTR_VALUE 30
-#define XLOG_REG_TYPE_MAX 30
+#define XLOG_REG_TYPE_ATTR_NNAME 31
+#define XLOG_REG_TYPE_MAX 31
/*
@@ -957,6 +958,7 @@ struct xfs_icreate_log {
#define XFS_ATTRI_OP_FLAGS_SET 1 /* Set the attribute */
#define XFS_ATTRI_OP_FLAGS_REMOVE 2 /* Remove the attribute */
#define XFS_ATTRI_OP_FLAGS_REPLACE 3 /* Replace the attribute */
+#define XFS_ATTRI_OP_FLAGS_NVREPLACE 4 /* Replace attr name and val */
#define XFS_ATTRI_OP_FLAGS_TYPE_MASK 0xFF /* Flags type mask */
/*
@@ -974,7 +976,7 @@ struct xfs_icreate_log {
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 */
+ uint32_t alfi_nname_len; /* attr new name length */
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 */
@@ -705,9 +705,9 @@ xlog_print_trans_attri(
memmove((char*)src_f, *ptr, src_len);
*ptr += src_len;
- printf(_("ATTRI: #regs: %d name_len: %d, value_len: %d id: 0x%llx\n"),
- src_f->alfi_size, src_f->alfi_name_len, src_f->alfi_value_len,
- (unsigned long long)src_f->alfi_id);
+ printf(_("ATTRI: #regs: %d name_len: %d, nname_len: %d value_len: %d id: 0x%llx\n"),
+ src_f->alfi_size, src_f->alfi_name_len, src_f->alfi_nname_len,
+ src_f->alfi_value_len, (unsigned long long)src_f->alfi_id);
if (src_f->alfi_name_len > 0) {
printf(_("\n"));
@@ -719,6 +719,16 @@ xlog_print_trans_attri(
goto error;
}
+ if (src_f->alfi_nname_len > 0) {
+ printf(_("\n"));
+ (*i)++;
+ head = (xlog_op_header_t *)*ptr;
+ xlog_print_op_header(head, *i, ptr);
+ error = xlog_print_trans_attri_name(ptr, be32_to_cpu(head->oh_len));
+ if (error)
+ goto error;
+ }
+
if (src_f->alfi_value_len > 0) {
printf(_("\n"));
(*i)++;
@@ -788,8 +798,8 @@ xlog_recover_print_attri(
if (xfs_attri_copy_log_format((char*)src_f, src_len, f))
goto out;
- printf(_("ATTRI: #regs: %d name_len: %d, value_len: %d id: 0x%llx\n"),
- f->alfi_size, f->alfi_name_len, f->alfi_value_len, (unsigned long long)f->alfi_id);
+ printf(_("ATTRI: #regs: %d name_len: %d, nname_len:%d, value_len: %d id: 0x%llx\n"),
+ f->alfi_size, f->alfi_name_len, f->alfi_nname_len, f->alfi_value_len, (unsigned long long)f->alfi_id);
if (f->alfi_name_len > 0) {
region++;
@@ -798,6 +808,13 @@ xlog_recover_print_attri(
f->alfi_name_len);
}
+ if (f->alfi_nname_len > 0) {
+ region++;
+ printf(_("ATTRI: nname len:%u\n"), f->alfi_nname_len);
+ print_or_dump((char *)item->ri_buf[region].i_addr,
+ f->alfi_nname_len);
+ }
+
if (f->alfi_value_len > 0) {
int len = f->alfi_value_len;