Mercurial > nomad
changeset 862:9a63d933a60e
objstore: expose dirent add/update helpers to the rest of objstore
These are useful anytime we want to create a new directory entry - create,
link, symlink, etc.
Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Sat, 17 Dec 2022 17:02:07 -0500 |
parents | 9f4bd7cfa177 |
children | 681892f1d3f7 |
files | src/objstore/CMakeLists.txt src/objstore/dir.c src/objstore/dir.h src/objstore/obj_dir_create.c |
diffstat | 4 files changed, 181 insertions(+), 154 deletions(-) [+] |
line wrap: on
line diff
--- a/src/objstore/CMakeLists.txt Sat Dec 17 17:13:46 2022 -0500 +++ b/src/objstore/CMakeLists.txt Sat Dec 17 17:02:07 2022 -0500 @@ -1,5 +1,5 @@ # -# Copyright (c) 2015-2020 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> +# Copyright (c) 2015-2020,2022 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 @@ -22,6 +22,7 @@ add_library(nomad_objstore SHARED cache.c + dir.c dirblock.c dirent.c dirent_target_packing.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/objstore/dir.c Sat Dec 17 17:02:07 2022 -0500 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2015-2020,2022 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" + +int dir_add_dirent(struct txn *txn, struct objver *dirver, const char *name, + uint16_t mode, const struct noid *child) +{ + uint8_t rawbuf[DIR_BLOCK_SIZE]; + struct nattr attrs = { + .size = dirver->attrs.size + DIR_BLOCK_SIZE, + }; + struct ndirent_tgt tgt; + struct dirblock block; + struct buffer buf; + ssize_t ret; + + /* TODO: try to put it into an existing block */ + + buffer_init_static(&buf, rawbuf, 0, sizeof(rawbuf), true); + + dirblock_init(&block); + + tgt.type = mode >> NATTR_TSHIFT; + tgt.deleted = false; + tgt.host = noid_get_allocator(child); + tgt.uniq = noid_get_uniq(child); + + ret = dirblock_add_dirent(&block, name, &tgt); + if (ret) + return ret; + + ret = dirblock_serialize(&block, &buf); + if (ret) + return ret; + + /* grow the directory by a block */ + obj_setattr(txn, dirver, &attrs, OBJ_ATTR_SIZE); + + /* fill in the fresh block */ + ret = obj_write(txn, dirver, buffer_data(&buf), buffer_size(&buf), + dirver->attrs.size - DIR_BLOCK_SIZE); + if (ret < 0) + return ret; + + if (ret != buffer_size(&buf)) + panic("dir block partial write!"); + + return 0; +} + +static int __dir_update_dirent(struct dirblock *block, const char *name, + uint16_t mode, const struct noid *child) +{ + 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->host != noid_get_allocator(child)) || + (tgt->uniq != noid_get_uniq(child))) + continue; + } + + /* update the target */ + if (j < block->entries[i].dirent.ntgts) { + /* found a match - just reset the flag */ + block->entries[i].tgts[j].deleted = false; + } else { + /* not found - allocate a new target */ + struct ndirent_tgt tgt; + int ret; + + tgt.type = mode >> NATTR_TSHIFT; + tgt.deleted = false; + tgt.host = noid_get_allocator(child); + tgt.uniq = noid_get_uniq(child); + + ret = dirblock_add_dirent_target(block, name, &tgt); + if (ret) + return ret; + } + + non_deleted_targets = 0; + for (j = 0; j < block->entries[i].dirent.ntgts; j++) + if (!block->entries[i].tgts[j].deleted) + non_deleted_targets++; + + VERIFY3U(non_deleted_targets, ==, 1); + + block->entries[i].dirent.conflicts = false; + block->entries[i].dirent.all_deleted = false; + + return 0; +} + +int dir_update_dirent(struct txn *txn, struct objver *dirver, + uint8_t *raw, uint64_t diroff, + uint16_t ndirents, const char *name, + uint16_t mode, const struct noid *child) +{ + uint8_t rawbuf[DIR_BLOCK_SIZE]; + struct dirblock block; + struct buffer buffer; + ssize_t ret; + + /* parse the block */ + ret = dirblock_parse(&block, raw, ndirents); + if (ret) + return ret; + + /* update the dirent target */ + ret = __dir_update_dirent(&block, name, mode, child); + if (ret) + return ret; + + /* serialize the block & write it out */ + buffer_init_static(&buffer, rawbuf, 0, sizeof(rawbuf), true); + + ret = dirblock_serialize(&block, &buffer); + if (ret) + return ret; + + ret = obj_write(txn, dirver, buffer_data(&buffer), buffer_size(&buffer), + diroff); + if (ret < 0) + return ret; + + if (ret != buffer_size(&buffer)) + panic("dir block partial write!"); + + return 0; +}
--- a/src/objstore/dir.h Sat Dec 17 17:13:46 2022 -0500 +++ b/src/objstore/dir.h Sat Dec 17 17:02:07 2022 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2015-2020,2022 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 @@ -217,6 +217,13 @@ extern int dirblock_add_dirent_target(struct dirblock *block, const char *name, const struct ndirent_tgt *tgt); +extern int dir_add_dirent(struct txn *txn, struct objver *dirver, + const char *name, uint16_t mode, + const struct noid *child); +extern int dir_update_dirent(struct txn *txn, struct objver *dirver, + uint8_t *raw, uint64_t diroff, + uint16_t ndirents, const char *name, + uint16_t mode, const struct noid *child); extern int dir_lookup_entry(struct objver *dirver, const char *name, uint8_t *raw, struct ndirent_mem *ent, uint64_t *_off, uint16_t *_ndirents);
--- a/src/objstore/obj_dir_create.c Sat Dec 17 17:13:46 2022 -0500 +++ b/src/objstore/obj_dir_create.c Sat Dec 17 17:02:07 2022 -0500 @@ -24,153 +24,6 @@ #include <jeffpc/time.h> -static int __dir_create_add_dirent(struct txn *txn, struct objver *dirver, - const char *name, uint16_t mode, - const struct noid *child) -{ - uint8_t rawbuf[DIR_BLOCK_SIZE]; - struct nattr attrs = { - .size = dirver->attrs.size + DIR_BLOCK_SIZE, - }; - struct ndirent_tgt tgt; - struct dirblock block; - struct buffer buf; - ssize_t ret; - - /* TODO: try to put it into an existing block */ - - buffer_init_static(&buf, rawbuf, 0, sizeof(rawbuf), true); - - dirblock_init(&block); - - tgt.type = mode >> NATTR_TSHIFT; - tgt.deleted = false; - tgt.host = noid_get_allocator(child); - tgt.uniq = noid_get_uniq(child); - - ret = dirblock_add_dirent(&block, name, &tgt); - if (ret) - return ret; - - ret = dirblock_serialize(&block, &buf); - if (ret) - return ret; - - /* grow the directory by a block */ - obj_setattr(txn, dirver, &attrs, OBJ_ATTR_SIZE); - - /* fill in the fresh block */ - ret = obj_write(txn, dirver, buffer_data(&buf), buffer_size(&buf), - dirver->attrs.size - DIR_BLOCK_SIZE); - if (ret < 0) - return ret; - - if (ret != buffer_size(&buf)) - panic("dir block partial write!"); - - return 0; -} - -static int __dir_create_update_dirent_real(struct dirblock *block, - const char *name, uint16_t mode, - const struct noid *child) -{ - 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->host != noid_get_allocator(child)) || - (tgt->uniq != noid_get_uniq(child))) - continue; - } - - /* update the target */ - if (j < block->entries[i].dirent.ntgts) { - /* found a match - just reset the flag */ - block->entries[i].tgts[j].deleted = false; - } else { - /* not found - allocate a new target */ - struct ndirent_tgt tgt; - int ret; - - tgt.type = mode >> NATTR_TSHIFT; - tgt.deleted = false; - tgt.host = noid_get_allocator(child); - tgt.uniq = noid_get_uniq(child); - - ret = dirblock_add_dirent_target(block, name, &tgt); - if (ret) - return ret; - } - - non_deleted_targets = 0; - for (j = 0; j < block->entries[i].dirent.ntgts; j++) - if (!block->entries[i].tgts[j].deleted) - non_deleted_targets++; - - VERIFY3U(non_deleted_targets, ==, 1); - - block->entries[i].dirent.conflicts = false; - block->entries[i].dirent.all_deleted = false; - - return 0; -} - -static int __dir_create_update_dirent(struct txn *txn, struct objver *dirver, - uint8_t *raw, uint64_t diroff, - uint16_t ndirents, const char *name, - uint16_t mode, const struct noid *child) -{ - uint8_t rawbuf[DIR_BLOCK_SIZE]; - struct dirblock block; - struct buffer buffer; - ssize_t ret; - - /* parse the block */ - ret = dirblock_parse(&block, raw, ndirents); - if (ret) - return ret; - - /* update the dirent target */ - ret = __dir_create_update_dirent_real(&block, name, mode, child); - if (ret) - return ret; - - /* serialize the block & write it out */ - buffer_init_static(&buffer, rawbuf, 0, sizeof(rawbuf), true); - - ret = dirblock_serialize(&block, &buffer); - if (ret) - return ret; - - ret = obj_write(txn, dirver, buffer_data(&buffer), buffer_size(&buffer), - diroff); - if (ret < 0) - return ret; - - if (ret != buffer_size(&buffer)) - panic("dir block partial write!"); - - return 0; -} - int dir_create(struct txn *txn, struct objver *dirver, const char *name, uint32_t owner, uint32_t group, uint16_t mode, struct noid *_child) @@ -248,14 +101,12 @@ /* add dirent to parent dir */ if (!update_existing) { - ret = __dir_create_add_dirent(txn, dirver, name, mode, - &child->obj->oid); + ret = dir_add_dirent(txn, dirver, name, mode, &child->obj->oid); if (ret) goto err; } else { - ret = __dir_create_update_dirent(txn, dirver, raw, diroff, - ndirents, name, mode, - &child->obj->oid); + ret = dir_update_dirent(txn, dirver, raw, diroff, ndirents, + name, mode, &child->obj->oid); if (ret) goto err; }