# HG changeset patch # User Tero Marttila # Date 1224263540 -10800 # Node ID 4f10421681d264e4a400ca067310ef1aca03cfef # Parent 460f995d3769d90e68e812fe26fb2102e971f3a5 working mknod, mkdir, symlink diff -r 460f995d3769 -r 4f10421681d2 Makefile --- a/Makefile Fri Oct 17 19:28:27 2008 +0300 +++ b/Makefile Fri Oct 17 20:12:20 2008 +0300 @@ -20,7 +20,7 @@ # complex modules EVSQL_OBJS = obj/evsql/evsql.o obj/evsql/util.o obj/evpq.o -DBFS_OBJS = obj/dbfs/dbfs.o obj/dbfs/common.o obj/dbfs/core.o obj/dbfs/op_base.o obj/dbfs/trans.o obj/dbfs/dirop.o obj/dirbuf.o obj/dbfs/fileop.o obj/dbfs/attr.o obj/dbfs/link.o obj/dbfs/tree.o +DBFS_OBJS = obj/dbfs/dbfs.o obj/dbfs/common.o obj/dbfs/core.o obj/dbfs/op_base.o obj/dbfs/trans.o obj/dbfs/dirop.o obj/dirbuf.o obj/dbfs/fileop.o obj/dbfs/attr.o obj/dbfs/link.o obj/dbfs/tree.o obj/dbfs/mk.o # first target all: ${BIN_PATHS} diff -r 460f995d3769 -r 4f10421681d2 doc/fuse_db.sql --- a/doc/fuse_db.sql Fri Oct 17 19:28:27 2008 +0300 +++ b/doc/fuse_db.sql Fri Oct 17 20:12:20 2008 +0300 @@ -31,6 +31,7 @@ ALTER TABLE inodes ALTER COLUMN ino SET DEFAULT nextval('ino_seq'::regclass); ALTER TABLE file_tree ADD COLUMN ino int4; +ALTER TABLE file_tree ADD CONSTRAINT file_tree_ino_fkey FOREIGN KEY (ino) REFERENCES inodes (ino); UPDATE file_tree SET ino = inode; ALTER TABLE file_tree DROP COLUMN inode; @@ -41,4 +42,3 @@ ELSE 0 END; $$; - diff -r 460f995d3769 -r 4f10421681d2 src/dbfs/dbfs.c --- a/src/dbfs/dbfs.c Fri Oct 17 19:28:27 2008 +0300 +++ b/src/dbfs/dbfs.c Fri Oct 17 20:12:20 2008 +0300 @@ -15,7 +15,9 @@ .getattr = dbfs_getattr, .setattr = dbfs_setattr, .readlink = dbfs_readlink, - + .mknod = dbfs_mknod, + .mkdir = dbfs_mkdir, + .symlink = dbfs_symlink, .rename = dbfs_rename, diff -r 460f995d3769 -r 4f10421681d2 src/dbfs/fileop.c --- a/src/dbfs/fileop.c Fri Oct 17 19:28:27 2008 +0300 +++ b/src/dbfs/fileop.c Fri Oct 17 20:12:20 2008 +0300 @@ -39,7 +39,7 @@ // is it a dir? if (_dbfs_mode(type) != S_IFREG) - EERROR(err = ENOENT, "wrong type: %s", type); + EERROR(err = EINVAL, "wrong type: %s", type); INFO("[dbfs.open %p:%p] -> ino=%lu, type=%s", fop, fop->base.req, (unsigned long int) fop->base.ino, type); diff -r 460f995d3769 -r 4f10421681d2 src/dbfs/link.c --- a/src/dbfs/link.c Fri Oct 17 19:28:27 2008 +0300 +++ b/src/dbfs/link.c Fri Oct 17 20:12:20 2008 +0300 @@ -1,9 +1,4 @@ -#include -#include -#include - #include "dbfs.h" -#include "trans.h" #include "../lib/log.h" @@ -83,184 +78,3 @@ } -struct dbfs_symlink_ctx { - struct dbfs_trans base; - - char *link, *name; - uint32_t ino, parent; -}; - -#define DBFS_SYMLINK_MODE 0777 - -void dbfs_symlink_free (struct dbfs_trans *ctx_base) { - struct dbfs_symlink_ctx *ctx = (struct dbfs_symlink_ctx *) ctx_base; - - free(ctx->link); - free(ctx->name); -} - -void dbfs_symlink_commit (struct dbfs_trans *ctx_base) { - struct dbfs_symlink_ctx *ctx = (struct dbfs_symlink_ctx *) ctx_base; - struct fuse_entry_param e; - int err; - - // build entry - e.ino = e.attr.st_ino = ctx->ino; - e.attr.st_mode = S_IFLNK | DBFS_SYMLINK_MODE; - e.attr.st_size = strlen(ctx->link); - e.attr.st_nlink = 1; - e.attr_timeout = e.entry_timeout = CACHE_TIMEOUT; - - // reply - if ((err = fuse_reply_entry(ctx_base->req, &e))) - goto error; - - // req good - ctx_base->req = NULL; - - // free - dbfs_trans_free(ctx_base); - - // return - return; - -error: - dbfs_trans_fail(ctx_base, err); -} - -void dbfs_symlink_filetree (const struct evsql_result_info *res, void *arg) { - struct dbfs_symlink_ctx *ctx = arg; - int err = EIO; - - // check results - if (_dbfs_check_res(res, 0, 0) < 0) - goto error; - - // commit - dbfs_trans_commit(&ctx->base); - - // fallthrough for result_free - err = 0; - -error: - if (err) - dbfs_trans_fail(&ctx->base, err); - - evsql_result_free(res); -} - -void dbfs_symlink_inode (const struct evsql_result_info *res, void *arg) { - struct dbfs_symlink_ctx *ctx = arg; - struct dbfs *dbfs_ctx = fuse_req_userdata(ctx->base.req); - int err = EIO; - - // check result - if ((err = _dbfs_check_res(res, 1, 1))) - SERROR(err = err > 0 ? ENOENT : EIO); - - // get ino - if (evsql_result_uint32(res, 0, 0, &ctx->ino, 0)) - goto error; - - // insert file_tree entry - const char *sql = - "INSERT" - " INTO file_tree (name, parent, ino)" - " VALUES ($1::varchar, $2::int4, $3::int4)"; - - static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) { - EVSQL_PARAM ( STRING ), - EVSQL_PARAM ( UINT32 ), - EVSQL_PARAM ( UINT32 ), - - EVSQL_PARAMS_END - }; - - if (0 - || evsql_param_string(¶ms, 0, ctx->name) - || evsql_param_uint32(¶ms, 1, ctx->parent) - || evsql_param_uint32(¶ms, 2, ctx->ino) - ) - goto error; - - // query - if (evsql_query_params(dbfs_ctx->db, ctx->base.trans, sql, ¶ms, dbfs_symlink_filetree, ctx)) - goto error; - - // fallthrough for result_free - err = 0; - -error: - if (err) - dbfs_trans_fail(&ctx->base, err); - - evsql_result_free(res); -} - -void dbfs_symlink_begin (struct dbfs_trans *ctx_base) { - struct dbfs_symlink_ctx *ctx = (struct dbfs_symlink_ctx *) ctx_base; - struct dbfs *dbfs_ctx = fuse_req_userdata(ctx_base->req); - - // insert inode - const char *sql = - "INSERT" - " INTO inodes (type, mode, link_path)" - " VALUES ('LNK', $1::int2, $2::varchar)" - " RETURNING inodes.ino"; - - static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) { - EVSQL_PARAM ( UINT16 ), - EVSQL_PARAM ( STRING ), - - EVSQL_PARAMS_END - }; - - if (0 - || evsql_param_uint16(¶ms, 0, DBFS_SYMLINK_MODE) - || evsql_param_string(¶ms, 1, ctx->link) - ) - goto error; - - if (evsql_query_params(dbfs_ctx->db, ctx_base->trans, sql, ¶ms, dbfs_symlink_inode, ctx) == NULL) - goto error; - - return; - -error: - dbfs_trans_fail(ctx_base, EIO); -} - -void dbfs_symlink (struct fuse_req *req, const char *link, fuse_ino_t parent, const char *name) { - struct dbfs_symlink_ctx *ctx = NULL; - - // alloc - if ((ctx = calloc(1, sizeof(*ctx))) == NULL) - ERROR("calloc"); - - // start trans - if (dbfs_trans_init(&ctx->base, req)) - goto error; - - // callbacks - ctx->base.free_fn = dbfs_symlink_free; - ctx->base.begin_fn = dbfs_symlink_begin; - ctx->base.commit_fn = dbfs_symlink_commit; - - // state - ctx->ino = 0; - ctx->parent = parent; - if (!((ctx->link = strdup(link)) && (ctx->name = strdup(name)))) - ERROR("strdup"); - - // log - INFO("[dbfs.symlink %p:%p] link=%s, parent=%lu, name=%s", ctx, req, link, parent, name); - - // wait - return; - -error: - if (ctx) - dbfs_trans_fail(&ctx->base, EIO); -} - - diff -r 460f995d3769 -r 4f10421681d2 src/dbfs/mk.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbfs/mk.c Fri Oct 17 20:12:20 2008 +0300 @@ -0,0 +1,238 @@ +#include +#include +#include + +#include "trans.h" +#include "../lib/log.h" + +struct dbfs_mk_ctx { + struct dbfs_trans base; + + const char *type, *data_expr; + char *link, *name; + uint16_t mode; + uint32_t ino, parent; +}; + +// default mode for symlinks +#define DBFS_SYMLINK_MODE 0777 + +// max. size for an dbfs_mk INSERT query +#define DBFS_MK_SQL_MAX 512 + +void dbfs_mk_free (struct dbfs_trans *ctx_base) { + struct dbfs_mk_ctx *ctx = (struct dbfs_mk_ctx *) ctx_base; + + free(ctx->link); + free(ctx->name); +} + +void dbfs_mk_commit (struct dbfs_trans *ctx_base) { + struct dbfs_mk_ctx *ctx = (struct dbfs_mk_ctx *) ctx_base; + struct fuse_entry_param e; + int err; + + // build entry + e.ino = e.attr.st_ino = ctx->ino; + e.attr.st_mode = _dbfs_mode(ctx->type) | ctx->mode; + e.attr.st_size = ctx->link ? strlen(ctx->link) : 0; + e.attr.st_nlink = 1; + e.attr_timeout = e.entry_timeout = CACHE_TIMEOUT; + + // reply + if ((err = fuse_reply_entry(ctx_base->req, &e))) + goto error; + + // req good + ctx_base->req = NULL; + + // free + dbfs_trans_free(ctx_base); + + // return + return; + +error: + dbfs_trans_fail(ctx_base, err); +} + +void dbfs_mk_filetree (const struct evsql_result_info *res, void *arg) { + struct dbfs_mk_ctx *ctx = arg; + int err = EIO; + + // check results + if (_dbfs_check_res(res, 0, 0) < 0) + goto error; + + // commit + dbfs_trans_commit(&ctx->base); + + // fallthrough for result_free + err = 0; + +error: + if (err) + dbfs_trans_fail(&ctx->base, err); + + evsql_result_free(res); +} + +void dbfs_mk_inode (const struct evsql_result_info *res, void *arg) { + struct dbfs_mk_ctx *ctx = arg; + struct dbfs *dbfs_ctx = fuse_req_userdata(ctx->base.req); + int err = EIO; + + // check result + if ((err = _dbfs_check_res(res, 1, 1))) + SERROR(err = err > 0 ? ENOENT : EIO); + + // get ino + if (evsql_result_uint32(res, 0, 0, &ctx->ino, 0)) + goto error; + + // insert file_tree entry + const char *sql = + "INSERT" + " INTO file_tree (name, parent, ino)" + " VALUES ($1::varchar, $2::int4, $3::int4)"; + + static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) { + EVSQL_PARAM ( STRING ), + EVSQL_PARAM ( UINT32 ), + EVSQL_PARAM ( UINT32 ), + + EVSQL_PARAMS_END + }; + + if (0 + || evsql_param_string(¶ms, 0, ctx->name) + || evsql_param_uint32(¶ms, 1, ctx->parent) + || evsql_param_uint32(¶ms, 2, ctx->ino) + ) + goto error; + + // query + if (evsql_query_params(dbfs_ctx->db, ctx->base.trans, sql, ¶ms, dbfs_mk_filetree, ctx)) + goto error; + + // fallthrough for result_free + err = 0; + +error: + if (err) + dbfs_trans_fail(&ctx->base, err); + + evsql_result_free(res); +} + +void dbfs_mk_begin (struct dbfs_trans *ctx_base) { + struct dbfs_mk_ctx *ctx = (struct dbfs_mk_ctx *) ctx_base; + struct dbfs *dbfs_ctx = fuse_req_userdata(ctx_base->req); + int ret; + + // insert inode + char sql_buf[DBFS_MK_SQL_MAX]; + + if ((ret = snprintf(sql_buf, DBFS_MK_SQL_MAX, + "INSERT" + " INTO inodes (type, mode, data, link_path)" + " VALUES ($1::char(3), $2::int2, %s, $3::varchar)" + " RETURNING inodes.ino", ctx->data_expr ? ctx->data_expr : "NULL" + )) >= DBFS_MK_SQL_MAX) + ERROR("sql_buf is too small: %d", ret); + + static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) { + EVSQL_PARAM ( STRING ), + EVSQL_PARAM ( UINT16 ), + EVSQL_PARAM ( STRING ), + + EVSQL_PARAMS_END + }; + + if (0 + || evsql_param_string(¶ms, 0, ctx->type) + || evsql_param_uint16(¶ms, 1, ctx->mode) + || evsql_param_string(¶ms, 2, ctx->link) + ) + goto error; + + if (evsql_query_params(dbfs_ctx->db, ctx_base->trans, sql_buf, ¶ms, dbfs_mk_inode, ctx) == NULL) + goto error; + + return; + +error: + dbfs_trans_fail(ctx_base, EIO); +} + +/* + * It is assumed that name and link_path must be copied, but type remains useable + */ +void dbfs_mk (struct fuse_req *req, fuse_ino_t parent, const char *name, const char *type, uint16_t mode, const char *data_expr, const char *link) { + struct dbfs_mk_ctx *ctx = NULL; + + // alloc + if ((ctx = calloc(1, sizeof(*ctx))) == NULL) + ERROR("calloc"); + + // start trans + if (dbfs_trans_init(&ctx->base, req)) + goto error; + + // callbacks + ctx->base.free_fn = dbfs_mk_free; + ctx->base.begin_fn = dbfs_mk_begin; + ctx->base.commit_fn = dbfs_mk_commit; + + // state + ctx->ino = 0; + ctx->parent = parent; + ctx->type = type; + ctx->data_expr = data_expr; + ctx->mode = mode; + + // copy volatile strings + if ( + (link && (ctx->link = strdup(link)) == NULL) + || (name && (ctx->name = strdup(name)) == NULL) + ) + ERROR("strdup"); + + // log + INFO("[dbfs.mk %p:%p] parent=%lu, name=%s, type=%s, mode=%#04o data_expr=%s link=%s", ctx, req, parent, name, type, mode, data_expr, link); + + // wait + return; + +error: + if (ctx) + dbfs_trans_fail(&ctx->base, EIO); +} + +/* + * These are all just aliases to dbfs_mk + */ +void dbfs_mknod (struct fuse_req *req, fuse_ino_t parent, const char *name, mode_t mode, dev_t rdev) { + int err; + + if ((mode & S_IFMT) != S_IFREG) + EERROR(err = EINVAL, "mode is not REG: %#08o", mode); + + dbfs_mk(req, parent, name, "REG", mode & 07777, "lo_create(0)", NULL); + + return; + +error: + if ((err = fuse_reply_err(req, err))) + EWARNING(err, "fuse_reply_error"); +} + +void dbfs_mkdir (struct fuse_req *req, fuse_ino_t parent, const char *name, mode_t mode) { + dbfs_mk(req, parent, name, "DIR", mode, NULL, NULL); +} + + +void dbfs_symlink (struct fuse_req *req, const char *link, fuse_ino_t parent, const char *name) { + dbfs_mk(req, parent, name, "LNK", DBFS_SYMLINK_MODE, NULL, link); +} + diff -r 460f995d3769 -r 4f10421681d2 src/dbfs/ops.h --- a/src/dbfs/ops.h Fri Oct 17 19:28:27 2008 +0300 +++ b/src/dbfs/ops.h Fri Oct 17 20:12:20 2008 +0300 @@ -16,13 +16,17 @@ /* link.c */ void dbfs_readlink (struct fuse_req *req, fuse_ino_t ino); -void dbfs_symlink (struct fuse_req *req, const char *link, fuse_ino_t parent, const char *name); /* dirop.c */ void dbfs_opendir (struct fuse_req *req, fuse_ino_t ino, struct fuse_file_info *fi); void dbfs_readdir (struct fuse_req *req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi); void dbfs_releasedir (struct fuse_req *req, fuse_ino_t ino, struct fuse_file_info *fi); +/* mk.c */ +void dbfs_mknod (struct fuse_req *req, fuse_ino_t parent, const char *name, mode_t mode, dev_t rdev); +void dbfs_mkdir (struct fuse_req *req, fuse_ino_t parent, const char *name, mode_t mode); +void dbfs_symlink (struct fuse_req *req, const char *link, fuse_ino_t parent, const char *name); + /* tree.c */ void dbfs_rename (struct fuse_req *req, fuse_ino_t parent, const char *name, fuse_ino_t newparent, const char *newname);