#include <sys/stat.h>
#include <sys/syscall.h>
-#include <libcfs/libcfs.h>
-#include <lustre/lustre_user.h>
+#include <linux/lustre/lustre_user.h>
#define MAX_HANDLE_SZ 128
-#if !defined(HAVE_FHANDLE_GLIBC_SUPPORT) && defined(HAVE_FHANDLE_SYSCALLS)
+void usage(char *prog)
+{
+ fprintf(stderr, "usage: %s <filepath> <mount2>\n",
+ prog);
+ fprintf(stderr, "the absolute path of a test file on a "
+ "lustre file system is needed.\n");
+ exit(1);
+}
+
+
+#ifndef HAVE_FHANDLE_GLIBC_SUPPORT
/* Because the kernel supports this functions doesn't mean that glibc does.
* Just in case we define what we need */
struct file_handle {
#define __NR_open_by_handle_at 265
#endif
-
#endif
static inline int
}
#endif
-void usage(char *prog)
+static int debug_mark(const char *msg)
{
- fprintf(stderr, "usage: %s <filepath>\n",
- prog);
- fprintf(stderr, "the absolute path of a test file on a "
- "lustre file system is needed.\n");
- exit(1);
+ char cmd[4096] = "";
+
+ snprintf(cmd, sizeof(cmd), "../utils/lctl mark %s 2>/dev/null", msg);
+ return system(cmd);
+}
+
+/* verify a file contents */
+int check_access(const char *filename,
+ int mnt_fd, struct file_handle *fh, struct stat *st_orig)
+{
+ int fd2, rc, len, offset;
+ struct stat st;
+ char *readbuf = NULL;
+
+ debug_mark("before open by handle");
+ /* Open the file handle */
+ fd2 = open_by_handle_at(mnt_fd, fh, O_RDONLY |
+ (S_ISDIR(st_orig->st_mode) ? O_DIRECTORY : 0));
+ debug_mark("after open by handle");
+ if (fd2 < 0) {
+ fprintf(stderr, "open_by_handle_at(%s) error: %s\n", filename,
+ strerror(errno));
+ if (errno == ESTALE)
+ fprintf(stderr, "second mountpoint not mounted?\n");
+ rc = errno;
+ goto out_f_handle;
+ }
+
+ /* Get file size */
+ bzero(&st, sizeof(struct stat));
+ debug_mark("before stat");
+ rc = fstat(fd2, &st);
+ debug_mark("after stat");
+ if (rc < 0) {
+ fprintf(stderr, "fstat(%s) error: %s\n", filename,
+ strerror(errno));
+ rc = errno;
+ goto out_fd2;
+ }
+
+ /* we can't check a ctime due unlink update */
+ if (st_orig->st_size != st.st_size ||
+ st_orig->st_ino != st.st_ino ||
+ st_orig->st_mode != st.st_mode ||
+ st_orig->st_mtime != st.st_mtime) {
+ fprintf(stderr,
+ "stat data mismatch between fopen and fhandle case\n");
+ rc = EINVAL;
+ goto out_fd2;
+ }
+
+ if (st.st_size && S_ISREG(st.st_mode)) {
+ len = st.st_blksize;
+ readbuf = malloc(len);
+ if (readbuf == NULL) {
+ fprintf(stderr, "malloc(%d) error: %s\n", len,
+ strerror(errno));
+ rc = errno;
+ goto out_fd2;
+ }
+
+ for (offset = 0; offset < st.st_size; offset += len) {
+ /* read from the file */
+ rc = read(fd2, readbuf, len);
+ if (rc < 0) {
+ fprintf(stderr, "read(%s) error: %s\n",
+ filename, strerror(errno));
+ rc = errno;
+ goto out_readbuf;
+ }
+ }
+ }
+ rc = 0;
+out_readbuf:
+ free(readbuf);
+out_fd2:
+ close(fd2);
+out_f_handle:
+ return rc;
}
int main(int argc, char **argv)
{
-#ifdef HAVE_FHANDLE_SYSCALLS
- char *filename, *file, *mount_point = NULL, *readbuf = NULL;
- int ret, rc = -EINVAL, mnt_id, mnt_fd, fd1, fd2, i, len, offset;
+ char *filename, *file;
+ int ret, rc = -EINVAL, mnt_fd, mnt_id, fd1, i;
struct file_handle *fh = NULL;
- int file_size, mtime, ctime;
struct lu_fid *parent, *fid;
- struct mntent *ent;
struct stat st;
- __ino_t inode;
- FILE *mntpt;
- if (argc != 2)
+ if (argc != 3)
usage(argv[0]);
file = argv[1];
goto out;
}
+ if (*argv[2] != '/') {
+ fprintf(stderr, "Need the absolete path of the mount point\n");
+ goto out;
+ }
+ filename = rindex(file, '/') + 1;
+
+ debug_mark("before first open");
fd1 = open(file, O_RDONLY);
+ debug_mark("after first open");
if (fd1 < 0) {
fprintf(stderr, "open file %s error: %s\n",
file, strerror(errno));
/* Get file stats using fd1 from traditional open */
bzero(&st, sizeof(struct stat));
+ debug_mark("before first stat");
rc = fstat(fd1, &st);
+ debug_mark("after first stat");
if (rc < 0) {
fprintf(stderr, "fstat(%s) error: %s\n", file,
strerror(errno));
goto out_fd1;
}
- inode = st.st_ino;
- mtime = st.st_mtime;
- ctime = st.st_ctime;
- file_size = st.st_size;
-
- /* Now for the setup to use fhandles */
- mntpt = setmntent("/etc/mtab", "r");
- if (mntpt == NULL) {
- fprintf(stderr, "setmntent error: %s\n",
- strerror(errno));
- rc = errno;
- goto out_fd1;
- }
-
- while (NULL != (ent = getmntent(mntpt))) {
- if ((strncmp(file, ent->mnt_dir, strlen(ent->mnt_dir)) == 0) &&
- (strcmp(ent->mnt_type, "lustre") == 0)) {
- mount_point = ent->mnt_dir;
- break;
- }
- }
- endmntent(mntpt);
-
- if (mount_point == NULL) {
- fprintf(stderr, "file is not located on a lustre file "
- "system?\n");
- goto out_fd1;
- }
-
- filename = rindex(file, '/') + 1;
-
/* Open mount point directory */
- mnt_fd = open(mount_point, O_DIRECTORY);
+ debug_mark("before directory open");
+ mnt_fd = open(argv[2], O_DIRECTORY);
+ debug_mark("after directory open");
if (mnt_fd < 0) {
- fprintf(stderr, "open(%s) error: %s\n)", mount_point,
+ fprintf(stderr, "open(%s) error: %s\n)", argv[2],
strerror(errno));
rc = errno;
goto out_fd1;
fh->handle_bytes = MAX_HANDLE_SZ;
/* Convert name to handle */
- ret = name_to_handle_at(mnt_fd, filename, fh, &mnt_id,
+ debug_mark("before get handle");
+ ret = name_to_handle_at(AT_FDCWD, file, fh, &mnt_id,
AT_SYMLINK_FOLLOW);
+ debug_mark("after get handle");
if (ret) {
fprintf(stderr, "name_by_handle_at(%s) error: %s\n", filename,
strerror(errno));
}
/* Print out the contents of the file handle */
- fprintf(stdout, "fh_bytes: %u\nfh_type: %d\nfh_data: ",
- fh->handle_bytes, fh->handle_type);
+ fprintf(stdout, "file: %s\nfh_bytes: %u\nfh_type: %d\nfh_data: ",
+ file, fh->handle_bytes, fh->handle_type);
for (i = 0; i < fh->handle_bytes; i++)
fprintf(stdout, "%02x ", fh->f_handle[i]);
fprintf(stdout, "\n");
fprintf(stdout, "file's parent FID is "DFID"\n", PFID(parent));
fprintf(stdout, "file FID is "DFID"\n", PFID(fid));
- /* Open the file handle */
- fd2 = open_by_handle_at(mnt_fd, fh, O_RDONLY);
- if (fd2 < 0) {
- fprintf(stderr, "open_by_handle_at(%s) error: %s\n", filename,
- strerror(errno));
- rc = errno;
+ fprintf(stdout, "access via mount point '%s' - ", argv[2]);
+ fflush(stdout);
+ rc = check_access(filename, mnt_fd, fh, &st);
+ if (rc != 0)
goto out_f_handle;
- }
-
- /* Get file size */
- bzero(&st, sizeof(struct stat));
- rc = fstat(fd2, &st);
- if (rc < 0) {
- fprintf(stderr, "fstat(%s) error: %s\n", filename,
- strerror(errno));
- rc = errno;
- goto out_fd2;
- }
-
- if (ctime != st.st_ctime || file_size != st.st_size ||
- inode != st.st_ino || mtime != st.st_mtime) {
- fprintf(stderr, "stat data does not match between fopen "
- "and fhandle case\n");
- goto out_fd2;
- }
-
- if (st.st_size) {
- len = st.st_blksize;
- readbuf = malloc(len);
- if (readbuf == NULL) {
- fprintf(stderr, "malloc(%d) error: %s\n", len,
- strerror(errno));
- rc = errno;
- goto out_fd2;
+ fprintf(stdout, "OK \n");
+ fflush(stdout);
+
+ if (S_ISREG(st.st_mode)) {
+ fprintf(stdout, "access after unlink - ");
+ fflush(stdout);
+ ret = unlink(file);
+ if (ret < 0) {
+ fprintf(stderr,
+ "can't unlink '%s'. check permissions?\n",
+ file);
+ goto out_f_handle;
}
- for (offset = 0; offset < st.st_size; offset += len) {
- /* read from the file */
- rc = read(fd2, readbuf, len);
- if (rc < 0) {
- fprintf(stderr, "read(%s) error: %s\n",
- filename, strerror(errno));
- rc = errno;
- goto out_readbuf;
- }
- }
+ rc = check_access(filename, mnt_fd, fh, &st);
+ if (rc != 0)
+ goto out_f_handle;
+ fprintf(stdout, "OK\n");
+ fflush(stdout);
}
rc = 0;
fprintf(stdout, "check_fhandle_syscalls test Passed!\n");
-out_readbuf:
- if (readbuf != NULL)
- free(readbuf);
-out_fd2:
- close(fd2);
out_f_handle:
free(fh);
out_mnt_fd:
close(fd1);
out:
return rc;
-#else /* !HAVE_FHANDLE_SYSCALLS */
- if (argc != 2)
- usage(argv[0]);
-
- fprintf(stderr, "HAVE_FHANDLE_SYSCALLS not defined\n");
- return 0;
-#endif /* HAVE_FHANDLE_SYSCALLS */
}