Loading...
Searching...
No Matches
XrdFfsXrootdfs.cc
Go to the documentation of this file.
/******************************************************************************/
/* xrootdfs.cc FUSE based file system interface to Xrootd Storage Cluster */
/* */
/* (c) 2010 by the Board of Trustees of the Leland Stanford, Jr., University */
/* All Rights Reserved */
/* Author: Wei Yang (SLAC National Accelerator Laboratory, 2009) */
/* Contract DE-AC02-76-SFO0515 with the Department of Energy */
/* */
/* This file is part of the XRootD software suite. */
/* */
/* XRootD is free software: you can redistribute it and/or modify it under */
/* the terms of the GNU Lesser General Public License as published by the */
/* Free Software Foundation, either version 3 of the License, or (at your */
/* option) any later version. */
/* */
/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
/* License for more details. */
/* */
/* You should have received a copy of the GNU Lesser General Public License */
/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
/* */
/* The copyright holder's institutional names and contributor's names may not */
/* be used to endorse or promote products derived from this software without */
/* specific prior written permission of the institution or contributor. */
/******************************************************************************/
#define FUSE_USE_VERSION 26
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <stddef.h>
#if defined(__linux__)
/* For pread()/pwrite() */
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 500
#endif
#endif
#include <fuse.h>
#include <fuse/fuse_opt.h>
#include <cctype>
#include <cstring>
#include <fcntl.h>
#include <dirent.h>
#include <cerrno>
#include <sys/time.h>
#include <pthread.h>
#include <pwd.h>
#include <libgen.h>
#include <syslog.h>
#include <signal.h>
#if defined(__linux__)
#include <sys/prctl.h>
#endif
#include <sys/xattr.h>
#include "XrdFfs/XrdFfsPosix.hh"
#include "XrdFfs/XrdFfsMisc.hh"
#include "XrdFfs/XrdFfsWcache.hh"
#include "XrdFfs/XrdFfsQueue.hh"
//#include "XrdFfs/XrdFfsDent.hh"
#include "XrdFfs/XrdFfsFsinfo.hh"
#include "XrdPosix/XrdPosixXrootd.hh"
#define MAXROOTURLLEN 1024 // this is also defined in other files
struct XROOTDFS {
char *rdr;
char *cns;
char *fastls;
char *daemon_user;
char *ssskeytab;
char *urlcachelife;
bool ofsfwd;
int nworkers;
int maxfd;
};
int cwdfd; // File descript of the initial working dir
struct XROOTDFS xrootdfs;
static struct fuse_opt xrootdfs_opts[14];
enum { OPT_KEY_HELP, OPT_KEY_SECSSS, };
bool usingEC = false;
static void* xrootdfs_init(struct fuse_conn_info *conn)
{
struct passwd pw, *pwp;
char *pwbuf;
size_t pwbuflen;
struct rlimit rl;
rl.rlim_cur = RLIM_INFINITY;
rl.rlim_max = RLIM_INFINITY;
setrlimit(RLIMIT_CORE, &rl); // attemp to enable core dump
pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
pwbuf = (char*)malloc(pwbuflen + 1);
if (xrootdfs.daemon_user != NULL)
{
int i, len;
len = strlen(xrootdfs.daemon_user);
for (i=0; i<len; i++) // daemon_user can be both string name or uid
{
if (isdigit(xrootdfs.daemon_user[i]) == 0)
{
getpwnam_r(xrootdfs.daemon_user, &pw, pwbuf, pwbuflen, &pwp);
break;
}
}
if (i == len) getpwuid_r(atoi(xrootdfs.daemon_user), &pw, pwbuf, pwbuflen, &pwp);
if( setgid((gid_t)pw.pw_gid) != 0 )
syslog( LOG_ERR, "ERROR: Unable to set gid to %d", pw.pw_gid );
if( setuid((uid_t)pw.pw_uid) != 0 )
syslog( LOG_ERR, "ERROR: Unable to set uid to %d", pw.pw_uid );
#if defined(__linux__)
prctl(PR_SET_DUMPABLE, 1); // enable core dump after setuid/setgid
#endif
}
free(pwbuf);
/* put Xrootd related initialization calls here, after fuse daemonize itself. */
XrdPosixXrootd *abc = new XrdPosixXrootd(-xrootdfs.maxfd);
XrdFfsMisc_xrd_init(xrootdfs.rdr,xrootdfs.urlcachelife,0);
XrdFfsWcache_init(abc->fdOrigin(), xrootdfs.maxfd);
char *next, *savptr;
next = strtok_r(strdup(xrootdfs.rdr), "//", &savptr);
next = strtok_r(NULL, "//", &savptr);
char exportpath[1024];
while ((next = strtok_r(NULL, "//", &savptr)) != NULL)
{
strcat(exportpath, "/");
strcat(exportpath, next);
}
setenv("XRDEXPORTS", exportpath, 1);
/*
From FAQ:
Miscellaneous threads should be started from the init() method.
Threads started before fuse_main() will exit when the process goes
into the background.
*/
#ifndef NOUSE_QUEUE
XrdFfsQueue_create_workers(xrootdfs.nworkers);
syslog(LOG_INFO, "INFO: Starting %d workers", XrdFfsQueue_count_workers());
#else
syslog(LOG_INFO, "INFO: Not compiled to use task queue");
#endif
if (fchdir(cwdfd)) {};
close(cwdfd);
return NULL;
}
static int xrootdfs_getattr(const char *path, struct stat *stbuf)
{
// int res, fd;
int res;
char rootpath[MAXROOTURLLEN];
// uid_t user_uid, uid;
// gid_t user_gid, gid;
// user_uid = fuse_get_context()->uid;
// uid = getuid();
// user_gid = fuse_get_context()->gid;
// gid = getgid();
XrdFfsMisc_xrd_secsss_register(fuse_get_context()->uid, fuse_get_context()->gid, 0);
rootpath[0]='\0';
/*
if (xrootdfs.cns != NULL && xrootdfs.fastls != NULL)
strcat(rootpath,xrootdfs.cns);
else
strcat(rootpath,xrootdfs.rdr);
strcat(rootpath,path);
// setegid(fuse_get_context()->gid);
// seteuid(fuse_get_context()->uid);
res = XrdFfsPosix_stat(rootpath, stbuf);
*/
if (xrootdfs.cns != NULL && xrootdfs.fastls != NULL)
{
strncat(rootpath,xrootdfs.cns, MAXROOTURLLEN - strlen(rootpath) -1);
strncat(rootpath,path, MAXROOTURLLEN - strlen(rootpath) -1);
XrdFfsMisc_xrd_secsss_editurl(rootpath, fuse_get_context()->uid, 0);
res = XrdFfsPosix_stat(rootpath, stbuf);
}
else
res = XrdFfsPosix_statall(xrootdfs.rdr, path, stbuf, fuse_get_context()->uid);
// seteuid(getuid());
// setegid(getgid());
// stbuf->st_uid = user_uid;
// stbuf->st_gid = user_gid;
if (res == 0)
{
if (S_ISREG(stbuf->st_mode))
{
/*
By adding the following 'if' block, 'xrootdfs.fastls = RDR' will force XrootdFS to check
with redirector for file status info (not directory).
Some applicatios such as SRM may do extensive file or directory existence checking.
These applications can't tolerant slow responding on file or directory info (if
don't exist). They also expect correct file size. For this type of application, we
can set 'xrootdfs.fastls = RDR'.
Allowing multi-thread may solve this problem. However, XrootdFS crashs under some
situation, and we have to add -s (single thread) option when runing XrootdFS.
*/
if (xrootdfs.cns != NULL && xrootdfs.fastls != NULL && strcmp(xrootdfs.fastls,"RDR") == 0)
{
rootpath[0]='\0';
strncat(rootpath,xrootdfs.rdr, MAXROOTURLLEN - strlen(rootpath) -1);
strncat(rootpath,path, MAXROOTURLLEN - strlen(rootpath) -1);
XrdFfsMisc_xrd_secsss_editurl(rootpath, fuse_get_context()->uid, 0);
XrdFfsPosix_stat(rootpath, stbuf);
// stbuf->st_uid = user_uid;
// stbuf->st_gid = user_gid;
}
stbuf->st_mode |= 0666;
stbuf->st_mode &= 0772777; /* remove sticky bit and suid bit */
stbuf->st_blksize = 32768; /* unfortunately, it is ignored, see include/fuse.h */
return 0;
}
else if (S_ISDIR(stbuf->st_mode))
{
stbuf->st_mode |= 0777;
stbuf->st_mode &= 0772777; /* remove sticky bit and suid bit */
return 0;
}
else
return -EIO;
}
else if (res == -1 && xrootdfs.cns != NULL && xrootdfs.fastls != NULL)
return -errno;
else if (xrootdfs.cns == NULL)
return -errno;
else
{
rootpath[0]='\0';
strncat(rootpath,xrootdfs.cns, MAXROOTURLLEN - strlen(rootpath) -1);
strncat(rootpath,path, MAXROOTURLLEN - strlen(rootpath) -1);
XrdFfsMisc_xrd_secsss_editurl(rootpath, fuse_get_context()->uid, 0);
res = XrdFfsPosix_stat(rootpath, stbuf);
// stbuf->st_uid = user_uid;
// stbuf->st_gid = user_gid;
if (res == -1)
return -errno;
else
{
if (S_ISREG(stbuf->st_mode))
return -ENOENT;
else if (S_ISDIR(stbuf->st_mode))
{
stbuf->st_mode |= 0777;
stbuf->st_mode &= 0772777;
return 0;
}
else
return -EIO;
}
}
}
static int xrootdfs_access(const char *path, int mask)
{
/*
int res;
res = access(path, mask);
if (res == -1)
return -errno;
*/
return 0;
}
static int xrootdfs_readlink(const char *path, char *buf, size_t size)
{
/*
int res;
res = readlink(path, buf, size - 1);
if (res == -1)
return -errno;
buf[res] = '\0';
*/
return 0;
}
static int xrootdfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi)
{
DIR *dp;
struct dirent *de;
(void) offset;
(void) fi;
char rootpath[MAXROOTURLLEN];
XrdFfsMisc_xrd_secsss_register(fuse_get_context()->uid, fuse_get_context()->gid, 0);
/*
if CNS server is not defined, there is no way to list files in a directory
because we don't know the data nodes
*/
if (xrootdfs.cns != NULL)
{
rootpath[0]='\0';
strncat(rootpath,xrootdfs.cns, MAXROOTURLLEN - strlen(rootpath) -1);
strncat(rootpath,path, MAXROOTURLLEN - strlen(rootpath) -1);
XrdFfsMisc_xrd_secsss_editurl(rootpath, fuse_get_context()->uid, 0);
dp = XrdFfsPosix_opendir(rootpath);
if (dp == NULL)
return -errno;
while ((de = XrdFfsPosix_readdir(dp)) != NULL)
{
/*
struct stat st;
memset(&st, 0, sizeof(st));
st.st_ino = de->d_ino;
st.st_mode = de->d_type << 12;
*/
if (filler(buf, de->d_name, NULL, 0))
break;
}
XrdFfsPosix_closedir(dp);
return 0;
}
else /* if there is no CNS, try collect dirents from all known data servers. */
{
int i, n;
char **dnarray = NULL;
n = XrdFfsPosix_readdirall(xrootdfs.rdr, path, &dnarray, fuse_get_context()->uid);
for (i = 0; i < n; i++)
if (filler(buf, dnarray[i], NULL, 0)) break;
/*
this loop should not be merged with the above loop because all members of
dnarray[] should be freed, or there will be memory leak.
*/
for (i = 0; i < n; i++)
free(dnarray[i]);
free(dnarray);
return -errno;
}
}
static int xrootdfs_do_create(const char *path, const char *url, int oflags, bool use_link_id, int *fd)
/* Actually implement creating a file as generally as possible.
*
* path: file path
* url: xrootd root url to use
* oflags: posix oflags
* use_link_id: register multiple secsss user numbers for editurl
* fd: return file descriptor here
*
* returns: 0 on success, -errno on error.
*/
{
int res, link_id;
int *p_link_id = NULL;
char rootpath[MAXROOTURLLEN] = "";
if (use_link_id)
p_link_id = &link_id;
XrdFfsMisc_xrd_secsss_register(fuse_get_context()->uid, fuse_get_context()->gid, p_link_id);
strncat(rootpath, url, MAXROOTURLLEN - strlen(rootpath) - 1);
strncat(rootpath, path, MAXROOTURLLEN - strlen(rootpath) - 1);
XrdFfsMisc_xrd_secsss_editurl(rootpath, fuse_get_context()->uid, p_link_id);
res = XrdFfsPosix_open(rootpath, oflags, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
if (res == -1)
return -errno;
if (fd != NULL)
*fd = res;
return 0;
}
static int xrootdfs_mknod(const char *path, mode_t mode, dev_t rdev)
/* Implement MKNOD for FUSE, which is supposed to be used for special files.
* Can be used when CREATE is not available.
* This implementation only supports normal files.
* Just create the file, then close it. Also create cns file.
*
* path: file path
* mode: file attribute bitmask
* rdev: device number
*
* returns: 0 on success, -errno on error.
*/
{
int res, fd;
if (!S_ISREG(mode))
return -EPERM;
/*
Around May 2008, the O_EXCL was added to the _open(). No reason was given. It is removed again
due to the following reason (the situation that redirector thinks a file exist while it doesn't):
1. FUSE will use _getattr to determine file status. _mknod() will be called only if _getattr()
determined that the file does not exist.
2. In the case that rootd security is enabled, if a user create a file at an unauthorized path
(and fail), redirector thinks the files exist but it actually does't exist (enabling security
on redirector doesn't seems to help. An authorized user won't be able to create the same file
until the redirector forgets about it.
res = XrdFfsPosix_open(rootpath, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
*/
res = xrootdfs_do_create(path, xrootdfs.rdr, O_CREAT | O_WRONLY, false, &fd);
if (res < 0) return res;
XrdFfsPosix_close(fd);
if (xrootdfs.cns != NULL)
{
xrootdfs_do_create(path, xrootdfs.cns, O_CREAT | O_EXCL, false, &fd);
XrdFfsPosix_close(fd);
}
return res;
}
static int xrootdfs_create(const char *path, mode_t mode, struct fuse_file_info *fi)
/* Implement CREATE for FUSE, to create and open a normal file.
* Create a file and return its fd. Also create cns file.
*
* path: file path
* mode: file attribute bitmask
* fi: file info, return file descriptor in here
*
* returns: 0 on success, -errno on error.
*/
{
int res, fd;
if (!S_ISREG(mode))
return -EPERM;
if (usingEC)
res = xrootdfs_do_create(path, xrootdfs.rdr, O_CREAT | O_WRONLY | O_EXCL, true, &fd);
else
res = xrootdfs_do_create(path, xrootdfs.rdr, O_CREAT | O_WRONLY, true, &fd);
if (res < 0) return res;
fi->fh = fd;
XrdFfsWcache_create(fd, fi->flags); // Unlike mknod and like open, prepare wcache.
if (xrootdfs.cns != NULL)
{
xrootdfs_do_create(path, xrootdfs.cns, O_CREAT | O_EXCL, false, &fd);
XrdFfsPosix_close(fd);
}
return res;
}
static int xrootdfs_mkdir(const char *path, mode_t mode)
{
int res;
char rootpath[1024];
/*
Posix Mkdir() fails on the current version of Xrootd, 20071101-0808p1
So we avoid doing that. This is fixed in CVS head version.
*/
/*
if CNS is defined, only mkdir() on CNS. Otherwise, mkdir() on redirector
*/
rootpath[0]='\0';
if (xrootdfs.cns != NULL)
strncat(rootpath,xrootdfs.cns, MAXROOTURLLEN - strlen(rootpath) -1);
else
strncat(rootpath,xrootdfs.rdr, MAXROOTURLLEN - strlen(rootpath) -1);
strncat(rootpath,path, MAXROOTURLLEN - strlen(rootpath) -1);
XrdFfsMisc_xrd_secsss_register(fuse_get_context()->uid, fuse_get_context()->gid, 0);
XrdFfsMisc_xrd_secsss_editurl(rootpath, fuse_get_context()->uid, 0);
res = XrdFfsPosix_mkdir(rootpath, mode);
if (res == 0) return 0;
/*
now we are here either because there is either a race to create the directory, or the redirector
incorrectly cached a non-existing one (see _mknod() for more explaitation)
the following code try to clear the redirector cache. In the case of two racing mkdir(), it doesn't
care which one will success/fail.
*/
XrdFfsPosix_clear_from_rdr_cache(rootpath);
res = XrdFfsPosix_mkdir(rootpath, mode);
return ((res == -1)? -errno : 0);
}
static int xrootdfs_unlink(const char *path)
{
int res;
char rootpath[MAXROOTURLLEN];
rootpath[0]='\0';
strncat(rootpath,xrootdfs.rdr, MAXROOTURLLEN - strlen(rootpath) -1);
strncat(rootpath,path, MAXROOTURLLEN - strlen(rootpath) -1);
XrdFfsMisc_xrd_secsss_register(fuse_get_context()->uid, fuse_get_context()->gid, 0);
if (xrootdfs.ofsfwd == true)
{
XrdFfsMisc_xrd_secsss_editurl(rootpath, fuse_get_context()->uid, 0);
res = XrdFfsPosix_unlink(rootpath);
}
else
res = XrdFfsPosix_unlinkall(xrootdfs.rdr, path, fuse_get_context()->uid);
if (res == -1)
return -errno;
if (xrootdfs.cns != NULL && xrootdfs.ofsfwd == false)
{
rootpath[0]='\0';
strncat(rootpath,xrootdfs.cns, MAXROOTURLLEN - strlen(rootpath) -1);
strncat(rootpath,path, MAXROOTURLLEN - strlen(rootpath) -1);
XrdFfsMisc_xrd_secsss_editurl(rootpath, fuse_get_context()->uid, 0);
res = XrdFfsPosix_unlink(rootpath);
if (res == -1)
return -errno;
}
return 0;
}
static int xrootdfs_rmdir(const char *path)
{
int res;
// struct stat stbuf;
char rootpath[MAXROOTURLLEN];
rootpath[0]='\0';
strncat(rootpath,xrootdfs.rdr, MAXROOTURLLEN - strlen(rootpath) -1);
strncat(rootpath,path, MAXROOTURLLEN - strlen(rootpath) -1);
XrdFfsMisc_xrd_secsss_register(fuse_get_context()->uid, fuse_get_context()->gid, 0);
if (xrootdfs.ofsfwd == true)
{
XrdFfsMisc_xrd_secsss_editurl(rootpath, fuse_get_context()->uid, 0);
res = XrdFfsPosix_rmdir(rootpath);
}
else
res = XrdFfsPosix_rmdirall(xrootdfs.rdr, path, fuse_get_context()->uid);
if (res == -1)
return -errno;
if (xrootdfs.cns != NULL && xrootdfs.ofsfwd == false)
{
rootpath[0]='\0';
strncat(rootpath,xrootdfs.cns, MAXROOTURLLEN - strlen(rootpath) -1);
strncat(rootpath,path, MAXROOTURLLEN - strlen(rootpath) -1);
XrdFfsMisc_xrd_secsss_editurl(rootpath, fuse_get_context()->uid, 0);
res = XrdFfsPosix_rmdir(rootpath);
if (res == -1)
return -errno;
}
/*
clear cache in redirector. otherwise, an immediate mkdir(path) will fail
if (xrootdfs.ofsfwd == false)
{
rootpath[0]='\0';
strcat(rootpath,xrootdfs.rdr);
strcat(rootpath,path);
XrdFfsMisc_xrd_secsss_editurl(rootpath, fuse_get_context()->uid);
XrdFfsPosix_clear_from_xrootdfs.rdr_cache(rootpath); // no needed. _mkdir() is doing this.
}
*/
return 0;
}
static int xrootdfs_symlink(const char *from, const char *to)
{
/*
int res;
res = symlink(from, to);
if (res == -1)
return -errno;
*/
return -EIO;
}
static int xrootdfs_rename(const char *from, const char *to)
{
int res;
char from_path[MAXROOTURLLEN], to_path[MAXROOTURLLEN];
struct stat stbuf;
from_path[0]='\0';
strncat(from_path, xrootdfs.rdr, MAXROOTURLLEN - strlen(from_path) -1);
strncat(from_path, from, MAXROOTURLLEN - strlen(from_path) -1);
to_path[0]='\0';
strncat(to_path, xrootdfs.rdr, MAXROOTURLLEN - strlen(to_path) -1);
strncat(to_path, to, MAXROOTURLLEN - strlen(to_path) -1);
/*
1. do actual renaming on data servers if if is a file in order to speed up
renaming
2. return -EXDEV for renaming of directory so that files in the directory
are renamed individually (in order for the .pfn pointing back correctly).
*/
XrdFfsMisc_xrd_secsss_register(fuse_get_context()->uid, fuse_get_context()->gid, 0);
XrdFfsMisc_xrd_secsss_editurl(from_path, fuse_get_context()->uid, 0);
XrdFfsPosix_stat(from_path, &stbuf);
if (S_ISDIR(stbuf.st_mode)) /* && xrootdfs.cns == NULL && xrootdfs.ofsfwd == false) */
return -EXDEV;
if (xrootdfs.ofsfwd == true)
res = XrdFfsPosix_rename(from_path, to_path);
else
res = XrdFfsPosix_renameall(xrootdfs.rdr, from, to, fuse_get_context()->uid);
if (res == -1)
return -errno;
/* data servers may not notify redirector about the renaming. So we notify redirector */
XrdFfsPosix_clear_from_rdr_cache(from_path);
if (xrootdfs.cns != NULL && xrootdfs.ofsfwd == false)
{
from_path[0]='\0';
strncat(from_path, xrootdfs.cns, MAXROOTURLLEN - strlen(from_path) -1);
strncat(from_path, from, MAXROOTURLLEN - strlen(from_path) -1);
to_path[0]='\0';
strncat(to_path, xrootdfs.cns, MAXROOTURLLEN - strlen(to_path) -1);
strncat(to_path, to, MAXROOTURLLEN - strlen(to_path) -1);
res = XrdFfsPosix_rename(from_path, to_path);
if (res == -1)
return -errno;
}
return 0;
/* return -EXDEV */
}
static int xrootdfs_link(const char *from, const char *to)
{
/*
int res;
res = link(from, to);
if (res == -1)
return -errno;
*/
return -EMLINK;
}
static int xrootdfs_chmod(const char *path, mode_t mode)
{
/*
int res;
res = chmod(path, mode);
if (res == -1)
return -errno;
*/
return 0;
}
static int xrootdfs_chown(const char *path, uid_t uid, gid_t gid)
{
/*
int res;
res = lchown(path, uid, gid);
if (res == -1)
return -errno;
*/
return 0;
}
/* _ftruncate() will only work with kernel >= 2.6.15. See FUSE ChangeLog */
static int xrootdfs_ftruncate(const char *path, off_t size,
struct fuse_file_info *fi)
{
int fd, res;
// char rootpath[1024];
fd = (int) fi->fh;
XrdFfsWcache_flush(fd);
res = XrdFfsPosix_ftruncate(fd, size);
if (res == -1)
return -errno;
/*
There is no need to update the size of the CNS shadow file now. That
should be updated when the file is closed
if (xrootdfs.cns != NULL)
{
rootpath[0]='\0';
strcat(rootpath,xrootdfs.cns);
strcat(rootpath,path);
res = XrdFfsPosix_truncate(rootpath, size);
if (res == -1)
return -errno;
}
*/
return 0;
}
static int xrootdfs_truncate(const char *path, off_t size)
{
int res;
char rootpath[MAXROOTURLLEN];
rootpath[0]='\0';
strncat(rootpath,xrootdfs.rdr, MAXROOTURLLEN - strlen(rootpath) -1);
strncat(rootpath,path, MAXROOTURLLEN - strlen(rootpath) -1);
XrdFfsMisc_xrd_secsss_register(fuse_get_context()->uid, fuse_get_context()->gid, 0);
if (xrootdfs.ofsfwd == true)
{
XrdFfsMisc_xrd_secsss_editurl(rootpath, fuse_get_context()->uid, 0);
res = XrdFfsPosix_truncate(rootpath, size);
}
else
res = XrdFfsPosix_truncateall(xrootdfs.rdr, path, size, fuse_get_context()->uid);
if (res == -1)
return -errno;
if (xrootdfs.cns != NULL && xrootdfs.ofsfwd == false)
{
rootpath[0]='\0';
strncat(rootpath,xrootdfs.cns, MAXROOTURLLEN - strlen(rootpath) -1);
strncat(rootpath,path, MAXROOTURLLEN - strlen(rootpath) -1);
XrdFfsMisc_xrd_secsss_editurl(rootpath, fuse_get_context()->uid, 0);
res = XrdFfsPosix_truncate(rootpath, size);
if (res == -1)
return -errno;
}
return 0;
}
static int xrootdfs_utimens(const char *path, const struct timespec ts[2])
{
/*
int res;
struct timeval tv[2];
tv[0].tv_sec = ts[0].tv_sec;
tv[0].tv_usec = ts[0].tv_nsec / 1000;
tv[1].tv_sec = ts[1].tv_sec;
tv[1].tv_usec = ts[1].tv_nsec / 1000;
res = utimes(path, tv);
if (res == -1)
return -errno;
*/
return 0;
}
static int xrootdfs_open(const char *path, struct fuse_file_info *fi)
/*
* path: path to file
* fi: file info, return file descriptor in fi->fh
*
* returns 0 on success and -errno on error
*/
{
int fd, lid = 1;
char rootpath[MAXROOTURLLEN]="";
strncat(rootpath,xrootdfs.rdr, MAXROOTURLLEN - strlen(rootpath) -1);
strncat(rootpath,path, MAXROOTURLLEN - strlen(rootpath) -1);
XrdFfsMisc_xrd_secsss_register(fuse_get_context()->uid, fuse_get_context()->gid, &lid);
XrdFfsMisc_xrd_secsss_editurl(rootpath, fuse_get_context()->uid, &lid);
fd = XrdFfsPosix_open(rootpath, fi->flags, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
if (fd == -1)
return -errno;
fi->fh = fd;
// be careful, 0 means error for this function
if (XrdFfsWcache_create(fi->fh, fi->flags))
return 0;
else
return -errno;
}
static int xrootdfs_read(const char *path, char *buf, size_t size, off_t offset,
struct fuse_file_info *fi)
{
int fd;
int res;
fd = (int) fi->fh;
if ((fi->flags & O_ACCMODE) == O_RDWR) XrdFfsWcache_flush(fd);
if (usingEC)
{
struct stat stbuf;
XrdPosixXrootd::Fstat(fd, &stbuf); // Silly but does not seem to hurt performance
off_t fsize = stbuf.st_size;
if ( offset >= fsize )
return 0;
size = (size_t)(fsize - offset) > size ? size : fsize - offset;
// Restrict the use of read cache to O_DIRECT use case
// See comment in XRdFfsWcache_pread()
if ( ((fi->flags & O_ACCMODE) != O_RDWR) && (fi->flags & O_DIRECT) )
res = XrdFfsWcache_pread(fd, buf, size, offset);
else
res = XrdFfsPosix_pread(fd, buf, size, offset);
}
else
res = XrdFfsPosix_pread(fd, buf, size, offset);
if (res == -1)
res = -errno;
return res;
}
static int xrootdfs_write(const char *path, const char *buf, size_t size,
off_t offset, struct fuse_file_info *fi)
{
int fd;
int res;
/*
File already existed. FUSE uses xrootdfs_open() and xrootdfs_truncate() to open and
truncate a file before calling xrootdfs_write()
*/
fd = (int) fi->fh;
// res = XrdFfsPosix_pwrite(fd, buf, size, offset);
res = XrdFfsWcache_pwrite(fd, (char *)buf, size, offset);
if (res == -1)
res = -errno;
return res;
}
static int xrootdfs_statfs(const char *path, struct statvfs *stbuf)
{
int res;
// char rootpath[1024], xattr[256];
// char *token, *key, *value;
// char *lasts_xattr[256], *lasts_tokens[128];
// long long size;
// XrdFfsMisc_xrd_secsss_register(fuse_get_context()->uid, fuse_get_context()->gid);
#ifndef __APPLE__
stbuf->f_bsize = 1024;
#else
stbuf->f_bsize = 1024 * 128; // work around 32 bit fsblkcnt_t in struct statvfs on Mac OSX
stbuf->f_frsize = stbuf->f_bsize; // seems there are other limitations, 1024*128 is a max we set
#endif
// res = XrdFfsPosix_statvfsall(xrootdfs.rdr, path, stbuf, fuse_get_context()->uid);
res = XrdFfsFsinfo_cache_search(&XrdFfsPosix_statvfsall, xrootdfs.rdr, path, stbuf, fuse_get_context()->uid);
/*
stbuf->f_blocks /= stbuf->f_bsize;
stbuf->f_bavail /= stbuf->f_bsize;
stbuf->f_bfree /= stbuf->f_bsize;
*/
return res;
/*
stbuf->f_bsize = 16384;
stbuf->f_blocks = 1048576;
stbuf->f_bfree = stbuf->f_blocks;
stbuf->f_bavail = stbuf->f_blocks;
if (xrootdfs.cns == NULL) return 0;
rootpath[0]='\0';
strcat(rootpath,xrootdfs.cns);
strcat(rootpath,path);
res = XrdFfsPosix_getxattr(rootpath, "xroot.space", xattr, 256);
if (res == -1)
return 0;
else
{
token = strtok_r(xattr, "&", lasts_xattr);
while (token != NULL)
{
token = strtok_r(NULL, "&", lasts_xattr);
if (token == NULL) break;
key = strtok_r(token, "=", lasts_tokens);
value = strtok_r(NULL, "=", lasts_tokens);
if (!strcmp(key,"oss.used"))
{
sscanf((const char*)value, "%lld", &size);
stbuf->f_bavail = size / stbuf->f_bsize;
}
else if (!strcmp(key,"oss.quota"))
{
sscanf((const char*)value, "%lld", &size);
stbuf->f_blocks = size / stbuf->f_bsize;
}
}
stbuf->f_bavail = stbuf->f_blocks - stbuf->f_bavail;
stbuf->f_bfree = stbuf->f_bavail;
}
return 0;
*/
}
static int xrootdfs_release(const char *path, struct fuse_file_info *fi)
{
/* Just a stub. This method is optional and can safely be left
unimplemented */
int fd, oflag;
struct stat xrdfile, cnsfile;
char rootpath[MAXROOTURLLEN];
fd = (int) fi->fh;
XrdFfsWcache_flush(fd);
XrdFfsWcache_destroy(fd);
XrdFfsPosix_close(fd);
fi->fh = 0;
/*
Return at here because the current version of Cluster Name Space daemon
doesn't implement the 'truncate' functon we originally planned.
return 0;
*/
if (xrootdfs.cns == NULL)
return 0;
int res;
char xattr[256], xrdtoken[256];
char *token, *key, *value;
char *lasts_xattr[256], *lasts_tokens[128];
rootpath[0]='\0';
strncat(rootpath,xrootdfs.rdr, MAXROOTURLLEN - strlen(rootpath) -1);
strncat(rootpath,path, MAXROOTURLLEN - strlen(rootpath) -1);
/*
* Get xrootd token info from data nodes. And set the token info on CNS
*/
XrdFfsMisc_xrd_secsss_register(fuse_get_context()->uid, fuse_get_context()->gid, 0);
XrdFfsMisc_xrd_secsss_editurl(rootpath, fuse_get_context()->uid, 0);
xrdtoken[0]='\0';
res = XrdFfsPosix_getxattr(rootpath, "xroot.xattr", xattr, 256);
if (res != -1)
{
token = strtok_r(xattr, "&", lasts_xattr);
while (token != NULL)
{
key = strtok_r(token, "=", lasts_tokens);
value = strtok_r(NULL, "=", lasts_tokens);
if (!strcmp(key,"oss.cgroup"))
strcpy(xrdtoken, value);
if (!strcmp(key,"oss.used"))
{long long llVal;
sscanf((const char*)value, "%lld", &llVal);
xrdfile.st_size = llVal;
}
token = strtok_r(NULL, "&", lasts_xattr);
}
}
else
{
XrdFfsPosix_stat(rootpath,&xrdfile);
}
rootpath[0]='\0';
strncat(rootpath,xrootdfs.cns, MAXROOTURLLEN - strlen(rootpath) -1);
strncat(rootpath,path, MAXROOTURLLEN - strlen(rootpath) -1);
XrdFfsMisc_xrd_secsss_editurl(rootpath, fuse_get_context()->uid, 0);
if (xrdtoken[0] != '\0' && strstr(path,"?oss.cgroup=") == NULL)
{
strncat(rootpath,"?oss.cgroup=", MAXROOTURLLEN - strlen(rootpath) -1);
strncat(rootpath,xrdtoken, MAXROOTURLLEN - strlen(rootpath) -1);
}
if (XrdFfsPosix_stat(rootpath,&cnsfile) == -1)
oflag = O_CREAT|O_WRONLY;
else
oflag = O_TRUNC|O_WRONLY;
/*
This creates a file on CNS with the right size. But it is actually an empty file.
It doesn't use disk space, only inodes.
*/
if (cnsfile.st_size != xrdfile.st_size)
{
fd = XrdFfsPosix_open(rootpath,oflag,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
if (fd >= 0)
{
XrdFfsPosix_lseek(fd,(off_t)xrdfile.st_size-1,SEEK_SET);
XrdFfsPosix_write(fd,"",1);
XrdFfsPosix_close(fd);
}
}
return 0;
}
static int xrootdfs_fsync(const char *path, int isdatasync,
struct fuse_file_info *fi)
{
int fd;
fd = (int) fi->fh;
XrdFfsWcache_flush(fd);
XrdFfsPosix_fsync(fd);
return 0;
}
/* xattr operations are optional and can safely be left unimplemented */
static int xrootdfs_setxattr(const char *path, const char *name, const char *value,
size_t size, int flags)
{
if (fuse_get_context()->uid != 0 && fuse_get_context()->uid != getuid())
return -EPERM;
if (!strcmp(name,"xrootdfs.fs.dataserverlist"))
{
XrdFfsMisc_refresh_url_cache(xrootdfs.rdr);
XrdFfsMisc_logging_url_cache(NULL);
}
else if (!strcmp(name,"xrootdfs.fs.nworkers"))
{
int i, j;
char *tmp_value;
tmp_value=strdup(value);
if (size > 0) tmp_value[size] = '\0';
i = XrdFfsQueue_count_workers();
j = atoi(tmp_value);
free(tmp_value);
if (j > i)
XrdFfsQueue_create_workers( j-i );
if (j < i)
XrdFfsQueue_remove_workers( i-j ); // XrdFfsQueue_remove_workers() will wait until workers are removed.
j = XrdFfsQueue_count_workers();
#ifndef NOUSE_QUEUE
syslog(LOG_INFO, "INFO: Adjust the number of workers from %d to %d", i, j);
#endif
}
return 0;
}
static int xrootdfs_getxattr(const char *path, const char *name, char *value,
size_t size)
{
int xattrlen;
char rootpath[MAXROOTURLLEN]="";
char rooturl[MAXROOTURLLEN]="";
if (!strcmp(name,"xroot.url"))
{
errno = 0;
strncat(rootpath,xrootdfs.rdr, MAXROOTURLLEN - strlen(rootpath) -1);
strncat(rootpath,path, MAXROOTURLLEN - strlen(rootpath) -1);
// XrdFfsMisc_get_current_url(rootpath, rooturl);
strcpy(rooturl, rootpath);
if (size == 0)
return strlen(rooturl);
else if (size > strlen(rooturl)) // check the size to make sure strcat(value, rooturl) is safe
{
size = strlen(rooturl);
if (size != 0)
{
value[0] = '\0';
strcat(value, rooturl);
}
return size;
}
else
{
errno = ERANGE;
return -1;
}
}
else if (!strcmp(name, "xrootdfs.fs.dataserverlist"))
{
char *hostlist;
hostlist = (char*) malloc(sizeof(char) * XrdFfs_MAX_NUM_NODES * 256);
XrdFfsMisc_get_list_of_data_servers(hostlist);
if (size == 0)
{
xattrlen = strlen(hostlist);
free(hostlist);
return xattrlen;
}
else if (size > strlen(hostlist))
{
size = strlen(hostlist);
if (size != 0)
{
value[0] = '\0';
strcat(value, hostlist);
}
free(hostlist);
return size;
}
else
{
errno = ERANGE;
free(hostlist);
return -1;
}
}
else if (!strcmp(name, "xrootdfs.fs.nworkers"))
{
char nworkers[7];
int n;
n = XrdFfsQueue_count_workers();
sprintf(nworkers, "%d", n);
if (size == 0)
return strlen(nworkers);
else if (size > strlen(nworkers))
{
size = strlen(nworkers);
if (size != 0)
{
value[0] = '\0';
strcat(value, nworkers);
}
return size;
}
else
{
errno = ERANGE;
return -1;
}
}
else if (!strcmp(name, "xrootdfs.file.permission"))
{
char xattr[256]="";
strncat(rootpath,xrootdfs.rdr, MAXROOTURLLEN - strlen(rootpath) -1);
strncat(rootpath,path, MAXROOTURLLEN - strlen(rootpath) -1);
XrdFfsMisc_xrd_secsss_register(fuse_get_context()->uid, fuse_get_context()->gid, 0);
XrdFfsMisc_xrd_secsss_editurl(rootpath, fuse_get_context()->uid, 0);
xattrlen = XrdFfsPosix_getxattr(rootpath, "xroot.xattr.ofs.ap", xattr, 255);
if (size == 0)
return xattrlen;
else if (size > (size_t)xattrlen)
{
strncpy(value, xattr, size);
size = xattrlen;
value[size] = '\0';
return size;
}
else
{
errno = ERANGE;
return -1;
}
}
if (xrootdfs.cns != NULL)
strncat(rootpath,xrootdfs.cns, MAXROOTURLLEN - strlen(rootpath) -1);
else
strncat(rootpath,xrootdfs.rdr, MAXROOTURLLEN - strlen(rootpath) -1);
strncat(rootpath,path, MAXROOTURLLEN - strlen(rootpath) -1);
XrdFfsMisc_xrd_secsss_register(fuse_get_context()->uid, fuse_get_context()->gid, 0);
XrdFfsMisc_xrd_secsss_editurl(rootpath, fuse_get_context()->uid, 0);
xattrlen = XrdFfsPosix_getxattr(rootpath, name, value, size);
if (xattrlen == -1)
return -errno;
else
return xattrlen;
}
static int xrootdfs_listxattr(const char *path, char *list, size_t size)
{
/*
int res = llistxattr(path, list, size);
if (res == -1)
return -errno;
return res;
*/
return 0;
}
static int xrootdfs_removexattr(const char *path, const char *name)
{
/*
int res = lremovexattr(path, name);
if (res == -1)
return -errno;
*/
return 0;
}
/*
* We need this as casting function pointer to a function pointer
* of a different type and then calling it results in undefined
* behavior (Annex J.2).
*
* GCC 8 available on Fedora 28 is very picky about those things.
* On the other hand unfortunatelly we cannot use a lambda expression
* as it is not supported on GCC 4.4 which is shipped by default on
* EPEL 6.
*
*/
void* XrdFfsMisc_logging_url_cache_pthread_create_cast( void *arg )
{
XrdFfsMisc_logging_url_cache( reinterpret_cast<char*>( arg ) );
return 0;
}
void xrootdfs_sigusr1_handler(int sig)
{
/* Do this in a new thread because XrdFfsMisc_refresh_url_cache() contents mutex. */
pthread_t *thread;
pthread_attr_t attr;
size_t stacksize = 2*1024*1024;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, stacksize);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
thread = (pthread_t*) malloc(sizeof(pthread_t));
pthread_create(thread, &attr, XrdFfsMisc_logging_url_cache_pthread_create_cast,
xrootdfs.rdr);
pthread_detach(*thread);
free(thread);
pthread_attr_destroy(&attr);
}
static struct fuse_operations xrootdfs_oper;
static void xrootdfs_usage(const char *progname)
{
fprintf(stderr,
"usage: %s mountpoint options\n"
"\n"
"XrootdFS options:\n"
" -h -help --help print help\n"
"\n"
"Default options:\n"
" fsname=xrootdfs,allow_other,max_write=131072,attr_timeout=10,entry_timeout=10,negative_timeout=5\n"
" In case of an Erasure Encoding storage, entry_timeout=0\n"
"\n"
"[Required]\n"
" -o rdr=redirector_url root URL of the Xrootd redirector\n"
"\n"
"[Optional]\n"
" -o cns=cns_server_url root URL of the CNS server\n"
" -o uid=username cause XrootdFS to switch effective uid to that of username if possible\n"
" -o sss[=keytab] use Xrootd seciruty module \"sss\", specifying a keytab file is optional\n"
" -o refreshdslist=NNNs/m/h/d refresh internal list of data servers in NNN sec/min/hour/day, default unit is second\n"
" Absents of this option will disable automatically refreshing\n"
" -o maxfd=N number of virtual file descriptors for posix requests, default 8192 (min 2048)\n"
" -o nworkers=N number of workers to handle parallel requests to data servers, default 4\n"
" -o fastls=RDR set to RDR when CNS is presented will cause stat() to go to redirector\n"
"\n", progname);
}
static int xrootdfs_opt_proc(void* data, const char* arg, int key, struct fuse_args* outargs)
{
(void) data;
(void) outargs;
// printf("hellow key %d arg %s\n", key, arg);
switch (key) {
case FUSE_OPT_KEY_OPT:
return 1;
case FUSE_OPT_KEY_NONOPT:
return 1;
case OPT_KEY_SECSSS:
setenv("XROOTDFS_SECMOD", "sss", 1);
return 0;
case OPT_KEY_HELP:
xrootdfs_usage(outargs->argv[0]);
fuse_opt_add_arg(outargs, "-ho");
fuse_main(outargs->argc, outargs->argv, &xrootdfs_oper, NULL);
exit(1);
default:
return(-1);
;
}
}
int main(int argc, char *argv[])
{
xrootdfs_oper.init = xrootdfs_init;
xrootdfs_oper.getattr = xrootdfs_getattr;
xrootdfs_oper.access = xrootdfs_access;
xrootdfs_oper.readlink = xrootdfs_readlink;
xrootdfs_oper.readdir = xrootdfs_readdir;
xrootdfs_oper.mknod = xrootdfs_mknod;
xrootdfs_oper.mkdir = xrootdfs_mkdir;
xrootdfs_oper.create = xrootdfs_create;
xrootdfs_oper.symlink = xrootdfs_symlink;
xrootdfs_oper.unlink = xrootdfs_unlink;
xrootdfs_oper.rmdir = xrootdfs_rmdir;
xrootdfs_oper.rename = xrootdfs_rename;
xrootdfs_oper.link = xrootdfs_link;
xrootdfs_oper.chmod = xrootdfs_chmod;
xrootdfs_oper.chown = xrootdfs_chown;
xrootdfs_oper.ftruncate = xrootdfs_ftruncate;
xrootdfs_oper.truncate = xrootdfs_truncate;
xrootdfs_oper.utimens = xrootdfs_utimens;
xrootdfs_oper.open = xrootdfs_open;
xrootdfs_oper.read = xrootdfs_read;
xrootdfs_oper.write = xrootdfs_write;
xrootdfs_oper.statfs = xrootdfs_statfs;
xrootdfs_oper.release = xrootdfs_release;
xrootdfs_oper.fsync = xrootdfs_fsync;
xrootdfs_oper.setxattr = xrootdfs_setxattr;
xrootdfs_oper.getxattr = xrootdfs_getxattr;
xrootdfs_oper.listxattr = xrootdfs_listxattr;
xrootdfs_oper.removexattr = xrootdfs_removexattr;
/* Define XrootdFS options */
char **cmdline_opts;
if (getenv("XRDCL_EC")) usingEC = true;
cmdline_opts = (char **) malloc(sizeof(char*) * (argc -1 + 3));
cmdline_opts[0] = argv[0];
cmdline_opts[1] = strdup("-o");
if (getenv("XROOTDFS_NO_ALLOW_OTHER") != NULL && ! strcmp(getenv("XROOTDFS_NO_ALLOW_OTHER"),"1") )
{
if (! usingEC)
cmdline_opts[2] = strdup("fsname=xrootdfs,max_write=131072,attr_timeout=10,entry_timeout=10,negative_timeout=5");
else
cmdline_opts[2] = strdup("fsname=xrootdfs,max_write=131072,attr_timeout=10,entry_timeout=0,negative_timeout=5");
}
else
{
if (! usingEC)
cmdline_opts[2] = strdup("fsname=xrootdfs,allow_other,max_write=131072,attr_timeout=10,entry_timeout=10,negative_timeout=5");
else
cmdline_opts[2] = strdup("fsname=xrootdfs,allow_other,max_write=131072,attr_timeout=10,entry_timeout=0,negative_timeout=5");
}
for (int i = 1; i < argc; i++)
cmdline_opts[i+2] = argv[i];
struct fuse_args args = FUSE_ARGS_INIT(argc -1 + 3, cmdline_opts);
xrootdfs_opts[0].templ = "-h";
xrootdfs_opts[0].offset = -1U;
xrootdfs_opts[0].value = OPT_KEY_HELP;
xrootdfs_opts[1].templ = "-help";
xrootdfs_opts[1].offset = -1U;
xrootdfs_opts[1].value = OPT_KEY_HELP;
xrootdfs_opts[2].templ = "--help";
xrootdfs_opts[2].offset = -1U;
xrootdfs_opts[2].value = OPT_KEY_HELP;
xrootdfs_opts[3].templ = "rdr=%s";
xrootdfs_opts[3].offset = offsetof(struct XROOTDFS, rdr);
xrootdfs_opts[3].value = 0;
xrootdfs_opts[4].templ = "cns=%s";
xrootdfs_opts[4].offset = offsetof(struct XROOTDFS, cns);
xrootdfs_opts[4].value = 0;
xrootdfs_opts[5].templ = "fastls=%s";
xrootdfs_opts[5].offset = offsetof(struct XROOTDFS, fastls);
xrootdfs_opts[5].value = 0;
xrootdfs_opts[6].templ = "uid=%s";
xrootdfs_opts[6].offset = offsetof(struct XROOTDFS, daemon_user);
xrootdfs_opts[6].value = 0;
xrootdfs_opts[7].templ = "ofsfwd=%s";
xrootdfs_opts[7].offset = offsetof(struct XROOTDFS, ofsfwd);
xrootdfs_opts[7].value = 0;
/* using "sss" security module. the actually location of the key is determined
by shell enviornment variable XrdSecsssKT (or default locations). */
/* The location of the key is not specified in command line. */
xrootdfs_opts[8].templ = "sss";
xrootdfs_opts[8].offset = -1U;
xrootdfs_opts[8].value = OPT_KEY_SECSSS;
/* The location of the key is specified in command line. */
xrootdfs_opts[9].templ = "sss=%s";
xrootdfs_opts[9].offset = offsetof(struct XROOTDFS, ssskeytab);
xrootdfs_opts[9].value = 0;
/* life time of the data server list */
xrootdfs_opts[10].templ = "refreshdslist=%s";
xrootdfs_opts[10].offset = offsetof(struct XROOTDFS, urlcachelife);
xrootdfs_opts[10].value = 0;
/* number of workers to handle parallel requests to data servers */
xrootdfs_opts[11].templ = "nworkers=%d";
xrootdfs_opts[11].offset = offsetof(struct XROOTDFS, nworkers);
xrootdfs_opts[11].value = 0;
/* number of virtual file descriptors */
xrootdfs_opts[12].templ = "maxfd=%d";
xrootdfs_opts[12].offset = offsetof(struct XROOTDFS, maxfd);
xrootdfs_opts[12].value = 0;
xrootdfs_opts[13].templ = NULL;
/* initialize struct xrootdfs */
// memset(&xrootdfs, 0, sizeof(xrootdfs));
xrootdfs.rdr = NULL;
xrootdfs.cns = NULL;
xrootdfs.fastls = NULL;
xrootdfs.daemon_user = NULL;
xrootdfs.ofsfwd = false;
xrootdfs.ssskeytab = NULL;
xrootdfs.urlcachelife = strdup("3650d"); /* 10 years */
xrootdfs.nworkers = 4;
xrootdfs.maxfd = 8192;
/* Get options from environment variables first */
xrootdfs.rdr = getenv("XROOTDFS_RDRURL");
xrootdfs.cns = getenv("XROOTDFS_CNSURL");
xrootdfs.fastls = getenv("XROOTDFS_FASTLS");
// If this is defined, XrootdFS will setuid/setgid to this user at xrootdfs_init().
xrootdfs.daemon_user = getenv("XROOTDFS_USER");
if (getenv("XROOTDFS_OFSFWD") != NULL && ! strcmp(getenv("XROOTDFS_OFSFWD"),"1")) xrootdfs.ofsfwd = true;
if (getenv("XROOTDFS_NWORKERS") != NULL) sscanf(getenv("XROOTDFS_NWORKERS"), "%d", &xrootdfs.nworkers);
if (getenv("XROOTDFS_MAXFD") != NULL) sscanf(getenv("XROOTDFS_MAXFD"), "%d", &xrootdfs.maxfd);
/* Parse XrootdFS options, will overwrite those defined in environment variables */
fuse_opt_parse(&args, &xrootdfs, xrootdfs_opts, xrootdfs_opt_proc);
/* make sure xrootdfs.rdr is specified */
if (xrootdfs.rdr == NULL)
{
argc = 2;
argv[1] = strdup("-h");
struct fuse_args xargs = FUSE_ARGS_INIT(argc, argv);
fuse_opt_parse(&xargs, &xrootdfs, xrootdfs_opts, xrootdfs_opt_proc);
}
/* convert xroot://... to root://... */
if (xrootdfs.rdr != NULL && xrootdfs.rdr[0] == 'x') xrootdfs.rdr += 1;
if (xrootdfs.cns != NULL && xrootdfs.cns[0] == 'x') xrootdfs.cns += 1;
/*
XROOTDFS_OFSFWD (ofs.fwd (and ofs.fwd 3way) on rm, rmdir, mv, truncate.
if this is not defined, XrootdFS will go to CNS and each data server
and do the work.
If CNS is not defined, we have to set ofsfwd to false, or we will not be able to
get a return status of rm, rmdir, mv and truncate.
*/
if (xrootdfs.cns == NULL) xrootdfs.ofsfwd = false;
if (xrootdfs.ssskeytab != NULL)
{
setenv("XROOTDFS_SECMOD", "sss", 1);
setenv("XrdSecsssKT", xrootdfs.ssskeytab, 1);
}
if (xrootdfs.maxfd < 2048) xrootdfs.maxfd = 2048;
signal(SIGUSR1,xrootdfs_sigusr1_handler);
cwdfd = open(".",O_RDONLY);
umask(0);
return fuse_main(args.argc, args.argv, &xrootdfs_oper, NULL);
}
ts
static std::string ts()
timestamp output for logging messages
Definition XrdCephOss.cc:53
O_DIRECT
#define O_DIRECT
Definition XrdCrc32c.cc:51
XrdFfsFsinfo_cache_search
int XrdFfsFsinfo_cache_search(int(*func)(const char *, const char *, struct statvfs *, uid_t), const char *rdrurl, const char *path, struct statvfs *stbuf, uid_t user_uid)
Definition XrdFfsFsinfo.cc:57
XrdFfsFsinfo.hh
XrdFfsMisc_logging_url_cache
void XrdFfsMisc_logging_url_cache(const char *url)
Definition XrdFfsMisc.cc:273
XrdFfsMisc_xrd_init
void XrdFfsMisc_xrd_init(const char *rdrurl, const char *urlcachelife, int startQueue)
Definition XrdFfsMisc.cc:296
XrdFfsMisc_get_list_of_data_servers
int XrdFfsMisc_get_list_of_data_servers(char *list)
Definition XrdFfsMisc.cc:209
XrdFfsMisc_xrd_secsss_register
void XrdFfsMisc_xrd_secsss_register(uid_t user_uid, gid_t user_gid, int *id)
Definition XrdFfsMisc.cc:380
XrdFfsMisc_xrd_secsss_editurl
void XrdFfsMisc_xrd_secsss_editurl(char *url, uid_t user_uid, int *id)
Definition XrdFfsMisc.cc:424
MAXROOTURLLEN
#define MAXROOTURLLEN
Definition XrdFfsMisc.cc:62
XrdFfsMisc_refresh_url_cache
void XrdFfsMisc_refresh_url_cache(const char *url)
Definition XrdFfsMisc.cc:249
XrdFfsMisc.hh
XrdFfs_MAX_NUM_NODES
#define XrdFfs_MAX_NUM_NODES
Definition XrdFfsMisc.hh:34
XrdFfsPosix_ftruncate
int XrdFfsPosix_ftruncate(int fildes, off_t offset)
Definition XrdFfsPosix.cc:172
XrdFfsPosix_rmdirall
int XrdFfsPosix_rmdirall(const char *rdrurl, const char *path, uid_t user_uid)
Definition XrdFfsPosix.cc:334
XrdFfsPosix_rename
int XrdFfsPosix_rename(const char *oldpath, const char *newpath)
Definition XrdFfsPosix.cc:167
XrdFfsPosix_opendir
DIR * XrdFfsPosix_opendir(const char *path)
Definition XrdFfsPosix.cc:82
XrdFfsPosix_open
int XrdFfsPosix_open(const char *path, int oflags, mode_t mode)
Definition XrdFfsPosix.cc:122
XrdFfsPosix_fsync
int XrdFfsPosix_fsync(int fildes)
Definition XrdFfsPosix.cc:157
XrdFfsPosix_unlink
int XrdFfsPosix_unlink(const char *path)
Definition XrdFfsPosix.cc:162
XrdFfsPosix_readdir
struct dirent * XrdFfsPosix_readdir(DIR *dirp)
Definition XrdFfsPosix.cc:87
XrdFfsPosix_renameall
int XrdFfsPosix_renameall(const char *rdrurl, const char *from, const char *to, uid_t user_uid)
Definition XrdFfsPosix.cc:339
XrdFfsPosix_clear_from_rdr_cache
void XrdFfsPosix_clear_from_rdr_cache(const char *rdrurl)
Definition XrdFfsPosix.cc:235
XrdFfsPosix_truncate
int XrdFfsPosix_truncate(const char *path, off_t Size)
Definition XrdFfsPosix.cc:176
XrdFfsPosix_truncateall
int XrdFfsPosix_truncateall(const char *rdrurl, const char *path, off_t size, uid_t user_uid)
Definition XrdFfsPosix.cc:390
XrdFfsPosix_closedir
int XrdFfsPosix_closedir(DIR *dirp)
Definition XrdFfsPosix.cc:92
XrdFfsPosix_rmdir
int XrdFfsPosix_rmdir(const char *path)
Definition XrdFfsPosix.cc:117
XrdFfsPosix_lseek
off_t XrdFfsPosix_lseek(int fildes, off_t offset, int whence)
Definition XrdFfsPosix.cc:132
XrdFfsPosix_close
int XrdFfsPosix_close(int fildes)
Definition XrdFfsPosix.cc:127
XrdFfsPosix_pread
ssize_t XrdFfsPosix_pread(int fildes, void *buf, size_t nbyte, off_t offset)
Definition XrdFfsPosix.cc:142
XrdFfsPosix_statvfsall
int XrdFfsPosix_statvfsall(const char *rdrurl, const char *path, struct statvfs *stbuf, uid_t user_uid)
Definition XrdFfsPosix.cc:677
XrdFfsPosix_readdirall
int XrdFfsPosix_readdirall(const char *rdrurl, const char *path, char ***direntarray, uid_t user_uid)
Definition XrdFfsPosix.cc:474
XrdFfsPosix_statall
int XrdFfsPosix_statall(const char *rdrurl, const char *path, struct stat *stbuf, uid_t user_uid)
Definition XrdFfsPosix.cc:759
XrdFfsPosix_unlinkall
int XrdFfsPosix_unlinkall(const char *rdrurl, const char *path, uid_t user_uid)
Definition XrdFfsPosix.cc:329
XrdFfsPosix_stat
int XrdFfsPosix_stat(const char *path, struct stat *buf)
Definition XrdFfsPosix.cc:66
XrdFfsPosix_mkdir
int XrdFfsPosix_mkdir(const char *path, mode_t mode)
Definition XrdFfsPosix.cc:97
XrdFfsPosix_getxattr
long long XrdFfsPosix_getxattr(const char *path, const char *name, void *value, unsigned long long size)
Definition XrdFfsPosix.cc:181
XrdFfsPosix_write
ssize_t XrdFfsPosix_write(int fildes, const void *buf, size_t nbyte)
Definition XrdFfsPosix.cc:147
XrdFfsPosix.hh
XrdFfsQueue_remove_workers
int XrdFfsQueue_remove_workers(int n)
Definition XrdFfsQueue.cc:229
XrdFfsQueue_count_workers
int XrdFfsQueue_count_workers()
Definition XrdFfsQueue.cc:254
XrdFfsQueue_create_workers
int XrdFfsQueue_create_workers(int n)
Definition XrdFfsQueue.cc:192
XrdFfsQueue.hh
XrdFfsWcache_init
void XrdFfsWcache_init(int basefd, int maxfd)
Definition XrdFfsWcache.cc:85
XrdFfsWcache_destroy
void XrdFfsWcache_destroy(int fd)
Definition XrdFfsWcache.cc:168
XrdFfsWcache_pwrite
ssize_t XrdFfsWcache_pwrite(int fd, char *buf, size_t len, off_t offset)
Definition XrdFfsWcache.cc:296
XrdFfsWcache_pread
ssize_t XrdFfsWcache_pread(int fd, char *buf, size_t len, off_t offset)
Definition XrdFfsWcache.cc:228
XrdFfsWcache_flush
ssize_t XrdFfsWcache_flush(int fd)
Definition XrdFfsWcache.cc:186
XrdFfsWcache_create
int XrdFfsWcache_create(int fd, int flags)
Definition XrdFfsWcache.cc:126
XrdFfsWcache.hh
xrootdfs_opt_proc
static int xrootdfs_opt_proc(void *data, const char *arg, int key, struct fuse_args *outargs)
Definition XrdFfsXrootdfs.cc:1289
xrootdfs_mknod
static int xrootdfs_mknod(const char *path, mode_t mode, dev_t rdev)
Definition XrdFfsXrootdfs.cc:403
xrootdfs_ftruncate
static int xrootdfs_ftruncate(const char *path, off_t size, struct fuse_file_info *fi)
Definition XrdFfsXrootdfs.cc:699
xrootdfs_release
static int xrootdfs_release(const char *path, struct fuse_file_info *fi)
Definition XrdFfsXrootdfs.cc:931
main
int main(int argc, char *argv[])
Definition XrdFfsXrootdfs.cc:1314
xrootdfs_link
static int xrootdfs_link(const char *from, const char *to)
Definition XrdFfsXrootdfs.cc:662
xrootdfs_getxattr
static int xrootdfs_getxattr(const char *path, const char *name, char *value, size_t size)
Definition XrdFfsXrootdfs.cc:1071
XROOTDFS::fastls
char * fastls
Definition XrdFfsXrootdfs.cc:75
xrootdfs_opts
static struct fuse_opt xrootdfs_opts[14]
Definition XrdFfsXrootdfs.cc:87
xrootdfs_fsync
static int xrootdfs_fsync(const char *path, int isdatasync, struct fuse_file_info *fi)
Definition XrdFfsXrootdfs.cc:1026
xrootdfs_symlink
static int xrootdfs_symlink(const char *from, const char *to)
Definition XrdFfsXrootdfs.cc:593
XrdFfsMisc_logging_url_cache_pthread_create_cast
void * XrdFfsMisc_logging_url_cache_pthread_create_cast(void *arg)
Definition XrdFfsXrootdfs.cc:1234
xrootdfs_usage
static void xrootdfs_usage(const char *progname)
Definition XrdFfsXrootdfs.cc:1262
cwdfd
int cwdfd
Definition XrdFfsXrootdfs.cc:84
usingEC
bool usingEC
Definition XrdFfsXrootdfs.cc:91
xrootdfs_rmdir
static int xrootdfs_rmdir(const char *path)
Definition XrdFfsXrootdfs.cc:545
xrootdfs_sigusr1_handler
void xrootdfs_sigusr1_handler(int sig)
Definition XrdFfsXrootdfs.cc:1240
xrootdfs_open
static int xrootdfs_open(const char *path, struct fuse_file_info *fi)
Definition XrdFfsXrootdfs.cc:782
xrootdfs_access
static int xrootdfs_access(const char *path, int mask)
Definition XrdFfsXrootdfs.cc:283
xrootdfs_utimens
static int xrootdfs_utimens(const char *path, const struct timespec ts[2])
Definition XrdFfsXrootdfs.cc:764
xrootdfs
struct XROOTDFS xrootdfs
Definition XrdFfsXrootdfs.cc:86
xrootdfs_create
static int xrootdfs_create(const char *path, mode_t mode, struct fuse_file_info *fi)
Definition XrdFfsXrootdfs.cc:443
xrootdfs_setxattr
static int xrootdfs_setxattr(const char *path, const char *name, const char *value, size_t size, int flags)
Definition XrdFfsXrootdfs.cc:1038
XROOTDFS::urlcachelife
char * urlcachelife
Definition XrdFfsXrootdfs.cc:78
xrootdfs_read
static int xrootdfs_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi)
Definition XrdFfsXrootdfs.cc:809
XROOTDFS::ssskeytab
char * ssskeytab
Definition XrdFfsXrootdfs.cc:77
XROOTDFS::ofsfwd
bool ofsfwd
Definition XrdFfsXrootdfs.cc:79
xrootdfs_removexattr
static int xrootdfs_removexattr(const char *path, const char *name)
Definition XrdFfsXrootdfs.cc:1213
xrootdfs_readlink
static int xrootdfs_readlink(const char *path, char *buf, size_t size)
Definition XrdFfsXrootdfs.cc:294
xrootdfs_truncate
static int xrootdfs_truncate(const char *path, off_t size)
Definition XrdFfsXrootdfs.cc:729
xrootdfs_write
static int xrootdfs_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi)
Definition XrdFfsXrootdfs.cc:845
XROOTDFS::nworkers
int nworkers
Definition XrdFfsXrootdfs.cc:80
xrootdfs_oper
static struct fuse_operations xrootdfs_oper
Definition XrdFfsXrootdfs.cc:1260
XROOTDFS::cns
char * cns
Definition XrdFfsXrootdfs.cc:74
xrootdfs_rename
static int xrootdfs_rename(const char *from, const char *to)
Definition XrdFfsXrootdfs.cc:605
xrootdfs_listxattr
static int xrootdfs_listxattr(const char *path, char *list, size_t size)
Definition XrdFfsXrootdfs.cc:1202
xrootdfs_init
static void * xrootdfs_init(struct fuse_conn_info *conn)
Definition XrdFfsXrootdfs.cc:93
xrootdfs_mkdir
static int xrootdfs_mkdir(const char *path, mode_t mode)
Definition XrdFfsXrootdfs.cc:472
xrootdfs_chown
static int xrootdfs_chown(const char *path, uid_t uid, gid_t gid)
Definition XrdFfsXrootdfs.cc:686
xrootdfs_readdir
static int xrootdfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi)
Definition XrdFfsXrootdfs.cc:308
XROOTDFS::daemon_user
char * daemon_user
Definition XrdFfsXrootdfs.cc:76
xrootdfs_do_create
static int xrootdfs_do_create(const char *path, const char *url, int oflags, bool use_link_id, int *fd)
Definition XrdFfsXrootdfs.cc:371
xrootdfs_getattr
static int xrootdfs_getattr(const char *path, struct stat *stbuf)
Definition XrdFfsXrootdfs.cc:166
xrootdfs_unlink
static int xrootdfs_unlink(const char *path)
Definition XrdFfsXrootdfs.cc:510
xrootdfs_statfs
static int xrootdfs_statfs(const char *path, struct statvfs *stbuf)
Definition XrdFfsXrootdfs.cc:864
XROOTDFS::rdr
char * rdr
Definition XrdFfsXrootdfs.cc:73
xrootdfs_chmod
static int xrootdfs_chmod(const char *path, mode_t mode)
Definition XrdFfsXrootdfs.cc:674
OPT_KEY_HELP
@ OPT_KEY_HELP
Definition XrdFfsXrootdfs.cc:89
OPT_KEY_SECSSS
@ OPT_KEY_SECSSS
Definition XrdFfsXrootdfs.cc:89
XROOTDFS::maxfd
int maxfd
Definition XrdFfsXrootdfs.cc:81
XROOTDFS
Definition XrdFfsXrootdfs.cc:72
XrdPosixXrootd.hh
close
#define close(a)
Definition XrdPosix.hh:48
open
#define open
Definition XrdPosix.hh:76
statvfs
#define statvfs(a, b)
Definition XrdPosix.hh:105
stat
#define stat(a, b)
Definition XrdPosix.hh:101
XrdPosixXrootd
POSIX interface to XRootD with some extensions, as noted.
Definition XrdPosixXrootd.hh:64
XrdPosixXrootd::Fstat
static int Fstat(int fildes, struct stat *buf)
Fstat() conforms to POSIX.1-2001 fstat().
Definition XrdPosixXrootd.cc:369
XrdPosixXrootd::fdOrigin
int fdOrigin()
Definition XrdPosixXrootd.hh:371