* [PATCH v3 00/30] xfsprogs: parent pointers v2
@ 2018-09-26 10:23 Allison Henderson
2018-09-26 10:23 ` [PATCH v3 01/30] xfsprogs: Move xfs_attr.h to libxfs Allison Henderson
` (29 more replies)
0 siblings, 30 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
This is the 3rd revision of the parent pointer patch set for xfsprogs. The
goal of the set is to enable use of the parent pointer feature on the kernel
side, and provide basic user space utilities.
The first 22 patches synchronize libxfs with changes seen the kernel space
patch. I will pick up the reviews from the kernel side series and mirror them
here.
Some points of interest since v2:
I've updated the series with feedback from the last revisions and also
synchronized the changes from v9 of the kernel side series. Patches 25 and
and 29 are new, so some attention there would be appreciated. Patch 29 adds
flags to the parent command to filter the output based on a particular inode or
filename, which helped to reduce the run time of the xfstests set.
As always, comments and feedback are appreciated. Thank you!
Allison
Allison Henderson (30):
xfsprogs: Move xfs_attr.h to libxfs
xfsprogs: Add helper function xfs_attr_try_sf_addname
xfsprogs: Add attibute set and helper functions
xfsprogs: Add attibute remove and helper functions
xfsprogs: Add trans toggle to attr routines
xfsprogs: Set up infastructure for deferred attribute operations
xfsprogs: Add xfs_attr_set_deferred and xfs_attr_remove_deferred
xfsprogs: Add xfs_has_attr and subroutines
xfs: Add attr context to log item
xfsprogs: Roll delayed attr operations by returning EAGAIN
xfsprogs: Remove roll_trans boolean
xfsprogs: Remove all strlen calls in all xfs_attr_* functions for attr
names
xfsprogs: get directory offset when adding directory name
xfsprogs: get directory offset when removing directory name
xfsprogs: get directory offset when replacing a directory name
xfsprogs: add parent pointer support to attribute code
xfsprogs: define parent pointer xattr format
xfsprogs: extent transaction reservations for parent attributes
xfsprogs: parent pointer attribute creation
xfsprogs: Add the parent pointer support to the superblock version 5.
xfsprogs: Add helper function xfs_attr_list_context_init
xfsprogs: Add parent pointer ioctl
xfsprogs: Add delayed attributes error tag
xfsprogs: Add parent pointer flag to cmd
xfsprogs: Add log item printing for ATTRI and ATTRD
xfsprogs: Add xfs_verify_pptr
xfsprogs: Add parent pointers to recreated inodes
xfsprogs: Add parent pointers during protofile creation
xfsprogs: implement the upper half of parent pointers
xfsprogs: Add i, n and f flags to parent command
include/handle.h | 2 +
include/parent.h | 25 +++
include/path.h | 19 ++
io/inject.c | 1 +
io/parent.c | 506 +++++++++++++++--------------------------------
libfrog/paths.c | 136 +++++++++++++
libhandle/Makefile | 2 +-
libhandle/handle.c | 7 +-
libhandle/parent.c | 361 +++++++++++++++++++++++++++++++++
libxfs/Makefile | 3 +
libxfs/libxfs_api_defs.h | 1 +
libxfs/xfs_attr.c | 495 +++++++++++++++++++++++++++++++---------------
libxfs/xfs_attr.h | 202 +++++++++++++++++++
libxfs/xfs_attr_leaf.c | 49 +++--
libxfs/xfs_attr_leaf.h | 3 +-
libxfs/xfs_attr_remote.c | 20 --
libxfs/xfs_bmap.c | 49 +++--
libxfs/xfs_bmap.h | 1 +
libxfs/xfs_da_btree.h | 1 +
libxfs/xfs_da_format.h | 37 +++-
libxfs/xfs_defer.h | 1 +
libxfs/xfs_dir2.c | 21 +-
libxfs/xfs_dir2.h | 7 +-
libxfs/xfs_dir2_block.c | 9 +-
libxfs/xfs_dir2_leaf.c | 8 +-
libxfs/xfs_dir2_node.c | 8 +-
libxfs/xfs_dir2_sf.c | 6 +
libxfs/xfs_errortag.h | 4 +-
libxfs/xfs_format.h | 10 +-
libxfs/xfs_fs.h | 46 +++++
libxfs/xfs_log_format.h | 44 ++++-
libxfs/xfs_parent.c | 207 +++++++++++++++++++
libxfs/xfs_parent.h | 37 ++++
libxfs/xfs_sb.c | 2 +
libxfs/xfs_trans_resv.c | 111 ++++++++---
libxfs/xfs_trans_resv.h | 1 +
libxfs/xfs_types.h | 1 +
logprint/log_misc.c | 11 ++
logprint/log_print_all.c | 12 ++
logprint/log_redo.c | 262 ++++++++++++++++++++++++
logprint/logprint.h | 6 +
mkfs/proto.c | 41 ++--
mkfs/xfs_mkfs.c | 23 ++-
repair/attr_repair.c | 21 +-
repair/da_util.c | 43 ++++
repair/da_util.h | 12 ++
repair/phase6.c | 52 +++--
scrub/inodes.c | 26 +++
scrub/inodes.h | 2 +
scrub/phase5.c | 9 +-
50 files changed, 2298 insertions(+), 665 deletions(-)
create mode 100644 libhandle/parent.c
create mode 100644 libxfs/xfs_attr.h
create mode 100644 libxfs/xfs_parent.c
create mode 100644 libxfs/xfs_parent.h
--
2.7.4
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH v3 01/30] xfsprogs: Move xfs_attr.h to libxfs
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 02/30] xfsprogs: Add helper function xfs_attr_try_sf_addname Allison Henderson
` (28 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
This patch moves fs/xfs/xfs_attr.h to fs/xfs/libxfs/xfs_attr.h
since xfs_attr.c is in libxfs. We will need these later in
xfsprogs.
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
libxfs/Makefile | 1 +
libxfs/xfs_attr.h | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 146 insertions(+)
diff --git a/libxfs/Makefile b/libxfs/Makefile
index 160498d..51ba9d6 100644
--- a/libxfs/Makefile
+++ b/libxfs/Makefile
@@ -21,6 +21,7 @@ HFILES = \
xfs_ag_resv.h \
xfs_alloc.h \
xfs_alloc_btree.h \
+ xfs_attr.h \
xfs_attr_leaf.h \
xfs_attr_sf.h \
xfs_bit.h \
diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h
new file mode 100644
index 0000000..525935c
--- /dev/null
+++ b/libxfs/xfs_attr.h
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2000,2002-2003,2005 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ */
+#ifndef __XFS_ATTR_H__
+#define __XFS_ATTR_H__
+
+struct xfs_inode;
+struct xfs_da_args;
+struct xfs_attr_list_context;
+
+/*
+ * Large attribute lists are structured around Btrees where all the data
+ * elements are in the leaf nodes. Attribute names are hashed into an int,
+ * then that int is used as the index into the Btree. Since the hashval
+ * of an attribute name may not be unique, we may have duplicate keys.
+ * The internal links in the Btree are logical block offsets into the file.
+ *
+ * Small attribute lists use a different format and are packed as tightly
+ * as possible so as to fit into the literal area of the inode.
+ */
+
+/*========================================================================
+ * External interfaces
+ *========================================================================*/
+
+
+#define ATTR_DONTFOLLOW 0x0001 /* -- unused, from IRIX -- */
+#define ATTR_ROOT 0x0002 /* use attrs in root (trusted) namespace */
+#define ATTR_TRUST 0x0004 /* -- unused, from IRIX -- */
+#define ATTR_SECURE 0x0008 /* use attrs in security namespace */
+#define ATTR_CREATE 0x0010 /* pure create: fail if attr already exists */
+#define ATTR_REPLACE 0x0020 /* pure set: fail if attr does not exist */
+
+#define ATTR_INCOMPLETE 0x4000 /* [kernel] return INCOMPLETE attr keys */
+
+#define XFS_ATTR_FLAGS \
+ { ATTR_DONTFOLLOW, "DONTFOLLOW" }, \
+ { ATTR_ROOT, "ROOT" }, \
+ { ATTR_TRUST, "TRUST" }, \
+ { ATTR_SECURE, "SECURE" }, \
+ { ATTR_CREATE, "CREATE" }, \
+ { ATTR_REPLACE, "REPLACE" }, \
+ { ATTR_KERNOTIME, "KERNOTIME" }, \
+ { ATTR_KERNOVAL, "KERNOVAL" }, \
+ { ATTR_INCOMPLETE, "INCOMPLETE" }
+
+/*
+ * The maximum size (into the kernel or returned from the kernel) of an
+ * attribute value or the buffer used for an attr_list() call. Larger
+ * sizes will result in an ERANGE return code.
+ */
+#define ATTR_MAX_VALUELEN (64*1024) /* max length of a value */
+
+/*
+ * Define how lists of attribute names are returned to the user from
+ * the attr_list() call. A large, 32bit aligned, buffer is passed in
+ * along with its size. We put an array of offsets at the top that each
+ * reference an attrlist_ent_t and pack the attrlist_ent_t's at the bottom.
+ */
+typedef struct attrlist {
+ __s32 al_count; /* number of entries in attrlist */
+ __s32 al_more; /* T/F: more attrs (do call again) */
+ __s32 al_offset[1]; /* byte offsets of attrs [var-sized] */
+} attrlist_t;
+
+/*
+ * Show the interesting info about one attribute. This is what the
+ * al_offset[i] entry points to.
+ */
+typedef struct attrlist_ent { /* data from attr_list() */
+ __u32 a_valuelen; /* number bytes in value of attr */
+ char a_name[1]; /* attr name (NULL terminated) */
+} attrlist_ent_t;
+
+/*
+ * Given a pointer to the (char*) buffer containing the attr_list() result,
+ * and an index, return a pointer to the indicated attribute in the buffer.
+ */
+#define ATTR_ENTRY(buffer, index) \
+ ((attrlist_ent_t *) \
+ &((char *)buffer)[ ((attrlist_t *)(buffer))->al_offset[index] ])
+
+/*
+ * Kernel-internal version of the attrlist cursor.
+ */
+typedef struct attrlist_cursor_kern {
+ __u32 hashval; /* hash value of next entry to add */
+ __u32 blkno; /* block containing entry (suggestion) */
+ __u32 offset; /* offset in list of equal-hashvals */
+ __u16 pad1; /* padding to match user-level */
+ __u8 pad2; /* padding to match user-level */
+ __u8 initted; /* T/F: cursor has been initialized */
+} attrlist_cursor_kern_t;
+
+
+/*========================================================================
+ * Structure used to pass context around among the routines.
+ *========================================================================*/
+
+
+/* void; state communicated via *context */
+typedef void (*put_listent_func_t)(struct xfs_attr_list_context *, int,
+ unsigned char *, int, int);
+
+typedef struct xfs_attr_list_context {
+ struct xfs_trans *tp;
+ struct xfs_inode *dp; /* inode */
+ struct attrlist_cursor_kern *cursor; /* position in list */
+ char *alist; /* output buffer */
+ int seen_enough; /* T/F: seen enough of list? */
+ ssize_t count; /* num used entries */
+ int dupcnt; /* count dup hashvals seen */
+ int bufsize; /* total buffer size */
+ int firstu; /* first used byte in buffer */
+ int flags; /* from VOP call */
+ int resynch; /* T/F: resynch with cursor */
+ put_listent_func_t put_listent; /* list output fmt function */
+ int index; /* index into output buffer */
+} xfs_attr_list_context_t;
+
+
+/*========================================================================
+ * Function prototypes for the kernel.
+ *========================================================================*/
+
+/*
+ * Overall external interface routines.
+ */
+int xfs_attr_inactive(struct xfs_inode *dp);
+int xfs_attr_list_int_ilocked(struct xfs_attr_list_context *);
+int xfs_attr_list_int(struct xfs_attr_list_context *);
+int xfs_inode_hasattr(struct xfs_inode *ip);
+int xfs_attr_get_ilocked(struct xfs_inode *ip, struct xfs_da_args *args);
+int xfs_attr_get(struct xfs_inode *ip, const unsigned char *name,
+ unsigned char *value, int *valuelenp, int flags);
+int xfs_attr_set(struct xfs_inode *dp, const unsigned char *name,
+ unsigned char *value, int valuelen, int flags);
+int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags);
+int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
+ int flags, struct attrlist_cursor_kern *cursor);
+
+
+#endif /* __XFS_ATTR_H__ */
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 02/30] xfsprogs: Add helper function xfs_attr_try_sf_addname
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
2018-09-26 10:23 ` [PATCH v3 01/30] xfsprogs: Move xfs_attr.h to libxfs Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 03/30] xfsprogs: Add attibute set and helper functions Allison Henderson
` (27 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
This patch adds a subroutine xfs_attr_try_sf_addname
used by xfs_attr_set. This subrotine will attempt to
add the attribute name specified in args in shortform,
as well and perform error handling previously done in
xfs_attr_set.
This patch helps to pre-simplify xfs_attr_set for reviewing
purposes and reduce indentation. New function will be added
in the next patch.
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
libxfs/xfs_attr.c | 61 ++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 40 insertions(+), 21 deletions(-)
diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
index bbfe4ee..cc5bde2 100644
--- a/libxfs/xfs_attr.c
+++ b/libxfs/xfs_attr.c
@@ -186,6 +186,42 @@ xfs_attr_calc_size(
return nblks;
}
+STATIC int
+xfs_attr_try_sf_addname(
+ struct xfs_inode *dp,
+ struct xfs_da_args *args)
+{
+
+ struct xfs_mount *mp = dp->i_mount;
+ int error;
+
+ error = xfs_attr_shortform_addname(args);
+ if (error == -ENOSPC)
+ return error;
+
+ /*
+ * Commit the shortform mods, and we're done.
+ * NOTE: this is also the error path
+ * (EEXIST, etc).
+ */
+ ASSERT(args->trans != NULL);
+
+ /*
+ * If this is a synchronous mount, make sure
+ * that the transaction goes to disk before
+ * returning to the user.
+ */
+ if (mp->m_flags & XFS_MOUNT_WSYNC)
+ xfs_trans_set_sync(args->trans);
+
+ if (!error && (args->flags & ATTR_KERNOTIME) == 0) {
+ xfs_trans_ichgtime(args->trans, dp,
+ XFS_ICHGTIME_CHG);
+ }
+
+ return error;
+}
+
int
xfs_attr_set(
struct xfs_inode *dp,
@@ -276,30 +312,13 @@ xfs_attr_set(
* Try to add the attr to the attribute list in
* the inode.
*/
- error = xfs_attr_shortform_addname(&args);
+ error = xfs_attr_try_sf_addname(dp, &args);
if (error != -ENOSPC) {
- /*
- * Commit the shortform mods, and we're done.
- * NOTE: this is also the error path (EEXIST, etc).
- */
- ASSERT(args.trans != NULL);
-
- /*
- * If this is a synchronous mount, make sure that
- * the transaction goes to disk before returning
- * to the user.
- */
- if (mp->m_flags & XFS_MOUNT_WSYNC)
- xfs_trans_set_sync(args.trans);
-
- if (!error && (flags & ATTR_KERNOTIME) == 0) {
- xfs_trans_ichgtime(args.trans, dp,
- XFS_ICHGTIME_CHG);
- }
err2 = xfs_trans_commit(args.trans);
- xfs_iunlock(dp, XFS_ILOCK_EXCL);
+ error = error ? error : err2;
- return error ? error : err2;
+ xfs_iunlock(dp, XFS_ILOCK_EXCL);
+ return error;
}
/*
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 03/30] xfsprogs: Add attibute set and helper functions
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
2018-09-26 10:23 ` [PATCH v3 01/30] xfsprogs: Move xfs_attr.h to libxfs Allison Henderson
2018-09-26 10:23 ` [PATCH v3 02/30] xfsprogs: Add helper function xfs_attr_try_sf_addname Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 04/30] xfsprogs: Add attibute remove " Allison Henderson
` (26 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
This patch adds xfs_attr_set_args and xfs_bmap_set_attrforkoff.
These sub-routines set the attributes specified in @args.
We will use this later for setting parent pointers as a deferred
attribute operation.
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
libxfs/xfs_attr.c | 152 ++++++++++++++++++++++++++++++++----------------------
libxfs/xfs_attr.h | 1 +
libxfs/xfs_bmap.c | 49 +++++++++++-------
libxfs/xfs_bmap.h | 1 +
4 files changed, 122 insertions(+), 81 deletions(-)
diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
index cc5bde2..f863fab 100644
--- a/libxfs/xfs_attr.c
+++ b/libxfs/xfs_attr.c
@@ -222,6 +222,94 @@ xfs_attr_try_sf_addname(
return error;
}
+/*
+ * Set the attribute specified in @args.
+ */
+int
+xfs_attr_set_args(
+ struct xfs_da_args *args,
+ struct xfs_buf **leaf_bp)
+{
+ struct xfs_inode *dp = args->dp;
+ int error;
+ int sf_size;
+
+ /*
+ * New inodes setting the parent pointer attr will
+ * not have an attribute fork yet. So set the attribute
+ * fork appropriately
+ */
+ if (XFS_IFORK_Q((args->dp)) == 0) {
+ sf_size = sizeof(struct xfs_attr_sf_hdr) +
+ XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen);
+ xfs_bmap_set_attrforkoff(args->dp, sf_size, NULL);
+ args->dp->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP);
+ args->dp->i_afp->if_flags = XFS_IFEXTENTS;
+ }
+
+ /*
+ * If the attribute list is non-existent or a shortform list,
+ * upgrade it to a single-leaf-block attribute list.
+ */
+ if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL ||
+ (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
+ dp->i_d.di_anextents == 0)) {
+
+ /*
+ * Build initial attribute list (if required).
+ */
+ if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS)
+ xfs_attr_shortform_create(args);
+
+ /*
+ * Try to add the attr to the attribute list in the inode.
+ */
+ error = xfs_attr_try_sf_addname(dp, args);
+ if (error != -ENOSPC)
+ goto out;
+
+ /*
+ * It won't fit in the shortform, transform to a leaf block.
+ * GROT: another possible req'mt for a double-split btree op.
+ */
+ error = xfs_attr_shortform_to_leaf(args, leaf_bp);
+ if (error)
+ goto out;
+
+ /*
+ * Prevent the leaf buffer from being unlocked so that a
+ * concurrent AIL push cannot grab the half-baked leaf
+ * buffer and run into problems with the write verifier.
+ */
+ xfs_trans_bhold(args->trans, *leaf_bp);
+
+ error = xfs_defer_finish(&args->trans);
+ if (error)
+ goto out;
+
+ /*
+ * Commit the leaf transformation. We'll need another
+ * (linked) transaction to add the new attribute to the
+ * leaf.
+ */
+ error = xfs_trans_roll_inode(&args->trans, dp);
+ if (error)
+ goto out;
+ xfs_trans_bjoin(args->trans, *leaf_bp);
+ *leaf_bp = NULL;
+ }
+
+ if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
+ error = xfs_attr_leaf_addname(args);
+ else
+ error = xfs_attr_node_addname(args);
+ if (error)
+ goto out;
+
+out:
+ return error;
+}
+
int
xfs_attr_set(
struct xfs_inode *dp,
@@ -235,7 +323,7 @@ xfs_attr_set(
struct xfs_da_args args;
struct xfs_trans_res tres;
int rsvd = (flags & ATTR_ROOT) != 0;
- int error, err2, local;
+ int error, local;
XFS_STATS_INC(mp, xs_attr_set);
@@ -293,67 +381,7 @@ xfs_attr_set(
}
xfs_trans_ijoin(args.trans, dp, 0);
-
- /*
- * If the attribute list is non-existent or a shortform list,
- * upgrade it to a single-leaf-block attribute list.
- */
- if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL ||
- (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
- dp->i_d.di_anextents == 0)) {
-
- /*
- * Build initial attribute list (if required).
- */
- if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS)
- xfs_attr_shortform_create(&args);
-
- /*
- * Try to add the attr to the attribute list in
- * the inode.
- */
- error = xfs_attr_try_sf_addname(dp, &args);
- if (error != -ENOSPC) {
- err2 = xfs_trans_commit(args.trans);
- error = error ? error : err2;
-
- xfs_iunlock(dp, XFS_ILOCK_EXCL);
- return error;
- }
-
- /*
- * It won't fit in the shortform, transform to a leaf block.
- * GROT: another possible req'mt for a double-split btree op.
- */
- error = xfs_attr_shortform_to_leaf(&args, &leaf_bp);
- if (error)
- goto out;
- /*
- * Prevent the leaf buffer from being unlocked so that a
- * concurrent AIL push cannot grab the half-baked leaf
- * buffer and run into problems with the write verifier.
- */
- xfs_trans_bhold(args.trans, leaf_bp);
- error = xfs_defer_finish(&args.trans);
- if (error)
- goto out;
-
- /*
- * Commit the leaf transformation. We'll need another (linked)
- * transaction to add the new attribute to the leaf, which
- * means that we have to hold & join the leaf buffer here too.
- */
- error = xfs_trans_roll_inode(&args.trans, dp);
- if (error)
- goto out;
- xfs_trans_bjoin(args.trans, leaf_bp);
- leaf_bp = NULL;
- }
-
- if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
- error = xfs_attr_leaf_addname(&args);
- else
- error = xfs_attr_node_addname(&args);
+ error = xfs_attr_set_args(&args, &leaf_bp);
if (error)
goto out;
diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h
index 525935c..a57630f 100644
--- a/libxfs/xfs_attr.h
+++ b/libxfs/xfs_attr.h
@@ -137,6 +137,7 @@ int xfs_attr_get(struct xfs_inode *ip, const unsigned char *name,
unsigned char *value, int *valuelenp, int flags);
int xfs_attr_set(struct xfs_inode *dp, const unsigned char *name,
unsigned char *value, int valuelen, int flags);
+int xfs_attr_set_args(struct xfs_da_args *args, struct xfs_buf **leaf_bp);
int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags);
int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
int flags, struct attrlist_cursor_kern *cursor);
diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c
index 8902ab8..45ba56f 100644
--- a/libxfs/xfs_bmap.c
+++ b/libxfs/xfs_bmap.c
@@ -1008,6 +1008,34 @@ xfs_bmap_add_attrfork_local(
return -EFSCORRUPTED;
}
+/* Set an inode attr fork off based on the format */
+int
+xfs_bmap_set_attrforkoff(
+ struct xfs_inode *ip,
+ int size,
+ int *version)
+{
+ switch (ip->i_d.di_format) {
+ case XFS_DINODE_FMT_DEV:
+ ip->i_d.di_forkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
+ break;
+ case XFS_DINODE_FMT_LOCAL:
+ case XFS_DINODE_FMT_EXTENTS:
+ case XFS_DINODE_FMT_BTREE:
+ ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size);
+ if (!ip->i_d.di_forkoff)
+ ip->i_d.di_forkoff = xfs_default_attroffset(ip) >> 3;
+ else if ((ip->i_mount->m_flags & XFS_MOUNT_ATTR2) && version)
+ *version = 2;
+ break;
+ default:
+ ASSERT(0);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/*
* Convert inode from non-attributed to attributed.
* Must not be in a transaction, ip must not be locked.
@@ -1059,26 +1087,9 @@ xfs_bmap_add_attrfork(
xfs_trans_ijoin(tp, ip, 0);
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-
- switch (ip->i_d.di_format) {
- case XFS_DINODE_FMT_DEV:
- ip->i_d.di_forkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
- break;
- case XFS_DINODE_FMT_LOCAL:
- case XFS_DINODE_FMT_EXTENTS:
- case XFS_DINODE_FMT_BTREE:
- ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size);
- if (!ip->i_d.di_forkoff)
- ip->i_d.di_forkoff = xfs_default_attroffset(ip) >> 3;
- else if (mp->m_flags & XFS_MOUNT_ATTR2)
- version = 2;
- break;
- default:
- ASSERT(0);
- error = -EINVAL;
+ error = xfs_bmap_set_attrforkoff(ip, size, &version);
+ if (error)
goto trans_cancel;
- }
-
ASSERT(ip->i_afp == NULL);
ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP);
ip->i_afp->if_flags = XFS_IFEXTENTS;
diff --git a/libxfs/xfs_bmap.h b/libxfs/xfs_bmap.h
index b6e9b63..488dc88 100644
--- a/libxfs/xfs_bmap.h
+++ b/libxfs/xfs_bmap.h
@@ -183,6 +183,7 @@ void xfs_trim_extent(struct xfs_bmbt_irec *irec, xfs_fileoff_t bno,
xfs_filblks_t len);
void xfs_trim_extent_eof(struct xfs_bmbt_irec *, struct xfs_inode *);
int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd);
+int xfs_bmap_set_attrforkoff(struct xfs_inode *ip, int size, int *version);
void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork);
void __xfs_bmap_add_free(struct xfs_trans *tp, xfs_fsblock_t bno,
xfs_filblks_t len, struct xfs_owner_info *oinfo,
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 04/30] xfsprogs: Add attibute remove and helper functions
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (2 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 03/30] xfsprogs: Add attibute set and helper functions Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 05/30] xfsprogs: Add trans toggle to attr routines Allison Henderson
` (25 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
This patch adds xfs_attr_remove_args. These sub-routines remove
the attributes specified in @args. We will use this later for setting
parent pointers as a deferred attribute operation.
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
libxfs/xfs_attr.c | 36 +++++++++++++++++++++++++-----------
libxfs/xfs_attr.h | 1 +
2 files changed, 26 insertions(+), 11 deletions(-)
diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
index f863fab..ae8d1d6 100644
--- a/libxfs/xfs_attr.c
+++ b/libxfs/xfs_attr.c
@@ -310,6 +310,30 @@ out:
return error;
}
+/*
+ * Remove the attribute specified in @args.
+ */
+int
+xfs_attr_remove_args(
+ struct xfs_da_args *args)
+{
+ struct xfs_inode *dp = args->dp;
+ int error;
+
+ if (!xfs_inode_hasattr(dp)) {
+ error = -ENOATTR;
+ } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
+ ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
+ error = xfs_attr_shortform_remove(args);
+ } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
+ error = xfs_attr_leaf_removename(args);
+ } else {
+ error = xfs_attr_node_removename(args);
+ }
+
+ return error;
+}
+
int
xfs_attr_set(
struct xfs_inode *dp,
@@ -465,17 +489,7 @@ xfs_attr_remove(
*/
xfs_trans_ijoin(args.trans, dp, 0);
- if (!xfs_inode_hasattr(dp)) {
- error = -ENOATTR;
- } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
- ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
- error = xfs_attr_shortform_remove(&args);
- } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
- error = xfs_attr_leaf_removename(&args);
- } else {
- error = xfs_attr_node_removename(&args);
- }
-
+ error = xfs_attr_remove_args(&args);
if (error)
goto out;
diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h
index a57630f..a6911b8 100644
--- a/libxfs/xfs_attr.h
+++ b/libxfs/xfs_attr.h
@@ -139,6 +139,7 @@ int xfs_attr_set(struct xfs_inode *dp, const unsigned char *name,
unsigned char *value, int valuelen, int flags);
int xfs_attr_set_args(struct xfs_da_args *args, struct xfs_buf **leaf_bp);
int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags);
+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);
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 05/30] xfsprogs: Add trans toggle to attr routines
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (3 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 04/30] xfsprogs: Add attibute remove " Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 06/30] xfsprogs: Set up infastructure for deferred attribute operations Allison Henderson
` (24 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
This patch adds a roll_trans parameter to all attribute routines
that may roll a transaction. Calling functions may pass true to
roll transactions as normal, or false to hold them.
This patch is temporary and will be removed later when all code
paths have been made to pass a false value. The temporary boolean
assists us to introduce changes across multiple smaller patches instead
of handling all affected code paths in one large patch.
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
libxfs/xfs_attr.c | 244 +++++++++++++++++++++++++++--------------------
libxfs/xfs_attr.h | 5 +-
libxfs/xfs_attr_leaf.c | 20 ++--
libxfs/xfs_attr_leaf.h | 8 +-
libxfs/xfs_attr_remote.c | 50 ++++++----
libxfs/xfs_attr_remote.h | 4 +-
6 files changed, 195 insertions(+), 136 deletions(-)
diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
index ae8d1d6..d31560d 100644
--- a/libxfs/xfs_attr.c
+++ b/libxfs/xfs_attr.c
@@ -44,15 +44,15 @@ STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
* Internal routines when attribute list is one block.
*/
STATIC int xfs_attr_leaf_get(xfs_da_args_t *args);
-STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args);
-STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args);
+STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args, bool roll_trans);
+STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args, bool roll_trans);
/*
* Internal routines when attribute list is more than one block.
*/
STATIC int xfs_attr_node_get(xfs_da_args_t *args);
-STATIC int xfs_attr_node_addname(xfs_da_args_t *args);
-STATIC int xfs_attr_node_removename(xfs_da_args_t *args);
+STATIC int xfs_attr_node_addname(xfs_da_args_t *args, bool roll_trans);
+STATIC int xfs_attr_node_removename(xfs_da_args_t *args, bool roll_trans);
STATIC int xfs_attr_fillstate(xfs_da_state_t *state);
STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
@@ -228,10 +228,11 @@ xfs_attr_try_sf_addname(
int
xfs_attr_set_args(
struct xfs_da_args *args,
- struct xfs_buf **leaf_bp)
+ struct xfs_buf **leaf_bp,
+ bool roll_trans)
{
struct xfs_inode *dp = args->dp;
- int error;
+ int error = 0;
int sf_size;
/*
@@ -276,33 +277,35 @@ xfs_attr_set_args(
if (error)
goto out;
- /*
- * Prevent the leaf buffer from being unlocked so that a
- * concurrent AIL push cannot grab the half-baked leaf
- * buffer and run into problems with the write verifier.
- */
- xfs_trans_bhold(args->trans, *leaf_bp);
+ if (roll_trans) {
+ /*
+ * Prevent the leaf buffer from being unlocked so that a
+ * concurrent AIL push cannot grab the half-baked leaf
+ * buffer and run into problems with the write verifier.
+ */
+ xfs_trans_bhold(args->trans, *leaf_bp);
- error = xfs_defer_finish(&args->trans);
- if (error)
- goto out;
+ error = xfs_defer_finish(&args->trans);
+ if (error)
+ goto out;
- /*
- * Commit the leaf transformation. We'll need another
- * (linked) transaction to add the new attribute to the
- * leaf.
- */
- error = xfs_trans_roll_inode(&args->trans, dp);
- if (error)
- goto out;
- xfs_trans_bjoin(args->trans, *leaf_bp);
- *leaf_bp = NULL;
+ /*
+ * Commit the leaf transformation. We'll need another
+ * (linked) transaction to add the new attribute to the
+ * leaf.
+ */
+ error = xfs_trans_roll_inode(&args->trans, dp);
+ if (error)
+ goto out;
+ xfs_trans_bjoin(args->trans, *leaf_bp);
+ *leaf_bp = NULL;
+ }
}
if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
- error = xfs_attr_leaf_addname(args);
+ error = xfs_attr_leaf_addname(args, roll_trans);
else
- error = xfs_attr_node_addname(args);
+ error = xfs_attr_node_addname(args, roll_trans);
if (error)
goto out;
@@ -315,7 +318,8 @@ out:
*/
int
xfs_attr_remove_args(
- struct xfs_da_args *args)
+ struct xfs_da_args *args,
+ bool roll_trans)
{
struct xfs_inode *dp = args->dp;
int error;
@@ -326,9 +330,9 @@ xfs_attr_remove_args(
ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
error = xfs_attr_shortform_remove(args);
} else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
- error = xfs_attr_leaf_removename(args);
+ error = xfs_attr_leaf_removename(args, roll_trans);
} else {
- error = xfs_attr_node_removename(args);
+ error = xfs_attr_node_removename(args, roll_trans);
}
return error;
@@ -405,7 +409,7 @@ xfs_attr_set(
}
xfs_trans_ijoin(args.trans, dp, 0);
- error = xfs_attr_set_args(&args, &leaf_bp);
+ error = xfs_attr_set_args(&args, &leaf_bp, true);
if (error)
goto out;
@@ -489,7 +493,8 @@ xfs_attr_remove(
*/
xfs_trans_ijoin(args.trans, dp, 0);
- error = xfs_attr_remove_args(&args);
+ error = xfs_attr_remove_args(&args, true);
+
if (error)
goto out;
@@ -579,7 +584,8 @@ xfs_attr_shortform_addname(xfs_da_args_t *args)
*/
STATIC int
xfs_attr_leaf_addname(
- struct xfs_da_args *args)
+ struct xfs_da_args *args,
+ bool roll_trans)
{
struct xfs_inode *dp;
struct xfs_buf *bp;
@@ -644,32 +650,39 @@ xfs_attr_leaf_addname(
error = xfs_attr3_leaf_to_node(args);
if (error)
goto out_defer_cancel;
- error = xfs_defer_finish(&args->trans);
- if (error)
- return error;
- /*
- * Commit the current trans (including the inode) and start
- * a new one.
- */
- error = xfs_trans_roll_inode(&args->trans, dp);
- if (error)
- return error;
+ if (roll_trans) {
+ error = xfs_defer_finish(&args->trans);
+ if (error)
+ return error;
+
+ /*
+ * Commit the current trans (including the inode) and
+ * start a new one.
+ */
+ error = xfs_trans_roll_inode(&args->trans, dp);
+ if (error)
+ return error;
+ }
/*
* Fob the whole rest of the problem off on the Btree code.
*/
- error = xfs_attr_node_addname(args);
+ error = xfs_attr_node_addname(args, roll_trans);
+
return error;
}
- /*
- * Commit the transaction that added the attr name so that
- * later routines can manage their own transactions.
- */
- error = xfs_trans_roll_inode(&args->trans, dp);
- if (error)
- return error;
+
+ if (roll_trans) {
+ /*
+ * Commit the transaction that added the attr name so that
+ * later routines can manage their own transactions.
+ */
+ error = xfs_trans_roll_inode(&args->trans, dp);
+ if (error)
+ return error;
+ }
/*
* If there was an out-of-line value, allocate the blocks we
@@ -678,7 +691,7 @@ xfs_attr_leaf_addname(
* maximum size of a transaction and/or hit a deadlock.
*/
if (args->rmtblkno > 0) {
- error = xfs_attr_rmtval_set(args);
+ error = xfs_attr_rmtval_set(args, roll_trans);
if (error)
return error;
}
@@ -694,7 +707,7 @@ xfs_attr_leaf_addname(
* In a separate transaction, set the incomplete flag on the
* "old" attr and clear the incomplete flag on the "new" attr.
*/
- error = xfs_attr3_leaf_flipflags(args);
+ error = xfs_attr3_leaf_flipflags(args, roll_trans);
if (error)
return error;
@@ -708,7 +721,7 @@ xfs_attr_leaf_addname(
args->rmtblkcnt = args->rmtblkcnt2;
args->rmtvaluelen = args->rmtvaluelen2;
if (args->rmtblkno) {
- error = xfs_attr_rmtval_remove(args);
+ error = xfs_attr_rmtval_remove(args, roll_trans);
if (error)
return error;
}
@@ -732,21 +745,25 @@ xfs_attr_leaf_addname(
/* bp is gone due to xfs_da_shrink_inode */
if (error)
goto out_defer_cancel;
- error = xfs_defer_finish(&args->trans);
- if (error)
- return error;
+
+ if (roll_trans) {
+ error = xfs_defer_finish(&args->trans);
+ if (error)
+ return error;
+ }
}
/*
* Commit the remove and start the next trans in series.
*/
- error = xfs_trans_roll_inode(&args->trans, dp);
+ if (roll_trans)
+ error = xfs_trans_roll_inode(&args->trans, dp);
} else if (args->rmtblkno > 0) {
/*
* Added a "remote" value, just clear the incomplete flag.
*/
- error = xfs_attr3_leaf_clearflag(args);
+ error = xfs_attr3_leaf_clearflag(args, roll_trans);
}
return error;
out_defer_cancel:
@@ -762,7 +779,8 @@ out_defer_cancel:
*/
STATIC int
xfs_attr_leaf_removename(
- struct xfs_da_args *args)
+ struct xfs_da_args *args,
+ bool roll_trans)
{
struct xfs_inode *dp;
struct xfs_buf *bp;
@@ -795,9 +813,11 @@ xfs_attr_leaf_removename(
/* bp is gone due to xfs_da_shrink_inode */
if (error)
goto out_defer_cancel;
- error = xfs_defer_finish(&args->trans);
- if (error)
- return error;
+ if (roll_trans) {
+ error = xfs_defer_finish(&args->trans);
+ if (error)
+ return error;
+ }
}
return 0;
out_defer_cancel:
@@ -853,7 +873,8 @@ xfs_attr_leaf_get(xfs_da_args_t *args)
*/
STATIC int
xfs_attr_node_addname(
- struct xfs_da_args *args)
+ struct xfs_da_args *args,
+ bool roll_trans)
{
struct xfs_da_state *state;
struct xfs_da_state_blk *blk;
@@ -918,20 +939,24 @@ restart:
*/
xfs_da_state_free(state);
state = NULL;
+
error = xfs_attr3_leaf_to_node(args);
if (error)
goto out_defer_cancel;
- error = xfs_defer_finish(&args->trans);
- if (error)
- goto out;
- /*
- * Commit the node conversion and start the next
- * trans in the chain.
- */
- error = xfs_trans_roll_inode(&args->trans, dp);
- if (error)
- goto out;
+ if (roll_trans) {
+ error = xfs_defer_finish(&args->trans);
+ if (error)
+ goto out;
+
+ /*
+ * Commit the node conversion and start the next
+ * trans in the chain.
+ */
+ error = xfs_trans_roll_inode(&args->trans, dp);
+ if (error)
+ goto out;
+ }
goto restart;
}
@@ -945,9 +970,12 @@ restart:
error = xfs_da3_split(state);
if (error)
goto out_defer_cancel;
- error = xfs_defer_finish(&args->trans);
- if (error)
- goto out;
+
+ if (roll_trans) {
+ error = xfs_defer_finish(&args->trans);
+ if (error)
+ goto out;
+ }
} else {
/*
* Addition succeeded, update Btree hashvals.
@@ -966,9 +994,11 @@ restart:
* Commit the leaf addition or btree split and start the next
* trans in the chain.
*/
- error = xfs_trans_roll_inode(&args->trans, dp);
- if (error)
- goto out;
+ if (roll_trans) {
+ error = xfs_trans_roll_inode(&args->trans, dp);
+ if (error)
+ goto out;
+ }
/*
* If there was an out-of-line value, allocate the blocks we
@@ -977,7 +1007,7 @@ restart:
* maximum size of a transaction and/or hit a deadlock.
*/
if (args->rmtblkno > 0) {
- error = xfs_attr_rmtval_set(args);
+ error = xfs_attr_rmtval_set(args, roll_trans);
if (error)
return error;
}
@@ -993,7 +1023,7 @@ restart:
* In a separate transaction, set the incomplete flag on the
* "old" attr and clear the incomplete flag on the "new" attr.
*/
- error = xfs_attr3_leaf_flipflags(args);
+ error = xfs_attr3_leaf_flipflags(args, roll_trans);
if (error)
goto out;
@@ -1007,7 +1037,7 @@ restart:
args->rmtblkcnt = args->rmtblkcnt2;
args->rmtvaluelen = args->rmtvaluelen2;
if (args->rmtblkno) {
- error = xfs_attr_rmtval_remove(args);
+ error = xfs_attr_rmtval_remove(args, roll_trans);
if (error)
return error;
}
@@ -1041,9 +1071,11 @@ restart:
error = xfs_da3_join(state);
if (error)
goto out_defer_cancel;
- error = xfs_defer_finish(&args->trans);
- if (error)
- goto out;
+ if (roll_trans) {
+ error = xfs_defer_finish(&args->trans);
+ if (error)
+ goto out;
+ }
}
/*
@@ -1057,7 +1089,7 @@ restart:
/*
* Added a "remote" value, just clear the incomplete flag.
*/
- error = xfs_attr3_leaf_clearflag(args);
+ error = xfs_attr3_leaf_clearflag(args, roll_trans);
if (error)
goto out;
}
@@ -1083,7 +1115,8 @@ out_defer_cancel:
*/
STATIC int
xfs_attr_node_removename(
- struct xfs_da_args *args)
+ struct xfs_da_args *args,
+ bool roll_trans)
{
struct xfs_da_state *state;
struct xfs_da_state_blk *blk;
@@ -1133,10 +1166,10 @@ xfs_attr_node_removename(
* Mark the attribute as INCOMPLETE, then bunmapi() the
* remote value.
*/
- error = xfs_attr3_leaf_setflag(args);
+ error = xfs_attr3_leaf_setflag(args, roll_trans);
if (error)
goto out;
- error = xfs_attr_rmtval_remove(args);
+ error = xfs_attr_rmtval_remove(args, roll_trans);
if (error)
goto out;
@@ -1164,15 +1197,19 @@ xfs_attr_node_removename(
error = xfs_da3_join(state);
if (error)
goto out_defer_cancel;
- error = xfs_defer_finish(&args->trans);
- if (error)
- goto out;
- /*
- * Commit the Btree join operation and start a new trans.
- */
- error = xfs_trans_roll_inode(&args->trans, dp);
- if (error)
- goto out;
+
+ if (roll_trans) {
+ error = xfs_defer_finish(&args->trans);
+ if (error)
+ goto out;
+ /*
+ * Commit the Btree join operation and
+ * start a new trans.
+ */
+ error = xfs_trans_roll_inode(&args->trans, dp);
+ if (error)
+ goto out;
+ }
}
/*
@@ -1195,9 +1232,12 @@ xfs_attr_node_removename(
/* bp is gone due to xfs_da_shrink_inode */
if (error)
goto out_defer_cancel;
- error = xfs_defer_finish(&args->trans);
- if (error)
- goto out;
+
+ if (roll_trans) {
+ error = xfs_defer_finish(&args->trans);
+ if (error)
+ goto out;
+ }
} else
xfs_trans_brelse(args->trans, bp);
}
diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h
index a6911b8..c7a194c 100644
--- a/libxfs/xfs_attr.h
+++ b/libxfs/xfs_attr.h
@@ -137,9 +137,10 @@ int xfs_attr_get(struct xfs_inode *ip, const unsigned char *name,
unsigned char *value, int *valuelenp, int flags);
int xfs_attr_set(struct xfs_inode *dp, const unsigned char *name,
unsigned char *value, int valuelen, int flags);
-int xfs_attr_set_args(struct xfs_da_args *args, struct xfs_buf **leaf_bp);
+int xfs_attr_set_args(struct xfs_da_args *args, struct xfs_buf **leaf_bp,
+ bool roll_trans);
int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags);
-int xfs_attr_remove_args(struct xfs_da_args *args);
+int xfs_attr_remove_args(struct xfs_da_args *args, bool roll_trans);
int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
int flags, struct attrlist_cursor_kern *cursor);
diff --git a/libxfs/xfs_attr_leaf.c b/libxfs/xfs_attr_leaf.c
index 3ecd524..60444d0 100644
--- a/libxfs/xfs_attr_leaf.c
+++ b/libxfs/xfs_attr_leaf.c
@@ -2634,7 +2634,8 @@ xfs_attr_leaf_newentsize(
*/
int
xfs_attr3_leaf_clearflag(
- struct xfs_da_args *args)
+ struct xfs_da_args *args,
+ bool roll_trans)
{
struct xfs_attr_leafblock *leaf;
struct xfs_attr_leaf_entry *entry;
@@ -2695,7 +2696,9 @@ xfs_attr3_leaf_clearflag(
/*
* Commit the flag value change and start the next trans in series.
*/
- return xfs_trans_roll_inode(&args->trans, args->dp);
+ if (roll_trans)
+ error = xfs_trans_roll_inode(&args->trans, args->dp);
+ return error;
}
/*
@@ -2703,7 +2706,8 @@ xfs_attr3_leaf_clearflag(
*/
int
xfs_attr3_leaf_setflag(
- struct xfs_da_args *args)
+ struct xfs_da_args *args,
+ bool roll_trans)
{
struct xfs_attr_leafblock *leaf;
struct xfs_attr_leaf_entry *entry;
@@ -2746,7 +2750,9 @@ xfs_attr3_leaf_setflag(
/*
* Commit the flag value change and start the next trans in series.
*/
- return xfs_trans_roll_inode(&args->trans, args->dp);
+ if (roll_trans)
+ error = xfs_trans_roll_inode(&args->trans, args->dp);
+ return error;
}
/*
@@ -2758,7 +2764,8 @@ xfs_attr3_leaf_setflag(
*/
int
xfs_attr3_leaf_flipflags(
- struct xfs_da_args *args)
+ struct xfs_da_args *args,
+ bool roll_trans)
{
struct xfs_attr_leafblock *leaf1;
struct xfs_attr_leafblock *leaf2;
@@ -2864,7 +2871,8 @@ xfs_attr3_leaf_flipflags(
/*
* Commit the flag value change and start the next trans in series.
*/
- error = xfs_trans_roll_inode(&args->trans, args->dp);
+ if (roll_trans)
+ error = xfs_trans_roll_inode(&args->trans, args->dp);
return error;
}
diff --git a/libxfs/xfs_attr_leaf.h b/libxfs/xfs_attr_leaf.h
index 7b74e18..9d830ec 100644
--- a/libxfs/xfs_attr_leaf.h
+++ b/libxfs/xfs_attr_leaf.h
@@ -49,10 +49,10 @@ void xfs_attr_fork_remove(struct xfs_inode *ip, struct xfs_trans *tp);
*/
int xfs_attr3_leaf_to_node(struct xfs_da_args *args);
int xfs_attr3_leaf_to_shortform(struct xfs_buf *bp,
- struct xfs_da_args *args, int forkoff);
-int xfs_attr3_leaf_clearflag(struct xfs_da_args *args);
-int xfs_attr3_leaf_setflag(struct xfs_da_args *args);
-int xfs_attr3_leaf_flipflags(struct xfs_da_args *args);
+ struct xfs_da_args *args, int forkoff);
+int xfs_attr3_leaf_clearflag(struct xfs_da_args *args, bool roll_trans);
+int xfs_attr3_leaf_setflag(struct xfs_da_args *args, bool roll_trans);
+int xfs_attr3_leaf_flipflags(struct xfs_da_args *args, bool roll_trans);
/*
* Routines used for growing the Btree.
diff --git a/libxfs/xfs_attr_remote.c b/libxfs/xfs_attr_remote.c
index 1d078ef..6446607 100644
--- a/libxfs/xfs_attr_remote.c
+++ b/libxfs/xfs_attr_remote.c
@@ -428,7 +428,8 @@ xfs_attr_rmtval_get(
*/
int
xfs_attr_rmtval_set(
- struct xfs_da_args *args)
+ struct xfs_da_args *args,
+ bool roll_trans)
{
struct xfs_inode *dp = args->dp;
struct xfs_mount *mp = dp->i_mount;
@@ -481,9 +482,12 @@ xfs_attr_rmtval_set(
&nmap);
if (error)
goto out_defer_cancel;
- error = xfs_defer_finish(&args->trans);
- if (error)
- return error;
+
+ if (roll_trans) {
+ error = xfs_defer_finish(&args->trans);
+ if (error)
+ return error;
+ }
ASSERT(nmap == 1);
ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
@@ -491,12 +495,14 @@ xfs_attr_rmtval_set(
lblkno += map.br_blockcount;
blkcnt -= map.br_blockcount;
- /*
- * Start the next trans in the chain.
- */
- error = xfs_trans_roll_inode(&args->trans, dp);
- if (error)
- return error;
+ if (roll_trans) {
+ /*
+ * Start the next trans in the chain.
+ */
+ error = xfs_trans_roll_inode(&args->trans, dp);
+ if (error)
+ return error;
+ }
}
/*
@@ -559,7 +565,8 @@ out_defer_cancel:
*/
int
xfs_attr_rmtval_remove(
- struct xfs_da_args *args)
+ struct xfs_da_args *args,
+ bool roll_trans)
{
struct xfs_mount *mp = args->dp->i_mount;
xfs_dablk_t lblkno;
@@ -621,16 +628,19 @@ xfs_attr_rmtval_remove(
XFS_BMAPI_ATTRFORK, 1, &done);
if (error)
goto out_defer_cancel;
- error = xfs_defer_finish(&args->trans);
- if (error)
- return error;
- /*
- * Close out trans and start the next one in the chain.
- */
- error = xfs_trans_roll_inode(&args->trans, args->dp);
- if (error)
- return error;
+ if (roll_trans) {
+ error = xfs_defer_finish(&args->trans);
+ if (error)
+ return error;
+
+ /*
+ * Close out trans and start the next one in the chain.
+ */
+ error = xfs_trans_roll_inode(&args->trans, args->dp);
+ if (error)
+ return error;
+ }
}
return 0;
out_defer_cancel:
diff --git a/libxfs/xfs_attr_remote.h b/libxfs/xfs_attr_remote.h
index 9d20b66..c7c073d 100644
--- a/libxfs/xfs_attr_remote.h
+++ b/libxfs/xfs_attr_remote.h
@@ -9,7 +9,7 @@
int xfs_attr3_rmt_blocks(struct xfs_mount *mp, int attrlen);
int xfs_attr_rmtval_get(struct xfs_da_args *args);
-int xfs_attr_rmtval_set(struct xfs_da_args *args);
-int xfs_attr_rmtval_remove(struct xfs_da_args *args);
+int xfs_attr_rmtval_set(struct xfs_da_args *args, bool roll_trans);
+int xfs_attr_rmtval_remove(struct xfs_da_args *args, bool roll_trans);
#endif /* __XFS_ATTR_REMOTE_H__ */
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 06/30] xfsprogs: Set up infastructure for deferred attribute operations
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (4 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 05/30] xfsprogs: Add trans toggle to attr routines Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 07/30] xfsprogs: Add xfs_attr_set_deferred and xfs_attr_remove_deferred Allison Henderson
` (23 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
This patch adds two new log item types for setting or
removing attributes as deferred operations. The
xfs_attri_log_item logs an intent to set or remove an
attribute. The corresponding xfs_attrd_log_item holds
a reference to the xfs_attri_log_item and is freed once
the transaction is done. Both log items use a generic
xfs_attr_log_format structure that contains the attribute
name, value, flags, inode, and an op_flag that indicates
if the operations is a set or remove.
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
libxfs/xfs_attr.c | 5 +++--
libxfs/xfs_attr.h | 26 +++++++++++++++++++++++++-
libxfs/xfs_defer.h | 1 +
libxfs/xfs_log_format.h | 44 ++++++++++++++++++++++++++++++++++++++++++--
libxfs/xfs_types.h | 1 +
5 files changed, 72 insertions(+), 5 deletions(-)
diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
index d31560d..566a617 100644
--- a/libxfs/xfs_attr.c
+++ b/libxfs/xfs_attr.c
@@ -24,6 +24,7 @@
#include "xfs_attr_remote.h"
#include "xfs_trans_space.h"
#include "xfs_trace.h"
+#include "xfs_attr_item.h"
/*
* xfs_attr.c
@@ -57,7 +58,7 @@ STATIC int xfs_attr_fillstate(xfs_da_state_t *state);
STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
-STATIC int
+int
xfs_attr_args_init(
struct xfs_da_args *args,
struct xfs_inode *dp,
@@ -153,7 +154,7 @@ xfs_attr_get(
/*
* Calculate how many blocks we need for the new attribute,
*/
-STATIC int
+int
xfs_attr_calc_size(
struct xfs_da_args *args,
int *local)
diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h
index c7a194c..39a7a26 100644
--- a/libxfs/xfs_attr.h
+++ b/libxfs/xfs_attr.h
@@ -75,6 +75,28 @@ typedef struct attrlist_ent { /* data from attr_list() */
} attrlist_ent_t;
/*
+ * List of attrs to commit later.
+ */
+struct xfs_attr_item {
+ struct xfs_inode *xattri_ip;
+ uint32_t xattri_op_flags;
+ void* xattri_value; /* attr value */
+ uint32_t xattri_value_len; /* length of value */
+ void* xattri_name; /* attr name */
+ uint32_t xattri_name_len; /* length of name */
+ uint32_t xattri_flags; /* attr flags */
+ struct list_head xattri_list;
+
+ /*
+ * A byte array follows the header containing the file name and
+ * attribute value.
+ */
+};
+
+#define XFS_ATTR_ITEM_SIZEOF(namelen, valuelen) \
+ (sizeof(struct xfs_attr_item) + (namelen) + (valuelen))
+
+/*
* Given a pointer to the (char*) buffer containing the attr_list() result,
* and an index, return a pointer to the indicated attribute in the buffer.
*/
@@ -143,6 +165,8 @@ int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags);
int xfs_attr_remove_args(struct xfs_da_args *args, bool roll_trans);
int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
int flags, struct attrlist_cursor_kern *cursor);
-
+int xfs_attr_args_init(struct xfs_da_args *args, struct xfs_inode *dp,
+ const unsigned char *name, int flags);
+int xfs_attr_calc_size(struct xfs_da_args *args, int *local);
#endif /* __XFS_ATTR_H__ */
diff --git a/libxfs/xfs_defer.h b/libxfs/xfs_defer.h
index 2584a5b..326fa2b 100644
--- a/libxfs/xfs_defer.h
+++ b/libxfs/xfs_defer.h
@@ -31,6 +31,7 @@ enum xfs_defer_ops_type {
XFS_DEFER_OPS_TYPE_RMAP,
XFS_DEFER_OPS_TYPE_FREE,
XFS_DEFER_OPS_TYPE_AGFL_FREE,
+ XFS_DEFER_OPS_TYPE_ATTR,
XFS_DEFER_OPS_TYPE_MAX,
};
diff --git a/libxfs/xfs_log_format.h b/libxfs/xfs_log_format.h
index e5f97c6..76d42e6 100644
--- a/libxfs/xfs_log_format.h
+++ b/libxfs/xfs_log_format.h
@@ -117,7 +117,12 @@ struct xfs_unmount_log_format {
#define XLOG_REG_TYPE_CUD_FORMAT 24
#define XLOG_REG_TYPE_BUI_FORMAT 25
#define XLOG_REG_TYPE_BUD_FORMAT 26
-#define XLOG_REG_TYPE_MAX 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_VALUE 30
+#define XLOG_REG_TYPE_MAX 31
+
/*
* Flags to log operation header
@@ -240,6 +245,8 @@ typedef struct xfs_trans_header {
#define XFS_LI_CUD 0x1243
#define XFS_LI_BUI 0x1244 /* bmbt update intent */
#define XFS_LI_BUD 0x1245
+#define XFS_LI_ATTRI 0x1246 /* attr set/remove intent*/
+#define XFS_LI_ATTRD 0x1247 /* attr set/remove done */
#define XFS_LI_TYPE_DESC \
{ XFS_LI_EFI, "XFS_LI_EFI" }, \
@@ -255,7 +262,9 @@ typedef struct xfs_trans_header {
{ XFS_LI_CUI, "XFS_LI_CUI" }, \
{ XFS_LI_CUD, "XFS_LI_CUD" }, \
{ XFS_LI_BUI, "XFS_LI_BUI" }, \
- { XFS_LI_BUD, "XFS_LI_BUD" }
+ { XFS_LI_BUD, "XFS_LI_BUD" }, \
+ { XFS_LI_ATTRI, "XFS_LI_ATTRI" }, \
+ { XFS_LI_ATTRD, "XFS_LI_ATTRD" }
/*
* Inode Log Item Format definitions.
@@ -853,4 +862,35 @@ struct xfs_icreate_log {
__be32 icl_gen; /* inode generation number to use */
};
+/*
+ * Flags for deferred attribute operations.
+ * Upper bits are flags, lower byte is type code
+ */
+#define XFS_ATTR_OP_FLAGS_SET 1 /* Set the attribute */
+#define XFS_ATTR_OP_FLAGS_REMOVE 2 /* Remove the attribute */
+#define XFS_ATTR_OP_FLAGS_TYPE_MASK 0x0FF /* Flags type mask */
+
+/*
+ * This is the structure used to lay out an attr log item in the
+ * 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 */
+ uint64_t alfi_id; /* attri identifier */
+ xfs_ino_t alfi_ino; /* the inode for this attr operation */
+ uint32_t alfi_op_flags; /* marks the op as a set or remove */
+ uint32_t alfi_name_len; /* attr name length */
+ uint32_t alfi_value_len; /* attr value length */
+ uint32_t alfi_attr_flags;/* attr flags */
+};
+
+struct xfs_attrd_log_format {
+ uint16_t alfd_type; /* attrd log item type */
+ uint16_t alfd_size; /* size of this item */
+ uint32_t __pad; /* pad to 64 bit aligned */
+ uint64_t alfd_alf_id; /* id of corresponding attrd */
+};
+
#endif /* __XFS_LOG_FORMAT_H__ */
diff --git a/libxfs/xfs_types.h b/libxfs/xfs_types.h
index b9e6c89..6f33dd6 100644
--- a/libxfs/xfs_types.h
+++ b/libxfs/xfs_types.h
@@ -11,6 +11,7 @@ typedef uint32_t prid_t; /* project ID */
typedef uint32_t xfs_agblock_t; /* blockno in alloc. group */
typedef uint32_t xfs_agino_t; /* inode # within allocation grp */
typedef uint32_t xfs_extlen_t; /* extent length in blocks */
+typedef uint32_t xfs_attrlen_t; /* attr length */
typedef uint32_t xfs_agnumber_t; /* allocation group number */
typedef int32_t xfs_extnum_t; /* # of extents in a file */
typedef int16_t xfs_aextnum_t; /* # extents in an attribute fork */
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 07/30] xfsprogs: Add xfs_attr_set_deferred and xfs_attr_remove_deferred
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (5 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 06/30] xfsprogs: Set up infastructure for deferred attribute operations Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 08/30] xfsprogs: Add xfs_has_attr and subroutines Allison Henderson
` (22 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
These routines set up set and start a new deferred attribute
operation. These functions are meant to be called by other
code needing to initiate a deferred attribute operation. We
will use these routines later in the parent pointer patches.
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
libxfs/xfs_attr.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
libxfs/xfs_attr.h | 7 +++++
2 files changed, 87 insertions(+)
diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
index 566a617..d50b5a1 100644
--- a/libxfs/xfs_attr.c
+++ b/libxfs/xfs_attr.c
@@ -25,6 +25,7 @@
#include "xfs_trans_space.h"
#include "xfs_trace.h"
#include "xfs_attr_item.h"
+#include "xfs_attr.h"
/*
* xfs_attr.c
@@ -442,6 +443,52 @@ out:
return error;
}
+/* Sets an attribute for an inode as a deferred operation */
+int
+xfs_attr_set_deferred(
+ struct xfs_inode *dp,
+ struct xfs_trans *tp,
+ const unsigned char *name,
+ unsigned int namelen,
+ const unsigned char *value,
+ unsigned int valuelen,
+ int flags)
+{
+
+ struct xfs_attr_item *new;
+ char *name_value;
+
+ /*
+ * All set operations must have a name
+ * but not necessarily a value.
+ * Generic 062
+ */
+ if (!namelen) {
+ ASSERT(0);
+ return -EFSCORRUPTED;
+ }
+
+ new = kmem_alloc(XFS_ATTR_ITEM_SIZEOF(namelen, valuelen),
+ KM_SLEEP|KM_NOFS);
+ name_value = ((char *)new) + sizeof(struct xfs_attr_item);
+ memset(new, 0, XFS_ATTR_ITEM_SIZEOF(namelen, valuelen));
+ new->xattri_ip = dp;
+ new->xattri_op_flags = XFS_ATTR_OP_FLAGS_SET;
+ new->xattri_name_len = namelen;
+ new->xattri_value_len = valuelen;
+ new->xattri_flags = flags;
+ memcpy(&name_value[0], name, namelen);
+ new->xattri_name = name_value;
+ new->xattri_value = name_value + namelen;
+
+ if (valuelen > 0)
+ memcpy(&name_value[namelen], value, valuelen);
+
+ xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_ATTR, &new->xattri_list);
+
+ return 0;
+}
+
/*
* Generic handler routine to remove a name from an attribute list.
* Transitions attribute list from Btree to shortform as necessary.
@@ -525,6 +572,39 @@ out:
return error;
}
+/* Removes an attribute for an inode as a deferred operation */
+int
+xfs_attr_remove_deferred(
+ struct xfs_inode *dp,
+ struct xfs_trans *tp,
+ const unsigned char *name,
+ unsigned int namelen,
+ int flags)
+{
+
+ struct xfs_attr_item *new;
+ char *name_value;
+
+ if (!namelen) {
+ ASSERT(0);
+ return -EFSCORRUPTED;
+ }
+
+ new = kmem_alloc(XFS_ATTR_ITEM_SIZEOF(namelen, 0), KM_SLEEP|KM_NOFS);
+ name_value = ((char *)new) + sizeof(struct xfs_attr_item);
+ memset(new, 0, XFS_ATTR_ITEM_SIZEOF(namelen, 0));
+ new->xattri_ip = dp;
+ new->xattri_op_flags = XFS_ATTR_OP_FLAGS_REMOVE;
+ new->xattri_name_len = namelen;
+ new->xattri_value_len = 0;
+ new->xattri_flags = flags;
+ memcpy(name_value, name, namelen);
+
+ xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_ATTR, &new->xattri_list);
+
+ return 0;
+}
+
/*========================================================================
* External routines when attribute list is inside the inode
*========================================================================*/
diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h
index 39a7a26..6e546a1 100644
--- a/libxfs/xfs_attr.h
+++ b/libxfs/xfs_attr.h
@@ -168,5 +168,12 @@ int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
int xfs_attr_args_init(struct xfs_da_args *args, struct xfs_inode *dp,
const unsigned char *name, int flags);
int xfs_attr_calc_size(struct xfs_da_args *args, int *local);
+int xfs_attr_set_deferred(struct xfs_inode *dp, struct xfs_trans *tp,
+ const unsigned char *name, unsigned int name_len,
+ const unsigned char *value, unsigned int valuelen,
+ int flags);
+int xfs_attr_remove_deferred(struct xfs_inode *dp, struct xfs_trans *tp,
+ const unsigned char *name, unsigned int namelen,
+ int flags);
#endif /* __XFS_ATTR_H__ */
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 08/30] xfsprogs: Add xfs_has_attr and subroutines
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (6 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 07/30] xfsprogs: Add xfs_attr_set_deferred and xfs_attr_remove_deferred Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 09/30] xfsprogs: Add attr context to log item Allison Henderson
` (21 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
This patch adds a new functions to check for the existence of
an attribute. Subroutines are also added to handle the cases
of leaf blocks, nodes or shortform. We will need this later
for delayed attributes since delayed operations cannot return
error codes.
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
libxfs/xfs_attr.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++
libxfs/xfs_attr.h | 1 +
libxfs/xfs_attr_leaf.c | 33 +++++++++++++++++++++
libxfs/xfs_attr_leaf.h | 1 +
4 files changed, 113 insertions(+)
diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
index d50b5a1..ad0c5cd 100644
--- a/libxfs/xfs_attr.c
+++ b/libxfs/xfs_attr.c
@@ -48,6 +48,7 @@ STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
STATIC int xfs_attr_leaf_get(xfs_da_args_t *args);
STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args, bool roll_trans);
STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args, bool roll_trans);
+STATIC int xfs_leaf_has_attr(xfs_da_args_t *args);
/*
* Internal routines when attribute list is more than one block.
@@ -55,6 +56,7 @@ STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args, bool roll_trans);
STATIC int xfs_attr_node_get(xfs_da_args_t *args);
STATIC int xfs_attr_node_addname(xfs_da_args_t *args, bool roll_trans);
STATIC int xfs_attr_node_removename(xfs_da_args_t *args, bool roll_trans);
+STATIC int xfs_attr_node_hasname(xfs_da_args_t *args);
STATIC int xfs_attr_fillstate(xfs_da_state_t *state);
STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
@@ -316,6 +318,29 @@ out:
}
/*
+ * Return successful if attr is found, or ENOATTR if not
+ */
+int
+xfs_has_attr(
+ struct xfs_da_args *args)
+{
+ struct xfs_inode *dp = args->dp;
+ int error;
+
+ if (!xfs_inode_hasattr(dp))
+ error = -ENOATTR;
+ else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
+ ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
+ error = xfs_shortform_has_attr(args);
+ } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
+ error = xfs_leaf_has_attr(args);
+ else
+ error = xfs_attr_node_hasname(args);
+
+ return error;
+}
+
+/*
* Remove the attribute specified in @args.
*/
int
@@ -853,6 +878,29 @@ out_defer_cancel:
}
/*
+ * Return successful if attr is found, or ENOATTR if not
+ */
+STATIC int
+xfs_leaf_has_attr(
+ struct xfs_da_args *args)
+{
+ struct xfs_buf *bp;
+ int error = 0;
+
+ args->blkno = 0;
+ error = xfs_attr3_leaf_read(args->trans, args->dp,
+ args->blkno, -1, &bp);
+ if (error)
+ return error;
+
+ error = xfs_attr3_leaf_lookup_int(bp, args);
+ error = (error == -ENOATTR) ? -ENOATTR : 0;
+ xfs_trans_brelse(args->trans, bp);
+
+ return error;
+}
+
+/*
* Remove a name from the leaf attribute list structure
*
* This leaf block cannot have a "remote" value, we only call this routine
@@ -1188,6 +1236,36 @@ out_defer_cancel:
}
/*
+ * Return successful if attr is found, or ENOATTR if not
+ */
+STATIC int
+xfs_attr_node_hasname(
+ struct xfs_da_args *args)
+{
+ struct xfs_da_state *state;
+ struct xfs_inode *dp;
+ int retval, error;
+
+ /*
+ * Tie a string around our finger to remind us where we are.
+ */
+ dp = args->dp;
+ state = xfs_da_state_alloc();
+ state->args = args;
+ state->mp = dp->i_mount;
+
+ /*
+ * Search to see if name exists, and get back a pointer to it.
+ */
+ error = xfs_da3_node_lookup_int(state, &retval);
+ if (error || (retval != -EEXIST)) {
+ if (error == 0)
+ error = retval;
+ }
+ return error;
+}
+
+/*
* Remove a name from a B-tree attribute list.
*
* This will involve walking down the Btree, and may involve joining
diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h
index 6e546a1..1225c42 100644
--- a/libxfs/xfs_attr.h
+++ b/libxfs/xfs_attr.h
@@ -162,6 +162,7 @@ int xfs_attr_set(struct xfs_inode *dp, const unsigned char *name,
int xfs_attr_set_args(struct xfs_da_args *args, struct xfs_buf **leaf_bp,
bool roll_trans);
int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags);
+int xfs_has_attr(struct xfs_da_args *args);
int xfs_attr_remove_args(struct xfs_da_args *args, bool roll_trans);
int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
int flags, struct attrlist_cursor_kern *cursor);
diff --git a/libxfs/xfs_attr_leaf.c b/libxfs/xfs_attr_leaf.c
index 60444d0..d84cd59 100644
--- a/libxfs/xfs_attr_leaf.c
+++ b/libxfs/xfs_attr_leaf.c
@@ -619,6 +619,39 @@ xfs_attr_fork_remove(
}
/*
+ * Return successful if attr is found, or ENOATTR if not
+ */
+int
+xfs_shortform_has_attr(
+ struct xfs_da_args *args)
+{
+ struct xfs_attr_shortform *sf;
+ struct xfs_attr_sf_entry *sfe;
+ int base = sizeof(struct xfs_attr_sf_hdr);
+ int size = 0;
+ int end;
+ int i;
+
+ sf = (struct xfs_attr_shortform *)args->dp->i_afp->if_u1.if_data;
+ sfe = &sf->list[0];
+ end = sf->hdr.count;
+ for (i = 0; i < end; sfe = XFS_ATTR_SF_NEXTENTRY(sfe),
+ base += size, i++) {
+ size = XFS_ATTR_SF_ENTSIZE(sfe);
+ if (sfe->namelen != args->namelen)
+ continue;
+ if (memcmp(sfe->nameval, args->name, args->namelen) != 0)
+ continue;
+ if (!xfs_attr_namesp_match(args->flags, sfe->flags))
+ continue;
+ break;
+ }
+ if (i == end)
+ return -ENOATTR;
+ return 0;
+}
+
+/*
* Remove an attribute from the shortform attribute list structure.
*/
int
diff --git a/libxfs/xfs_attr_leaf.h b/libxfs/xfs_attr_leaf.h
index 9d830ec..98dd169 100644
--- a/libxfs/xfs_attr_leaf.h
+++ b/libxfs/xfs_attr_leaf.h
@@ -39,6 +39,7 @@ int xfs_attr_shortform_getvalue(struct xfs_da_args *args);
int xfs_attr_shortform_to_leaf(struct xfs_da_args *args,
struct xfs_buf **leaf_bp);
int xfs_attr_shortform_remove(struct xfs_da_args *args);
+int xfs_shortform_has_attr(struct xfs_da_args *args);
int xfs_attr_shortform_allfit(struct xfs_buf *bp, struct xfs_inode *dp);
int xfs_attr_shortform_bytesfit(struct xfs_inode *dp, int bytes);
xfs_failaddr_t xfs_attr_shortform_verify(struct xfs_inode *ip);
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 09/30] xfsprogs: Add attr context to log item
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (7 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 08/30] xfsprogs: Add xfs_has_attr and subroutines Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 10/30] xfsprogs: Roll delayed attr operations by returning EAGAIN Allison Henderson
` (20 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
This patch modifies xfs_attr_item to store a xfs_da_args, a xfs_buf pointer
and a new state type. We will use these in the next patch when
we modify xfs_set_attr_args to roll transactions by returning EAGAIN.
Because the subroutines of this function modify the contents of these
structures, we need to find a place to store them where they remain
instantiated across multiple calls to xfs_set_attr_args.
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
libxfs/xfs_attr.h | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h
index 1225c42..ad2a73c 100644
--- a/libxfs/xfs_attr.h
+++ b/libxfs/xfs_attr.h
@@ -74,6 +74,12 @@ typedef struct attrlist_ent { /* data from attr_list() */
char a_name[1]; /* attr name (NULL terminated) */
} attrlist_ent_t;
+/* Attr state machine types */
+typedef enum {
+ XFS_ATTR_STATE1 = 1,
+ XFS_ATTR_STATE2 = 2,
+} xfs_attr_state_t;
+
/*
* List of attrs to commit later.
*/
@@ -85,7 +91,16 @@ struct xfs_attr_item {
void* xattri_name; /* attr name */
uint32_t xattri_name_len; /* length of name */
uint32_t xattri_flags; /* attr flags */
- struct list_head xattri_list;
+
+ /*
+ * Delayed attr parameters that need to remain instantiated
+ * across transaction rolls during the defer finish
+ */
+ struct xfs_buf *xattri_leaf_bp; /* Leaf buf to release */
+ xfs_attr_state_t xattri_state; /* state machine marker */
+ struct xfs_da_args xattri_args; /* args context */
+
+ struct list_head xattri_list;
/*
* A byte array follows the header containing the file name and
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 10/30] xfsprogs: Roll delayed attr operations by returning EAGAIN
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (8 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 09/30] xfsprogs: Add attr context to log item Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 11/30] xfsprogs: Remove roll_trans boolean Allison Henderson
` (19 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
This patch modifies xfs_attr_set_args to return -EAGAIN
when a transaction needs to be rolled. All functions
currently calling xfs_attr_set_args are modified to use
the deferred attr operation, or handle the -EAGAIN return
code
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
libxfs/xfs_attr.c | 43 +++++++++++++++++++++++++++++++++----------
libxfs/xfs_attr.h | 2 +-
2 files changed, 34 insertions(+), 11 deletions(-)
diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
index ad0c5cd..1935128 100644
--- a/libxfs/xfs_attr.c
+++ b/libxfs/xfs_attr.c
@@ -233,12 +233,20 @@ int
xfs_attr_set_args(
struct xfs_da_args *args,
struct xfs_buf **leaf_bp,
+ xfs_attr_state_t *state,
bool roll_trans)
{
struct xfs_inode *dp = args->dp;
int error = 0;
int sf_size;
+ switch (*state) {
+ case (XFS_ATTR_STATE1):
+ goto state1;
+ case (XFS_ATTR_STATE2):
+ goto state2;
+ }
+
/*
* New inodes setting the parent pointer attr will
* not have an attribute fork yet. So set the attribute
@@ -259,7 +267,6 @@ xfs_attr_set_args(
if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL ||
(dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
dp->i_d.di_anextents == 0)) {
-
/*
* Build initial attribute list (if required).
*/
@@ -273,6 +280,9 @@ xfs_attr_set_args(
if (error != -ENOSPC)
goto out;
+ *state = XFS_ATTR_STATE1;
+ return -EAGAIN;
+state1:
/*
* It won't fit in the shortform, transform to a leaf block.
* GROT: another possible req'mt for a double-split btree op.
@@ -281,14 +291,14 @@ xfs_attr_set_args(
if (error)
goto out;
- if (roll_trans) {
- /*
- * Prevent the leaf buffer from being unlocked so that a
- * concurrent AIL push cannot grab the half-baked leaf
- * buffer and run into problems with the write verifier.
- */
- xfs_trans_bhold(args->trans, *leaf_bp);
+ /*
+ * Prevent the leaf buffer from being unlocked so that a
+ * concurrent AIL push cannot grab the half-baked leaf
+ * buffer and run into problems with the write verifier.
+ */
+ xfs_trans_bhold(args->trans, *leaf_bp);
+ if (roll_trans) {
error = xfs_defer_finish(&args->trans);
if (error)
goto out;
@@ -304,6 +314,12 @@ xfs_attr_set_args(
xfs_trans_bjoin(args->trans, *leaf_bp);
*leaf_bp = NULL;
}
+
+ *state = XFS_ATTR_STATE2;
+ return -EAGAIN;
+state2:
+ if (*leaf_bp != NULL)
+ xfs_trans_brelse(args->trans, *leaf_bp);
}
if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
@@ -436,7 +452,9 @@ xfs_attr_set(
}
xfs_trans_ijoin(args.trans, dp, 0);
- error = xfs_attr_set_args(&args, &leaf_bp, true);
+
+ error = xfs_attr_set_deferred(dp, args.trans, name, strlen(name),
+ value, valuelen, flags);
if (error)
goto out;
@@ -566,8 +584,13 @@ xfs_attr_remove(
*/
xfs_trans_ijoin(args.trans, dp, 0);
- error = xfs_attr_remove_args(&args, true);
+ error = xfs_has_attr(&args);
+ if (error)
+ goto out;
+
+ error = xfs_attr_remove_deferred(dp, args.trans,
+ name, strlen(name), flags);
if (error)
goto out;
diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h
index ad2a73c..ee4bc13 100644
--- a/libxfs/xfs_attr.h
+++ b/libxfs/xfs_attr.h
@@ -175,7 +175,7 @@ int xfs_attr_get(struct xfs_inode *ip, const unsigned char *name,
int xfs_attr_set(struct xfs_inode *dp, const unsigned char *name,
unsigned char *value, int valuelen, int flags);
int xfs_attr_set_args(struct xfs_da_args *args, struct xfs_buf **leaf_bp,
- bool roll_trans);
+ xfs_attr_state_t *state, bool roll_trans);
int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags);
int xfs_has_attr(struct xfs_da_args *args);
int xfs_attr_remove_args(struct xfs_da_args *args, bool roll_trans);
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 11/30] xfsprogs: Remove roll_trans boolean
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (9 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 10/30] xfsprogs: Roll delayed attr operations by returning EAGAIN Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 12/30] xfsprogs: Remove all strlen calls in all xfs_attr_* functions for attr names Allison Henderson
` (18 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
All calls to functions using this parameter are now passing a
false value. We can now remove the boolean and all affected
code
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
libxfs/xfs_attr.c | 168 +++++++----------------------------------------
libxfs/xfs_attr.h | 4 +-
libxfs/xfs_attr_leaf.c | 25 +------
libxfs/xfs_attr_leaf.h | 6 +-
libxfs/xfs_attr_remote.c | 34 +---------
libxfs/xfs_attr_remote.h | 4 +-
6 files changed, 37 insertions(+), 204 deletions(-)
diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
index 1935128..b71d9ed 100644
--- a/libxfs/xfs_attr.c
+++ b/libxfs/xfs_attr.c
@@ -46,16 +46,16 @@ STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
* Internal routines when attribute list is one block.
*/
STATIC int xfs_attr_leaf_get(xfs_da_args_t *args);
-STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args, bool roll_trans);
-STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args, bool roll_trans);
+STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args);
+STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args);
STATIC int xfs_leaf_has_attr(xfs_da_args_t *args);
/*
* Internal routines when attribute list is more than one block.
*/
STATIC int xfs_attr_node_get(xfs_da_args_t *args);
-STATIC int xfs_attr_node_addname(xfs_da_args_t *args, bool roll_trans);
-STATIC int xfs_attr_node_removename(xfs_da_args_t *args, bool roll_trans);
+STATIC int xfs_attr_node_addname(xfs_da_args_t *args);
+STATIC int xfs_attr_node_removename(xfs_da_args_t *args);
STATIC int xfs_attr_node_hasname(xfs_da_args_t *args);
STATIC int xfs_attr_fillstate(xfs_da_state_t *state);
STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
@@ -233,8 +233,7 @@ int
xfs_attr_set_args(
struct xfs_da_args *args,
struct xfs_buf **leaf_bp,
- xfs_attr_state_t *state,
- bool roll_trans)
+ xfs_attr_state_t *state)
{
struct xfs_inode *dp = args->dp;
int error = 0;
@@ -298,23 +297,6 @@ state1:
*/
xfs_trans_bhold(args->trans, *leaf_bp);
- if (roll_trans) {
- error = xfs_defer_finish(&args->trans);
- if (error)
- goto out;
-
- /*
- * Commit the leaf transformation. We'll need another
- * (linked) transaction to add the new attribute to the
- * leaf.
- */
- error = xfs_trans_roll_inode(&args->trans, dp);
- if (error)
- goto out;
- xfs_trans_bjoin(args->trans, *leaf_bp);
- *leaf_bp = NULL;
- }
-
*state = XFS_ATTR_STATE2;
return -EAGAIN;
state2:
@@ -323,9 +305,9 @@ state2:
}
if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
- error = xfs_attr_leaf_addname(args, roll_trans);
+ error = xfs_attr_leaf_addname(args);
else
- error = xfs_attr_node_addname(args, roll_trans);
+ error = xfs_attr_node_addname(args);
if (error)
goto out;
@@ -361,8 +343,7 @@ xfs_has_attr(
*/
int
xfs_attr_remove_args(
- struct xfs_da_args *args,
- bool roll_trans)
+ struct xfs_da_args *args)
{
struct xfs_inode *dp = args->dp;
int error;
@@ -373,9 +354,9 @@ xfs_attr_remove_args(
ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
error = xfs_attr_shortform_remove(args);
} else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
- error = xfs_attr_leaf_removename(args, roll_trans);
+ error = xfs_attr_leaf_removename(args);
} else {
- error = xfs_attr_node_removename(args, roll_trans);
+ error = xfs_attr_node_removename(args);
}
return error;
@@ -713,8 +694,7 @@ xfs_attr_shortform_addname(xfs_da_args_t *args)
*/
STATIC int
xfs_attr_leaf_addname(
- struct xfs_da_args *args,
- bool roll_trans)
+ struct xfs_da_args *args)
{
struct xfs_inode *dp;
struct xfs_buf *bp;
@@ -780,39 +760,14 @@ xfs_attr_leaf_addname(
if (error)
goto out_defer_cancel;
- if (roll_trans) {
- error = xfs_defer_finish(&args->trans);
- if (error)
- return error;
-
- /*
- * Commit the current trans (including the inode) and
- * start a new one.
- */
- error = xfs_trans_roll_inode(&args->trans, dp);
- if (error)
- return error;
- }
-
/*
* Fob the whole rest of the problem off on the Btree code.
*/
- error = xfs_attr_node_addname(args, roll_trans);
+ error = xfs_attr_node_addname(args);
return error;
}
-
- if (roll_trans) {
- /*
- * Commit the transaction that added the attr name so that
- * later routines can manage their own transactions.
- */
- error = xfs_trans_roll_inode(&args->trans, dp);
- if (error)
- return error;
- }
-
/*
* If there was an out-of-line value, allocate the blocks we
* identified for its storage and copy the value. This is done
@@ -820,7 +775,7 @@ xfs_attr_leaf_addname(
* maximum size of a transaction and/or hit a deadlock.
*/
if (args->rmtblkno > 0) {
- error = xfs_attr_rmtval_set(args, roll_trans);
+ error = xfs_attr_rmtval_set(args);
if (error)
return error;
}
@@ -836,7 +791,7 @@ xfs_attr_leaf_addname(
* In a separate transaction, set the incomplete flag on the
* "old" attr and clear the incomplete flag on the "new" attr.
*/
- error = xfs_attr3_leaf_flipflags(args, roll_trans);
+ error = xfs_attr3_leaf_flipflags(args);
if (error)
return error;
@@ -850,7 +805,7 @@ xfs_attr_leaf_addname(
args->rmtblkcnt = args->rmtblkcnt2;
args->rmtvaluelen = args->rmtvaluelen2;
if (args->rmtblkno) {
- error = xfs_attr_rmtval_remove(args, roll_trans);
+ error = xfs_attr_rmtval_remove(args);
if (error)
return error;
}
@@ -874,25 +829,13 @@ xfs_attr_leaf_addname(
/* bp is gone due to xfs_da_shrink_inode */
if (error)
goto out_defer_cancel;
-
- if (roll_trans) {
- error = xfs_defer_finish(&args->trans);
- if (error)
- return error;
- }
}
- /*
- * Commit the remove and start the next trans in series.
- */
- if (roll_trans)
- error = xfs_trans_roll_inode(&args->trans, dp);
-
} else if (args->rmtblkno > 0) {
/*
* Added a "remote" value, just clear the incomplete flag.
*/
- error = xfs_attr3_leaf_clearflag(args, roll_trans);
+ error = xfs_attr3_leaf_clearflag(args);
}
return error;
out_defer_cancel:
@@ -931,8 +874,7 @@ xfs_leaf_has_attr(
*/
STATIC int
xfs_attr_leaf_removename(
- struct xfs_da_args *args,
- bool roll_trans)
+ struct xfs_da_args *args)
{
struct xfs_inode *dp;
struct xfs_buf *bp;
@@ -965,11 +907,6 @@ xfs_attr_leaf_removename(
/* bp is gone due to xfs_da_shrink_inode */
if (error)
goto out_defer_cancel;
- if (roll_trans) {
- error = xfs_defer_finish(&args->trans);
- if (error)
- return error;
- }
}
return 0;
out_defer_cancel:
@@ -1025,8 +962,7 @@ xfs_attr_leaf_get(xfs_da_args_t *args)
*/
STATIC int
xfs_attr_node_addname(
- struct xfs_da_args *args,
- bool roll_trans)
+ struct xfs_da_args *args)
{
struct xfs_da_state *state;
struct xfs_da_state_blk *blk;
@@ -1096,20 +1032,6 @@ restart:
if (error)
goto out_defer_cancel;
- if (roll_trans) {
- error = xfs_defer_finish(&args->trans);
- if (error)
- goto out;
-
- /*
- * Commit the node conversion and start the next
- * trans in the chain.
- */
- error = xfs_trans_roll_inode(&args->trans, dp);
- if (error)
- goto out;
- }
-
goto restart;
}
@@ -1122,12 +1044,6 @@ restart:
error = xfs_da3_split(state);
if (error)
goto out_defer_cancel;
-
- if (roll_trans) {
- error = xfs_defer_finish(&args->trans);
- if (error)
- goto out;
- }
} else {
/*
* Addition succeeded, update Btree hashvals.
@@ -1143,23 +1059,13 @@ restart:
state = NULL;
/*
- * Commit the leaf addition or btree split and start the next
- * trans in the chain.
- */
- if (roll_trans) {
- error = xfs_trans_roll_inode(&args->trans, dp);
- if (error)
- goto out;
- }
-
- /*
* If there was an out-of-line value, allocate the blocks we
* identified for its storage and copy the value. This is done
* after we create the attribute so that we don't overflow the
* maximum size of a transaction and/or hit a deadlock.
*/
if (args->rmtblkno > 0) {
- error = xfs_attr_rmtval_set(args, roll_trans);
+ error = xfs_attr_rmtval_set(args);
if (error)
return error;
}
@@ -1175,7 +1081,7 @@ restart:
* In a separate transaction, set the incomplete flag on the
* "old" attr and clear the incomplete flag on the "new" attr.
*/
- error = xfs_attr3_leaf_flipflags(args, roll_trans);
+ error = xfs_attr3_leaf_flipflags(args);
if (error)
goto out;
@@ -1189,7 +1095,7 @@ restart:
args->rmtblkcnt = args->rmtblkcnt2;
args->rmtvaluelen = args->rmtvaluelen2;
if (args->rmtblkno) {
- error = xfs_attr_rmtval_remove(args, roll_trans);
+ error = xfs_attr_rmtval_remove(args);
if (error)
return error;
}
@@ -1223,11 +1129,6 @@ restart:
error = xfs_da3_join(state);
if (error)
goto out_defer_cancel;
- if (roll_trans) {
- error = xfs_defer_finish(&args->trans);
- if (error)
- goto out;
- }
}
/*
@@ -1241,7 +1142,7 @@ restart:
/*
* Added a "remote" value, just clear the incomplete flag.
*/
- error = xfs_attr3_leaf_clearflag(args, roll_trans);
+ error = xfs_attr3_leaf_clearflag(args);
if (error)
goto out;
}
@@ -1297,8 +1198,7 @@ xfs_attr_node_hasname(
*/
STATIC int
xfs_attr_node_removename(
- struct xfs_da_args *args,
- bool roll_trans)
+ struct xfs_da_args *args)
{
struct xfs_da_state *state;
struct xfs_da_state_blk *blk;
@@ -1348,10 +1248,10 @@ xfs_attr_node_removename(
* Mark the attribute as INCOMPLETE, then bunmapi() the
* remote value.
*/
- error = xfs_attr3_leaf_setflag(args, roll_trans);
+ error = xfs_attr3_leaf_setflag(args);
if (error)
goto out;
- error = xfs_attr_rmtval_remove(args, roll_trans);
+ error = xfs_attr_rmtval_remove(args);
if (error)
goto out;
@@ -1379,19 +1279,6 @@ xfs_attr_node_removename(
error = xfs_da3_join(state);
if (error)
goto out_defer_cancel;
-
- if (roll_trans) {
- error = xfs_defer_finish(&args->trans);
- if (error)
- goto out;
- /*
- * Commit the Btree join operation and
- * start a new trans.
- */
- error = xfs_trans_roll_inode(&args->trans, dp);
- if (error)
- goto out;
- }
}
/*
@@ -1415,11 +1302,6 @@ xfs_attr_node_removename(
if (error)
goto out_defer_cancel;
- if (roll_trans) {
- error = xfs_defer_finish(&args->trans);
- if (error)
- goto out;
- }
} else
xfs_trans_brelse(args->trans, bp);
}
diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h
index ee4bc13..c076f0c 100644
--- a/libxfs/xfs_attr.h
+++ b/libxfs/xfs_attr.h
@@ -175,10 +175,10 @@ int xfs_attr_get(struct xfs_inode *ip, const unsigned char *name,
int xfs_attr_set(struct xfs_inode *dp, const unsigned char *name,
unsigned char *value, int valuelen, int flags);
int xfs_attr_set_args(struct xfs_da_args *args, struct xfs_buf **leaf_bp,
- xfs_attr_state_t *state, bool roll_trans);
+ xfs_attr_state_t *state);
int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags);
int xfs_has_attr(struct xfs_da_args *args);
-int xfs_attr_remove_args(struct xfs_da_args *args, bool roll_trans);
+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);
int xfs_attr_args_init(struct xfs_da_args *args, struct xfs_inode *dp,
diff --git a/libxfs/xfs_attr_leaf.c b/libxfs/xfs_attr_leaf.c
index d84cd59..7942aee 100644
--- a/libxfs/xfs_attr_leaf.c
+++ b/libxfs/xfs_attr_leaf.c
@@ -2667,8 +2667,7 @@ xfs_attr_leaf_newentsize(
*/
int
xfs_attr3_leaf_clearflag(
- struct xfs_da_args *args,
- bool roll_trans)
+ struct xfs_da_args *args)
{
struct xfs_attr_leafblock *leaf;
struct xfs_attr_leaf_entry *entry;
@@ -2726,11 +2725,6 @@ xfs_attr3_leaf_clearflag(
XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt)));
}
- /*
- * Commit the flag value change and start the next trans in series.
- */
- if (roll_trans)
- error = xfs_trans_roll_inode(&args->trans, args->dp);
return error;
}
@@ -2739,8 +2733,7 @@ xfs_attr3_leaf_clearflag(
*/
int
xfs_attr3_leaf_setflag(
- struct xfs_da_args *args,
- bool roll_trans)
+ struct xfs_da_args *args)
{
struct xfs_attr_leafblock *leaf;
struct xfs_attr_leaf_entry *entry;
@@ -2780,11 +2773,6 @@ xfs_attr3_leaf_setflag(
XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt)));
}
- /*
- * Commit the flag value change and start the next trans in series.
- */
- if (roll_trans)
- error = xfs_trans_roll_inode(&args->trans, args->dp);
return error;
}
@@ -2797,8 +2785,7 @@ xfs_attr3_leaf_setflag(
*/
int
xfs_attr3_leaf_flipflags(
- struct xfs_da_args *args,
- bool roll_trans)
+ struct xfs_da_args *args)
{
struct xfs_attr_leafblock *leaf1;
struct xfs_attr_leafblock *leaf2;
@@ -2901,11 +2888,5 @@ xfs_attr3_leaf_flipflags(
XFS_DA_LOGRANGE(leaf2, name_rmt, sizeof(*name_rmt)));
}
- /*
- * Commit the flag value change and start the next trans in series.
- */
- if (roll_trans)
- error = xfs_trans_roll_inode(&args->trans, args->dp);
-
return error;
}
diff --git a/libxfs/xfs_attr_leaf.h b/libxfs/xfs_attr_leaf.h
index 98dd169..d38c558 100644
--- a/libxfs/xfs_attr_leaf.h
+++ b/libxfs/xfs_attr_leaf.h
@@ -51,9 +51,9 @@ void xfs_attr_fork_remove(struct xfs_inode *ip, struct xfs_trans *tp);
int xfs_attr3_leaf_to_node(struct xfs_da_args *args);
int xfs_attr3_leaf_to_shortform(struct xfs_buf *bp,
struct xfs_da_args *args, int forkoff);
-int xfs_attr3_leaf_clearflag(struct xfs_da_args *args, bool roll_trans);
-int xfs_attr3_leaf_setflag(struct xfs_da_args *args, bool roll_trans);
-int xfs_attr3_leaf_flipflags(struct xfs_da_args *args, bool roll_trans);
+int xfs_attr3_leaf_clearflag(struct xfs_da_args *args);
+int xfs_attr3_leaf_setflag(struct xfs_da_args *args);
+int xfs_attr3_leaf_flipflags(struct xfs_da_args *args);
/*
* Routines used for growing the Btree.
diff --git a/libxfs/xfs_attr_remote.c b/libxfs/xfs_attr_remote.c
index 6446607..ad018a4 100644
--- a/libxfs/xfs_attr_remote.c
+++ b/libxfs/xfs_attr_remote.c
@@ -428,8 +428,7 @@ xfs_attr_rmtval_get(
*/
int
xfs_attr_rmtval_set(
- struct xfs_da_args *args,
- bool roll_trans)
+ struct xfs_da_args *args)
{
struct xfs_inode *dp = args->dp;
struct xfs_mount *mp = dp->i_mount;
@@ -483,26 +482,11 @@ xfs_attr_rmtval_set(
if (error)
goto out_defer_cancel;
- if (roll_trans) {
- error = xfs_defer_finish(&args->trans);
- if (error)
- return error;
- }
-
ASSERT(nmap == 1);
ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
(map.br_startblock != HOLESTARTBLOCK));
lblkno += map.br_blockcount;
blkcnt -= map.br_blockcount;
-
- if (roll_trans) {
- /*
- * Start the next trans in the chain.
- */
- error = xfs_trans_roll_inode(&args->trans, dp);
- if (error)
- return error;
- }
}
/*
@@ -565,8 +549,7 @@ out_defer_cancel:
*/
int
xfs_attr_rmtval_remove(
- struct xfs_da_args *args,
- bool roll_trans)
+ struct xfs_da_args *args)
{
struct xfs_mount *mp = args->dp->i_mount;
xfs_dablk_t lblkno;
@@ -628,19 +611,6 @@ xfs_attr_rmtval_remove(
XFS_BMAPI_ATTRFORK, 1, &done);
if (error)
goto out_defer_cancel;
-
- if (roll_trans) {
- error = xfs_defer_finish(&args->trans);
- if (error)
- return error;
-
- /*
- * Close out trans and start the next one in the chain.
- */
- error = xfs_trans_roll_inode(&args->trans, args->dp);
- if (error)
- return error;
- }
}
return 0;
out_defer_cancel:
diff --git a/libxfs/xfs_attr_remote.h b/libxfs/xfs_attr_remote.h
index c7c073d..9d20b66 100644
--- a/libxfs/xfs_attr_remote.h
+++ b/libxfs/xfs_attr_remote.h
@@ -9,7 +9,7 @@
int xfs_attr3_rmt_blocks(struct xfs_mount *mp, int attrlen);
int xfs_attr_rmtval_get(struct xfs_da_args *args);
-int xfs_attr_rmtval_set(struct xfs_da_args *args, bool roll_trans);
-int xfs_attr_rmtval_remove(struct xfs_da_args *args, bool roll_trans);
+int xfs_attr_rmtval_set(struct xfs_da_args *args);
+int xfs_attr_rmtval_remove(struct xfs_da_args *args);
#endif /* __XFS_ATTR_REMOTE_H__ */
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 12/30] xfsprogs: Remove all strlen calls in all xfs_attr_* functions for attr names
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (10 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 11/30] xfsprogs: Remove roll_trans boolean Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 13/30] xfsprogs: get directory offset when adding directory name Allison Henderson
` (17 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
Parent pointer attributes use a binary name, so strlen will not work.
Calling functions will need to pass in the name length
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
---
libxfs/xfs_attr.c | 16 ++++++++++------
libxfs/xfs_attr.h | 10 ++++++----
2 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
index b71d9ed..1e86c94 100644
--- a/libxfs/xfs_attr.c
+++ b/libxfs/xfs_attr.c
@@ -66,6 +66,7 @@ xfs_attr_args_init(
struct xfs_da_args *args,
struct xfs_inode *dp,
const unsigned char *name,
+ size_t namelen,
int flags)
{
@@ -78,7 +79,7 @@ xfs_attr_args_init(
args->dp = dp;
args->flags = flags;
args->name = name;
- args->namelen = strlen((const char *)name);
+ args->namelen = namelen;
if (args->namelen >= MAXNAMELEN)
return -EFAULT; /* match IRIX behaviour */
@@ -124,6 +125,7 @@ int
xfs_attr_get(
struct xfs_inode *ip,
const unsigned char *name,
+ size_t namelen,
unsigned char *value,
int *valuelenp,
int flags)
@@ -137,7 +139,7 @@ xfs_attr_get(
if (XFS_FORCED_SHUTDOWN(ip->i_mount))
return -EIO;
- error = xfs_attr_args_init(&args, ip, name, flags);
+ error = xfs_attr_args_init(&args, ip, name, namelen, flags);
if (error)
return error;
@@ -366,6 +368,7 @@ int
xfs_attr_set(
struct xfs_inode *dp,
const unsigned char *name,
+ size_t namelen,
unsigned char *value,
int valuelen,
int flags)
@@ -382,7 +385,7 @@ xfs_attr_set(
if (XFS_FORCED_SHUTDOWN(dp->i_mount))
return -EIO;
- error = xfs_attr_args_init(&args, dp, name, flags);
+ error = xfs_attr_args_init(&args, dp, name, namelen, flags);
if (error)
return error;
@@ -434,7 +437,7 @@ xfs_attr_set(
xfs_trans_ijoin(args.trans, dp, 0);
- error = xfs_attr_set_deferred(dp, args.trans, name, strlen(name),
+ error = xfs_attr_set_deferred(dp, args.trans, name, namelen,
value, valuelen, flags);
if (error)
goto out;
@@ -521,6 +524,7 @@ int
xfs_attr_remove(
struct xfs_inode *dp,
const unsigned char *name,
+ size_t namelen,
int flags)
{
struct xfs_mount *mp = dp->i_mount;
@@ -532,7 +536,7 @@ xfs_attr_remove(
if (XFS_FORCED_SHUTDOWN(dp->i_mount))
return -EIO;
- error = xfs_attr_args_init(&args, dp, name, flags);
+ error = xfs_attr_args_init(&args, dp, name, namelen, flags);
if (error)
return error;
@@ -571,7 +575,7 @@ xfs_attr_remove(
error = xfs_attr_remove_deferred(dp, args.trans,
- name, strlen(name), flags);
+ name, namelen, flags);
if (error)
goto out;
diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h
index c076f0c..d3407f1 100644
--- a/libxfs/xfs_attr.h
+++ b/libxfs/xfs_attr.h
@@ -171,18 +171,20 @@ int xfs_attr_list_int(struct xfs_attr_list_context *);
int xfs_inode_hasattr(struct xfs_inode *ip);
int xfs_attr_get_ilocked(struct xfs_inode *ip, struct xfs_da_args *args);
int xfs_attr_get(struct xfs_inode *ip, const unsigned char *name,
- unsigned char *value, int *valuelenp, int flags);
+ size_t namelen, unsigned char *value, int *valuelenp,
+ int flags);
int xfs_attr_set(struct xfs_inode *dp, const unsigned char *name,
- unsigned char *value, int valuelen, int flags);
+ size_t namelen, unsigned char *value, int valuelen, int flags);
int xfs_attr_set_args(struct xfs_da_args *args, struct xfs_buf **leaf_bp,
xfs_attr_state_t *state);
-int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags);
+int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name,
+ size_t namelen, int flags);
int xfs_has_attr(struct xfs_da_args *args);
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);
int xfs_attr_args_init(struct xfs_da_args *args, struct xfs_inode *dp,
- const unsigned char *name, int flags);
+ const unsigned char *name, size_t namelen, int flags);
int xfs_attr_calc_size(struct xfs_da_args *args, int *local);
int xfs_attr_set_deferred(struct xfs_inode *dp, struct xfs_trans *tp,
const unsigned char *name, unsigned int name_len,
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 13/30] xfsprogs: get directory offset when adding directory name
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (11 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 12/30] xfsprogs: Remove all strlen calls in all xfs_attr_* functions for attr names Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 14/30] xfsprogs: get directory offset when removing " Allison Henderson
` (16 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
Return the directory offset information when adding an entry to the
directory.
This offset will be used as the parent pointer offset in xfs_create,
xfs_symlink, xfs_link and xfs_rename.
[dchinner: forward ported and cleaned up]
[dchinner: no s-o-b from Mark]
[bfoster: rebased, use args->geo in dir code]
[achender: rebased, chaged __uint32_t to xfs_dir2_dataptr_t]
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
libxfs/xfs_da_btree.h | 1 +
libxfs/xfs_dir2.c | 9 +++++++--
libxfs/xfs_dir2.h | 2 +-
libxfs/xfs_dir2_block.c | 1 +
libxfs/xfs_dir2_leaf.c | 2 ++
libxfs/xfs_dir2_node.c | 2 ++
libxfs/xfs_dir2_sf.c | 2 ++
mkfs/proto.c | 2 +-
repair/phase6.c | 16 ++++++++--------
9 files changed, 25 insertions(+), 12 deletions(-)
diff --git a/libxfs/xfs_da_btree.h b/libxfs/xfs_da_btree.h
index 84dd865..04a0641 100644
--- a/libxfs/xfs_da_btree.h
+++ b/libxfs/xfs_da_btree.h
@@ -71,6 +71,7 @@ typedef struct xfs_da_args {
int rmtvaluelen2; /* remote attr value length in bytes */
int op_flags; /* operation flags */
enum xfs_dacmp cmpresult; /* name compare result for lookups */
+ xfs_dir2_dataptr_t offset; /* OUT: offset in directory */
} xfs_da_args_t;
/*
diff --git a/libxfs/xfs_dir2.c b/libxfs/xfs_dir2.c
index b0ad4a8..af6f4b1 100644
--- a/libxfs/xfs_dir2.c
+++ b/libxfs/xfs_dir2.c
@@ -241,7 +241,8 @@ xfs_dir_createname(
struct xfs_inode *dp,
struct xfs_name *name,
xfs_ino_t inum, /* new entry inode number */
- xfs_extlen_t total) /* bmap's total block count */
+ xfs_extlen_t total, /* bmap's total block count */
+ xfs_dir2_dataptr_t *offset) /* OUT entry's dir offset */
{
struct xfs_da_args *args;
int rval;
@@ -296,6 +297,10 @@ xfs_dir_createname(
rval = xfs_dir2_node_addname(args);
out_free:
+ /* return the location that this entry was place in the parent inode */
+ if (offset)
+ *offset = args->offset;
+
kmem_free(args);
return rval;
}
@@ -534,7 +539,7 @@ xfs_dir_canenter(
xfs_inode_t *dp,
struct xfs_name *name) /* name of entry to add */
{
- return xfs_dir_createname(tp, dp, name, 0, 0);
+ return xfs_dir_createname(tp, dp, name, 0, 0, NULL);
}
/*
diff --git a/libxfs/xfs_dir2.h b/libxfs/xfs_dir2.h
index c3e3f6b..c164a38 100644
--- a/libxfs/xfs_dir2.h
+++ b/libxfs/xfs_dir2.h
@@ -117,7 +117,7 @@ extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp,
struct xfs_inode *pdp);
extern int xfs_dir_createname(struct xfs_trans *tp, struct xfs_inode *dp,
struct xfs_name *name, xfs_ino_t inum,
- xfs_extlen_t tot);
+ xfs_extlen_t tot, xfs_dir2_dataptr_t *offset);
extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp,
struct xfs_name *name, xfs_ino_t *inum,
struct xfs_name *ci_name);
diff --git a/libxfs/xfs_dir2_block.c b/libxfs/xfs_dir2_block.c
index 554029c..e52344a 100644
--- a/libxfs/xfs_dir2_block.c
+++ b/libxfs/xfs_dir2_block.c
@@ -543,6 +543,7 @@ xfs_dir2_block_addname(
dp->d_ops->data_put_ftype(dep, args->filetype);
tagp = dp->d_ops->data_entry_tag_p(dep);
*tagp = cpu_to_be16((char *)dep - (char *)hdr);
+ args->offset = xfs_dir2_byte_to_dataptr((char *)dep - (char *)hdr);
/*
* Clean up the bestfree array and log the header, tail, and entry.
*/
diff --git a/libxfs/xfs_dir2_leaf.c b/libxfs/xfs_dir2_leaf.c
index dbe4d2e..df1a214 100644
--- a/libxfs/xfs_dir2_leaf.c
+++ b/libxfs/xfs_dir2_leaf.c
@@ -879,6 +879,8 @@ xfs_dir2_leaf_addname(
dp->d_ops->data_put_ftype(dep, args->filetype);
tagp = dp->d_ops->data_entry_tag_p(dep);
*tagp = cpu_to_be16((char *)dep - (char *)hdr);
+ args->offset = xfs_dir2_db_off_to_dataptr(args->geo, use_block,
+ (char *)dep - (char *)hdr);
/*
* Need to scan fix up the bestfree table.
*/
diff --git a/libxfs/xfs_dir2_node.c b/libxfs/xfs_dir2_node.c
index a0d2dce..286c50e 100644
--- a/libxfs/xfs_dir2_node.c
+++ b/libxfs/xfs_dir2_node.c
@@ -2024,6 +2024,8 @@ xfs_dir2_node_addname_int(
dp->d_ops->data_put_ftype(dep, args->filetype);
tagp = dp->d_ops->data_entry_tag_p(dep);
*tagp = cpu_to_be16((char *)dep - (char *)hdr);
+ args->offset = xfs_dir2_db_off_to_dataptr(args->geo, dbno,
+ (char *)dep - (char *)hdr);
xfs_dir2_data_log_entry(args, dbp, dep);
/*
* Rescan the block for bestfree if needed.
diff --git a/libxfs/xfs_dir2_sf.c b/libxfs/xfs_dir2_sf.c
index 24a0e61..e4a1519 100644
--- a/libxfs/xfs_dir2_sf.c
+++ b/libxfs/xfs_dir2_sf.c
@@ -391,6 +391,7 @@ xfs_dir2_sf_addname_easy(
memcpy(sfep->name, args->name, sfep->namelen);
dp->d_ops->sf_put_ino(sfp, sfep, args->inumber);
dp->d_ops->sf_put_ftype(sfep, args->filetype);
+ args->offset = xfs_dir2_byte_to_dataptr(offset);
/*
* Update the header and inode.
@@ -482,6 +483,7 @@ xfs_dir2_sf_addname_hard(
memcpy(sfep->name, args->name, sfep->namelen);
dp->d_ops->sf_put_ino(sfp, sfep, args->inumber);
dp->d_ops->sf_put_ftype(sfep, args->filetype);
+ args->offset = xfs_dir2_byte_to_dataptr(offset);
sfp->count++;
if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && !objchange)
sfp->i8count++;
diff --git a/mkfs/proto.c b/mkfs/proto.c
index a51d011..a0b2003 100644
--- a/mkfs/proto.c
+++ b/mkfs/proto.c
@@ -314,7 +314,7 @@ newdirent(
rsv = XFS_DIRENTER_SPACE_RES(mp, name->len);
- error = -libxfs_dir_createname(tp, pip, name, inum, rsv);
+ error = -libxfs_dir_createname(tp, pip, name, inum, rsv, NULL);
if (error)
fail(_("directory createname error"), error);
}
diff --git a/repair/phase6.c b/repair/phase6.c
index dd59b1e..db37a6c 100644
--- a/repair/phase6.c
+++ b/repair/phase6.c
@@ -1014,7 +1014,7 @@ mk_orphanage(xfs_mount_t *mp)
/*
* create the actual entry
*/
- error = -libxfs_dir_createname(tp, pip, &xname, ip->i_ino, nres);
+ error = -libxfs_dir_createname(tp, pip, &xname, ip->i_ino, nres, NULL);
if (error)
do_error(
_("can't make %s, createname error %d\n"),
@@ -1111,7 +1111,7 @@ mv_orphanage(
libxfs_trans_ijoin(tp, ino_p, 0);
err = -libxfs_dir_createname(tp, orphanage_ip, &xname,
- ino, nres);
+ ino, nres, NULL);
if (err)
do_error(
_("name create failed in %s (%d), filesystem may be out of space\n"),
@@ -1124,7 +1124,7 @@ mv_orphanage(
libxfs_trans_log_inode(tp, orphanage_ip, XFS_ILOG_CORE);
err = -libxfs_dir_createname(tp, ino_p, &xfs_name_dotdot,
- orphanage_ino, nres);
+ orphanage_ino, nres, NULL);
if (err)
do_error(
_("creation of .. entry failed (%d), filesystem may be out of space\n"),
@@ -1145,7 +1145,7 @@ mv_orphanage(
libxfs_trans_ijoin(tp, ino_p, 0);
err = -libxfs_dir_createname(tp, orphanage_ip, &xname,
- ino, nres);
+ ino, nres, NULL);
if (err)
do_error(
_("name create failed in %s (%d), filesystem may be out of space\n"),
@@ -1193,7 +1193,7 @@ mv_orphanage(
libxfs_trans_ijoin(tp, ino_p, 0);
err = -libxfs_dir_createname(tp, orphanage_ip, &xname, ino,
- nres);
+ nres, NULL);
if (err)
do_error(
_("name create failed in %s (%d), filesystem may be out of space\n"),
@@ -1361,7 +1361,7 @@ longform_dir2_rebuild(
libxfs_trans_ijoin(tp, ip, 0);
error = -libxfs_dir_createname(tp, ip, &p->name, p->inum,
- nres);
+ nres, NULL);
if (error) {
do_warn(
_("name create failed in ino %" PRIu64 " (%d), filesystem may be out of space\n"),
@@ -2939,7 +2939,7 @@ process_dir_inode(
libxfs_trans_ijoin(tp, ip, 0);
error = -libxfs_dir_createname(tp, ip, &xfs_name_dotdot,
- ip->i_ino, nres);
+ ip->i_ino, nres, NULL);
if (error)
do_error(
_("can't make \"..\" entry in root inode %" PRIu64 ", createname error %d\n"), ino, error);
@@ -2991,7 +2991,7 @@ process_dir_inode(
libxfs_trans_ijoin(tp, ip, 0);
error = -libxfs_dir_createname(tp, ip, &xfs_name_dot,
- ip->i_ino, nres);
+ ip->i_ino, nres, NULL);
if (error)
do_error(
_("can't make \".\" entry in dir ino %" PRIu64 ", createname error %d\n"),
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 14/30] xfsprogs: get directory offset when removing directory name
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (12 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 13/30] xfsprogs: get directory offset when adding directory name Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 15/30] xfsprogs: get directory offset when replacing a " Allison Henderson
` (15 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
Return the directory offset information when removing an entry to the
directory.
This offset will be used as the parent pointer offset in xfs_remove.
[dchinner: forward ported and cleaned up]
[achender: rebased, changed __unint32_t to xfs_dir2_dataptr_t,
Changed typedefs to raw struct types]
Signed-off-by: Mark Tinguely <tinguely@sgi.com>
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
libxfs/xfs_dir2.c | 6 +++++-
libxfs/xfs_dir2.h | 3 ++-
libxfs/xfs_dir2_block.c | 4 ++--
libxfs/xfs_dir2_leaf.c | 5 +++--
libxfs/xfs_dir2_node.c | 5 +++--
libxfs/xfs_dir2_sf.c | 2 ++
6 files changed, 17 insertions(+), 8 deletions(-)
diff --git a/libxfs/xfs_dir2.c b/libxfs/xfs_dir2.c
index af6f4b1..0093417 100644
--- a/libxfs/xfs_dir2.c
+++ b/libxfs/xfs_dir2.c
@@ -420,7 +420,8 @@ xfs_dir_removename(
struct xfs_inode *dp,
struct xfs_name *name,
xfs_ino_t ino,
- xfs_extlen_t total) /* bmap's total block count */
+ xfs_extlen_t total, /* bmap's total block count */
+ xfs_dir2_dataptr_t *offset) /* OUT: offset in directory */
{
struct xfs_da_args *args;
int rval;
@@ -465,6 +466,9 @@ xfs_dir_removename(
else
rval = xfs_dir2_node_removename(args);
out_free:
+ if (offset)
+ *offset = args->offset;
+
kmem_free(args);
return rval;
}
diff --git a/libxfs/xfs_dir2.h b/libxfs/xfs_dir2.h
index c164a38..2cf1d87 100644
--- a/libxfs/xfs_dir2.h
+++ b/libxfs/xfs_dir2.h
@@ -123,7 +123,8 @@ extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp,
struct xfs_name *ci_name);
extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp,
struct xfs_name *name, xfs_ino_t ino,
- xfs_extlen_t tot);
+ xfs_extlen_t tot,
+ xfs_dir2_dataptr_t *offset);
extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
struct xfs_name *name, xfs_ino_t inum,
xfs_extlen_t tot);
diff --git a/libxfs/xfs_dir2_block.c b/libxfs/xfs_dir2_block.c
index e52344a..514b3fc 100644
--- a/libxfs/xfs_dir2_block.c
+++ b/libxfs/xfs_dir2_block.c
@@ -782,9 +782,9 @@ xfs_dir2_block_removename(
/*
* Point to the data entry using the leaf entry.
*/
+ args->offset = be32_to_cpu(blp[ent].address);
dep = (xfs_dir2_data_entry_t *)((char *)hdr +
- xfs_dir2_dataptr_to_off(args->geo,
- be32_to_cpu(blp[ent].address)));
+ xfs_dir2_dataptr_to_off(args->geo, args->offset));
/*
* Mark the data entry's space free.
*/
diff --git a/libxfs/xfs_dir2_leaf.c b/libxfs/xfs_dir2_leaf.c
index df1a214..21906b1 100644
--- a/libxfs/xfs_dir2_leaf.c
+++ b/libxfs/xfs_dir2_leaf.c
@@ -1399,9 +1399,10 @@ xfs_dir2_leaf_removename(
* Point to the leaf entry, use that to point to the data entry.
*/
lep = &ents[index];
- db = xfs_dir2_dataptr_to_db(args->geo, be32_to_cpu(lep->address));
+ args->offset = be32_to_cpu(lep->address);
+ db = xfs_dir2_dataptr_to_db(args->geo, args->offset);
dep = (xfs_dir2_data_entry_t *)((char *)hdr +
- xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(lep->address)));
+ xfs_dir2_dataptr_to_off(args->geo, args->offset));
needscan = needlog = 0;
oldbest = be16_to_cpu(bf[0].length);
ltp = xfs_dir2_leaf_tail_p(args->geo, leaf);
diff --git a/libxfs/xfs_dir2_node.c b/libxfs/xfs_dir2_node.c
index 286c50e..8a6cee1 100644
--- a/libxfs/xfs_dir2_node.c
+++ b/libxfs/xfs_dir2_node.c
@@ -1235,9 +1235,10 @@ xfs_dir2_leafn_remove(
/*
* Extract the data block and offset from the entry.
*/
- db = xfs_dir2_dataptr_to_db(args->geo, be32_to_cpu(lep->address));
+ args->offset = be32_to_cpu(lep->address);
+ db = xfs_dir2_dataptr_to_db(args->geo, args->offset);
ASSERT(dblk->blkno == db);
- off = xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(lep->address));
+ off = xfs_dir2_dataptr_to_off(args->geo, args->offset);
ASSERT(dblk->index == off);
/*
diff --git a/libxfs/xfs_dir2_sf.c b/libxfs/xfs_dir2_sf.c
index e4a1519..70808c9 100644
--- a/libxfs/xfs_dir2_sf.c
+++ b/libxfs/xfs_dir2_sf.c
@@ -903,6 +903,8 @@ xfs_dir2_sf_removename(
XFS_CMP_EXACT) {
ASSERT(dp->d_ops->sf_get_ino(sfp, sfep) ==
args->inumber);
+ args->offset = xfs_dir2_byte_to_dataptr(
+ xfs_dir2_sf_get_offset(sfep));
break;
}
}
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 15/30] xfsprogs: get directory offset when replacing a directory name
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (13 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 14/30] xfsprogs: get directory offset when removing " Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 16/30] xfsprogs: add parent pointer support to attribute code Allison Henderson
` (14 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
Return the directory offset information when replacing an entry to the
directory.
This offset will be used as the parent pointer offset in xfs_rename.
[dchinner: forward ported and cleaned up]
[achender: rebased, changed __unint32_t to xfs_dir2_dataptr_t,
Changed typedefs to raw struct types]
Signed-off-by: Mark Tinguely <tinguely@sgi.com>
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
libxfs/xfs_dir2.c | 8 ++++++--
libxfs/xfs_dir2.h | 2 +-
libxfs/xfs_dir2_block.c | 4 ++--
libxfs/xfs_dir2_leaf.c | 1 +
libxfs/xfs_dir2_node.c | 1 +
libxfs/xfs_dir2_sf.c | 2 ++
repair/phase6.c | 2 +-
7 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/libxfs/xfs_dir2.c b/libxfs/xfs_dir2.c
index 0093417..f76f412 100644
--- a/libxfs/xfs_dir2.c
+++ b/libxfs/xfs_dir2.c
@@ -466,7 +466,7 @@ xfs_dir_removename(
else
rval = xfs_dir2_node_removename(args);
out_free:
- if (offset)
+ if (!rval && offset)
*offset = args->offset;
kmem_free(args);
@@ -482,7 +482,8 @@ xfs_dir_replace(
struct xfs_inode *dp,
struct xfs_name *name, /* name of entry to replace */
xfs_ino_t inum, /* new inode number */
- xfs_extlen_t total) /* bmap's total block count */
+ xfs_extlen_t total, /* bmap's total block count */
+ xfs_dir2_dataptr_t *offset) /* OUT: offset in directory */
{
struct xfs_da_args *args;
int rval;
@@ -530,6 +531,9 @@ xfs_dir_replace(
else
rval = xfs_dir2_node_replace(args);
out_free:
+ if (offset)
+ *offset = args->offset;
+
kmem_free(args);
return rval;
}
diff --git a/libxfs/xfs_dir2.h b/libxfs/xfs_dir2.h
index 2cf1d87..63de5b9 100644
--- a/libxfs/xfs_dir2.h
+++ b/libxfs/xfs_dir2.h
@@ -127,7 +127,7 @@ extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp,
xfs_dir2_dataptr_t *offset);
extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
struct xfs_name *name, xfs_ino_t inum,
- xfs_extlen_t tot);
+ xfs_extlen_t tot, xfs_dir2_dataptr_t *offset);
extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp,
struct xfs_name *name);
diff --git a/libxfs/xfs_dir2_block.c b/libxfs/xfs_dir2_block.c
index 514b3fc..c80f9e4 100644
--- a/libxfs/xfs_dir2_block.c
+++ b/libxfs/xfs_dir2_block.c
@@ -856,9 +856,9 @@ xfs_dir2_block_replace(
/*
* Point to the data entry we need to change.
*/
+ args->offset = be32_to_cpu(blp[ent].address);
dep = (xfs_dir2_data_entry_t *)((char *)hdr +
- xfs_dir2_dataptr_to_off(args->geo,
- be32_to_cpu(blp[ent].address)));
+ xfs_dir2_dataptr_to_off(args->geo, args->offset));
ASSERT(be64_to_cpu(dep->inumber) != args->inumber);
/*
* Change the inode number to the new value.
diff --git a/libxfs/xfs_dir2_leaf.c b/libxfs/xfs_dir2_leaf.c
index 21906b1..c8e15e5 100644
--- a/libxfs/xfs_dir2_leaf.c
+++ b/libxfs/xfs_dir2_leaf.c
@@ -1535,6 +1535,7 @@ xfs_dir2_leaf_replace(
/*
* Point to the data entry.
*/
+ args->offset = be32_to_cpu(lep->address);
dep = (xfs_dir2_data_entry_t *)
((char *)dbp->b_addr +
xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(lep->address)));
diff --git a/libxfs/xfs_dir2_node.c b/libxfs/xfs_dir2_node.c
index 8a6cee1..b35b22f 100644
--- a/libxfs/xfs_dir2_node.c
+++ b/libxfs/xfs_dir2_node.c
@@ -2239,6 +2239,7 @@ xfs_dir2_node_replace(
hdr = state->extrablk.bp->b_addr;
ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC));
+ args->offset = be32_to_cpu(lep->address);
dep = (xfs_dir2_data_entry_t *)
((char *)hdr +
xfs_dir2_dataptr_to_off(args->geo,
diff --git a/libxfs/xfs_dir2_sf.c b/libxfs/xfs_dir2_sf.c
index 70808c9..7aa82e7 100644
--- a/libxfs/xfs_dir2_sf.c
+++ b/libxfs/xfs_dir2_sf.c
@@ -1029,6 +1029,8 @@ xfs_dir2_sf_replace(
ASSERT(args->inumber != ino);
dp->d_ops->sf_put_ino(sfp, sfep, args->inumber);
dp->d_ops->sf_put_ftype(sfep, args->filetype);
+ args->offset = xfs_dir2_byte_to_dataptr(
+ xfs_dir2_sf_get_offset(sfep));
break;
}
}
diff --git a/repair/phase6.c b/repair/phase6.c
index db37a6c..c4651bc 100644
--- a/repair/phase6.c
+++ b/repair/phase6.c
@@ -1164,7 +1164,7 @@ mv_orphanage(
if (entry_ino_num != orphanage_ino) {
err = -libxfs_dir_replace(tp, ino_p,
&xfs_name_dotdot, orphanage_ino,
- nres);
+ nres, NULL);
if (err)
do_error(
_("name replace op failed (%d), filesystem may be out of space\n"),
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 16/30] xfsprogs: add parent pointer support to attribute code
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (14 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 15/30] xfsprogs: get directory offset when replacing a " Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 17/30] xfsprogs: define parent pointer xattr format Allison Henderson
` (13 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
Add the new parent attribute type. XFS_ATTR_PARENT is used only for
parent pointer entries; it uses reserved blocks like XFS_ATTR_ROOT.
[dchinner: forward ported and cleaned up]
[achender: rebased]
Signed-off-by: Mark Tinguely <tinguely@sgi.com>
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
libxfs/xfs_attr.c | 4 +++-
libxfs/xfs_attr.h | 2 ++
libxfs/xfs_attr_leaf.c | 1 +
libxfs/xfs_da_format.h | 12 ++++++++----
4 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
index 1e86c94..3a5f8f8 100644
--- a/libxfs/xfs_attr.c
+++ b/libxfs/xfs_attr.c
@@ -377,11 +377,13 @@ xfs_attr_set(
struct xfs_buf *leaf_bp = NULL;
struct xfs_da_args args;
struct xfs_trans_res tres;
- int rsvd = (flags & ATTR_ROOT) != 0;
+ int rsvd;
int error, local;
XFS_STATS_INC(mp, xs_attr_set);
+ rsvd = ((flags & ATTR_ROOT) | ATTR_PARENT) != 0;
+
if (XFS_FORCED_SHUTDOWN(dp->i_mount))
return -EIO;
diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h
index d3407f1..126a024 100644
--- a/libxfs/xfs_attr.h
+++ b/libxfs/xfs_attr.h
@@ -32,6 +32,7 @@ struct xfs_attr_list_context;
#define ATTR_SECURE 0x0008 /* use attrs in security namespace */
#define ATTR_CREATE 0x0010 /* pure create: fail if attr already exists */
#define ATTR_REPLACE 0x0020 /* pure set: fail if attr does not exist */
+#define ATTR_PARENT 0x0040 /* use attrs in parent namespace */
#define ATTR_INCOMPLETE 0x4000 /* [kernel] return INCOMPLETE attr keys */
@@ -42,6 +43,7 @@ struct xfs_attr_list_context;
{ ATTR_SECURE, "SECURE" }, \
{ ATTR_CREATE, "CREATE" }, \
{ ATTR_REPLACE, "REPLACE" }, \
+ { ATTR_PARENT, "PARENT" }, \
{ ATTR_KERNOTIME, "KERNOTIME" }, \
{ ATTR_KERNOVAL, "KERNOVAL" }, \
{ ATTR_INCOMPLETE, "INCOMPLETE" }
diff --git a/libxfs/xfs_attr_leaf.c b/libxfs/xfs_attr_leaf.c
index 7942aee..5420682 100644
--- a/libxfs/xfs_attr_leaf.c
+++ b/libxfs/xfs_attr_leaf.c
@@ -21,6 +21,7 @@
#include "xfs_bmap.h"
#include "xfs_attr_sf.h"
#include "xfs_attr_remote.h"
+#include "xfs_attr.h"
#include "xfs_attr_leaf.h"
#include "xfs_trace.h"
#include "xfs_cksum.h"
diff --git a/libxfs/xfs_da_format.h b/libxfs/xfs_da_format.h
index 5d5bf3b..67cb9ea 100644
--- a/libxfs/xfs_da_format.h
+++ b/libxfs/xfs_da_format.h
@@ -746,24 +746,28 @@ struct xfs_attr3_icleaf_hdr {
#define XFS_ATTR_LOCAL_BIT 0 /* attr is stored locally */
#define XFS_ATTR_ROOT_BIT 1 /* limit access to trusted attrs */
#define XFS_ATTR_SECURE_BIT 2 /* limit access to secure attrs */
+#define XFS_ATTR_PARENT_BIT 3 /* parent pointer secure attrs */
#define XFS_ATTR_INCOMPLETE_BIT 7 /* attr in middle of create/delete */
#define XFS_ATTR_LOCAL (1 << XFS_ATTR_LOCAL_BIT)
#define XFS_ATTR_ROOT (1 << XFS_ATTR_ROOT_BIT)
#define XFS_ATTR_SECURE (1 << XFS_ATTR_SECURE_BIT)
+#define XFS_ATTR_PARENT (1 << XFS_ATTR_PARENT_BIT)
#define XFS_ATTR_INCOMPLETE (1 << XFS_ATTR_INCOMPLETE_BIT)
/*
* Conversion macros for converting namespace bits from argument flags
* to ondisk flags.
*/
-#define XFS_ATTR_NSP_ARGS_MASK (ATTR_ROOT | ATTR_SECURE)
-#define XFS_ATTR_NSP_ONDISK_MASK (XFS_ATTR_ROOT | XFS_ATTR_SECURE)
+#define XFS_ATTR_NSP_ARGS_MASK (ATTR_ROOT | ATTR_SECURE | XFS_ATTR_PARENT)
+#define XFS_ATTR_NSP_ONDISK_MASK (XFS_ATTR_ROOT | XFS_ATTR_SECURE | XFS_ATTR_PARENT)
#define XFS_ATTR_NSP_ONDISK(flags) ((flags) & XFS_ATTR_NSP_ONDISK_MASK)
#define XFS_ATTR_NSP_ARGS(flags) ((flags) & XFS_ATTR_NSP_ARGS_MASK)
#define XFS_ATTR_NSP_ARGS_TO_ONDISK(x) (((x) & ATTR_ROOT ? XFS_ATTR_ROOT : 0) |\
- ((x) & ATTR_SECURE ? XFS_ATTR_SECURE : 0))
+ ((x) & ATTR_SECURE ? XFS_ATTR_SECURE : 0) | \
+ ((x) & ATTR_PARENT ? XFS_ATTR_PARENT : 0))
#define XFS_ATTR_NSP_ONDISK_TO_ARGS(x) (((x) & XFS_ATTR_ROOT ? ATTR_ROOT : 0) |\
- ((x) & XFS_ATTR_SECURE ? ATTR_SECURE : 0))
+ ((x) & XFS_ATTR_SECURE ? ATTR_SECURE : 0) | \
+ ((x) & XFS_ATTR_PARENT ? ATTR_PARENT : 0))
/*
* Alignment for namelist and valuelist entries (since they are mixed
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 17/30] xfsprogs: define parent pointer xattr format
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (15 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 16/30] xfsprogs: add parent pointer support to attribute code Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 18/30] xfsprogs: extent transaction reservations for parent attributes Allison Henderson
` (12 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
We need to define the parent pointer attribute format before we
start adding support for it into all the code that needs to use it.
The EA format we will use encodes the following information:
name={parent inode #, parent inode generation, dirent offset}
value={dirent filename}
The inode/gen gives all the information we need to reliably identify
the parent without requiring child->parent lock ordering, and allows
userspace to do pathname component level reconstruction without the
kernel ever needing to verify the parent itself as part of ioctl
calls.
By using the dirent offset in the EA name, we have a method of
knowing the exact parent pointer EA we need to modify/remove in
rename/unlink without an unbound EA name search.
By keeping the dirent name in the value, we have enough information
to be able to validate and reconstruct damaged directory trees.
While the diroffset of a filename alone is not unique enough to
identify the child, the {diroffset,filename,child_inode} tuple is
sufficient. That is, if the diroffset gets reused and points to a
different filename, we can detect that from the contents of EA. If a
link of the same name is created, then we can check whether it
points at the same inode as the parent EA we current have.
[achender: rebased, changed __unint32_t to xfs_dir2_dataptr_t,
changed p_ino to xfs_ino_t and p_namelen to uint8_t,
moved to xfs_da_format for xfs_dir2_dataptr_t]
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
Reviewed-by: Darrick J. Wong<darrick.wong@oracle.com>
---
libxfs/xfs_da_format.h | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/libxfs/xfs_da_format.h b/libxfs/xfs_da_format.h
index 67cb9ea..b6405d7 100644
--- a/libxfs/xfs_da_format.h
+++ b/libxfs/xfs_da_format.h
@@ -873,4 +873,29 @@ static inline unsigned int xfs_dir2_dirblock_bytes(struct xfs_sb *sbp)
return 1 << (sbp->sb_blocklog + sbp->sb_dirblklog);
}
+/*
+ * Parent pointer attribute format definition
+ *
+ * EA name encodes the parent inode number, generation and the offset of
+ * the dirent that points to the child inode. The EA value contains the
+ * same name as the dirent in the parent directory.
+ */
+struct xfs_parent_name_rec {
+ __be64 p_ino;
+ __be32 p_gen;
+ __be32 p_diroffset;
+};
+
+/*
+ * incore version of the above, also contains name pointers so callers
+ * can pass/obtain all the parent pointer information in a single structure
+ */
+struct xfs_parent_name_irec {
+ xfs_ino_t p_ino;
+ uint32_t p_gen;
+ xfs_dir2_dataptr_t p_diroffset;
+ const char *p_name;
+ uint8_t p_namelen;
+};
+
#endif /* __XFS_DA_FORMAT_H__ */
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 18/30] xfsprogs: extent transaction reservations for parent attributes
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (16 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 17/30] xfsprogs: define parent pointer xattr format Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 19/30] xfsprogs: parent pointer attribute creation Allison Henderson
` (11 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
We need to add, remove or modify parent pointer attributes during
create/link/unlink/rename operations atomically with the dirents in the parent
directories being modified. This means they need to be modified in the same
transaction as the parent directories, and so we need to add the required
space for the attribute modifications to the transaction reservations.
[achender: rebased, added xfs_sb_version_hasparent stub]
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
libxfs/xfs_format.h | 5 +++
libxfs/xfs_trans_resv.c | 111 ++++++++++++++++++++++++++++++++++++++----------
libxfs/xfs_trans_resv.h | 1 +
3 files changed, 94 insertions(+), 23 deletions(-)
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index be3a3bf..d00dd0a 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -550,6 +550,11 @@ static inline bool xfs_sb_version_hasreflink(struct xfs_sb *sbp)
(sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_REFLINK);
}
+static inline bool xfs_sb_version_hasparent(struct xfs_sb *sbp)
+{
+ return false; /* We'll enable this at the end of the set */
+}
+
/*
* end of superblock version macros
*/
diff --git a/libxfs/xfs_trans_resv.c b/libxfs/xfs_trans_resv.c
index 4ecf7c2..3f37a8b 100644
--- a/libxfs/xfs_trans_resv.c
+++ b/libxfs/xfs_trans_resv.c
@@ -774,29 +774,30 @@ xfs_calc_sb_reservation(
return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);
}
+/*
+ * Namespace reservations.
+ *
+ * These get tricky when parent pointers are enabled as we have attribute
+ * modifications occurring from within these transactions. Rather than confuse
+ * each of these reservation calculations with the conditional attribute
+ * reservations, add them here in a clear and concise manner. This assumes that
+ * the attribute reservations have already been calculated.
+ *
+ * Note that we only include the static attribute reservation here; the runtime
+ * reservation will have to be modified by the size of the attributes being
+ * added/removed/modified. See the comments on the attribute reservation
+ * calculations for more details.
+ *
+ * Note for rename: rename will vastly overestimate requirements. This will be
+ * addressed later when modifications are made to ensure parent attribute
+ * modifications can be done atomically with the rename operation.
+ */
void
-xfs_trans_resv_calc(
+xfs_calc_namespace_reservations(
struct xfs_mount *mp,
struct xfs_trans_resv *resp)
{
- /*
- * The following transactions are logged in physical format and
- * require a permanent reservation on space.
- */
- resp->tr_write.tr_logres = xfs_calc_write_reservation(mp);
- if (xfs_sb_version_hasreflink(&mp->m_sb))
- resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT_REFLINK;
- else
- resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT;
- resp->tr_write.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
-
- resp->tr_itruncate.tr_logres = xfs_calc_itruncate_reservation(mp);
- if (xfs_sb_version_hasreflink(&mp->m_sb))
- resp->tr_itruncate.tr_logcount =
- XFS_ITRUNCATE_LOG_COUNT_REFLINK;
- else
- resp->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT;
- resp->tr_itruncate.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
+ ASSERT(resp->tr_attrsetm.tr_logres > 0);
resp->tr_rename.tr_logres = xfs_calc_rename_reservation(mp);
resp->tr_rename.tr_logcount = XFS_RENAME_LOG_COUNT;
@@ -818,15 +819,77 @@ xfs_trans_resv_calc(
resp->tr_create.tr_logcount = XFS_CREATE_LOG_COUNT;
resp->tr_create.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
+ resp->tr_mkdir.tr_logres = xfs_calc_mkdir_reservation(mp);
+ resp->tr_mkdir.tr_logcount = XFS_MKDIR_LOG_COUNT;
+ resp->tr_mkdir.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
+
+ xfs_calc_parent_ptr_reservations(mp);
+}
+
+void xfs_calc_parent_ptr_reservations(struct xfs_mount *mp)
+{
+ struct xfs_trans_resv *resp = M_RES(mp);
+
+ /* Calculate extra space needed for parent pointer attributes */
+ if (!xfs_sb_version_hasparent(&mp->m_sb))
+ return;
+
+ /* rename can add/remove/modify 4 parent attributes */
+ resp->tr_rename.tr_logres += 4 * max(resp->tr_attrsetm.tr_logres,
+ resp->tr_attrrm.tr_logres);
+ resp->tr_rename.tr_logcount += 4 * max(resp->tr_attrsetm.tr_logcount,
+ resp->tr_attrrm.tr_logcount);
+
+ /* create will add 1 parent attribute */
+ resp->tr_create.tr_logres += resp->tr_attrsetm.tr_logres;
+ resp->tr_create.tr_logcount += resp->tr_attrsetm.tr_logcount;
+
+ /* mkdir will add 1 parent attribute */
+ resp->tr_mkdir.tr_logres += resp->tr_attrsetm.tr_logres;
+ resp->tr_mkdir.tr_logcount += resp->tr_attrsetm.tr_logcount;
+
+ /* link will add 1 parent attribute */
+ resp->tr_link.tr_logres += resp->tr_attrsetm.tr_logres;
+ resp->tr_link.tr_logcount += resp->tr_attrsetm.tr_logcount;
+
+ /* symlink will add 1 parent attribute */
+ resp->tr_symlink.tr_logres += resp->tr_attrsetm.tr_logres;
+ resp->tr_symlink.tr_logcount += resp->tr_attrsetm.tr_logcount;
+
+ /* remove will remove 1 parent attribute */
+ resp->tr_remove.tr_logres += resp->tr_attrrm.tr_logres;
+ resp->tr_remove.tr_logcount += resp->tr_attrrm.tr_logcount;
+}
+
+void
+xfs_trans_resv_calc(
+ struct xfs_mount *mp,
+ struct xfs_trans_resv *resp)
+{
+ /*
+ * The following transactions are logged in physical format and
+ * require a permanent reservation on space.
+ */
+ resp->tr_write.tr_logres = xfs_calc_write_reservation(mp);
+ if (xfs_sb_version_hasreflink(&mp->m_sb))
+ resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT_REFLINK;
+ else
+ resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT;
+ resp->tr_write.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
+
+ resp->tr_itruncate.tr_logres = xfs_calc_itruncate_reservation(mp);
+ if (xfs_sb_version_hasreflink(&mp->m_sb))
+ resp->tr_itruncate.tr_logcount =
+ XFS_ITRUNCATE_LOG_COUNT_REFLINK;
+ else
+ resp->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT;
+ resp->tr_itruncate.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
+
resp->tr_create_tmpfile.tr_logres =
xfs_calc_create_tmpfile_reservation(mp);
resp->tr_create_tmpfile.tr_logcount = XFS_CREATE_TMPFILE_LOG_COUNT;
resp->tr_create_tmpfile.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
- resp->tr_mkdir.tr_logres = xfs_calc_mkdir_reservation(mp);
- resp->tr_mkdir.tr_logcount = XFS_MKDIR_LOG_COUNT;
- resp->tr_mkdir.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
-
resp->tr_ifree.tr_logres = xfs_calc_ifree_reservation(mp);
resp->tr_ifree.tr_logcount = XFS_INACTIVE_LOG_COUNT;
resp->tr_ifree.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
@@ -858,6 +921,8 @@ xfs_trans_resv_calc(
resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT;
resp->tr_qm_dqalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
+ xfs_calc_namespace_reservations(mp, resp);
+
/*
* The following transactions are logged in logical format with
* a default log count.
diff --git a/libxfs/xfs_trans_resv.h b/libxfs/xfs_trans_resv.h
index 7241ab2..0197d9e 100644
--- a/libxfs/xfs_trans_resv.h
+++ b/libxfs/xfs_trans_resv.h
@@ -93,5 +93,6 @@ struct xfs_trans_resv {
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);
+void xfs_calc_parent_ptr_reservations(struct xfs_mount *mp);
#endif /* __XFS_TRANS_RESV_H__ */
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 19/30] xfsprogs: parent pointer attribute creation
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (17 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 18/30] xfsprogs: extent transaction reservations for parent attributes Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 20/30] xfsprogs: Add the parent pointer support to the superblock version 5 Allison Henderson
` (10 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
Add parent pointer attribute during xfs_create, and
subroutines to initialize attributes
Kernel create routines take advantage of deferred attributes,
where as libxfs routines will add parent pointers directly.
[bfoster: rebase, use VFS inode generation]
[achender: rebased, changed __unint32_t to xfs_dir2_dataptr_t,
fixed some null pointer bugs,
merged error handling patch,
added subroutines to handle attribute initialization,
remove unnecessary ENOSPC handling in xfs_attr_set_first_parent]
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
libxfs/Makefile | 2 +
libxfs/xfs_parent.c | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++++
libxfs/xfs_parent.h | 35 ++++++++++
3 files changed, 234 insertions(+)
diff --git a/libxfs/Makefile b/libxfs/Makefile
index 51ba9d6..9d37e2b 100644
--- a/libxfs/Makefile
+++ b/libxfs/Makefile
@@ -37,6 +37,7 @@ HFILES = \
xfs_ialloc_btree.h \
xfs_inode_buf.h \
xfs_inode_fork.h \
+ xfs_parent.h \
xfs_quota_defs.h \
xfs_refcount.h \
xfs_refcount_btree.h \
@@ -87,6 +88,7 @@ CFILES = cache.c \
xfs_inode_fork.c \
xfs_ialloc_btree.c \
xfs_log_rlimit.c \
+ xfs_parent.c \
xfs_refcount.c \
xfs_refcount_btree.c \
xfs_rmap.c \
diff --git a/libxfs/xfs_parent.c b/libxfs/xfs_parent.c
new file mode 100644
index 0000000..f83815f
--- /dev/null
+++ b/libxfs/xfs_parent.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2015 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation
+ */
+#include "xfs.h"
+#include "xfs_fs.h"
+#include "platform_defs.h"
+#include "xfs_arch.h"
+#include "xfs_format.h"
+#include "xfs_da_format.h"
+#include "xfs_log_format.h"
+#include "list.h"
+#include "xfs_shared.h"
+#include "xfs_trans_resv.h"
+#include "radix-tree.h"
+#include "atomic.h"
+#include "xfs_mount.h"
+#include "xfs_da_format.h"
+#include "xfs_bmap_btree.h"
+#include "cache.h"
+#include "xfs_cksum.h"
+#include "libxfs_io.h"
+#include "xfs_inode.h"
+#include "xfs_trace.h"
+#include "xfs_trans.h"
+#include "xfs_da_btree.h"
+#include "xfs_attr.h"
+#include "xfs_da_btree.h"
+#include "xfs_attr_sf.h"
+#include "libxfs_api_defs.h"
+#include "kmem.h"
+#include "xfs_bmap.h"
+
+/*
+ * Parent pointer attribute handling.
+ *
+ * Because the attribute value is a filename component, it will never be longer
+ * than 255 bytes. This means the attribute will always be a local format
+ * attribute as it is xfs_attr_leaf_entsize_local_max() for v5 filesystems will
+ * always be larger than this (max is 75% of block size).
+ *
+ * Creating a new parent attribute will always create a new attribute - there
+ * should never, ever be an existing attribute in the tree for a new inode.
+ * ENOSPC behaviour is problematic - creating the inode without the parent
+ * pointer is effectively a corruption, so we allow parent attribute creation
+ * to dip into the reserve block pool to avoid unexpected ENOSPC errors from
+ * occurring.
+ */
+
+
+/* Initializes a xfs_parent_name_rec to be stored as an attribute name */
+void
+xfs_init_parent_name_rec(
+ struct xfs_parent_name_rec *rec,
+ struct xfs_inode *ip,
+ uint32_t p_diroffset)
+{
+ xfs_ino_t p_ino = ip->i_ino;
+ uint32_t p_gen = VFS_I(ip)->i_generation;
+
+ rec->p_ino = cpu_to_be64(p_ino);
+ rec->p_gen = cpu_to_be32(p_gen);
+ rec->p_diroffset = cpu_to_be32(p_diroffset);
+}
+
+/* Initializes a xfs_parent_name_irec from an xfs_parent_name_rec */
+void
+xfs_init_parent_name_irec(
+ struct xfs_parent_name_irec *irec,
+ struct xfs_parent_name_rec *rec)
+{
+ irec->p_ino = be64_to_cpu(rec->p_ino);
+ irec->p_gen = be32_to_cpu(rec->p_gen);
+ irec->p_diroffset = be32_to_cpu(rec->p_diroffset);
+}
+
+/*
+ * Directly add a parent pointer instead of as a deferred operation
+ * Currently only used during protofile creation
+ */
+int
+xfs_parent_add(
+ struct xfs_inode *parent,
+ struct xfs_inode *child,
+ struct xfs_name *child_name,
+ uint32_t diroffset)
+{
+ struct xfs_parent_name_rec rec;
+ int error, err2;
+ struct xfs_da_args args;
+ int local = 0;
+ int rsvd = 0;
+ struct xfs_buf *leaf_bp = NULL;
+ struct xfs_trans_res tres;
+ struct xfs_mount *mp = child->i_mount;
+ xfs_attr_state_t state = 0;
+ int flags = ATTR_PARENT;
+
+ xfs_init_parent_name_rec(&rec, parent, diroffset);
+
+ error = xfs_attr_args_init(&args, child, (const unsigned char *)&rec,
+ sizeof(rec), flags);
+ if (error)
+ return error;
+
+ args.hashval = xfs_da_hashname(args.name, args.namelen);
+ args.flags = flags;
+ args.value = (uint8_t *)child_name->name;
+ args.valuelen = child_name->len;
+ args.op_flags = XFS_DA_OP_OKNOENT | XFS_DA_OP_ADDNAME;
+ args.total = xfs_attr_calc_size(&args, &local);
+
+ tres.tr_logres = M_RES(mp)->tr_attrsetm.tr_logres +
+ M_RES(mp)->tr_attrsetrt.tr_logres * args.total;
+ tres.tr_logcount = XFS_ATTRSET_LOG_COUNT;
+ tres.tr_logflags = XFS_TRANS_PERM_LOG_RES;
+
+ /*
+ * Root fork attributes can use reserved data blocks for this
+ * operation if necessary
+ */
+ error = xfs_trans_alloc(mp, &tres, args.total, 0,
+ rsvd ? XFS_TRANS_RESERVE : 0, &args.trans);
+ if (error)
+ goto out;
+
+ /*
+ * If the inode doesn't have an attribute fork, add one.
+ * (inode must not be locked when we call this routine)
+ */
+ if (XFS_IFORK_Q(child) == 0) {
+ int sf_size = sizeof(xfs_attr_sf_hdr_t) +
+ XFS_ATTR_SF_ENTSIZE_BYNAME(args.namelen,
+ args.valuelen);
+
+ error = xfs_bmap_add_attrfork(child, sf_size, rsvd);
+ if (error)
+ return error;
+ }
+
+ xfs_trans_ijoin(args.trans, child, 0);
+
+ do {
+ leaf_bp = NULL;
+
+ error = xfs_attr_set_args(&args, &leaf_bp,
+ &state);
+ if (error && error != -EAGAIN)
+ goto out;
+
+ xfs_trans_log_inode(args.trans, child,
+ XFS_ILOG_CORE | XFS_ILOG_ADATA);
+
+ err2 = xfs_trans_commit(args.trans);
+ if (err2) {
+ error = err2;
+ goto out;
+ }
+
+ if (error == -EAGAIN) {
+ err2 = xfs_trans_alloc(mp, &tres, args.total, 0,
+ XFS_TRANS_PERM_LOG_RES, &args.trans);
+ if (err2) {
+ error = err2;
+ goto out;
+ }
+ xfs_trans_ijoin(args.trans, child, 0);
+ }
+ } while (error == -EAGAIN);
+
+ if (leaf_bp)
+ xfs_trans_brelse(args.trans, leaf_bp);
+
+ xfs_trans_log_inode(args.trans, child, XFS_ILOG_CORE);
+
+ return error;
+
+out:
+ if (args.trans)
+ xfs_trans_cancel(args.trans);
+
+ return error;
+}
+
+
diff --git a/libxfs/xfs_parent.h b/libxfs/xfs_parent.h
new file mode 100644
index 0000000..60f1172
--- /dev/null
+++ b/libxfs/xfs_parent.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2018 Oracle, Inc.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation Inc.
+ */
+#ifndef __XFS_PARENT_H__
+#define __XFS_PARENT_H__
+
+#include "xfs_da_format.h"
+#include "xfs_format.h"
+
+/*
+ * Parent pointer attribute prototypes
+ */
+void xfs_init_parent_name_rec(struct xfs_parent_name_rec *rec,
+ struct xfs_inode *ip,
+ uint32_t p_diroffset);
+void xfs_init_parent_name_irec(struct xfs_parent_name_irec *irec,
+ struct xfs_parent_name_rec *rec);
+
+int xfs_parent_add(struct xfs_inode *parent,
+ struct xfs_inode *child, struct xfs_name *child_name,
+ uint32_t diroffset);
+#endif /* __XFS_PARENT_H__ */
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 20/30] xfsprogs: Add the parent pointer support to the superblock version 5.
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (18 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 19/30] xfsprogs: parent pointer attribute creation Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 21/30] xfsprogs: Add helper function xfs_attr_list_context_init Allison Henderson
` (9 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
[dchinner: forward ported and cleaned up]
[achender: rebased and added parent pointer attribute to
compatible attributes mask]
Signed-off-by: Mark Tinguely <tinguely@sgi.com>
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
libxfs/xfs_format.h | 7 +++++--
libxfs/xfs_fs.h | 1 +
libxfs/xfs_sb.c | 2 ++
3 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index d00dd0a..0eb01c1 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -453,10 +453,12 @@ xfs_sb_has_compat_feature(
#define XFS_SB_FEAT_RO_COMPAT_FINOBT (1 << 0) /* free inode btree */
#define XFS_SB_FEAT_RO_COMPAT_RMAPBT (1 << 1) /* reverse map btree */
#define XFS_SB_FEAT_RO_COMPAT_REFLINK (1 << 2) /* reflinked files */
+#define XFS_SB_FEAT_RO_COMPAT_PARENT (1 << 3) /* parent inode ptr */
#define XFS_SB_FEAT_RO_COMPAT_ALL \
(XFS_SB_FEAT_RO_COMPAT_FINOBT | \
XFS_SB_FEAT_RO_COMPAT_RMAPBT | \
- XFS_SB_FEAT_RO_COMPAT_REFLINK)
+ XFS_SB_FEAT_RO_COMPAT_REFLINK| \
+ XFS_SB_FEAT_RO_COMPAT_PARENT)
#define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALL
static inline bool
xfs_sb_has_ro_compat_feature(
@@ -552,7 +554,8 @@ static inline bool xfs_sb_version_hasreflink(struct xfs_sb *sbp)
static inline bool xfs_sb_version_hasparent(struct xfs_sb *sbp)
{
- return false; /* We'll enable this at the end of the set */
+ return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 &&
+ (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_PARENT));
}
/*
diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h
index c8a3b12..407cd61 100644
--- a/libxfs/xfs_fs.h
+++ b/libxfs/xfs_fs.h
@@ -231,6 +231,7 @@ typedef struct xfs_fsop_resblks {
#define XFS_FSOP_GEOM_FLAGS_SPINODES 0x40000 /* sparse inode chunks */
#define XFS_FSOP_GEOM_FLAGS_RMAPBT 0x80000 /* reverse mapping btree */
#define XFS_FSOP_GEOM_FLAGS_REFLINK 0x100000 /* files can share blocks */
+#define XFS_FSOP_GEOM_FLAGS_PARENT 0x200000 /* parent pointers */
/*
* Minimum and maximum sizes need for growth checks.
diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c
index 93584fa..dc70708 100644
--- a/libxfs/xfs_sb.c
+++ b/libxfs/xfs_sb.c
@@ -1125,6 +1125,8 @@ xfs_fs_geometry(
geo->flags |= XFS_FSOP_GEOM_FLAGS_RMAPBT;
if (xfs_sb_version_hasreflink(sbp))
geo->flags |= XFS_FSOP_GEOM_FLAGS_REFLINK;
+ if(xfs_sb_version_hasparent(sbp))
+ geo->flags |= XFS_FSOP_GEOM_FLAGS_PARENT;
if (xfs_sb_version_hassector(sbp))
geo->logsectsize = sbp->sb_logsectsize;
else
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 21/30] xfsprogs: Add helper function xfs_attr_list_context_init
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (19 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 20/30] xfsprogs: Add the parent pointer support to the superblock version 5 Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 22/30] xfsprogs: Add parent pointer ioctl Allison Henderson
` (8 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
This patch adds a helper function xfs_attr_list_context_init
used by xfs_attr_list. This function initializes the
xfs_attr_list_context structure passed to xfs_attr_list_int.
We will need this later to call xfs_attr_list_int_ilocked when
the node is already locked.
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
libxfs/xfs_attr.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h
index 126a024..9afa5eb 100644
--- a/libxfs/xfs_attr.h
+++ b/libxfs/xfs_attr.h
@@ -185,6 +185,9 @@ int xfs_has_attr(struct xfs_da_args *args);
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);
+int xfs_attr_list_context_init(struct xfs_inode *dp, char *buffer, int bufsize,
+ int flags, struct attrlist_cursor_kern *cursor,
+ struct xfs_attr_list_context *context);
int xfs_attr_args_init(struct xfs_da_args *args, struct xfs_inode *dp,
const unsigned char *name, size_t namelen, int flags);
int xfs_attr_calc_size(struct xfs_da_args *args, int *local);
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 22/30] xfsprogs: Add parent pointer ioctl
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (20 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 21/30] xfsprogs: Add helper function xfs_attr_list_context_init Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 23/30] xfs_io: Add delayed attributes error tag Allison Henderson
` (7 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
This patch adds a new file ioctl to retrieve the parent
pointer of a given inode
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
libxfs/xfs_fs.h | 45 +++++++++++++++++++++++++++++++++++++++++++++
libxfs/xfs_parent.c | 10 ++++++++++
libxfs/xfs_parent.h | 2 ++
3 files changed, 57 insertions(+)
diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h
index 407cd61..4c597be 100644
--- a/libxfs/xfs_fs.h
+++ b/libxfs/xfs_fs.h
@@ -568,6 +568,50 @@ struct xfs_scrub_metadata {
XFS_SCRUB_OFLAG_NO_REPAIR_NEEDED)
#define XFS_SCRUB_FLAGS_ALL (XFS_SCRUB_FLAGS_IN | XFS_SCRUB_FLAGS_OUT)
+#define XFS_PPTR_MAXNAMELEN 256
+
+/* return parents of the handle, not the open fd */
+#define XFS_PPTR_IFLAG_HANDLE (1U << 0)
+
+/* target was the root directory */
+#define XFS_PPTR_OFLAG_ROOT (1U << 1)
+
+/* Cursor is done iterating pptrs */
+#define XFS_PPTR_OFLAG_DONE (1U << 2)
+
+/* Get an inode parent pointer through ioctl */
+struct xfs_parent_ptr {
+ __u64 xpp_ino; /* Inode */
+ __u32 xpp_gen; /* Inode generation */
+ __u32 xpp_diroffset; /* Directory offset */
+ __u32 xpp_namelen; /* File name length */
+ __u32 xpp_pad;
+ __u8 xpp_name[XFS_PPTR_MAXNAMELEN]; /* File name */
+};
+
+/* Iterate through an inodes parent pointers */
+struct xfs_pptr_info {
+ struct xfs_handle pi_handle;
+ struct xfs_attrlist_cursor pi_cursor;
+ __u32 pi_flags;
+ __u32 pi_reserved;
+ __u32 pi_ptrs_size;
+ __u32 pi_ptrs_used;
+ __u64 pi_reserved2[6];
+
+ /*
+ * An array of struct xfs_parent_ptr follows the header
+ * information. Use XFS_PPINFO_TO_PP() to access the
+ * parent pointer array entries.
+ */
+};
+
+#define XFS_PPTR_INFO_SIZEOF(nr_ptrs) sizeof (struct xfs_pptr_info) + \
+ nr_ptrs * sizeof(struct xfs_parent_ptr)
+
+#define XFS_PPINFO_TO_PP(info, idx) \
+ (&(((struct xfs_parent_ptr *)((char *)(info) + sizeof(*(info))))[(idx)]))
+
/*
* ioctl limits
*/
@@ -611,6 +655,7 @@ struct xfs_scrub_metadata {
#define XFS_IOC_FREE_EOFBLOCKS _IOR ('X', 58, struct xfs_fs_eofblocks)
/* XFS_IOC_GETFSMAP ------ hoisted 59 */
#define XFS_IOC_SCRUB_METADATA _IOWR('X', 60, struct xfs_scrub_metadata)
+#define XFS_IOC_GETPPOINTER _IOR ('X', 61, struct xfs_parent_ptr)
/*
* ioctl commands that replace IRIX syssgi()'s
diff --git a/libxfs/xfs_parent.c b/libxfs/xfs_parent.c
index f83815f..d506c22 100644
--- a/libxfs/xfs_parent.c
+++ b/libxfs/xfs_parent.c
@@ -43,6 +43,16 @@
#include "kmem.h"
#include "xfs_bmap.h"
+/* Initializes a xfs_parent_ptr from an xfs_parent_name_rec */
+void
+xfs_init_parent_ptr(struct xfs_parent_ptr *xpp,
+ struct xfs_parent_name_rec *rec)
+{
+ xpp->xpp_ino = be64_to_cpu(rec->p_ino);
+ xpp->xpp_gen = be32_to_cpu(rec->p_gen);
+ xpp->xpp_diroffset = be32_to_cpu(rec->p_diroffset);
+}
+
/*
* Parent pointer attribute handling.
*
diff --git a/libxfs/xfs_parent.h b/libxfs/xfs_parent.h
index 60f1172..3fcbbbb 100644
--- a/libxfs/xfs_parent.h
+++ b/libxfs/xfs_parent.h
@@ -32,4 +32,6 @@ void xfs_init_parent_name_irec(struct xfs_parent_name_irec *irec,
int xfs_parent_add(struct xfs_inode *parent,
struct xfs_inode *child, struct xfs_name *child_name,
uint32_t diroffset);
+void xfs_init_parent_ptr(struct xfs_parent_ptr *xpp,
+ struct xfs_parent_name_rec *rec);
#endif /* __XFS_PARENT_H__ */
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 23/30] xfs_io: Add delayed attributes error tag
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (21 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 22/30] xfsprogs: Add parent pointer ioctl Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 24/30] xfsprogs: Add parent pointer flag to cmd Allison Henderson
` (6 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
This patch adds an error tag that we can use to test
delayed attribute recovery and replay
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
io/inject.c | 1 +
libxfs/xfs_errortag.h | 4 +++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/io/inject.c b/io/inject.c
index 2061c95..8711bdb 100644
--- a/io/inject.c
+++ b/io/inject.c
@@ -53,6 +53,7 @@ error_tag(char *name)
{ XFS_ERRTAG_BUF_LRU_REF, "buf_lru_ref" },
{ XFS_ERRTAG_FORCE_SCRUB_REPAIR, "force_repair" },
{ XFS_ERRTAG_FORCE_SUMMARY_RECALC, "bad_summary" },
+ { XFS_ERRTAG_DELAYED_ATTR, "delayed_attr" },
{ XFS_ERRTAG_MAX, NULL }
};
int count;
diff --git a/libxfs/xfs_errortag.h b/libxfs/xfs_errortag.h
index 66077a1..5cd408d 100644
--- a/libxfs/xfs_errortag.h
+++ b/libxfs/xfs_errortag.h
@@ -54,7 +54,8 @@
#define XFS_ERRTAG_BUF_LRU_REF 31
#define XFS_ERRTAG_FORCE_SCRUB_REPAIR 32
#define XFS_ERRTAG_FORCE_SUMMARY_RECALC 33
-#define XFS_ERRTAG_MAX 34
+#define XFS_ERRTAG_DELAYED_ATTR 34
+#define XFS_ERRTAG_MAX 35
/*
* Random factors for above tags, 1 means always, 2 means 1/2 time, etc.
@@ -93,5 +94,6 @@
#define XFS_RANDOM_BUF_LRU_REF 2
#define XFS_RANDOM_FORCE_SCRUB_REPAIR 1
#define XFS_RANDOM_FORCE_SUMMARY_RECALC 1
+#define XFS_RANDOM_DELAYED_ATTR 1
#endif /* __XFS_ERRORTAG_H_ */
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 24/30] xfsprogs: Add parent pointer flag to cmd
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (22 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 23/30] xfs_io: Add delayed attributes error tag Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 25/30] xfsprogs: Add log item printing for ATTRI and ATTRD Allison Henderson
` (5 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
mkfs: enable formatting with parent pointers
Enable parent pointer support in mkfs via the '-n parent' parameter.
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
mkfs/xfs_mkfs.c | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 2e53c1e..d4afc08 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -92,6 +92,7 @@ enum {
N_SIZE = 0,
N_VERSION,
N_FTYPE,
+ N_PARENT,
N_MAX_OPTS,
};
@@ -538,6 +539,7 @@ struct opt_params nopts = {
[N_SIZE] = "size",
[N_VERSION] = "version",
[N_FTYPE] = "ftype",
+ [N_PARENT] = "parent",
},
.subopt_params = {
{ .index = N_SIZE,
@@ -560,6 +562,12 @@ struct opt_params nopts = {
.maxval = 1,
.defaultval = 1,
},
+ { .index = N_PARENT,
+ .conflicts = { { NULL, LAST_CONFLICT } },
+ .minval = 0,
+ .maxval = 1,
+ .defaultval = 1,
+ },
},
};
@@ -864,7 +872,7 @@ usage( void )
/* log subvol */ [-l agnum=n,internal,size=num,logdev=xxx,version=n\n\
sunit=value|su=num,sectsize=num,lazy-count=0|1]\n\
/* label */ [-L label (maximum 12 characters)]\n\
-/* naming */ [-n size=num,version=2|ci,ftype=0|1]\n\
+/* naming */ [-n size=num,version=2|ci,ftype=0|1,parent=0|1]\n\
/* no-op info only */ [-N]\n\
/* prototype file */ [-p fname]\n\
/* quiet */ [-q]\n\
@@ -1603,6 +1611,9 @@ naming_opts_parser(
case N_FTYPE:
cli->sb_feat.dirftype = getnum(value, opts, subopt);
break;
+ case N_PARENT:
+ cli->sb_feat.parent_pointers = getnum(value, &nopts, N_PARENT);
+ break;
default:
return -EINVAL;
}
@@ -2006,6 +2017,14 @@ _("reflink not supported without CRC support\n"));
cli->sb_feat.reflink = false;
}
+ if ((cli->sb_feat.parent_pointers) &&
+ cli->sb_feat.dir_version == 4) {
+ fprintf(stderr,
+_("parent pointers not supported on v4 filesystems\n"));
+ usage();
+ cli->sb_feat.parent_pointers = false;
+ }
+
if ((cli->fsx.fsx_xflags & FS_XFLAG_COWEXTSIZE) &&
!cli->sb_feat.reflink) {
fprintf(stderr,
@@ -2885,6 +2904,8 @@ sb_set_features(
sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_RMAPBT;
if (fp->reflink)
sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_REFLINK;
+ if (fp->parent_pointers)
+ sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_PARENT;
/*
* Sparse inode chunk support has two main inode alignment requirements.
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 25/30] xfsprogs: Add log item printing for ATTRI and ATTRD
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (23 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 24/30] xfsprogs: Add parent pointer flag to cmd Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 26/30] xfsprogs: Add xfs_verify_pptr Allison Henderson
` (4 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
This patch implements a new set of log printing functions to
print the ATTRI and ATTRD items and vectors in the log. These
will be used during log dump and log recover operations.
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
logprint/log_misc.c | 11 ++
logprint/log_print_all.c | 12 +++
logprint/log_redo.c | 262 +++++++++++++++++++++++++++++++++++++++++++++++
logprint/logprint.h | 6 ++
4 files changed, 291 insertions(+)
diff --git a/logprint/log_misc.c b/logprint/log_misc.c
index 640c00e..f932bfd 100644
--- a/logprint/log_misc.c
+++ b/logprint/log_misc.c
@@ -947,6 +947,17 @@ xlog_print_record(
be32_to_cpu(op_head->oh_len));
break;
}
+ case XFS_LI_ATTRI: {
+ skip = xlog_print_trans_attri(&ptr,
+ be32_to_cpu(op_head->oh_len),
+ &i);
+ break;
+ }
+ case XFS_LI_ATTRD: {
+ skip = xlog_print_trans_attrd(&ptr,
+ be32_to_cpu(op_head->oh_len));
+ break;
+ }
case XFS_LI_RUI: {
skip = xlog_print_trans_rui(&ptr,
be32_to_cpu(op_head->oh_len),
diff --git a/logprint/log_print_all.c b/logprint/log_print_all.c
index cd47313..4b839c8 100644
--- a/logprint/log_print_all.c
+++ b/logprint/log_print_all.c
@@ -400,6 +400,12 @@ xlog_recover_print_logitem(
case XFS_LI_EFI:
xlog_recover_print_efi(item);
break;
+ case XFS_LI_ATTRD:
+ xlog_recover_print_attrd(item);
+ break;
+ case XFS_LI_ATTRI:
+ xlog_recover_print_attri(item);
+ break;
case XFS_LI_RUD:
xlog_recover_print_rud(item);
break;
@@ -452,6 +458,12 @@ xlog_recover_print_item(
case XFS_LI_EFI:
printf("EFI");
break;
+ case XFS_LI_ATTRD:
+ printf("ATTRD");
+ break;
+ case XFS_LI_ATTRI:
+ printf("ATTRI");
+ break;
case XFS_LI_RUD:
printf("RUD");
break;
diff --git a/logprint/log_redo.c b/logprint/log_redo.c
index f1f690e..27a6432 100644
--- a/logprint/log_redo.c
+++ b/logprint/log_redo.c
@@ -8,6 +8,7 @@
#include "libxlog.h"
#include "logprint.h"
+#include "xfs_attr_item.h"
/* Extent Free Items */
@@ -653,3 +654,264 @@ xlog_recover_print_bud(
f = item->ri_buf[0].i_addr;
xlog_print_trans_bud(&f, sizeof(struct xfs_bud_log_format));
}
+
+/* Attr Items */
+
+static int
+xfs_attri_copy_log_format(
+ char *buf,
+ uint len,
+ struct xfs_attri_log_format *dst_attri_fmt)
+{
+ uint dst_len = sizeof(struct xfs_attri_log_format);
+
+ if (len == dst_len) {
+ memcpy((char *)dst_attri_fmt, buf, len);
+ return 0;
+ }
+
+ fprintf(stderr, _("%s: bad size of attri format: %u; expected %u\n"),
+ progname, len, dst_len);
+ return 1;
+}
+
+static int
+xfs_attri_copy_name_format(
+ char *buf,
+ uint len,
+ struct xfs_parent_name_rec *dst_attri_fmt)
+{
+ uint dst_len = ATTR_NVEC_SIZE(sizeof(struct xfs_parent_name_rec));
+
+ if (len == dst_len) {
+ memcpy((char *)dst_attri_fmt, buf, len);
+ return 0;
+ }
+
+ fprintf(stderr, _("%s: bad size of attri name format: %u; expected %u\n"),
+ progname, len, dst_len);
+
+ return 1;
+}
+
+int
+xlog_print_trans_attri(
+ char **ptr,
+ uint src_len,
+ int *i)
+{
+ struct xfs_attri_log_format *src_f = NULL;
+ xlog_op_header_t *head = NULL;
+ uint dst_len;
+ int error = 0;
+
+ dst_len = sizeof(struct xfs_attri_log_format);
+ if (src_len != dst_len) {
+ fprintf(stderr, _("%s: bad size of attri format: %u; expected %u\n"),
+ progname, src_len, dst_len);
+ return 1;
+ }
+
+ /*
+ * memmove to ensure 8-byte alignment for the long longs in
+ * xfs_attri_log_format_t structure
+ */
+ if ((src_f = (struct xfs_attri_log_format *)malloc(src_len)) == NULL) {
+ fprintf(stderr, _("%s: xlog_print_trans_attri: malloc failed\n"),
+ progname);
+ exit(1);
+ }
+ 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);
+
+ if (src_f->alfi_name_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)++;
+ head = (xlog_op_header_t *)*ptr;
+ xlog_print_op_header(head, *i, ptr);
+ error = xlog_print_trans_attri_value(ptr, be32_to_cpu(head->oh_len),
+ src_f->alfi_value_len);
+ }
+error:
+ free(src_f);
+
+ return error;
+} /* xlog_print_trans_attri */
+
+int
+xlog_print_trans_attri_name(
+ char **ptr,
+ uint src_len)
+{
+ struct xfs_parent_name_rec *src_f = NULL;
+ uint dst_len;
+
+ dst_len = ATTR_NVEC_SIZE(sizeof(struct xfs_parent_name_rec));
+ if (dst_len != src_len) {
+ fprintf(stderr, _("%s: bad size of attri name format: %u; expected %u\n"),
+ progname, src_len, dst_len);
+ return 1;
+ }
+
+ /*
+ * memmove to ensure 8-byte alignment for the long longs in
+ * xfs_parent_name_rec structure
+ */
+ if ((src_f = (struct xfs_parent_name_rec *)malloc(src_len)) == NULL) {
+ fprintf(stderr, _("%s: xlog_print_trans_attri_name: malloc failed\n"), progname);
+ exit(1);
+ }
+ memmove((char*)src_f, *ptr, src_len);
+ *ptr += src_len;
+
+ printf(_("ATTRI: #p_ino: %llu p_gen: %u, p_diroffset: %u\n"),
+ be64_to_cpu(src_f->p_ino), be32_to_cpu(src_f->p_gen),
+ be32_to_cpu(src_f->p_diroffset));
+
+ free(src_f);
+ return 0;
+} /* xlog_print_trans_attri */
+
+int
+xlog_print_trans_attri_value(
+ char **ptr,
+ uint src_len,
+ int value_len)
+{
+ char *f = NULL;
+
+ if ((f = (char *)malloc(src_len)) == NULL) {
+ fprintf(stderr, _("%s: xlog_print_trans_attri: malloc failed\n"), progname);
+ exit(1);
+ }
+
+ memcpy(f, *ptr, value_len);
+ printf(_("ATTRI: value: %.*s\n"), value_len, f);
+ *ptr += src_len;
+
+ free(f);
+ return 0;
+} /* xlog_print_trans_attri_value */
+
+void
+xlog_recover_print_attri(
+ xlog_recover_item_t *item)
+{
+ struct xfs_attri_log_format *f, *src_f = NULL;
+ uint src_len, dst_len;
+
+ struct xfs_parent_name_rec *rec, *src_rec = NULL;
+ char *value, *src_value = NULL;
+
+ int region = 0;
+
+ src_f = (struct xfs_attri_log_format *)item->ri_buf[0].i_addr;
+ src_len = item->ri_buf[region].i_len;
+
+ /*
+ * An xfs_attri_log_format structure contains a attribute name and
+ * variable length value as the last field.
+ */
+ dst_len = sizeof(struct xfs_attri_log_format);
+
+ if ((f = ((struct xfs_attri_log_format *)malloc(dst_len))) == NULL) {
+ fprintf(stderr, _("%s: xlog_recover_print_attri: malloc failed\n"),
+ progname);
+ exit(1);
+ }
+ 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);
+
+ if (f->alfi_name_len > 0) {
+ region++;
+ src_rec = (struct xfs_parent_name_rec *)item->ri_buf[region].i_addr;
+ src_len = item->ri_buf[region].i_len;
+
+ dst_len = ATTR_NVEC_SIZE(sizeof(struct xfs_parent_name_rec));
+
+ if ((rec = ((struct xfs_parent_name_rec *)malloc(dst_len))) == NULL) {
+ fprintf(stderr, _("%s: xlog_recover_print_attri: malloc failed\n"),
+ progname);
+ exit(1);
+ }
+ if (xfs_attri_copy_name_format((char *)src_rec, src_len, rec)) {
+ goto out;
+ }
+
+ printf(_("ATTRI: #inode: %llu gen: %u, offset: %u\n"),
+ be64_to_cpu(rec->p_ino), be32_to_cpu(rec->p_gen), be32_to_cpu(rec->p_diroffset));
+
+ free(rec);
+ }
+
+ if (f->alfi_value_len > 0) {
+ region++;
+ src_value = (char *)item->ri_buf[region].i_addr;
+
+ if ((value = ((char *)malloc(f->alfi_value_len))) == NULL) {
+ fprintf(stderr, _("%s: xlog_recover_print_attri: malloc failed\n"),
+ progname);
+ exit(1);
+ }
+
+ memcpy((char *)value, (char *)src_value, f->alfi_value_len);
+ printf("ATTRI: value: %.*s\n", f->alfi_value_len, value);
+
+ free(value);
+ }
+
+out:
+ free(f);
+
+}
+
+int
+xlog_print_trans_attrd(char **ptr, uint len)
+{
+ struct xfs_attrd_log_format *f;
+ struct xfs_attrd_log_format lbuf;
+ uint core_size = sizeof(struct xfs_attrd_log_format);
+
+ memcpy(&lbuf, *ptr, MIN(core_size, len));
+ f = &lbuf;
+ *ptr += len;
+ if (len >= core_size) {
+ printf(_("ATTRD: #regs: %d id: 0x%llx\n"),
+ f->alfd_size,
+ (unsigned long long)f->alfd_alf_id);
+ return 0;
+ } else {
+ printf(_("ATTRD: Not enough data to decode further\n"));
+ return 1;
+ }
+} /* xlog_print_trans_attrd */
+
+void
+xlog_recover_print_attrd(
+ xlog_recover_item_t *item)
+{
+ struct xfs_attrd_log_format *f;
+
+ f = (struct xfs_attrd_log_format *)item->ri_buf[0].i_addr;
+
+ printf(_(" ATTRD: #regs: %d id: 0x%llx\n"),
+ f->alfd_size,
+ (unsigned long long)f->alfd_alf_id);
+}
diff --git a/logprint/logprint.h b/logprint/logprint.h
index 98ac0d4..a5d5396 100644
--- a/logprint/logprint.h
+++ b/logprint/logprint.h
@@ -52,4 +52,10 @@ extern void xlog_recover_print_bui(struct xlog_recover_item *item);
extern int xlog_print_trans_bud(char **ptr, uint len);
extern void xlog_recover_print_bud(struct xlog_recover_item *item);
+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);
+extern int xlog_print_trans_attri_value(char **ptr, uint src_len, int value_len);
+extern void xlog_recover_print_attri(xlog_recover_item_t *item);
+extern int xlog_print_trans_attrd(char **ptr, uint len);
+extern void xlog_recover_print_attrd(xlog_recover_item_t *item);
#endif /* LOGPRINT_H */
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 26/30] xfsprogs: Add xfs_verify_pptr
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (24 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 25/30] xfsprogs: Add log item printing for ATTRI and ATTRD Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 27/30] xfsprogs: Add parent pointers to recreated inodes Allison Henderson
` (3 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
Attribute names of parent pointers are not strings. So we
need to modify attr_namecheck to verify parent pointer
records when the XFS_ATTR_PARENT flag is set.
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
repair/attr_repair.c | 21 +++++++++++----------
repair/da_util.c | 43 +++++++++++++++++++++++++++++++++++++++++++
repair/da_util.h | 12 ++++++++++++
3 files changed, 66 insertions(+), 10 deletions(-)
diff --git a/repair/attr_repair.c b/repair/attr_repair.c
index 1d04500..df27fa4 100644
--- a/repair/attr_repair.c
+++ b/repair/attr_repair.c
@@ -292,13 +292,14 @@ process_shortform_attr(
}
}
- /* namecheck checks for / and null terminated for file names.
- * attributes names currently follow the same rules.
- */
- if (namecheck((char *)¤tentry->nameval[0],
- currententry->namelen)) {
+ /* namecheck checks for / and null terminated for file names,
+ * or verifies parent pointer record in the case of a parent
+ * pointer attribute.
+ */
+ if (attr_namecheck(mp, (char *)¤tentry->nameval[0],
+ currententry->namelen, currententry->flags)) {
do_warn(
- _("entry contains illegal character in shortform attribute name\n"));
+ _("entry contains illegal shortform attribute name\n"));
junkit = 1;
}
@@ -458,8 +459,8 @@ process_leaf_attr_local(
xfs_attr_leaf_name_local_t *local;
local = xfs_attr3_leaf_name_local(leaf, i);
- if (local->namelen == 0 || namecheck((char *)&local->nameval[0],
- local->namelen)) {
+ if (attr_namecheck(mp, (char *)&local->nameval[0],
+ local->namelen, entry->flags)) {
do_warn(
_("attribute entry %d in attr block %u, inode %" PRIu64 " has bad name (namelen = %d)\n"),
i, da_bno, ino, local->namelen);
@@ -513,8 +514,8 @@ process_leaf_attr_remote(
remotep = xfs_attr3_leaf_name_remote(leaf, i);
- if (remotep->namelen == 0 || namecheck((char *)&remotep->name[0],
- remotep->namelen) ||
+ if (attr_namecheck(mp, (char *)&remotep->name[0],
+ remotep->namelen, entry->flags) ||
be32_to_cpu(entry->hashval) !=
libxfs_da_hashname((unsigned char *)&remotep->name[0],
remotep->namelen) ||
diff --git a/repair/da_util.c b/repair/da_util.c
index 1450767..d94a31c 100644
--- a/repair/da_util.c
+++ b/repair/da_util.c
@@ -13,6 +13,49 @@
#include "da_util.h"
/*
+ * Verify parent pointer attribute is valid.
+ * Return 0 on success or 1 on failure
+ */
+int
+xfs_verify_pptr(struct xfs_mount *mp, struct xfs_parent_name_rec *rec)
+{
+ xfs_ino_t p_ino = (xfs_ino_t)be64_to_cpu(rec->p_ino);
+ xfs_dir2_dataptr_t p_diroffset =
+ (xfs_dir2_dataptr_t)be32_to_cpu(rec->p_diroffset);
+
+ if (!xfs_verify_ino(mp, p_ino))
+ return 1;
+
+ if (p_diroffset > XFS_DIR2_MAX_DATAPTR)
+ return 1;
+
+ return 0;
+}
+
+/*
+ * Check if an attribute name is valid
+ * Returns 0 on success and 1 on failure
+ */
+int
+attr_namecheck(struct xfs_mount *mp, char *name, int length, int flags)
+{
+ if (flags & XFS_ATTR_PARENT) {
+ if (length != sizeof(struct xfs_parent_name_rec))
+ return 1;
+ return xfs_verify_pptr(mp, (struct xfs_parent_name_rec *)name);
+ }
+
+ if (length == 0)
+ return 1;
+
+ /*
+ * namecheck checks for / and null terminated for file names.
+ * attributes names currently follow the same rules.
+ */
+ return namecheck(name, length);
+}
+
+/*
* takes a name and length (name need not be null-terminated)
* and returns 1 if the name contains a '/' or a \0, returns 0
* otherwise
diff --git a/repair/da_util.h b/repair/da_util.h
index d36dfd0..53ba843 100644
--- a/repair/da_util.h
+++ b/repair/da_util.h
@@ -25,6 +25,18 @@ typedef struct da_bt_cursor {
} da_bt_cursor_t;
int
+xfs_verify_pptr(
+ struct xfs_mount *mp,
+ struct xfs_parent_name_rec *rec);
+
+int
+attr_namecheck(
+ struct xfs_mount *mp,
+ char *name,
+ int length,
+ int flags);
+
+int
namecheck(
char *name,
int length);
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 27/30] xfsprogs: Add parent pointers to recreated inodes
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (25 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 26/30] xfsprogs: Add xfs_verify_pptr Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 28/30] xfsprogs: Add parent pointers during protofile creation Allison Henderson
` (2 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
Inodes that are not recovered from the orphanage will
be recreated, so we will need to re-add the parent pointers
here too.
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
libxfs/libxfs_api_defs.h | 1 +
repair/phase6.c | 36 ++++++++++++++++++++++++------------
2 files changed, 25 insertions(+), 12 deletions(-)
diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
index ad5d65d..d3a581c 100644
--- a/libxfs/libxfs_api_defs.h
+++ b/libxfs/libxfs_api_defs.h
@@ -149,5 +149,6 @@
#define xfs_dir_get_ops libxfs_dir_get_ops
#define xfs_default_ifork_ops libxfs_default_ifork_ops
#define xfs_fs_geometry libxfs_fs_geometry
+#define xfs_parent_add libxfs_parent_add
#endif /* __LIBXFS_API_DEFS_H__ */
diff --git a/repair/phase6.c b/repair/phase6.c
index c4651bc..48a6cee 100644
--- a/repair/phase6.c
+++ b/repair/phase6.c
@@ -17,6 +17,7 @@
#include "dinode.h"
#include "progress.h"
#include "versions.h"
+#include "xfs_parent.h"
static struct cred zerocr;
static struct fsxattr zerofsx;
@@ -919,17 +920,18 @@ mk_root_dir(xfs_mount_t *mp)
static xfs_ino_t
mk_orphanage(xfs_mount_t *mp)
{
- xfs_ino_t ino;
- xfs_trans_t *tp;
- xfs_inode_t *ip;
- xfs_inode_t *pip;
- ino_tree_node_t *irec;
- int ino_offset = 0;
- int i;
- int error;
- const int mode = 0755;
- int nres;
- struct xfs_name xname;
+ xfs_ino_t ino;
+ struct xfs_trans *tp;
+ struct xfs_inode *ip;
+ struct xfs_inode *pip;
+ struct ino_tree_node *irec;
+ int ino_offset = 0;
+ int i;
+ int error;
+ const int mode = 0755;
+ int nres;
+ struct xfs_name xname;
+ xfs_dir2_dataptr_t offset;
/*
* check for an existing lost+found first, if it exists, return
@@ -1014,7 +1016,7 @@ mk_orphanage(xfs_mount_t *mp)
/*
* create the actual entry
*/
- error = -libxfs_dir_createname(tp, pip, &xname, ip->i_ino, nres, NULL);
+ error = -libxfs_dir_createname(tp, pip, &xname, ip->i_ino, nres, &offset);
if (error)
do_error(
_("can't make %s, createname error %d\n"),
@@ -1034,6 +1036,16 @@ mk_orphanage(xfs_mount_t *mp)
libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE);
libxfs_dir_init(tp, ip, pip);
libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+
+ if (xfs_sb_version_hasparent(&mp->m_sb)) {
+ error = -libxfs_parent_add(pip, ip, &xname, offset);
+ if (error)
+ do_error(_("Error creating parent pointer: %d\n"),
+ error);
+ libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE);
+ libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+ }
+
libxfs_trans_commit(tp);
IRELE(ip);
IRELE(pip);
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 28/30] xfsprogs: Add parent pointers during protofile creation
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (26 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 27/30] xfsprogs: Add parent pointers to recreated inodes Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 29/30] xfsprogs: implement the upper half of parent pointers Allison Henderson
2018-09-26 10:23 ` [PATCH v3 30/30] xfsprogs: Add i, n and f flags to parent command Allison Henderson
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
Inodes created from protofile parsing will also need to
add the appropriate parent pointers
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
mkfs/proto.c | 41 +++++++++++++++++++++++++----------------
1 file changed, 25 insertions(+), 16 deletions(-)
diff --git a/mkfs/proto.c b/mkfs/proto.c
index a0b2003..0d8c229 100644
--- a/mkfs/proto.c
+++ b/mkfs/proto.c
@@ -7,6 +7,7 @@
#include "libxfs.h"
#include <sys/stat.h>
#include "xfs_multidisk.h"
+#include "xfs_parent.h"
/*
* Prototypes for internal functions.
@@ -303,18 +304,19 @@ newregfile(
static void
newdirent(
- xfs_mount_t *mp,
- xfs_trans_t *tp,
- xfs_inode_t *pip,
- struct xfs_name *name,
- xfs_ino_t inum)
+ struct xfs_mount *mp,
+ struct xfs_trans *tp,
+ struct xfs_inode *pip,
+ struct xfs_name *name,
+ xfs_ino_t inum,
+ xfs_dir2_dataptr_t *offset)
{
- int error;
- int rsv;
+ int error;
+ int rsv;
rsv = XFS_DIRENTER_SPACE_RES(mp, name->len);
- error = -libxfs_dir_createname(tp, pip, name, inum, rsv, NULL);
+ error = -libxfs_dir_createname(tp, pip, name, inum, rsv, offset);
if (error)
fail(_("directory createname error"), error);
}
@@ -351,7 +353,6 @@ parseproto(
char *buf;
int error;
- xfs_fsblock_t first;
int flags;
int fmt;
int i;
@@ -368,6 +369,7 @@ parseproto(
cred_t creds;
char *value;
struct xfs_name xname;
+ xfs_dir2_dataptr_t offset;
memset(&creds, 0, sizeof(creds));
mstr = getstr(pp);
@@ -450,7 +452,7 @@ parseproto(
free(buf);
libxfs_trans_ijoin(tp, pip, 0);
xname.type = XFS_DIR3_FT_REG_FILE;
- newdirent(mp, tp, pip, &xname, ip->i_ino);
+ newdirent(mp, tp, pip, &xname, ip->i_ino, &offset);
break;
case IF_RESERVED: /* pre-allocated space only */
@@ -473,7 +475,7 @@ parseproto(
libxfs_trans_ijoin(tp, pip, 0);
xname.type = XFS_DIR3_FT_REG_FILE;
- newdirent(mp, tp, pip, &xname, ip->i_ino);
+ newdirent(mp, tp, pip, &xname, ip->i_ino, &offset);
libxfs_trans_log_inode(tp, ip, flags);
libxfs_trans_commit(tp);
rsvfile(mp, ip, llen);
@@ -491,7 +493,7 @@ parseproto(
}
libxfs_trans_ijoin(tp, pip, 0);
xname.type = XFS_DIR3_FT_BLKDEV;
- newdirent(mp, tp, pip, &xname, ip->i_ino);
+ newdirent(mp, tp, pip, &xname, ip->i_ino, &offset);
flags |= XFS_ILOG_DEV;
break;
@@ -505,7 +507,7 @@ parseproto(
fail(_("Inode allocation failed"), error);
libxfs_trans_ijoin(tp, pip, 0);
xname.type = XFS_DIR3_FT_CHRDEV;
- newdirent(mp, tp, pip, &xname, ip->i_ino);
+ newdirent(mp, tp, pip, &xname, ip->i_ino, &offset);
flags |= XFS_ILOG_DEV;
break;
@@ -517,7 +519,7 @@ parseproto(
fail(_("Inode allocation failed"), error);
libxfs_trans_ijoin(tp, pip, 0);
xname.type = XFS_DIR3_FT_FIFO;
- newdirent(mp, tp, pip, &xname, ip->i_ino);
+ newdirent(mp, tp, pip, &xname, ip->i_ino, &offset);
break;
case IF_SYMLINK:
buf = getstr(pp);
@@ -530,7 +532,7 @@ parseproto(
flags |= newfile(tp, ip, 1, 1, buf, len);
libxfs_trans_ijoin(tp, pip, 0);
xname.type = XFS_DIR3_FT_SYMLINK;
- newdirent(mp, tp, pip, &xname, ip->i_ino);
+ newdirent(mp, tp, pip, &xname, ip->i_ino, &offset);
break;
case IF_DIRECTORY:
tp = getres(mp, 0);
@@ -547,7 +549,7 @@ parseproto(
} else {
libxfs_trans_ijoin(tp, pip, 0);
xname.type = XFS_DIR3_FT_DIR;
- newdirent(mp, tp, pip, &xname, ip->i_ino);
+ newdirent(mp, tp, pip, &xname, ip->i_ino, &offset);
inc_nlink(VFS_I(pip));
libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE);
}
@@ -577,6 +579,13 @@ parseproto(
}
libxfs_trans_log_inode(tp, ip, flags);
libxfs_trans_commit(tp);
+
+ if (xfs_sb_version_hasparent(&mp->m_sb)) {
+ error = xfs_parent_add(pip, ip, &xname, offset);
+ if (error)
+ fail(_("Error creating parent pointer"), error);
+ }
+
IRELE(ip);
}
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 29/30] xfsprogs: implement the upper half of parent pointers
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (27 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 28/30] xfsprogs: Add parent pointers during protofile creation Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
2018-09-26 10:23 ` [PATCH v3 30/30] xfsprogs: Add i, n and f flags to parent command Allison Henderson
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
Add ioctl definitions to libxfs, build the necessary helpers into
libfrog and libhandle to iterate parents (and parent paths), then wire
up xfs_scrub to be able to query parent pointers from userspace. The
goal of this patch is to exercise userspace, and is nowhere near a
complete solution. A basic xfs_io parent command implementation
replaces ... whatever that is that's there now.
[achender: Minor syntax adjustments to sew solution in actual support
in libxfs for working with parent ptrs]
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
include/handle.h | 2 +
include/parent.h | 18 +++
include/path.h | 19 +++
io/parent.c | 468 ++++++++++++++---------------------------------------
libfrog/paths.c | 136 ++++++++++++++++
libhandle/Makefile | 2 +-
libhandle/handle.c | 7 +-
libhandle/parent.c | 328 +++++++++++++++++++++++++++++++++++++
scrub/inodes.c | 26 +++
scrub/inodes.h | 2 +
scrub/phase5.c | 9 +-
11 files changed, 656 insertions(+), 361 deletions(-)
diff --git a/include/handle.h b/include/handle.h
index 34246f3..1f02c96 100644
--- a/include/handle.h
+++ b/include/handle.h
@@ -40,6 +40,8 @@ extern int fssetdm_by_handle (void *__hanp, size_t __hlen,
void fshandle_destroy(void);
+int handle_to_fsfd(void *hanp, char **path);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/parent.h b/include/parent.h
index 4d3ad51..fb90004 100644
--- a/include/parent.h
+++ b/include/parent.h
@@ -17,4 +17,22 @@ typedef struct parent_cursor {
__u32 opaque[4]; /* an opaque cookie */
} parent_cursor_t;
+struct path_list;
+
+typedef int (*walk_pptr_fn)(struct xfs_pptr_info *pi, struct xfs_parent_ptr *pptr,
+ void *arg);
+typedef int (*walk_ppath_fn)(const char *mntpt, struct path_list *path,
+ void *arg);
+
+#define WALK_PPTRS_ABORT 1
+int fd_walk_pptrs(int fd, walk_pptr_fn fn, void *arg);
+int handle_walk_pptrs(void *hanp, size_t hanlen, walk_pptr_fn fn, void *arg);
+
+#define WALK_PPATHS_ABORT 1
+int fd_walk_ppaths(int fd, walk_ppath_fn fn, void *arg);
+int handle_walk_ppaths(void *hanp, size_t hanlen, walk_ppath_fn fn, void *arg);
+
+int fd_to_path(int fd, char *path, size_t pathlen);
+int handle_to_path(void *hanp, size_t hlen, char *path, size_t pathlen);
+
#endif
diff --git a/include/path.h b/include/path.h
index 2d6c3c5..9b33d86 100644
--- a/include/path.h
+++ b/include/path.h
@@ -58,4 +58,23 @@ typedef struct fs_cursor {
extern void fs_cursor_initialise(char *__dir, uint __flags, fs_cursor_t *__cp);
extern fs_path_t *fs_cursor_next_entry(fs_cursor_t *__cp);
+/* Path information. */
+
+struct path_list;
+struct path_component;
+
+struct path_component *path_component_init(const char *name);
+void path_component_free(struct path_component *pc);
+int path_component_change(struct path_component *pc, void *name,
+ size_t namelen);
+
+struct path_list *path_list_init(void);
+void path_list_free(struct path_list *path);
+void path_list_add_parent_component(struct path_list *path,
+ struct path_component *pc);
+void path_list_add_component(struct path_list *path, struct path_component *pc);
+void path_list_del_component(struct path_list *path, struct path_component *pc);
+
+ssize_t path_list_to_string(struct path_list *path, char *buf, size_t buflen);
+
#endif /* __PATH_H__ */
diff --git a/io/parent.c b/io/parent.c
index 53ac659..0e94d96 100644
--- a/io/parent.c
+++ b/io/parent.c
@@ -9,363 +9,105 @@
#include "path.h"
#include "parent.h"
#include "handle.h"
-#include "jdm.h"
#include "init.h"
#include "io.h"
-#define PARENTBUF_SZ 16384
-#define BSTATBUF_SZ 16384
-
static cmdinfo_t parent_cmd;
-static int verbose_flag;
-static int err_status;
-static __u64 inodes_checked;
static char *mntpt;
-/*
- * check out a parent entry to see if the values seem valid
- */
-static void
-check_parent_entry(xfs_bstat_t *bstatp, parent_t *parent)
-{
- int sts;
- char fullpath[PATH_MAX];
- struct stat statbuf;
- char *str;
-
- sprintf(fullpath, _("%s%s"), mntpt, parent->p_name);
-
- sts = lstat(fullpath, &statbuf);
- if (sts != 0) {
- fprintf(stderr,
- _("inode-path for inode: %llu is incorrect - path \"%s\" non-existent\n"),
- (unsigned long long) bstatp->bs_ino, fullpath);
- if (verbose_flag) {
- fprintf(stderr,
- _("path \"%s\" does not stat for inode: %llu; err = %s\n"),
- fullpath,
- (unsigned long long) bstatp->bs_ino,
- strerror(errno));
- }
- err_status++;
- return;
- } else {
- if (verbose_flag > 1) {
- printf(_("path \"%s\" found\n"), fullpath);
- }
- }
-
- if (statbuf.st_ino != bstatp->bs_ino) {
- fprintf(stderr,
- _("inode-path for inode: %llu is incorrect - wrong inode#\n"),
- (unsigned long long) bstatp->bs_ino);
- if (verbose_flag) {
- fprintf(stderr,
- _("ino mismatch for path \"%s\" %llu vs %llu\n"),
- fullpath,
- (unsigned long long)statbuf.st_ino,
- (unsigned long long)bstatp->bs_ino);
- }
- err_status++;
- return;
- } else if (verbose_flag > 1) {
- printf(_("inode number match: %llu\n"),
- (unsigned long long)statbuf.st_ino);
- }
-
- /* get parent path */
- str = strrchr(fullpath, '/');
- *str = '\0';
- sts = stat(fullpath, &statbuf);
- if (sts != 0) {
- fprintf(stderr,
- _("parent path \"%s\" does not stat: %s\n"),
- fullpath,
- strerror(errno));
- err_status++;
- return;
- } else {
- if (parent->p_ino != statbuf.st_ino) {
- fprintf(stderr,
- _("inode-path for inode: %llu is incorrect - wrong parent inode#\n"),
- (unsigned long long) bstatp->bs_ino);
- if (verbose_flag) {
- fprintf(stderr,
- _("ino mismatch for path \"%s\" %llu vs %llu\n"),
- fullpath,
- (unsigned long long)parent->p_ino,
- (unsigned long long)statbuf.st_ino);
- }
- err_status++;
- return;
- } else {
- if (verbose_flag > 1) {
- printf(_("parent ino match for %llu\n"),
- (unsigned long long) parent->p_ino);
- }
- }
- }
-}
-
-static void
-check_parents(parent_t *parentbuf, size_t *parentbuf_size,
- jdm_fshandle_t *fshandlep, xfs_bstat_t *statp)
-{
- int error, i;
- __u32 count;
- parent_t *entryp;
-
- do {
- error = jdm_parentpaths(fshandlep, statp, parentbuf, *parentbuf_size, &count);
-
- if (error == ERANGE) {
- *parentbuf_size *= 2;
- parentbuf = (parent_t *)realloc(parentbuf, *parentbuf_size);
- } else if (error) {
- fprintf(stderr, _("parentpaths failed for ino %llu: %s\n"),
- (unsigned long long) statp->bs_ino,
- strerror(errno));
- err_status++;
- break;
- }
- } while (error == ERANGE);
-
-
- if (count == 0) {
- /* no links for inode - something wrong here */
- fprintf(stderr, _("inode-path for inode: %llu is missing\n"),
- (unsigned long long) statp->bs_ino);
- err_status++;
- }
-
- entryp = parentbuf;
- for (i = 0; i < count; i++) {
- check_parent_entry(statp, entryp);
- entryp = (parent_t*) (((char*)entryp) + entryp->p_reclen);
- }
-}
-
static int
-do_bulkstat(parent_t *parentbuf, size_t *parentbuf_size, xfs_bstat_t *bstatbuf,
- int fsfd, jdm_fshandle_t *fshandlep)
+pptr_print(
+ struct xfs_pptr_info *pi,
+ struct xfs_parent_ptr *pptr,
+ void *arg)
{
- __s32 buflenout;
- __u64 lastino = 0;
- xfs_bstat_t *p;
- xfs_bstat_t *endp;
- xfs_fsop_bulkreq_t bulkreq;
- struct stat mntstat;
+ char buf[XFS_PPTR_MAXNAMELEN + 1];
- if (stat(mntpt, &mntstat)) {
- fprintf(stderr, _("can't stat mount point \"%s\": %s\n"),
- mntpt, strerror(errno));
- return 1;
+ if (pi->pi_flags & XFS_PPTR_OFLAG_ROOT) {
+ printf(_("Root directory.\n"));
+ return 0;
}
- bulkreq.lastip = &lastino;
- bulkreq.icount = BSTATBUF_SZ;
- bulkreq.ubuffer = (void *)bstatbuf;
- bulkreq.ocount = &buflenout;
-
- while (xfsctl(mntpt, fsfd, XFS_IOC_FSBULKSTAT, &bulkreq) == 0) {
- if (*(bulkreq.ocount) == 0) {
- return 0;
- }
- for (p = bstatbuf, endp = bstatbuf + *bulkreq.ocount; p < endp; p++) {
-
- /* inode being modified, get synced data with iget */
- if ( (!p->bs_nlink || !p->bs_mode) && p->bs_ino != 0 ) {
-
- if (xfsctl(mntpt, fsfd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq) < 0) {
- fprintf(stderr,
- _("failed to get bulkstat information for inode %llu\n"),
- (unsigned long long) p->bs_ino);
- continue;
- }
- if (!p->bs_nlink || !p->bs_mode || !p->bs_ino) {
- fprintf(stderr,
- _("failed to get valid bulkstat information for inode %llu\n"),
- (unsigned long long) p->bs_ino);
- continue;
- }
- }
-
- /* skip root */
- if (p->bs_ino == mntstat.st_ino) {
- continue;
- }
-
- if (verbose_flag > 1) {
- printf(_("checking inode %llu\n"),
- (unsigned long long) p->bs_ino);
- }
-
- /* print dotted progress */
- if ((inodes_checked % 100) == 0 && verbose_flag == 1) {
- printf("."); fflush(stdout);
- }
- inodes_checked++;
-
- check_parents(parentbuf, parentbuf_size, fshandlep, p);
- }
-
- }/*while*/
-
- fprintf(stderr, _("syssgi bulkstat failed: %s\n"), strerror(errno));
- return 1;
+ memcpy(buf, pptr->xpp_name, pptr->xpp_namelen);
+ buf[pptr->xpp_namelen] = 0;
+ printf(_("p_ino = %llu\n"), (unsigned long long)pptr->xpp_ino);
+ printf(_("p_gen = %u\n"), (unsigned int)pptr->xpp_gen);
+ printf(_("p_reclen = %u\n"), (unsigned int)pptr->xpp_namelen);
+ printf(_("p_name = \"%s\"\n\n"), buf);
+ return 0;
}
-static int
-parent_check(void)
+int
+print_parents(
+ struct xfs_handle *handle)
{
- int fsfd;
- jdm_fshandle_t *fshandlep;
- parent_t *parentbuf;
- size_t parentbuf_size = PARENTBUF_SZ;
- xfs_bstat_t *bstatbuf;
-
- err_status = 0;
- inodes_checked = 0;
-
- sync();
-
- fsfd = file->fd;
-
- fshandlep = jdm_getfshandle(mntpt);
- if (fshandlep == NULL) {
- fprintf(stderr, _("unable to open \"%s\" for jdm: %s\n"),
- mntpt,
- strerror(errno));
- return 1;
- }
-
- /* allocate buffers */
- bstatbuf = (xfs_bstat_t *)calloc(BSTATBUF_SZ, sizeof(xfs_bstat_t));
- parentbuf = (parent_t *)malloc(parentbuf_size);
- if (!bstatbuf || !parentbuf) {
- fprintf(stderr, _("unable to allocate buffers: %s\n"),
- strerror(errno));
- err_status = 1;
- goto out;
- }
+ int ret;
- if (do_bulkstat(parentbuf, &parentbuf_size, bstatbuf, fsfd, fshandlep) != 0)
- err_status++;
-
- if (err_status > 0)
- fprintf(stderr, _("num errors: %d\n"), err_status);
+ if (handle)
+ ret = handle_walk_pptrs(handle, sizeof(*handle), pptr_print,
+ NULL);
else
- printf(_("succeeded checking %llu inodes\n"),
- (unsigned long long) inodes_checked);
-
-out:
- free(bstatbuf);
- free(parentbuf);
- free(fshandlep);
- return err_status;
-}
+ ret = fd_walk_pptrs(file->fd, pptr_print, NULL);
+ if (ret)
+ perror(file->name);
-static void
-print_parent_entry(parent_t *parent, int fullpath)
-{
- printf(_("p_ino = %llu\n"), (unsigned long long) parent->p_ino);
- printf(_("p_gen = %u\n"), parent->p_gen);
- printf(_("p_reclen = %u\n"), parent->p_reclen);
- if (fullpath)
- printf(_("p_name = \"%s%s\"\n"), mntpt, parent->p_name);
- else
- printf(_("p_name = \"%s\"\n"), parent->p_name);
+ return 0;
}
static int
-parent_list(int fullpath)
-{
- void *handlep = NULL;
- size_t handlen;
- int error, i;
- int retval = 1;
- __u32 count;
- parent_t *entryp;
- parent_t *parentbuf = NULL;
- char *path = file->name;
- int pb_size = PARENTBUF_SZ;
-
- /* XXXX for linux libhandle version - to set libhandle fsfd cache */
- {
- void *fshandle;
- size_t fshlen;
-
- if (path_to_fshandle(mntpt, &fshandle, &fshlen) != 0) {
- fprintf(stderr, _("%s: failed path_to_fshandle \"%s\": %s\n"),
- progname, path, strerror(errno));
- goto error;
- }
- free_handle(fshandle, fshlen);
- }
-
- if (path_to_handle(path, &handlep, &handlen) != 0) {
- fprintf(stderr, _("%s: path_to_handle failed for \"%s\"\n"), progname, path);
- goto error;
- }
-
- do {
- parentbuf = (parent_t *)realloc(parentbuf, pb_size);
- if (!parentbuf) {
- fprintf(stderr, _("%s: unable to allocate parent buffer: %s\n"),
- progname, strerror(errno));
- goto error;
- }
+path_print(
+ const char *mntpt,
+ struct path_list *path,
+ void *arg) {
- if (fullpath) {
- error = parentpaths_by_handle(handlep,
- handlen,
- parentbuf,
- pb_size,
- &count);
- } else {
- error = parents_by_handle(handlep,
- handlen,
- parentbuf,
- pb_size,
- &count);
- }
- if (error == ERANGE) {
- pb_size *= 2;
- } else if (error) {
- fprintf(stderr, _("%s: %s call failed for \"%s\": %s\n"),
- progname, fullpath ? "parentpaths" : "parents",
- path, strerror(errno));
- goto error;
- }
- } while (error == ERANGE);
+ char buf[PATH_MAX];
+ size_t len = PATH_MAX;
+ int ret;
- if (count == 0) {
- /* no links for inode - something wrong here */
- fprintf(stderr, _("%s: inode-path is missing\n"), progname);
- goto error;
+ ret = snprintf(buf, len, "%s", mntpt);
+ if (ret != strlen(mntpt)) {
+ errno = ENOMEM;
+ return -1;
}
- entryp = parentbuf;
- for (i = 0; i < count; i++) {
- print_parent_entry(entryp, fullpath);
- entryp = (parent_t*) (((char*)entryp) + entryp->p_reclen);
- }
+ ret = path_list_to_string(path, buf + ret, len - ret);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
- retval = 0;
-error:
- free(handlep);
- free(parentbuf);
- return retval;
+int
+print_paths(
+ struct xfs_handle *handle)
+{
+ int ret;
+
+ if (handle)
+ ret = handle_walk_ppaths(handle, sizeof(*handle), path_print,
+ NULL);
+ else
+ ret = fd_walk_ppaths(file->fd, path_print, NULL);
+ if (ret)
+ perror(file->name);
+ return 0;
}
int
-parent_f(int argc, char **argv)
+parent_f(
+ int argc,
+ char **argv)
{
- int c;
- int listpath_flag = 0;
- int check_flag = 0;
- fs_path_t *fs;
- static int tab_init;
+ struct xfs_handle handle;
+ void *hanp = NULL;
+ size_t hlen;
+ struct fs_path *fs;
+ char *p;
+ uint64_t ino = 0;
+ uint32_t gen = 0;
+ int c;
+ int listpath_flag = 0;
+ int ret;
+ static int tab_init;
if (!tab_init) {
tab_init = 1;
@@ -379,46 +121,72 @@ parent_f(int argc, char **argv)
}
mntpt = fs->fs_dir;
- verbose_flag = 0;
-
- while ((c = getopt(argc, argv, "cpv")) != EOF) {
+ while ((c = getopt(argc, argv, "p")) != EOF) {
switch (c) {
- case 'c':
- check_flag = 1;
- break;
case 'p':
listpath_flag = 1;
break;
- case 'v':
- verbose_flag++;
- break;
default:
return command_usage(&parent_cmd);
}
}
- if (!check_flag && !listpath_flag) /* default case */
- exitcode = parent_list(listpath_flag);
- else {
- if (listpath_flag)
- exitcode = parent_list(listpath_flag);
- if (check_flag)
- exitcode = parent_check();
+ /*
+ * Always initialize the fshandle table because we need it for
+ * the ppaths functions to work.
+ */
+ ret = path_to_fshandle((char *)mntpt, &hanp, &hlen);
+ if (ret) {
+ perror(mntpt);
+ return 0;
+ }
+
+ if (optind + 2 == argc) {
+ ino = strtoull(argv[optind], &p, 0);
+ if (*p != '\0' || ino == 0) {
+ fprintf(stderr,
+ _("Bad inode number '%s'.\n"),
+ argv[optind]);
+ return 0;
+ }
+ gen = strtoul(argv[optind + 1], &p, 0);
+ if (*p != '\0') {
+ fprintf(stderr,
+ _("Bad generation number '%s'.\n"),
+ argv[optind + 1]);
+ return 0;
+ }
+
+ memcpy(&handle, hanp, sizeof(handle));
+ handle.ha_fid.fid_len = sizeof(xfs_fid_t) -
+ sizeof(handle.ha_fid.fid_len);
+ handle.ha_fid.fid_pad = 0;
+ handle.ha_fid.fid_ino = ino;
+ handle.ha_fid.fid_gen = gen;
+
}
+ if (listpath_flag)
+ exitcode = print_paths(ino ? &handle : NULL);
+ else
+ exitcode = print_parents(ino ? &handle : NULL);
+
+ if (hanp)
+ free_handle(hanp, hlen);
+
return 0;
}
static void
parent_help(void)
{
- printf(_(
+printf(_(
"\n"
" list the current file's parents and their filenames\n"
"\n"
-" -c -- check the current file's file system for parent consistency\n"
-" -p -- list the current file's parents and their full paths\n"
-" -v -- verbose mode\n"
+" -p -- list the current file's paths up to the root\n"
+"\n"
+"If ino and gen are supplied, use them instead.\n"
"\n"));
}
@@ -429,9 +197,9 @@ parent_init(void)
parent_cmd.cfunc = parent_f;
parent_cmd.argmin = 0;
parent_cmd.argmax = -1;
- parent_cmd.args = _("[-cpv]");
+ parent_cmd.args = _("[-p] [ino gen]");
parent_cmd.flags = CMD_NOMAP_OK;
- parent_cmd.oneline = _("print or check parent inodes");
+ parent_cmd.oneline = _("print parent inodes");
parent_cmd.help = parent_help;
if (expert)
diff --git a/libfrog/paths.c b/libfrog/paths.c
index 2379ea4..16bcb0b 100644
--- a/libfrog/paths.c
+++ b/libfrog/paths.c
@@ -15,6 +15,7 @@
#include "path.h"
#include "input.h"
#include "project.h"
+#include "list.h"
#include <limits.h>
extern char *progname;
@@ -620,3 +621,138 @@ fs_table_insert_project_path(
exit(1);
}
}
+
+
+/* Structured path components. */
+
+struct path_list {
+ struct list_head p_head;
+};
+
+struct path_component {
+ struct list_head pc_list;
+ char *pc_fname;
+};
+
+/* Initialize a path component with a given name. */
+struct path_component *
+path_component_init(
+ const char *name)
+{
+ struct path_component *pc;
+
+ pc = malloc(sizeof(struct path_component));
+ if (!pc)
+ return NULL;
+ INIT_LIST_HEAD(&pc->pc_list);
+ pc->pc_fname = strdup(name);
+ if (!pc->pc_fname) {
+ free(pc);
+ return NULL;
+ }
+ return pc;
+}
+
+/* Free a path component. */
+void
+path_component_free(
+ struct path_component *pc)
+{
+ free(pc->pc_fname);
+ free(pc);
+}
+
+/* Change a path component's filename. */
+int
+path_component_change(
+ struct path_component *pc,
+ void *name,
+ size_t namelen)
+{
+ void *p;
+
+ p = realloc(pc->pc_fname, namelen + 1);
+ if (!p)
+ return -1;
+ pc->pc_fname = p;
+ memcpy(pc->pc_fname, name, namelen);
+ pc->pc_fname[namelen] = 0;
+ return 0;
+}
+
+/* Initialize a pathname. */
+struct path_list *
+path_list_init(void)
+{
+ struct path_list *path;
+
+ path = malloc(sizeof(struct path_list));
+ if (!path)
+ return NULL;
+ INIT_LIST_HEAD(&path->p_head);
+ return path;
+}
+
+/* Empty out a pathname. */
+void
+path_list_free(
+ struct path_list *path)
+{
+ struct path_component *pos;
+ struct path_component *n;
+
+ list_for_each_entry_safe(pos, n, &path->p_head, pc_list) {
+ path_list_del_component(path, pos);
+ path_component_free(pos);
+ }
+ free(path);
+}
+
+/* Add a parent component to a pathname. */
+void
+path_list_add_parent_component(
+ struct path_list *path,
+ struct path_component *pc)
+{
+ list_add(&pc->pc_list, &path->p_head);
+}
+
+/* Add a component to a pathname. */
+void
+path_list_add_component(
+ struct path_list *path,
+ struct path_component *pc)
+{
+ list_add_tail(&pc->pc_list, &path->p_head);
+}
+
+/* Remove a component from a pathname. */
+void
+path_list_del_component(
+ struct path_list *path,
+ struct path_component *pc)
+{
+ list_del_init(&pc->pc_list);
+}
+
+/* Convert a pathname into a string. */
+ssize_t
+path_list_to_string(
+ struct path_list *path,
+ char *buf,
+ size_t buflen)
+{
+ struct path_component *pos;
+ ssize_t bytes = 0;
+ int ret;
+
+ list_for_each_entry(pos, &path->p_head, pc_list) {
+ ret = snprintf(buf, buflen, "/%s", pos->pc_fname);
+ if (ret != 1 + strlen(pos->pc_fname))
+ return -1;
+ bytes += ret;
+ buf += ret;
+ buflen -= ret;
+ }
+ return bytes;
+}
diff --git a/libhandle/Makefile b/libhandle/Makefile
index 998081b..48b6ad9 100644
--- a/libhandle/Makefile
+++ b/libhandle/Makefile
@@ -16,7 +16,7 @@ else
LTLDFLAGS += -Wl,--version-script,libhandle.sym
endif
-CFILES = handle.c jdm.c
+CFILES = handle.c jdm.c parent.c
LSRCFILES = libhandle.sym
default: ltdepend $(LTLIBRARY)
diff --git a/libhandle/handle.c b/libhandle/handle.c
index eb099f4..a9b8baf 100644
--- a/libhandle/handle.c
+++ b/libhandle/handle.c
@@ -29,7 +29,6 @@ typedef union {
} comarg_t;
static int obj_to_handle(char *, int, unsigned int, comarg_t, void**, size_t*);
-static int handle_to_fsfd(void *, char **);
static char *path_to_fspath(char *path);
@@ -202,8 +201,10 @@ handle_to_fshandle(
return 0;
}
-static int
-handle_to_fsfd(void *hanp, char **path)
+int
+handle_to_fsfd(
+ void *hanp,
+ char **path)
{
struct fdhash *fdhp;
diff --git a/libhandle/parent.c b/libhandle/parent.c
new file mode 100644
index 0000000..eee5ec1
--- /dev/null
+++ b/libhandle/parent.c
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2017 Oracle. All Rights Reserved.
+ *
+ * Author: Darrick J. Wong <darrick.wong@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include "platform_defs.h"
+#include "xfs.h"
+#include "xfs_arch.h"
+#include "list.h"
+#include "path.h"
+#include "handle.h"
+#include "parent.h"
+
+/* Allocate a buffer large enough for some parent pointer records. */
+static inline struct xfs_pptr_info *
+xfs_pptr_alloc(
+ size_t nr_ptrs)
+{
+ struct xfs_pptr_info *pi;
+
+ pi = malloc(XFS_PPTR_INFO_SIZEOF(nr_ptrs));
+ if (!pi)
+ return NULL;
+ memset(pi, 0, sizeof(struct xfs_pptr_info));
+ pi->pi_ptrs_size = nr_ptrs;
+ return pi;
+}
+
+/* Walk all parents of the given file handle. */
+static int
+handle_walk_parents(
+ int fd,
+ struct xfs_handle *handle,
+ walk_pptr_fn fn,
+ void *arg)
+{
+ struct xfs_pptr_info *pi;
+ struct xfs_parent_ptr *p;
+ unsigned int i;
+ ssize_t ret = -1;
+
+ pi = xfs_pptr_alloc(4);
+ if (!pi)
+ return -1;
+
+ if (handle) {
+ memcpy(&pi->pi_handle, handle, sizeof(struct xfs_handle));
+ pi->pi_flags = XFS_PPTR_IFLAG_HANDLE;
+ }
+
+ ret = ioctl(fd, XFS_IOC_GETPPOINTER, pi);
+ while (!ret) {
+ if (pi->pi_flags & XFS_PPTR_OFLAG_ROOT) {
+ ret = fn(pi, NULL, arg);
+ break;
+ }
+
+ for (i = 0; i < pi->pi_ptrs_used; i++) {
+ p = XFS_PPINFO_TO_PP(pi, i);
+ ret = fn(pi, p, arg);
+ if (ret)
+ goto out_pi;
+ }
+
+ if (pi->pi_flags & XFS_PPTR_OFLAG_DONE)
+ break;
+
+ ret = ioctl(fd, XFS_IOC_GETPPOINTER, pi);
+ }
+
+out_pi:
+ free(pi);
+ return ret;
+}
+
+/* Walk all parent pointers of this handle. */
+int
+handle_walk_pptrs(
+ void *hanp,
+ size_t hlen,
+ walk_pptr_fn fn,
+ void *arg)
+{
+ char *mntpt;
+ int fd;
+
+ if (hlen != sizeof(struct xfs_handle)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ fd = handle_to_fsfd(hanp, &mntpt);
+ if (fd < 0)
+ return -1;
+
+ return handle_walk_parents(fd, hanp, fn, arg);
+}
+
+/* Walk all parent pointers of this fd. */
+int
+fd_walk_pptrs(
+ int fd,
+ walk_pptr_fn fn,
+ void *arg)
+{
+ return handle_walk_parents(fd, NULL, fn, arg);
+}
+
+struct walk_ppaths_info {
+ walk_ppath_fn fn;
+ void *arg;
+ char *mntpt;
+ struct path_list *path;
+ int fd;
+};
+
+struct walk_ppath_level_info {
+ struct xfs_handle newhandle;
+ struct path_component *pc;
+ struct walk_ppaths_info *wpi;
+};
+
+static int handle_walk_parent_paths(struct walk_ppaths_info *wpi,
+ struct xfs_handle *handle);
+
+static int
+handle_walk_parent_path_ptr(
+ struct xfs_pptr_info *pi,
+ struct xfs_parent_ptr *p,
+ void *arg)
+{
+ struct walk_ppath_level_info *wpli = arg;
+ struct walk_ppaths_info *wpi = wpli->wpi;
+ unsigned int i;
+ int ret = 0;
+
+ if (pi->pi_flags & XFS_PPTR_OFLAG_ROOT)
+ return wpi->fn(wpi->mntpt, wpi->path, wpi->arg);
+
+ for (i = 0; i < pi->pi_ptrs_used; i++) {
+ p = XFS_PPINFO_TO_PP(pi, i);
+ ret = path_component_change(wpli->pc, p->xpp_name,
+ p->xpp_namelen);
+ if (ret)
+ break;
+ wpli->newhandle.ha_fid.fid_ino = p->xpp_ino;
+ wpli->newhandle.ha_fid.fid_gen = p->xpp_gen;
+ path_list_add_parent_component(wpi->path, wpli->pc);
+ ret = handle_walk_parent_paths(wpi, &wpli->newhandle);
+ path_list_del_component(wpi->path, wpli->pc);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * Recursively walk all parents of the given file handle; if we hit the
+ * fs root then we call the associated function with the constructed path.
+ */
+static int
+handle_walk_parent_paths(
+ struct walk_ppaths_info *wpi,
+ struct xfs_handle *handle)
+{
+ struct walk_ppath_level_info *wpli;
+ int ret;
+
+ wpli = malloc(sizeof(struct walk_ppath_level_info));
+ if (!wpli)
+ return -1;
+ wpli->pc = path_component_init("");
+ if (!wpli->pc) {
+ free(wpli);
+ return -1;
+ }
+ wpli->wpi = wpi;
+ memcpy(&wpli->newhandle, handle, sizeof(struct xfs_handle));
+
+ ret = handle_walk_parents(wpi->fd, handle, handle_walk_parent_path_ptr,
+ wpli);
+
+ path_component_free(wpli->pc);
+ free(wpli);
+ return ret;
+}
+
+/*
+ * Call the given function on all known paths from the vfs root to the inode
+ * described in the handle.
+ */
+int
+handle_walk_ppaths(
+ void *hanp,
+ size_t hlen,
+ walk_ppath_fn fn,
+ void *arg)
+{
+ struct walk_ppaths_info wpi;
+ ssize_t ret;
+
+ if (hlen != sizeof(struct xfs_handle)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ wpi.fd = handle_to_fsfd(hanp, &wpi.mntpt);
+ if (wpi.fd < 0)
+ return -1;
+ wpi.path = path_list_init();
+ if (!wpi.path)
+ return -1;
+ wpi.fn = fn;
+ wpi.arg = arg;
+
+ ret = handle_walk_parent_paths(&wpi, hanp);
+ path_list_free(wpi.path);
+
+ return ret;
+}
+
+/*
+ * Call the given function on all known paths from the vfs root to the inode
+ * referred to by the file description.
+ */
+int
+fd_walk_ppaths(
+ int fd,
+ walk_ppath_fn fn,
+ void *arg)
+{
+ struct walk_ppaths_info wpi;
+ void *hanp;
+ size_t hlen;
+ int fsfd;
+ int ret;
+
+ ret = fd_to_handle(fd, &hanp, &hlen);
+ if (ret)
+ return ret;
+
+ fsfd = handle_to_fsfd(hanp, &wpi.mntpt);
+ if (fsfd < 0)
+ return -1;
+ wpi.fd = fd;
+ wpi.path = path_list_init();
+ if (!wpi.path)
+ return -1;
+ wpi.fn = fn;
+ wpi.arg = arg;
+
+ ret = handle_walk_parent_paths(&wpi, hanp);
+ path_list_free(wpi.path);
+
+ return ret;
+}
+
+struct path_walk_info {
+ char *buf;
+ size_t len;
+};
+
+/* Helper that stringifies the first full path that we find. */
+static int
+handle_to_path_walk(
+ const char *mntpt,
+ struct path_list *path,
+ void *arg)
+{
+ struct path_walk_info *pwi = arg;
+ int ret;
+
+ ret = snprintf(pwi->buf, pwi->len, "%s", mntpt);
+ if (ret != strlen(mntpt)) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ ret = path_list_to_string(path, pwi->buf + ret, pwi->len - ret);
+ if (ret < 0)
+ return ret;
+
+ return WALK_PPATHS_ABORT;
+}
+
+/* Return any eligible path to this file handle. */
+int
+handle_to_path(
+ void *hanp,
+ size_t hlen,
+ char *path,
+ size_t pathlen)
+{
+ struct path_walk_info pwi;
+
+ pwi.buf = path;
+ pwi.len = pathlen;
+ return handle_walk_ppaths(hanp, hlen, handle_to_path_walk, &pwi);
+}
+
+/* Return any eligible path to this file description. */
+int
+fd_to_path(
+ int fd,
+ char *path,
+ size_t pathlen)
+{
+ struct path_walk_info pwi;
+
+ pwi.buf = path;
+ pwi.len = pathlen;
+ return fd_walk_ppaths(fd, handle_to_path_walk, &pwi);
+}
diff --git a/scrub/inodes.c b/scrub/inodes.c
index add6876..8619017 100644
--- a/scrub/inodes.c
+++ b/scrub/inodes.c
@@ -17,6 +17,7 @@
#include "xfs_scrub.h"
#include "common.h"
#include "inodes.h"
+#include "parent.h"
/*
* Iterate a range of inodes.
@@ -279,3 +280,28 @@ xfs_open_handle(
return open_by_fshandle(handle, sizeof(*handle),
O_RDONLY | O_NOATIME | O_NOFOLLOW | O_NOCTTY);
}
+
+/* Construct a description for an inode. */
+void
+xfs_scrub_ino_descr(
+ struct scrub_ctx *ctx,
+ struct xfs_handle *handle,
+ char *buf,
+ size_t buflen)
+{
+ uint64_t ino;
+ xfs_agnumber_t agno;
+ xfs_agino_t agino;
+ int ret;
+
+ ret = handle_to_path(handle, sizeof(struct xfs_handle), buf, buflen);
+ if (ret >= 0)
+ return;
+
+ ino = handle->ha_fid.fid_ino;
+ agno = ino / (1ULL << (ctx->inopblog + ctx->agblklog));
+ agino = ino % (1ULL << (ctx->inopblog + ctx->agblklog));
+ snprintf(buf, buflen, _("inode %"PRIu64" (%u/%u)"), ino, agno,
+ agino);
+}
+
diff --git a/scrub/inodes.h b/scrub/inodes.h
index 631848c..ee09d68 100644
--- a/scrub/inodes.h
+++ b/scrub/inodes.h
@@ -14,5 +14,7 @@ bool xfs_scan_all_inodes(struct scrub_ctx *ctx, xfs_inode_iter_fn fn,
void *arg);
int xfs_open_handle(struct xfs_handle *handle);
+void xfs_scrub_ino_descr(struct scrub_ctx *ctx, struct xfs_handle *handle,
+ char *buf, size_t buflen);
#endif /* XFS_SCRUB_INODES_H_ */
diff --git a/scrub/phase5.c b/scrub/phase5.c
index 6ffcec2..6295560 100644
--- a/scrub/phase5.c
+++ b/scrub/phase5.c
@@ -231,17 +231,12 @@ xfs_scrub_connections(
void *arg)
{
bool *pmoveon = arg;
- char descr[DESCR_BUFSZ];
+ char descr[PATH_MAX];
bool moveon = true;
- xfs_agnumber_t agno;
- xfs_agino_t agino;
int fd = -1;
int error;
- agno = bstat->bs_ino / (1ULL << (ctx->inopblog + ctx->agblklog));
- agino = bstat->bs_ino % (1ULL << (ctx->inopblog + ctx->agblklog));
- snprintf(descr, DESCR_BUFSZ, _("inode %"PRIu64" (%u/%u)"),
- (uint64_t)bstat->bs_ino, agno, agino);
+ xfs_scrub_ino_descr(ctx, handle, descr, PATH_MAX);
background_sleep();
/* Warn about naming problems in xattrs. */
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v3 30/30] xfsprogs: Add i, n and f flags to parent command
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
` (28 preceding siblings ...)
2018-09-26 10:23 ` [PATCH v3 29/30] xfsprogs: implement the upper half of parent pointers Allison Henderson
@ 2018-09-26 10:23 ` Allison Henderson
29 siblings, 0 replies; 31+ messages in thread
From: Allison Henderson @ 2018-09-26 10:23 UTC (permalink / raw)
To: linux-xfs
This patch adds the flags i, n, and f to the parent command.
These flags add filtering options that are used by the new
parent pointer tests in xfstests, and help to improve the test
run time. The flags are:
-i: Only show parent pointer records containing the given inode
-n: Only show parent pointer records containing the given filename
-f: Print records in short format: ino/gen/namelen/name
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
include/parent.h | 17 ++++++++----
io/parent.c | 80 ++++++++++++++++++++++++++++++++++++++++++------------
libhandle/parent.c | 73 +++++++++++++++++++++++++++++++++++--------------
3 files changed, 128 insertions(+), 42 deletions(-)
diff --git a/include/parent.h b/include/parent.h
index fb90004..2e13672 100644
--- a/include/parent.h
+++ b/include/parent.h
@@ -17,20 +17,27 @@ typedef struct parent_cursor {
__u32 opaque[4]; /* an opaque cookie */
} parent_cursor_t;
+/* Print parent pointer option flags */
+#define XFS_PPPTR_OFLAG_SHORT (1<<0) /* Print in short format */
+
struct path_list;
typedef int (*walk_pptr_fn)(struct xfs_pptr_info *pi, struct xfs_parent_ptr *pptr,
- void *arg);
+ void *arg, int flags);
typedef int (*walk_ppath_fn)(const char *mntpt, struct path_list *path,
void *arg);
#define WALK_PPTRS_ABORT 1
-int fd_walk_pptrs(int fd, walk_pptr_fn fn, void *arg);
-int handle_walk_pptrs(void *hanp, size_t hanlen, walk_pptr_fn fn, void *arg);
+int fd_walk_pptrs(int fd, uint64_t pino, char *pname, walk_pptr_fn fn,
+ void *arg, int flags);
+int handle_walk_pptrs(void *hanp, size_t hanlen, uint64_t pino, char *pname,
+ walk_pptr_fn fn, void *arg, int flags);
#define WALK_PPATHS_ABORT 1
-int fd_walk_ppaths(int fd, walk_ppath_fn fn, void *arg);
-int handle_walk_ppaths(void *hanp, size_t hanlen, walk_ppath_fn fn, void *arg);
+int fd_walk_ppaths(int fd, uint64_t pino, char *pname, walk_ppath_fn fn,
+ void *arg, int flags);
+int handle_walk_ppaths(void *hanp, size_t hanlen, uint64_t pino, char *pname,
+ walk_ppath_fn fn, void *arg, int flags);
int fd_to_path(int fd, char *path, size_t pathlen);
int handle_to_path(void *hanp, size_t hlen, char *path, size_t pathlen);
diff --git a/io/parent.c b/io/parent.c
index 0e94d96..022dcf0 100644
--- a/io/parent.c
+++ b/io/parent.c
@@ -19,7 +19,8 @@ static int
pptr_print(
struct xfs_pptr_info *pi,
struct xfs_parent_ptr *pptr,
- void *arg)
+ void *arg,
+ int flags)
{
char buf[XFS_PPTR_MAXNAMELEN + 1];
@@ -30,24 +31,38 @@ pptr_print(
memcpy(buf, pptr->xpp_name, pptr->xpp_namelen);
buf[pptr->xpp_namelen] = 0;
- printf(_("p_ino = %llu\n"), (unsigned long long)pptr->xpp_ino);
- printf(_("p_gen = %u\n"), (unsigned int)pptr->xpp_gen);
- printf(_("p_reclen = %u\n"), (unsigned int)pptr->xpp_namelen);
- printf(_("p_name = \"%s\"\n\n"), buf);
+
+ if (flags & XFS_PPPTR_OFLAG_SHORT) {
+ printf("%llu/%u/%u/%s\n",
+ (unsigned long long)pptr->xpp_ino,
+ (unsigned int)pptr->xpp_gen,
+ (unsigned int)pptr->xpp_namelen,
+ buf);
+ }
+ else {
+ printf(_("p_ino = %llu\n"), (unsigned long long)pptr->xpp_ino);
+ printf(_("p_gen = %u\n"), (unsigned int)pptr->xpp_gen);
+ printf(_("p_reclen = %u\n"), (unsigned int)pptr->xpp_namelen);
+ printf(_("p_name = \"%s\"\n\n"), buf);
+ }
return 0;
}
int
print_parents(
- struct xfs_handle *handle)
+ struct xfs_handle *handle,
+ uint64_t pino,
+ char *pname,
+ int flags)
{
int ret;
if (handle)
- ret = handle_walk_pptrs(handle, sizeof(*handle), pptr_print,
- NULL);
+ ret = handle_walk_pptrs(handle, sizeof(*handle), pino,
+ pname, pptr_print, NULL, flags);
else
- ret = fd_walk_pptrs(file->fd, pptr_print, NULL);
+ ret = fd_walk_pptrs(file->fd, pino, pname, pptr_print,
+ NULL, flags);
if (ret)
perror(file->name);
@@ -78,15 +93,19 @@ path_print(
int
print_paths(
- struct xfs_handle *handle)
+ struct xfs_handle *handle,
+ uint64_t pino,
+ char *pname,
+ int flags)
{
int ret;
if (handle)
- ret = handle_walk_ppaths(handle, sizeof(*handle), path_print,
- NULL);
+ ret = handle_walk_ppaths(handle, sizeof(*handle), pino,
+ pname, path_print, NULL, flags);
else
- ret = fd_walk_ppaths(file->fd, path_print, NULL);
+ ret = fd_walk_ppaths(file->fd, pino, pname, path_print,
+ NULL, flags);
if (ret)
perror(file->name);
return 0;
@@ -108,6 +127,9 @@ parent_f(
int listpath_flag = 0;
int ret;
static int tab_init;
+ uint64_t pino = 0;
+ char *pname = NULL;
+ int ppptr_flags = 0;
if (!tab_init) {
tab_init = 1;
@@ -121,11 +143,27 @@ parent_f(
}
mntpt = fs->fs_dir;
- while ((c = getopt(argc, argv, "p")) != EOF) {
+ while ((c = getopt(argc, argv, "pfi:n:")) != EOF) {
switch (c) {
case 'p':
listpath_flag = 1;
break;
+ case 'i':
+ pino = strtoull(optarg, &p, 0);
+ if (*p != '\0' || pino == 0) {
+ fprintf(stderr,
+ _("Bad inode number '%s'.\n"),
+ optarg);
+ return 0;
+ }
+
+ break;
+ case 'n':
+ pname = optarg;
+ break;
+ case 'f':
+ ppptr_flags |= XFS_PPPTR_OFLAG_SHORT;
+ break;
default:
return command_usage(&parent_cmd);
}
@@ -167,9 +205,11 @@ parent_f(
}
if (listpath_flag)
- exitcode = print_paths(ino ? &handle : NULL);
+ exitcode = print_paths(ino ? &handle : NULL,
+ pino, pname, ppptr_flags);
else
- exitcode = print_parents(ino ? &handle : NULL);
+ exitcode = print_parents(ino ? &handle : NULL,
+ pino, pname, ppptr_flags);
if (hanp)
free_handle(hanp, hlen);
@@ -187,6 +227,12 @@ printf(_(
" -p -- list the current file's paths up to the root\n"
"\n"
"If ino and gen are supplied, use them instead.\n"
+"\n"
+" -i -- Only show parent pointer records containing the given inode\n"
+"\n"
+" -n -- Only show parent pointer records containing the given filename\n"
+"\n"
+" -f -- Print records in short format: ino/gen/namelen/filename\n"
"\n"));
}
@@ -197,7 +243,7 @@ parent_init(void)
parent_cmd.cfunc = parent_f;
parent_cmd.argmin = 0;
parent_cmd.argmax = -1;
- parent_cmd.args = _("[-p] [ino gen]");
+ parent_cmd.args = _("[-p] [ino gen] [-i] [ino] [-n] [name] [-f]");
parent_cmd.flags = CMD_NOMAP_OK;
parent_cmd.oneline = _("print parent inodes");
parent_cmd.help = parent_help;
diff --git a/libhandle/parent.c b/libhandle/parent.c
index eee5ec1..72310d7 100644
--- a/libhandle/parent.c
+++ b/libhandle/parent.c
@@ -40,13 +40,21 @@ xfs_pptr_alloc(
return pi;
}
-/* Walk all parents of the given file handle. */
+/*
+ * Walk all parents of the given file handle.
+ * If pino is set, print only the parent pointer
+ * of that inode. If pname is set, print only the
+ * parent pointer of that filename
+ */
static int
handle_walk_parents(
int fd,
struct xfs_handle *handle,
+ uint64_t pino,
+ char *pname,
walk_pptr_fn fn,
- void *arg)
+ void *arg,
+ int flags)
{
struct xfs_pptr_info *pi;
struct xfs_parent_ptr *p;
@@ -65,13 +73,20 @@ handle_walk_parents(
ret = ioctl(fd, XFS_IOC_GETPPOINTER, pi);
while (!ret) {
if (pi->pi_flags & XFS_PPTR_OFLAG_ROOT) {
- ret = fn(pi, NULL, arg);
+ ret = fn(pi, NULL, arg, flags);
break;
}
for (i = 0; i < pi->pi_ptrs_used; i++) {
p = XFS_PPINFO_TO_PP(pi, i);
- ret = fn(pi, p, arg);
+ if ((pino != 0) && (pino != p->xpp_ino))
+ continue;
+
+ if ((pname != NULL) && (strcmp(pname,
+ (char *)p->xpp_name) != 0))
+ continue;
+
+ ret = fn(pi, p, arg, flags);
if (ret)
goto out_pi;
}
@@ -92,8 +107,11 @@ int
handle_walk_pptrs(
void *hanp,
size_t hlen,
+ uint64_t pino,
+ char *pname,
walk_pptr_fn fn,
- void *arg)
+ void *arg,
+ int flags)
{
char *mntpt;
int fd;
@@ -107,17 +125,20 @@ handle_walk_pptrs(
if (fd < 0)
return -1;
- return handle_walk_parents(fd, hanp, fn, arg);
+ return handle_walk_parents(fd, hanp, pino, pname, fn, arg, flags);
}
/* Walk all parent pointers of this fd. */
int
fd_walk_pptrs(
int fd,
+ uint64_t pino,
+ char *pname,
walk_pptr_fn fn,
- void *arg)
+ void *arg,
+ int flags)
{
- return handle_walk_parents(fd, NULL, fn, arg);
+ return handle_walk_parents(fd, NULL, pino, pname, fn, arg, flags);
}
struct walk_ppaths_info {
@@ -135,13 +156,15 @@ struct walk_ppath_level_info {
};
static int handle_walk_parent_paths(struct walk_ppaths_info *wpi,
- struct xfs_handle *handle);
+ struct xfs_handle *handle, uint64_t pino, char *pname,
+ int flags);
static int
handle_walk_parent_path_ptr(
struct xfs_pptr_info *pi,
struct xfs_parent_ptr *p,
- void *arg)
+ void *arg,
+ int flags)
{
struct walk_ppath_level_info *wpli = arg;
struct walk_ppaths_info *wpi = wpli->wpi;
@@ -160,7 +183,7 @@ handle_walk_parent_path_ptr(
wpli->newhandle.ha_fid.fid_ino = p->xpp_ino;
wpli->newhandle.ha_fid.fid_gen = p->xpp_gen;
path_list_add_parent_component(wpi->path, wpli->pc);
- ret = handle_walk_parent_paths(wpi, &wpli->newhandle);
+ ret = handle_walk_parent_paths(wpi, &wpli->newhandle, 0, NULL, 0);
path_list_del_component(wpi->path, wpli->pc);
if (ret)
break;
@@ -176,7 +199,10 @@ handle_walk_parent_path_ptr(
static int
handle_walk_parent_paths(
struct walk_ppaths_info *wpi,
- struct xfs_handle *handle)
+ struct xfs_handle *handle,
+ uint64_t pino,
+ char *pname,
+ int flags)
{
struct walk_ppath_level_info *wpli;
int ret;
@@ -192,8 +218,8 @@ handle_walk_parent_paths(
wpli->wpi = wpi;
memcpy(&wpli->newhandle, handle, sizeof(struct xfs_handle));
- ret = handle_walk_parents(wpi->fd, handle, handle_walk_parent_path_ptr,
- wpli);
+ ret = handle_walk_parents(wpi->fd, handle, pino, pname,
+ handle_walk_parent_path_ptr, wpli, flags);
path_component_free(wpli->pc);
free(wpli);
@@ -208,8 +234,11 @@ int
handle_walk_ppaths(
void *hanp,
size_t hlen,
+ uint64_t pino,
+ char *pname,
walk_ppath_fn fn,
- void *arg)
+ void *arg,
+ int flags)
{
struct walk_ppaths_info wpi;
ssize_t ret;
@@ -228,7 +257,7 @@ handle_walk_ppaths(
wpi.fn = fn;
wpi.arg = arg;
- ret = handle_walk_parent_paths(&wpi, hanp);
+ ret = handle_walk_parent_paths(&wpi, hanp, pino, pname, flags);
path_list_free(wpi.path);
return ret;
@@ -241,8 +270,11 @@ handle_walk_ppaths(
int
fd_walk_ppaths(
int fd,
+ uint64_t pino,
+ char *pname,
walk_ppath_fn fn,
- void *arg)
+ void *arg,
+ int flags)
{
struct walk_ppaths_info wpi;
void *hanp;
@@ -264,7 +296,7 @@ fd_walk_ppaths(
wpi.fn = fn;
wpi.arg = arg;
- ret = handle_walk_parent_paths(&wpi, hanp);
+ ret = handle_walk_parent_paths(&wpi, hanp, pino, pname, flags);
path_list_free(wpi.path);
return ret;
@@ -310,7 +342,8 @@ handle_to_path(
pwi.buf = path;
pwi.len = pathlen;
- return handle_walk_ppaths(hanp, hlen, handle_to_path_walk, &pwi);
+ return handle_walk_ppaths(hanp, hlen, 0, NULL, handle_to_path_walk,
+ &pwi, 0);
}
/* Return any eligible path to this file description. */
@@ -324,5 +357,5 @@ fd_to_path(
pwi.buf = path;
pwi.len = pathlen;
- return fd_walk_ppaths(fd, handle_to_path_walk, &pwi);
+ return fd_walk_ppaths(fd, 0, NULL, handle_to_path_walk, &pwi, 0);
}
--
2.7.4
^ permalink raw reply related [flat|nested] 31+ messages in thread
end of thread, other threads:[~2018-09-26 16:38 UTC | newest]
Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-09-26 10:23 [PATCH v3 00/30] xfsprogs: parent pointers v2 Allison Henderson
2018-09-26 10:23 ` [PATCH v3 01/30] xfsprogs: Move xfs_attr.h to libxfs Allison Henderson
2018-09-26 10:23 ` [PATCH v3 02/30] xfsprogs: Add helper function xfs_attr_try_sf_addname Allison Henderson
2018-09-26 10:23 ` [PATCH v3 03/30] xfsprogs: Add attibute set and helper functions Allison Henderson
2018-09-26 10:23 ` [PATCH v3 04/30] xfsprogs: Add attibute remove " Allison Henderson
2018-09-26 10:23 ` [PATCH v3 05/30] xfsprogs: Add trans toggle to attr routines Allison Henderson
2018-09-26 10:23 ` [PATCH v3 06/30] xfsprogs: Set up infastructure for deferred attribute operations Allison Henderson
2018-09-26 10:23 ` [PATCH v3 07/30] xfsprogs: Add xfs_attr_set_deferred and xfs_attr_remove_deferred Allison Henderson
2018-09-26 10:23 ` [PATCH v3 08/30] xfsprogs: Add xfs_has_attr and subroutines Allison Henderson
2018-09-26 10:23 ` [PATCH v3 09/30] xfsprogs: Add attr context to log item Allison Henderson
2018-09-26 10:23 ` [PATCH v3 10/30] xfsprogs: Roll delayed attr operations by returning EAGAIN Allison Henderson
2018-09-26 10:23 ` [PATCH v3 11/30] xfsprogs: Remove roll_trans boolean Allison Henderson
2018-09-26 10:23 ` [PATCH v3 12/30] xfsprogs: Remove all strlen calls in all xfs_attr_* functions for attr names Allison Henderson
2018-09-26 10:23 ` [PATCH v3 13/30] xfsprogs: get directory offset when adding directory name Allison Henderson
2018-09-26 10:23 ` [PATCH v3 14/30] xfsprogs: get directory offset when removing " Allison Henderson
2018-09-26 10:23 ` [PATCH v3 15/30] xfsprogs: get directory offset when replacing a " Allison Henderson
2018-09-26 10:23 ` [PATCH v3 16/30] xfsprogs: add parent pointer support to attribute code Allison Henderson
2018-09-26 10:23 ` [PATCH v3 17/30] xfsprogs: define parent pointer xattr format Allison Henderson
2018-09-26 10:23 ` [PATCH v3 18/30] xfsprogs: extent transaction reservations for parent attributes Allison Henderson
2018-09-26 10:23 ` [PATCH v3 19/30] xfsprogs: parent pointer attribute creation Allison Henderson
2018-09-26 10:23 ` [PATCH v3 20/30] xfsprogs: Add the parent pointer support to the superblock version 5 Allison Henderson
2018-09-26 10:23 ` [PATCH v3 21/30] xfsprogs: Add helper function xfs_attr_list_context_init Allison Henderson
2018-09-26 10:23 ` [PATCH v3 22/30] xfsprogs: Add parent pointer ioctl Allison Henderson
2018-09-26 10:23 ` [PATCH v3 23/30] xfs_io: Add delayed attributes error tag Allison Henderson
2018-09-26 10:23 ` [PATCH v3 24/30] xfsprogs: Add parent pointer flag to cmd Allison Henderson
2018-09-26 10:23 ` [PATCH v3 25/30] xfsprogs: Add log item printing for ATTRI and ATTRD Allison Henderson
2018-09-26 10:23 ` [PATCH v3 26/30] xfsprogs: Add xfs_verify_pptr Allison Henderson
2018-09-26 10:23 ` [PATCH v3 27/30] xfsprogs: Add parent pointers to recreated inodes Allison Henderson
2018-09-26 10:23 ` [PATCH v3 28/30] xfsprogs: Add parent pointers during protofile creation Allison Henderson
2018-09-26 10:23 ` [PATCH v3 29/30] xfsprogs: implement the upper half of parent pointers Allison Henderson
2018-09-26 10:23 ` [PATCH v3 30/30] xfsprogs: Add i, n and f flags to parent command Allison Henderson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).