Index: pvfs2_src/src/apps/admin/pvfs2-lsplus.c
===================================================================
--- pvfs2_src/src/apps/admin/pvfs2-lsplus.c	(revision 2316)
+++ pvfs2_src/src/apps/admin/pvfs2-lsplus.c	(working copy)
@@ -43,6 +43,7 @@
     int list_human_readable;
     int list_long;
     int list_verbose;
+    int list_recursive;
     int list_numeric_uid_gid;
     int list_directory;
     int list_no_group;
@@ -55,6 +56,13 @@
     int num_starts;
 };
 
+struct subdir_list
+{
+    char *path;
+    struct subdir_list *next;
+};
+typedef struct subdir_list subdir;
+
 static char *process_name = NULL;
 static int do_timing = 0;
 
@@ -71,6 +79,7 @@
     struct options *opts);
 
 static int do_list(
+    char *full_path,
     char *start,
     int fs_id,
     struct options *opts);
@@ -378,6 +421,7 @@
 }
 
 int do_list(
+    char *full_path,
     char *start,
     int fs_id,
     struct options *opts)
@@ -395,12 +439,18 @@
     PVFS_ds_position token;
     uint64_t dir_version = 0;
     double begin = 0., end;
+    subdir *current, *head = NULL, *tail = NULL;
 
     name = start;
 
     memset(&lk_response,0,sizeof(PVFS_sysresp_lookup));
     PVFS_util_gen_credentials(&credentials);
 
+    if (opts->list_recursive || opts->num_starts > 1)
+    {
+        printf("%s%s:\n",full_path,start);
+    }
+
     ret = PVFS_sys_lookup(fs_id, name, &credentials,
                         &lk_response, PVFS2_LOOKUP_LINK_NO_FOLLOW);
     if(ret < 0)
@@ -506,8 +556,40 @@
                     &rdplus_response.attr_array[i],
                     rdplus_response.stat_err_array[i],
                     opts);
+
+            PVFS_sys_attr *attr = &rdplus_response.attr_array[i];
+            if(attr->objtype == PVFS_TYPE_DIRECTORY && opts->list_recursive)
+            {
+                int path_len = strlen(start) + strlen(cur_file) + 1;
+                current = (subdir *) malloc(sizeof(subdir));
+
+                /* Prevent duplicate slashes in path */
+                if(start[strlen(start)-1] == '/')
+                {
+                    current->path = (char *) malloc(path_len);
+                    snprintf(current->path,path_len,"%s%s",start,cur_file);
+                }
+                else
+                {
+                    current->path = (char *) malloc(path_len + 1);
+                    snprintf(current->path,path_len+1,"%s/%s",start,cur_file);
+                }
+
+                /* Update linked list of subdirectories to recurse */
+                current->next = NULL;
+                if(!head)
+                {
+                    head = current;
+                    tail = current;
+                }
+                else
+                {
+                    tail->next = current;
+                    tail = current;
+                }
+            }
         }
         token += rdplus_response.pvfs_dirent_outcount;
 
         if (rdplus_response.pvfs_dirent_outcount)
         {
@@ -547,6 +629,19 @@
         free(rdplus_response.attr_array);
         rdplus_response.attr_array = NULL;
     }
+
+    if (opts->list_recursive)
+    {
+        current = head;
+        while(current)
+        {
+            printf("\n");
+            do_list(full_path,current->path,fs_id,opts);
+            current = current->next;
+            free(head);
+            head = current;
+        }
+    }
     return 0;
 }
 
@@ -567,6 +662,7 @@
         {"human-readable",0,0,0},
         {"si",0,0,0},
         {"version",0,0,0},
+        {"recursive",0,0,0},
         {"verbose",0,0,0},
         {"numeric-uid-gid",0,0,0},
         {"directory",0,0,0},
@@ -585,7 +681,7 @@
     }
     memset(tmp_opts, 0, sizeof(struct options));
 
-    while((ret = getopt_long(argc, argv, "hVndGoAaiglt",
+    while((ret = getopt_long(argc, argv, "hRVndGoAaiglt",
                              long_opts, &option_index)) != -1)
     {
 	switch(ret)
@@ -612,6 +708,10 @@
                     printf("%s\n", PVFS2_VERSION);
                     exit(0);
                 }
+                else if (strcmp("recursive", cur_option) == 0)
+                {
+                    goto list_recursive;
+                }
                 else if (strcmp("verbose", cur_option) == 0)
                 {
                     goto list_verbose;
@@ -650,6 +750,10 @@
           list_human_readable:
                 tmp_opts->list_human_readable = 1;
                 break;
+            case 'R':
+          list_recursive:
+                tmp_opts->list_recursive = 1;
+                break;
             case 'V':
           list_verbose:
                 tmp_opts->list_verbose = 1;
@@ -740,6 +844,8 @@
             "list group information\n");
     fprintf(stderr,"      --help                 display this help "
             "and exit\n");
+    fprintf(stderr,"  -R, --recursive            list subdirectories "
+            "recursively\n");
     fprintf(stderr,"  -V, --verbose              reports if the dir is "
             "changing during listing\n");
     fprintf(stderr,"      --version              output version "
@@ -832,13 +938,35 @@
 
     for(i = 0; i < user_opts->num_starts; i++)
     {
-        if (user_opts->num_starts > 1)
+        char *substr = strstr(user_opts->start[i],pvfs_path[i]);
+        char *index = user_opts->start[i];
+        char *search = substr; 
+        int j = 0;
+
+        /* Keep the mount path info to mimic /bin/ls output */
+        if( strncmp(pvfs_path[i],"/",strlen(pvfs_path[i])) )
         {
-            printf("%s:\n", pvfs_path[i]);
+            /* Get last matching substring */
+            while (search) 
+            {
+                substr = search;
+                search = strstr(++search,pvfs_path[i]);
+            }
         }
+        else /* Root directory case has nothing to match */
+        {
+            substr = &user_opts->start[i][strlen(user_opts->start[i])-1];
+        }
 
-        do_list(pvfs_path[i], fs_id_array[i], user_opts);
+        while (index != substr)
+        {
+            index++;
+            j++;
+        }
+        user_opts->start[i][j] = '\0';
 
+        do_list(user_opts->start[i], pvfs_path[i], fs_id_array[i], user_opts);
+
         if (user_opts->num_starts > 1)
         {
             printf("\n");
