Errors from basic open_by_handle operations
I am having troubles with elementary file handle functions in libhandle.
A basic open_by_handle is giving "Bad file descriptor".
But I am suspicious of a side effect; using path_to_fshandle earlier in the program changes these errors to "Operation not permitted".
Is there a basic mistake in my use of these calls, or a bug/unmaintained code?
I am on an XFS filesystem (otherwise the first call fails with 'inappropriate ioctl'). The only documentation I can find is the man page; no mention about initialising the library, and I wasn't able to find any examples.
I'm on Scientific Linux 6.6 (like RedHat 6, kernel 2.6.32-504.1.3), and also tried updating to the latest xfsprogs from Git, with the same results.
Many thanks
Signature · 104 lines
Mark
$ ./test-xfs ~/scratch/tmp/xfs/file.c; echo $?
Handle 24 bytes: bd2c94ba959858e0000000870000000
readlink_by_handle: Bad file descriptor
open_by_handle: Bad file descriptor
0
$ ./test-xfs ~/scratch/tmp/xfs/file.c; echo $?
Handle 8 bytes: bd2c94ba959858
Handle 24 bytes: bd2c94ba959858e0000000870000000
readlink_by_handle: Operation not permitted
open_by_handle: Operation not permitted
0
/*
* xfs file handle test
*
* compile with: gcc -o test-xfs test-xfs.c -lhandle -Wall
*/
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <xfs/handle.h>
static void dump(FILE *f, void *m, size_t len)
{
fprintf(f, "Handle %zu bytes: ", len);
while (len--) {
fprintf(f, "%hhx", *(unsigned char*)m);
m++;
}
putchar('\n');
}
int main(int argc, char *argv[])
{
int fd;
char *pathname;
void *hanp = NULL;
size_t hlen;
char buf[PATH_MAX];
pathname = argv[1];
#if 0
/*
* Switching this section on changes changes the
* errors from the later calls
*/
if (path_to_fshandle(pathname, &hanp, &hlen) == -1) {
perror("path_to_fshandle");
return -1;
}
dump(stderr, hanp, hlen);
free_handle(hanp, hlen);
#endif
if (path_to_handle(pathname, &hanp, &hlen) == -1) {
perror("path_to_handle");
return -1;
}
dump(stderr, hanp, hlen);
/*
* The above calls were successful, but the next part always
* fails
*/
if (readlink_by_handle(hanp, hlen, buf, sizeof buf) == -1)
perror("readlink_by_handle");
else
printf("Link: %s\n", buf);
fd = open_by_handle(hanp, hlen, O_RDONLY);
if (fd == -1) {
perror("open_by_handle");
} else {
if (close(fd) == -1)
abort();
}
free_handle(hanp, hlen);
return 0;
}
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfsThere's a small gotcha - the filesystem itself has to have been opened:
void *xfs_handle = 0;
size_t hlen = 0;
/* xfs library needs the filesystem to have been opened */
if (path_to_fshandle(mountpoint, &xfs_handle, &hlen) < 0) {
/* error */
exit(4);
}
free(xfs_handle);Quoted 21 lines · Mark Hills
I am having troubles with elementary file handle functions in libhandle.
A basic
open_by_handleis giving "Bad file descriptor".But I am suspicious of a side effect; using
path_to_fshandleearlier in the program changes these errors to "Operation not permitted".Is there a basic mistake in my use of these calls, or a bug/unmaintained code?
I am on an XFS filesystem (otherwise the first call fails with 'inappropriate ioctl'). The only documentation I can find is the man page; no mention about initialising the library, and I wasn't able to find any examples.
I'm on Scientific Linux 6.6 (like RedHat 6, kernel 2.6.32-504.1.3), and also tried updating to the latest xfsprogs from Git, with the same results.
Many thanks
Signature · 6 lines
Roger Willcocks <[email protected]> _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Quoted 13 lines · Roger Willcocks
There's a small gotcha - the filesystem itself has to have been opened:
void *xfs_handle = 0; size_t hlen = 0; /* xfs library needs the filesystem to have been opened */ if (path_to_fshandle(mountpoint, &xfs_handle, &hlen) < 0) { /* error */ exit(4); } free(xfs_handle);
Thank you Roger, that moves me one step but not to success
Now I know "Operation not permitted" is the correct message I assume that use of XFS file handles requires root.
But even as root, I cannot open a file with O_RDONLY:
$ sudo ./test-xfs ~/scratch/tmp/xfs/file.c ; echo $? Handle 8 bytes: bd2c94ba959858 Handle 24 bytes: bd2c94ba959858e0000000870000000 readlink_by_handle: Not a directory open_by_handle: Not a directory 0
I am able to do open_by_handle(O_RDONLY) on a directory though:
$ sudo ./test-xfs ~/scratch/tmp/xfs/directory ; echo $? Handle 8 bytes: bd2c94ba959858 Handle 24 bytes: bd2c94ba959858e0000000880000000 readlink_by_handle: Invalid argument 0
and a readlink_by_handle on a symlink works:
$ sudo ./test-xfs ~/scratch/tmp/xfs/link.c ; echo $? Handle 8 bytes: bd2c94ba959858 Handle 24 bytes: bd2c94ba959858e0000000860000000 Link: fortress.c open_by_handle: Operation not permitted 0
Switching to O_RDWR does not succeed in opening a file either, and also stops the directory case.
It seems possible flags are getting mangled and are not what I think they mean. The docs state the call as analogous to open(); is the 'oflags' argument actually ready to accept O_RDONLY etc. or some other set of flags? Because it seems like I can't actually open a file here.
Many thanks
Signature · 6 lines
Mark _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Quoted 6 lines · Mark Hills
I am having troubles with elementary file handle functions in libhandle.
A basic
open_by_handleis giving "Bad file descriptor".But I am suspicious of a side effect; using
path_to_fshandleearlier in the program changes these errors to "Operation not permitted".
EPERM. Root permissions are required to convert file handles back to file descriptors, as the handle could have been passed to anyone and open_by_handle has no directory based access/permission checks to determine if the user actually has permission to access the inode behind the filehandle.
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH 1/1 libhandle: document the need for path_to_handle
In reply to Mark HillsThe handle ioctls require an open file descriptor to the XFS mount directory. This file descriptor is found and supplied in the libhandle code by matching the entry added with a path_to_handle() call. Document the requirement and supply a simple example.
--- man/man3/handle.3 | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-)
man/man3/handle.3 +69 -1
@@ -74,6 +74,12 @@ The function returns the handle for the filesystem in which the object given by the .I path argument resides. +.I path +must be the path to the mount point or +.BR open_by_handle () +will return the +.B ENOTDIR +error. .PP The .BR fd_to_handle ()
@@ -95,7 +101,16 @@ The function opens a file descriptor for the object referenced by a handle. It is analogous and identical to .BR open (2) -with the exception of accepting handles instead of path names. +with the exception of accepting handles instead of path names. The returned +file descriptor is opened to do invisible IO. Internally, +.BR open_by_handle () +uses the mount point file descriptor that was saved by +.BR path_to_fshandle (). +Therefore, +.BR path_to_fshandle (). +must be called before calling +.BR open_by_handle (). +See below for an example. .PP The .BR readlink_by_handle ()
@@ -192,6 +207,59 @@ does not exist. .TP .B EPERM The caller does not have sufficient privileges. +.SH EXAMPLE +Example of +.BR open_by_handle (). +.PP +.Vb 1 +\& main() +.br +\& { +.br +\& int fd; +.br +\& size_t hlen; +.br +\& void *han; +.br +\& size_t sz_int_used; +.br +\& void *hdl_int_used; +.br +\& char *mount_path = "/mnt/"; +.br +\& char *file = "file_to_open"; +.br +\& if (path_to_handle(file, &han, &hlen) < 0) { +.br +\& perror("path-to-handle"); +.br +\& exit(1); +.br +\& } +.br +\& /* +.br +\& * path_to_fshandle saves an internal copy of the mount point's +.br +\& * (/mnt in this example) file descriptor. The open_by_handle call +.br +\& * looks up this internal file descriptor and uses it in the +.br +\& * xfsctl call to the kernel. Once path_to_fshandle is called, +.br +\& * this internal file descriptor remains open for the remaining +.br +\& * life of the application. +.br +\& */ +.br +\& path_to_fshandle(mount_path, &hdl_int_used, &sz_int_used); +.br +\& fd = open_by_handle(han, hlen, O_RDWR); +.br +\&} +.Ve .SH SEE ALSO .BR open (2), .BR readlink (2),
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH] libhandle: document the need for path_to_handle
Quoted 17 lines · On Thu, Apr 09, 2015 at 08:31:04AM -0500, [email protected] wrote:
The handle ioctls require an open file descriptor to the XFS mount directory. This file descriptor is found and supplied in the libhandle code by matching the entry added with a
path_to_handle()call. Document the requirement and supply a simple example.Signed-off-by Mark Tinguely <[email protected]>--- man/man3/handle.3 | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-)Index: b/man/man3/handle.3
===================================================================
man/man3/handle.3 The · line 82
Quoted 9 lines
man/man3/handle.3 +6
-0@@ -74,6 +74,12 @@ The function returns the handle for the filesystem in which the object given by the .I path argument resides. +.I path +must be the path to the mount point or +.BR open_by_handle () +will return the +.B ENOTDIR +error.
This is wrong. ENOTDIR is only returned by open_by_handle if the cached fsfd is not a directory - it does not check if it's the root of a mount point at all. i.e, filesystem root is /mnt/scratch:
$ ls -l /mnt/scratch total 4 -rw-r--r--. 1 root root 0 Apr 13 09:57 foo drwxr-xr-x. 102 root root 4096 Apr 11 01:49 quota_dir $ $ sudo ./fhtest /mnt/scratch /mnt/scratch/foo open_by_handle: Success $ sudo ./fhtest /mnt/scratch/foo /mnt/scratch/foo open_by_handle: Not a directory $ sudo ./fhtest /mnt/scratch/quota_dir/ /mnt/scratch/foo open_by_handle: Success
So, as long as the fs path points to a directory on the filesystem in question, open_by_handle (and all the other handle functions) works just fine.
man/man3/handle.3 The · line 105
Quoted 10 lines
man/man3/handle.3 +2
-1.PP The .BR fd_to_handle ()@@ -95,7 +101,16 @@ The function opens a file descriptor for the object referenced by a handle. It is analogous and identical to .BR open (2) -with the exception of accepting handles instead of path names. +with the exception of accepting handles instead of path names. The returned +file descriptor is opened to do invisible IO. Internally,
Invisible IO is not defined anywhere in the man page, and most people will have no idea what it means. Either don't mention it, or define it properly first. For simplicity, I'd just omit it.
man/man3/handle.3 The · line 111
Quoted 6 lines
man/man3/handle.3 +6
-0+.BR open_by_handle () +uses the mount point file descriptor that was saved by +.BR path_to_fshandle (). +Therefore, +.BR path_to_fshandle (). +must be called before calling
I don't think you need to mention anything about internal implemenation of libhandle, just that a call to path_to_fshandle() is required first.
Quoted 45 lines
man/man3/handle.3 +38
-0+.BR open_by_handle (). +See below for an example. .PP The .BR readlink_by_handle ()@@ -192,6 +207,59 @@ does not exist. .TP .B EPERM The caller does not have sufficient privileges. +.SH EXAMPLE +Example of +.BR open_by_handle (). +.PP +.Vb 1 +\& main() +.br +\& { +.br +\& int fd; +.br +\& size_t hlen; +.br +\& void *han; +.br +\& size_t sz_int_used; +.br +\& void *hdl_int_used; +.br +\& char *mount_path = "/mnt/"; +.br +\& char *file = "file_to_open"; +.br +\& if (path_to_handle(file, &han, &hlen) < 0) { +.br +\& perror("path-to-handle"); +.br +\& exit(1); +.br +\& } +.br +\& /* +.br +\& * path_to_fshandle saves an internal copy of the mount point's +.br +\& * (/mnt in this example) file descriptor. The open_by_handle call
man/man3/handle.3 does not exist. · line 255
Quoted 10 lines
man/man3/handle.3 +10
-0+.br +\& * looks up this internal file descriptor and uses it in the +.br +\& * xfsctl call to the kernel. Once path_to_fshandle is called, +.br +\& * this internal file descriptor remains open for the remaining +.br +\& * life of the application. +.br +\& */
Again, this is internal implementation details, so isn't appropriate for a man page documenting an API.
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
The code below works here on a CentOS 6.4 box ('test' is a file at the root of the volume):
$ ./a.out hlen = 24 fd = -1 $ sudo ./a.out hlen = 24 fd = 4
/* g++ handle_test.cpp -lhandle */
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <xfs/handle.h>
int main(int argc, char *argv[])
{
void *xfs_handle = 0;
size_t hlen = 0;
if (path_to_fshandle("/mnt/disk1", &xfs_handle, &hlen) < 0)
exit(4);
if (path_to_handle("/mnt/disk1/test", &xfs_handle, &hlen) < 0)
exit(5);
printf("hlen = %d\n", (int)hlen);
int fd = open_by_handle(xfs_handle, hlen, O_RDWR); printf("fd = %d\n", fd);
return 0;
}
Quoted 21 lines · Mark Hills
I am having troubles with elementary file handle functions in libhandle.
A basic
open_by_handleis giving "Bad file descriptor".But I am suspicious of a side effect; using
path_to_fshandleearlier in the program changes these errors to "Operation not permitted".Is there a basic mistake in my use of these calls, or a bug/unmaintained code?
I am on an XFS filesystem (otherwise the first call fails with 'inappropriate ioctl'). The only documentation I can find is the man page; no mention about initialising the library, and I wasn't able to find any examples.
I'm on Scientific Linux 6.6 (like RedHat 6, kernel 2.6.32-504.1.3), and also tried updating to the latest xfsprogs from Git, with the same results.
Many thanks
Signature · 6 lines
Roger Willcocks <[email protected]> _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Quoted 9 lines · Roger Willcocks
The code below works here on a CentOS 6.4 box ('test' is a file at the root of the volume):
$ ./a.out hlen = 24 fd = -1 $ sudo ./a.out hlen = 24 fd = 4
Yup, and I can reproduce that here on my system, thanks.
It seems the subtlety is rooted here:
Quoted 5 lines
if (path_to_fshandle("/mnt/disk1", &xfs_handle, &hlen) < 0)
exit(4);
if (path_to_handle("/mnt/disk1/test", &xfs_handle, &hlen) < 0)
exit(5);This code is correct, and it looks like it's necessary to do path_to_fshandle on the file system root, otherwise it does not satisfy the precondition of open_by_handle().
So what I was doing:
path_to_fshandle("/mnt/disk1/test-file" ... );
...
path_to_handle("/mnt/disk1/test-file" ... );even though it reports the expected success (and returns the right file handles), is not enough to allow open_by_handle() to work on a file.
It does leave me needing to have prior knowledge of the mounted filesystem root (or look it up); handle_to_fshandle() doesn't achieve the same.
Definitely some oddities here -- but now I have enough to get me started though I hope.
Thanks for all the help, and perhaps I can look at some patches to the man page as I go.
Thanks
Signature · 6 lines
Mark _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs