]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
Parent pointer userspace support. Adds in libhandle code and xfs_io parent command...
authorTim Shimmin <tes@sgi.com>
Mon, 14 Nov 2005 14:07:56 +0000 (14:07 +0000)
committerTim Shimmin <tes@sgi.com>
Mon, 14 Nov 2005 14:07:56 +0000 (14:07 +0000)
Merge of master-melb:xfs-cmds:24394a by kenmcd.

  Add getparents handle functions.

13 files changed:
include/handle.h
include/irix.h
include/jdm.h
include/parent.h [new file with mode: 0644]
io/Makefile
io/init.c
io/io.h
io/open.c
io/parent.c [new file with mode: 0644]
libhandle/handle.c
libhandle/jdm.c
man/man3/handle.3
man/man8/xfs_io.8

index 8505db0c09cc45c0f54c9a6a1a908943b32220b9..777df22c749c2d06eb299f5385654f3069c0f08b 100644 (file)
@@ -24,6 +24,8 @@ extern "C" {
 
 struct fsdmidata;
 struct attrlist_cursor;
+struct parent_cursor;
+struct parent;
 
 extern int  path_to_handle (char *__path, void **__hanp, size_t *__hlen);
 extern int  path_to_fshandle (char *__path, void **__fshanp, size_t *__fshlen);
@@ -39,6 +41,14 @@ extern int  attr_multi_by_handle (void *__hanp, size_t __hlen, void *__buf,
 extern int  attr_list_by_handle (void *__hanp, size_t __hlen, void *__buf,
                                 size_t __bufsize, int __flags,
                                 struct attrlist_cursor *__cursor);
+extern int  getparents_by_handle(void *__hanp, size_t __hlen,
+                                struct parent *__buf, size_t __bufsize,
+                                struct parent_cursor *__cursor,
+                                unsigned int *__count, unsigned int *__more);
+extern int  getparentpaths_by_handle(void *__hanp, size_t __hlen,
+                                    struct parent *__buf, size_t __bufsize,
+                                    struct parent_cursor *__cursor,
+                                    unsigned int *__count, unsigned int *__more);
 extern int  fssetdm_by_handle (void *__hanp, size_t __hlen,
                               struct fsdmidata *__fsdmi);
 
index ca93457137d41cc2fdfbb621dbeeda066510137b..d03afb52ed4134ffc112c09389057b194de01ada 100644 (file)
@@ -101,6 +101,15 @@ typedef struct xfs_fsop_attrlist_handlereq {
        void                            *buffer;        /* returned names */
 } xfs_fsop_attrlist_handlereq_t;
 
+typedef struct xfs_fsop_getparents_handlereq {
+       struct xfs_fsop_handlereq       hreq; /* handle interface structure */
+       struct xfs_attrlist_cursor      pos; /* opaque cookie, list offset */
+       __u32                           buflen; /* length of buffer supplied */
+       void                            *buffer; /* returned data */
+       __u32                           *ocount; /* return number of links */
+       __u32                           *omore; /* return whether more to come */
+} xfs_fsop_getparents_handlereq_t;
+
 typedef struct xfs_attr_multiop {
        __u32           am_opcode;
        __s32           am_error;
@@ -196,6 +205,16 @@ static __inline__ int xfsctl(const char *path, int fd, int cmd, void *arg)
                                        ((xfs_fsop_attrlist_handlereq_t*)arg)->buflen,
                                        ((xfs_fsop_attrlist_handlereq_t*)arg)->flags,
                                        &(((xfs_fsop_attrlist_handlereq_t*)arg)->pos));
+               case SGI_XFS_GETPARENTS:
+               case SGI_XFS_GETPARENTPATHS:
+                       return syssgi(cmd,
+                                       ((xfs_fsop_getparents_handlereq_t*)arg)->hreq.ihandle,
+                                       ((xfs_fsop_getparents_handlereq_t*)arg)->hreq.ihandlen,
+                                       ((xfs_fsop_getparents_handlereq_t*)arg)->buffer,
+                                       ((xfs_fsop_getparents_handlereq_t*)arg)->buflen,
+                                       &(((xfs_fsop_getparents_handlereq_t*)arg)->pos),
+                                       ((xfs_fsop_getparents_handlereq_t*)arg)->ocount,
+                                       ((xfs_fsop_getparents_handlereq_t*)arg)->omore);
                case SGI_ATTR_MULTI_BY_HANDLE:
                        return syssgi(cmd,
                                        ((xfs_fsop_attrmulti_handlereq_t*)arg)->hreq.ihandle,
@@ -302,5 +321,7 @@ static __inline__ char * strsep(char **s, const char *ct)
 #define XFS_IOC_ATTRMULTI_BY_HANDLE    SGI_ATTR_MULTI_BY_HANDLE
 #define XFS_IOC_FSGEOMETRY             XFS_FS_GEOMETRY
 #define XFS_IOC_GOINGDOWN              XFS_FS_GOINGDOWN
+#define XFS_IOC_GETPARENTS             SGI_XFS_GETPARENTS
+#define XFS_IOC_GETPARENTPATHS         SGI_XFS_GETPARENTPATHS
 
 #endif /* __XFS_IRIX_H__ */
index c84b70e8be9610ce1412e1f3c5dd75bf09ef4753..0410a9ea3a3097f080f5b5b5f23949939d8557e2 100644 (file)
@@ -24,6 +24,8 @@ typedef void  jdm_filehandle_t;       /* filehandle */
 
 struct xfs_bstat;
 struct attrlist_cursor;
+struct parent_cursor;
+struct parent;
 
 extern jdm_fshandle_t *
 jdm_getfshandle( char *mntpnt);
@@ -60,6 +62,20 @@ jdm_attr_list(       jdm_fshandle_t *fshp,
                char *bufp, size_t bufsz, int flags,
                struct attrlist_cursor *cursor);
 
+extern int
+jdm_getparents( jdm_fshandle_t *fshp,
+               xfs_bstat_t *statp,
+               struct parent *bufp, size_t bufsz,
+               struct parent_cursor *cursor,
+               unsigned int *count, unsigned int *more);
+
+extern int
+jdm_getparentpaths( jdm_fshandle_t *fshp,
+               xfs_bstat_t *statp,
+               struct parent *bufp, size_t bufsz,
+               struct parent_cursor *cursor,
+               unsigned int *count, unsigned int *more);
+
 /* macro for determining the size of a structure member */
 #define sizeofmember( t, m )   sizeof( ( ( t * )0 )->m )
 
diff --git a/include/parent.h b/include/parent.h
new file mode 100644 (file)
index 0000000..f338f96
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 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 Lesser 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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 __PARENT_H__
+#define        __PARENT_H__
+
+typedef struct parent {
+       __u64   p_ino;
+       __u32   p_gen;
+       __u16   p_reclen;
+       char    p_name[1];
+} parent_t;
+
+typedef struct parent_cursor {
+       __u32   opaque[4];      /* an opaque cookie */
+} parent_cursor_t;
+
+#endif
index c9224788d6807d66c21bde18ff846af30f3c89f0..e7a5de0685151bcd0b62da3bd9f9fb3ff32df52f 100644 (file)
@@ -44,11 +44,14 @@ else
 LSRCFILES += sendfile.c
 endif
 
-ifneq ($(PKG_PLATFORM),irix)
+ifeq ($(PKG_PLATFORM),irix)
+LSRCFILES += inject.c resblks.c shutdown.c
+CFILES += parent.c
+LCFLAGS += -DHAVE_PARENT
+else
+LSRCFILES += parent.c
 CFILES += inject.c resblks.c shutdown.c
 LCFLAGS += -DHAVE_INJECT -DHAVE_RESBLKS -DHAVE_SHUTDOWN
-else
-LSRCFILES += inject.c resblks.c shutdown.c
 endif
 
 ifeq ($(ENABLE_READLINE),yes)
index 33361b9336529d9a2360172c6c0cb3bb14d65047..8cb5cfeebb607d38422ecc1c89264dad934889bf 100644 (file)
--- a/io/init.c
+++ b/io/init.c
@@ -66,6 +66,7 @@ init_commands(void)
        inject_init();
        mmap_init();
        open_init();
+       parent_init();
        pread_init();
        prealloc_init();
        pwrite_init();
diff --git a/io/io.h b/io/io.h
index 5c002204bcaa9fea5f622a44cb028ed17f25fc4c..8ae431b3d657a0708e63bf3e70029d72f8c24233 100644 (file)
--- a/io/io.h
+++ b/io/io.h
@@ -146,3 +146,8 @@ extern void         mincore_init(void);
 #define mincore_init() do { } while (0)
 #endif
 
+#ifdef HAVE_PARENT
+extern void            parent_init(void);
+#else
+#define parent_init()  do { } while (0)
+#endif
index 1361e66101d1e4956cfa44dfd3aa6d9aa975a424..9f02a92c9b956b8acd844e7839d58a73630fdeb7 100644 (file)
--- a/io/open.c
+++ b/io/open.c
@@ -135,8 +135,20 @@ openfile(
 
        fd = open(path, oflags, mode);
        if (fd < 0) {
-               perror(path);
-               return -1;
+               if ((errno == EISDIR) && (oflags & O_RDWR)) {
+                       /* make it as if we asked for O_RDONLY & try again */
+                       oflags &= ~O_RDWR;
+                       oflags |= O_RDONLY;
+                       flags |= IO_READONLY;
+                       fd = open(path, oflags, mode);
+                       if (fd < 0) {
+                               perror(path);
+                               return -1;
+                       }
+               } else {
+                       perror(path);
+                       return -1;
+               }
        }
 
        if (!geom)
diff --git a/io/parent.c b/io/parent.c
new file mode 100644 (file)
index 0000000..155660b
--- /dev/null
@@ -0,0 +1,447 @@
+/*
+ * Copyright (c) 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
+ */
+
+#include <xfs/xfs.h>
+#include <xfs/command.h>
+#include <xfs/input.h>
+#include <xfs/path.h>
+#include <xfs/parent.h>
+#include <xfs/handle.h>
+#include <xfs/jdm.h>
+#include "init.h"
+#include "io.h"
+
+#define PARENTBUF_SZ           16384
+#define BSTATBUF_SZ            4096
+
+static cmdinfo_t parent_cmd;
+static int verbose_flag;
+static int err_status;
+static uint64_t inodes_checked;
+
+/*
+ * check out a parent entry to see if the values seem valid
+ */
+static void
+check_parent_entry(xfs_bstat_t *bstatp, parent_t *parent, char *mntpt)
+{
+       int sts;
+       char fullpath[PATH_MAX];
+       struct stat statbuf;
+       char *str;
+
+       sprintf(fullpath, _("%s%s"), mntpt, parent->p_name);
+
+       sts = lstat(fullpath, &statbuf);
+       if (sts != 0) {
+               fprintf(stderr,
+                       _("inode-path for inode: %llu is incorrect - path non-existent\n"),
+                       bstatp->bs_ino);
+               if (verbose_flag) {
+                       fprintf(stderr,
+                               _("path \"%s\" does not stat for inode: %llu; err = %s\n"),
+                               fullpath,
+                               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"),
+                       bstatp->bs_ino);
+               if (verbose_flag) {
+                       fprintf(stderr,
+                               _("ino mismatch for path \"%s\" %llu vs %llu\n"),
+                               fullpath,
+                               statbuf.st_ino,
+                               bstatp->bs_ino);
+               }
+               err_status++;
+               return;
+       } else if (verbose_flag > 1) {
+               printf(_("inode number match: %llu\n"), 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"),
+                               bstatp->bs_ino);
+                       if (verbose_flag) {
+                               fprintf(stderr,
+                                       _("ino mismatch for path \"%s\" %llu vs %llu\n"),
+                                       fullpath,
+                                       parent->p_ino,
+                                       statbuf.st_ino);
+                       }
+                       err_status++;
+                       return;
+               } else {
+                       if (verbose_flag > 1) {
+                               printf(_("parent ino match for %llu\n"), parent->p_ino);
+                       }
+               }
+       }
+}
+
+static void
+check_parents(parent_t *parentbuf, jdm_fshandle_t *fshandlep, xfs_bstat_t *statp, char *mntpt)
+{
+       int error, i;
+       __u32 count, more;
+       parent_t *entryp;
+       parent_cursor_t cursor;
+
+       memset(&cursor, 0, sizeof(cursor));
+       do {
+               error = jdm_getparentpaths(fshandlep,
+                                          statp,
+                                          parentbuf,
+                                          PARENTBUF_SZ,
+                                          &cursor,
+                                          &count,
+                                          &more);
+
+               if (error) {
+                       fprintf(stderr, _("getparentpaths failed for ino %llu: %s\n"),
+                               statp->bs_ino,
+                               strerror(error));
+                       err_status++;
+                       break;
+               }
+
+               if (count == 0) {
+                       /* no links for inode - something wrong here */
+                       fprintf(stderr, _("inode-path for inode: %llu is missing\n"), statp->bs_ino);
+                       err_status++;
+                       break;
+               }
+
+               entryp = parentbuf;
+               for (i = 0; i < count; i++) {
+                       check_parent_entry(statp, entryp, mntpt);
+                       entryp = (parent_t*) (((char*)entryp) + entryp->p_reclen);
+               }
+
+       } while(more);
+}
+
+static int
+do_bulkstat(parent_t *parentbuf, xfs_bstat_t *bstatbuf,
+           char *mntpt, int fsfd, jdm_fshandle_t *fshandlep)
+{
+       int error;
+       int buflenout;
+       ino64_t lastino = 0;
+       xfs_bstat_t *p;
+       xfs_bstat_t *endp;
+       xfs_fsop_bulkreq_t bulkreq;
+       struct stat mntstat;
+
+       if ((error = stat(mntpt, &mntstat))) {
+               fprintf(stderr, _("can't stat mount point \"%s\": %s\n"),
+                       mntpt, strerror(error));
+               return 1;
+       }
+
+       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"),
+                                         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"),
+                                         p->bs_ino );
+                                   continue;
+                               }
+                       }
+
+                       /* skip root */
+                       if (p->bs_ino == mntstat.st_ino) {
+                               continue;
+                       }
+
+                       if (verbose_flag > 1) {
+                               printf(_("checking inode %llu\n"), p->bs_ino);
+                       }
+
+                       /* print dotted progress */
+                       if ((inodes_checked % 100) == 0 && verbose_flag == 1) {
+                               printf("."); fflush(stdout);
+                       }
+                       inodes_checked++;
+
+                       check_parents(parentbuf, fshandlep, p, mntpt);
+               }
+
+       }/*while*/
+
+       fprintf(stderr, _("syssgi bulkstat failed: %s\n"), strerror(errno));
+       return 1;
+}
+
+static int
+parent_check(void)
+{
+       static int tab_init;
+       char *mntpt;
+       fs_path_t *fs;
+       int fsfd;
+       jdm_fshandle_t *fshandlep;
+       parent_t *parentbuf;
+       xfs_bstat_t *bstatbuf;
+
+       err_status = 0;
+       inodes_checked = 0;
+
+       sync();
+
+       if (!tab_init) {
+               tab_init = 1;
+               fs_table_initialise();
+       }
+       fs = fs_table_lookup(file->name, FS_MOUNT_POINT);
+       if (!fs) {
+               fprintf(stderr, _("file argument, \"%s\", is not in a mounted XFS filesystem\n"),
+                       file->name);
+               return 1;
+       }
+       mntpt = fs->fs_dir;
+        fsfd = file->fd;
+
+       fshandlep = jdm_getfshandle(mntpt);
+       if (fshandlep == 0) {
+               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_SZ);
+       if (!bstatbuf || !parentbuf) {
+               fprintf(stderr, _("unable to allocate buffers: %s\n"),
+                       strerror(errno));
+               return 1;
+       }
+
+       if (do_bulkstat(parentbuf, bstatbuf, mntpt, fsfd, fshandlep) != 0)
+               err_status++;
+
+       if (err_status > 0)
+               fprintf(stderr, _("num errors: %d\n"), err_status);
+       else
+               printf(_("succeeded checking %llu inodes\n"), inodes_checked);
+
+       free(bstatbuf);
+       free(parentbuf);
+       return err_status;
+}
+
+static void
+print_parent_entry(parent_t *parent)
+{
+       printf(_("p_ino    = %llu\n"),  parent->p_ino);
+       printf(_("p_gen    = %u\n"),    parent->p_gen);
+       printf(_("p_reclen = %u\n"),    parent->p_reclen);
+       printf(_("p_name   = \"%s\"\n"),parent->p_name);
+}
+
+static int
+parent_list(int fullpath)
+{
+       void *handlep;
+       size_t handlen;
+       int error, i;
+       int retval = 1;
+       __u32 count, more;
+       parent_t *entryp;
+       parent_cursor_t cursor;
+       parent_t *parentbuf;
+       char *path = file->name;
+
+       parentbuf = (parent_t *)malloc(PARENTBUF_SZ);
+       if (!parentbuf) {
+               fprintf(stderr, _("%s: unable to allocate parent buffer: %s\n"),
+                       progname, strerror(errno));
+               return 1;
+       }
+
+       /* XXXX for linux libhandle version - to set libhandle fsfd cache */
+       {
+               void *fshandle;
+               size_t fshlen;
+
+               if (path_to_fshandle(path, &fshandle, &fshlen) != 0) {
+                       fprintf(stderr, _("%s: failed path_to_fshandle \"%s\": %s\n"),
+                               progname, path, strerror(errno));
+                       goto error;
+               }
+       }
+
+       if (path_to_handle(path, &handlep, &handlen) != 0) {
+               fprintf(stderr, _("%s: path_to_handle failed for \"%s\"\n"), progname, path);
+               goto error;
+       }
+
+       memset(&cursor, 0, sizeof(cursor));
+       do {
+               if (fullpath) {
+                       error = getparentpaths_by_handle(handlep,
+                                                      handlen,
+                                                      parentbuf,
+                                                      PARENTBUF_SZ,
+                                                      &cursor,
+                                                      &count,
+                                                      &more);
+               } else {
+                       error = getparents_by_handle(handlep,
+                                                  handlen,
+                                                  parentbuf,
+                                                  PARENTBUF_SZ,
+                                                  &cursor,
+                                                  &count,
+                                                  &more);
+               }
+
+               if (error) {
+                       fprintf(stderr, _("%s: getparentpaths failed for \"%s\": %s\n"),
+                               progname, path, strerror(errno));
+                       goto error;
+               }
+
+               if (count == 0) {
+                       /* no links for inode - something wrong here */
+                       fprintf(stderr, _("%s: inode-path is missing\n"), progname);
+                       goto error;
+               }
+
+               entryp = parentbuf;
+               for (i = 0; i < count; i++) {
+                       print_parent_entry(entryp);
+                       entryp = (parent_t*) (((char*)entryp) + entryp->p_reclen);
+               }
+
+       } while(more);
+
+       retval = 0;
+error:
+       free(parentbuf);
+       return retval;
+}
+
+int
+parent_f(int argc, char **argv)
+{
+       int c;
+       int listpath_flag = 0;
+       int check_flag = 0;
+
+       verbose_flag = 0;
+
+       while ((c = getopt(argc, argv, "cpv")) != 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();
+       }
+
+       return 0;
+}
+
+static void
+parent_help(void)
+{
+       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"
+"\n"));
+}
+
+void
+parent_init(void)
+{
+       parent_cmd.name = _("parent");
+       parent_cmd.cfunc = parent_f;
+       parent_cmd.argmin = 0;
+       parent_cmd.argmax = -1;
+       parent_cmd.args = _("[-cpv]");
+       parent_cmd.flags = CMD_NOMAP_OK;
+       parent_cmd.oneline = _("print or check parent inodes");
+       parent_cmd.help = parent_help;
+
+       if (expert)
+               add_command(&parent_cmd);
+}
index dbd40f18280d54b5d182f8e444cc2ea4dd0b70bc..4bd052b23cf087cbce02108494e64b168da885d3 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <xfs/xfs.h>
 #include <xfs/handle.h>
+#include <xfs/parent.h>
 
 /* just pick a value we know is more than big enough */
 #define        MAXHANSIZ       64
@@ -342,7 +343,7 @@ attr_list_by_handle(
        int             flags,
        struct attrlist_cursor *cursor)
 {
-       int             fd;
+       int             error, fd;
        char            *path;
        xfs_fsop_attrlist_handlereq_t alhreq;
 
@@ -362,7 +363,93 @@ attr_list_by_handle(
        alhreq.buflen = bufsize;
        alhreq.buffer = buf;
 
-       return xfsctl(path, fd, XFS_IOC_ATTRLIST_BY_HANDLE, &alhreq);
+       error = xfsctl(path, fd, XFS_IOC_ATTRLIST_BY_HANDLE, &alhreq);
+
+       memcpy(cursor, &alhreq.pos, sizeof(alhreq.pos));
+       return error;
+}
+
+int
+getparents_by_handle(
+       void            *hanp,
+       size_t          hlen,
+       parent_t        *buf,
+       size_t          bufsiz,
+       parent_cursor_t *cursor,
+       unsigned int    *count,
+       unsigned int    *more)
+{
+#if !defined(__sgi__)
+       errno = EOPNOTSUPP;
+       return -1;
+#else
+
+       int             error, fd;
+       char            *path;
+       xfs_fsop_getparents_handlereq_t gphreq;
+
+       if ((fd = handle_to_fsfd(hanp, &path)) < 0)
+               return -1;
+
+       gphreq.hreq.fd       = 0;
+       gphreq.hreq.path     = NULL;
+       gphreq.hreq.oflags   = O_LARGEFILE;
+       gphreq.hreq.ihandle  = hanp;
+       gphreq.hreq.ihandlen = hlen;
+       gphreq.hreq.ohandle  = NULL;
+       gphreq.hreq.ohandlen = NULL;
+       memcpy(&gphreq.pos, cursor, sizeof(gphreq.pos));
+       gphreq.buflen = bufsiz;
+       gphreq.buffer = buf;
+       gphreq.ocount = count;
+       gphreq.omore = more;
+
+       error = xfsctl(path, fd, XFS_IOC_GETPARENTS, &gphreq);
+
+       memcpy(cursor, &gphreq.pos, sizeof(gphreq.pos));
+       return error;
+#endif
+}
+
+int
+getparentpaths_by_handle(
+       void            *hanp,
+       size_t          hlen,
+       parent_t        *buf,
+       size_t          bufsiz,
+       parent_cursor_t *cursor,
+       unsigned int    *count,
+       unsigned int    *more)
+{
+#if !defined(__sgi__)
+       errno = EOPNOTSUPP;
+       return -1;
+#else
+       int             error, fd;
+       char            *path;
+       xfs_fsop_getparents_handlereq_t gphreq;
+
+       if ((fd = handle_to_fsfd(hanp, &path)) < 0)
+               return -1;
+
+       gphreq.hreq.fd       = 0;
+       gphreq.hreq.path     = NULL;
+       gphreq.hreq.oflags   = O_LARGEFILE;
+       gphreq.hreq.ihandle  = hanp;
+       gphreq.hreq.ihandlen = hlen;
+       gphreq.hreq.ohandle  = NULL;
+       gphreq.hreq.ohandlen = NULL;
+       memcpy(&gphreq.pos, cursor, sizeof(gphreq.pos));
+       gphreq.buflen = bufsiz;
+       gphreq.buffer = buf;
+       gphreq.ocount = count;
+       gphreq.omore = more;
+
+       error = xfsctl(path, fd, XFS_IOC_GETPARENTPATHS, &gphreq);
+
+       memcpy(cursor, &gphreq.pos, sizeof(gphreq.pos));
+       return error;
+#endif
 }
 
 int
index ae94ed3d7c211d66e0ad910d4ea73dfe2821fa73..bac68c0a93260ba5ab91aa451a5ee3cdfad8d20b 100644 (file)
@@ -19,6 +19,7 @@
 #include <xfs/xfs.h>
 #include <xfs/handle.h>
 #include <xfs/jdm.h>
+#include <xfs/parent.h>
 
 /* internal fshandle - typecast to a void for external use */
 #define FSHANDLE_SZ            8
@@ -171,3 +172,45 @@ jdm_attr_list(     jdm_fshandle_t *fshp,
                        bufp, bufsz, flags, cursor);
        return rval;
 }
+
+int
+jdm_getparents( jdm_fshandle_t *fshp,
+               xfs_bstat_t *statp,
+               parent_t *bufp, size_t bufsz,
+               parent_cursor_t *cursor,
+               unsigned int *count, unsigned int *more)
+{
+#if !defined(__sgi__)
+       errno = EOPNOTSUPP;
+       return -1;
+#else
+       register fshandle_t *fshandlep = ( fshandle_t * )fshp;
+       filehandle_t filehandle;
+
+       jdm_fill_filehandle( &filehandle, fshandlep, statp );
+       return getparents_by_handle (( void * )&filehandle,
+                       sizeof( filehandle ),
+                       bufp, bufsz, cursor, count, more);
+#endif
+}
+
+int
+jdm_getparentpaths( jdm_fshandle_t *fshp,
+               xfs_bstat_t *statp,
+               parent_t *bufp, size_t bufsz,
+               parent_cursor_t *cursor,
+               unsigned int *count, unsigned int *more)
+{
+#if !defined(__sgi__)
+       errno = EOPNOTSUPP;
+       return -1;
+#else
+       register fshandle_t *fshandlep = ( fshandle_t * )fshp;
+       filehandle_t filehandle;
+
+       jdm_fill_filehandle( &filehandle, fshandlep, statp );
+       return getparentpaths_by_handle (( void * )&filehandle,
+                       sizeof( filehandle ),
+                       bufp, bufsz, cursor, count, more);
+#endif
+}
index 67dbc198a859e20a00cced5e223f3842162ccc42..9caee1f6ccbbcd32169afd36bec0c1628b89ade0 100644 (file)
@@ -1,6 +1,6 @@
 .TH HANDLE 3 
 .SH NAME
-path_to_handle, path_to_fshandle, fd_to_handle, handle_to_fshandle, open_by_handle, readlink_by_handle, attr_multi_by_handle, attr_list_by_handle, fssetdm_by_handle, free_handle \- file handle operations
+path_to_handle, path_to_fshandle, fd_to_handle, handle_to_fshandle, open_by_handle, readlink_by_handle, attr_multi_by_handle, attr_list_by_handle, fssetdm_by_handle, free_handle, getparents_by_handle, getparentpaths_by_handle \- file handle operations
 .SH C SYNOPSIS
 .nf
 .B #include <sys/types.h>
@@ -36,6 +36,16 @@ path_to_handle, path_to_fshandle, fd_to_handle, handle_to_fshandle, open_by_hand
 .B "                       struct fsdmidata *fssetdm);"
 .PP
 .B "void free_handle (void *hanp, size_t hlen);
+.PP
+.B "int getparents_by_handle(void *hanp, size_t hlen,"
+.B "                         parent_t *buf, size_t bufsiz,"
+.B "                         parent_cursor_t *cursor,"
+.B "                         unsigned int *count, unsigned int *more);"
+.PP
+.B "int getparentpaths_by_handle(void *hanp, size_t hlen,"
+.B "                             parent_t *buf, size_t bufsiz,"
+.B "                             parent_cursor_t *cursor,"
+.B "                             unsigned int *count, unsigned int *more);"
 .Op
 .SH DESCRIPTION
 .PP
@@ -135,6 +145,19 @@ returned by the following functions:
 \f2fd_to_handle\f1(),
 and
 \f2handle_to_fshandle\f1().
+.P
+The \f2getparents_by_handle\f1() function returns an array
+of \f2parent_t\f1 structures for each hardlink to
+the inode represented by the given handle. The parent structure
+encodes the parent inode number, generation number and the 
+basename of the link.
+This function is not operational on Linux.
+.P
+The \f2getparentpaths_by_handle\f1() function is identical to
+the \f2getparents_by_handle\f1() function except that instead
+of returning the basename it returns the path of the link up
+to the mount point.
+This function is also not operational on Linux.
 .SH "SEE ALSO"
 open(2),
 readlink(2),
index 673c65bcbd1e92d48aaa147bc91e2212eb6247da..99903db340561ddc07c62686b3a24d80374c69c0 100644 (file)
@@ -309,6 +309,19 @@ If the \f2-v\f1 option is specified, the atime (last access), mtime
 \f3statfs\f1
 Selected statistics from \f2statfs\f1(2) and the XFS_IOC_FSGEOMETRY
 system call on the filesystem where the current file resides.
+.TP
+\f3parent\f1 [ \f2\-cpv\f1 ]
+By default this command prints out the parent inode numbers,
+inode generation numbers and basenames of all the hardlinks which
+point to the inode of the current file.
+If the \f2-p\f1 option is specified, then the output is similar 
+to the default output except pathnames up to the mount-point
+are printed out instead of the component name.
+If the \f2-c\f1 option is specified, then the file's filesystem
+will check all the parent attributes for consistency. 
+If the \f2-v\f1 option is specified, then verbose output will be
+printed.
+Not currently operational on Linux.
 
 .SH IRIX SEE ALSO
 mkfs_xfs(1M),