Hi John

Does the attached patch fix it?
It was a mistake in the code (not in the way you are using it). I only
tested the VFS code path and not the system interface path. Thanks for
the reports!

> pascal006:~>pvfs2-viewdist -f /mnt/pvfs2/hosts
> Not a meta file!
> Could not open /mnt/pvfs2/hosts
>
> The file does exist though:
> pascal006:~>pvfs2-ls /mnt/pvfs2/hosts
> hosts
>
> Am I doing something funny?
>
> Btw, the usage for pvfs2-viewdist is incorrect.  It says:
> Usage: pvfs2-viewdist ARGS src_file dest_file
> where ARGS are blah.
> But the code only looks at ARGS and not for src_file and dest_file.  Must
> have been copied from pvfs2-cp. :)

Oops. How embarassing :) I fixed that in the attached patch..

> Thanks by the way for all of the speedy replies I've been getting.  It
> really helps a lot to have such a well-monitored and well-supported
> mailing list.

Thank you for all reports!
Murali

>
> John
>
> On Mon, 21 Nov 2005, Murali Vilayannur wrote:
>
> > Hi,
> > Could you give the attached patch a go and see if it works out?
> > All it does is print the servers that hold chunks/strips of a file (both
> > for the VFS and system interface users) using xattrs.
> > Patch is against CVS.
> > P.S: RobR, I noticed that we arenot setting the fs_id field of the
> > statfs structure (statfs/fstatfs system call). Is/are there any
> > reason/reasons for not doing so?
> > I need that change to have VFS clients know the fs_id.
> > Thanks
> > Murali
> >
> > On Mon, 21 Nov 2005, Hamza KAYA wrote:
> >
> > > Hi,
> > > Thank you for the code. It works great:) I was able to find the
> > > distribution parameters of a file which was created by varstrip-dist.
> > > So by setting the jitter variable to a constant value in
> > > PINT_cached_config_get_next_io, I'll be able to find the physical
> > > mapping of a file to the datanodes, at least I hope so:) am I wrong?
> > >
> > > Thanks very much.
> > >
> > > P.S.:
> > > I posted this mail directly to Murali. So I re-post it to the list.
> > > Sorry for the inconvenience.
> > >
> > > --
> > > Hamza
> > >
> > > On 11/18/05, Murali Vilayannur <[EMAIL PROTECTED]> wrote:
> > > > Hi,
> > > > Does the attached program tell you the distribution at least? Compile it
> > > > like you compile pvfs2-cp or some other program. It uses the VFS 
> > > > fgetxattr
> > > > system call or the PVFS2 pvfs_sys_geteattr.
> > > >  If it works, then I will work on it some more and print out more of
> > > > the information that you wanted...
> > > > Thanks,
> > > > Murali
> > > >
> > > > On Fri, 18 Nov 2005, Hamza KAYA wrote:
> > > >
> > > > > Hi,
> > > > >
> > > > > Using PVFS2 system calls I was able to apply the varstrip
> > > > > distribution. Using pvfs2-fs-dump I can see the results. But I can't
> > > > > find out the reverse operation. I mean how can I learn the
> > > > > distribution of a file or the physical location of a given file using
> > > > > system calls?
> > > > >
> > > > > --
> > > > > hamza
> > > > >
> > > > > _______________________________________________
> > > > > PVFS2-users mailing list
> > > > > [email protected]
> > > > > http://www.beowulf-underground.org/mailman/listinfo/pvfs2-users
> > > > >
> > > > >
> > > >
> > > >
> > >
> > > _______________________________________________
> > > PVFS2-users mailing list
> > > [email protected]
> > > http://www.beowulf-underground.org/mailman/listinfo/pvfs2-users
> > >
> > >
>
>
diff -Naur pvfs2/src/apps/admin/module.mk.in 
new_pvfs2/src/apps/admin/module.mk.in
--- pvfs2/src/apps/admin/module.mk.in   2005-08-03 15:02:19.000000000 -0500
+++ new_pvfs2/src/apps/admin/module.mk.in       2005-11-23 14:21:29.000000000 
-0600
@@ -19,6 +19,7 @@
        $(DIR)/pvfs2-fs-dump.c\
        $(DIR)/pvfs2-fsck.c\
        $(DIR)/pvfs2-cp.c \
+       $(DIR)/pvfs2-viewdist.c \
        $(DIR)/pvfs2-touch.c \
        $(DIR)/pvfs2-remove-object.c \
        $(DIR)/pvfs2-ln.c
diff -Naur pvfs2/src/apps/admin/pvfs2-viewdist.c 
new_pvfs2/src/apps/admin/pvfs2-viewdist.c
--- pvfs2/src/apps/admin/pvfs2-viewdist.c       1969-12-31 17:00:00.000000000 
-0700
+++ new_pvfs2/src/apps/admin/pvfs2-viewdist.c   2005-11-23 14:21:10.000000000 
-0600
@@ -0,0 +1,417 @@
+/*
+ * (C) 2001 Clemson University and The University of Chicago
+ *
+ * See COPYING in top-level directory.
+ */
+
+/* pvfs2-viewdist
+ *  View the distribution information of a file        
+ *  by using extended attributes!
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <sys/statfs.h>
+#include <attr/xattr.h>
+
+#define __PINT_REQPROTO_ENCODE_FUNCS_C
+#include "pvfs2.h"
+#include "str-utils.h"
+#include "pint-sysint-utils.h"
+#include "pint-distribution.h"
+#include "pvfs2-dist-basic.h"
+#include "pvfs2-dist-simple-stripe.h"
+#include "pvfs2-dist-varstrip.h"
+
+struct options 
+{
+    char *srcfile;
+};
+
+enum object_type { 
+    UNIX_FILE, 
+    PVFS2_FILE 
+};
+
+typedef struct pvfs2_file_object_s {
+    PVFS_fs_id fs_id;
+    PVFS_object_ref ref;
+    char pvfs2_path[PVFS_NAME_MAX];    
+    char user_path[PVFS_NAME_MAX];
+    PVFS_sys_attr attr;
+    PVFS_permissions perms;
+} pvfs2_file_object;
+
+typedef struct unix_file_object_s {
+    int fd;
+    int mode;
+    char path[NAME_MAX];
+    PVFS_fs_id fs_id;
+} unix_file_object;
+
+typedef struct file_object_s {
+    int fs_type;
+    union {
+       unix_file_object ufs;
+       pvfs2_file_object pvfs2;
+    } u;
+} file_object;
+
+
+static struct options* parse_args(int argc, char* argv[]);
+static void usage(int argc, char** argv);
+static int resolve_filename(file_object *obj, char *filename);
+static int generic_open(file_object *obj, PVFS_credentials *credentials);
+static int generic_server_location(file_object *obj, PVFS_credentials *creds,
+        char **servers, int *nservers);
+
+#define DIST_KEY "metafile_dist"
+#define DFILE_KEY "datafile_handles"
+
+static int generic_dist(file_object *obj, PVFS_credentials *creds,
+        char **dist, int *size)
+{
+    char *buffer = (char *) malloc(4096);
+    int ret;
+    
+    if (obj->fs_type == UNIX_FILE)
+    {
+        if ((ret = fgetxattr(obj->u.ufs.fd, DIST_KEY, buffer, 4096)) < 0)
+        {
+            perror("fgetxattr:");
+            return -1;
+        }
+        *size = ret;
+    }
+    else
+    {
+        PVFS_ds_keyval key, val;
+
+        key.buffer = DIST_KEY;
+        key.buffer_sz = strlen(DIST_KEY) + 1;
+        val.buffer = buffer;
+        val.buffer_sz = 4096;
+        if ((ret = PVFS_sys_geteattr(obj->u.pvfs2.ref, 
+                creds, &key, &val)) < 0)
+        {
+            PVFS_perror("PVFS_sys_geteattr failed %d\n", ret);
+            return -1;
+        }
+        *size = val.read_sz;
+    }
+    *dist = buffer;
+    return 0;
+}
+
+/*
+ * nservers is an in-out style parameter
+ * servers is allocated memory upto *nservers and each element inside that
+ * is allocated internally in this function.
+ * callers job is to free up all the memory
+ */
+static int generic_server_location(file_object *obj, PVFS_credentials *creds,
+        char **servers, int *nservers)
+{
+    char *buffer = (char *) malloc(4096);
+    int ret, num_dfiles, count;
+    PVFS_fs_id fsid;
+    
+    if (obj->fs_type == UNIX_FILE)
+    {
+        if ((ret = fgetxattr(obj->u.ufs.fd, DFILE_KEY, buffer, 4096)) < 0)
+        {
+            perror("fgetxattr:");
+            return -1;
+        }
+        fsid = obj->u.ufs.fs_id;
+    }
+    else
+    {
+        PVFS_ds_keyval key, val;
+
+        key.buffer = DFILE_KEY;
+        key.buffer_sz = strlen(DFILE_KEY) + 1;
+        val.buffer = buffer;
+        val.buffer_sz = 4096;
+        if ((ret = PVFS_sys_geteattr(obj->u.pvfs2.ref, 
+                creds, &key, &val)) < 0)
+        {
+            PVFS_perror("PVFS_sys_geteattr failed %d\n", ret);
+            return -1;
+        }
+        ret = val.read_sz;
+        fsid = obj->u.pvfs2.fs_id;
+    }
+    /*
+     * At this point, we know all the dfile handles 
+     */
+    num_dfiles = (ret / sizeof(PVFS_handle));
+    count = num_dfiles < *nservers ? num_dfiles : *nservers;
+    for (ret = 0; ret < count; ret++)
+    {
+        PVFS_handle *ptr = (PVFS_handle *) ((char *) buffer + ret * 
sizeof(PVFS_handle));
+        servers[ret] = (char *) calloc(1, PVFS_MAX_SERVER_ADDR_LEN);
+        if (servers[ret] == NULL)
+        {
+            break;
+        }
+        /* ignore any errors */
+        PINT_cached_config_get_server_name(
+                servers[ret], PVFS_MAX_SERVER_ADDR_LEN,
+                *ptr, fsid);
+    }
+    if (ret != count)
+    {
+        int j;
+        for (j = 0; j < ret; j++)
+        {
+            free(servers[j]);
+            servers[j] = NULL;
+        }
+        return -1;
+    }
+    *nservers = count;
+    return 0;
+}
+
+int main(int argc, char ** argv)
+{
+    struct options* user_opts = NULL;
+    file_object src;
+    PINT_dist dist;
+    char *dist_buf = NULL;
+    int dist_size;
+    int64_t ret;
+    PVFS_credentials credentials;
+    char *servers[256];
+    int i, nservers = 256;
+
+    memset(&dist, 0, sizeof(dist));
+    user_opts = parse_args(argc, argv);
+    if (!user_opts)
+    {
+       fprintf(stderr, "Error, failed to parse command line arguments\n");
+       return(-1);
+    }
+
+    ret = PVFS_util_init_defaults();
+    if (ret < 0)
+    {
+       PVFS_perror("PVFS_util_init_defaults", ret);
+       return(-1);
+    }
+    memset(&src, 0, sizeof(src));
+
+    resolve_filename(&src,  user_opts->srcfile);
+
+    PVFS_util_gen_credentials(&credentials);
+
+    ret = generic_open(&src, &credentials);
+    if (ret < 0)
+    {
+       fprintf(stderr, "Could not open %s\n", user_opts->srcfile);
+       goto main_out;
+    }
+
+    ret = generic_dist(&src, &credentials, &dist_buf, &dist_size);
+    if (ret < 0)
+    {
+        fprintf(stderr, "Could not read distribution information!\n");
+        goto main_out;
+    }
+    ret = generic_server_location(&src, &credentials, servers, &nservers);
+    if (ret < 0)
+    {
+        fprintf(stderr, "Could not read server location information!\n");
+        goto main_out;
+    }
+    /* okay now print out by deserializing the buffer */
+    PINT_dist_decode(&dist, dist_buf);
+    printf("dist_name = %s\n", dist.dist_name);
+    if (strcmp(dist.dist_name, PVFS_DIST_SIMPLE_STRIPE_NAME) == 0)
+    {
+        PVFS_simple_stripe_params params;
+        PINT_dist_getparams(&params, &dist);
+        printf("strip_size = %ld\n", (unsigned long)(params.strip_size));
+    }
+    printf("Number of datafiles/servers = %d\n", nservers);
+    for (i = 0; i < nservers; i++)
+    {
+        printf("Server %d - %s\n", i, servers[i]);
+        free(servers[i]);
+    }
+main_out:
+    PVFS_sys_finalize();
+    free(user_opts);
+    return(ret);
+}
+
+/* parse_args()
+ *
+ * parses command line arguments
+ *
+ * returns pointer to options structure on success, NULL on failure
+ */
+static struct options* parse_args(int argc, char* argv[])
+{
+    /* getopt stuff */
+    extern char* optarg;
+    extern int optind, opterr, optopt;
+    char flags[] = "vf:";
+    int one_opt = 0;
+
+    struct options* tmp_opts = NULL;
+
+    /* create storage for the command line options */
+    tmp_opts = (struct options*)malloc(sizeof(struct options));
+    if(!tmp_opts){
+       return(NULL);
+    }
+    memset(tmp_opts, 0, sizeof(struct options));
+
+    /* look at command line arguments */
+    while((one_opt = getopt(argc, argv, flags)) != EOF)
+    {
+       switch(one_opt){
+            case('v'):
+                printf("%s\n", PVFS2_VERSION);
+                exit(0);
+            case('f'):
+                tmp_opts->srcfile = optarg;
+                break;
+           case('?'):
+               usage(argc, argv);
+               exit(EXIT_FAILURE);
+       }
+    }
+    if (tmp_opts->srcfile == NULL)
+    {
+        usage(argc, argv);
+        exit(EXIT_FAILURE);
+    }
+    return(tmp_opts);
+}
+
+static void usage(int argc, char** argv)
+{
+    fprintf(stderr, 
+       "Usage: %s ARGS \n", argv[0]);
+    fprintf(stderr, "Where ARGS is one or more of"
+       "\n-f <file name>\t\t\tPVFS2 file pathname"
+       "\n-v\t\t\t\tprint version number and exit\n");
+    return;
+}
+
+/* resolve_filename:
+ *  given 'filename', find the PVFS2 fs_id and relative pvfs_path.  In case of
+ *  error, assume 'filename' is a unix file.
+ */
+static int resolve_filename(file_object *obj, char *filename)
+{
+    int ret;
+
+    ret = PVFS_util_resolve(filename, &(obj->u.pvfs2.fs_id), 
+           obj->u.pvfs2.pvfs2_path, PVFS_NAME_MAX);
+    if (ret < 0)
+    {
+       obj->fs_type = UNIX_FILE;
+       strncpy(obj->u.ufs.path, filename, NAME_MAX);
+    } else {
+       obj->fs_type = PVFS2_FILE;
+       strncpy(obj->u.pvfs2.user_path, filename, PVFS_NAME_MAX);
+    }
+    return 0;
+}
+
+/* generic_open:
+ *  given a file_object, perform the apropriate open calls.  
+ */
+static int generic_open(file_object *obj, PVFS_credentials *credentials)
+{
+    struct stat stat_buf;
+    PVFS_sysresp_lookup resp_lookup;
+    PVFS_sysresp_getattr resp_getattr;
+    PVFS_object_ref ref;
+    int ret = -1;
+
+    if (obj->fs_type == UNIX_FILE)
+    {
+        struct statfs statfsbuf;
+        memset(&stat_buf, 0, sizeof(struct stat));
+
+        stat(obj->u.ufs.path, &stat_buf);
+        if (!S_ISREG(stat_buf.st_mode))
+        {
+            fprintf(stderr, "Not a file!\n");
+            return(-1);
+        }
+        obj->u.ufs.fd = open(obj->u.ufs.path, O_RDONLY);
+        obj->u.ufs.mode = (int)stat_buf.st_mode;
+       if (obj->u.ufs.fd < 0)
+       {
+           perror("open");
+           fprintf(stderr, "could not open %s\n", obj->u.ufs.path);
+           return (-1);
+       }
+        if (fstatfs(obj->u.ufs.fd, &statfsbuf) < 0)
+        {
+            perror("fstatfs:");
+            fprintf(stderr, "could not fstatfs %s\n", obj->u.ufs.path);
+        }
+        memcpy(&obj->u.ufs.fs_id, &statfsbuf.f_fsid, sizeof(statfsbuf.f_fsid));
+        return 0;
+    }
+    else
+    {
+        memset(&resp_lookup, 0, sizeof(PVFS_sysresp_lookup));
+        ret = PVFS_sys_lookup(obj->u.pvfs2.fs_id, 
+                              (char *) obj->u.pvfs2.pvfs2_path,
+                              credentials, 
+                              &resp_lookup,
+                              PVFS2_LOOKUP_LINK_FOLLOW);
+        if (ret < 0)
+        {
+            PVFS_perror("PVFS_sys_lookup", ret);
+            return (-1);
+        }
+        ref.handle = resp_lookup.ref.handle;
+        ref.fs_id = resp_lookup.ref.fs_id;
+
+        memset(&resp_getattr, 0, sizeof(PVFS_sysresp_getattr));
+        ret = PVFS_sys_getattr(ref, PVFS_ATTR_SYS_ALL,
+                               credentials, &resp_getattr);
+        if (ret)
+        {
+            fprintf(stderr, "Failed to do pvfs2 getattr on %s\n",
+                    obj->u.pvfs2.pvfs2_path);
+            return -1;
+        }
+
+        if (resp_getattr.attr.objtype != PVFS_TYPE_METAFILE)
+        {
+            fprintf(stderr, "Not a meta file!\n");
+            return -1;
+        }
+        obj->u.pvfs2.perms = resp_getattr.attr.perms;
+        memcpy(&obj->u.pvfs2.attr, &resp_getattr.attr,
+               sizeof(PVFS_sys_attr));
+        obj->u.pvfs2.attr.mask = PVFS_ATTR_SYS_ALL_SETABLE;
+        obj->u.pvfs2.ref = ref;
+    }
+    return 0;
+}
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ * End:
+ *
+ * vim: ts=8 sts=4 sw=4 expandtab
+ */
diff -Naur pvfs2/src/kernel/linux-2.6/pvfs2-utils.c 
new_pvfs2/src/kernel/linux-2.6/pvfs2-utils.c
--- pvfs2/src/kernel/linux-2.6/pvfs2-utils.c    2005-11-11 15:31:08.000000000 
-0600
+++ new_pvfs2/src/kernel/linux-2.6/pvfs2-utils.c        2005-11-23 
14:24:09.000000000 -0600
@@ -72,6 +72,11 @@
         */
         inode->i_blksize = pvfs_bufmap_size_query();
         inode->i_blkbits = PAGE_CACHE_SHIFT;
+        pvfs2_print("attrs->mask = %x (%d, objtype = %d), size = %ld\n", 
+                attrs->mask, attrs->mask & PVFS_ATTR_SYS_SIZE, 
+                attrs->objtype,
+                (unsigned long) attrs->size);
+                
 
         if ((attrs->objtype == PVFS_TYPE_METAFILE) &&
             (attrs->mask & PVFS_ATTR_SYS_SIZE))
@@ -464,6 +469,27 @@
 
 
 /* Extended attributes helper functions */
+static char *xattr_non_zero_terminated[] = {
+    "datafile_handles"
+};
+
+/*
+ * this function returns 
+ * 0 if the val corresponding to name is known to be not terminated with an 
explicit \0
+ * 1 if the val corresponding to name is known to be \0 terminated
+ */
+static int xattr_zero_terminated(const char *name)
+{
+    int i;
+    static int xattr_count = sizeof(xattr_non_zero_terminated)/sizeof(char *);
+    for (i = 0;i < xattr_count; i++)
+    {
+        if (strcmp(name, xattr_non_zero_terminated[i]) == 0)
+            return 0;
+    }
+    return 1;
+}
+
 /*
  * Tries to get a specified key's attributes of a given
  * file into a user-specified buffer. Note that the getxattr
@@ -532,17 +558,33 @@
          */
         if (ret == 0)
         {
+            ssize_t new_length;
             length = new_op->downcall.resp.getxattr.val_sz;
+            /*
+             * if the xattr corresponding to name was not terminated with a \0
+             * then we return the entire response length
+             */
+            if (xattr_zero_terminated(name) == 0)
+            {
+                new_length = length;
+            }
+            /*
+             * if it was terminated by a \0 then we return 1 less for the 
getfattr
+             * programs to play nicely with displaying it
+             */
+            else {
+                new_length = length - 1;
+            }
             /* Just return the length of the queried attribute after
              * subtracting the \0 thingie */
             if (size == 0)
             {
-                ret = length - 1;
+                ret = new_length;
             }
             else
             {
                 /* check to see if key length is > provided buffer size */
-                if (length - 1 > size)
+                if (new_length > size)
                 {
                     ret = -ERANGE;
                 }
@@ -551,8 +593,8 @@
                     /* No size problems */
                     memset(buffer, 0, size);
                     memcpy(buffer, new_op->downcall.resp.getxattr.val, 
-                            length - 1);
-                    ret = length - 1;
+                            new_length);
+                    ret = new_length;
                     pvfs2_print("pvfs2_getxattr: key: %s, val_length: %d\n",
                             name, (int) ret);
                 }
diff -Naur pvfs2/src/kernel/linux-2.6/super.c 
new_pvfs2/src/kernel/linux-2.6/super.c
--- pvfs2/src/kernel/linux-2.6/super.c  2005-10-07 16:03:08.000000000 -0500
+++ new_pvfs2/src/kernel/linux-2.6/super.c      2005-11-23 14:24:39.000000000 
-0600
@@ -345,6 +345,7 @@
                     new_op->downcall.resp.statfs.blocks_total);
 
         buf->f_type = sb->s_magic;
+        memcpy(&buf->f_fsid, &(PVFS2_SB(sb)->fs_id), 
sizeof(PVFS2_SB(sb)->fs_id));
         buf->f_bsize = sb->s_blocksize;
         buf->f_namelen = PVFS2_NAME_LEN;
 
_______________________________________________
PVFS2-users mailing list
[email protected]
http://www.beowulf-underground.org/mailman/listinfo/pvfs2-users

Reply via email to