From: Mark Tinguely <tinguely@sgi.com>
To: xfs@oss.sgi.com
Subject: [RFC 12/17] xfs: (parent ptr) add parent pointer support for user space
Date: Wed, 15 Jan 2014 16:00:24 -0600 [thread overview]
Message-ID: <20140116000852.215757527@sgi.com> (raw)
In-Reply-To: 20140115220012.624438534@sgi.com
[-- Attachment #1: 12-pptr-add-incore-to-getparentpaths_by_handle.patch --]
[-- Type: text/plain, Size: 17487 bytes --]
Add the parent inode / offset support for user space.
This adds two new ioctls to provide the names or paths
for an inode that is pointed to by handle.
---
fs/xfs/xfs_attr.h | 2
fs/xfs/xfs_fs.h | 10 +
fs/xfs/xfs_ioctl.c | 72 ++++++++
fs/xfs/xfs_parent.c | 435 ++++++++++++++++++++++++++++++++++++++++++++++++++++
fs/xfs/xfs_parent.h | 30 +++
5 files changed, 548 insertions(+), 1 deletion(-)
Index: b/fs/xfs/xfs_attr.h
===================================================================
--- a/fs/xfs/xfs_attr.h
+++ b/fs/xfs/xfs_attr.h
@@ -131,6 +131,8 @@ typedef struct xfs_attr_list_context {
int put_value; /* T/F: need value for listent */
put_listent_func_t put_listent; /* list output fmt function */
int index; /* index into output buffer */
+ char *scratch; /* parent private buf */
+ int srtchlen; /* parent priv buf len */
} xfs_attr_list_context_t;
Index: b/fs/xfs/xfs_fs.h
===================================================================
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -438,6 +438,14 @@ typedef struct xfs_fsop_attrmulti_handle
struct xfs_attr_multiop __user *ops; /* attr_multi data */
} xfs_fsop_attrmulti_handlereq_t;
+typedef struct xfs_fsop_parentlist_handlereq {
+ struct xfs_fsop_handlereq hreq; /* handle interface structure */
+ u32 flags; /* which namespace to use */
+ u32 buflen; /* length of supplied buffer */
+ __s32 __user *ocount; /* output count ptr */
+ void __user *buffer; /* returned names */
+} xfs_fsop_parentlist_handlereq_t;
+
/*
* per machine unique filesystem identifier types.
*/
@@ -553,6 +561,8 @@ typedef struct xfs_swapext
#define XFS_IOC_ATTRMULTI_BY_HANDLE _IOW ('X', 123, struct xfs_fsop_attrmulti_handlereq)
#define XFS_IOC_FSGEOMETRY _IOR ('X', 124, struct xfs_fsop_geom)
#define XFS_IOC_GOINGDOWN _IOR ('X', 125, __uint32_t)
+#define XFS_IOC_GETPARENTS_BY_HANDLE _IOWR('X', 126, struct xfs_fsop_parentlist_handlereq)
+#define XFS_IOC_GETPARENTPATHS_BY_HANDLE _IOWR('X', 127, struct xfs_fsop_parentlist_handlereq)
/* XFS_IOC_GETFSUUID ---------- deprecated 140 */
Index: b/fs/xfs/xfs_ioctl.c
===================================================================
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -42,6 +42,7 @@
#include "xfs_symlink.h"
#include "xfs_dinode.h"
#include "xfs_trans.h"
+#include "xfs_parent.h"
#include <linux/capability.h>
#include <linux/dcache.h>
@@ -632,6 +633,73 @@ xfs_attrmulti_by_handle(
return -error;
}
+STATIC int
+xfs_getparent_by_handle(
+ struct file *parfilp,
+ void __user *arg,
+ unsigned int cmd)
+{
+ int error = -ENOMEM;
+ int count = 0;
+ struct xfs_fsop_parentlist_handlereq pl_hreq;
+ struct dentry *dentry;
+ char *kbuf;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -XFS_ERROR(EPERM);
+
+ if (copy_from_user(&pl_hreq, arg, sizeof(pl_hreq)))
+ return -XFS_ERROR(EFAULT);
+
+ if (pl_hreq.buflen > XATTR_LIST_MAX)
+ return -XFS_ERROR(EINVAL);
+
+ /*
+ * Reject flags, only allow namespaces.
+ */
+ if (pl_hreq.flags & ~(ATTR_PARENT))
+ return -XFS_ERROR(EINVAL);
+
+ dentry = xfs_handlereq_to_dentry(parfilp, &pl_hreq.hreq);
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
+
+ kbuf = kmem_zalloc_large(pl_hreq.buflen, KM_SLEEP);
+ if (!kbuf)
+ goto out_dput;
+
+ switch (cmd) {
+ case XFS_IOC_GETPARENTS_BY_HANDLE:
+ error = -xfs_parents_attr_list(XFS_I(dentry->d_inode), kbuf,
+ pl_hreq.buflen, &count);
+ break;
+ case XFS_IOC_GETPARENTPATHS_BY_HANDLE:
+ error = -xfs_parentpaths_attr_list(XFS_I(dentry->d_inode),
+ kbuf, pl_hreq.buflen, &count);
+ break;
+ default:
+ error = -ENOTTY;
+ }
+ if (error)
+ goto out_kfree;
+
+ if (copy_to_user(pl_hreq.buffer, kbuf, pl_hreq.buflen)) {
+ error = -XFS_ERROR(EFAULT);
+ goto out_kfree;
+ }
+
+ if (pl_hreq.ocount != NULL) {
+ if (copy_to_user(pl_hreq.ocount, &count, sizeof(count)))
+ error = -XFS_ERROR(EFAULT);
+ }
+
+ out_kfree:
+ kmem_free(kbuf);
+ out_dput:
+ dput(dentry);
+ return error;
+}
+
int
xfs_ioc_space(
struct xfs_inode *ip,
@@ -1675,6 +1743,10 @@ xfs_file_ioctl(
case XFS_IOC_ATTRMULTI_BY_HANDLE:
return xfs_attrmulti_by_handle(filp, arg);
+ case XFS_IOC_GETPARENTS_BY_HANDLE:
+ case XFS_IOC_GETPARENTPATHS_BY_HANDLE:
+ return xfs_getparent_by_handle(filp, arg, cmd);
+
case XFS_IOC_SWAPEXT: {
struct xfs_swapext sxp;
Index: b/fs/xfs/xfs_parent.c
===================================================================
--- a/fs/xfs/xfs_parent.c
+++ b/fs/xfs/xfs_parent.c
@@ -156,3 +156,438 @@ xfs_pptr_rename(
*/
return XFSREMOVESRC;
}
+
+/* the fill function for xfs_readdir */
+static int
+xfs_gpfill(
+ void *gfill,
+ const char *name,
+ int namlen,
+ loff_t offset,
+ u64 ino,
+ unsigned int type)
+{
+ struct xfs_pfillinfo *gfp = (struct xfs_pfillinfo *) gfill;
+
+ if (offset != gfp->gp_off) /*XXX mft remove */
+ return 0;
+
+ namlen = MIN(namlen, gfp->gp_len);
+ strncpy(gfp->gp_path + gfp->gp_len - namlen, name, namlen);
+ gfp->gp_len -= namlen;
+ return 1; /* return a 1 to stop */
+}
+
+/* save name of entry at directory pino/offset to the buffer (path) */
+int
+xfs_getpname(
+ struct xfs_mount *mp, /* IN mount point */
+ xfs_ino_t pino, /* IN starting parent ino */
+ xfs_off_t offset, /* IN starting dir offset */
+ char *path, /* OUT buffer to hold path */
+ int *plen) /* IN/OUT pref MAXPATHLEN+1 */
+{
+ int error = 0;
+ struct xfs_inode *dp = NULL;
+ struct xfs_pfillinfo gfill = {
+ .ctx.actor = xfs_gpfill
+ };
+
+ ASSERT(path != NULL);
+
+ gfill.ctx.pos = offset;
+ gfill.gp_off = offset;
+ gfill.gp_path = path;
+ gfill.gp_path[*plen-1] = '\0';
+ memset(path, 0, *plen);
+ gfill.gp_len = *plen-1;
+
+ error = xfs_iget(mp, NULL, pino, 0, XFS_ILOCK_SHARED, &dp);
+ if (error)
+ return error;
+
+ error = xfs_readdir(dp, &(gfill.ctx), *plen);
+ xfs_iunlock(dp, XFS_ILOCK_SHARED);
+ IRELE(dp);
+ *plen = *plen - 1 - gfill.gp_len;
+ return error;
+}
+
+STATIC int
+xfs_attr_paths_put_listent(
+ struct xfs_attr_list_context *context,
+ int flags,
+ unsigned char *name,
+ int namelen,
+ int valuelen,
+ unsigned char *value)
+{
+ struct xfs_pattr *p_attr;
+ struct xfs_parent *p_entry;
+
+ ASSERT(!(context->flags & ATTR_KERNOVAL));
+ ASSERT(context->count >= 0);
+ ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
+ ASSERT(namelen == sizeof(struct xfs_pattr));
+
+ /*
+ * Only list entries in the right namespace.
+ */
+ if ((context->flags & ATTR_PARENT) == 0)
+ return 0;
+
+ if (namelen != sizeof(struct xfs_pattr))
+ return 0;
+
+ p_attr = (struct xfs_pattr *) name;
+
+ p_entry = (struct xfs_parent *)context->alist;
+ p_entry->p_ino = be64_to_cpu(p_attr->p_ino);
+ p_entry->p_offset = be32_to_cpu(p_attr->p_offset);
+ context->seen_enough = 1;
+ return 0;
+}
+
+/* save path of entry at directory pino/offset to the buffer (path) */
+int
+xfs_getpath(
+ struct xfs_mount *mp, /* IN mount point */
+ xfs_ino_t pino, /* IN starting parent ino */
+ xfs_off_t offset, /* IN starting dir offset */
+ char *path, /* OUT buffer to hold path */
+ int *plen) /* IN/OUT pref MAXPATHLEN+1 */
+{
+ int error = 0;
+ uint32_t dotdot;
+ struct xfs_inode *dp = NULL;
+ struct xfs_pfillinfo gfill = {
+ .ctx.actor = xfs_gpfill
+ };
+
+ ASSERT(path != NULL);
+
+ gfill.ctx.pos = offset;
+ gfill.gp_off = offset;
+ gfill.gp_path = path;
+ gfill.gp_path[*plen-1] = '\0';
+ memset(path, 0, *plen);
+ gfill.gp_len = *plen-1;
+
+
+ error = xfs_iget(mp, NULL, pino, 0, XFS_ILOCK_SHARED, &dp);
+ if (error)
+ return error;
+
+ dotdot = dp->d_ops->data_dotdot_offset >> XFS_DIR2_DATA_ALIGN_LOG;
+
+ /*
+ * start with the specified parent inode/offset. save the current
+ * name and then loop through the parent directories filling in
+ * the current directory name until the mount point is reached or
+ * the buffer is full.
+ */
+
+ while (gfill.gp_len > 1 ) {
+ gfill.gp_off = offset; /*XXX mft remove */
+ gfill.ctx.pos = offset;
+ error = xfs_readdir(dp, &(gfill.ctx), *plen);
+ if (error)
+ goto out_irelse;
+
+ /* look for the parent attribute in the current directory */
+ pino = be64_to_cpu(dp->i_d.di_parent);
+ offset = be32_to_cpu(dp->i_d.di_poffset);
+
+ /* stop at root directory */
+ if (pino == mp->m_sb.sb_rootino && offset <= dotdot)
+ break;
+
+ xfs_iunlock(dp, XFS_ILOCK_SHARED);
+ IRELE(dp);
+
+ error = xfs_iget(mp, NULL, pino, 0, XFS_ILOCK_SHARED, &dp);
+ if (error)
+ goto out_irelse;
+
+ if (gfill.gp_len < 1)
+ break;
+
+ /* there is another parent directory - add dir slash */
+ gfill.gp_len--;
+ *(gfill.gp_path + gfill.gp_len) = '/';
+ }
+
+ *plen = *plen - 1 - gfill.gp_len;
+
+ out_irelse:
+ xfs_iunlock(dp, XFS_ILOCK_SHARED);
+ IRELE(dp);
+ return error;
+}
+
+/*
+ * Format an attribute and copy it out to the user's buffer.
+ * Take care to check values and protect against them changing later,
+ * we may be reading them directly out of a user buffer.
+ */
+/*ARGSUSED*/
+STATIC int
+xfs_attr_parents_put_listent(
+ struct xfs_attr_list_context *context,
+ int flags,
+ unsigned char *name,
+ int namelen,
+ int valuelen,
+ unsigned char *value)
+{
+ int error;
+ int len;
+ int reclen;
+ struct xfs_pattr *p_attr;
+ struct xfs_parent *p_entry;
+
+ ASSERT(!(context->flags & ATTR_KERNOVAL));
+ ASSERT(context->count >= 0);
+ ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
+ ASSERT(namelen == sizeof(struct xfs_pattr));
+
+ /*
+ * Only list entries in the right namespace.
+ */
+ if ((context->flags & ATTR_PARENT) == 0)
+ return 0;
+
+ if (namelen != sizeof(struct xfs_pattr))
+ return 0;
+
+ len = context->srtchlen;
+ p_attr = (struct xfs_pattr *) name;
+ error = xfs_getpname(context->dp->i_mount, be64_to_cpu(p_attr->p_ino),
+ be32_to_cpu(p_attr->p_offset), context->scratch, &len);
+ if (error)
+ return 0;
+
+ /* round up to the nearest 8 byte alignment */
+ reclen = PARENT_ENTSIZE(namelen);
+ if ((context->index + reclen) >= context->bufsize) {
+ context->seen_enough = 1;
+ return 0;
+ }
+
+ p_entry = (struct xfs_parent *)(context->alist + context->index);
+ p_entry->p_ino = be64_to_cpu(p_attr->p_ino);
+ p_entry->p_offset = be32_to_cpu(p_attr->p_offset);
+
+ /*
+ * xfs_getpname() will write the name at the end of the buffer
+ * and null terminated. Copy the path and null to xfs_parent_t
+ */
+ memcpy(p_entry->p_name, context->scratch + context->srtchlen -1 - len,
+ len + 1);
+ p_entry->p_reclen = reclen;
+
+ context->index += reclen;
+ context->count++;
+ return 0;
+}
+
+/*
+ * Format an attribute and copy it out to the user's buffer.
+ * Take care to check values and protect against them changing later,
+ * we may be reading them directly out of a user buffer.
+ */
+/*ARGSUSED*/
+STATIC int
+xfs_attr_parentpaths_put_listent(
+ struct xfs_attr_list_context *context,
+ int flags,
+ unsigned char *name,
+ int namelen,
+ int valuelen,
+ unsigned char *value)
+{
+ int error;
+ int len;
+ int reclen;
+ struct xfs_pattr *p_attr;
+ struct xfs_parent *p_entry;
+
+ ASSERT(!(context->flags & ATTR_KERNOVAL));
+ ASSERT(context->count >= 0);
+ ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
+ ASSERT(namelen == sizeof(struct xfs_pattr));
+
+ /*
+ * Only list entries in the right namespace.
+ */
+ if ((context->flags & ATTR_PARENT) == 0)
+ return 0;
+
+ if (namelen != sizeof(struct xfs_pattr))
+ return 0;
+
+ len = context->srtchlen;
+ p_attr = (struct xfs_pattr *) name;
+ error = xfs_getpath(context->dp->i_mount, be64_to_cpu(p_attr->p_ino),
+ be32_to_cpu(p_attr->p_offset), context->scratch, &len);
+ if (error)
+ return 0;
+
+ /* round up to the nearest 8 byte alignment */
+ reclen = PARENT_ENTSIZE(len);
+ if ((context->index + reclen) >= context->bufsize) {
+ context->seen_enough = 1;
+ return 0;
+ }
+
+ p_entry = (struct xfs_parent *)(context->alist + context->index);
+ p_entry->p_ino = be64_to_cpu(p_attr->p_ino);
+ p_entry->p_offset = be32_to_cpu(p_attr->p_offset);
+
+ /*
+ * xfs_getpath() will write the path at the end of the buffer
+ * and null terminated. Copy the path and null to xfs_parent_t
+ */
+ memcpy(p_entry->p_name, context->scratch + context->srtchlen - 1 - len,
+ len + 1);
+ p_entry->p_reclen = reclen;
+
+ context->index += reclen;
+ context->count++;
+ return 0;
+}
+
+/*
+ * Generate a list of extended attribute parent directory path names */
+int
+xfs_parents_attr_list(
+ struct xfs_inode *dp,
+ char *buffer,
+ int bufsize,
+ int *count)
+{
+ struct attrlist_cursor_kern cursor;
+ struct xfs_attr_list_context context;
+ int error;
+
+ /*
+ * Check for a properly aligned buffer.
+ */
+ if (((long)buffer) & (sizeof(int)-1))
+ return XFS_ERROR(EFAULT);
+
+ /*
+ * Initialize the output buffer.
+ */
+ memset(&cursor, 0, sizeof(cursor));
+ memset(&context, 0, sizeof(context));
+ context.dp = dp;
+ context.cursor = &cursor;
+ context.resynch = 1;
+ context.flags = ATTR_PARENT;
+ context.alist = buffer;
+ context.bufsize = (bufsize & ~(sizeof(int)-1)); /* align */
+ context.firstu = context.bufsize;
+ context.put_listent = xfs_attr_parents_put_listent;
+ context.scratch = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
+ context.srtchlen = MAXPATHLEN+1;
+ *(context.scratch+MAXPATHLEN) = '\0';
+
+ if (dp->i_d.di_parent != NULLFSINO) {
+ struct xfs_pattr p_attr;
+
+ /* copy the incore entry */
+ p_attr.p_ino = dp->i_d.di_parent;
+ p_attr.p_offset = dp->i_d.di_poffset;
+ xfs_attr_parents_put_listent(&context, ATTR_PARENT,
+ (char *)&p_attr, sizeof(p_attr), 0, NULL);
+ if (context.seen_enough) {
+ *count = context.count;
+ error = ERANGE;
+ goto freeout;
+ }
+ }
+
+ /* copy the parent extended attribute entries */
+ error = xfs_attr_list_int(&context);
+
+ *count = context.count;
+ if (context.seen_enough) {
+ /*
+ * The buffer is full and we return error.
+ * User would need to recall us with a bigger buffer.
+ */
+ error = ERANGE;
+ }
+ freeout:
+ kfree(context.scratch);
+ return XFS_ERROR(error);
+}
+
+/*
+ * Generate a list of extended attribute parent directory path names
+ */
+int
+xfs_parentpaths_attr_list(
+ struct xfs_inode *dp,
+ char *buffer,
+ int bufsize,
+ int *count)
+{
+ struct attrlist_cursor_kern cursor;
+ struct xfs_attr_list_context context;
+ int error;
+
+ /*
+ * Check for a properly aligned buffer.
+ */
+ if (((long)buffer) & (sizeof(int) - 1))
+ return XFS_ERROR(EFAULT);
+
+ /*
+ * Initialize the output buffer.
+ */
+ memset(&cursor, 0, sizeof(cursor));
+ memset(&context, 0, sizeof(context));
+ context.dp = dp;
+ context.cursor = &cursor;
+ context.resynch = 1;
+ context.flags = ATTR_PARENT;
+ context.alist = buffer;
+ context.bufsize = (bufsize & ~(sizeof(int) - 1)); /* align */
+ context.firstu = context.bufsize;
+ context.put_listent = xfs_attr_parentpaths_put_listent;
+ context.scratch = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
+ context.srtchlen = MAXPATHLEN+1;
+ *(context.scratch+MAXPATHLEN) = '\0';
+
+ if (dp->i_d.di_parent != NULLFSINO) {
+ struct xfs_pattr p_attr;
+
+ /* copy the incore entry */
+ p_attr.p_ino = dp->i_d.di_parent;
+ p_attr.p_offset = dp->i_d.di_poffset;
+ xfs_attr_parentpaths_put_listent(&context, ATTR_PARENT,
+ (char *)&p_attr, sizeof(p_attr), 0, NULL);
+ if (context.seen_enough) {
+ *count = context.count;
+ error = ERANGE;
+ goto freeout;
+ }
+ }
+
+ /* copy the parent extended attribute entries */
+ error = xfs_attr_list_int(&context);
+
+ *count = context.count;
+ if (context.seen_enough) {
+ /*
+ * The buffer is full and we return error.
+ * User would need to recall us with a bigger buffer.
+ */
+ error = ERANGE;
+ }
+ freeout:
+ kfree(context.scratch);
+ return XFS_ERROR(error);
+}
Index: b/fs/xfs/xfs_parent.h
===================================================================
--- a/fs/xfs/xfs_parent.h
+++ b/fs/xfs/xfs_parent.h
@@ -28,6 +28,22 @@ struct xfs_pattr {
__be32 p_offset;
} __attribute__((packed));
+/* xfs_readdir fill program private data */
+struct xfs_pfillinfo {
+ struct dir_context ctx; /* must be first entry */
+ int gp_len;
+ int gp_off;
+ char *gp_path;
+};
+
+typedef struct xfs_parent {
+ uint64_t p_ino; /* parent inode number */
+ uint32_t p_offset; /* entry offset in parent inode */
+ uint16_t p_reclen; /* name length */
+ uint16_t p_pad; /* padding for future */
+ char p_name[1]; /* variable length name */
+} xfs_parent_t;
+
static inline void xfs_parent_pname(xfs_ino_t ino, __uint32_t off, struct xfs_pattr *pe, struct xfs_name *pn)
{
pe->p_ino = cpu_to_be64(ino);
@@ -36,9 +52,21 @@ static inline void xfs_parent_pname(xfs_
pn->len = sizeof(struct xfs_pattr);
}
+/* actual bytes used by parent entry */
+#define PARENT_ENTSIZE(namelen) \
+ ((offsetof(struct xfs_parent, p_name) + (namelen) + 1 + \
+ sizeof(uint64_t)-1) & ~(sizeof(uint64_t)-1))
+
+int xfs_getpath(struct xfs_mount *mp, xfs_ino_t pino, xfs_off_t offset,
+ char *path, int *plen);
+int xfs_getpname(struct xfs_mount *mp, xfs_ino_t pino, xfs_off_t offset,
+ char *path, int *plen);
+int xfs_parents_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
+ int *count);
+int xfs_parentpaths_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
+ int *count);
int xfs_pptr_rename(struct xfs_mount *mp, struct xfs_trans *tp,
struct xfs_inode *src_dp, struct xfs_inode *target_dp,
struct xfs_inode *src_ip, struct xfs_inode *target_ip,
uint src_offset, uint tar_offset);
#endif /* __XFS_PARENT_H__ */
-
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
next prev parent reply other threads:[~2014-01-16 0:30 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-01-15 22:00 [RFC 00/17] RFC parent inode pointers Mark Tinguely
2014-01-15 22:00 ` [RFC 01/17] xfs: (parent ptr) get offset when adding directory name Mark Tinguely
2014-01-15 22:00 ` [RFC 02/17] xfs: (parent ptr) get offset when removing " Mark Tinguely
2014-01-15 22:00 ` [RFC 03/17] xfs: (parent ptr) get offset when replacing a " Mark Tinguely
2014-01-15 22:00 ` [RFC 04/17] xfs: (parent ptr) add parent pointer support to xfs_sb.h Mark Tinguely
2014-01-15 22:00 ` [RFC 05/17] xfs: (parent ptr) add parent pointer support to attribute code Mark Tinguely
2014-01-15 22:00 ` [RFC 06/17] xfs: (parent ptr) add parent pointer support to inode v5 Mark Tinguely
2014-01-15 22:00 ` [RFC 07/17] xfs: (parent ptr) add parent pointer support to xfs_create Mark Tinguely
2014-01-15 22:00 ` [RFC 08/17] xfs: (parent ptr) add parent pointer support to xfs_symlink Mark Tinguely
2014-01-15 22:00 ` [RFC 09/17] xfs: (parent ptr) add parent pointer support to xfs_link Mark Tinguely
2014-01-15 22:00 ` [RFC 10/17] xfs: (parent ptr) add parent pointer support to xfs_remove Mark Tinguely
2014-01-15 22:00 ` [RFC 11/17] xfs: (parent ptr) add parent pointer support to xfs_rename Mark Tinguely
2014-01-15 22:00 ` Mark Tinguely [this message]
2014-01-15 22:00 ` [RFC 13/17] xfsprogs: add parent pointer support into Linux 3.10 inode 3 Mark Tinguely
2014-01-15 22:00 ` [RFC 14/17] xfsprogs: add parent pointer values to headers and fix repair Mark Tinguely
2014-01-15 22:00 ` [RFC 15/17] xfsprogs: add basic parent pointer support to xfs_db Mark Tinguely
2014-01-15 22:00 ` [RFC 16/17] xfsprogs: add parent pointer support to xfs_io Mark Tinguely
2014-01-15 22:00 ` [RFC 17/17] xfsprogs: add parent GEOM information Mark Tinguely
2014-01-16 5:56 ` [RFC 00/17] RFC parent inode pointers Dave Chinner
2014-01-17 21:25 ` Mark Tinguely
2014-01-18 3:12 ` Dave Chinner
2014-01-27 19:41 ` Mark Tinguely
2014-01-28 3:00 ` Dave Chinner
2014-01-28 22:02 ` Geoffrey Wehrman
2014-02-04 0:09 ` Dave Chinner
2014-02-04 5:37 ` Geoffrey Wehrman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20140116000852.215757527@sgi.com \
--to=tinguely@sgi.com \
--cc=xfs@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).