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 <linux/lustre/lustre_user.h>
48 #define MAX_HANDLE_SZ 128
50 void usage(char *prog)
52 fprintf(stderr, "usage: %s <filepath> <mount2>\n",
54 fprintf(stderr, "the absolute path of a test file on a "
55 "lustre file system is needed.\n");
60 #ifndef HAVE_FHANDLE_SYSCALLS
62 int main(int argc, char **argv)
67 fprintf(stderr, "HAVE_FHANDLE_SYSCALLS not defined\n");
73 #ifndef HAVE_FHANDLE_GLIBC_SUPPORT
74 /* Because the kernel supports this functions doesn't mean that glibc does.
75 * Just in case we define what we need */
80 unsigned char f_handle[0];
83 #if defined(_ASM_X86_UNISTD_64_H)
85 #ifndef __NR_name_to_handle_at
86 #define __NR_name_to_handle_at 303
89 #ifndef __NR_open_by_handle_at
90 #define __NR_open_by_handle_at 304
93 #elif defined(_ASM_X86_UNISTD_32_H)
95 #ifndef __NR_name_to_handle_at
96 #define __NR_name_to_handle_at 341
99 #ifndef __NR_open_by_handle_at
100 #define __NR_open_by_handle_at 342
105 #ifndef __NR_name_to_handle_at
106 #define __NR_name_to_handle_at 264
109 #ifndef __NR_open_by_handle_at
110 #define __NR_open_by_handle_at 265
116 name_to_handle_at(int mnt_fd, const char *filename, struct file_handle *fh,
117 int *mnt_id, int flags)
119 return syscall(__NR_name_to_handle_at, mnt_fd, filename, fh,
124 open_by_handle_at(int mnt_fd, struct file_handle *fh, int mode)
126 return syscall(__NR_open_by_handle_at, mnt_fd, fh, mode);
130 /* verify a file contents */
131 int check_access(const char *filename,
132 int mnt_fd, struct file_handle *fh, struct stat *st_orig)
134 int fd2, rc, len, offset;
136 char *readbuf = NULL;
138 /* Open the file handle */
139 fd2 = open_by_handle_at(mnt_fd, fh, O_RDONLY);
141 fprintf(stderr, "open_by_handle_at(%s) error: %s\n", filename,
148 bzero(&st, sizeof(struct stat));
149 rc = fstat(fd2, &st);
151 fprintf(stderr, "fstat(%s) error: %s\n", filename,
157 /* we can't check a ctime due unlink update */
158 if (st_orig->st_size != st.st_size ||
159 st_orig->st_ino != st.st_ino ||
160 st_orig->st_mtime != st.st_mtime) {
161 fprintf(stderr, "stat data does not match between fopen "
162 "and fhandle case\n");
169 readbuf = malloc(len);
170 if (readbuf == NULL) {
171 fprintf(stderr, "malloc(%d) error: %s\n", len,
177 for (offset = 0; offset < st.st_size; offset += len) {
178 /* read from the file */
179 rc = read(fd2, readbuf, len);
181 fprintf(stderr, "read(%s) error: %s\n",
182 filename, strerror(errno));
197 int main(int argc, char **argv)
199 char *filename, *file;
200 int ret, rc = -EINVAL, mnt_fd, mnt_id, fd1, i;
201 struct file_handle *fh = NULL;
202 struct lu_fid *parent, *fid;
209 if (file[0] != '/') {
210 fprintf(stderr, "Need the absolete path of the file\n");
214 if (*argv[2] != '/') {
215 fprintf(stderr, "Need the absolete path of the mount point\n");
218 filename = rindex(file, '/') + 1;
220 fd1 = open(file, O_RDONLY);
222 fprintf(stderr, "open file %s error: %s\n",
223 file, strerror(errno));
228 /* Get file stats using fd1 from traditional open */
229 bzero(&st, sizeof(struct stat));
230 rc = fstat(fd1, &st);
232 fprintf(stderr, "fstat(%s) error: %s\n", file,
238 /* Open mount point directory */
239 mnt_fd = open(argv[2], O_DIRECTORY);
241 fprintf(stderr, "open(%s) error: %s\n)", argv[2],
247 /* Allocate memory for file handle */
248 fh = malloc(sizeof(struct file_handle) + MAX_HANDLE_SZ);
250 fprintf(stderr, "malloc(%d) error: %s\n", MAX_HANDLE_SZ,
255 fh->handle_bytes = MAX_HANDLE_SZ;
257 /* Convert name to handle */
258 ret = name_to_handle_at(AT_FDCWD, file, fh, &mnt_id,
261 fprintf(stderr, "name_by_handle_at(%s) error: %s\n", filename,
267 /* Print out the contents of the file handle */
268 fprintf(stdout, "fh_bytes: %u\nfh_type: %d\nfh_data: ",
269 fh->handle_bytes, fh->handle_type);
270 for (i = 0; i < fh->handle_bytes; i++)
271 fprintf(stdout, "%02x ", fh->f_handle[i]);
272 fprintf(stdout, "\n");
274 /* Lustre stores both the parents FID and the file FID
275 * in the f_handle. */
276 parent = (struct lu_fid *)(fh->f_handle + 16);
277 fid = (struct lu_fid *)fh->f_handle;
278 fprintf(stdout, "file's parent FID is "DFID"\n", PFID(parent));
279 fprintf(stdout, "file FID is "DFID"\n", PFID(fid));
281 fprintf(stdout, "just access via different mount point - ");
282 rc = check_access(filename, mnt_fd, fh, &st);
285 fprintf(stdout, "OK \n");
287 fprintf(stdout, "access after unlink - ");
290 fprintf(stderr, "can't unlink a file. check permissions?\n");
294 rc = check_access(filename, mnt_fd, fh, &st);
297 fprintf(stdout, "OK\n");
300 fprintf(stdout, "check_fhandle_syscalls test Passed!\n");