Discussion:
[OpenAFS] check in c (linux) whether a directory entry is a mount point for an AFS volume
Christian
2018-08-03 11:08:02 UTC
Permalink
Hi all,

is there an easy way to check in C (under linux) whether a directory
entry is a mount point for an afs volume and maybe also obtain the name
of the volume mounted?

Thanks,

Christian
Stephan Wiesand
2018-08-03 11:22:05 UTC
Permalink
Post by Christian
is there an easy way to check in C (under linux) whether a directory
entry is a mount point for an afs volume and maybe also obtain the name
of the volume mounted?
popen("fs lsm /the/path", "r") ?
Michael Meffie
2018-08-04 03:04:44 UTC
Permalink
On Fri, 3 Aug 2018 13:22:05 +0200
Post by Stephan Wiesand
Post by Christian
is there an easy way to check in C (under linux) whether a directory
entry is a mount point for an afs volume and maybe also obtain the name
of the volume mounted?
popen("fs lsm /the/path", "r") ?
Hi Christian,

Since you asked for a way to check in C, looking at the fs lsmount
implementation, you can see the OpenAFS fs program issues an ioctl (under linux) to
do a "mount point stat". The ioctl returns EINVAL if the path is not an openafs
"mount point".

Here's a working example (for linux only):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>

#define AFSCALL_PIOCTL 20
#define AFS_PIOCTL_MAXSIZE 2048

#define _VICEIOCTL(id) ((unsigned int) _IOW('V', id, struct ViceIoctl))
#define VIOC_AFS_STAT_MT_PT _VICEIOCTL(29)
#define VIOC_SYSCALL_TYPE 'C'
#define VIOC_SYSCALL _IOW(VIOC_SYSCALL_TYPE,1,void *)

#define PROC_SYSCALL_FNAME "/proc/fs/openafs/afs_ioctl"

struct ViceIoctl {
caddr_t in;
caddr_t out;
short in_size;
short out_size;
};

struct afsprocdata {
long param4;
long param3;
long param2;
long param1;
long syscall;
};

char buffer[AFS_PIOCTL_MAXSIZE];

int pioctl(char *path, int command, struct ViceIoctl *arg, int follow)
{
int code;
int fd;
struct afsprocdata syscall_data;

fd = open(PROC_SYSCALL_FNAME, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "failed to open %s; errno=%d\n", PROC_SYSCALL_FNAME, errno);
return -1;
}

syscall_data.syscall = (long)AFSCALL_PIOCTL;
syscall_data.param1 = (long)path;
syscall_data.param2 = (long)command;
syscall_data.param3 = (long)arg;
syscall_data.param4 = (long)follow;

code = ioctl(fd, VIOC_SYSCALL, &syscall_data);
close(fd);
return code;
}

int main(int argc, char *argv)
{
int code;
struct ViceIoctl blob;
char *parent = "/afs/example.com/test";
char *last = "xyzzy";

memset(buffer, 0, AFS_PIOCTL_MAXSIZE);
blob.in = last;
blob.in_size = strlen(last) + 1;
blob.out_size = AFS_PIOCTL_MAXSIZE;
blob.out = buffer;

code = pioctl(parent, VIOC_AFS_STAT_MT_PT, &blob, 1);
if (code == 0) {
printf("%s/%s is a mount point for volume %s\n", parent, last, buffer);
} else if (errno == EINVAL) {
printf("%s/%s is not a mount point\n", parent, last);
} else {
fprintf(stderr, "pioctl failed: code=%d; errno=%d\n", code, errno);
}

return 0;
}

/*
* Example usage:
*
* $ make lsm
* cc lsm.c -o lsm
* $ ./lsm
* /afs/example.com/test/xyzzy is a mount point for volume #xyzzy
*
*/

Hope this helps,
Mike
--
Michael Meffie <***@sinenomine.net>
David Howells
2018-08-03 14:43:59 UTC
Permalink
With kAFS, you can do this:

[***@andromeda ~]# getfattr /kafs/.procyon.org.uk -d --match ".*"
getfattr: Removing leading '/' from absolute path names
# file: kafs/.procyon.org.uk
afs.cell="procyon.org.uk"
afs.fid="100005:1:1"
afs.volume="root.cell"

could that be added to OpenAFS also?

Also, you can use statx(2) to find out if the target path is an automount
point (struct statx::stx_attributes & STATX_ATTR_AUTOMOUNT) under kAFS.
OpenAFS could set the bit to indicate that this is a mountpoint, even though
it doesn't actually use the Linux kernel d_automount function.

David
Ken Hornstein
2018-08-04 04:40:16 UTC
Permalink
Post by Christian
is there an easy way to check in C (under linux) whether a directory
entry is a mount point for an afs volume and maybe also obtain the name
of the volume mounted?
Assuming vanilla AFS ... the absolute easiest way to check to see if a
directory entry is a mount point is stat() the directory. If the inode
number of the directory is odd, it's a "real" directory. If the inode
number is even, it's a mount point.

Determing the mount point NAME is more code from C; popen("fs lsm <X>")
might be the easist. You won't have to do it that often once you figure
out what is and isn't a mountpoint, though.

--Ken
Jeffrey Altman
2018-08-05 00:25:31 UTC
Permalink
Post by Ken Hornstein
Post by Christian
is there an easy way to check in C (under linux) whether a directory
entry is a mount point for an afs volume and maybe also obtain the name
of the volume mounted?
Assuming vanilla AFS ... the absolute easiest way to check to see if a
directory entry is a mount point is stat() the directory. If the inode
number of the directory is odd, it's a "real" directory. If the inode
number is even, it's a mount point.
Determing the mount point NAME is more code from C; popen("fs lsm <X>")
might be the easist. You won't have to do it that often once you figure
out what is and isn't a mountpoint, though.
--Ken
I'm not sure that the application will have the ability to stat the
mount point object. The OpenAFS cache manager will always provide the
details of the target volume root directory unless the target volume
cannot be located or accessed.

Jeffrey Altman
Ken Hornstein
2018-08-05 00:30:20 UTC
Permalink
Post by Jeffrey Altman
I'm not sure that the application will have the ability to stat the
mount point object. The OpenAFS cache manager will always provide the
details of the target volume root directory unless the target volume
cannot be located or accessed.
I can only say that this technique has worked for several decades and
still seems to work today.

--Ken
Jeffrey Altman
2018-08-05 00:43:36 UTC
Permalink
Post by Ken Hornstein
Post by Jeffrey Altman
I'm not sure that the application will have the ability to stat the
mount point object. The OpenAFS cache manager will always provide the
details of the target volume root directory unless the target volume
cannot be located or accessed.
I can only say that this technique has worked for several decades and
still seems to work today.
--Ken
that would be an odd inconsistency in behavior between "fs examine" and
stat().
Christian
2018-08-31 13:55:11 UTC
Permalink
Dear Ken,

thank you, this is exactly what I was looking for. I can confirm that it
works. The code from Michael were also very helpful. Thanks to all those
who replied,

Christian
Post by Ken Hornstein
Post by Christian
is there an easy way to check in C (under linux) whether a directory
entry is a mount point for an afs volume and maybe also obtain the name
of the volume mounted?
Assuming vanilla AFS ... the absolute easiest way to check to see if a
directory entry is a mount point is stat() the directory. If the inode
number of the directory is odd, it's a "real" directory. If the inode
number is even, it's a mount point.
Determing the mount point NAME is more code from C; popen("fs lsm <X>")
might be the easist. You won't have to do it that often once you figure
out what is and isn't a mountpoint, though.
--Ken
Loading...