Mercurial > nomad
view src/objstore/obj_dir_unlink.c @ 871:7f43822eef34
objstore: add a FIXME about decrementing the unlink target's nlinks
Not doing this is currently fine because:
1. nothing will have a link count >1 as we don't support hardlinks yet
2. everything we unlink will cease to exist, so not writing a 0 nlinks is ok
Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Sat, 17 Dec 2022 20:19:31 -0500 |
parents | 75e654e85cab |
children |
line wrap: on
line source
/* * 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" static int __dir_unlink_update(struct dirblock *block, const char *name, const struct noid *desired, bool rmdir) { 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 (rmdir && (block->entries[i].tgts[j].type != NDIRENT_TYPE_DIR)) return -ENOTDIR; if (!rmdir && (block->entries[i].tgts[j].type == NDIRENT_TYPE_DIR)) return -EISDIR; if (!rmdir) FIXME("need to decrement the target's link count"); /* 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, bool rmdir) { uint8_t raw[DIR_BLOCK_SIZE]; struct ndirent_mem ent; struct dirblock block; struct buffer buffer; uint64_t diroff; uint16_t ndirents; ssize_t 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, rmdir); if (ret) return ret; /* serialize the block & write it out */ buffer_init_static(&buffer, raw, 0, sizeof(raw), 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; }