Mercurial > nomad
changeset 787:f53967574f3e
objstore: implement file unlink
Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Wed, 25 Mar 2020 12:33:44 -0400 |
parents | 3fc635b4636f |
children | 1eef9314f649 |
files | src/objstore/CMakeLists.txt src/objstore/obj_dir.c src/objstore/obj_dir_unlink.c src/objstore/obj_ops.c src/objstore/objstore_impl.h |
diffstat | 5 files changed, 160 insertions(+), 27 deletions(-) [+] |
line wrap: on
line diff
--- a/src/objstore/CMakeLists.txt Tue Mar 31 13:09:46 2020 -0400 +++ b/src/objstore/CMakeLists.txt Wed Mar 25 12:33:44 2020 -0400 @@ -27,6 +27,7 @@ obj.c obj_dir.c obj_dir_create.c + obj_dir_unlink.c obj_ops.c obj_txn.c objstore.c
--- a/src/objstore/obj_dir.c Tue Mar 31 13:09:46 2020 -0400 +++ b/src/objstore/obj_dir.c Wed Mar 25 12:33:44 2020 -0400 @@ -401,26 +401,3 @@ return ret; } - -int dir_unlink(struct objver *dirver, const char *name, const struct noid *desired) -{ - uint8_t raw[DIR_BLOCK_SIZE]; - struct ndirent_mem ent; - int ret; - - ret = dir_lookup_entry(dirver, name, raw, &ent, NULL, NULL); - if (ret) - return ret; - - if (ent.all_deleted) - return -ENOENT; - - if (ent.conflicts && noid_is_null(desired)) - return -ENOTUNIQ; - - FIXME("not yet implemented"); - - /* TODO: mark dirent tgt as removed */ - - return -ENOTSUP; -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/objstore/obj_dir_unlink.c Wed Mar 25 12:33:44 2020 -0400 @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2015-2020 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "dir.h" + +static int __dir_unlink_update(struct dirblock *block, const char *name, + const struct noid *desired) +{ + const size_t namelen = strlen(name); + size_t non_deleted_targets; + size_t i, j; + + /* find the dirent */ + for (i = 0; i < block->ndirents; i++) { + if (namelen != block->entries[i].dirent.namelen) + continue; + + if (!strncmp(name, block->entries[i].name, namelen)) + break; + } + + VERIFY3U(i, <, block->ndirents); + + VERIFY(!block->entries[i].dirent.all_deleted); + + /* find the target */ + for (j = 0; j < block->entries[i].dirent.ntgts; j++) { + struct ndirent_tgt *tgt = &block->entries[i].tgts[j]; + + if (tgt->deleted) + continue; + + if (noid_is_null(desired)) + break; /* found it */ + + /* looking for a specific target */ + + if (tgt->type == NDIRENT_TYPE_GRAFT) { + if (xuuid_compare(&tgt->graft, noid_get_vol(desired))) + continue; + } else { + if ((tgt->host != noid_get_allocator(desired)) || + (tgt->uniq != noid_get_uniq(desired))) + continue; + } + } + + VERIFY3U(j, <, block->entries[i].dirent.ntgts); + VERIFY(!block->entries[i].tgts[j].deleted); + + if (block->entries[i].tgts[j].type == NDIRENT_TYPE_DIR) + return -EISDIR; + + /* update the target */ + block->entries[i].tgts[j].deleted = true; + + non_deleted_targets = 0; + for (j = 0; j < block->entries[i].dirent.ntgts; j++) + if (!block->entries[i].tgts[j].deleted) + non_deleted_targets++; + + if (!block->entries[i].dirent.conflicts) + VERIFY3U(non_deleted_targets, ==, 0); + + block->entries[i].dirent.conflicts = (non_deleted_targets > 1); + block->entries[i].dirent.all_deleted = (non_deleted_targets == 0); + + return 0; +} + +int dir_unlink(struct txn *txn, struct objver *dirver, const char *name, + const struct noid *desired) +{ + uint8_t raw[DIR_BLOCK_SIZE]; + struct ndirent_mem ent; + struct dirblock block; + struct buffer buffer; + uint64_t diroff; + uint16_t ndirents; + int ret; + + ret = dir_lookup_entry(dirver, name, raw, &ent, &diroff, + &ndirents); + if (ret) + return ret; + + if (ent.all_deleted) + return -ENOENT; + + if (ent.conflicts && noid_is_null(desired)) + return -ENOTUNIQ; + + /* parse the block */ + ret = dirblock_parse(&block, raw, ndirents); + if (ret) + return ret; + + /* update the dirent target */ + ret = __dir_unlink_update(&block, name, desired); + if (ret) + return ret; + + /* serialize the block & write it out */ + ret = buffer_init_heap(&buffer, DIR_BLOCK_SIZE); + if (ret) + return ret; + + VERIFY0(buffer_truncate(&buffer, 0)); + + ret = dirblock_serialize(&block, &buffer); + if (ret) { + buffer_free(&buffer); + return ret; + } + + obj_write(txn, dirver, &buffer, diroff); + + return 0; +}
--- a/src/objstore/obj_ops.c Tue Mar 31 13:09:46 2020 -0400 +++ b/src/objstore/obj_ops.c Wed Mar 25 12:33:44 2020 -0400 @@ -431,6 +431,7 @@ int objstore_unlink(struct objstore_open_obj_info *diropen, const char *name, const struct noid *desired) { + struct txn txn; struct obj *dir; int ret; @@ -446,10 +447,26 @@ return -EROFS; MXLOCK(&dir->lock); - if (!NATTR_ISDIR(diropen->ver->attrs.mode)) + + if (!NATTR_ISDIR(diropen->ver->attrs.mode)) { ret = -ENOTDIR; - else - ret = dir_unlink(diropen->ver, name, desired); + goto err; + } + + ret = txn_begin(&txn, diropen->ver->obj->clone); + if (ret) + goto err; + + ret = obj_cow(&txn, diropen); + if (ret) + goto err_txn; + + ret = dir_unlink(&txn, diropen->ver, name, desired); + +err_txn: + ret = txn_commitabort(&txn, ret); + +err: MXUNLOCK(&dir->lock); return ret;
--- a/src/objstore/objstore_impl.h Tue Mar 31 13:09:46 2020 -0400 +++ b/src/objstore/objstore_impl.h Wed Mar 25 12:33:44 2020 -0400 @@ -83,7 +83,7 @@ struct ndirent *child); extern int dir_create(struct txn *txn, struct objver *dirver, const char *name, uint16_t mode, struct noid *child); -extern int dir_unlink(struct objver *dirver, const char *name, +extern int dir_unlink(struct txn *txn, struct objver *dirver, const char *name, const struct noid *desired); /*