From: Tim Shimmin Date: Mon, 14 Nov 2005 14:07:56 +0000 (+0000) Subject: Parent pointer userspace support. Adds in libhandle code and xfs_io parent command... X-Git-Tag: v2.8.0~63 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=258b00ead0037ad13f288c8130cc888b57153a09;p=thirdparty%2Fxfsprogs-dev.git Parent pointer userspace support. Adds in libhandle code and xfs_io parent command support. Merge of master-melb:xfs-cmds:24394a by kenmcd. Add getparents handle functions. --- diff --git a/include/handle.h b/include/handle.h index 8505db0c0..777df22c7 100644 --- a/include/handle.h +++ b/include/handle.h @@ -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); diff --git a/include/irix.h b/include/irix.h index ca9345713..d03afb52e 100644 --- a/include/irix.h +++ b/include/irix.h @@ -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__ */ diff --git a/include/jdm.h b/include/jdm.h index c84b70e8b..0410a9ea3 100644 --- a/include/jdm.h +++ b/include/jdm.h @@ -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 index 000000000..f338f96b4 --- /dev/null +++ b/include/parent.h @@ -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 diff --git a/io/Makefile b/io/Makefile index c9224788d..e7a5de068 100644 --- a/io/Makefile +++ b/io/Makefile @@ -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) diff --git a/io/init.c b/io/init.c index 33361b933..8cb5cfeeb 100644 --- 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 5c002204b..8ae431b3d 100644 --- 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 diff --git a/io/open.c b/io/open.c index 1361e6610..9f02a92c9 100644 --- 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 index 000000000..155660bdb --- /dev/null +++ b/io/parent.c @@ -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 +#include +#include +#include +#include +#include +#include +#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); +} diff --git a/libhandle/handle.c b/libhandle/handle.c index dbd40f182..4bd052b23 100644 --- a/libhandle/handle.c +++ b/libhandle/handle.c @@ -18,6 +18,7 @@ #include #include +#include /* 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 diff --git a/libhandle/jdm.c b/libhandle/jdm.c index ae94ed3d7..bac68c0a9 100644 --- a/libhandle/jdm.c +++ b/libhandle/jdm.c @@ -19,6 +19,7 @@ #include #include #include +#include /* 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 +} diff --git a/man/man3/handle.3 b/man/man3/handle.3 index 67dbc198a..9caee1f6c 100644 --- a/man/man3/handle.3 +++ b/man/man3/handle.3 @@ -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 @@ -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), diff --git a/man/man8/xfs_io.8 b/man/man8/xfs_io.8 index 673c65bcb..99903db34 100644 --- a/man/man8/xfs_io.8 +++ b/man/man8/xfs_io.8 @@ -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),