From 8bfab80415ee47886d5505eb68d1e22f95447bce Mon Sep 17 00:00:00 2001 From: sageweil Date: Sun, 19 Aug 2007 18:45:46 +0000 Subject: [PATCH] fusetrace! git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@1644 29311d96-e01e-0410-9327-a35deaab8ce9 --- trunk/fusetrace/fusetrace.cc | 601 +++++++++++++++++++++++++++++++ trunk/fusetrace/fusetrace_ll.cc | 606 ++++++++++++++++++++++++++++++++ 2 files changed, 1207 insertions(+) create mode 100644 trunk/fusetrace/fusetrace.cc create mode 100644 trunk/fusetrace/fusetrace_ll.cc diff --git a/trunk/fusetrace/fusetrace.cc b/trunk/fusetrace/fusetrace.cc new file mode 100644 index 0000000000000..f8b500c9f1209 --- /dev/null +++ b/trunk/fusetrace/fusetrace.cc @@ -0,0 +1,601 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:4; indent-tabs-mode:t -*- +// vim: ts=8 sw=4 smarttab + +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU GPL. + See the file COPYING. + + gcc -Wall `pkg-config fuse --cflags --libs` -lulockmgr fusexmp_fh.c -o fusexmp_fh +*/ + +#define FUSE_USE_VERSION 26 + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SETXATTR +#include +#endif + + +#include +using namespace __gnu_cxx; + +#include +#include +using namespace std; + +#include "../ceph/common/Mutex.h" + +Mutex trace_lock; +fstream traceout; + +const char *basedir = 0; + + +static int ft_getattr(const char *path, struct stat *stbuf) +{ + int res; + + trace_lock.Lock(); + traceout << "getattr" << endl << path << endl; + trace_lock.Unlock(); + + res = lstat(path, stbuf); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_fgetattr(const char *path, struct stat *stbuf, + struct fuse_file_info *fi) +{ + int res; + + (void) path; + + trace_lock.Lock(); + traceout << "fgetattr" << endl << fi->fh << endl; + trace_lock.Unlock(); + + res = fstat(fi->fh, stbuf); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_access(const char *path, int mask) +{ + int res; + + trace_lock.Lock(); + traceout << "access" << endl << path << endl; + trace_lock.Unlock(); + + res = access(path, mask); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_readlink(const char *path, char *buf, size_t size) +{ + int res; + + trace_lock.Lock(); + traceout << "readlink" << endl << path << endl; + trace_lock.Unlock(); + + res = readlink(path, buf, size - 1); + if (res == -1) + return -errno; + + buf[res] = '\0'; + return 0; +} + +static int ft_opendir(const char *path, struct fuse_file_info *fi) +{ + DIR *dp = opendir(path); + if (dp == NULL) + return -errno; + + fi->fh = (unsigned long) dp; + + trace_lock.Lock(); + traceout << "opendir" << endl << path << endl << fi->fh << endl; + trace_lock.Unlock(); + + return 0; +} + +static inline DIR *get_dirp(struct fuse_file_info *fi) +{ + return (DIR *) (uintptr_t) fi->fh; +} + +static int ft_readdir(const char *path, void *buf, fuse_fill_dir_t filler, + off_t offset, struct fuse_file_info *fi) +{ + DIR *dp = get_dirp(fi); + struct dirent *de; + + (void) path; + seekdir(dp, offset); + while ((de = 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, &st, telldir(dp))) + break; + } + + trace_lock.Lock(); + traceout << "readdir" << endl << fi->fh << endl; + trace_lock.Unlock(); + + return 0; +} + +static int ft_releasedir(const char *path, struct fuse_file_info *fi) +{ + DIR *dp = get_dirp(fi); + (void) path; + closedir(dp); + + trace_lock.Lock(); + traceout << "releasedir" << endl << fi->fh << endl; + trace_lock.Unlock(); + + return 0; +} + +static int ft_mknod(const char *path, mode_t mode, dev_t rdev) +{ + int res; + + trace_lock.Lock(); + traceout << "mknod" << endl << path << endl << mode << endl << rdev << endl; + trace_lock.Unlock(); + + if (S_ISFIFO(mode)) + res = mkfifo(path, mode); + else + res = mknod(path, mode, rdev); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_mkdir(const char *path, mode_t mode) +{ + int res; + + trace_lock.Lock(); + traceout << "mkdir" << endl << path << endl << mode << endl; + trace_lock.Unlock(); + + res = mkdir(path, mode); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_unlink(const char *path) +{ + int res; + + trace_lock.Lock(); + traceout << "unlink" << endl << path << endl; + trace_lock.Unlock(); + + res = unlink(path); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_rmdir(const char *path) +{ + int res; + + trace_lock.Lock(); + traceout << "rmdir" << endl << path << endl; + trace_lock.Unlock(); + + res = rmdir(path); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_symlink(const char *from, const char *to) +{ + int res; + + trace_lock.Lock(); + traceout << "symlink" << endl << from << endl << to << endl; + trace_lock.Unlock(); + + res = symlink(from, to); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_rename(const char *from, const char *to) +{ + int res; + + trace_lock.Lock(); + traceout << "rename" << endl << from << endl << to << endl; + trace_lock.Unlock(); + + res = rename(from, to); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_link(const char *from, const char *to) +{ + int res; + + trace_lock.Lock(); + traceout << "link" << endl << from << endl << to << endl; + trace_lock.Unlock(); + + res = link(from, to); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_chmod(const char *path, mode_t mode) +{ + int res; + + trace_lock.Lock(); + traceout << "chmod" << endl << path << endl << mode << endl; + trace_lock.Unlock(); + + res = chmod(path, mode); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_chown(const char *path, uid_t uid, gid_t gid) +{ + int res; + + trace_lock.Lock(); + traceout << "chown" << endl << path << endl << uid << endl << gid << endl; + trace_lock.Unlock(); + + res = lchown(path, uid, gid); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_truncate(const char *path, off_t size) +{ + int res; + + trace_lock.Lock(); + traceout << "truncate" << endl << path << endl << size << endl; + trace_lock.Unlock(); + + res = truncate(path, size); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_ftruncate(const char *path, off_t size, + struct fuse_file_info *fi) +{ + int res; + + (void) path; + + trace_lock.Lock(); + traceout << "ftruncate" << endl << fi->fh << endl << size << endl; + trace_lock.Unlock(); + + res = ftruncate(fi->fh, size); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_utimens(const char *path, const struct timespec ts[2]) +{ + int res; + struct timeval tv[2]; + + trace_lock.Lock(); + traceout << "utimens" << endl << path + << tv[0].tv_sec << endl << tv[0].tv_nsec << endl + << tv[1].tv_sec << endl << tv[1].tv_nsec << endl; + trace_lock.Unlock(); + + 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 ft_create(const char *path, mode_t mode, struct fuse_file_info *fi) +{ + int fd; + + trace_lock.Lock(); + traceout << "create" << endl << path << endl << mode << endl << fi->flags << endl; + trace_lock.Unlock(); + + fd = open(path, fi->flags, mode); + if (fd == -1) + return -errno; + + fi->fh = fd; + return 0; +} + +static int ft_open(const char *path, struct fuse_file_info *fi) +{ + int fd; + + fd = open(path, fi->flags); + + trace_lock.Lock(); + traceout << "open" << endl << path << endl << fi->flags << endl << (fd > 0 ? fd:0) << endl; + trace_lock.Unlock(); + + if (fd == -1) + return -errno; + + fi->fh = fd; + return 0; +} + +static int ft_read(const char *path, char *buf, size_t size, off_t offset, + struct fuse_file_info *fi) +{ + int res; + + trace_lock.Lock(); + traceout << "read" << endl << fi->fh << endl << offset << endl << size << endl; + trace_lock.Unlock(); + + (void) path; + res = pread(fi->fh, buf, size, offset); + if (res == -1) + res = -errno; + + return res; +} + +static int ft_write(const char *path, const char *buf, size_t size, + off_t offset, struct fuse_file_info *fi) +{ + int res; + + trace_lock.Lock(); + traceout << "write" << endl << fi->fh << endl << offset << endl << size << endl; + trace_lock.Unlock(); + + (void) path; + res = pwrite(fi->fh, buf, size, offset); + if (res == -1) + res = -errno; + + return res; +} + +static int ft_statfs(const char *path, struct statvfs *stbuf) +{ + int res; + + trace_lock.Lock(); + traceout << "statfs" << endl << path << endl; + trace_lock.Unlock(); + + res = statvfs(path, stbuf); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_flush(const char *path, struct fuse_file_info *fi) +{ + int res; + + trace_lock.Lock(); + traceout << "flush" << endl << fi->fh << endl; + trace_lock.Unlock(); + + (void) path; + /* This is called from every close on an open file, so call the + close on the underlying filesystem. But since flush may be + called multiple times for an open file, this must not really + close the file. This is important if used on a network + filesystem like NFS which flush the data/metadata on close() */ + res = close(dup(fi->fh)); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_release(const char *path, struct fuse_file_info *fi) +{ + (void) path; + close(fi->fh); + + trace_lock.Lock(); + traceout << "release" << endl << fi->fh << endl; + trace_lock.Unlock(); + + return 0; +} + +static int ft_fsync(const char *path, int isdatasync, + struct fuse_file_info *fi) +{ + int res; + (void) path; + +#ifndef HAVE_FDATASYNC + (void) isdatasync; +#else + if (isdatasync) + res = fdatasync(fi->fh); + else +#endif + res = fsync(fi->fh); + + trace_lock.Lock(); + traceout << "fsync" << endl << fi->fh << endl << isdatasync << endl; + trace_lock.Unlock(); + + if (res == -1) + return -errno; + + return 0; +} + +#ifdef HAVE_SETXATTR +/* xattr operations are optional and can safely be left unimplemented */ +static int ft_setxattr(const char *path, const char *name, const char *value, + size_t size, int flags) +{ + int res = lsetxattr(path, name, value, size, flags); + if (res == -1) + return -errno; + return 0; +} + +static int ft_getxattr(const char *path, const char *name, char *value, + size_t size) +{ + int res = lgetxattr(path, name, value, size); + if (res == -1) + return -errno; + return res; +} + +static int ft_listxattr(const char *path, char *list, size_t size) +{ + int res = llistxattr(path, list, size); + if (res == -1) + return -errno; + return res; +} + +static int ft_removexattr(const char *path, const char *name) +{ + int res = lremovexattr(path, name); + if (res == -1) + return -errno; + return 0; +} +#endif /* HAVE_SETXATTR */ + +static int ft_lock(const char *path, struct fuse_file_info *fi, int cmd, + struct flock *lock) +{ + (void) path; + + /* + trace_lock.Lock(); + traceout << "fsync" << endl << fi->fh << endl << isdatasync << endl; + trace_lock.Unlock(); + */ + return ulockmgr_op(fi->fh, cmd, lock, &fi->lock_owner, + sizeof(fi->lock_owner)); +} + +static struct fuse_operations ft_oper = { + .getattr = ft_getattr, + .fgetattr = ft_fgetattr, + //.access = ft_access, + .readlink = ft_readlink, + .opendir = ft_opendir, + .readdir = ft_readdir, + .releasedir = ft_releasedir, + .mknod = ft_mknod, + .mkdir = ft_mkdir, + .symlink = ft_symlink, + .unlink = ft_unlink, + .rmdir = ft_rmdir, + .rename = ft_rename, + .link = ft_link, + .chmod = ft_chmod, + .chown = ft_chown, + .truncate = ft_truncate, + .ftruncate = ft_ftruncate, + .utimens = ft_utimens, + .create = ft_create, + .open = ft_open, + .read = ft_read, + .write = ft_write, + .statfs = ft_statfs, + .flush = ft_flush, + .release = ft_release, + .fsync = ft_fsync, +#ifdef HAVE_SETXATTR + .setxattr = ft_setxattr, + .getxattr = ft_getxattr, + .listxattr = ft_listxattr, + .removexattr= ft_removexattr, +#endif + .lock = ft_lock, +}; + +int main(int argc, char *argv[]) +{ + // open trace + + + umask(0); + return fuse_main(argc, argv, &ft_oper, NULL); +} diff --git a/trunk/fusetrace/fusetrace_ll.cc b/trunk/fusetrace/fusetrace_ll.cc new file mode 100644 index 0000000000000..053de9d36f1e8 --- /dev/null +++ b/trunk/fusetrace/fusetrace_ll.cc @@ -0,0 +1,606 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:4; indent-tabs-mode:t -*- +// vim: ts=8 sw=4 smarttab + +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU GPL. + See the file COPYING. + + gcc -Wall `pkg-config fuse --cflags --libs` -lulockmgr fusexmp_fh.c -o fusexmp_fh +*/ + +#define FUSE_USE_VERSION 26 + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SETXATTR +#include +#endif + + +#include +using namespace __gnu_cxx; + +#include +#include +using namespace std; + +#include "../ceph/common/Mutex.h" + +Mutex trace_lock; +fstream traceout; + +const char *basedir = 0; + + +hash_map inode_map; + + + + +static int ft_getattr(const char *path, struct stat *stbuf) +{ + int res; + + trace_lock.Lock(); + traceout << "getattr" << endl << path << endl; + trace_lock.Unlock(); + + res = lstat(path, stbuf); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_fgetattr(const char *path, struct stat *stbuf, + struct fuse_file_info *fi) +{ + int res; + + (void) path; + + trace_lock.Lock(); + traceout << "fgetattr" << endl << fi->fh << endl; + trace_lock.Unlock(); + + res = fstat(fi->fh, stbuf); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_access(const char *path, int mask) +{ + int res; + + trace_lock.Lock(); + traceout << "access" << endl << path << endl; + trace_lock.Unlock(); + + res = access(path, mask); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_readlink(const char *path, char *buf, size_t size) +{ + int res; + + trace_lock.Lock(); + traceout << "readlink" << endl << path << endl; + trace_lock.Unlock(); + + res = readlink(path, buf, size - 1); + if (res == -1) + return -errno; + + buf[res] = '\0'; + return 0; +} + +static int ft_opendir(const char *path, struct fuse_file_info *fi) +{ + DIR *dp = opendir(path); + if (dp == NULL) + return -errno; + + fi->fh = (unsigned long) dp; + + trace_lock.Lock(); + traceout << "opendir" << endl << path << endl << fi->fh << endl; + trace_lock.Unlock(); + + return 0; +} + +static inline DIR *get_dirp(struct fuse_file_info *fi) +{ + return (DIR *) (uintptr_t) fi->fh; +} + +static int ft_readdir(const char *path, void *buf, fuse_fill_dir_t filler, + off_t offset, struct fuse_file_info *fi) +{ + DIR *dp = get_dirp(fi); + struct dirent *de; + + (void) path; + seekdir(dp, offset); + while ((de = 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, &st, telldir(dp))) + break; + } + + trace_lock.Lock(); + traceout << "readdir" << endl << fi->fh << endl; + trace_lock.Unlock(); + + return 0; +} + +static int ft_releasedir(const char *path, struct fuse_file_info *fi) +{ + DIR *dp = get_dirp(fi); + (void) path; + closedir(dp); + + trace_lock.Lock(); + traceout << "releasedir" << endl << fi->fh << endl; + trace_lock.Unlock(); + + return 0; +} + +static int ft_mknod(const char *path, mode_t mode, dev_t rdev) +{ + int res; + + trace_lock.Lock(); + traceout << "mknod" << endl << path << endl << mode << endl << rdev << endl; + trace_lock.Unlock(); + + if (S_ISFIFO(mode)) + res = mkfifo(path, mode); + else + res = mknod(path, mode, rdev); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_mkdir(const char *path, mode_t mode) +{ + int res; + + trace_lock.Lock(); + traceout << "mkdir" << endl << path << endl << mode << endl; + trace_lock.Unlock(); + + res = mkdir(path, mode); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_unlink(const char *path) +{ + int res; + + trace_lock.Lock(); + traceout << "unlink" << endl << path << endl; + trace_lock.Unlock(); + + res = unlink(path); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_rmdir(const char *path) +{ + int res; + + trace_lock.Lock(); + traceout << "rmdir" << endl << path << endl; + trace_lock.Unlock(); + + res = rmdir(path); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_symlink(const char *from, const char *to) +{ + int res; + + trace_lock.Lock(); + traceout << "symlink" << endl << from << endl << to << endl; + trace_lock.Unlock(); + + res = symlink(from, to); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_rename(const char *from, const char *to) +{ + int res; + + trace_lock.Lock(); + traceout << "rename" << endl << from << endl << to << endl; + trace_lock.Unlock(); + + res = rename(from, to); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_link(const char *from, const char *to) +{ + int res; + + trace_lock.Lock(); + traceout << "link" << endl << from << endl << to << endl; + trace_lock.Unlock(); + + res = link(from, to); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_chmod(const char *path, mode_t mode) +{ + int res; + + trace_lock.Lock(); + traceout << "chmod" << endl << path << endl << mode << endl; + trace_lock.Unlock(); + + res = chmod(path, mode); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_chown(const char *path, uid_t uid, gid_t gid) +{ + int res; + + trace_lock.Lock(); + traceout << "chown" << endl << path << endl << uid << endl << gid << endl; + trace_lock.Unlock(); + + res = lchown(path, uid, gid); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_truncate(const char *path, off_t size) +{ + int res; + + trace_lock.Lock(); + traceout << "truncate" << endl << path << endl << size << endl; + trace_lock.Unlock(); + + res = truncate(path, size); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_ftruncate(const char *path, off_t size, + struct fuse_file_info *fi) +{ + int res; + + (void) path; + + trace_lock.Lock(); + traceout << "ftruncate" << endl << fi->fh << endl << size << endl; + trace_lock.Unlock(); + + res = ftruncate(fi->fh, size); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_utimens(const char *path, const struct timespec ts[2]) +{ + int res; + struct timeval tv[2]; + + trace_lock.Lock(); + traceout << "utimens" << endl << path + << tv[0].tv_sec << endl << tv[0].tv_nsec << endl + << tv[1].tv_sec << endl << tv[1].tv_nsec << endl; + trace_lock.Unlock(); + + 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 ft_create(const char *path, mode_t mode, struct fuse_file_info *fi) +{ + int fd; + + trace_lock.Lock(); + traceout << "create" << endl << path << endl << mode << endl << fi->flags << endl; + trace_lock.Unlock(); + + fd = open(path, fi->flags, mode); + if (fd == -1) + return -errno; + + fi->fh = fd; + return 0; +} + +static int ft_open(const char *path, struct fuse_file_info *fi) +{ + int fd; + + fd = open(path, fi->flags); + + trace_lock.Lock(); + traceout << "open" << endl << path << endl << fi->flags << endl << (fd > 0 ? fd:0) << endl; + trace_lock.Unlock(); + + if (fd == -1) + return -errno; + + fi->fh = fd; + return 0; +} + +static int ft_read(const char *path, char *buf, size_t size, off_t offset, + struct fuse_file_info *fi) +{ + int res; + + trace_lock.Lock(); + traceout << "read" << endl << fi->fh << endl << offset << endl << size << endl; + trace_lock.Unlock(); + + (void) path; + res = pread(fi->fh, buf, size, offset); + if (res == -1) + res = -errno; + + return res; +} + +static int ft_write(const char *path, const char *buf, size_t size, + off_t offset, struct fuse_file_info *fi) +{ + int res; + + trace_lock.Lock(); + traceout << "write" << endl << fi->fh << endl << offset << endl << size << endl; + trace_lock.Unlock(); + + (void) path; + res = pwrite(fi->fh, buf, size, offset); + if (res == -1) + res = -errno; + + return res; +} + +static int ft_statfs(const char *path, struct statvfs *stbuf) +{ + int res; + + trace_lock.Lock(); + traceout << "statfs" << endl << path << endl; + trace_lock.Unlock(); + + res = statvfs(path, stbuf); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_flush(const char *path, struct fuse_file_info *fi) +{ + int res; + + trace_lock.Lock(); + traceout << "flush" << endl << fi->fh << endl; + trace_lock.Unlock(); + + (void) path; + /* This is called from every close on an open file, so call the + close on the underlying filesystem. But since flush may be + called multiple times for an open file, this must not really + close the file. This is important if used on a network + filesystem like NFS which flush the data/metadata on close() */ + res = close(dup(fi->fh)); + if (res == -1) + return -errno; + + return 0; +} + +static int ft_release(const char *path, struct fuse_file_info *fi) +{ + (void) path; + close(fi->fh); + + trace_lock.Lock(); + traceout << "release" << endl << fi->fh << endl; + trace_lock.Unlock(); + + return 0; +} + +static int ft_fsync(const char *path, int isdatasync, + struct fuse_file_info *fi) +{ + int res; + (void) path; + +#ifndef HAVE_FDATASYNC + (void) isdatasync; +#else + if (isdatasync) + res = fdatasync(fi->fh); + else +#endif + res = fsync(fi->fh); + + trace_lock.Lock(); + traceout << "fsync" << endl << fi->fh << endl << isdatasync << endl; + trace_lock.Unlock(); + + if (res == -1) + return -errno; + + return 0; +} + +#ifdef HAVE_SETXATTR +/* xattr operations are optional and can safely be left unimplemented */ +static int ft_setxattr(const char *path, const char *name, const char *value, + size_t size, int flags) +{ + int res = lsetxattr(path, name, value, size, flags); + if (res == -1) + return -errno; + return 0; +} + +static int ft_getxattr(const char *path, const char *name, char *value, + size_t size) +{ + int res = lgetxattr(path, name, value, size); + if (res == -1) + return -errno; + return res; +} + +static int ft_listxattr(const char *path, char *list, size_t size) +{ + int res = llistxattr(path, list, size); + if (res == -1) + return -errno; + return res; +} + +static int ft_removexattr(const char *path, const char *name) +{ + int res = lremovexattr(path, name); + if (res == -1) + return -errno; + return 0; +} +#endif /* HAVE_SETXATTR */ + +static int ft_lock(const char *path, struct fuse_file_info *fi, int cmd, + struct flock *lock) +{ + (void) path; + + /* + trace_lock.Lock(); + traceout << "fsync" << endl << fi->fh << endl << isdatasync << endl; + trace_lock.Unlock(); + */ + return ulockmgr_op(fi->fh, cmd, lock, &fi->lock_owner, + sizeof(fi->lock_owner)); +} + +static struct fuse_operations ft_oper = { + .getattr = ft_getattr, + .fgetattr = ft_fgetattr, + //.access = ft_access, + .readlink = ft_readlink, + .opendir = ft_opendir, + .readdir = ft_readdir, + .releasedir = ft_releasedir, + .mknod = ft_mknod, + .mkdir = ft_mkdir, + .symlink = ft_symlink, + .unlink = ft_unlink, + .rmdir = ft_rmdir, + .rename = ft_rename, + .link = ft_link, + .chmod = ft_chmod, + .chown = ft_chown, + .truncate = ft_truncate, + .ftruncate = ft_ftruncate, + .utimens = ft_utimens, + .create = ft_create, + .open = ft_open, + .read = ft_read, + .write = ft_write, + .statfs = ft_statfs, + .flush = ft_flush, + .release = ft_release, + .fsync = ft_fsync, +#ifdef HAVE_SETXATTR + .setxattr = ft_setxattr, + .getxattr = ft_getxattr, + .listxattr = ft_listxattr, + .removexattr= ft_removexattr, +#endif + .lock = ft_lock, +}; + +int main(int argc, char *argv[]) +{ + // open trace + + + umask(0); + return fuse_main(argc, argv, &ft_oper, NULL); +} -- 2.39.5