Whamcloud - gitweb
b=13919
authorkalpak <kalpak>
Wed, 28 Nov 2007 10:50:13 +0000 (10:50 +0000)
committerkalpak <kalpak>
Wed, 28 Nov 2007 10:50:13 +0000 (10:50 +0000)
i=adilger,johann

llapi_semantic_traverse may report wrong filetype for some older kernels and we assumed that suchc files were either directories or regular files. This patch ensures that if DT_UNKNOWN is returned as filetype then it is correctly handled by finding out the correct filetype.

lustre/include/lustre/liblustreapi.h
lustre/tests/sanity.sh
lustre/utils/liblustreapi.c

index 87b45d3..696dd2c 100644 (file)
@@ -40,7 +40,8 @@ struct find_param {
         int     size_sign;
         unsigned long long size_units;
 
-        unsigned zeroend:1, recursive:1, got_uuids:1, obds_printed:1, exclude_pattern:1, exclude_type:1;
+        unsigned zeroend:1, recursive:1, got_uuids:1, obds_printed:1,
+                 exclude_pattern:1, exclude_type:1, have_fileinfo:1;
 
         int     verbose;
         int     quiet;
index 648351d..4820f2e 100644 (file)
@@ -2458,12 +2458,12 @@ setup_56_special() {
                for i in `seq 1 $LOCAL_NUMFILES` ; do
                        mknod $TDIR/loop${i}b b 7 $i
                        mknod $TDIR/null${i}c c 1 3
-                       ln -s $TDIR/file0 $TDIR/link${i}l
+                       ln -s $TDIR/file1 $TDIR/link${i}l
                done
                for i in `seq 1 $LOCAL_NUMDIRS` ; do
                        mknod $TDIR/dir$i/loop${i}b b 7 $i
                        mknod $TDIR/dir$i/null${i}c c 1 3
-                       ln -s $TDIR/dir$i/file0 $TDIR/dir$i/link${i}l
+                       ln -s $TDIR/dir$i/file1 $TDIR/dir$i/link${i}l
                done
        fi
 }
index 0cf6c69..89ca95e 100644 (file)
 #include <obd_lov.h>
 #include <lustre/liblustreapi.h>
 
+static unsigned llapi_dir_filetype_table[] = {
+        [DT_UNKNOWN]= 0,
+        [DT_FIFO]= S_IFIFO,
+        [DT_CHR] = S_IFCHR,
+        [DT_DIR] = S_IFDIR,
+        [DT_BLK] = S_IFBLK,
+        [DT_REG] = S_IFREG,
+        [DT_LNK] = S_IFLNK,
+        [DT_SOCK]= S_IFSOCK,
+#if defined(DT_DOOR) && defined(S_IFDOOR)
+        [DT_DOOR]= S_IFDOOR,
+#endif
+};
+
+#if defined(DT_DOOR) && defined(S_IFDOOR)
+static const int DT_MAX = DT_DOOR;
+#else
+static const int DT_MAX = DT_SOCK;
+#endif
+
+static unsigned llapi_filetype_dir_table[] = {
+        [0]= DT_UNKNOWN,
+        [S_IFIFO]= DT_FIFO,
+        [S_IFCHR] = DT_CHR,
+        [S_IFDIR] = DT_DIR,
+        [S_IFBLK] = DT_BLK,
+        [S_IFREG] = DT_REG,
+        [S_IFLNK] = DT_LNK,
+        [S_IFSOCK]= DT_SOCK,
+#if defined(DT_DOOR) && defined(S_IFDOOR)
+        [S_IFDOOR]= DT_DOOR,
+#endif
+};
+
+#if defined(DT_DOOR) && defined(S_IFDOOR)
+static const int S_IFMAX = DT_DOOR;
+#else
+static const int S_IFMAX = DT_SOCK;
+#endif
+
 static void err_msg(char *fmt, ...)
 {
         va_list args;
@@ -620,20 +660,43 @@ int llapi_file_lookup(int dirfd, const char *name)
         return ioctl(dirfd, IOC_MDC_LOOKUP, buf);
 }
 
-/* some 64bit libcs implement readdir64() by calling sys_getdents().  the
- * kernel's sys_getdents() doesn't return d_type.  */
-unsigned char handle_dt_unknown(char *path)
+int llapi_mds_getfileinfo(char *path, DIR *parent,
+                          struct lov_user_mds_data *lmd)
 {
-        int fd;
+        lstat_t *st = &lmd->lmd_st;
+        char *fname = strrchr(path, '/');
+        int ret = 0;
 
-        fd = open(path, O_DIRECTORY|O_RDONLY);
-        if (fd < 0) {
-                if (errno == ENOTDIR)
-                        return DT_REG; /* kind of a lie */
-                return DT_UNKNOWN;
+        if (parent == NULL)
+                return -EINVAL;
+
+        fname = (fname == NULL ? path : fname + 1);
+        /* retrieve needed file info */
+        strncpy((char *)lmd, fname, lov_mds_md_size(MAX_LOV_UUID_COUNT));
+        ret = ioctl(dirfd(parent), IOC_MDC_GETFILEINFO, (void *)lmd);
+
+        if (ret) {
+                if (errno == ENOTTY) {
+                        /* ioctl is not supported, it is not a lustre fs.
+                         * Do the regular lstat(2) instead. */
+                        ret = lstat_f(path, st);
+                        if (ret) {
+                                err_msg("error: %s: lstat failed for %s",
+                                        __FUNCTION__, path);
+                                return ret;
+                        }
+                } else if (errno == ENOENT) {
+                        err_msg("warning: %s: %s does not exist", __FUNCTION__,
+                                path);
+                        return -ENOENT;
+                } else {
+                        err_msg("error: %s: IOC_MDC_GETFILEINFO failed for %s",
+                                __FUNCTION__, path);
+                        return ret;
+                }
         }
-        close(fd);
-        return DT_DIR;
+
+        return 0;
 }
 
 static DIR *opendir_parent(char *path)
@@ -684,6 +747,8 @@ static int llapi_semantic_traverse(char *path, int size, DIR *parent,
                 GOTO(out, ret = 0);
 
         while ((dent = readdir64(d)) != NULL) {
+                ((struct find_param *)data)->have_fileinfo = 0;
+
                 if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
                         continue;
 
@@ -697,17 +762,24 @@ static int llapi_semantic_traverse(char *path, int size, DIR *parent,
                 strcat(path, "/");
                 strcat(path, dent->d_name);
 
-                if (dent->d_type == DT_UNKNOWN)
-                        dent->d_type = handle_dt_unknown(path);
+                if (dent->d_type == DT_UNKNOWN) {
+                        lstat_t *st = &((struct find_param *)data)->lmd->lmd_st;
+
+                        ret = llapi_mds_getfileinfo(path, d,
+                                             ((struct find_param *)data)->lmd);
+                        if (ret == 0) {
+                                ((struct find_param *)data)->have_fileinfo = 1;
+                                dent->d_type = llapi_filetype_dir_table[st->st_mode &
+                                                                        S_IFMT];
+                        }
+                        if (ret == -ENOENT)
+                                continue;
+                }
 
                 switch (dent->d_type) {
                 case DT_UNKNOWN:
                         fprintf(stderr, "error: %s: '%s' is UNKNOWN type %d",
                                 __FUNCTION__, dent->d_name, dent->d_type);
-                        /* If we cared we could stat the file to determine
-                         * type and continue on here, but we don't since we
-                         * know d_type should be valid for lustre and this
-                         * tool only makes sense for lustre filesystems. */
                         break;
                 case DT_DIR:
                         ret = llapi_semantic_traverse(path, size, d, sem_init,
@@ -832,25 +904,6 @@ static int find_time_check(lstat_t *st, struct find_param *param, int mds)
         return rc;
 }
 
-static unsigned llapi_dir_filetype_table[] = {
-        [DT_UNKNOWN]= 0,
-        [DT_FIFO]= S_IFIFO,
-        [DT_CHR] = S_IFCHR,
-        [DT_DIR] = S_IFDIR,
-        [DT_BLK] = S_IFBLK,
-        [DT_REG] = S_IFREG,
-        [DT_LNK] = S_IFLNK,
-        [DT_SOCK]= S_IFSOCK,
-#if defined(DT_DOOR) && defined(S_IFDOOR)
-        [DT_DOOR]= S_IFDOOR,
-#endif
-};
-#if defined(DT_DOOR) && defined(S_IFDOOR)
-static const int DT_MAX = DT_DOOR;
-#else
-static const int DT_MAX = DT_SOCK;
-#endif
-
 static int cb_find_init(char *path, DIR *parent, DIR *dir,
                         void *data, struct dirent64 *de)
 {
@@ -859,7 +912,7 @@ static int cb_find_init(char *path, DIR *parent, DIR *dir,
         lstat_t *st = &param->lmd->lmd_st;
         int lustre_fs = 1;
         int checked_type = 0;
-        int ret;
+        int ret = 0;
 
         LASSERT(parent != NULL || dir != NULL);
 
@@ -894,19 +947,22 @@ static int cb_find_init(char *path, DIR *parent, DIR *dir,
             param->size)
                 decision = 0;
 
+        ret = 0;
         /* Request MDS for the stat info. */
-        if (dir) {
-                /* retrieve needed file info */
-                ret = ioctl(dirfd(dir), LL_IOC_MDC_GETINFO,
-                            (void *)param->lmd);
-        } else /* if (parent) LASSERT() above makes always true */ {
-                char *fname = strrchr(path, '/');
-                fname = (fname == NULL ? path : fname + 1);
+        if (param->have_fileinfo == 0) {
+                if (dir) {
+                        /* retrieve needed file info */
+                        ret = ioctl(dirfd(dir), LL_IOC_MDC_GETINFO,
+                                    (void *)param->lmd);
+                } else {
+                        char *fname = strrchr(path, '/');
+                        fname = (fname == NULL ? path : fname + 1);
 
-                /* retrieve needed file info */
-                strncpy((char *)param->lmd, fname, param->lumlen);
-                ret = ioctl(dirfd(parent), IOC_MDC_GETFILEINFO,
-                           (void *)param->lmd);
+                        /* retrieve needed file info */
+                        strncpy((char *)param->lmd, fname, param->lumlen);
+                        ret = ioctl(dirfd(parent), IOC_MDC_GETFILEINFO,
+                                   (void *)param->lmd);
+                }
         }
 
         if (ret) {