3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 only,
7 * as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License version 2 for more details (a copy is included
13 * in the LICENSE file that accompanied this code).
15 * You should have received a copy of the GNU General Public License
16 * version 2 along with this program; If not, see
17 * http://www.gnu.org/licenses/gpl-2.0.html
23 * Copyright (C) 2013, DataDirect Networks, Inc.
25 * Copyright (c) 2014, Intel Corporation.
27 * Author: Swapnil Pimpale <spimpale@ddn.com>
42 #include <linux/unistd.h>
44 #include <sys/syscall.h>
46 #include <libcfs/libcfs.h>
47 #include <lustre/lustre_user.h>
49 #define MAX_HANDLE_SZ 128
51 #if !defined(HAVE_FHANDLE_GLIBC_SUPPORT) && defined(HAVE_FHANDLE_SYSCALLS)
52 /* Because the kernel supports this functions doesn't mean that glibc does.
53 * Just in case we define what we need */
58 unsigned char f_handle[0];
61 #if defined(_ASM_X86_UNISTD_64_H)
63 #ifndef __NR_name_to_handle_at
64 #define __NR_name_to_handle_at 303
67 #ifndef __NR_open_by_handle_at
68 #define __NR_open_by_handle_at 304
71 #elif defined(_ASM_X86_UNISTD_32_H)
73 #ifndef __NR_name_to_handle_at
74 #define __NR_name_to_handle_at 341
77 #ifndef __NR_open_by_handle_at
78 #define __NR_open_by_handle_at 342
83 #ifndef __NR_name_to_handle_at
84 #define __NR_name_to_handle_at 264
87 #ifndef __NR_open_by_handle_at
88 #define __NR_open_by_handle_at 265
95 name_to_handle_at(int mnt_fd, const char *filename, struct file_handle *fh,
96 int *mnt_id, int flags)
98 return syscall(__NR_name_to_handle_at, mnt_fd, filename, fh,
103 open_by_handle_at(int mnt_fd, struct file_handle *fh, int mode)
105 return syscall(__NR_open_by_handle_at, mnt_fd, fh, mode);
109 void usage(char *prog)
111 fprintf(stderr, "usage: %s <filepath>\n",
113 fprintf(stderr, "the absolute path of a test file on a "
114 "lustre file system is needed.\n");
118 int main(int argc, char **argv)
120 #ifdef HAVE_FHANDLE_SYSCALLS
121 char *filename, *file, *mount_point = NULL, *readbuf = NULL;
122 int ret, rc = -EINVAL, mnt_id, mnt_fd, fd1, fd2, i, len, offset;
123 struct file_handle *fh = NULL;
124 int file_size, mtime, ctime;
125 struct lu_fid *parent, *fid;
135 if (file[0] != '/') {
136 fprintf(stderr, "Need the absolete path of the file\n");
140 fd1 = open(file, O_RDONLY);
142 fprintf(stderr, "open file %s error: %s\n",
143 file, strerror(errno));
148 /* Get file stats using fd1 from traditional open */
149 bzero(&st, sizeof(struct stat));
150 rc = fstat(fd1, &st);
152 fprintf(stderr, "fstat(%s) error: %s\n", file,
161 file_size = st.st_size;
163 /* Now for the setup to use fhandles */
164 mntpt = setmntent("/etc/mtab", "r");
166 fprintf(stderr, "setmntent error: %s\n",
172 while (NULL != (ent = getmntent(mntpt))) {
173 if ((strncmp(file, ent->mnt_dir, strlen(ent->mnt_dir)) == 0) &&
174 (strcmp(ent->mnt_type, "lustre") == 0)) {
175 mount_point = ent->mnt_dir;
181 if (mount_point == NULL) {
182 fprintf(stderr, "file is not located on a lustre file "
187 filename = rindex(file, '/') + 1;
189 /* Open mount point directory */
190 mnt_fd = open(mount_point, O_DIRECTORY);
192 fprintf(stderr, "open(%s) error: %s\n)", mount_point,
198 /* Allocate memory for file handle */
199 fh = malloc(sizeof(struct file_handle) + MAX_HANDLE_SZ);
201 fprintf(stderr, "malloc(%d) error: %s\n", MAX_HANDLE_SZ,
206 fh->handle_bytes = MAX_HANDLE_SZ;
208 /* Convert name to handle */
209 ret = name_to_handle_at(mnt_fd, filename, fh, &mnt_id,
212 fprintf(stderr, "name_by_handle_at(%s) error: %s\n", filename,
218 /* Print out the contents of the file handle */
219 fprintf(stdout, "fh_bytes: %u\nfh_type: %d\nfh_data: ",
220 fh->handle_bytes, fh->handle_type);
221 for (i = 0; i < fh->handle_bytes; i++)
222 fprintf(stdout, "%02x ", fh->f_handle[i]);
223 fprintf(stdout, "\n");
225 /* Lustre stores both the parents FID and the file FID
226 * in the f_handle. */
227 parent = (struct lu_fid *)(fh->f_handle + 16);
228 fid = (struct lu_fid *)fh->f_handle;
229 fprintf(stdout, "file's parent FID is "DFID"\n", PFID(parent));
230 fprintf(stdout, "file FID is "DFID"\n", PFID(fid));
232 /* Open the file handle */
233 fd2 = open_by_handle_at(mnt_fd, fh, O_RDONLY);
235 fprintf(stderr, "open_by_handle_at(%s) error: %s\n", filename,
242 bzero(&st, sizeof(struct stat));
243 rc = fstat(fd2, &st);
245 fprintf(stderr, "fstat(%s) error: %s\n", filename,
251 if (ctime != st.st_ctime || file_size != st.st_size ||
252 inode != st.st_ino || mtime != st.st_mtime) {
253 fprintf(stderr, "stat data does not match between fopen "
254 "and fhandle case\n");
260 readbuf = malloc(len);
261 if (readbuf == NULL) {
262 fprintf(stderr, "malloc(%d) error: %s\n", len,
268 for (offset = 0; offset < st.st_size; offset += len) {
269 /* read from the file */
270 rc = read(fd2, readbuf, len);
272 fprintf(stderr, "read(%s) error: %s\n",
273 filename, strerror(errno));
281 fprintf(stdout, "check_fhandle_syscalls test Passed!\n");
296 #else /* !HAVE_FHANDLE_SYSCALLS */
300 fprintf(stderr, "HAVE_FHANDLE_SYSCALLS not defined\n");
302 #endif /* HAVE_FHANDLE_SYSCALLS */