All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/27] xfsprogs: parent pointers v2
@ 2018-06-10  5:07 Allison Henderson
  2018-06-10  5:07 ` [PATCH v2 01/27] xfsprogs: Move xfs_attr.h to libxfs Allison Henderson
                   ` (26 more replies)
  0 siblings, 27 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 UTC (permalink / raw)
  To: linux-xfs

This is the 2nd 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 19 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 v1:
I've updated the series with feedback from the last revisions.  Patches 23, 24
and 25 have split out from a previously larger patch, and patches 22 and 27 are
new.  So they could use some attention.

As always, comments and feedback are appreciated.  Thank you!

Allison Henderson (26):
  xfsprogs: Move xfs_attr.h to libxfs
  xfsprogs: Add helper function xfs_attr_try_sf_addname
  xfsprogs: Add trans toggle to attr routines
  xfsprogs: Add attibute set and helper functions
  xfsprogs: Add attibute remove and helper functions
  xfsprogs: Set up infastructure for deferred attribute operations
  xfsprogs: Add xfs_attr_set_deferred and xfs_attr_remove_deferred
  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: Remove single byte array from struct parent
  xfsprogs: Add log item printing for ATTRI and ATTRD
  xfsprogs: Do not use namechecks on parent pointers
  xfsprogs: Add parent pointers to recreated inodes
  xfsprogs: Add parent pointers during protofile creation
  xfsprogs: Clean up old parent pointer definitions

Darrick J. Wong (1):
  xfsprogs: implement the upper half of parent pointers

 include/handle.h         |   2 +
 include/parent.h         |  25 ++-
 include/path.h           |  19 ++
 io/inject.c              |   1 +
 io/parent.c              | 468 +++++++++++--------------------------------
 libfrog/paths.c          | 136 +++++++++++++
 libhandle/Makefile       |   2 +-
 libhandle/handle.c       |  33 +---
 libhandle/jdm.c          |  20 --
 libhandle/parent.c       | 325 ++++++++++++++++++++++++++++++
 libxfs/Makefile          |   3 +
 libxfs/libxfs_api_defs.h |   1 +
 libxfs/xfs_attr.c        | 505 ++++++++++++++++++++++++++++++++---------------
 libxfs/xfs_attr.h        | 194 ++++++++++++++++++
 libxfs/xfs_attr_leaf.c   |  14 +-
 libxfs/xfs_attr_leaf.h   |  10 +-
 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        |  41 ++--
 libxfs/xfs_dir2.h        |  10 +-
 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    |   5 +-
 libxfs/xfs_format.h      |  10 +-
 libxfs/xfs_fs.h          |  43 ++++
 libxfs/xfs_log_format.h  |  44 ++++-
 libxfs/xfs_parent.c      | 178 +++++++++++++++++
 libxfs/xfs_parent.h      |  38 ++++
 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             |  54 +++--
 mkfs/xfs_mkfs.c          |  15 +-
 repair/attr_repair.c     |  18 +-
 repair/phase6.c          |  57 ++++--
 scrub/inodes.c           |  26 +++
 scrub/inodes.h           |   2 +
 scrub/phase5.c           |   9 +-
 48 files changed, 2122 insertions(+), 712 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] 51+ messages in thread

* [PATCH v2 01/27] xfsprogs: Move xfs_attr.h to libxfs
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-10  5:07 ` [PATCH v2 02/27] xfsprogs: Add helper function xfs_attr_try_sf_addname Allison Henderson
                   ` (25 subsequent siblings)
  26 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 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 | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 158 insertions(+)

diff --git a/libxfs/Makefile b/libxfs/Makefile
index 0470f5f..75ce980 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..8abf398
--- /dev/null
+++ b/libxfs/xfs_attr.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2000,2002-2003,2005 Silicon Graphics, 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.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#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] 51+ messages in thread

* [PATCH v2 02/27] xfsprogs: Add helper function xfs_attr_try_sf_addname
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
  2018-06-10  5:07 ` [PATCH v2 01/27] xfsprogs: Move xfs_attr.h to libxfs Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-10  5:07 ` [PATCH v2 03/27] xfsprogs: Add trans toggle to attr routines Allison Henderson
                   ` (24 subsequent siblings)
  26 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 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 | 64 +++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 41 insertions(+), 23 deletions(-)

diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
index a4bde02..51b567d 100644
--- a/libxfs/xfs_attr.c
+++ b/libxfs/xfs_attr.c
@@ -198,6 +198,44 @@ xfs_attr_calc_size(
 	return nblks;
 }
 
+STATIC int
+xfs_attr_try_sf_addname(
+	struct xfs_inode	*dp,
+	struct xfs_da_args	*args,
+	int			flags)
+{
+
+	struct xfs_mount	*mp = dp->i_mount;
+	int			error;
+	int			err2;
+
+	error = xfs_attr_shortform_addname(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);
+		error = error ? error : err2;
+	}
+	return error;
+}
+
 int
 xfs_attr_set(
 	struct xfs_inode	*dp,
@@ -213,7 +251,7 @@ xfs_attr_set(
 	struct xfs_trans_res	tres;
 	xfs_fsblock_t		firstblock;
 	int			rsvd = (flags & ATTR_ROOT) != 0;
-	int			error, err2, local;
+	int			error, local;
 
 	XFS_STATS_INC(mp, xs_attr_set);
 
@@ -292,30 +330,10 @@ 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, flags);
 		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);
-
-			return error ? error : err2;
+			return error;
 		}
 
 		/*
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 03/27] xfsprogs: Add trans toggle to attr routines
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
  2018-06-10  5:07 ` [PATCH v2 01/27] xfsprogs: Move xfs_attr.h to libxfs Allison Henderson
  2018-06-10  5:07 ` [PATCH v2 02/27] xfsprogs: Add helper function xfs_attr_try_sf_addname Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-10  7:02   ` Amir Goldstein
  2018-06-10  5:07 ` [PATCH v2 04/27] xfsprogs: Add attibute set and helper functions Allison Henderson
                   ` (23 subsequent siblings)
  26 siblings, 1 reply; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 UTC (permalink / raw)
  To: linux-xfs

This patch adds a roll_trans parameter to all attribute routines.
Calling functions may pass true to roll transactions as normal,
or false to hold them.  We will need this later for delayed
attribute operations.

Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
 libxfs/xfs_attr.c      | 165 ++++++++++++++++++++++++++++---------------------
 libxfs/xfs_attr_leaf.c |  12 ++--
 libxfs/xfs_attr_leaf.h |  10 +--
 3 files changed, 108 insertions(+), 79 deletions(-)

diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
index 51b567d..7ef35f3 100644
--- a/libxfs/xfs_attr.c
+++ b/libxfs/xfs_attr.c
@@ -50,21 +50,21 @@
 /*
  * Internal routines when attribute list fits inside the inode.
  */
-STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
+STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args, bool roll_trans);
 
 /*
  * 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);
 
@@ -202,15 +202,16 @@ STATIC int
 xfs_attr_try_sf_addname(
 	struct xfs_inode	*dp,
 	struct xfs_da_args	*args,
-	int			flags)
+	int			flags,
+	bool			roll_trans)
 {
 
 	struct xfs_mount	*mp = dp->i_mount;
 	int			error;
 	int			err2;
 
-	error = xfs_attr_shortform_addname(args);
-	if (error != -ENOSPC) {
+	error = xfs_attr_shortform_addname(args, roll_trans);
+	if (error != -ENOSPC && roll_trans) {
 		/*
 		 * Commit the shortform mods, and we're done.
 		 * NOTE: this is also the error path
@@ -330,7 +331,7 @@ xfs_attr_set(
 		 * Try to add the attr to the attribute list in
 		 * the inode.
 		 */
-		error = xfs_attr_try_sf_addname(dp, &args, flags);
+		error = xfs_attr_try_sf_addname(dp, &args, flags, true);
 		if (error != -ENOSPC) {
 			xfs_iunlock(dp, XFS_ILOCK_EXCL);
 			return error;
@@ -369,9 +370,9 @@ xfs_attr_set(
 	}
 
 	if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
-		error = xfs_attr_leaf_addname(&args);
+		error = xfs_attr_leaf_addname(&args, true);
 	else
-		error = xfs_attr_node_addname(&args);
+		error = xfs_attr_node_addname(&args, true);
 	if (error)
 		goto out;
 
@@ -466,11 +467,11 @@ xfs_attr_remove(
 		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);
+		error = xfs_attr_shortform_remove(&args, true);
 	} else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
-		error = xfs_attr_leaf_removename(&args);
+		error = xfs_attr_leaf_removename(&args, true);
 	} else {
-		error = xfs_attr_node_removename(&args);
+		error = xfs_attr_node_removename(&args, true);
 	}
 
 	if (error)
@@ -511,7 +512,7 @@ out:
  * This is the external routine.
  */
 STATIC int
-xfs_attr_shortform_addname(xfs_da_args_t *args)
+xfs_attr_shortform_addname(xfs_da_args_t *args, bool roll_trans)
 {
 	int newsize, forkoff, retval;
 
@@ -523,7 +524,7 @@ xfs_attr_shortform_addname(xfs_da_args_t *args)
 	} else if (retval == -EEXIST) {
 		if (args->flags & ATTR_CREATE)
 			return retval;
-		retval = xfs_attr_shortform_remove(args);
+		retval = xfs_attr_shortform_remove(args, roll_trans);
 		ASSERT(retval == 0);
 	}
 
@@ -538,7 +539,7 @@ xfs_attr_shortform_addname(xfs_da_args_t *args)
 	if (!forkoff)
 		return -ENOSPC;
 
-	xfs_attr_shortform_add(args, forkoff);
+	xfs_attr_shortform_add(args, forkoff, roll_trans);
 	return 0;
 }
 
@@ -554,7 +555,7 @@ xfs_attr_shortform_addname(xfs_da_args_t *args)
  * if bmap_one_block() says there is only one block (ie: no remote blks).
  */
 STATIC int
-xfs_attr_leaf_addname(xfs_da_args_t *args)
+xfs_attr_leaf_addname(xfs_da_args_t *args, bool roll_trans)
 {
 	xfs_inode_t *dp;
 	struct xfs_buf *bp;
@@ -617,36 +618,42 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
 		 * can manage its own transactions.
 		 */
 		xfs_defer_init(args->dfops, args->firstblock);
-		error = xfs_attr3_leaf_to_node(args);
+		error = xfs_attr3_leaf_to_node(args, roll_trans);
 		if (error)
 			goto out_defer_cancel;
 		xfs_defer_ijoin(args->dfops, dp);
-		error = xfs_defer_finish(&args->trans, args->dfops);
-		if (error)
-			goto out_defer_cancel;
+		if (roll_trans) {
+			error = xfs_defer_finish(&args->trans, args->dfops);
+			if (error)
+				goto out_defer_cancel;
 
-		/*
-		 * Commit the current trans (including the inode) and start
-		 * a new one.
-		 */
-		error = xfs_trans_roll_inode(&args->trans, dp);
-		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
@@ -704,9 +711,11 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
 		/*
 		 * If the result is small enough, shrink it all into the inode.
 		 */
-		if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
+		if ((forkoff = xfs_attr_shortform_allfit(bp, dp)) &&
+				roll_trans) {
 			xfs_defer_init(args->dfops, args->firstblock);
-			error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
+			error = xfs_attr3_leaf_to_shortform(bp, args, forkoff,
+					roll_trans);
 			/* bp is gone due to xfs_da_shrink_inode */
 			if (error)
 				goto out_defer_cancel;
@@ -740,7 +749,7 @@ out_defer_cancel:
  * if bmap_one_block() says there is only one block (ie: no remote blks).
  */
 STATIC int
-xfs_attr_leaf_removename(xfs_da_args_t *args)
+xfs_attr_leaf_removename(xfs_da_args_t *args, bool roll_trans)
 {
 	xfs_inode_t *dp;
 	struct xfs_buf *bp;
@@ -769,15 +778,19 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
 	 * If the result is small enough, shrink it all into the inode.
 	 */
 	if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
-		xfs_defer_init(args->dfops, args->firstblock);
-		error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
+		if (roll_trans)
+			xfs_defer_init(args->dfops, args->firstblock);
+		error = xfs_attr3_leaf_to_shortform(bp, args, forkoff,
+							roll_trans);
 		/* bp is gone due to xfs_da_shrink_inode */
 		if (error)
 			goto out_defer_cancel;
 		xfs_defer_ijoin(args->dfops, dp);
-		error = xfs_defer_finish(&args->trans, args->dfops);
-		if (error)
-			goto out_defer_cancel;
+		if (roll_trans) {
+			error = xfs_defer_finish(&args->trans, args->dfops);
+			if (error)
+				goto out_defer_cancel;
+		}
 	}
 	return 0;
 out_defer_cancel:
@@ -832,7 +845,7 @@ xfs_attr_leaf_get(xfs_da_args_t *args)
  * add a whole extra layer of confusion on top of that.
  */
 STATIC int
-xfs_attr_node_addname(xfs_da_args_t *args)
+xfs_attr_node_addname(xfs_da_args_t *args, bool roll_trans)
 {
 	xfs_da_state_t *state;
 	xfs_da_state_blk_t *blk;
@@ -898,21 +911,24 @@ restart:
 			xfs_da_state_free(state);
 			state = NULL;
 			xfs_defer_init(args->dfops, args->firstblock);
-			error = xfs_attr3_leaf_to_node(args);
+			error = xfs_attr3_leaf_to_node(args, roll_trans);
 			if (error)
 				goto out_defer_cancel;
 			xfs_defer_ijoin(args->dfops, dp);
-			error = xfs_defer_finish(&args->trans, args->dfops);
-			if (error)
-				goto out_defer_cancel;
-
-			/*
-			 * 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,
+						args->dfops);
+				if (error)
+					goto out_defer_cancel;
+
+				/*
+				 * 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;
 		}
@@ -928,9 +944,11 @@ restart:
 		if (error)
 			goto out_defer_cancel;
 		xfs_defer_ijoin(args->dfops, dp);
-		error = xfs_defer_finish(&args->trans, args->dfops);
-		if (error)
-			goto out_defer_cancel;
+		if (roll_trans) {
+			error = xfs_defer_finish(&args->trans, args->dfops);
+			if (error)
+				goto out_defer_cancel;
+		}
 	} else {
 		/*
 		 * Addition succeeded, update Btree hashvals.
@@ -949,9 +967,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
@@ -1026,9 +1046,12 @@ restart:
 			if (error)
 				goto out_defer_cancel;
 			xfs_defer_ijoin(args->dfops, dp);
-			error = xfs_defer_finish(&args->trans, args->dfops);
-			if (error)
-				goto out_defer_cancel;
+			if (roll_trans) {
+				error = xfs_defer_finish(&args->trans,
+						args->dfops);
+				if (error)
+					goto out_defer_cancel;
+			}
 		}
 
 		/*
@@ -1067,7 +1090,7 @@ out_defer_cancel:
  * the root node (a special case of an intermediate node).
  */
 STATIC int
-xfs_attr_node_removename(xfs_da_args_t *args)
+xfs_attr_node_removename(xfs_da_args_t *args, bool roll_trans)
 {
 	xfs_da_state_t *state;
 	xfs_da_state_blk_t *blk;
@@ -1176,9 +1199,11 @@ xfs_attr_node_removename(xfs_da_args_t *args)
 		if (error)
 			goto out;
 
-		if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
+		if ((forkoff = xfs_attr_shortform_allfit(bp, dp)) &&
+					roll_trans) {
 			xfs_defer_init(args->dfops, args->firstblock);
-			error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
+			error = xfs_attr3_leaf_to_shortform(bp, args, forkoff,
+					roll_trans);
 			/* bp is gone due to xfs_da_shrink_inode */
 			if (error)
 				goto out_defer_cancel;
diff --git a/libxfs/xfs_attr_leaf.c b/libxfs/xfs_attr_leaf.c
index c3682eb..ef53215 100644
--- a/libxfs/xfs_attr_leaf.c
+++ b/libxfs/xfs_attr_leaf.c
@@ -541,7 +541,7 @@ xfs_attr_shortform_create(xfs_da_args_t *args)
  * Overflow from the inode has already been checked for.
  */
 void
-xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff)
+xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff, bool roll_trans)
 {
 	xfs_attr_shortform_t *sf;
 	xfs_attr_sf_entry_t *sfe;
@@ -613,7 +613,7 @@ xfs_attr_fork_remove(
  * Remove an attribute from the shortform attribute list structure.
  */
 int
-xfs_attr_shortform_remove(xfs_da_args_t *args)
+xfs_attr_shortform_remove(xfs_da_args_t *args, bool roll_trans)
 {
 	xfs_attr_shortform_t *sf;
 	xfs_attr_sf_entry_t *sfe;
@@ -965,7 +965,8 @@ int
 xfs_attr3_leaf_to_shortform(
 	struct xfs_buf		*bp,
 	struct xfs_da_args	*args,
-	int			forkoff)
+	int			forkoff,
+	bool			roll_trans)
 {
 	struct xfs_attr_leafblock *leaf;
 	struct xfs_attr3_icleaf_hdr ichdr;
@@ -1034,7 +1035,7 @@ xfs_attr3_leaf_to_shortform(
 		nargs.valuelen = be16_to_cpu(name_loc->valuelen);
 		nargs.hashval = be32_to_cpu(entry->hashval);
 		nargs.flags = XFS_ATTR_NSP_ONDISK_TO_ARGS(entry->flags);
-		xfs_attr_shortform_add(&nargs, forkoff);
+		xfs_attr_shortform_add(&nargs, forkoff, roll_trans);
 	}
 	error = 0;
 
@@ -1048,7 +1049,8 @@ out:
  */
 int
 xfs_attr3_leaf_to_node(
-	struct xfs_da_args	*args)
+	struct xfs_da_args	*args,
+	bool			roll_trans)
 {
 	struct xfs_attr_leafblock *leaf;
 	struct xfs_attr3_icleaf_hdr icleafhdr;
diff --git a/libxfs/xfs_attr_leaf.h b/libxfs/xfs_attr_leaf.h
index 4da08af..79c236c 100644
--- a/libxfs/xfs_attr_leaf.h
+++ b/libxfs/xfs_attr_leaf.h
@@ -45,12 +45,13 @@ typedef struct xfs_attr_inactive_list {
  * Internal routines when attribute fork size < XFS_LITINO(mp).
  */
 void	xfs_attr_shortform_create(struct xfs_da_args *args);
-void	xfs_attr_shortform_add(struct xfs_da_args *args, int forkoff);
+void	xfs_attr_shortform_add(struct xfs_da_args *args, int forkoff,
+			bool roll_trans);
 int	xfs_attr_shortform_lookup(struct xfs_da_args *args);
 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_attr_shortform_remove(struct xfs_da_args *args, bool roll_trans);
 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);
@@ -59,9 +60,10 @@ void	xfs_attr_fork_remove(struct xfs_inode *ip, struct xfs_trans *tp);
 /*
  * Internal routines when attribute fork size == XFS_LBSIZE(mp).
  */
-int	xfs_attr3_leaf_to_node(struct xfs_da_args *args);
+int	xfs_attr3_leaf_to_node(struct xfs_da_args *args, bool roll_trans);
 int	xfs_attr3_leaf_to_shortform(struct xfs_buf *bp,
-				   struct xfs_da_args *args, int forkoff);
+			struct xfs_da_args *args, int forkoff,
+			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);
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 04/27] xfsprogs: Add attibute set and helper functions
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (2 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 03/27] xfsprogs: Add trans toggle to attr routines Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-10  5:07 ` [PATCH v2 05/27] xfsprogs: Add attibute remove " Allison Henderson
                   ` (22 subsequent siblings)
  26 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 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 | 169 +++++++++++++++++++++++++++++++++---------------------
 libxfs/xfs_attr.h |   2 +
 libxfs/xfs_bmap.c |  49 ++++++++++------
 libxfs/xfs_bmap.h |   1 +
 4 files changed, 137 insertions(+), 84 deletions(-)

diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
index 7ef35f3..02b73ad 100644
--- a/libxfs/xfs_attr.c
+++ b/libxfs/xfs_attr.c
@@ -237,6 +237,108 @@ xfs_attr_try_sf_addname(
 	return error;
 }
 
+/*
+ * Set the attribute specified in @args. In the case of the parent attribute
+ * being set, we do not want to roll the transaction on shortform-to-leaf
+ * conversion, as the attribute must be added in the same transaction as the
+ * parent directory modifications. Hence @roll_trans needs to be set
+ * appropriately to control whether the transaction is committed during this
+ * function.
+ */
+int
+xfs_attr_set_args(
+	struct xfs_da_args	*args,
+	int			flags,
+	struct xfs_buf          *leaf_bp,
+	bool			roll_trans)
+{
+	struct xfs_inode	*dp = args->dp;
+	int			error = 0;
+	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, flags, roll_trans);
+		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;
+
+		xfs_defer_bjoin(args->dfops, leaf_bp);
+		xfs_defer_ijoin(args->dfops, dp);
+		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, args->dfops);
+			if (error) {
+				args->trans = NULL;
+				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_defer_ijoin(args->dfops, dp);
+			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, roll_trans);
+	else
+		error = xfs_attr_node_addname(args, roll_trans);
+	if (error)
+		goto out;
+
+out:
+	return error;
+}
+
 int
 xfs_attr_set(
 	struct xfs_inode	*dp,
@@ -313,68 +415,9 @@ 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, flags, true);
-		if (error != -ENOSPC) {
-			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.
-		 */
-		xfs_defer_init(args.dfops, args.firstblock);
-		error = xfs_attr_shortform_to_leaf(&args, &leaf_bp);
-		if (error)
-			goto out_defer_cancel;
-		/*
-		 * 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);
-		xfs_defer_bjoin(args.dfops, leaf_bp);
-		xfs_defer_ijoin(args.dfops, dp);
-		error = xfs_defer_finish(&args.trans, args.dfops);
-		if (error)
-			goto out_defer_cancel;
-
-		/*
-		 * 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, true);
-	else
-		error = xfs_attr_node_addname(&args, true);
+	error = xfs_attr_set_args(&args, flags, leaf_bp, true);
 	if (error)
-		goto out;
+		goto out_defer_cancel;
 
 	/*
 	 * If this is a synchronous mount, make sure that the
@@ -383,9 +426,6 @@ xfs_attr_set(
 	if (mp->m_flags & XFS_MOUNT_WSYNC)
 		xfs_trans_set_sync(args.trans);
 
-	if ((flags & ATTR_KERNOTIME) == 0)
-		xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG);
-
 	/*
 	 * Commit the last in the sequence of transactions.
 	 */
@@ -397,7 +437,6 @@ xfs_attr_set(
 
 out_defer_cancel:
 	xfs_defer_cancel(&dfops);
-out:
 	if (leaf_bp)
 		xfs_trans_brelse(args.trans, leaf_bp);
 	if (args.trans)
diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h
index 8abf398..adb1619 100644
--- a/libxfs/xfs_attr.h
+++ b/libxfs/xfs_attr.h
@@ -149,6 +149,8 @@ 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, int flags,
+			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_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 afc569c..79fcaf0 100644
--- a/libxfs/xfs_bmap.c
+++ b/libxfs/xfs_bmap.c
@@ -1022,6 +1022,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.
@@ -1075,26 +1103,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 e36d757..f7e51e6 100644
--- a/libxfs/xfs_bmap.h
+++ b/libxfs/xfs_bmap.h
@@ -191,6 +191,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_mount *mp, struct xfs_defer_ops *dfops,
 			  xfs_fsblock_t bno, xfs_filblks_t len,
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 05/27] xfsprogs: Add attibute remove and helper functions
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (3 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 04/27] xfsprogs: Add attibute set and helper functions Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-10  5:07 ` [PATCH v2 06/27] xfsprogs: Set up infastructure for deferred attribute operations Allison Henderson
                   ` (21 subsequent siblings)
  26 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 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 | 37 +++++++++++++++++++++++++++----------
 libxfs/xfs_attr.h |  1 +
 2 files changed, 28 insertions(+), 10 deletions(-)

diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
index 02b73ad..13271bb 100644
--- a/libxfs/xfs_attr.c
+++ b/libxfs/xfs_attr.c
@@ -339,6 +339,32 @@ out:
 	return error;
 }
 
+/*
+ * Remove the attribute specified in @args.
+ */
+int
+xfs_attr_remove_args(
+	struct xfs_da_args      *args,
+	int			flags,
+	bool                    roll_trans)
+{
+	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, roll_trans);
+	} else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
+		error = xfs_attr_leaf_removename(args, roll_trans);
+	} else {
+		error = xfs_attr_node_removename(args, roll_trans);
+	}
+
+	return error;
+}
+
 int
 xfs_attr_set(
 	struct xfs_inode	*dp,
@@ -502,16 +528,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, true);
-	} else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
-		error = xfs_attr_leaf_removename(&args, true);
-	} else {
-		error = xfs_attr_node_removename(&args, true);
-	}
+	error = xfs_attr_remove_args(&args, flags, true);
 
 	if (error)
 		goto out;
diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h
index adb1619..de2b99f 100644
--- a/libxfs/xfs_attr.h
+++ b/libxfs/xfs_attr.h
@@ -152,6 +152,7 @@ int xfs_attr_set(struct xfs_inode *dp, const unsigned char *name,
 int xfs_attr_set_args(struct xfs_da_args *args, int flags,
 			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 flags, bool roll_trans);
 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] 51+ messages in thread

* [PATCH v2 06/27] xfsprogs: Set up infastructure for deferred attribute operations
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (4 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 05/27] xfsprogs: Add attibute remove " Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-10  5:07 ` [PATCH v2 07/27] xfsprogs: Add xfs_attr_set_deferred and xfs_attr_remove_deferred Allison Henderson
                   ` (20 subsequent siblings)
  26 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 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.

At the moment, this feature will only be used by the parent
pointer patch set which uses attributes to store information
about an inodes parent.

Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
 libxfs/xfs_attr.c       |  5 +++--
 libxfs/xfs_attr.h       | 24 +++++++++++++++++++++++-
 libxfs/xfs_defer.h      |  1 +
 libxfs/xfs_log_format.h | 44 ++++++++++++++++++++++++++++++++++++++++++--
 libxfs/xfs_types.h      |  1 +
 5 files changed, 70 insertions(+), 5 deletions(-)

diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
index 13271bb..e894468 100644
--- a/libxfs/xfs_attr.c
+++ b/libxfs/xfs_attr.c
@@ -36,6 +36,7 @@
 #include "xfs_attr_remote.h"
 #include "xfs_trans_space.h"
 #include "xfs_trace.h"
+#include "xfs_attr_item.h"
 
 /*
  * xfs_attr.c
@@ -69,7 +70,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,
@@ -165,7 +166,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 de2b99f..eebfad7 100644
--- a/libxfs/xfs_attr.h
+++ b/libxfs/xfs_attr.h
@@ -87,6 +87,26 @@ 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;
+	uint32_t	  xattri_value_len;   /* length of value */
+	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.
  */
@@ -155,6 +175,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, int flags, 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 045beac..11e1690 100644
--- a/libxfs/xfs_defer.h
+++ b/libxfs/xfs_defer.h
@@ -55,6 +55,7 @@ enum xfs_defer_ops_type {
 	XFS_DEFER_OPS_TYPE_REFCOUNT,
 	XFS_DEFER_OPS_TYPE_RMAP,
 	XFS_DEFER_OPS_TYPE_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 349d9f8..291e5ff 100644
--- a/libxfs/xfs_log_format.h
+++ b/libxfs/xfs_log_format.h
@@ -116,7 +116,12 @@ static inline uint xlog_get_cycle(char *ptr)
 #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
@@ -239,6 +244,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" }, \
@@ -254,7 +261,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.
@@ -852,4 +861,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 3c56069..2905ce3 100644
--- a/libxfs/xfs_types.h
+++ b/libxfs/xfs_types.h
@@ -23,6 +23,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] 51+ messages in thread

* [PATCH v2 07/27] xfsprogs: Add xfs_attr_set_deferred and xfs_attr_remove_deferred
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (5 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 06/27] xfsprogs: Set up infastructure for deferred attribute operations Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-10  5:07 ` [PATCH v2 08/27] xfsprogs: Remove all strlen calls in all xfs_attr_* functions for attr names Allison Henderson
                   ` (19 subsequent siblings)
  26 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 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 | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 libxfs/xfs_attr.h |  5 ++++
 2 files changed, 78 insertions(+)

diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
index e894468..fae5c9a 100644
--- a/libxfs/xfs_attr.c
+++ b/libxfs/xfs_attr.c
@@ -37,6 +37,7 @@
 #include "xfs_trans_space.h"
 #include "xfs_trace.h"
 #include "xfs_attr_item.h"
+#include "xfs_attr.h"
 
 /*
  * xfs_attr.c
@@ -472,6 +473,44 @@ out_defer_cancel:
 	return error;
 }
 
+/* Sets an attribute for an inode as a deferred operation */
+int
+xfs_attr_set_deferred(
+	struct xfs_inode	*dp,
+	struct xfs_defer_ops    *dfops,
+	void			*name,
+	unsigned int		namelen,
+	void			*value,
+	unsigned int		valuelen,
+	int			flags)
+{
+
+	struct xfs_attr_item	*new;
+	char			*name_value;
+
+	if (!namelen || !valuelen) {
+		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);
+	memcpy(&name_value[namelen], value, valuelen);
+
+	xfs_defer_ijoin(dfops, dp);
+	xfs_defer_add(dfops, 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.
@@ -560,6 +599,40 @@ out:
 	return error;
 }
 
+/* Removes an attribute for an inode as a deferred operation */
+int
+xfs_attr_remove_deferred(
+	struct xfs_inode        *dp,
+	struct xfs_defer_ops    *dfops,
+	void			*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_ijoin(dfops, dp);
+	xfs_defer_add(dfops, 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 eebfad7..c706976 100644
--- a/libxfs/xfs_attr.h
+++ b/libxfs/xfs_attr.h
@@ -178,5 +178,10 @@ 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_defer_ops *dfops,
+			  void *name, unsigned int name_len, void *value,
+			  unsigned int valuelen, int flags);
+int xfs_attr_remove_deferred(struct xfs_inode *dp, struct xfs_defer_ops *dfops,
+			    void *name, unsigned int namelen, int flags);
 
 #endif	/* __XFS_ATTR_H__ */
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 08/27] xfsprogs: Remove all strlen calls in all xfs_attr_* functions for attr names
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (6 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 07/27] xfsprogs: Add xfs_attr_set_deferred and xfs_attr_remove_deferred Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-10  5:07 ` [PATCH v2 09/27] xfsprogs: get directory offset when adding directory name Allison Henderson
                   ` (18 subsequent siblings)
  26 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 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 | 12 ++++++++----
 libxfs/xfs_attr.h | 10 ++++++----
 2 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
index fae5c9a..64fb6ef 100644
--- a/libxfs/xfs_attr.c
+++ b/libxfs/xfs_attr.c
@@ -76,6 +76,7 @@ xfs_attr_args_init(
 	struct xfs_da_args	*args,
 	struct xfs_inode	*dp,
 	const unsigned char	*name,
+	size_t			namelen,
 	int			flags)
 {
 
@@ -88,7 +89,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 */
 
@@ -134,6 +135,7 @@ int
 xfs_attr_get(
 	struct xfs_inode	*ip,
 	const unsigned char	*name,
+	size_t			namelen,
 	unsigned char		*value,
 	int			*valuelenp,
 	int			flags)
@@ -147,7 +149,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;
 
@@ -371,6 +373,7 @@ int
 xfs_attr_set(
 	struct xfs_inode	*dp,
 	const unsigned char	*name,
+	size_t			namelen,
 	unsigned char		*value,
 	int			valuelen,
 	int			flags)
@@ -389,7 +392,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;
 
@@ -519,6 +522,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;
 
diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h
index c706976..d23cf4a 100644
--- a/libxfs/xfs_attr.h
+++ b/libxfs/xfs_attr.h
@@ -166,17 +166,19 @@ 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, int flags,
 			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(struct xfs_inode *dp, const unsigned char *name,
+		size_t namelen, int flags);
 int xfs_attr_remove_args(struct xfs_da_args *args, int flags, 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);
+		       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_defer_ops *dfops,
 			  void *name, unsigned int name_len, void *value,
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 09/27] xfsprogs: get directory offset when adding directory name
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (7 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 08/27] xfsprogs: Remove all strlen calls in all xfs_attr_* functions for attr names Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-10  5:07 ` [PATCH v2 10/27] xfsprogs: get directory offset when removing " Allison Henderson
                   ` (17 subsequent siblings)
  26 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 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       |  3 ++-
 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            |  3 ++-
 repair/phase6.c         | 17 +++++++++--------
 9 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/libxfs/xfs_da_btree.h b/libxfs/xfs_da_btree.h
index ae6de17..bce96d6 100644
--- a/libxfs/xfs_da_btree.h
+++ b/libxfs/xfs_da_btree.h
@@ -86,6 +86,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 d82eaab..cd67e1b 100644
--- a/libxfs/xfs_dir2.c
+++ b/libxfs/xfs_dir2.c
@@ -255,7 +255,8 @@ xfs_dir_createname(
 	xfs_ino_t		inum,		/* new entry inode number */
 	xfs_fsblock_t		*first,		/* bmap's firstblock */
 	struct xfs_defer_ops	*dfops,		/* bmap's freeblock list */
-	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;
@@ -311,6 +312,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;
 }
@@ -557,7 +562,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, NULL, NULL, 0);
+	return xfs_dir_createname(tp, dp, name, 0, NULL, NULL, 0, NULL);
 }
 
 /*
diff --git a/libxfs/xfs_dir2.h b/libxfs/xfs_dir2.h
index 388d67c..378c654 100644
--- a/libxfs/xfs_dir2.h
+++ b/libxfs/xfs_dir2.h
@@ -131,7 +131,8 @@ extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp,
 extern int xfs_dir_createname(struct xfs_trans *tp, struct xfs_inode *dp,
 				struct xfs_name *name, xfs_ino_t inum,
 				xfs_fsblock_t *first,
-				struct xfs_defer_ops *dfops, xfs_extlen_t tot);
+				struct xfs_defer_ops *dfops, 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 e2c524e..4815d26 100644
--- a/libxfs/xfs_dir2_block.c
+++ b/libxfs/xfs_dir2_block.c
@@ -549,6 +549,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 60f7eb2..949e798 100644
--- a/libxfs/xfs_dir2_leaf.c
+++ b/libxfs/xfs_dir2_leaf.c
@@ -887,6 +887,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 6d7986c..697e37e 100644
--- a/libxfs/xfs_dir2_node.c
+++ b/libxfs/xfs_dir2_node.c
@@ -2032,6 +2032,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 fbb9482..e601208 100644
--- a/libxfs/xfs_dir2_sf.c
+++ b/libxfs/xfs_dir2_sf.c
@@ -403,6 +403,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.
@@ -494,6 +495,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 bc38345..67c228a 100644
--- a/mkfs/proto.c
+++ b/mkfs/proto.c
@@ -331,7 +331,8 @@ newdirent(
 
 	rsv = XFS_DIRENTER_SPACE_RES(mp, name->len);
 
-	error = -libxfs_dir_createname(tp, pip, name, inum, first, dfops, rsv);
+	error = -libxfs_dir_createname(tp, pip, name, inum, first, dfops, rsv,
+				       NULL);
 	if (error)
 		fail(_("directory createname error"), error);
 }
diff --git a/repair/phase6.c b/repair/phase6.c
index 498a3b5..b41cc2b 100644
--- a/repair/phase6.c
+++ b/repair/phase6.c
@@ -1061,7 +1061,7 @@ mk_orphanage(xfs_mount_t *mp)
 	 * create the actual entry
 	 */
 	error = -libxfs_dir_createname(tp, pip, &xname, ip->i_ino, &first,
-					&dfops, nres);
+					&dfops, nres, NULL);
 	if (error)
 		do_error(
 		_("can't make %s, createname error %d\n"),
@@ -1170,7 +1170,7 @@ mv_orphanage(
 
 			libxfs_defer_init(&dfops, &first);
 			err = -libxfs_dir_createname(tp, orphanage_ip, &xname,
-						ino, &first, &dfops, nres);
+						ino, &first, &dfops, nres, NULL);
 			if (err)
 				do_error(
 	_("name create failed in %s (%d), filesystem may be out of space\n"),
@@ -1183,7 +1183,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, &first, &dfops, nres);
+					orphanage_ino, &first, &dfops, nres, NULL);
 			if (err)
 				do_error(
 	_("creation of .. entry failed (%d), filesystem may be out of space\n"),
@@ -1214,7 +1214,7 @@ mv_orphanage(
 			libxfs_defer_init(&dfops, &first);
 
 			err = -libxfs_dir_createname(tp, orphanage_ip, &xname,
-						ino, &first, &dfops, nres);
+						ino, &first, &dfops, nres, NULL);
 			if (err)
 				do_error(
 	_("name create failed in %s (%d), filesystem may be out of space\n"),
@@ -1270,7 +1270,7 @@ mv_orphanage(
 
 		libxfs_defer_init(&dfops, &first);
 		err = -libxfs_dir_createname(tp, orphanage_ip, &xname, ino,
-						&first, &dfops, nres);
+						&first, &dfops, nres, NULL);
 		if (err)
 			do_error(
 	_("name create failed in %s (%d), filesystem may be out of space\n"),
@@ -1408,7 +1408,8 @@ longform_dir2_rebuild(
 
 		libxfs_defer_init(&dfops, &firstblock);
 		error = -libxfs_dir_createname(tp, ip, &p->name, p->inum,
-						&firstblock, &dfops, nres);
+						&firstblock, &dfops, nres,
+						NULL);
 		if (error) {
 			do_warn(
 _("name create failed in ino %" PRIu64 " (%d), filesystem may be out of space\n"),
@@ -3011,7 +3012,7 @@ process_dir_inode(
 		libxfs_defer_init(&dfops, &first);
 
 		error = -libxfs_dir_createname(tp, ip, &xfs_name_dotdot,
-					ip->i_ino, &first, &dfops, nres);
+					ip->i_ino, &first, &dfops, nres, NULL);
 		if (error)
 			do_error(
 	_("can't make \"..\" entry in root inode %" PRIu64 ", createname error %d\n"), ino, error);
@@ -3069,7 +3070,7 @@ process_dir_inode(
 			libxfs_defer_init(&dfops, &first);
 
 			error = -libxfs_dir_createname(tp, ip, &xfs_name_dot,
-					ip->i_ino, &first, &dfops, nres);
+					ip->i_ino, &first, &dfops, 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] 51+ messages in thread

* [PATCH v2 10/27] xfsprogs: get directory offset when removing directory name
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (8 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 09/27] xfsprogs: get directory offset when adding directory name Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-10  5:07 ` [PATCH v2 11/27] xfsprogs: get directory offset when replacing a " Allison Henderson
                   ` (16 subsequent siblings)
  26 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 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       | 16 ++++++++++------
 libxfs/xfs_dir2.h       |  4 +++-
 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, 23 insertions(+), 13 deletions(-)

diff --git a/libxfs/xfs_dir2.c b/libxfs/xfs_dir2.c
index cd67e1b..ef9fba6 100644
--- a/libxfs/xfs_dir2.c
+++ b/libxfs/xfs_dir2.c
@@ -431,13 +431,14 @@ out_free:
  */
 int
 xfs_dir_removename(
-	xfs_trans_t	*tp,
-	xfs_inode_t	*dp,
-	struct xfs_name	*name,
-	xfs_ino_t	ino,
-	xfs_fsblock_t	*first,		/* bmap's firstblock */
+	struct xfs_trans	*tp,
+	struct xfs_inode	*dp,
+	struct xfs_name		*name,
+	xfs_ino_t		ino,
+	xfs_fsblock_t		*first,		/* bmap's firstblock */
 	struct xfs_defer_ops	*dfops,		/* bmap's freeblock list */
-	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;
@@ -484,6 +485,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 378c654..e2cd70b 100644
--- a/libxfs/xfs_dir2.h
+++ b/libxfs/xfs_dir2.h
@@ -139,7 +139,9 @@ extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp,
 extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp,
 				struct xfs_name *name, xfs_ino_t ino,
 				xfs_fsblock_t *first,
-				struct xfs_defer_ops *dfops, xfs_extlen_t tot);
+				struct xfs_defer_ops *dfops,
+				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_fsblock_t *first,
diff --git a/libxfs/xfs_dir2_block.c b/libxfs/xfs_dir2_block.c
index 4815d26..e7ce6a9 100644
--- a/libxfs/xfs_dir2_block.c
+++ b/libxfs/xfs_dir2_block.c
@@ -788,9 +788,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 949e798..8cca19e 100644
--- a/libxfs/xfs_dir2_leaf.c
+++ b/libxfs/xfs_dir2_leaf.c
@@ -1407,9 +1407,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 697e37e..e4ca481 100644
--- a/libxfs/xfs_dir2_node.c
+++ b/libxfs/xfs_dir2_node.c
@@ -1248,9 +1248,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 e601208..8013ddd 100644
--- a/libxfs/xfs_dir2_sf.c
+++ b/libxfs/xfs_dir2_sf.c
@@ -915,6 +915,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] 51+ messages in thread

* [PATCH v2 11/27] xfsprogs: get directory offset when replacing a directory name
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (9 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 10/27] xfsprogs: get directory offset when removing " Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-10  5:07 ` [PATCH v2 12/27] xfsprogs: add parent pointer support to attribute code Allison Henderson
                   ` (15 subsequent siblings)
  26 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 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       | 18 +++++++++++-------
 libxfs/xfs_dir2.h       |  3 ++-
 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, 20 insertions(+), 11 deletions(-)

diff --git a/libxfs/xfs_dir2.c b/libxfs/xfs_dir2.c
index ef9fba6..db7c697 100644
--- a/libxfs/xfs_dir2.c
+++ b/libxfs/xfs_dir2.c
@@ -485,7 +485,7 @@ xfs_dir_removename(
 	else
 		rval = xfs_dir2_node_removename(args);
 out_free:
-	if (offset)
+	if (!rval && offset)
 		*offset = args->offset;
 
 	kmem_free(args);
@@ -497,13 +497,14 @@ out_free:
  */
 int
 xfs_dir_replace(
-	xfs_trans_t	*tp,
-	xfs_inode_t	*dp,
-	struct xfs_name	*name,		/* name of entry to replace */
-	xfs_ino_t	inum,		/* new inode number */
-	xfs_fsblock_t	*first,		/* bmap's firstblock */
+	struct xfs_trans	*tp,
+	struct xfs_inode	*dp,
+	struct xfs_name		*name,		/* name of entry to replace */
+	xfs_ino_t		inum,		/* new inode number */
+	xfs_fsblock_t		*first,		/* bmap's firstblock */
 	struct xfs_defer_ops	*dfops,		/* bmap's freeblock list */
-	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;
@@ -553,6 +554,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 e2cd70b..cb6fda0 100644
--- a/libxfs/xfs_dir2.h
+++ b/libxfs/xfs_dir2.h
@@ -145,7 +145,8 @@ extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp,
 extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
 				struct xfs_name *name, xfs_ino_t inum,
 				xfs_fsblock_t *first,
-				struct xfs_defer_ops *dfops, xfs_extlen_t tot);
+				struct xfs_defer_ops *dfops, 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 e7ce6a9..34d6a0d 100644
--- a/libxfs/xfs_dir2_block.c
+++ b/libxfs/xfs_dir2_block.c
@@ -862,9 +862,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 8cca19e..ee16fc4 100644
--- a/libxfs/xfs_dir2_leaf.c
+++ b/libxfs/xfs_dir2_leaf.c
@@ -1542,6 +1542,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 e4ca481..e604b1c 100644
--- a/libxfs/xfs_dir2_node.c
+++ b/libxfs/xfs_dir2_node.c
@@ -2247,6 +2247,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 8013ddd..11561a9 100644
--- a/libxfs/xfs_dir2_sf.c
+++ b/libxfs/xfs_dir2_sf.c
@@ -1041,6 +1041,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 b41cc2b..4fedb35 100644
--- a/repair/phase6.c
+++ b/repair/phase6.c
@@ -1233,7 +1233,7 @@ mv_orphanage(
 			if (entry_ino_num != orphanage_ino)  {
 				err = -libxfs_dir_replace(tp, ino_p,
 						&xfs_name_dotdot, orphanage_ino,
-						&first, &dfops, nres);
+						&first, &dfops, 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] 51+ messages in thread

* [PATCH v2 12/27] xfsprogs: add parent pointer support to attribute code
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (10 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 11/27] xfsprogs: get directory offset when replacing a " Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-10  5:07 ` [PATCH v2 13/27] xfsprogs: define parent pointer xattr format Allison Henderson
                   ` (14 subsequent siblings)
  26 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 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      |  2 +-
 libxfs/xfs_attr.h      |  2 ++
 libxfs/xfs_attr_leaf.c |  2 +-
 libxfs/xfs_da_format.h | 12 ++++++++----
 4 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
index 64fb6ef..df0bd91 100644
--- a/libxfs/xfs_attr.c
+++ b/libxfs/xfs_attr.c
@@ -384,7 +384,7 @@ xfs_attr_set(
 	struct xfs_defer_ops	dfops;
 	struct xfs_trans_res	tres;
 	xfs_fsblock_t		firstblock;
-	int			rsvd = (flags & ATTR_ROOT) != 0;
+	bool			rsvd = (flags & (ATTR_ROOT | ATTR_PARENT)) != 0;
 	int			error, local;
 
 	XFS_STATS_INC(mp, xs_attr_set);
diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h
index d23cf4a..f388f5f 100644
--- a/libxfs/xfs_attr.h
+++ b/libxfs/xfs_attr.h
@@ -44,6 +44,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 */
 
@@ -54,6 +55,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 ef53215..0440003 100644
--- a/libxfs/xfs_attr_leaf.c
+++ b/libxfs/xfs_attr_leaf.c
@@ -37,7 +37,7 @@
 #include "xfs_trace.h"
 #include "xfs_cksum.h"
 #include "xfs_dir2.h"
-
+#include "xfs_attr.h"
 
 /*
  * xfs_attr_leaf.c
diff --git a/libxfs/xfs_da_format.h b/libxfs/xfs_da_format.h
index 7e77299..9bd2e6b 100644
--- a/libxfs/xfs_da_format.h
+++ b/libxfs/xfs_da_format.h
@@ -758,24 +758,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] 51+ messages in thread

* [PATCH v2 13/27] xfsprogs: define parent pointer xattr format
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (11 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 12/27] xfsprogs: add parent pointer support to attribute code Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-10  5:07 ` [PATCH v2 14/27] xfsprogs: extent transaction reservations for parent attributes Allison Henderson
                   ` (13 subsequent siblings)
  26 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 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>
Signed-off-by: Allison Henderson <allison.henderson@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 9bd2e6b..bb5d8ec 100644
--- a/libxfs/xfs_da_format.h
+++ b/libxfs/xfs_da_format.h
@@ -885,4 +885,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] 51+ messages in thread

* [PATCH v2 14/27] xfsprogs: extent transaction reservations for parent attributes
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (12 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 13/27] xfsprogs: define parent pointer xattr format Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-10  5:07 ` [PATCH v2 15/27] xfsprogs: parent pointer attribute creation Allison Henderson
                   ` (12 subsequent siblings)
  26 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 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 4854893..de8b14a 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -559,6 +559,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 3cebb90..7b7d98f 100644
--- a/libxfs/xfs_trans_resv.c
+++ b/libxfs/xfs_trans_resv.c
@@ -788,29 +788,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;
@@ -832,15 +833,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 2 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;
@@ -872,6 +935,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 b7e5357..c7190d6 100644
--- a/libxfs/xfs_trans_resv.h
+++ b/libxfs/xfs_trans_resv.h
@@ -105,5 +105,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] 51+ messages in thread

* [PATCH v2 15/27] xfsprogs: parent pointer attribute creation
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (13 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 14/27] xfsprogs: extent transaction reservations for parent attributes Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-10  5:07 ` [PATCH v2 16/27] xfsprogs: Add the parent pointer support to the superblock version 5 Allison Henderson
                   ` (11 subsequent siblings)
  26 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 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 | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 libxfs/xfs_parent.h |  36 +++++++++++
 3 files changed, 206 insertions(+)

diff --git a/libxfs/Makefile b/libxfs/Makefile
index 75ce980..6fdcdf7 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 \
@@ -89,6 +90,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..3510828
--- /dev/null
+++ b/libxfs/xfs_parent.c
@@ -0,0 +1,168 @@
+/*
+ * 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_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_attr.h"
+#include "xfs_da_btree.h"
+#include "xfs_attr_sf.h"
+#include "libxfs_api_defs.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,
+	xfs_fsblock_t			*firstblock,
+	struct xfs_defer_ops		*dfops)
+{
+	struct xfs_parent_name_rec	rec;
+	int				error;
+	struct xfs_da_args		args;
+	int				flags = ATTR_PARENT;
+	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_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.value = (char *)child_name->name;
+	args.valuelen = child_name->len;
+	args.dfops = dfops;
+	args.op_flags = XFS_DA_OP_OKNOENT | XFS_DA_OP_ADDNAME;
+	args.firstblock = firstblock;
+	args.total = xfs_attr_calc_size(&args, &local);
+	ASSERT(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);
+
+	error = xfs_attr_set_args(&args, flags, leaf_bp, false);
+
+	if (error)
+		goto out;
+
+	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..6197817
--- /dev/null
+++ b/libxfs/xfs_parent.h
@@ -0,0 +1,36 @@
+/*
+ * 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, xfs_fsblock_t *firstblock,
+		   struct xfs_defer_ops *dfops);
+#endif	/* __XFS_PARENT_H__ */
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 16/27] xfsprogs: Add the parent pointer support to the superblock version 5.
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (14 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 15/27] xfsprogs: parent pointer attribute creation Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-10  5:07 ` [PATCH v2 17/27] xfsprogs: Add helper function xfs_attr_list_context_init Allison Henderson
                   ` (10 subsequent siblings)
  26 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 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 de8b14a..05431b0 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -462,10 +462,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(
@@ -561,7 +563,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 86a379f..0c6f9fa 100644
--- a/libxfs/xfs_fs.h
+++ b/libxfs/xfs_fs.h
@@ -243,6 +243,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 e8dd463..1c5b6e7 100644
--- a/libxfs/xfs_sb.c
+++ b/libxfs/xfs_sb.c
@@ -940,6 +940,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] 51+ messages in thread

* [PATCH v2 17/27] xfsprogs: Add helper function xfs_attr_list_context_init
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (15 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 16/27] xfsprogs: Add the parent pointer support to the superblock version 5 Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-10  5:07 ` [PATCH v2 18/27] xfsprogs: Add parent pointer ioctl Allison Henderson
                   ` (9 subsequent siblings)
  26 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 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 f388f5f..54f82f5 100644
--- a/libxfs/xfs_attr.h
+++ b/libxfs/xfs_attr.h
@@ -179,6 +179,9 @@ int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name,
 int xfs_attr_remove_args(struct xfs_da_args *args, int flags, 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_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] 51+ messages in thread

* [PATCH v2 18/27] xfsprogs: Add parent pointer ioctl
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (16 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 17/27] xfsprogs: Add helper function xfs_attr_list_context_init Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-10  5:07 ` [PATCH v2 19/27] xfsprogs: Add delayed attributes error tag Allison Henderson
                   ` (8 subsequent siblings)
  26 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 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     | 42 ++++++++++++++++++++++++++++++++++++++++++
 libxfs/xfs_parent.c | 10 ++++++++++
 libxfs/xfs_parent.h |  2 ++
 3 files changed, 54 insertions(+)

diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h
index 0c6f9fa..3ebfe75 100644
--- a/libxfs/xfs_fs.h
+++ b/libxfs/xfs_fs.h
@@ -573,6 +573,47 @@ struct xfs_scrub_metadata {
 				 XFS_SCRUB_OFLAG_WARNING)
 #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)
+
+/* 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 though 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_pptr 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
  */
@@ -616,6 +657,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 3510828..70c12ba 100644
--- a/libxfs/xfs_parent.c
+++ b/libxfs/xfs_parent.c
@@ -39,6 +39,16 @@
 #include "xfs_attr_sf.h"
 #include "libxfs_api_defs.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 6197817..7771719 100644
--- a/libxfs/xfs_parent.h
+++ b/libxfs/xfs_parent.h
@@ -33,4 +33,6 @@ int xfs_parent_add(struct xfs_inode *parent,
 		   struct xfs_inode *child, struct xfs_name *child_name,
 		   uint32_t diroffset, xfs_fsblock_t *firstblock,
 		   struct xfs_defer_ops *dfops);
+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] 51+ messages in thread

* [PATCH v2 19/27] xfsprogs: Add delayed attributes error tag
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (17 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 18/27] xfsprogs: Add parent pointer ioctl Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-11 17:28   ` Darrick J. Wong
  2018-06-10  5:07 ` [PATCH v2 20/27] xfsprogs: Add parent pointer flag to cmd Allison Henderson
                   ` (7 subsequent siblings)
  26 siblings, 1 reply; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 UTC (permalink / raw)
  To: linux-xfs

Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
 io/inject.c           | 1 +
 libxfs/xfs_errortag.h | 5 ++++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/io/inject.c b/io/inject.c
index fc3cf25..2d6cc9c 100644
--- a/io/inject.c
+++ b/io/inject.c
@@ -63,6 +63,7 @@ error_tag(char *name)
 		{ XFS_ERRTAG_LOG_BAD_CRC,		"log_bad_crc" },
 		{ XFS_ERRTAG_LOG_ITEM_PIN,		"log_item_pin" },
 		{ XFS_ERRTAG_BUF_LRU_REF,		"buf_lru_ref" },
+		{ 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 bc1789d..f606ab6 100644
--- a/libxfs/xfs_errortag.h
+++ b/libxfs/xfs_errortag.h
@@ -65,7 +65,8 @@
 #define XFS_ERRTAG_LOG_BAD_CRC				29
 #define XFS_ERRTAG_LOG_ITEM_PIN				30
 #define XFS_ERRTAG_BUF_LRU_REF				31
-#define XFS_ERRTAG_MAX					32
+#define XFS_ERRTAG_DELAYED_ATTR			32
+#define XFS_ERRTAG_MAX					33
 
 /*
  * Random factors for above tags, 1 means always, 2 means 1/2 time, etc.
@@ -102,5 +103,7 @@
 #define XFS_RANDOM_LOG_BAD_CRC				1
 #define XFS_RANDOM_LOG_ITEM_PIN				1
 #define XFS_RANDOM_BUF_LRU_REF				2
+#define XFS_RANDOM_DELAYED_ATTR			1
 
 #endif /* __XFS_ERRORTAG_H_ */
+
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 20/27] xfsprogs: Add parent pointer flag to cmd
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (18 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 19/27] xfsprogs: Add delayed attributes error tag Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-11 17:43   ` Darrick J. Wong
  2018-06-10  5:07 ` [PATCH v2 21/27] xfsprogs: Remove single byte array from struct parent Allison Henderson
                   ` (6 subsequent siblings)
  26 siblings, 1 reply; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 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 | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 78d0ce5..b9a8b00 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -104,6 +104,7 @@ enum {
 	N_SIZE = 0,
 	N_VERSION,
 	N_FTYPE,
+	N_PARENT,
 	N_MAX_OPTS,
 };
 
@@ -550,6 +551,7 @@ struct opt_params nopts = {
 		[N_SIZE] = "size",
 		[N_VERSION] = "version",
 		[N_FTYPE] = "ftype",
+		[N_PARENT] = "parent",
 	},
 	.subopt_params = {
 		{ .index = N_SIZE,
@@ -572,6 +574,12 @@ struct opt_params nopts = {
 		  .maxval = 1,
 		  .defaultval = 1,
 		},
+		{ .index = N_PARENT,
+		  .conflicts = { { NULL, LAST_CONFLICT } },
+		  .minval = 0,
+		  .maxval = 1,
+		  .defaultval = 1,
+		},
 	},
 };
 
@@ -876,7 +884,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\
@@ -1615,6 +1623,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;
 	}
@@ -2887,6 +2898,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] 51+ messages in thread

* [PATCH v2 21/27] xfsprogs: Remove single byte array from struct parent
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (19 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 20/27] xfsprogs: Add parent pointer flag to cmd Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-10 11:21   ` Amir Goldstein
  2018-06-10  5:07 ` [PATCH v2 22/27] xfsprogs: Add log item printing for ATTRI and ATTRD Allison Henderson
                   ` (5 subsequent siblings)
  26 siblings, 1 reply; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 UTC (permalink / raw)
  To: linux-xfs

Variable sized arrays implemented this way may cause
corruptions depending on how different compilers pack
the structure.

Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
 include/parent.h | 1 -
 io/parent.c      | 9 ++++++---
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/include/parent.h b/include/parent.h
index f338f96..85cef85 100644
--- a/include/parent.h
+++ b/include/parent.h
@@ -22,7 +22,6 @@ typedef struct parent {
 	__u64	p_ino;
 	__u32	p_gen;
 	__u16	p_reclen;
-	char	p_name[1];
 } parent_t;
 
 typedef struct parent_cursor {
diff --git a/io/parent.c b/io/parent.c
index 1968516..55b8b49 100644
--- a/io/parent.c
+++ b/io/parent.c
@@ -45,7 +45,8 @@ check_parent_entry(xfs_bstat_t *bstatp, parent_t *parent)
 	struct stat statbuf;
 	char *str;
 
-	sprintf(fullpath, _("%s%s"), mntpt, parent->p_name);
+	snprintf(fullpath, parent->p_reclen, _("%s%s"), mntpt,
+				((char*)parent)+sizeof(struct parent));
 
 	sts = lstat(fullpath, &statbuf);
 	if (sts != 0) {
@@ -284,9 +285,11 @@ print_parent_entry(parent_t *parent, int fullpath)
 	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);
+		printf(_("p_name   = \"%s%s\"\n"), mntpt,
+					((char*)parent)+sizeof(struct parent));
 	else
-		printf(_("p_name   = \"%s\"\n"), parent->p_name);
+		printf(_("p_name   = \"%s\"\n"),
+					((char*)parent)+sizeof(struct parent));
 }
 
 static int
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 22/27] xfsprogs: Add log item printing for ATTRI and ATTRD
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (20 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 21/27] xfsprogs: Remove single byte array from struct parent Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-10  5:07 ` [PATCH v2 23/27] xfsprogs: Do not use namechecks on parent pointers Allison Henderson
                   ` (4 subsequent siblings)
  26 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 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 fd46cc3..23946a8 100644
--- a/logprint/log_misc.c
+++ b/logprint/log_misc.c
@@ -959,6 +959,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 cdaf77b..7857522 100644
--- a/logprint/log_print_all.c
+++ b/logprint/log_print_all.c
@@ -412,6 +412,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;
@@ -464,6 +470,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 d39f8e9..6618724 100644
--- a/logprint/log_redo.c
+++ b/logprint/log_redo.c
@@ -20,6 +20,7 @@
 #include "libxlog.h"
 
 #include "logprint.h"
+#include "xfs_attr_item.h"
 
 /* Extent Free Items */
 
@@ -665,3 +666,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 20f1be4..52e3619 100644
--- a/logprint/logprint.h
+++ b/logprint/logprint.h
@@ -64,4 +64,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] 51+ messages in thread

* [PATCH v2 23/27] xfsprogs: Do not use namechecks on parent pointers
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (21 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 22/27] xfsprogs: Add log item printing for ATTRI and ATTRD Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-11 18:00   ` Darrick J. Wong
  2018-06-10  5:07 ` [PATCH v2 24/27] xfsprogs: Add parent pointers to recreated inodes Allison Henderson
                   ` (3 subsequent siblings)
  26 siblings, 1 reply; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 UTC (permalink / raw)
  To: linux-xfs

Attribute names of parent pointers are not strings.  So
avoid doing namechecks for these attributes.

Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
 repair/attr_repair.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/repair/attr_repair.c b/repair/attr_repair.c
index 8b1b8a7..b8b0768 100644
--- a/repair/attr_repair.c
+++ b/repair/attr_repair.c
@@ -308,8 +308,9 @@ process_shortform_attr(
 		/* namecheck checks for / and null terminated for file names.
 		 * attributes names currently follow the same rules.
 		*/
-		if (namecheck((char *)&currententry->nameval[0],
-						currententry->namelen))  {
+		if (!(currententry->flags & XFS_ATTR_PARENT) &&
+			namecheck((char *)&currententry->nameval[0],
+			currententry->namelen))  {
 			do_warn(
 	_("entry contains illegal character in shortform attribute name\n"));
 			junkit = 1;
@@ -470,8 +471,9 @@ 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 (!(entry->flags & XFS_ATTR_PARENT) &&
+		(local->namelen == 0 || namecheck((char *)&local->nameval[0],
+		local->namelen))) {
 		do_warn(
 	_("attribute entry %d in attr block %u, inode %" PRIu64 " has bad name (namelen = %d)\n"),
 			i, da_bno, ino, local->namelen);
@@ -525,13 +527,15 @@ process_leaf_attr_remote(
 
 	remotep = xfs_attr3_leaf_name_remote(leaf, i);
 
-	if (remotep->namelen == 0 || namecheck((char *)&remotep->name[0],
-						remotep->namelen) ||
+	if (!(entry->flags & XFS_ATTR_PARENT) &&
+			(remotep->namelen == 0 ||
+			namecheck((char *)&remotep->name[0],
+				remotep->namelen) ||
 			be32_to_cpu(entry->hashval) !=
 				libxfs_da_hashname((unsigned char *)&remotep->name[0],
 						remotep->namelen) ||
 			be32_to_cpu(entry->hashval) < last_hashval ||
-			be32_to_cpu(remotep->valueblk) == 0) {
+			be32_to_cpu(remotep->valueblk) == 0)) {
 		do_warn(
 	_("inconsistent remote attribute entry %d in attr block %u, ino %" PRIu64 "\n"), i, da_bno, ino);
 		return -1;
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 24/27] xfsprogs: Add parent pointers to recreated inodes
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (22 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 23/27] xfsprogs: Do not use namechecks on parent pointers Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-10 11:27   ` Amir Goldstein
  2018-06-11 18:06   ` Darrick J. Wong
  2018-06-10  5:07 ` [PATCH v2 25/27] xfsprogs: Add parent pointers during protofile creation Allison Henderson
                   ` (2 subsequent siblings)
  26 siblings, 2 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 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          | 40 +++++++++++++++++++++++++++-------------
 2 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
index 78daca0..4b47479 100644
--- a/libxfs/libxfs_api_defs.h
+++ b/libxfs/libxfs_api_defs.h
@@ -152,5 +152,6 @@
 #define xfs_rmap_compare		libxfs_rmap_compare
 #define xfs_dir_get_ops			libxfs_dir_get_ops
 #define xfs_default_ifork_ops		libxfs_default_ifork_ops
+#define xfs_parent_add    		libxfs_parent_add
 
 #endif /* __LIBXFS_API_DEFS_H__ */
diff --git a/repair/phase6.c b/repair/phase6.c
index 4fedb35..96ffade 100644
--- a/repair/phase6.c
+++ b/repair/phase6.c
@@ -29,6 +29,7 @@
 #include "dinode.h"
 #include "progress.h"
 #include "versions.h"
+#include "xfs_parent.h"
 
 static struct cred		zerocr;
 static struct fsxattr 		zerofsx;
@@ -962,19 +963,20 @@ 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;
-	xfs_fsblock_t	first;
-	ino_tree_node_t	*irec;
-	int		ino_offset = 0;
-	int		i;
-	int		error;
+	xfs_ino_t		ino;
+	struct xfs_trans	*tp;
+	struct xfs_inode	*ip;
+	struct xfs_inode	*pip;
+	xfs_fsblock_t		first;
+	struct ino_tree_node	*irec;
+	int			ino_offset = 0;
+	int			i;
+	int			error;
 	struct xfs_defer_ops	dfops;
-	const int	mode = 0755;
-	int		nres;
-	struct xfs_name	xname;
+	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
@@ -1061,7 +1063,7 @@ mk_orphanage(xfs_mount_t *mp)
 	 * create the actual entry
 	 */
 	error = -libxfs_dir_createname(tp, pip, &xname, ip->i_ino, &first,
-					&dfops, nres, NULL);
+					&dfops, nres, &offset);
 	if (error)
 		do_error(
 		_("can't make %s, createname error %d\n"),
@@ -1083,6 +1085,18 @@ mk_orphanage(xfs_mount_t *mp)
 	libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 
 	libxfs_defer_ijoin(&dfops, ip);
+
+        if (xfs_sb_version_hasparent(&mp->m_sb)) {
+                error = -libxfs_parent_add(pip, ip, &xname, offset,
+				       &first, &dfops);
+                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_defer_ijoin(&dfops, pip);
+        }
+
 	error = -libxfs_defer_finish(&tp, &dfops);
 	if (error) {
 		do_error(_("%s directory creation failed -- bmapf error %d\n"),
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 25/27] xfsprogs: Add parent pointers during protofile creation
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (23 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 24/27] xfsprogs: Add parent pointers to recreated inodes Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-10 11:32   ` Amir Goldstein
  2018-06-11 18:15   ` Darrick J. Wong
  2018-06-10  5:07 ` [PATCH v2 26/27] xfsprogs: implement the upper half of parent pointers Allison Henderson
  2018-06-10  5:07 ` [PATCH v2 27/27] xfsprogs: Clean up old parent pointer definitions Allison Henderson
  26 siblings, 2 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 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 | 55 ++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 36 insertions(+), 19 deletions(-)

diff --git a/mkfs/proto.c b/mkfs/proto.c
index 67c228a..222479f 100644
--- a/mkfs/proto.c
+++ b/mkfs/proto.c
@@ -19,6 +19,7 @@
 #include "libxfs.h"
 #include <sys/stat.h>
 #include "xfs_multidisk.h"
+#include "xfs_parent.h"
 
 /*
  * Prototypes for internal functions.
@@ -318,23 +319,25 @@ newregfile(
 
 static void
 newdirent(
-	xfs_mount_t	*mp,
-	xfs_trans_t	*tp,
-	xfs_inode_t	*pip,
-	struct xfs_name	*name,
-	xfs_ino_t	inum,
-	xfs_fsblock_t	*first,
-	struct xfs_defer_ops	*dfops)
+	struct xfs_mount	*mp,
+	struct xfs_trans	*tp,
+	struct xfs_inode	*pip,
+	struct xfs_name		*name,
+	struct xfs_inode	*ip,
+	xfs_fsblock_t		*first,
+	struct xfs_defer_ops	*dfops,
+	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, first, dfops, rsv,
-				       NULL);
+	error = -libxfs_dir_createname(tp, pip, name, ip->i_ino, first, dfops, rsv,
+				       offset);
 	if (error)
 		fail(_("directory createname error"), error);
+
 }
 
 static void
@@ -387,6 +390,7 @@ parseproto(
 	cred_t		creds;
 	char		*value;
 	struct xfs_name	xname;
+	xfs_dir2_dataptr_t offset;
 
 	memset(&creds, 0, sizeof(creds));
 	mstr = getstr(pp);
@@ -470,7 +474,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, &first, &dfops);
+		newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
 		break;
 
 	case IF_RESERVED:			/* pre-allocated space only */
@@ -493,7 +497,7 @@ parseproto(
 		libxfs_trans_ijoin(tp, pip, 0);
 
 		xname.type = XFS_DIR3_FT_REG_FILE;
-		newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops);
+		newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
 		libxfs_trans_log_inode(tp, ip, flags);
 
 		libxfs_defer_ijoin(&dfops, ip);
@@ -516,7 +520,7 @@ parseproto(
 		}
 		libxfs_trans_ijoin(tp, pip, 0);
 		xname.type = XFS_DIR3_FT_BLKDEV;
-		newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops);
+		newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
 		flags |= XFS_ILOG_DEV;
 		break;
 
@@ -530,7 +534,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, &first, &dfops);
+		newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
 		flags |= XFS_ILOG_DEV;
 		break;
 
@@ -542,7 +546,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, &first, &dfops);
+		newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
 		break;
 	case IF_SYMLINK:
 		buf = getstr(pp);
@@ -555,7 +559,7 @@ parseproto(
 		flags |= newfile(tp, ip, &dfops, &first, 1, 1, buf, len);
 		libxfs_trans_ijoin(tp, pip, 0);
 		xname.type = XFS_DIR3_FT_SYMLINK;
-		newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops);
+		newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
 		break;
 	case IF_DIRECTORY:
 		tp = getres(mp, 0);
@@ -572,8 +576,8 @@ parseproto(
 		} else {
 			libxfs_trans_ijoin(tp, pip, 0);
 			xname.type = XFS_DIR3_FT_DIR;
-			newdirent(mp, tp, pip, &xname, ip->i_ino,
-				  &first, &dfops);
+			newdirent(mp, tp, pip, &xname, ip,
+				  &first, &dfops, &offset);
 			inc_nlink(VFS_I(pip));
 			libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE);
 		}
@@ -612,6 +616,19 @@ parseproto(
 		fail(_("Error encountered creating file from prototype file"),
 			error);
 	}
+
+	if (xfs_sb_version_hasparent(&mp->m_sb)) {
+		error = xfs_parent_add(pip, ip, &xname, offset, &first, &dfops);
+		if (error)
+			fail(_("Error creating parent pointer"), error);
+
+		libxfs_trans_log_inode(tp, ip, flags);
+		libxfs_defer_ijoin(&dfops, ip);
+		error = -libxfs_defer_finish(&tp, &dfops);
+		if (error)
+			fail(_("Directory creation failed"), error);
+	}
+
 	libxfs_trans_commit(tp);
 	IRELE(ip);
 }
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [PATCH v2 26/27] xfsprogs: implement the upper half of parent pointers
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (24 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 25/27] xfsprogs: Add parent pointers during protofile creation Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-10 12:06   ` Amir Goldstein
  2018-06-10  5:07 ` [PATCH v2 27/27] xfsprogs: Clean up old parent pointer definitions Allison Henderson
  26 siblings, 1 reply; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 UTC (permalink / raw)
  To: linux-xfs

From: "Darrick J. Wong" <darrick.wong@oracle.com>

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.

Totally missing: actual support in libxfs for working with parent ptrs
straight off the disk (mkfs, xfs_db, xfs_repair).

[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        | 471 ++++++++++++++---------------------------------------
 libfrog/paths.c    | 136 ++++++++++++++++
 libhandle/Makefile |   2 +-
 libhandle/handle.c |   7 +-
 libhandle/parent.c | 325 ++++++++++++++++++++++++++++++++++++
 scrub/inodes.c     |  26 +++
 scrub/inodes.h     |   2 +
 scrub/phase5.c     |   9 +-
 11 files changed, 653 insertions(+), 364 deletions(-)

diff --git a/include/handle.h b/include/handle.h
index 49f1441..00aa43d 100644
--- a/include/handle.h
+++ b/include/handle.h
@@ -52,6 +52,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 85cef85..33f8d85 100644
--- a/include/parent.h
+++ b/include/parent.h
@@ -28,4 +28,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 88dc44b..cbe4e19 100644
--- a/include/path.h
+++ b/include/path.h
@@ -70,4 +70,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 55b8b49..ad51fe6 100644
--- a/io/parent.c
+++ b/io/parent.c
@@ -21,366 +21,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;
-
-	snprintf(fullpath, parent->p_reclen, _("%s%s"), mntpt,
-				((char*)parent)+sizeof(struct parent));
-
-	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,
-					((char*)parent)+sizeof(struct parent));
-	else
-		printf(_("p_name   = \"%s\"\n"),
-					((char*)parent)+sizeof(struct parent));
+	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;
@@ -394,46 +133,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"));
 }
 
@@ -444,9 +209,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 c7895e9..9fb0140 100644
--- a/libfrog/paths.c
+++ b/libfrog/paths.c
@@ -27,6 +27,7 @@
 #include "path.h"
 #include "input.h"
 #include "project.h"
+#include "list.h"
 #include <limits.h>
 
 extern char *progname;
@@ -632,3 +633,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 fe1a2af..d3cea41 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 878d14d..a70fa32 100644
--- a/libhandle/handle.c
+++ b/libhandle/handle.c
@@ -41,7 +41,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);
 
 
@@ -214,8 +213,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..f6be3bd
--- /dev/null
+++ b/libhandle/parent.c
@@ -0,0 +1,325 @@
+/*
+ * 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;
+		}
+		if (pi->pi_ptrs_used == 0)
+			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;
+		}
+		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 ccfb9e0..3fbcd1a 100644
--- a/scrub/inodes.c
+++ b/scrub/inodes.c
@@ -31,6 +31,7 @@
 #include "xfs_scrub.h"
 #include "common.h"
 #include "inodes.h"
+#include "parent.h"
 
 /*
  * Iterate a range of inodes.
@@ -293,3 +294,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 693cb05..e94de0a 100644
--- a/scrub/inodes.h
+++ b/scrub/inodes.h
@@ -28,5 +28,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 01038f7..ecaaaaa 100644
--- a/scrub/phase5.c
+++ b/scrub/phase5.c
@@ -245,16 +245,11 @@ 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;
 
-	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] 51+ messages in thread

* [PATCH v2 27/27] xfsprogs: Clean up old parent pointer definitions
  2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
                   ` (25 preceding siblings ...)
  2018-06-10  5:07 ` [PATCH v2 26/27] xfsprogs: implement the upper half of parent pointers Allison Henderson
@ 2018-06-10  5:07 ` Allison Henderson
  2018-06-11 18:20   ` Darrick J. Wong
  26 siblings, 1 reply; 51+ messages in thread
From: Allison Henderson @ 2018-06-10  5:07 UTC (permalink / raw)
  To: linux-xfs

Existing parent pointer stubs and structs are not used in this
implementation.  Remove uneeded definitions.

Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
 include/parent.h   | 10 ----------
 libhandle/handle.c | 26 --------------------------
 libhandle/jdm.c    | 20 --------------------
 3 files changed, 56 deletions(-)

diff --git a/include/parent.h b/include/parent.h
index 33f8d85..5665d64 100644
--- a/include/parent.h
+++ b/include/parent.h
@@ -18,16 +18,6 @@
 #ifndef __PARENT_H__
 #define	__PARENT_H__
 
-typedef struct parent {
-	__u64	p_ino;
-	__u32	p_gen;
-	__u16	p_reclen;
-} parent_t;
-
-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,
diff --git a/libhandle/handle.c b/libhandle/handle.c
index a70fa32..862b943 100644
--- a/libhandle/handle.c
+++ b/libhandle/handle.c
@@ -20,7 +20,6 @@
 #include "platform_defs.h"
 #include "xfs.h"
 #include "handle.h"
-#include "parent.h"
 
 /* just pick a value we know is more than big enough */
 #define	MAXHANSIZ	64
@@ -422,31 +421,6 @@ attr_list_by_handle(
 }
 
 int
-parents_by_handle(
-	void		*hanp,
-	size_t		hlen,
-	parent_t	*buf,
-	size_t		bufsiz,
-	unsigned int	*count)
-
-{
-	errno = EOPNOTSUPP;
-	return -1;
-}
-
-int
-parentpaths_by_handle(
-	void		*hanp,
-	size_t		hlen,
-	parent_t	*buf,
-	size_t		bufsiz,
-	unsigned int	*count)
-{
-	errno = EOPNOTSUPP;
-	return -1;
-}
-
-int
 fssetdm_by_handle(
 	void		*hanp,
 	size_t		hlen,
diff --git a/libhandle/jdm.c b/libhandle/jdm.c
index 821061b..0c2440b 100644
--- a/libhandle/jdm.c
+++ b/libhandle/jdm.c
@@ -20,7 +20,6 @@
 #include "xfs.h"
 #include "handle.h"
 #include "jdm.h"
-#include "parent.h"
 
 /* internal fshandle - typecast to a void for external use */
 #define FSHANDLE_SZ		8
@@ -178,22 +177,3 @@ jdm_attr_list(	jdm_fshandle_t *fshp,
 	return rval;
 }
 
-int
-jdm_parents( jdm_fshandle_t *fshp,
-		xfs_bstat_t *statp,
-		parent_t *bufp, size_t bufsz,
-		unsigned int *count)
-{
-	errno = EOPNOTSUPP;
-	return -1;
-}
-
-int
-jdm_parentpaths( jdm_fshandle_t *fshp,
-		xfs_bstat_t *statp,
-		parent_t *bufp, size_t bufsz,
-		unsigned int *count)
-{
-	errno = EOPNOTSUPP;
-	return -1;
-}
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 03/27] xfsprogs: Add trans toggle to attr routines
  2018-06-10  5:07 ` [PATCH v2 03/27] xfsprogs: Add trans toggle to attr routines Allison Henderson
@ 2018-06-10  7:02   ` Amir Goldstein
  2018-06-10 16:19     ` Allison Henderson
  0 siblings, 1 reply; 51+ messages in thread
From: Amir Goldstein @ 2018-06-10  7:02 UTC (permalink / raw)
  To: Allison Henderson; +Cc: linux-xfs

On Sun, Jun 10, 2018 at 8:07 AM, Allison Henderson
<allison.henderson@oracle.com> wrote:
> This patch adds a roll_trans parameter to all attribute routines.
> Calling functions may pass true to roll transactions as normal,
> or false to hold them.  We will need this later for delayed
> attribute operations.
>
> Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
> ---
>  libxfs/xfs_attr.c      | 165 ++++++++++++++++++++++++++++---------------------
>  libxfs/xfs_attr_leaf.c |  12 ++--
>  libxfs/xfs_attr_leaf.h |  10 +--
>  3 files changed, 108 insertions(+), 79 deletions(-)
>
> diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
> index 51b567d..7ef35f3 100644
> --- a/libxfs/xfs_attr.c
> +++ b/libxfs/xfs_attr.c
> @@ -50,21 +50,21 @@
>  /*
>   * Internal routines when attribute list fits inside the inode.
>   */
> -STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
> +STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args, bool roll_trans);
>

So "working on another solution to path 3" means folding roll_trans into
xfs_da_args_t? if yes, then no further comments.

>  /*
>   * 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);
>
> @@ -202,15 +202,16 @@ STATIC int
>  xfs_attr_try_sf_addname(
>         struct xfs_inode        *dp,
>         struct xfs_da_args      *args,
> -       int                     flags)
> +       int                     flags,
> +       bool                    roll_trans)
>  {
>
>         struct xfs_mount        *mp = dp->i_mount;
>         int                     error;
>         int                     err2;
>
> -       error = xfs_attr_shortform_addname(args);
> -       if (error != -ENOSPC) {
> +       error = xfs_attr_shortform_addname(args, roll_trans);
> +       if (error != -ENOSPC && roll_trans) {
>                 /*
>                  * Commit the shortform mods, and we're done.
>                  * NOTE: this is also the error path
> @@ -330,7 +331,7 @@ xfs_attr_set(
>                  * Try to add the attr to the attribute list in
>                  * the inode.
>                  */
> -               error = xfs_attr_try_sf_addname(dp, &args, flags);
> +               error = xfs_attr_try_sf_addname(dp, &args, flags, true);
>                 if (error != -ENOSPC) {
>                         xfs_iunlock(dp, XFS_ILOCK_EXCL);
>                         return error;
> @@ -369,9 +370,9 @@ xfs_attr_set(
>         }
>
>         if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
> -               error = xfs_attr_leaf_addname(&args);
> +               error = xfs_attr_leaf_addname(&args, true);
>         else
> -               error = xfs_attr_node_addname(&args);
> +               error = xfs_attr_node_addname(&args, true);
>         if (error)
>                 goto out;
>
> @@ -466,11 +467,11 @@ xfs_attr_remove(
>                 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);
> +               error = xfs_attr_shortform_remove(&args, true);
>         } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
> -               error = xfs_attr_leaf_removename(&args);
> +               error = xfs_attr_leaf_removename(&args, true);
>         } else {
> -               error = xfs_attr_node_removename(&args);
> +               error = xfs_attr_node_removename(&args, true);
>         }
>
>         if (error)
> @@ -511,7 +512,7 @@ out:
>   * This is the external routine.
>   */
>  STATIC int
> -xfs_attr_shortform_addname(xfs_da_args_t *args)
> +xfs_attr_shortform_addname(xfs_da_args_t *args, bool roll_trans)
>  {
>         int newsize, forkoff, retval;
>
> @@ -523,7 +524,7 @@ xfs_attr_shortform_addname(xfs_da_args_t *args)
>         } else if (retval == -EEXIST) {
>                 if (args->flags & ATTR_CREATE)
>                         return retval;
> -               retval = xfs_attr_shortform_remove(args);
> +               retval = xfs_attr_shortform_remove(args, roll_trans);
>                 ASSERT(retval == 0);
>         }
>
> @@ -538,7 +539,7 @@ xfs_attr_shortform_addname(xfs_da_args_t *args)
>         if (!forkoff)
>                 return -ENOSPC;
>
> -       xfs_attr_shortform_add(args, forkoff);
> +       xfs_attr_shortform_add(args, forkoff, roll_trans);
>         return 0;
>  }
>
> @@ -554,7 +555,7 @@ xfs_attr_shortform_addname(xfs_da_args_t *args)
>   * if bmap_one_block() says there is only one block (ie: no remote blks).
>   */
>  STATIC int
> -xfs_attr_leaf_addname(xfs_da_args_t *args)
> +xfs_attr_leaf_addname(xfs_da_args_t *args, bool roll_trans)
>  {
>         xfs_inode_t *dp;
>         struct xfs_buf *bp;
> @@ -617,36 +618,42 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
>                  * can manage its own transactions.
>                  */
>                 xfs_defer_init(args->dfops, args->firstblock);
> -               error = xfs_attr3_leaf_to_node(args);
> +               error = xfs_attr3_leaf_to_node(args, roll_trans);
>                 if (error)
>                         goto out_defer_cancel;
>                 xfs_defer_ijoin(args->dfops, dp);
> -               error = xfs_defer_finish(&args->trans, args->dfops);
> -               if (error)
> -                       goto out_defer_cancel;
> +               if (roll_trans) {
> +                       error = xfs_defer_finish(&args->trans, args->dfops);
> +                       if (error)
> +                               goto out_defer_cancel;
>
> -               /*
> -                * Commit the current trans (including the inode) and start
> -                * a new one.
> -                */
> -               error = xfs_trans_roll_inode(&args->trans, dp);
> -               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
> @@ -704,9 +711,11 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
>                 /*
>                  * If the result is small enough, shrink it all into the inode.
>                  */
> -               if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
> +               if ((forkoff = xfs_attr_shortform_allfit(bp, dp)) &&
> +                               roll_trans) {
>                         xfs_defer_init(args->dfops, args->firstblock);
> -                       error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
> +                       error = xfs_attr3_leaf_to_shortform(bp, args, forkoff,
> +                                       roll_trans);
>                         /* bp is gone due to xfs_da_shrink_inode */
>                         if (error)
>                                 goto out_defer_cancel;
> @@ -740,7 +749,7 @@ out_defer_cancel:
>   * if bmap_one_block() says there is only one block (ie: no remote blks).
>   */
>  STATIC int
> -xfs_attr_leaf_removename(xfs_da_args_t *args)
> +xfs_attr_leaf_removename(xfs_da_args_t *args, bool roll_trans)
>  {
>         xfs_inode_t *dp;
>         struct xfs_buf *bp;
> @@ -769,15 +778,19 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
>          * If the result is small enough, shrink it all into the inode.
>          */
>         if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
> -               xfs_defer_init(args->dfops, args->firstblock);
> -               error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
> +               if (roll_trans)
> +                       xfs_defer_init(args->dfops, args->firstblock);
> +               error = xfs_attr3_leaf_to_shortform(bp, args, forkoff,
> +                                                       roll_trans);
>                 /* bp is gone due to xfs_da_shrink_inode */
>                 if (error)
>                         goto out_defer_cancel;
>                 xfs_defer_ijoin(args->dfops, dp);
> -               error = xfs_defer_finish(&args->trans, args->dfops);
> -               if (error)
> -                       goto out_defer_cancel;
> +               if (roll_trans) {
> +                       error = xfs_defer_finish(&args->trans, args->dfops);
> +                       if (error)
> +                               goto out_defer_cancel;
> +               }
>         }
>         return 0;
>  out_defer_cancel:
> @@ -832,7 +845,7 @@ xfs_attr_leaf_get(xfs_da_args_t *args)
>   * add a whole extra layer of confusion on top of that.
>   */
>  STATIC int
> -xfs_attr_node_addname(xfs_da_args_t *args)
> +xfs_attr_node_addname(xfs_da_args_t *args, bool roll_trans)
>  {
>         xfs_da_state_t *state;
>         xfs_da_state_blk_t *blk;
> @@ -898,21 +911,24 @@ restart:
>                         xfs_da_state_free(state);
>                         state = NULL;
>                         xfs_defer_init(args->dfops, args->firstblock);
> -                       error = xfs_attr3_leaf_to_node(args);
> +                       error = xfs_attr3_leaf_to_node(args, roll_trans);
>                         if (error)
>                                 goto out_defer_cancel;
>                         xfs_defer_ijoin(args->dfops, dp);
> -                       error = xfs_defer_finish(&args->trans, args->dfops);
> -                       if (error)
> -                               goto out_defer_cancel;
> -
> -                       /*
> -                        * 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,
> +                                               args->dfops);
> +                               if (error)
> +                                       goto out_defer_cancel;
> +
> +                               /*
> +                                * 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;
>                 }
> @@ -928,9 +944,11 @@ restart:
>                 if (error)
>                         goto out_defer_cancel;
>                 xfs_defer_ijoin(args->dfops, dp);
> -               error = xfs_defer_finish(&args->trans, args->dfops);
> -               if (error)
> -                       goto out_defer_cancel;
> +               if (roll_trans) {
> +                       error = xfs_defer_finish(&args->trans, args->dfops);
> +                       if (error)
> +                               goto out_defer_cancel;
> +               }
>         } else {
>                 /*
>                  * Addition succeeded, update Btree hashvals.
> @@ -949,9 +967,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
> @@ -1026,9 +1046,12 @@ restart:
>                         if (error)
>                                 goto out_defer_cancel;
>                         xfs_defer_ijoin(args->dfops, dp);
> -                       error = xfs_defer_finish(&args->trans, args->dfops);
> -                       if (error)
> -                               goto out_defer_cancel;
> +                       if (roll_trans) {
> +                               error = xfs_defer_finish(&args->trans,
> +                                               args->dfops);
> +                               if (error)
> +                                       goto out_defer_cancel;
> +                       }
>                 }
>
>                 /*
> @@ -1067,7 +1090,7 @@ out_defer_cancel:
>   * the root node (a special case of an intermediate node).
>   */
>  STATIC int
> -xfs_attr_node_removename(xfs_da_args_t *args)
> +xfs_attr_node_removename(xfs_da_args_t *args, bool roll_trans)
>  {
>         xfs_da_state_t *state;
>         xfs_da_state_blk_t *blk;
> @@ -1176,9 +1199,11 @@ xfs_attr_node_removename(xfs_da_args_t *args)
>                 if (error)
>                         goto out;
>
> -               if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
> +               if ((forkoff = xfs_attr_shortform_allfit(bp, dp)) &&
> +                                       roll_trans) {
>                         xfs_defer_init(args->dfops, args->firstblock);
> -                       error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
> +                       error = xfs_attr3_leaf_to_shortform(bp, args, forkoff,
> +                                       roll_trans);
>                         /* bp is gone due to xfs_da_shrink_inode */
>                         if (error)
>                                 goto out_defer_cancel;
> diff --git a/libxfs/xfs_attr_leaf.c b/libxfs/xfs_attr_leaf.c
> index c3682eb..ef53215 100644
> --- a/libxfs/xfs_attr_leaf.c
> +++ b/libxfs/xfs_attr_leaf.c
> @@ -541,7 +541,7 @@ xfs_attr_shortform_create(xfs_da_args_t *args)
>   * Overflow from the inode has already been checked for.
>   */
>  void
> -xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff)
> +xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff, bool roll_trans)
>  {
>         xfs_attr_shortform_t *sf;
>         xfs_attr_sf_entry_t *sfe;
> @@ -613,7 +613,7 @@ xfs_attr_fork_remove(
>   * Remove an attribute from the shortform attribute list structure.
>   */
>  int
> -xfs_attr_shortform_remove(xfs_da_args_t *args)
> +xfs_attr_shortform_remove(xfs_da_args_t *args, bool roll_trans)
>  {
>         xfs_attr_shortform_t *sf;
>         xfs_attr_sf_entry_t *sfe;
> @@ -965,7 +965,8 @@ int
>  xfs_attr3_leaf_to_shortform(
>         struct xfs_buf          *bp,
>         struct xfs_da_args      *args,
> -       int                     forkoff)
> +       int                     forkoff,
> +       bool                    roll_trans)
>  {
>         struct xfs_attr_leafblock *leaf;
>         struct xfs_attr3_icleaf_hdr ichdr;
> @@ -1034,7 +1035,7 @@ xfs_attr3_leaf_to_shortform(
>                 nargs.valuelen = be16_to_cpu(name_loc->valuelen);
>                 nargs.hashval = be32_to_cpu(entry->hashval);
>                 nargs.flags = XFS_ATTR_NSP_ONDISK_TO_ARGS(entry->flags);
> -               xfs_attr_shortform_add(&nargs, forkoff);
> +               xfs_attr_shortform_add(&nargs, forkoff, roll_trans);
>         }
>         error = 0;
>
> @@ -1048,7 +1049,8 @@ out:
>   */
>  int
>  xfs_attr3_leaf_to_node(
> -       struct xfs_da_args      *args)
> +       struct xfs_da_args      *args,
> +       bool                    roll_trans)
>  {
>         struct xfs_attr_leafblock *leaf;
>         struct xfs_attr3_icleaf_hdr icleafhdr;
> diff --git a/libxfs/xfs_attr_leaf.h b/libxfs/xfs_attr_leaf.h
> index 4da08af..79c236c 100644
> --- a/libxfs/xfs_attr_leaf.h
> +++ b/libxfs/xfs_attr_leaf.h
> @@ -45,12 +45,13 @@ typedef struct xfs_attr_inactive_list {
>   * Internal routines when attribute fork size < XFS_LITINO(mp).
>   */
>  void   xfs_attr_shortform_create(struct xfs_da_args *args);
> -void   xfs_attr_shortform_add(struct xfs_da_args *args, int forkoff);
> +void   xfs_attr_shortform_add(struct xfs_da_args *args, int forkoff,
> +                       bool roll_trans);
>  int    xfs_attr_shortform_lookup(struct xfs_da_args *args);
>  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_attr_shortform_remove(struct xfs_da_args *args, bool roll_trans);
>  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);
> @@ -59,9 +60,10 @@ void xfs_attr_fork_remove(struct xfs_inode *ip, struct xfs_trans *tp);
>  /*
>   * Internal routines when attribute fork size == XFS_LBSIZE(mp).
>   */
> -int    xfs_attr3_leaf_to_node(struct xfs_da_args *args);
> +int    xfs_attr3_leaf_to_node(struct xfs_da_args *args, bool roll_trans);
>  int    xfs_attr3_leaf_to_shortform(struct xfs_buf *bp,
> -                                  struct xfs_da_args *args, int forkoff);
> +                       struct xfs_da_args *args, int forkoff,
> +                       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);
> --
> 2.7.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 21/27] xfsprogs: Remove single byte array from struct parent
  2018-06-10  5:07 ` [PATCH v2 21/27] xfsprogs: Remove single byte array from struct parent Allison Henderson
@ 2018-06-10 11:21   ` Amir Goldstein
  2018-06-10 15:25     ` Allison Henderson
  0 siblings, 1 reply; 51+ messages in thread
From: Amir Goldstein @ 2018-06-10 11:21 UTC (permalink / raw)
  To: Allison Henderson; +Cc: linux-xfs

On Sun, Jun 10, 2018 at 8:07 AM, Allison Henderson
<allison.henderson@oracle.com> wrote:
> Variable sized arrays implemented this way may cause
> corruptions depending on how different compilers pack
> the structure.
>
> Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
> ---
>  include/parent.h | 1 -
>  io/parent.c      | 9 ++++++---
>  2 files changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/include/parent.h b/include/parent.h
> index f338f96..85cef85 100644
> --- a/include/parent.h
> +++ b/include/parent.h
> @@ -22,7 +22,6 @@ typedef struct parent {
>         __u64   p_ino;
>         __u32   p_gen;
>         __u16   p_reclen;
> -       char    p_name[1];

How about
   char    p_name[0];

Is that also risky? keeps the code cleaner IMO.
Second best, at least have a macro to access p_name
instead of open coding ((char*)parent)+sizeof(struct parent))
all the time. First option is much better IMO.

Thanks,
Amir.

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 24/27] xfsprogs: Add parent pointers to recreated inodes
  2018-06-10  5:07 ` [PATCH v2 24/27] xfsprogs: Add parent pointers to recreated inodes Allison Henderson
@ 2018-06-10 11:27   ` Amir Goldstein
  2018-06-10 17:19     ` Allison Henderson
  2018-06-11 18:06   ` Darrick J. Wong
  1 sibling, 1 reply; 51+ messages in thread
From: Amir Goldstein @ 2018-06-10 11:27 UTC (permalink / raw)
  To: Allison Henderson; +Cc: linux-xfs

On Sun, Jun 10, 2018 at 8:07 AM, Allison Henderson
<allison.henderson@oracle.com> wrote:
> 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          | 40 +++++++++++++++++++++++++++-------------
>  2 files changed, 28 insertions(+), 13 deletions(-)
>
> diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
> index 78daca0..4b47479 100644
> --- a/libxfs/libxfs_api_defs.h
> +++ b/libxfs/libxfs_api_defs.h
> @@ -152,5 +152,6 @@
>  #define xfs_rmap_compare               libxfs_rmap_compare
>  #define xfs_dir_get_ops                        libxfs_dir_get_ops
>  #define xfs_default_ifork_ops          libxfs_default_ifork_ops
> +#define xfs_parent_add                 libxfs_parent_add
>
>  #endif /* __LIBXFS_API_DEFS_H__ */
> diff --git a/repair/phase6.c b/repair/phase6.c
> index 4fedb35..96ffade 100644
> --- a/repair/phase6.c
> +++ b/repair/phase6.c
> @@ -29,6 +29,7 @@
>  #include "dinode.h"
>  #include "progress.h"
>  #include "versions.h"
> +#include "xfs_parent.h"
>
>  static struct cred             zerocr;
>  static struct fsxattr          zerofsx;
> @@ -962,19 +963,20 @@ 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;
> -       xfs_fsblock_t   first;
> -       ino_tree_node_t *irec;
> -       int             ino_offset = 0;
> -       int             i;
> -       int             error;
> +       xfs_ino_t               ino;
> +       struct xfs_trans        *tp;
> +       struct xfs_inode        *ip;
> +       struct xfs_inode        *pip;

I guess you did some whitespace cleanups here while at it,
but why did those types change from xfs_inode_t etc?

> +       xfs_fsblock_t           first;
> +       struct ino_tree_node    *irec;
> +       int                     ino_offset = 0;
> +       int                     i;
> +       int                     error;
>         struct xfs_defer_ops    dfops;
> -       const int       mode = 0755;
> -       int             nres;
> -       struct xfs_name xname;
> +       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
> @@ -1061,7 +1063,7 @@ mk_orphanage(xfs_mount_t *mp)
>          * create the actual entry
>          */
>         error = -libxfs_dir_createname(tp, pip, &xname, ip->i_ino, &first,
> -                                       &dfops, nres, NULL);
> +                                       &dfops, nres, &offset);
>         if (error)
>                 do_error(
>                 _("can't make %s, createname error %d\n"),
> @@ -1083,6 +1085,18 @@ mk_orphanage(xfs_mount_t *mp)
>         libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
>
>         libxfs_defer_ijoin(&dfops, ip);
> +
> +        if (xfs_sb_version_hasparent(&mp->m_sb)) {
> +                error = -libxfs_parent_add(pip, ip, &xname, offset,
> +                                      &first, &dfops);
> +                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_defer_ijoin(&dfops, pip);
> +        }
> +
>         error = -libxfs_defer_finish(&tp, &dfops);
>         if (error) {
>                 do_error(_("%s directory creation failed -- bmapf error %d\n"),
> --
> 2.7.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 25/27] xfsprogs: Add parent pointers during protofile creation
  2018-06-10  5:07 ` [PATCH v2 25/27] xfsprogs: Add parent pointers during protofile creation Allison Henderson
@ 2018-06-10 11:32   ` Amir Goldstein
  2018-06-11 18:15   ` Darrick J. Wong
  1 sibling, 0 replies; 51+ messages in thread
From: Amir Goldstein @ 2018-06-10 11:32 UTC (permalink / raw)
  To: Allison Henderson; +Cc: linux-xfs

On Sun, Jun 10, 2018 at 8:07 AM, Allison Henderson
<allison.henderson@oracle.com> wrote:
> 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 | 55 ++++++++++++++++++++++++++++++++++++-------------------
>  1 file changed, 36 insertions(+), 19 deletions(-)
>
> diff --git a/mkfs/proto.c b/mkfs/proto.c
> index 67c228a..222479f 100644
> --- a/mkfs/proto.c
> +++ b/mkfs/proto.c
> @@ -19,6 +19,7 @@
>  #include "libxfs.h"
>  #include <sys/stat.h>
>  #include "xfs_multidisk.h"
> +#include "xfs_parent.h"
>
>  /*
>   * Prototypes for internal functions.
> @@ -318,23 +319,25 @@ newregfile(
>
>  static void
>  newdirent(
> -       xfs_mount_t     *mp,
> -       xfs_trans_t     *tp,
> -       xfs_inode_t     *pip,
> -       struct xfs_name *name,
> -       xfs_ino_t       inum,
> -       xfs_fsblock_t   *first,
> -       struct xfs_defer_ops    *dfops)
> +       struct xfs_mount        *mp,
> +       struct xfs_trans        *tp,
> +       struct xfs_inode        *pip,
> +       struct xfs_name         *name,

Here too. was there a reason to convert to the non typedef-ed
types?

> +       struct xfs_inode        *ip,
> +       xfs_fsblock_t           *first,
> +       struct xfs_defer_ops    *dfops,
> +       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, first, dfops, rsv,
> -                                      NULL);
> +       error = -libxfs_dir_createname(tp, pip, name, ip->i_ino, first, dfops, rsv,
> +                                      offset);
>         if (error)
>                 fail(_("directory createname error"), error);
> +
>  }
>
>  static void
> @@ -387,6 +390,7 @@ parseproto(
>         cred_t          creds;
>         char            *value;
>         struct xfs_name xname;
> +       xfs_dir2_dataptr_t offset;
>
>         memset(&creds, 0, sizeof(creds));
>         mstr = getstr(pp);
> @@ -470,7 +474,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, &first, &dfops);
> +               newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
>                 break;
>
>         case IF_RESERVED:                       /* pre-allocated space only */
> @@ -493,7 +497,7 @@ parseproto(
>                 libxfs_trans_ijoin(tp, pip, 0);
>
>                 xname.type = XFS_DIR3_FT_REG_FILE;
> -               newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops);
> +               newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
>                 libxfs_trans_log_inode(tp, ip, flags);
>
>                 libxfs_defer_ijoin(&dfops, ip);
> @@ -516,7 +520,7 @@ parseproto(
>                 }
>                 libxfs_trans_ijoin(tp, pip, 0);
>                 xname.type = XFS_DIR3_FT_BLKDEV;
> -               newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops);
> +               newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
>                 flags |= XFS_ILOG_DEV;
>                 break;
>
> @@ -530,7 +534,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, &first, &dfops);
> +               newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
>                 flags |= XFS_ILOG_DEV;
>                 break;
>
> @@ -542,7 +546,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, &first, &dfops);
> +               newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
>                 break;
>         case IF_SYMLINK:
>                 buf = getstr(pp);
> @@ -555,7 +559,7 @@ parseproto(
>                 flags |= newfile(tp, ip, &dfops, &first, 1, 1, buf, len);
>                 libxfs_trans_ijoin(tp, pip, 0);
>                 xname.type = XFS_DIR3_FT_SYMLINK;
> -               newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops);
> +               newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
>                 break;
>         case IF_DIRECTORY:
>                 tp = getres(mp, 0);
> @@ -572,8 +576,8 @@ parseproto(
>                 } else {
>                         libxfs_trans_ijoin(tp, pip, 0);
>                         xname.type = XFS_DIR3_FT_DIR;
> -                       newdirent(mp, tp, pip, &xname, ip->i_ino,
> -                                 &first, &dfops);
> +                       newdirent(mp, tp, pip, &xname, ip,
> +                                 &first, &dfops, &offset);
>                         inc_nlink(VFS_I(pip));
>                         libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE);
>                 }
> @@ -612,6 +616,19 @@ parseproto(
>                 fail(_("Error encountered creating file from prototype file"),
>                         error);
>         }
> +
> +       if (xfs_sb_version_hasparent(&mp->m_sb)) {
> +               error = xfs_parent_add(pip, ip, &xname, offset, &first, &dfops);
> +               if (error)
> +                       fail(_("Error creating parent pointer"), error);
> +
> +               libxfs_trans_log_inode(tp, ip, flags);
> +               libxfs_defer_ijoin(&dfops, ip);
> +               error = -libxfs_defer_finish(&tp, &dfops);
> +               if (error)
> +                       fail(_("Directory creation failed"), error);
> +       }
> +
>         libxfs_trans_commit(tp);
>         IRELE(ip);
>  }
> --
> 2.7.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 26/27] xfsprogs: implement the upper half of parent pointers
  2018-06-10  5:07 ` [PATCH v2 26/27] xfsprogs: implement the upper half of parent pointers Allison Henderson
@ 2018-06-10 12:06   ` Amir Goldstein
  0 siblings, 0 replies; 51+ messages in thread
From: Amir Goldstein @ 2018-06-10 12:06 UTC (permalink / raw)
  To: Allison Henderson; +Cc: linux-xfs

On Sun, Jun 10, 2018 at 8:07 AM, Allison Henderson
<allison.henderson@oracle.com> wrote:
> From: "Darrick J. Wong" <darrick.wong@oracle.com>
>
> 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.
>
> Totally missing: actual support in libxfs for working with parent ptrs
> straight off the disk (mkfs, xfs_db, xfs_repair).
>
> [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>
> ---

While I'm going through unmodified code, a nit picking comment to
Darrick:

> +
> +/* 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);
> +}
> +

If we are not using XFS_INO_ macros, at lease let's keep the aritmetic
consistent with the arithmetic used by the macros?

Thanks,
Amir.

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 21/27] xfsprogs: Remove single byte array from struct parent
  2018-06-10 11:21   ` Amir Goldstein
@ 2018-06-10 15:25     ` Allison Henderson
  0 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-10 15:25 UTC (permalink / raw)
  To: Amir Goldstein; +Cc: linux-xfs


On 06/10/2018 04:21 AM, Amir Goldstein wrote:
> On Sun, Jun 10, 2018 at 8:07 AM, Allison Henderson
> <allison.henderson@oracle.com> wrote:
>> Variable sized arrays implemented this way may cause
>> corruptions depending on how different compilers pack
>> the structure.
>>
>> Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
>> ---
>>   include/parent.h | 1 -
>>   io/parent.c      | 9 ++++++---
>>   2 files changed, 6 insertions(+), 4 deletions(-)
>>
>> diff --git a/include/parent.h b/include/parent.h
>> index f338f96..85cef85 100644
>> --- a/include/parent.h
>> +++ b/include/parent.h
>> @@ -22,7 +22,6 @@ typedef struct parent {
>>          __u64   p_ino;
>>          __u32   p_gen;
>>          __u16   p_reclen;
>> -       char    p_name[1];
> 
> How about
>     char    p_name[0];
> 
> Is that also risky? keeps the code cleaner IMO.
> Second best, at least have a macro to access p_name
> instead of open coding ((char*)parent)+sizeof(struct parent))
> all the time. First option is much better IMO.
> 
> Thanks,
> Amir.
> 

Oh yes, I think there was some discussion about not using declarations 
like that in a previous review of the set last year.  Initially I had 
applied the same logic here to sort of prepare these older structs for 
use in an alternate solution to patch 26, but then later adopted 
Darricks solution that does not require then.  I could probably drop 
this patch from the set since this code is removed in patch 27.  Thx for 
the catch though!

Allison

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 03/27] xfsprogs: Add trans toggle to attr routines
  2018-06-10  7:02   ` Amir Goldstein
@ 2018-06-10 16:19     ` Allison Henderson
  0 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-10 16:19 UTC (permalink / raw)
  To: Amir Goldstein; +Cc: linux-xfs

On 06/10/2018 12:02 AM, Amir Goldstein wrote:
> On Sun, Jun 10, 2018 at 8:07 AM, Allison Henderson
> <allison.henderson@oracle.com> wrote:
>> This patch adds a roll_trans parameter to all attribute routines.
>> Calling functions may pass true to roll transactions as normal,
>> or false to hold them.  We will need this later for delayed
>> attribute operations.
>>
>> Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
>> ---
>>   libxfs/xfs_attr.c      | 165 ++++++++++++++++++++++++++++---------------------
>>   libxfs/xfs_attr_leaf.c |  12 ++--
>>   libxfs/xfs_attr_leaf.h |  10 +--
>>   3 files changed, 108 insertions(+), 79 deletions(-)
>>
>> diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
>> index 51b567d..7ef35f3 100644
>> --- a/libxfs/xfs_attr.c
>> +++ b/libxfs/xfs_attr.c
>> @@ -50,21 +50,21 @@
>>   /*
>>    * Internal routines when attribute list fits inside the inode.
>>    */
>> -STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
>> +STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args, bool roll_trans);
>>
> 
> So "working on another solution to path 3" means folding roll_trans into
> xfs_da_args_t? if yes, then no further comments.
> 
Well, I think maybe the boolean is not the most graceful solution?  It's 
really more the result of me following my nose through a lot of tracing 
and applying a band-aid everywhere it rolled out the transaction too 
soon.  In the last revision we had talked about trying to re-roll the 
transaction by bailing out of the roll with an EAGAIN, but that is 
something I am still looking at.  I need to update my code base too (i 
think I'm still on 4.16), but I wanted to push out now and get another 
sweep of reviews before too much time gets away. :-)

>>   /*
>>    * 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);
>>
>> @@ -202,15 +202,16 @@ STATIC int
>>   xfs_attr_try_sf_addname(
>>          struct xfs_inode        *dp,
>>          struct xfs_da_args      *args,
>> -       int                     flags)
>> +       int                     flags,
>> +       bool                    roll_trans)
>>   {
>>
>>          struct xfs_mount        *mp = dp->i_mount;
>>          int                     error;
>>          int                     err2;
>>
>> -       error = xfs_attr_shortform_addname(args);
>> -       if (error != -ENOSPC) {
>> +       error = xfs_attr_shortform_addname(args, roll_trans);
>> +       if (error != -ENOSPC && roll_trans) {
>>                  /*
>>                   * Commit the shortform mods, and we're done.
>>                   * NOTE: this is also the error path
>> @@ -330,7 +331,7 @@ xfs_attr_set(
>>                   * Try to add the attr to the attribute list in
>>                   * the inode.
>>                   */
>> -               error = xfs_attr_try_sf_addname(dp, &args, flags);
>> +               error = xfs_attr_try_sf_addname(dp, &args, flags, true);
>>                  if (error != -ENOSPC) {
>>                          xfs_iunlock(dp, XFS_ILOCK_EXCL);
>>                          return error;
>> @@ -369,9 +370,9 @@ xfs_attr_set(
>>          }
>>
>>          if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
>> -               error = xfs_attr_leaf_addname(&args);
>> +               error = xfs_attr_leaf_addname(&args, true);
>>          else
>> -               error = xfs_attr_node_addname(&args);
>> +               error = xfs_attr_node_addname(&args, true);
>>          if (error)
>>                  goto out;
>>
>> @@ -466,11 +467,11 @@ xfs_attr_remove(
>>                  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);
>> +               error = xfs_attr_shortform_remove(&args, true);
>>          } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
>> -               error = xfs_attr_leaf_removename(&args);
>> +               error = xfs_attr_leaf_removename(&args, true);
>>          } else {
>> -               error = xfs_attr_node_removename(&args);
>> +               error = xfs_attr_node_removename(&args, true);
>>          }
>>
>>          if (error)
>> @@ -511,7 +512,7 @@ out:
>>    * This is the external routine.
>>    */
>>   STATIC int
>> -xfs_attr_shortform_addname(xfs_da_args_t *args)
>> +xfs_attr_shortform_addname(xfs_da_args_t *args, bool roll_trans)
>>   {
>>          int newsize, forkoff, retval;
>>
>> @@ -523,7 +524,7 @@ xfs_attr_shortform_addname(xfs_da_args_t *args)
>>          } else if (retval == -EEXIST) {
>>                  if (args->flags & ATTR_CREATE)
>>                          return retval;
>> -               retval = xfs_attr_shortform_remove(args);
>> +               retval = xfs_attr_shortform_remove(args, roll_trans);
>>                  ASSERT(retval == 0);
>>          }
>>
>> @@ -538,7 +539,7 @@ xfs_attr_shortform_addname(xfs_da_args_t *args)
>>          if (!forkoff)
>>                  return -ENOSPC;
>>
>> -       xfs_attr_shortform_add(args, forkoff);
>> +       xfs_attr_shortform_add(args, forkoff, roll_trans);
>>          return 0;
>>   }
>>
>> @@ -554,7 +555,7 @@ xfs_attr_shortform_addname(xfs_da_args_t *args)
>>    * if bmap_one_block() says there is only one block (ie: no remote blks).
>>    */
>>   STATIC int
>> -xfs_attr_leaf_addname(xfs_da_args_t *args)
>> +xfs_attr_leaf_addname(xfs_da_args_t *args, bool roll_trans)
>>   {
>>          xfs_inode_t *dp;
>>          struct xfs_buf *bp;
>> @@ -617,36 +618,42 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
>>                   * can manage its own transactions.
>>                   */
>>                  xfs_defer_init(args->dfops, args->firstblock);
>> -               error = xfs_attr3_leaf_to_node(args);
>> +               error = xfs_attr3_leaf_to_node(args, roll_trans);
>>                  if (error)
>>                          goto out_defer_cancel;
>>                  xfs_defer_ijoin(args->dfops, dp);
>> -               error = xfs_defer_finish(&args->trans, args->dfops);
>> -               if (error)
>> -                       goto out_defer_cancel;
>> +               if (roll_trans) {
>> +                       error = xfs_defer_finish(&args->trans, args->dfops);
>> +                       if (error)
>> +                               goto out_defer_cancel;
>>
>> -               /*
>> -                * Commit the current trans (including the inode) and start
>> -                * a new one.
>> -                */
>> -               error = xfs_trans_roll_inode(&args->trans, dp);
>> -               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
>> @@ -704,9 +711,11 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
>>                  /*
>>                   * If the result is small enough, shrink it all into the inode.
>>                   */
>> -               if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
>> +               if ((forkoff = xfs_attr_shortform_allfit(bp, dp)) &&
>> +                               roll_trans) {
>>                          xfs_defer_init(args->dfops, args->firstblock);
>> -                       error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
>> +                       error = xfs_attr3_leaf_to_shortform(bp, args, forkoff,
>> +                                       roll_trans);
>>                          /* bp is gone due to xfs_da_shrink_inode */
>>                          if (error)
>>                                  goto out_defer_cancel;
>> @@ -740,7 +749,7 @@ out_defer_cancel:
>>    * if bmap_one_block() says there is only one block (ie: no remote blks).
>>    */
>>   STATIC int
>> -xfs_attr_leaf_removename(xfs_da_args_t *args)
>> +xfs_attr_leaf_removename(xfs_da_args_t *args, bool roll_trans)
>>   {
>>          xfs_inode_t *dp;
>>          struct xfs_buf *bp;
>> @@ -769,15 +778,19 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
>>           * If the result is small enough, shrink it all into the inode.
>>           */
>>          if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
>> -               xfs_defer_init(args->dfops, args->firstblock);
>> -               error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
>> +               if (roll_trans)
>> +                       xfs_defer_init(args->dfops, args->firstblock);
>> +               error = xfs_attr3_leaf_to_shortform(bp, args, forkoff,
>> +                                                       roll_trans);
>>                  /* bp is gone due to xfs_da_shrink_inode */
>>                  if (error)
>>                          goto out_defer_cancel;
>>                  xfs_defer_ijoin(args->dfops, dp);
>> -               error = xfs_defer_finish(&args->trans, args->dfops);
>> -               if (error)
>> -                       goto out_defer_cancel;
>> +               if (roll_trans) {
>> +                       error = xfs_defer_finish(&args->trans, args->dfops);
>> +                       if (error)
>> +                               goto out_defer_cancel;
>> +               }
>>          }
>>          return 0;
>>   out_defer_cancel:
>> @@ -832,7 +845,7 @@ xfs_attr_leaf_get(xfs_da_args_t *args)
>>    * add a whole extra layer of confusion on top of that.
>>    */
>>   STATIC int
>> -xfs_attr_node_addname(xfs_da_args_t *args)
>> +xfs_attr_node_addname(xfs_da_args_t *args, bool roll_trans)
>>   {
>>          xfs_da_state_t *state;
>>          xfs_da_state_blk_t *blk;
>> @@ -898,21 +911,24 @@ restart:
>>                          xfs_da_state_free(state);
>>                          state = NULL;
>>                          xfs_defer_init(args->dfops, args->firstblock);
>> -                       error = xfs_attr3_leaf_to_node(args);
>> +                       error = xfs_attr3_leaf_to_node(args, roll_trans);
>>                          if (error)
>>                                  goto out_defer_cancel;
>>                          xfs_defer_ijoin(args->dfops, dp);
>> -                       error = xfs_defer_finish(&args->trans, args->dfops);
>> -                       if (error)
>> -                               goto out_defer_cancel;
>> -
>> -                       /*
>> -                        * 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,
>> +                                               args->dfops);
>> +                               if (error)
>> +                                       goto out_defer_cancel;
>> +
>> +                               /*
>> +                                * 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;
>>                  }
>> @@ -928,9 +944,11 @@ restart:
>>                  if (error)
>>                          goto out_defer_cancel;
>>                  xfs_defer_ijoin(args->dfops, dp);
>> -               error = xfs_defer_finish(&args->trans, args->dfops);
>> -               if (error)
>> -                       goto out_defer_cancel;
>> +               if (roll_trans) {
>> +                       error = xfs_defer_finish(&args->trans, args->dfops);
>> +                       if (error)
>> +                               goto out_defer_cancel;
>> +               }
>>          } else {
>>                  /*
>>                   * Addition succeeded, update Btree hashvals.
>> @@ -949,9 +967,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
>> @@ -1026,9 +1046,12 @@ restart:
>>                          if (error)
>>                                  goto out_defer_cancel;
>>                          xfs_defer_ijoin(args->dfops, dp);
>> -                       error = xfs_defer_finish(&args->trans, args->dfops);
>> -                       if (error)
>> -                               goto out_defer_cancel;
>> +                       if (roll_trans) {
>> +                               error = xfs_defer_finish(&args->trans,
>> +                                               args->dfops);
>> +                               if (error)
>> +                                       goto out_defer_cancel;
>> +                       }
>>                  }
>>
>>                  /*
>> @@ -1067,7 +1090,7 @@ out_defer_cancel:
>>    * the root node (a special case of an intermediate node).
>>    */
>>   STATIC int
>> -xfs_attr_node_removename(xfs_da_args_t *args)
>> +xfs_attr_node_removename(xfs_da_args_t *args, bool roll_trans)
>>   {
>>          xfs_da_state_t *state;
>>          xfs_da_state_blk_t *blk;
>> @@ -1176,9 +1199,11 @@ xfs_attr_node_removename(xfs_da_args_t *args)
>>                  if (error)
>>                          goto out;
>>
>> -               if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
>> +               if ((forkoff = xfs_attr_shortform_allfit(bp, dp)) &&
>> +                                       roll_trans) {
>>                          xfs_defer_init(args->dfops, args->firstblock);
>> -                       error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
>> +                       error = xfs_attr3_leaf_to_shortform(bp, args, forkoff,
>> +                                       roll_trans);
>>                          /* bp is gone due to xfs_da_shrink_inode */
>>                          if (error)
>>                                  goto out_defer_cancel;
>> diff --git a/libxfs/xfs_attr_leaf.c b/libxfs/xfs_attr_leaf.c
>> index c3682eb..ef53215 100644
>> --- a/libxfs/xfs_attr_leaf.c
>> +++ b/libxfs/xfs_attr_leaf.c
>> @@ -541,7 +541,7 @@ xfs_attr_shortform_create(xfs_da_args_t *args)
>>    * Overflow from the inode has already been checked for.
>>    */
>>   void
>> -xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff)
>> +xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff, bool roll_trans)
>>   {
>>          xfs_attr_shortform_t *sf;
>>          xfs_attr_sf_entry_t *sfe;
>> @@ -613,7 +613,7 @@ xfs_attr_fork_remove(
>>    * Remove an attribute from the shortform attribute list structure.
>>    */
>>   int
>> -xfs_attr_shortform_remove(xfs_da_args_t *args)
>> +xfs_attr_shortform_remove(xfs_da_args_t *args, bool roll_trans)
>>   {
>>          xfs_attr_shortform_t *sf;
>>          xfs_attr_sf_entry_t *sfe;
>> @@ -965,7 +965,8 @@ int
>>   xfs_attr3_leaf_to_shortform(
>>          struct xfs_buf          *bp,
>>          struct xfs_da_args      *args,
>> -       int                     forkoff)
>> +       int                     forkoff,
>> +       bool                    roll_trans)
>>   {
>>          struct xfs_attr_leafblock *leaf;
>>          struct xfs_attr3_icleaf_hdr ichdr;
>> @@ -1034,7 +1035,7 @@ xfs_attr3_leaf_to_shortform(
>>                  nargs.valuelen = be16_to_cpu(name_loc->valuelen);
>>                  nargs.hashval = be32_to_cpu(entry->hashval);
>>                  nargs.flags = XFS_ATTR_NSP_ONDISK_TO_ARGS(entry->flags);
>> -               xfs_attr_shortform_add(&nargs, forkoff);
>> +               xfs_attr_shortform_add(&nargs, forkoff, roll_trans);
>>          }
>>          error = 0;
>>
>> @@ -1048,7 +1049,8 @@ out:
>>    */
>>   int
>>   xfs_attr3_leaf_to_node(
>> -       struct xfs_da_args      *args)
>> +       struct xfs_da_args      *args,
>> +       bool                    roll_trans)
>>   {
>>          struct xfs_attr_leafblock *leaf;
>>          struct xfs_attr3_icleaf_hdr icleafhdr;
>> diff --git a/libxfs/xfs_attr_leaf.h b/libxfs/xfs_attr_leaf.h
>> index 4da08af..79c236c 100644
>> --- a/libxfs/xfs_attr_leaf.h
>> +++ b/libxfs/xfs_attr_leaf.h
>> @@ -45,12 +45,13 @@ typedef struct xfs_attr_inactive_list {
>>    * Internal routines when attribute fork size < XFS_LITINO(mp).
>>    */
>>   void   xfs_attr_shortform_create(struct xfs_da_args *args);
>> -void   xfs_attr_shortform_add(struct xfs_da_args *args, int forkoff);
>> +void   xfs_attr_shortform_add(struct xfs_da_args *args, int forkoff,
>> +                       bool roll_trans);
>>   int    xfs_attr_shortform_lookup(struct xfs_da_args *args);
>>   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_attr_shortform_remove(struct xfs_da_args *args, bool roll_trans);
>>   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);
>> @@ -59,9 +60,10 @@ void xfs_attr_fork_remove(struct xfs_inode *ip, struct xfs_trans *tp);
>>   /*
>>    * Internal routines when attribute fork size == XFS_LBSIZE(mp).
>>    */
>> -int    xfs_attr3_leaf_to_node(struct xfs_da_args *args);
>> +int    xfs_attr3_leaf_to_node(struct xfs_da_args *args, bool roll_trans);
>>   int    xfs_attr3_leaf_to_shortform(struct xfs_buf *bp,
>> -                                  struct xfs_da_args *args, int forkoff);
>> +                       struct xfs_da_args *args, int forkoff,
>> +                       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);
>> --
>> 2.7.4
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  https://urldefense.proofpoint.com/v2/url?u=http-3A__vger.kernel.org_majordomo-2Dinfo.html&d=DwIBaQ&c=RoP1YumCXCgaWHvlZYR8PZh8Bv7qIrMUB65eapI_JnE&r=LHZQ8fHvy6wDKXGTWcm97burZH5sQKHRDMaY1UthQxc&m=4T_oG8VHnaL8I5DKuoJ84kc5w28til1Dib_6WuBJnnA&s=WuTPogezCUjTLZLd4sppEhtNBAwBUVSwlctPWtH9H50&e=
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  https://urldefense.proofpoint.com/v2/url?u=http-3A__vger.kernel.org_majordomo-2Dinfo.html&d=DwIBaQ&c=RoP1YumCXCgaWHvlZYR8PZh8Bv7qIrMUB65eapI_JnE&r=LHZQ8fHvy6wDKXGTWcm97burZH5sQKHRDMaY1UthQxc&m=4T_oG8VHnaL8I5DKuoJ84kc5w28til1Dib_6WuBJnnA&s=WuTPogezCUjTLZLd4sppEhtNBAwBUVSwlctPWtH9H50&e=
> 

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 24/27] xfsprogs: Add parent pointers to recreated inodes
  2018-06-10 11:27   ` Amir Goldstein
@ 2018-06-10 17:19     ` Allison Henderson
  2018-06-11 17:31       ` Darrick J. Wong
  0 siblings, 1 reply; 51+ messages in thread
From: Allison Henderson @ 2018-06-10 17:19 UTC (permalink / raw)
  To: Amir Goldstein; +Cc: linux-xfs

On 06/10/2018 04:27 AM, Amir Goldstein wrote:
> On Sun, Jun 10, 2018 at 8:07 AM, Allison Henderson
> <allison.henderson@oracle.com> wrote:
>> 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          | 40 +++++++++++++++++++++++++++-------------
>>   2 files changed, 28 insertions(+), 13 deletions(-)
>>
>> diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
>> index 78daca0..4b47479 100644
>> --- a/libxfs/libxfs_api_defs.h
>> +++ b/libxfs/libxfs_api_defs.h
>> @@ -152,5 +152,6 @@
>>   #define xfs_rmap_compare               libxfs_rmap_compare
>>   #define xfs_dir_get_ops                        libxfs_dir_get_ops
>>   #define xfs_default_ifork_ops          libxfs_default_ifork_ops
>> +#define xfs_parent_add                 libxfs_parent_add
>>
>>   #endif /* __LIBXFS_API_DEFS_H__ */
>> diff --git a/repair/phase6.c b/repair/phase6.c
>> index 4fedb35..96ffade 100644
>> --- a/repair/phase6.c
>> +++ b/repair/phase6.c
>> @@ -29,6 +29,7 @@
>>   #include "dinode.h"
>>   #include "progress.h"
>>   #include "versions.h"
>> +#include "xfs_parent.h"
>>
>>   static struct cred             zerocr;
>>   static struct fsxattr          zerofsx;
>> @@ -962,19 +963,20 @@ 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;
>> -       xfs_fsblock_t   first;
>> -       ino_tree_node_t *irec;
>> -       int             ino_offset = 0;
>> -       int             i;
>> -       int             error;
>> +       xfs_ino_t               ino;
>> +       struct xfs_trans        *tp;
>> +       struct xfs_inode        *ip;
>> +       struct xfs_inode        *pip;
> 
> I guess you did some whitespace cleanups here while at it,
> but why did those types change from xfs_inode_t etc?

Yes, removing the *_t types where appropriate was something that came up 
in a few of the earlier reviews.  I just assumed we are trying to clear 
them all out?  It does seem to kind of help distinguish whats a 
structure and whats a primitive data type.

Allison


> 
>> +       xfs_fsblock_t           first;
>> +       struct ino_tree_node    *irec;
>> +       int                     ino_offset = 0;
>> +       int                     i;
>> +       int                     error;
>>          struct xfs_defer_ops    dfops;
>> -       const int       mode = 0755;
>> -       int             nres;
>> -       struct xfs_name xname;
>> +       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
>> @@ -1061,7 +1063,7 @@ mk_orphanage(xfs_mount_t *mp)
>>           * create the actual entry
>>           */
>>          error = -libxfs_dir_createname(tp, pip, &xname, ip->i_ino, &first,
>> -                                       &dfops, nres, NULL);
>> +                                       &dfops, nres, &offset);
>>          if (error)
>>                  do_error(
>>                  _("can't make %s, createname error %d\n"),
>> @@ -1083,6 +1085,18 @@ mk_orphanage(xfs_mount_t *mp)
>>          libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
>>
>>          libxfs_defer_ijoin(&dfops, ip);
>> +
>> +        if (xfs_sb_version_hasparent(&mp->m_sb)) {
>> +                error = -libxfs_parent_add(pip, ip, &xname, offset,
>> +                                      &first, &dfops);
>> +                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_defer_ijoin(&dfops, pip);
>> +        }
>> +
>>          error = -libxfs_defer_finish(&tp, &dfops);
>>          if (error) {
>>                  do_error(_("%s directory creation failed -- bmapf error %d\n"),
>> --
>> 2.7.4
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  https://urldefense.proofpoint.com/v2/url?u=http-3A__vger.kernel.org_majordomo-2Dinfo.html&d=DwIBaQ&c=RoP1YumCXCgaWHvlZYR8PZh8Bv7qIrMUB65eapI_JnE&r=LHZQ8fHvy6wDKXGTWcm97burZH5sQKHRDMaY1UthQxc&m=G-6Ft7goE2Cf-mpLlEpFZl98e-5uBpekKLRKZzIJTXE&s=SbB24E7j4VibOio0puyqOZPpxpfyIMm0xJ2wF-rltDA&e=

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 19/27] xfsprogs: Add delayed attributes error tag
  2018-06-10  5:07 ` [PATCH v2 19/27] xfsprogs: Add delayed attributes error tag Allison Henderson
@ 2018-06-11 17:28   ` Darrick J. Wong
  2018-06-11 19:59     ` Allison Henderson
  0 siblings, 1 reply; 51+ messages in thread
From: Darrick J. Wong @ 2018-06-11 17:28 UTC (permalink / raw)
  To: Allison Henderson; +Cc: linux-xfs

> Subject: [PATCH v2 19/27] xfsprogs: Add delayed attributes error tag

Please identify the tool name in the subject when possible, e.g.

[PATCH v2 19/27] xfs_io: Add delayed attributes error tag

Otherwise looks ok, though in the end I suspect the xfs_errortag.h chunk
will be ported in from the kernel patch and this will be a separate
patch with just the xfs_io part.

Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>

--D


On Sat, Jun 09, 2018 at 10:07:44PM -0700, Allison Henderson wrote:
> Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
> ---
>  io/inject.c           | 1 +
>  libxfs/xfs_errortag.h | 5 ++++-
>  2 files changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/io/inject.c b/io/inject.c
> index fc3cf25..2d6cc9c 100644
> --- a/io/inject.c
> +++ b/io/inject.c
> @@ -63,6 +63,7 @@ error_tag(char *name)
>  		{ XFS_ERRTAG_LOG_BAD_CRC,		"log_bad_crc" },
>  		{ XFS_ERRTAG_LOG_ITEM_PIN,		"log_item_pin" },
>  		{ XFS_ERRTAG_BUF_LRU_REF,		"buf_lru_ref" },
> +		{ 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 bc1789d..f606ab6 100644
> --- a/libxfs/xfs_errortag.h
> +++ b/libxfs/xfs_errortag.h
> @@ -65,7 +65,8 @@
>  #define XFS_ERRTAG_LOG_BAD_CRC				29
>  #define XFS_ERRTAG_LOG_ITEM_PIN				30
>  #define XFS_ERRTAG_BUF_LRU_REF				31
> -#define XFS_ERRTAG_MAX					32
> +#define XFS_ERRTAG_DELAYED_ATTR			32
> +#define XFS_ERRTAG_MAX					33
>  
>  /*
>   * Random factors for above tags, 1 means always, 2 means 1/2 time, etc.
> @@ -102,5 +103,7 @@
>  #define XFS_RANDOM_LOG_BAD_CRC				1
>  #define XFS_RANDOM_LOG_ITEM_PIN				1
>  #define XFS_RANDOM_BUF_LRU_REF				2
> +#define XFS_RANDOM_DELAYED_ATTR			1
>  
>  #endif /* __XFS_ERRORTAG_H_ */
> +
> -- 
> 2.7.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 24/27] xfsprogs: Add parent pointers to recreated inodes
  2018-06-10 17:19     ` Allison Henderson
@ 2018-06-11 17:31       ` Darrick J. Wong
  0 siblings, 0 replies; 51+ messages in thread
From: Darrick J. Wong @ 2018-06-11 17:31 UTC (permalink / raw)
  To: Allison Henderson; +Cc: Amir Goldstein, linux-xfs

On Sun, Jun 10, 2018 at 10:19:48AM -0700, Allison Henderson wrote:
> On 06/10/2018 04:27 AM, Amir Goldstein wrote:
> > On Sun, Jun 10, 2018 at 8:07 AM, Allison Henderson
> > <allison.henderson@oracle.com> wrote:
> > > 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          | 40 +++++++++++++++++++++++++++-------------
> > >   2 files changed, 28 insertions(+), 13 deletions(-)
> > > 
> > > diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
> > > index 78daca0..4b47479 100644
> > > --- a/libxfs/libxfs_api_defs.h
> > > +++ b/libxfs/libxfs_api_defs.h
> > > @@ -152,5 +152,6 @@
> > >   #define xfs_rmap_compare               libxfs_rmap_compare
> > >   #define xfs_dir_get_ops                        libxfs_dir_get_ops
> > >   #define xfs_default_ifork_ops          libxfs_default_ifork_ops
> > > +#define xfs_parent_add                 libxfs_parent_add
> > > 
> > >   #endif /* __LIBXFS_API_DEFS_H__ */
> > > diff --git a/repair/phase6.c b/repair/phase6.c
> > > index 4fedb35..96ffade 100644
> > > --- a/repair/phase6.c
> > > +++ b/repair/phase6.c
> > > @@ -29,6 +29,7 @@
> > >   #include "dinode.h"
> > >   #include "progress.h"
> > >   #include "versions.h"
> > > +#include "xfs_parent.h"
> > > 
> > >   static struct cred             zerocr;
> > >   static struct fsxattr          zerofsx;
> > > @@ -962,19 +963,20 @@ 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;
> > > -       xfs_fsblock_t   first;
> > > -       ino_tree_node_t *irec;
> > > -       int             ino_offset = 0;
> > > -       int             i;
> > > -       int             error;
> > > +       xfs_ino_t               ino;
> > > +       struct xfs_trans        *tp;
> > > +       struct xfs_inode        *ip;
> > > +       struct xfs_inode        *pip;
> > 
> > I guess you did some whitespace cleanups here while at it,
> > but why did those types change from xfs_inode_t etc?
> 
> Yes, removing the *_t types where appropriate was something that came up in
> a few of the earlier reviews.  I just assumed we are trying to clear them
> all out?  It does seem to kind of help distinguish whats a structure and
> whats a primitive data type.

Yes, the general practice (afaict) is to de-typedef-ify code when making
changes to them.

--D

> Allison
> 
> 
> > 
> > > +       xfs_fsblock_t           first;
> > > +       struct ino_tree_node    *irec;
> > > +       int                     ino_offset = 0;
> > > +       int                     i;
> > > +       int                     error;
> > >          struct xfs_defer_ops    dfops;
> > > -       const int       mode = 0755;
> > > -       int             nres;
> > > -       struct xfs_name xname;
> > > +       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
> > > @@ -1061,7 +1063,7 @@ mk_orphanage(xfs_mount_t *mp)
> > >           * create the actual entry
> > >           */
> > >          error = -libxfs_dir_createname(tp, pip, &xname, ip->i_ino, &first,
> > > -                                       &dfops, nres, NULL);
> > > +                                       &dfops, nres, &offset);
> > >          if (error)
> > >                  do_error(
> > >                  _("can't make %s, createname error %d\n"),
> > > @@ -1083,6 +1085,18 @@ mk_orphanage(xfs_mount_t *mp)
> > >          libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
> > > 
> > >          libxfs_defer_ijoin(&dfops, ip);
> > > +
> > > +        if (xfs_sb_version_hasparent(&mp->m_sb)) {
> > > +                error = -libxfs_parent_add(pip, ip, &xname, offset,
> > > +                                      &first, &dfops);
> > > +                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_defer_ijoin(&dfops, pip);
> > > +        }
> > > +
> > >          error = -libxfs_defer_finish(&tp, &dfops);
> > >          if (error) {
> > >                  do_error(_("%s directory creation failed -- bmapf error %d\n"),
> > > --
> > > 2.7.4
> > > 
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> > > the body of a message to majordomo@vger.kernel.org
> > > More majordomo info at  https://urldefense.proofpoint.com/v2/url?u=http-3A__vger.kernel.org_majordomo-2Dinfo.html&d=DwIBaQ&c=RoP1YumCXCgaWHvlZYR8PZh8Bv7qIrMUB65eapI_JnE&r=LHZQ8fHvy6wDKXGTWcm97burZH5sQKHRDMaY1UthQxc&m=G-6Ft7goE2Cf-mpLlEpFZl98e-5uBpekKLRKZzIJTXE&s=SbB24E7j4VibOio0puyqOZPpxpfyIMm0xJ2wF-rltDA&e=
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 20/27] xfsprogs: Add parent pointer flag to cmd
  2018-06-10  5:07 ` [PATCH v2 20/27] xfsprogs: Add parent pointer flag to cmd Allison Henderson
@ 2018-06-11 17:43   ` Darrick J. Wong
  2018-06-11 20:00     ` Allison Henderson
  0 siblings, 1 reply; 51+ messages in thread
From: Darrick J. Wong @ 2018-06-11 17:43 UTC (permalink / raw)
  To: Allison Henderson; +Cc: linux-xfs

On Sat, Jun 09, 2018 at 10:07:45PM -0700, Allison Henderson wrote:
> 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 | 15 ++++++++++++++-
>  1 file changed, 14 insertions(+), 1 deletion(-)
> 
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index 78d0ce5..b9a8b00 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -104,6 +104,7 @@ enum {
>  	N_SIZE = 0,
>  	N_VERSION,
>  	N_FTYPE,
> +	N_PARENT,
>  	N_MAX_OPTS,
>  };
>  
> @@ -550,6 +551,7 @@ struct opt_params nopts = {
>  		[N_SIZE] = "size",
>  		[N_VERSION] = "version",
>  		[N_FTYPE] = "ftype",
> +		[N_PARENT] = "parent",
>  	},
>  	.subopt_params = {
>  		{ .index = N_SIZE,
> @@ -572,6 +574,12 @@ struct opt_params nopts = {
>  		  .maxval = 1,
>  		  .defaultval = 1,
>  		},
> +		{ .index = N_PARENT,
> +		  .conflicts = { { NULL, LAST_CONFLICT } },
> +		  .minval = 0,
> +		  .maxval = 1,
> +		  .defaultval = 1,
> +		},
>  	},
>  };
>  
> @@ -876,7 +884,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\
> @@ -1615,6 +1623,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;
>  	}

validate_sb_features() needs to disallow parent pointers on v4
filesystems.  See "reflink not supported without CRC support" around
xfs_mkfs.c line 2015.

--D

> @@ -2887,6 +2898,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
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 23/27] xfsprogs: Do not use namechecks on parent pointers
  2018-06-10  5:07 ` [PATCH v2 23/27] xfsprogs: Do not use namechecks on parent pointers Allison Henderson
@ 2018-06-11 18:00   ` Darrick J. Wong
  2018-06-11 20:00     ` Allison Henderson
  0 siblings, 1 reply; 51+ messages in thread
From: Darrick J. Wong @ 2018-06-11 18:00 UTC (permalink / raw)
  To: Allison Henderson; +Cc: linux-xfs

On Sat, Jun 09, 2018 at 10:07:48PM -0700, Allison Henderson wrote:
> Attribute names of parent pointers are not strings.  So
> avoid doing namechecks for these attributes.
> 
> Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
> ---
>  repair/attr_repair.c | 18 +++++++++++-------
>  1 file changed, 11 insertions(+), 7 deletions(-)
> 
> diff --git a/repair/attr_repair.c b/repair/attr_repair.c
> index 8b1b8a7..b8b0768 100644
> --- a/repair/attr_repair.c
> +++ b/repair/attr_repair.c
> @@ -308,8 +308,9 @@ process_shortform_attr(
>  		/* namecheck checks for / and null terminated for file names.
>  		 * attributes names currently follow the same rules.
>  		*/
> -		if (namecheck((char *)&currententry->nameval[0],
> -						currententry->namelen))  {
> +		if (!(currententry->flags & XFS_ATTR_PARENT) &&
> +			namecheck((char *)&currententry->nameval[0],
> +			currententry->namelen))  {
>  			do_warn(

Please don't indent the condition tests to the same column as the code.
Either line them up with the if parentheses or double-tab them.

if (!(currententry->flags & XFS_ATTR_PARENT) &&
    namecheck((char *)&currententry->nameval[0],
		currententry->namelen)) {
	do_warn(...);
}

>  	_("entry contains illegal character in shortform attribute name\n"));
>  			junkit = 1;
> @@ -470,8 +471,9 @@ 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 (!(entry->flags & XFS_ATTR_PARENT) &&
> +		(local->namelen == 0 || namecheck((char *)&local->nameval[0],
> +		local->namelen))) {

Why skip the namelen checks when it's a parent pointer?  Isn't the pptr
corrupt if the (ino, gen, offset) data is length zero?

>  		do_warn(
>  	_("attribute entry %d in attr block %u, inode %" PRIu64 " has bad name (namelen = %d)\n"),
>  			i, da_bno, ino, local->namelen);
> @@ -525,13 +527,15 @@ process_leaf_attr_remote(
>  
>  	remotep = xfs_attr3_leaf_name_remote(leaf, i);
>  
> -	if (remotep->namelen == 0 || namecheck((char *)&remotep->name[0],
> -						remotep->namelen) ||
> +	if (!(entry->flags & XFS_ATTR_PARENT) &&
> +			(remotep->namelen == 0 ||
> +			namecheck((char *)&remotep->name[0],
> +				remotep->namelen) ||
>  			be32_to_cpu(entry->hashval) !=
>  				libxfs_da_hashname((unsigned char *)&remotep->name[0],
>  						remotep->namelen) ||
>  			be32_to_cpu(entry->hashval) < last_hashval ||
> -			be32_to_cpu(remotep->valueblk) == 0) {
> +			be32_to_cpu(remotep->valueblk) == 0)) {

Do parent pointer attrs ever end up using a remote value block to store
the name?  If so, I think you only want to skip the namecheck, not the
namelen/hashval/valueblk checks, right?

--D

>  		do_warn(
>  	_("inconsistent remote attribute entry %d in attr block %u, ino %" PRIu64 "\n"), i, da_bno, ino);
>  		return -1;
> -- 
> 2.7.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 24/27] xfsprogs: Add parent pointers to recreated inodes
  2018-06-10  5:07 ` [PATCH v2 24/27] xfsprogs: Add parent pointers to recreated inodes Allison Henderson
  2018-06-10 11:27   ` Amir Goldstein
@ 2018-06-11 18:06   ` Darrick J. Wong
  2018-06-11 20:00     ` Allison Henderson
  1 sibling, 1 reply; 51+ messages in thread
From: Darrick J. Wong @ 2018-06-11 18:06 UTC (permalink / raw)
  To: Allison Henderson; +Cc: linux-xfs

On Sat, Jun 09, 2018 at 10:07:49PM -0700, Allison Henderson wrote:
> 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          | 40 +++++++++++++++++++++++++++-------------
>  2 files changed, 28 insertions(+), 13 deletions(-)
> 
> diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
> index 78daca0..4b47479 100644
> --- a/libxfs/libxfs_api_defs.h
> +++ b/libxfs/libxfs_api_defs.h
> @@ -152,5 +152,6 @@
>  #define xfs_rmap_compare		libxfs_rmap_compare
>  #define xfs_dir_get_ops			libxfs_dir_get_ops
>  #define xfs_default_ifork_ops		libxfs_default_ifork_ops
> +#define xfs_parent_add    		libxfs_parent_add
>  
>  #endif /* __LIBXFS_API_DEFS_H__ */
> diff --git a/repair/phase6.c b/repair/phase6.c
> index 4fedb35..96ffade 100644
> --- a/repair/phase6.c
> +++ b/repair/phase6.c
> @@ -29,6 +29,7 @@
>  #include "dinode.h"
>  #include "progress.h"
>  #include "versions.h"
> +#include "xfs_parent.h"
>  
>  static struct cred		zerocr;
>  static struct fsxattr 		zerofsx;
> @@ -962,19 +963,20 @@ 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;
> -	xfs_fsblock_t	first;
> -	ino_tree_node_t	*irec;
> -	int		ino_offset = 0;
> -	int		i;
> -	int		error;
> +	xfs_ino_t		ino;
> +	struct xfs_trans	*tp;
> +	struct xfs_inode	*ip;
> +	struct xfs_inode	*pip;
> +	xfs_fsblock_t		first;
> +	struct ino_tree_node	*irec;
> +	int			ino_offset = 0;
> +	int			i;
> +	int			error;
>  	struct xfs_defer_ops	dfops;
> -	const int	mode = 0755;
> -	int		nres;
> -	struct xfs_name	xname;
> +	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
> @@ -1061,7 +1063,7 @@ mk_orphanage(xfs_mount_t *mp)
>  	 * create the actual entry
>  	 */
>  	error = -libxfs_dir_createname(tp, pip, &xname, ip->i_ino, &first,
> -					&dfops, nres, NULL);
> +					&dfops, nres, &offset);
>  	if (error)
>  		do_error(
>  		_("can't make %s, createname error %d\n"),
> @@ -1083,6 +1085,18 @@ mk_orphanage(xfs_mount_t *mp)
>  	libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
>  
>  	libxfs_defer_ijoin(&dfops, ip);
> +
> +        if (xfs_sb_version_hasparent(&mp->m_sb)) {
> +                error = -libxfs_parent_add(pip, ip, &xname, offset,

Tabs, not spaces for the indenting.

> +				       &first, &dfops);
> +                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_defer_ijoin(&dfops, pip);

/me wonders if it's really necessary to _defer_ijoin either of the
inodes to the transaction since we commit and IRELE both of them
immediately afterwards...

--D

> +        }
> +
>  	error = -libxfs_defer_finish(&tp, &dfops);
>  	if (error) {
>  		do_error(_("%s directory creation failed -- bmapf error %d\n"),
> -- 
> 2.7.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 25/27] xfsprogs: Add parent pointers during protofile creation
  2018-06-10  5:07 ` [PATCH v2 25/27] xfsprogs: Add parent pointers during protofile creation Allison Henderson
  2018-06-10 11:32   ` Amir Goldstein
@ 2018-06-11 18:15   ` Darrick J. Wong
  2018-06-11 19:58     ` Allison Henderson
  1 sibling, 1 reply; 51+ messages in thread
From: Darrick J. Wong @ 2018-06-11 18:15 UTC (permalink / raw)
  To: Allison Henderson; +Cc: linux-xfs

On Sat, Jun 09, 2018 at 10:07:50PM -0700, Allison Henderson wrote:
> 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 | 55 ++++++++++++++++++++++++++++++++++++-------------------
>  1 file changed, 36 insertions(+), 19 deletions(-)
> 
> diff --git a/mkfs/proto.c b/mkfs/proto.c
> index 67c228a..222479f 100644
> --- a/mkfs/proto.c
> +++ b/mkfs/proto.c
> @@ -19,6 +19,7 @@
>  #include "libxfs.h"
>  #include <sys/stat.h>
>  #include "xfs_multidisk.h"
> +#include "xfs_parent.h"
>  
>  /*
>   * Prototypes for internal functions.
> @@ -318,23 +319,25 @@ newregfile(
>  
>  static void
>  newdirent(
> -	xfs_mount_t	*mp,
> -	xfs_trans_t	*tp,
> -	xfs_inode_t	*pip,
> -	struct xfs_name	*name,
> -	xfs_ino_t	inum,
> -	xfs_fsblock_t	*first,
> -	struct xfs_defer_ops	*dfops)
> +	struct xfs_mount	*mp,
> +	struct xfs_trans	*tp,
> +	struct xfs_inode	*pip,
> +	struct xfs_name		*name,
> +	struct xfs_inode	*ip,
> +	xfs_fsblock_t		*first,
> +	struct xfs_defer_ops	*dfops,
> +	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, first, dfops, rsv,
> -				       NULL);
> +	error = -libxfs_dir_createname(tp, pip, name, ip->i_ino, first, dfops, rsv,
> +				       offset);

This line is over 80 characters, please just rewrap the whole thing:

	error = -libxfs_dir_createname(tp, pip, name, ip->i_ino, first, dfops,
			rsv, offset);

>  	if (error)
>  		fail(_("directory createname error"), error);
> +
>  }
>  
>  static void
> @@ -387,6 +390,7 @@ parseproto(
>  	cred_t		creds;
>  	char		*value;
>  	struct xfs_name	xname;
> +	xfs_dir2_dataptr_t offset;
>  
>  	memset(&creds, 0, sizeof(creds));
>  	mstr = getstr(pp);
> @@ -470,7 +474,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, &first, &dfops);
> +		newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
>  		break;
>  
>  	case IF_RESERVED:			/* pre-allocated space only */
> @@ -493,7 +497,7 @@ parseproto(
>  		libxfs_trans_ijoin(tp, pip, 0);
>  
>  		xname.type = XFS_DIR3_FT_REG_FILE;
> -		newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops);
> +		newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
>  		libxfs_trans_log_inode(tp, ip, flags);
>  
>  		libxfs_defer_ijoin(&dfops, ip);
> @@ -516,7 +520,7 @@ parseproto(
>  		}
>  		libxfs_trans_ijoin(tp, pip, 0);
>  		xname.type = XFS_DIR3_FT_BLKDEV;
> -		newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops);
> +		newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
>  		flags |= XFS_ILOG_DEV;
>  		break;
>  
> @@ -530,7 +534,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, &first, &dfops);
> +		newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
>  		flags |= XFS_ILOG_DEV;
>  		break;
>  
> @@ -542,7 +546,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, &first, &dfops);
> +		newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
>  		break;
>  	case IF_SYMLINK:
>  		buf = getstr(pp);
> @@ -555,7 +559,7 @@ parseproto(
>  		flags |= newfile(tp, ip, &dfops, &first, 1, 1, buf, len);
>  		libxfs_trans_ijoin(tp, pip, 0);
>  		xname.type = XFS_DIR3_FT_SYMLINK;
> -		newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops);
> +		newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
>  		break;
>  	case IF_DIRECTORY:
>  		tp = getres(mp, 0);
> @@ -572,8 +576,8 @@ parseproto(
>  		} else {
>  			libxfs_trans_ijoin(tp, pip, 0);
>  			xname.type = XFS_DIR3_FT_DIR;
> -			newdirent(mp, tp, pip, &xname, ip->i_ino,
> -				  &first, &dfops);
> +			newdirent(mp, tp, pip, &xname, ip,
> +				  &first, &dfops, &offset);
>  			inc_nlink(VFS_I(pip));
>  			libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE);
>  		}
> @@ -612,6 +616,19 @@ parseproto(
>  		fail(_("Error encountered creating file from prototype file"),
>  			error);
>  	}
> +
> +	if (xfs_sb_version_hasparent(&mp->m_sb)) {
> +		error = xfs_parent_add(pip, ip, &xname, offset, &first, &dfops);

Didn't we just _defer_finish(&dfops) in the hunk right above this?  Why
not add the deferred pptr before the first _defer_finish call?

--D

> +		if (error)
> +			fail(_("Error creating parent pointer"), error);
> +
> +		libxfs_trans_log_inode(tp, ip, flags);
> +		libxfs_defer_ijoin(&dfops, ip);
> +		error = -libxfs_defer_finish(&tp, &dfops);
> +		if (error)
> +			fail(_("Directory creation failed"), error);
> +	}
> +
>  	libxfs_trans_commit(tp);
>  	IRELE(ip);
>  }
> -- 
> 2.7.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 27/27] xfsprogs: Clean up old parent pointer definitions
  2018-06-10  5:07 ` [PATCH v2 27/27] xfsprogs: Clean up old parent pointer definitions Allison Henderson
@ 2018-06-11 18:20   ` Darrick J. Wong
  2018-06-11 20:06     ` Allison Henderson
  0 siblings, 1 reply; 51+ messages in thread
From: Darrick J. Wong @ 2018-06-11 18:20 UTC (permalink / raw)
  To: Allison Henderson; +Cc: linux-xfs

On Sat, Jun 09, 2018 at 10:07:52PM -0700, Allison Henderson wrote:
> Existing parent pointer stubs and structs are not used in this
> implementation.  Remove uneeded definitions.
> 
> Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
> ---
>  include/parent.h   | 10 ----------
>  libhandle/handle.c | 26 --------------------------
>  libhandle/jdm.c    | 20 --------------------
>  3 files changed, 56 deletions(-)
> 
> diff --git a/include/parent.h b/include/parent.h
> index 33f8d85..5665d64 100644
> --- a/include/parent.h
> +++ b/include/parent.h
> @@ -18,16 +18,6 @@
>  #ifndef __PARENT_H__
>  #define	__PARENT_H__
>  
> -typedef struct parent {
> -	__u64	p_ino;
> -	__u32	p_gen;
> -	__u16	p_reclen;
> -} parent_t;
> -
> -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,
> diff --git a/libhandle/handle.c b/libhandle/handle.c
> index a70fa32..862b943 100644
> --- a/libhandle/handle.c
> +++ b/libhandle/handle.c
> @@ -20,7 +20,6 @@
>  #include "platform_defs.h"
>  #include "xfs.h"
>  #include "handle.h"
> -#include "parent.h"
>  
>  /* just pick a value we know is more than big enough */
>  #define	MAXHANSIZ	64
> @@ -422,31 +421,6 @@ attr_list_by_handle(
>  }
>  
>  int
> -parents_by_handle(
> -	void		*hanp,
> -	size_t		hlen,
> -	parent_t	*buf,
> -	size_t		bufsiz,
> -	unsigned int	*count)
> -
> -{
> -	errno = EOPNOTSUPP;
> -	return -1;
> -}

You probably need to scrape the declarations out of the header files
because otherwise any program that thinks it wants to use this will
compile ok but barf on unresolved symbols in the linker phase.

There's a murkier question here about how do we handle deprecating these
libhandle APIs that have never been usable on Linux?

--D

> -
> -int
> -parentpaths_by_handle(
> -	void		*hanp,
> -	size_t		hlen,
> -	parent_t	*buf,
> -	size_t		bufsiz,
> -	unsigned int	*count)
> -{
> -	errno = EOPNOTSUPP;
> -	return -1;
> -}
> -
> -int
>  fssetdm_by_handle(
>  	void		*hanp,
>  	size_t		hlen,
> diff --git a/libhandle/jdm.c b/libhandle/jdm.c
> index 821061b..0c2440b 100644
> --- a/libhandle/jdm.c
> +++ b/libhandle/jdm.c
> @@ -20,7 +20,6 @@
>  #include "xfs.h"
>  #include "handle.h"
>  #include "jdm.h"
> -#include "parent.h"
>  
>  /* internal fshandle - typecast to a void for external use */
>  #define FSHANDLE_SZ		8
> @@ -178,22 +177,3 @@ jdm_attr_list(	jdm_fshandle_t *fshp,
>  	return rval;
>  }
>  
> -int
> -jdm_parents( jdm_fshandle_t *fshp,
> -		xfs_bstat_t *statp,
> -		parent_t *bufp, size_t bufsz,
> -		unsigned int *count)
> -{
> -	errno = EOPNOTSUPP;
> -	return -1;
> -}
> -
> -int
> -jdm_parentpaths( jdm_fshandle_t *fshp,
> -		xfs_bstat_t *statp,
> -		parent_t *bufp, size_t bufsz,
> -		unsigned int *count)
> -{
> -	errno = EOPNOTSUPP;
> -	return -1;
> -}
> -- 
> 2.7.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 25/27] xfsprogs: Add parent pointers during protofile creation
  2018-06-11 18:15   ` Darrick J. Wong
@ 2018-06-11 19:58     ` Allison Henderson
  0 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-11 19:58 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs

On 06/11/2018 11:15 AM, Darrick J. Wong wrote:
> On Sat, Jun 09, 2018 at 10:07:50PM -0700, Allison Henderson wrote:
>> 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 | 55 ++++++++++++++++++++++++++++++++++++-------------------
>>   1 file changed, 36 insertions(+), 19 deletions(-)
>>
>> diff --git a/mkfs/proto.c b/mkfs/proto.c
>> index 67c228a..222479f 100644
>> --- a/mkfs/proto.c
>> +++ b/mkfs/proto.c
>> @@ -19,6 +19,7 @@
>>   #include "libxfs.h"
>>   #include <sys/stat.h>
>>   #include "xfs_multidisk.h"
>> +#include "xfs_parent.h"
>>   
>>   /*
>>    * Prototypes for internal functions.
>> @@ -318,23 +319,25 @@ newregfile(
>>   
>>   static void
>>   newdirent(
>> -	xfs_mount_t	*mp,
>> -	xfs_trans_t	*tp,
>> -	xfs_inode_t	*pip,
>> -	struct xfs_name	*name,
>> -	xfs_ino_t	inum,
>> -	xfs_fsblock_t	*first,
>> -	struct xfs_defer_ops	*dfops)
>> +	struct xfs_mount	*mp,
>> +	struct xfs_trans	*tp,
>> +	struct xfs_inode	*pip,
>> +	struct xfs_name		*name,
>> +	struct xfs_inode	*ip,
>> +	xfs_fsblock_t		*first,
>> +	struct xfs_defer_ops	*dfops,
>> +	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, first, dfops, rsv,
>> -				       NULL);
>> +	error = -libxfs_dir_createname(tp, pip, name, ip->i_ino, first, dfops, rsv,
>> +				       offset);
> 
> This line is over 80 characters, please just rewrap the whole thing:
> 
> 	error = -libxfs_dir_createname(tp, pip, name, ip->i_ino, first, dfops,
> 			rsv, offset);
> 
>>   	if (error)
>>   		fail(_("directory createname error"), error);
>> +
>>   }
>>   
>>   static void
>> @@ -387,6 +390,7 @@ parseproto(
>>   	cred_t		creds;
>>   	char		*value;
>>   	struct xfs_name	xname;
>> +	xfs_dir2_dataptr_t offset;
>>   
>>   	memset(&creds, 0, sizeof(creds));
>>   	mstr = getstr(pp);
>> @@ -470,7 +474,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, &first, &dfops);
>> +		newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
>>   		break;
>>   
>>   	case IF_RESERVED:			/* pre-allocated space only */
>> @@ -493,7 +497,7 @@ parseproto(
>>   		libxfs_trans_ijoin(tp, pip, 0);
>>   
>>   		xname.type = XFS_DIR3_FT_REG_FILE;
>> -		newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops);
>> +		newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
>>   		libxfs_trans_log_inode(tp, ip, flags);
>>   
>>   		libxfs_defer_ijoin(&dfops, ip);
>> @@ -516,7 +520,7 @@ parseproto(
>>   		}
>>   		libxfs_trans_ijoin(tp, pip, 0);
>>   		xname.type = XFS_DIR3_FT_BLKDEV;
>> -		newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops);
>> +		newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
>>   		flags |= XFS_ILOG_DEV;
>>   		break;
>>   
>> @@ -530,7 +534,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, &first, &dfops);
>> +		newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
>>   		flags |= XFS_ILOG_DEV;
>>   		break;
>>   
>> @@ -542,7 +546,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, &first, &dfops);
>> +		newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
>>   		break;
>>   	case IF_SYMLINK:
>>   		buf = getstr(pp);
>> @@ -555,7 +559,7 @@ parseproto(
>>   		flags |= newfile(tp, ip, &dfops, &first, 1, 1, buf, len);
>>   		libxfs_trans_ijoin(tp, pip, 0);
>>   		xname.type = XFS_DIR3_FT_SYMLINK;
>> -		newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops);
>> +		newdirent(mp, tp, pip, &xname, ip, &first, &dfops, &offset);
>>   		break;
>>   	case IF_DIRECTORY:
>>   		tp = getres(mp, 0);
>> @@ -572,8 +576,8 @@ parseproto(
>>   		} else {
>>   			libxfs_trans_ijoin(tp, pip, 0);
>>   			xname.type = XFS_DIR3_FT_DIR;
>> -			newdirent(mp, tp, pip, &xname, ip->i_ino,
>> -				  &first, &dfops);
>> +			newdirent(mp, tp, pip, &xname, ip,
>> +				  &first, &dfops, &offset);
>>   			inc_nlink(VFS_I(pip));
>>   			libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE);
>>   		}
>> @@ -612,6 +616,19 @@ parseproto(
>>   		fail(_("Error encountered creating file from prototype file"),
>>   			error);
>>   	}
>> +
>> +	if (xfs_sb_version_hasparent(&mp->m_sb)) {
>> +		error = xfs_parent_add(pip, ip, &xname, offset, &first, &dfops);
> 
> Didn't we just _defer_finish(&dfops) in the hunk right above this?  Why
> not add the deferred pptr before the first _defer_finish call?
> 
> --D

Oh ok, I'll see if I can move it up and get rid of the extra finish.  Thx!

Allison

> 
>> +		if (error)
>> +			fail(_("Error creating parent pointer"), error);
>> +
>> +		libxfs_trans_log_inode(tp, ip, flags);
>> +		libxfs_defer_ijoin(&dfops, ip);
>> +		error = -libxfs_defer_finish(&tp, &dfops);
>> +		if (error)
>> +			fail(_("Directory creation failed"), error);
>> +	}
>> +
>>   	libxfs_trans_commit(tp);
>>   	IRELE(ip);
>>   }
>> -- 
>> 2.7.4
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 19/27] xfsprogs: Add delayed attributes error tag
  2018-06-11 17:28   ` Darrick J. Wong
@ 2018-06-11 19:59     ` Allison Henderson
  0 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-11 19:59 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs



On 06/11/2018 10:28 AM, Darrick J. Wong wrote:
>> Subject: [PATCH v2 19/27] xfsprogs: Add delayed attributes error tag
> 
> Please identify the tool name in the subject when possible, e.g.
> 
> [PATCH v2 19/27] xfs_io: Add delayed attributes error tag
> 
> Otherwise looks ok, though in the end I suspect the xfs_errortag.h chunk
> will be ported in from the kernel patch and this will be a separate
> patch with just the xfs_io part.
> 
> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
> 
> --D

Alrighty then, will update.  Thx!

Allison

> 
> 
> On Sat, Jun 09, 2018 at 10:07:44PM -0700, Allison Henderson wrote:
>> Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
>> ---
>>   io/inject.c           | 1 +
>>   libxfs/xfs_errortag.h | 5 ++++-
>>   2 files changed, 5 insertions(+), 1 deletion(-)
>>
>> diff --git a/io/inject.c b/io/inject.c
>> index fc3cf25..2d6cc9c 100644
>> --- a/io/inject.c
>> +++ b/io/inject.c
>> @@ -63,6 +63,7 @@ error_tag(char *name)
>>   		{ XFS_ERRTAG_LOG_BAD_CRC,		"log_bad_crc" },
>>   		{ XFS_ERRTAG_LOG_ITEM_PIN,		"log_item_pin" },
>>   		{ XFS_ERRTAG_BUF_LRU_REF,		"buf_lru_ref" },
>> +		{ 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 bc1789d..f606ab6 100644
>> --- a/libxfs/xfs_errortag.h
>> +++ b/libxfs/xfs_errortag.h
>> @@ -65,7 +65,8 @@
>>   #define XFS_ERRTAG_LOG_BAD_CRC				29
>>   #define XFS_ERRTAG_LOG_ITEM_PIN				30
>>   #define XFS_ERRTAG_BUF_LRU_REF				31
>> -#define XFS_ERRTAG_MAX					32
>> +#define XFS_ERRTAG_DELAYED_ATTR			32
>> +#define XFS_ERRTAG_MAX					33
>>   
>>   /*
>>    * Random factors for above tags, 1 means always, 2 means 1/2 time, etc.
>> @@ -102,5 +103,7 @@
>>   #define XFS_RANDOM_LOG_BAD_CRC				1
>>   #define XFS_RANDOM_LOG_ITEM_PIN				1
>>   #define XFS_RANDOM_BUF_LRU_REF				2
>> +#define XFS_RANDOM_DELAYED_ATTR			1
>>   
>>   #endif /* __XFS_ERRORTAG_H_ */
>> +
>> -- 
>> 2.7.4
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  https://urldefense.proofpoint.com/v2/url?u=http-3A__vger.kernel.org_majordomo-2Dinfo.html&d=DwIBAg&c=RoP1YumCXCgaWHvlZYR8PZh8Bv7qIrMUB65eapI_JnE&r=LHZQ8fHvy6wDKXGTWcm97burZH5sQKHRDMaY1UthQxc&m=QbTHukRdcKCnd1O8XZT7S_muyoJoMTtTL4i6k23zRGY&s=bhDah3NrmTekLEKtbCYu5KGb-r_-7o59FAmFdI_tqfM&e=
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  https://urldefense.proofpoint.com/v2/url?u=http-3A__vger.kernel.org_majordomo-2Dinfo.html&d=DwIBAg&c=RoP1YumCXCgaWHvlZYR8PZh8Bv7qIrMUB65eapI_JnE&r=LHZQ8fHvy6wDKXGTWcm97burZH5sQKHRDMaY1UthQxc&m=QbTHukRdcKCnd1O8XZT7S_muyoJoMTtTL4i6k23zRGY&s=bhDah3NrmTekLEKtbCYu5KGb-r_-7o59FAmFdI_tqfM&e=
> 

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 20/27] xfsprogs: Add parent pointer flag to cmd
  2018-06-11 17:43   ` Darrick J. Wong
@ 2018-06-11 20:00     ` Allison Henderson
  0 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-11 20:00 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs

On 06/11/2018 10:43 AM, Darrick J. Wong wrote:
> On Sat, Jun 09, 2018 at 10:07:45PM -0700, Allison Henderson wrote:
>> 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 | 15 ++++++++++++++-
>>   1 file changed, 14 insertions(+), 1 deletion(-)
>>
>> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
>> index 78d0ce5..b9a8b00 100644
>> --- a/mkfs/xfs_mkfs.c
>> +++ b/mkfs/xfs_mkfs.c
>> @@ -104,6 +104,7 @@ enum {
>>   	N_SIZE = 0,
>>   	N_VERSION,
>>   	N_FTYPE,
>> +	N_PARENT,
>>   	N_MAX_OPTS,
>>   };
>>   
>> @@ -550,6 +551,7 @@ struct opt_params nopts = {
>>   		[N_SIZE] = "size",
>>   		[N_VERSION] = "version",
>>   		[N_FTYPE] = "ftype",
>> +		[N_PARENT] = "parent",
>>   	},
>>   	.subopt_params = {
>>   		{ .index = N_SIZE,
>> @@ -572,6 +574,12 @@ struct opt_params nopts = {
>>   		  .maxval = 1,
>>   		  .defaultval = 1,
>>   		},
>> +		{ .index = N_PARENT,
>> +		  .conflicts = { { NULL, LAST_CONFLICT } },
>> +		  .minval = 0,
>> +		  .maxval = 1,
>> +		  .defaultval = 1,
>> +		},
>>   	},
>>   };
>>   
>> @@ -876,7 +884,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\
>> @@ -1615,6 +1623,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;
>>   	}
> 
> validate_sb_features() needs to disallow parent pointers on v4
> filesystems.  See "reflink not supported without CRC support" around
> xfs_mkfs.c line 2015.
> 
> --D
Ok, I will add a check for that.  Thx!

Allison

> 
>> @@ -2887,6 +2898,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
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 23/27] xfsprogs: Do not use namechecks on parent pointers
  2018-06-11 18:00   ` Darrick J. Wong
@ 2018-06-11 20:00     ` Allison Henderson
  2018-06-11 20:23       ` Darrick J. Wong
  0 siblings, 1 reply; 51+ messages in thread
From: Allison Henderson @ 2018-06-11 20:00 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs

On 06/11/2018 11:00 AM, Darrick J. Wong wrote:
> On Sat, Jun 09, 2018 at 10:07:48PM -0700, Allison Henderson wrote:
>> Attribute names of parent pointers are not strings.  So
>> avoid doing namechecks for these attributes.
>>
>> Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
>> ---
>>   repair/attr_repair.c | 18 +++++++++++-------
>>   1 file changed, 11 insertions(+), 7 deletions(-)
>>
>> diff --git a/repair/attr_repair.c b/repair/attr_repair.c
>> index 8b1b8a7..b8b0768 100644
>> --- a/repair/attr_repair.c
>> +++ b/repair/attr_repair.c
>> @@ -308,8 +308,9 @@ process_shortform_attr(
>>   		/* namecheck checks for / and null terminated for file names.
>>   		 * attributes names currently follow the same rules.
>>   		*/
>> -		if (namecheck((char *)&currententry->nameval[0],
>> -						currententry->namelen))  {
>> +		if (!(currententry->flags & XFS_ATTR_PARENT) &&
>> +			namecheck((char *)&currententry->nameval[0],
>> +			currententry->namelen))  {
>>   			do_warn(
> 
> Please don't indent the condition tests to the same column as the code.
> Either line them up with the if parentheses or double-tab them.
> 
> if (!(currententry->flags & XFS_ATTR_PARENT) &&
>      namecheck((char *)&currententry->nameval[0],
> 		currententry->namelen)) {
> 	do_warn(...);
> }
> 
Alrighty, will fix

>>   	_("entry contains illegal character in shortform attribute name\n"));
>>   			junkit = 1;
>> @@ -470,8 +471,9 @@ 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 (!(entry->flags & XFS_ATTR_PARENT) &&
>> +		(local->namelen == 0 || namecheck((char *)&local->nameval[0],
>> +		local->namelen))) {
> 
> Why skip the namelen checks when it's a parent pointer?  Isn't the pptr
> corrupt if the (ino, gen, offset) data is length zero?
> 
Thats true, though I suppose in the case of parent pointers it should be 
the size of the name record.  Would it maybe be cleaner to make a 
subroutine that took local and entry and did the appropriate length 
checking there?  It may make things simpler here and also in the case below?


>>   		do_warn(
>>   	_("attribute entry %d in attr block %u, inode %" PRIu64 " has bad name (namelen = %d)\n"),
>>   			i, da_bno, ino, local->namelen);
>> @@ -525,13 +527,15 @@ process_leaf_attr_remote(
>>   
>>   	remotep = xfs_attr3_leaf_name_remote(leaf, i);
>>   
>> -	if (remotep->namelen == 0 || namecheck((char *)&remotep->name[0],
>> -						remotep->namelen) ||
>> +	if (!(entry->flags & XFS_ATTR_PARENT) &&
>> +			(remotep->namelen == 0 ||
>> +			namecheck((char *)&remotep->name[0],
>> +				remotep->namelen) ||
>>   			be32_to_cpu(entry->hashval) !=
>>   				libxfs_da_hashname((unsigned char *)&remotep->name[0],
>>   						remotep->namelen) ||
>>   			be32_to_cpu(entry->hashval) < last_hashval ||
>> -			be32_to_cpu(remotep->valueblk) == 0) {
>> +			be32_to_cpu(remotep->valueblk) == 0)) {
> 
> Do parent pointer attrs ever end up using a remote value block to store
> the name?  If so, I think you only want to skip the namecheck, not the
> namelen/hashval/valueblk checks, right?
> 
> --D
> 
>>   		do_warn(
>>   	_("inconsistent remote attribute entry %d in attr block %u, ino %" PRIu64 "\n"), i, da_bno, ino);
>>   		return -1;
>> -- 
>> 2.7.4
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 24/27] xfsprogs: Add parent pointers to recreated inodes
  2018-06-11 18:06   ` Darrick J. Wong
@ 2018-06-11 20:00     ` Allison Henderson
  0 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-11 20:00 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs



On 06/11/2018 11:06 AM, Darrick J. Wong wrote:
> On Sat, Jun 09, 2018 at 10:07:49PM -0700, Allison Henderson wrote:
>> 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          | 40 +++++++++++++++++++++++++++-------------
>>   2 files changed, 28 insertions(+), 13 deletions(-)
>>
>> diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
>> index 78daca0..4b47479 100644
>> --- a/libxfs/libxfs_api_defs.h
>> +++ b/libxfs/libxfs_api_defs.h
>> @@ -152,5 +152,6 @@
>>   #define xfs_rmap_compare		libxfs_rmap_compare
>>   #define xfs_dir_get_ops			libxfs_dir_get_ops
>>   #define xfs_default_ifork_ops		libxfs_default_ifork_ops
>> +#define xfs_parent_add    		libxfs_parent_add
>>   
>>   #endif /* __LIBXFS_API_DEFS_H__ */
>> diff --git a/repair/phase6.c b/repair/phase6.c
>> index 4fedb35..96ffade 100644
>> --- a/repair/phase6.c
>> +++ b/repair/phase6.c
>> @@ -29,6 +29,7 @@
>>   #include "dinode.h"
>>   #include "progress.h"
>>   #include "versions.h"
>> +#include "xfs_parent.h"
>>   
>>   static struct cred		zerocr;
>>   static struct fsxattr 		zerofsx;
>> @@ -962,19 +963,20 @@ 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;
>> -	xfs_fsblock_t	first;
>> -	ino_tree_node_t	*irec;
>> -	int		ino_offset = 0;
>> -	int		i;
>> -	int		error;
>> +	xfs_ino_t		ino;
>> +	struct xfs_trans	*tp;
>> +	struct xfs_inode	*ip;
>> +	struct xfs_inode	*pip;
>> +	xfs_fsblock_t		first;
>> +	struct ino_tree_node	*irec;
>> +	int			ino_offset = 0;
>> +	int			i;
>> +	int			error;
>>   	struct xfs_defer_ops	dfops;
>> -	const int	mode = 0755;
>> -	int		nres;
>> -	struct xfs_name	xname;
>> +	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
>> @@ -1061,7 +1063,7 @@ mk_orphanage(xfs_mount_t *mp)
>>   	 * create the actual entry
>>   	 */
>>   	error = -libxfs_dir_createname(tp, pip, &xname, ip->i_ino, &first,
>> -					&dfops, nres, NULL);
>> +					&dfops, nres, &offset);
>>   	if (error)
>>   		do_error(
>>   		_("can't make %s, createname error %d\n"),
>> @@ -1083,6 +1085,18 @@ mk_orphanage(xfs_mount_t *mp)
>>   	libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
>>   
>>   	libxfs_defer_ijoin(&dfops, ip);
>> +
>> +        if (xfs_sb_version_hasparent(&mp->m_sb)) {
>> +                error = -libxfs_parent_add(pip, ip, &xname, offset,
> 
> Tabs, not spaces for the indenting.
> 
>> +				       &first, &dfops);
>> +                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_defer_ijoin(&dfops, pip);
> 
> /me wonders if it's really necessary to _defer_ijoin either of the
> inodes to the transaction since we commit and IRELE both of them
> immediately afterwards...
> 
> --D

Ok, let me see if I can get away with taking that out.  Thx!

Allison
> 
>> +        }
>> +
>>   	error = -libxfs_defer_finish(&tp, &dfops);
>>   	if (error) {
>>   		do_error(_("%s directory creation failed -- bmapf error %d\n"),
>> -- 
>> 2.7.4
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 27/27] xfsprogs: Clean up old parent pointer definitions
  2018-06-11 18:20   ` Darrick J. Wong
@ 2018-06-11 20:06     ` Allison Henderson
  0 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-11 20:06 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs

On 06/11/2018 11:20 AM, Darrick J. Wong wrote:
> On Sat, Jun 09, 2018 at 10:07:52PM -0700, Allison Henderson wrote:
>> Existing parent pointer stubs and structs are not used in this
>> implementation.  Remove uneeded definitions.
>>
>> Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
>> ---
>>   include/parent.h   | 10 ----------
>>   libhandle/handle.c | 26 --------------------------
>>   libhandle/jdm.c    | 20 --------------------
>>   3 files changed, 56 deletions(-)
>>
>> diff --git a/include/parent.h b/include/parent.h
>> index 33f8d85..5665d64 100644
>> --- a/include/parent.h
>> +++ b/include/parent.h
>> @@ -18,16 +18,6 @@
>>   #ifndef __PARENT_H__
>>   #define	__PARENT_H__
>>   
>> -typedef struct parent {
>> -	__u64	p_ino;
>> -	__u32	p_gen;
>> -	__u16	p_reclen;
>> -} parent_t;
>> -
>> -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,
>> diff --git a/libhandle/handle.c b/libhandle/handle.c
>> index a70fa32..862b943 100644
>> --- a/libhandle/handle.c
>> +++ b/libhandle/handle.c
>> @@ -20,7 +20,6 @@
>>   #include "platform_defs.h"
>>   #include "xfs.h"
>>   #include "handle.h"
>> -#include "parent.h"
>>   
>>   /* just pick a value we know is more than big enough */
>>   #define	MAXHANSIZ	64
>> @@ -422,31 +421,6 @@ attr_list_by_handle(
>>   }
>>   
>>   int
>> -parents_by_handle(
>> -	void		*hanp,
>> -	size_t		hlen,
>> -	parent_t	*buf,
>> -	size_t		bufsiz,
>> -	unsigned int	*count)
>> -
>> -{
>> -	errno = EOPNOTSUPP;
>> -	return -1;
>> -}
> 
> You probably need to scrape the declarations out of the header files
> because otherwise any program that thinks it wants to use this will
> compile ok but barf on unresolved symbols in the linker phase.
> 
> There's a murkier question here about how do we handle deprecating these
> libhandle APIs that have never been usable on Linux?
> 
> --D
Oh I see... is there a formal procedure for deprecation that we need to 
be following?  In case someone was depending on getting their EOPNOTSUPP rc?

> 
>> -
>> -int
>> -parentpaths_by_handle(
>> -	void		*hanp,
>> -	size_t		hlen,
>> -	parent_t	*buf,
>> -	size_t		bufsiz,
>> -	unsigned int	*count)
>> -{
>> -	errno = EOPNOTSUPP;
>> -	return -1;
>> -}
>> -
>> -int
>>   fssetdm_by_handle(
>>   	void		*hanp,
>>   	size_t		hlen,
>> diff --git a/libhandle/jdm.c b/libhandle/jdm.c
>> index 821061b..0c2440b 100644
>> --- a/libhandle/jdm.c
>> +++ b/libhandle/jdm.c
>> @@ -20,7 +20,6 @@
>>   #include "xfs.h"
>>   #include "handle.h"
>>   #include "jdm.h"
>> -#include "parent.h"
>>   
>>   /* internal fshandle - typecast to a void for external use */
>>   #define FSHANDLE_SZ		8
>> @@ -178,22 +177,3 @@ jdm_attr_list(	jdm_fshandle_t *fshp,
>>   	return rval;
>>   }
>>   
>> -int
>> -jdm_parents( jdm_fshandle_t *fshp,
>> -		xfs_bstat_t *statp,
>> -		parent_t *bufp, size_t bufsz,
>> -		unsigned int *count)
>> -{
>> -	errno = EOPNOTSUPP;
>> -	return -1;
>> -}
>> -
>> -int
>> -jdm_parentpaths( jdm_fshandle_t *fshp,
>> -		xfs_bstat_t *statp,
>> -		parent_t *bufp, size_t bufsz,
>> -		unsigned int *count)
>> -{
>> -	errno = EOPNOTSUPP;
>> -	return -1;
>> -}
>> -- 
>> 2.7.4
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 23/27] xfsprogs: Do not use namechecks on parent pointers
  2018-06-11 20:00     ` Allison Henderson
@ 2018-06-11 20:23       ` Darrick J. Wong
  2018-06-11 20:38         ` Allison Henderson
  0 siblings, 1 reply; 51+ messages in thread
From: Darrick J. Wong @ 2018-06-11 20:23 UTC (permalink / raw)
  To: Allison Henderson; +Cc: linux-xfs

On Mon, Jun 11, 2018 at 01:00:45PM -0700, Allison Henderson wrote:
> On 06/11/2018 11:00 AM, Darrick J. Wong wrote:
> > On Sat, Jun 09, 2018 at 10:07:48PM -0700, Allison Henderson wrote:
> > > Attribute names of parent pointers are not strings.  So
> > > avoid doing namechecks for these attributes.
> > > 
> > > Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
> > > ---
> > >   repair/attr_repair.c | 18 +++++++++++-------
> > >   1 file changed, 11 insertions(+), 7 deletions(-)
> > > 
> > > diff --git a/repair/attr_repair.c b/repair/attr_repair.c
> > > index 8b1b8a7..b8b0768 100644
> > > --- a/repair/attr_repair.c
> > > +++ b/repair/attr_repair.c
> > > @@ -308,8 +308,9 @@ process_shortform_attr(
> > >   		/* namecheck checks for / and null terminated for file names.
> > >   		 * attributes names currently follow the same rules.
> > >   		*/
> > > -		if (namecheck((char *)&currententry->nameval[0],
> > > -						currententry->namelen))  {
> > > +		if (!(currententry->flags & XFS_ATTR_PARENT) &&
> > > +			namecheck((char *)&currententry->nameval[0],
> > > +			currententry->namelen))  {
> > >   			do_warn(
> > 
> > Please don't indent the condition tests to the same column as the code.
> > Either line them up with the if parentheses or double-tab them.
> > 
> > if (!(currententry->flags & XFS_ATTR_PARENT) &&
> >      namecheck((char *)&currententry->nameval[0],
> > 		currententry->namelen)) {
> > 	do_warn(...);
> > }
> > 
> Alrighty, will fix
> 
> > >   	_("entry contains illegal character in shortform attribute name\n"));
> > >   			junkit = 1;
> > > @@ -470,8 +471,9 @@ 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 (!(entry->flags & XFS_ATTR_PARENT) &&
> > > +		(local->namelen == 0 || namecheck((char *)&local->nameval[0],
> > > +		local->namelen))) {
> > 
> > Why skip the namelen checks when it's a parent pointer?  Isn't the pptr
> > corrupt if the (ino, gen, offset) data is length zero?
> > 
> Thats true, though I suppose in the case of parent pointers it should be the
> size of the name record.  Would it maybe be cleaner to make a subroutine
> that took local and entry and did the appropriate length checking there?  It
> may make things simpler here and also in the case below?

I probably wouldn't bother for the local entry because it's fairly
short.  The remote format case below is sort of gnarly, maybe it'd be
better refactored as a functi...

...hmm, thinking further, in the (flags & PARENT) case, namelen should
be exactly sizeof(struct xfs_parent_name_rec), right?

So perhaps we just move the namelen == 0 check into namecheck and pass
in the entry->flags so that we can do....

...thinking even further ahead, if there's some sort of verifier
function for struct xfs_parent_name_rec then we should call that here
too.  What do you think of this?

/* return true if attr name is garbage */
bool namecheck(entry, nameptr, namelen)
{
	if (namelen == 0)
		return true;
	if (entry->flags & _ATTR_PARENT) {
		xfs_failaddr_t	fa;

		if (namelen != sizeof(struct xfs_parent_name_rec))
			return true;

		fa = xfs_verify_pptr(mp, (struct xfs_parent_name_rec *)nameptr);
		return fa != NULL;
	}
	/* do the other name checks */
}

--D

> 
> 
> > >   		do_warn(
> > >   	_("attribute entry %d in attr block %u, inode %" PRIu64 " has bad name (namelen = %d)\n"),
> > >   			i, da_bno, ino, local->namelen);
> > > @@ -525,13 +527,15 @@ process_leaf_attr_remote(
> > >   	remotep = xfs_attr3_leaf_name_remote(leaf, i);
> > > -	if (remotep->namelen == 0 || namecheck((char *)&remotep->name[0],
> > > -						remotep->namelen) ||
> > > +	if (!(entry->flags & XFS_ATTR_PARENT) &&
> > > +			(remotep->namelen == 0 ||
> > > +			namecheck((char *)&remotep->name[0],
> > > +				remotep->namelen) ||
> > >   			be32_to_cpu(entry->hashval) !=
> > >   				libxfs_da_hashname((unsigned char *)&remotep->name[0],
> > >   						remotep->namelen) ||
> > >   			be32_to_cpu(entry->hashval) < last_hashval ||
> > > -			be32_to_cpu(remotep->valueblk) == 0) {
> > > +			be32_to_cpu(remotep->valueblk) == 0)) {
> > 
> > Do parent pointer attrs ever end up using a remote value block to store
> > the name?  If so, I think you only want to skip the namecheck, not the
> > namelen/hashval/valueblk checks, right?
> > 
> > --D
> > 
> > >   		do_warn(
> > >   	_("inconsistent remote attribute entry %d in attr block %u, ino %" PRIu64 "\n"), i, da_bno, ino);
> > >   		return -1;
> > > -- 
> > > 2.7.4
> > > 
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> > > the body of a message to majordomo@vger.kernel.org
> > > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [PATCH v2 23/27] xfsprogs: Do not use namechecks on parent pointers
  2018-06-11 20:23       ` Darrick J. Wong
@ 2018-06-11 20:38         ` Allison Henderson
  0 siblings, 0 replies; 51+ messages in thread
From: Allison Henderson @ 2018-06-11 20:38 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs

On 06/11/2018 01:23 PM, Darrick J. Wong wrote:
> On Mon, Jun 11, 2018 at 01:00:45PM -0700, Allison Henderson wrote:
>> On 06/11/2018 11:00 AM, Darrick J. Wong wrote:
>>> On Sat, Jun 09, 2018 at 10:07:48PM -0700, Allison Henderson wrote:
>>>> Attribute names of parent pointers are not strings.  So
>>>> avoid doing namechecks for these attributes.
>>>>
>>>> Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
>>>> ---
>>>>    repair/attr_repair.c | 18 +++++++++++-------
>>>>    1 file changed, 11 insertions(+), 7 deletions(-)
>>>>
>>>> diff --git a/repair/attr_repair.c b/repair/attr_repair.c
>>>> index 8b1b8a7..b8b0768 100644
>>>> --- a/repair/attr_repair.c
>>>> +++ b/repair/attr_repair.c
>>>> @@ -308,8 +308,9 @@ process_shortform_attr(
>>>>    		/* namecheck checks for / and null terminated for file names.
>>>>    		 * attributes names currently follow the same rules.
>>>>    		*/
>>>> -		if (namecheck((char *)&currententry->nameval[0],
>>>> -						currententry->namelen))  {
>>>> +		if (!(currententry->flags & XFS_ATTR_PARENT) &&
>>>> +			namecheck((char *)&currententry->nameval[0],
>>>> +			currententry->namelen))  {
>>>>    			do_warn(
>>>
>>> Please don't indent the condition tests to the same column as the code.
>>> Either line them up with the if parentheses or double-tab them.
>>>
>>> if (!(currententry->flags & XFS_ATTR_PARENT) &&
>>>       namecheck((char *)&currententry->nameval[0],
>>> 		currententry->namelen)) {
>>> 	do_warn(...);
>>> }
>>>
>> Alrighty, will fix
>>
>>>>    	_("entry contains illegal character in shortform attribute name\n"));
>>>>    			junkit = 1;
>>>> @@ -470,8 +471,9 @@ 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 (!(entry->flags & XFS_ATTR_PARENT) &&
>>>> +		(local->namelen == 0 || namecheck((char *)&local->nameval[0],
>>>> +		local->namelen))) {
>>>
>>> Why skip the namelen checks when it's a parent pointer?  Isn't the pptr
>>> corrupt if the (ino, gen, offset) data is length zero?
>>>
>> Thats true, though I suppose in the case of parent pointers it should be the
>> size of the name record.  Would it maybe be cleaner to make a subroutine
>> that took local and entry and did the appropriate length checking there?  It
>> may make things simpler here and also in the case below?
> 
> I probably wouldn't bother for the local entry because it's fairly
> short.  The remote format case below is sort of gnarly, maybe it'd be
> better refactored as a functi...
> 
> ...hmm, thinking further, in the (flags & PARENT) case, namelen should
> be exactly sizeof(struct xfs_parent_name_rec), right?
> 
> So perhaps we just move the namelen == 0 check into namecheck and pass
> in the entry->flags so that we can do....
> 
> ...thinking even further ahead, if there's some sort of verifier
> function for struct xfs_parent_name_rec then we should call that here
> too.  What do you think of this?
> 
> /* return true if attr name is garbage */
> bool namecheck(entry, nameptr, namelen)
> {
> 	if (namelen == 0)
> 		return true;
> 	if (entry->flags & _ATTR_PARENT) {
> 		xfs_failaddr_t	fa;
> 
> 		if (namelen != sizeof(struct xfs_parent_name_rec))
> 			return true;
> 
> 		fa = xfs_verify_pptr(mp, (struct xfs_parent_name_rec *)nameptr);
> 		return fa != NULL;
> 	}
> 	/* do the other name checks */
> }
> 
> --D

Lol, alrighty then that looks good.  I will see if I can put together a 
pptr verifier.  Thx!

Allison

> 
>>
>>
>>>>    		do_warn(
>>>>    	_("attribute entry %d in attr block %u, inode %" PRIu64 " has bad name (namelen = %d)\n"),
>>>>    			i, da_bno, ino, local->namelen);
>>>> @@ -525,13 +527,15 @@ process_leaf_attr_remote(
>>>>    	remotep = xfs_attr3_leaf_name_remote(leaf, i);
>>>> -	if (remotep->namelen == 0 || namecheck((char *)&remotep->name[0],
>>>> -						remotep->namelen) ||
>>>> +	if (!(entry->flags & XFS_ATTR_PARENT) &&
>>>> +			(remotep->namelen == 0 ||
>>>> +			namecheck((char *)&remotep->name[0],
>>>> +				remotep->namelen) ||
>>>>    			be32_to_cpu(entry->hashval) !=
>>>>    				libxfs_da_hashname((unsigned char *)&remotep->name[0],
>>>>    						remotep->namelen) ||
>>>>    			be32_to_cpu(entry->hashval) < last_hashval ||
>>>> -			be32_to_cpu(remotep->valueblk) == 0) {
>>>> +			be32_to_cpu(remotep->valueblk) == 0)) {
>>>
>>> Do parent pointer attrs ever end up using a remote value block to store
>>> the name?  If so, I think you only want to skip the namecheck, not the
>>> namelen/hashval/valueblk checks, right?
>>>
>>> --D
>>>
>>>>    		do_warn(
>>>>    	_("inconsistent remote attribute entry %d in attr block %u, ino %" PRIu64 "\n"), i, da_bno, ino);
>>>>    		return -1;
>>>> -- 
>>>> 2.7.4
>>>>
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
>>>> the body of a message to majordomo@vger.kernel.org
>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 51+ messages in thread

end of thread, other threads:[~2018-06-11 20:38 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-10  5:07 [PATCH v2 00/27] xfsprogs: parent pointers v2 Allison Henderson
2018-06-10  5:07 ` [PATCH v2 01/27] xfsprogs: Move xfs_attr.h to libxfs Allison Henderson
2018-06-10  5:07 ` [PATCH v2 02/27] xfsprogs: Add helper function xfs_attr_try_sf_addname Allison Henderson
2018-06-10  5:07 ` [PATCH v2 03/27] xfsprogs: Add trans toggle to attr routines Allison Henderson
2018-06-10  7:02   ` Amir Goldstein
2018-06-10 16:19     ` Allison Henderson
2018-06-10  5:07 ` [PATCH v2 04/27] xfsprogs: Add attibute set and helper functions Allison Henderson
2018-06-10  5:07 ` [PATCH v2 05/27] xfsprogs: Add attibute remove " Allison Henderson
2018-06-10  5:07 ` [PATCH v2 06/27] xfsprogs: Set up infastructure for deferred attribute operations Allison Henderson
2018-06-10  5:07 ` [PATCH v2 07/27] xfsprogs: Add xfs_attr_set_deferred and xfs_attr_remove_deferred Allison Henderson
2018-06-10  5:07 ` [PATCH v2 08/27] xfsprogs: Remove all strlen calls in all xfs_attr_* functions for attr names Allison Henderson
2018-06-10  5:07 ` [PATCH v2 09/27] xfsprogs: get directory offset when adding directory name Allison Henderson
2018-06-10  5:07 ` [PATCH v2 10/27] xfsprogs: get directory offset when removing " Allison Henderson
2018-06-10  5:07 ` [PATCH v2 11/27] xfsprogs: get directory offset when replacing a " Allison Henderson
2018-06-10  5:07 ` [PATCH v2 12/27] xfsprogs: add parent pointer support to attribute code Allison Henderson
2018-06-10  5:07 ` [PATCH v2 13/27] xfsprogs: define parent pointer xattr format Allison Henderson
2018-06-10  5:07 ` [PATCH v2 14/27] xfsprogs: extent transaction reservations for parent attributes Allison Henderson
2018-06-10  5:07 ` [PATCH v2 15/27] xfsprogs: parent pointer attribute creation Allison Henderson
2018-06-10  5:07 ` [PATCH v2 16/27] xfsprogs: Add the parent pointer support to the superblock version 5 Allison Henderson
2018-06-10  5:07 ` [PATCH v2 17/27] xfsprogs: Add helper function xfs_attr_list_context_init Allison Henderson
2018-06-10  5:07 ` [PATCH v2 18/27] xfsprogs: Add parent pointer ioctl Allison Henderson
2018-06-10  5:07 ` [PATCH v2 19/27] xfsprogs: Add delayed attributes error tag Allison Henderson
2018-06-11 17:28   ` Darrick J. Wong
2018-06-11 19:59     ` Allison Henderson
2018-06-10  5:07 ` [PATCH v2 20/27] xfsprogs: Add parent pointer flag to cmd Allison Henderson
2018-06-11 17:43   ` Darrick J. Wong
2018-06-11 20:00     ` Allison Henderson
2018-06-10  5:07 ` [PATCH v2 21/27] xfsprogs: Remove single byte array from struct parent Allison Henderson
2018-06-10 11:21   ` Amir Goldstein
2018-06-10 15:25     ` Allison Henderson
2018-06-10  5:07 ` [PATCH v2 22/27] xfsprogs: Add log item printing for ATTRI and ATTRD Allison Henderson
2018-06-10  5:07 ` [PATCH v2 23/27] xfsprogs: Do not use namechecks on parent pointers Allison Henderson
2018-06-11 18:00   ` Darrick J. Wong
2018-06-11 20:00     ` Allison Henderson
2018-06-11 20:23       ` Darrick J. Wong
2018-06-11 20:38         ` Allison Henderson
2018-06-10  5:07 ` [PATCH v2 24/27] xfsprogs: Add parent pointers to recreated inodes Allison Henderson
2018-06-10 11:27   ` Amir Goldstein
2018-06-10 17:19     ` Allison Henderson
2018-06-11 17:31       ` Darrick J. Wong
2018-06-11 18:06   ` Darrick J. Wong
2018-06-11 20:00     ` Allison Henderson
2018-06-10  5:07 ` [PATCH v2 25/27] xfsprogs: Add parent pointers during protofile creation Allison Henderson
2018-06-10 11:32   ` Amir Goldstein
2018-06-11 18:15   ` Darrick J. Wong
2018-06-11 19:58     ` Allison Henderson
2018-06-10  5:07 ` [PATCH v2 26/27] xfsprogs: implement the upper half of parent pointers Allison Henderson
2018-06-10 12:06   ` Amir Goldstein
2018-06-10  5:07 ` [PATCH v2 27/27] xfsprogs: Clean up old parent pointer definitions Allison Henderson
2018-06-11 18:20   ` Darrick J. Wong
2018-06-11 20:06     ` Allison Henderson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.