checkpoint

This commit is contained in:
Antonio SJ Musumeci 2020-08-20 23:23:15 -04:00
parent a02f3a6856
commit 96095d1fce
3 changed files with 477 additions and 270 deletions

27
libfuse/lib/ansi.h Normal file
View File

@ -0,0 +1,27 @@
#pragma once
#define ANSI_RESET "\033[00m"
#define ANSI_BOLD "\033[1m"
#define ANSI_DARK "\033[2m"
#define ANSI_UNDERLINE "\033[4m"
#define ANSI_BLINK "\033[5m"
#define ANSI_REVERSE "\033[7m"
#define ANSI_CONCEALED "\033[8m"
#define ANSI_GRAY "\033[30m"
#define ANSI_GREY "\033[30m"
#define ANSI_RED "\033[31m"
#define ANSI_GREEN "\033[32m"
#define ANSI_YELLOW "\033[33m"
#define ANSI_BLUE "\033[34m"
#define ANSI_MAGENTA "\033[35m"
#define ANSI_CYAN "\033[36m"
#define ANSI_WHITE "\033[37m"
#define ANSI_BG_GRAY "\033[40m"
#define ANSI_BG_GREY "\033[40m"
#define ANSI_BG_RED "\033[41m"
#define ANSI_BG_GREEN "\033[42m"
#define ANSI_BG_YELLOW "\033[43m"
#define ANSI_BG_BLUE "\033[44m"
#define ANSI_BG_MAGENTA "\033[45m"
#define ANSI_BG_CYAN "\033[46m"
#define ANSI_BG_WHITE "\033[47m"

View File

@ -1549,20 +1549,17 @@ req_fuse(fuse_req_t req)
}
int
fuse_fs_getattr(struct fuse_fs *fs,
const char *path,
struct stat *buf,
fuse_timeouts_t *timeout)
fuse_fs_getattr(struct fuse_fs *fs_,
const char *path_,
struct stat *buf_,
fuse_timeouts_t *timeout_)
{
if(fs->op.getattr == NULL)
if(fs_->op.getattr == NULL)
return -ENOSYS;
if(fs->debug)
fprintf(stderr,"getattr %s\n",path);
fuse_get_context()->private_data = fs_->user_data;
fuse_get_context()->private_data = fs->user_data;
return fs->op.getattr(path,buf,timeout);
return fs_->op.getattr(path_,buf_,timeout_);
}
int
@ -2872,11 +2869,10 @@ fuse_lib_forget_multi(fuse_req_t req,
static
void
fuse_lib_getattr(fuse_req_t req,
fuse_ino_t ino,
fuse_file_info_t *fi)
fuse_lib_getattr(fuse_req_t req_,
fuse_ino_t ino_,
fuse_file_info_t *fi_)
{
int err;
char *path;
struct fuse *f;
@ -2885,15 +2881,15 @@ fuse_lib_getattr(fuse_req_t req,
fuse_timeouts_t timeout;
fuse_file_info_t ffi = {0};
f = req_fuse_prepare(req);
if(fi == NULL)
f = req_fuse_prepare(req_);
if(fi_ == NULL)
{
pthread_mutex_lock(&f->lock);
node = get_node(f,ino);
node = get_node(f,ino_);
if(node->is_hidden)
{
fi = &ffi;
fi->fh = node->hidden_fh;
fi_ = &ffi;
fi_->fh = node->hidden_fh;
}
pthread_mutex_unlock(&f->lock);
}
@ -2902,44 +2898,44 @@ fuse_lib_getattr(fuse_req_t req,
err = 0;
path = NULL;
if((fi == NULL) || (f->fs->op.fgetattr == NULL))
err = get_path(f,ino,&path);
if((fi_ == NULL) || (f->fs->op.fgetattr == NULL))
err = get_path(f,ino_,&path);
if(!err)
{
err = ((fi == NULL) ?
err = ((fi_ == NULL) ?
fuse_fs_getattr(f->fs,path,&buf,&timeout) :
fuse_fs_fgetattr(f->fs,&buf,fi,&timeout));
fuse_fs_fgetattr(f->fs,&buf,fi_,&timeout));
free_path(f,ino,path);
free_path(f,ino_,path);
}
if(!err)
{
pthread_mutex_lock(&f->lock);
node = get_node(f,ino);
node = get_node(f,ino_);
update_stat(node,&buf);
pthread_mutex_unlock(&f->lock);
set_stat(f,ino,&buf);
fuse_reply_attr(req,&buf,timeout.attr);
set_stat(f,ino_,&buf);
fuse_reply_attr(req_,&buf,timeout.attr);
}
else
{
reply_err(req,err);
reply_err(req_,err);
}
}
int
fuse_fs_chmod(struct fuse_fs *fs,
const char *path,
mode_t mode)
fuse_fs_chmod(struct fuse_fs *fs_,
const char *path_,
mode_t mode_)
{
if(fs->op.chmod == NULL)
if(fs_->op.chmod == NULL)
return -ENOSYS;
fuse_get_context()->private_data = fs->user_data;
fuse_get_context()->private_data = fs_->user_data;
return fs->op.chmod(path,mode);
return fs_->op.chmod(path_,mode_);
}
int
@ -2963,7 +2959,7 @@ fuse_lib_setattr(fuse_req_t req,
int valid,
fuse_file_info_t *fi)
{
struct fuse *f = req_fuse_prepare(req);
struct fuse *f;
struct stat buf;
char *path;
int err;
@ -2971,6 +2967,7 @@ fuse_lib_setattr(fuse_req_t req,
fuse_timeouts_t timeout;
fuse_file_info_t ffi = {0};
f = req_fuse_prepare(req);
if(fi == NULL)
{
pthread_mutex_lock(&f->lock);

View File

@ -8,6 +8,7 @@
#define _GNU_SOURCE
#include "ansi.h"
#include "config.h"
#include "fuse_i.h"
#include "fuse_kernel.h"
@ -199,18 +200,15 @@ fuse_send_msg(struct fuse_ll *f,
fprintf(stderr, "NOTIFY: code=%d length=%u\n",
out->error, out->len);
}
else if (out->error)
{
fprintf(stderr,
" unique: %llu, error: %i (%s), outsize: %i\n",
(unsigned long long) out->unique, out->error,
strerror(-out->error), out->len);
}
else
{
fprintf(stderr,
" unique: %llu, success, outsize: %i\n",
(unsigned long long) out->unique, out->len);
ANSI_RED"response:"ANSI_RESET
" unique: %zu; error: %d (%s); len: %d;\n",
out->unique,
out->error,
strerror(-out->error),
out->len);
}
}
@ -225,7 +223,7 @@ fuse_send_reply_iov_nofree(fuse_req_t req,
{
struct fuse_out_header out;
if (error <= -1000 || error > 0)
if((error <= -1000) || (error > 0))
{
fprintf(stderr,"fuse: bad error value: %i\n",error);
error = -ERANGE;
@ -410,6 +408,13 @@ fill_open(struct fuse_open_out *arg,
arg->open_flags |= FOPEN_CACHE_DIR;
}
static
void
debug_fuse_entry_out(const struct fuse_entry_out *arg_)
{
}
int
fuse_reply_entry(fuse_req_t req,
const struct fuse_entry_param *e)
@ -426,6 +431,9 @@ fuse_reply_entry(fuse_req_t req,
memset(&arg, 0, sizeof(arg));
fill_entry(&arg, e);
if(req->f->debug)
debug_fuse_entry_out(&arg);
return send_reply_ok(req, &arg, size);
}
@ -447,6 +455,49 @@ fuse_reply_create(fuse_req_t req,
return send_reply_ok(req, buf, entrysize + sizeof(struct fuse_open_out));
}
static
void
debug_fuse_attr_out(const struct fuse_attr_out *arg_)
{
fprintf(stderr,
ANSI_YELLOW"fuse_attr_out:"ANSI_RESET
" attr_valid=%zu;"
" attr_valid_nsec=%u;"
" ino=%zu;"
" size=%zu;"
" blocks=%zu;"
" atime=%zu;"
" mtime=%zu;"
" ctime=%zu;"
" atimensec=%u;"
" mtimensec=%u;"
" ctimensec=%u;"
" mode=%o;"
" nlink=%u;"
" uid=%u;"
" gid=%u;"
" rdev=%u;"
" blksize=%u;"
"\n",
arg_->attr_valid,
arg_->attr_valid_nsec,
arg_->attr.ino,
arg_->attr.size,
arg_->attr.blocks,
arg_->attr.atime,
arg_->attr.mtime,
arg_->attr.ctime,
arg_->attr.atimensec,
arg_->attr.mtimensec,
arg_->attr.ctimensec,
arg_->attr.mode,
arg_->attr.nlink,
arg_->attr.uid,
arg_->attr.gid,
arg_->attr.rdev,
arg_->attr.blksize);
}
int
fuse_reply_attr(fuse_req_t req,
const struct stat *attr,
@ -461,6 +512,9 @@ fuse_reply_attr(fuse_req_t req,
arg.attr_valid_nsec = 0;
convert_stat(attr,&arg.attr);
if(req->f->debug)
debug_fuse_attr_out(&arg);
return send_reply_ok(req,&arg,size);
}
@ -1212,16 +1266,32 @@ do_batch_forget(fuse_req_t req,
static
void
do_getattr(fuse_req_t req,
fuse_ino_t nodeid,
const void *inarg)
debug_fuse_getattr_in(const struct fuse_getattr_in* arg_)
{
fuse_file_info_t *fip = NULL;
fuse_file_info_t fi;
fprintf(stderr,
ANSI_YELLOW"fuse_getattr_in:"ANSI_RESET
" getattr_flags: 0x%08X;"
" fh: %zu;\n",
arg_->getattr_flags,
arg_->fh);
}
if (req->f->conn.proto_minor >= 9)
static
void
do_getattr(fuse_req_t req_,
fuse_ino_t nodeid_,
const void *inarg_)
{
struct fuse_getattr_in *arg = (struct fuse_getattr_in *) inarg;
fuse_file_info_t fi;
fuse_file_info_t *fip;
fip = NULL;
if(req_->f->conn.proto_minor >= 9)
{
struct fuse_getattr_in *arg = (struct fuse_getattr_in*)inarg_;
if(req_->f->debug)
debug_fuse_getattr_in(arg);
if(arg->getattr_flags & FUSE_GETATTR_FH)
{
@ -1231,10 +1301,10 @@ do_getattr(fuse_req_t req,
}
}
if (req->f->op.getattr)
req->f->op.getattr(req, nodeid, fip);
if(req_->f->op.getattr)
req_->f->op.getattr(req_,nodeid_,fip);
else
fuse_reply_err(req, ENOSYS);
fuse_reply_err(req_,ENOSYS);
}
static
@ -2134,6 +2204,133 @@ do_fallocate(fuse_req_t req,
fuse_reply_err(req, ENOSYS);
}
static
int
is_compatible_protocol(const struct fuse_init_in *arg_)
{
if(arg_->major != 7)
return 0;
if(arg_->minor < 13)
return 0;
return 1;
}
#define FLAG_CASE(X) case FUSE_##X: return #X
static
const
char*
flag_to_str(const uint32_t offset_)
{
switch(1 << offset_)
{
FLAG_CASE(ASYNC_READ);
FLAG_CASE(POSIX_LOCKS);
FLAG_CASE(FILE_OPS);
FLAG_CASE(ATOMIC_O_TRUNC);
FLAG_CASE(EXPORT_SUPPORT);
FLAG_CASE(BIG_WRITES);
FLAG_CASE(DONT_MASK);
FLAG_CASE(SPLICE_WRITE);
FLAG_CASE(SPLICE_MOVE);
FLAG_CASE(SPLICE_READ);
FLAG_CASE(FLOCK_LOCKS);
FLAG_CASE(HAS_IOCTL_DIR);
FLAG_CASE(AUTO_INVAL_DATA);
FLAG_CASE(DO_READDIRPLUS);
FLAG_CASE(READDIRPLUS_AUTO);
FLAG_CASE(ASYNC_DIO);
FLAG_CASE(WRITEBACK_CACHE);
FLAG_CASE(NO_OPEN_SUPPORT);
FLAG_CASE(PARALLEL_DIROPS);
FLAG_CASE(HANDLE_KILLPRIV);
FLAG_CASE(POSIX_ACL);
FLAG_CASE(ABORT_ERROR);
FLAG_CASE(MAX_PAGES);
FLAG_CASE(CACHE_SYMLINKS);
FLAG_CASE(NO_OPENDIR_SUPPORT);
FLAG_CASE(EXPLICIT_INVAL_DATA);
FLAG_CASE(MAP_ALIGNMENT);
}
return NULL;
}
#undef FLAG_CASE
static
void
debug_fuse_init_in(const struct fuse_init_in *arg_)
{
fprintf(stderr,
ANSI_YELLOW"fuse_init_in:"ANSI_RESET
" major=%u;"
" minor=%u;"
" max_readahead=%u;"
" flags=0x%08X (",
arg_->major,
arg_->minor,
arg_->max_readahead,
arg_->flags);
for(int i = 0; i < (sizeof(arg_->flags)*8); i++)
{
const char *str;
if(!(arg_->flags & (1 << i)))
continue;
str = flag_to_str(i);
if(str == NULL)
break;
fprintf(stderr,"%s,",str);
}
fprintf(stderr,")\n");
}
static
void
debug_fuse_init_out(const struct fuse_init_out *arg_)
{
fprintf(stderr,
ANSI_YELLOW"fuse_init_out:"ANSI_RESET
" major=%u;"
" minor=%u;"
" max_readahead=%u;"
" max_background=%u;"
" congestion_threshold=%u;"
" max_write=%u;"
" time_gran=%u;"
" max_pages=%u;"
" map_alignment=%u;"
" flags=0x%08X (",
arg_->major,
arg_->minor,
arg_->max_readahead,
arg_->max_background,
arg_->congestion_threshold,
arg_->max_write,
arg_->time_gran,
arg_->max_pages,
arg_->map_alignment,
arg_->flags);
for(int i = 0; i < (sizeof(arg_->flags)*8); i++)
{
const char *str;
if(!(arg_->flags & (1 << i)))
continue;
str = flag_to_str(i);
if(str == NULL)
break;
fprintf(stderr,"%s,",str);
}
fprintf(stderr,")\n");
}
static
void
do_init(fuse_req_t req,
@ -2145,17 +2342,18 @@ do_init(fuse_req_t req,
struct fuse_ll *f = req->f;
size_t bufsize = fuse_chan_bufsize(req->ch);
(void) nodeid;
if(!is_compatible_protocol(arg))
{
fprintf(stderr,
"fuse: unsupported protocol version - %u.%u\n",
arg->major,
arg->minor);
fuse_reply_err(req,EPROTO);
return;
}
if(f->debug)
{
fprintf(stderr, "INIT: %u.%u\n", arg->major, arg->minor);
if (arg->major == 7 && arg->minor >= 6)
{
fprintf(stderr, "flags=0x%08x\n", arg->flags);
fprintf(stderr, "max_readahead=0x%08x\n",
arg->max_readahead);
}
}
debug_fuse_init_in(arg);
f->conn.proto_major = arg->major;
f->conn.proto_minor = arg->minor;
@ -2168,14 +2366,6 @@ do_init(fuse_req_t req,
outarg.minor = FUSE_KERNEL_MINOR_VERSION;
outarg.max_pages = FUSE_DEFAULT_MAX_PAGES_PER_REQ;
if (arg->major < 7)
{
fprintf(stderr, "fuse: unsupported protocol version: %u.%u\n",
arg->major, arg->minor);
fuse_reply_err(req, EPROTO);
return;
}
if(arg->major > 7)
{
/* Wait for a second INIT request with a 7.X version */
@ -2183,8 +2373,6 @@ do_init(fuse_req_t req,
return;
}
if (arg->minor >= 6)
{
if(arg->max_readahead < f->conn.max_readahead)
f->conn.max_readahead = arg->max_readahead;
if(arg->flags & FUSE_ASYNC_READ)
@ -2217,12 +2405,6 @@ do_init(fuse_req_t req,
f->conn.capable |= FUSE_CAP_READDIR_PLUS;
if(arg->flags & FUSE_READDIRPLUS_AUTO)
f->conn.capable |= FUSE_CAP_READDIR_PLUS_AUTO;
}
else
{
f->conn.want &= ~FUSE_CAP_ASYNC_READ;
f->conn.max_readahead = 0;
}
if(req->f->conn.proto_minor >= 14)
{
@ -2314,27 +2496,14 @@ do_init(fuse_req_t req,
if(f->conn.congestion_threshold > f->conn.max_background)
f->conn.congestion_threshold = f->conn.max_background;
if(!f->conn.congestion_threshold)
{
f->conn.congestion_threshold = f->conn.max_background * 3 / 4;
}
outarg.max_background = f->conn.max_background;
outarg.congestion_threshold = f->conn.congestion_threshold;
}
if(f->debug)
{
fprintf(stderr, " INIT: %u.%u\n", outarg.major, outarg.minor);
fprintf(stderr, " flags=0x%08x\n", outarg.flags);
fprintf(stderr, " max_readahead=0x%08x\n",
outarg.max_readahead);
fprintf(stderr, " max_write=0x%08x\n", outarg.max_write);
fprintf(stderr, " max_background=%i\n",
outarg.max_background);
fprintf(stderr, " congestion_threshold=%i\n",
outarg.congestion_threshold);
fprintf(stderr, " max_pages=%d\n",outarg.max_pages);
}
debug_fuse_init_out(&outarg);
size_t outargsize;
if(arg->minor < 5)
@ -2408,6 +2577,7 @@ do_notify_reply(fuse_req_t req,
pthread_mutex_lock(&f->lock);
head = &f->notify_list;
for(nreq = head->next; nreq != head; nreq = nreq->next)
{
if (nreq->unique == req->unique)
@ -2474,6 +2644,7 @@ send_notify_iov(struct fuse_ll *f,
int
fuse_lowlevel_notify_poll(fuse_pollhandle_t *ph)
{
if(ph != NULL)
{
struct fuse_notify_poll_wakeup_out outarg;
@ -2773,7 +2944,8 @@ fuse_req_interrupted(fuse_req_t req)
return interrupted;
}
static struct {
static struct
{
void (*func)(fuse_req_t, fuse_ino_t, const void *);
const char *name;
} fuse_ll_ops[] =
@ -2856,6 +3028,22 @@ fuse_ll_copy_from_pipe(struct fuse_bufvec *dst,
return 0;
}
static
void
debug_fuse_in_header(const struct fuse_in_header *hdr_)
{
fprintf(stderr,
ANSI_GREEN"opcode:"ANSI_RESET
" %s (%u); unique: %zu; nodeid: %zu; uid: %u; gid: %u; pid: %u\n",
opname(hdr_->opcode),
hdr_->opcode,
hdr_->unique,
hdr_->nodeid,
hdr_->uid,
hdr_->gid,
hdr_->pid);
}
static
void
fuse_ll_process_buf(void *data,
@ -2899,22 +3087,18 @@ fuse_ll_process_buf(void *data,
}
if(f->debug)
{
fprintf(stderr,
"unique: %llu, opcode: %s (%i), nodeid: %lu, insize: %zu, pid: %u\n",
(unsigned long long) in->unique,
opname((enum fuse_opcode) in->opcode), in->opcode,
(unsigned long) in->nodeid, buf->size, in->pid);
}
debug_fuse_in_header(in);
req = fuse_ll_alloc_req(f);
if(req == NULL)
{
struct fuse_out_header out = {
struct fuse_out_header out =
{
.unique = in->unique,
.error = -ENOMEM,
};
struct iovec iov = {
struct iovec iov =
{
.iov_base = &out,
.iov_len = sizeof(struct fuse_out_header),
};
@ -2962,7 +3146,8 @@ fuse_ll_process_buf(void *data,
err = ENOSYS;
if(in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func)
goto reply_err;
if (in->opcode != FUSE_INTERRUPT) {
if(in->opcode != FUSE_INTERRUPT)
{
struct fuse_req *intr;
pthread_mutex_lock(&f->lock);
intr = check_interrupt(f, req);
@ -3300,6 +3485,7 @@ fuse_lowlevel_new_common(struct fuse_args *args,
.destroy = fuse_ll_destroy,
};
if(sizeof(struct fuse_lowlevel_ops) < op_size)
{
fprintf(stderr, "fuse: warning: library too old, some operations may not work\n");
@ -3332,9 +3518,6 @@ fuse_lowlevel_new_common(struct fuse_args *args,
if(fuse_opt_parse(args, f, fuse_ll_opts, fuse_ll_opt_proc) == -1)
goto out_key_destroy;
if (f->debug)
fprintf(stderr, "FUSE library version: %s\n", PACKAGE_VERSION);
memcpy(&f->op, op, op_size);
f->owner = getuid();
f->userdata = userdata;