From c4f3c26343d8fa8c0df7d88b4050b99cb38934d5 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Sun, 17 Sep 2017 12:58:16 -0700 Subject: [PATCH] scoutfs: add scoutfs_item_update_dirty() Add a function for updating the value of a dirty item. Callers can use this to make changes without having to worry about failure. Signed-off-by: Zach Brown --- kmod/src/item.c | 28 ++++++++++++++++++++++++++++ kmod/src/item.h | 2 ++ 2 files changed, 30 insertions(+) diff --git a/kmod/src/item.c b/kmod/src/item.c index 38662a98..f996bd1e 100644 --- a/kmod/src/item.c +++ b/kmod/src/item.c @@ -1436,6 +1436,34 @@ void scoutfs_item_delete_dirty(struct super_block *sb, scoutfs_kvec_kfree(del_val); } +/* + * Copy the callers value into the dirty item and truncate its value if + * the existing value is longer. The caller must have ensured that the + * item was dirty and had a large enough value. + */ +void scoutfs_item_update_dirty(struct super_block *sb, + struct scoutfs_key_buf *key, struct kvec *val) +{ + struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb); + struct item_cache *cac = sbi->item_cache; + struct cached_item *item; + unsigned long flags; + signed delta; + + spin_lock_irqsave(&cac->lock, flags); + + item = find_item(sb, &cac->items, key); + + BUG_ON(!item || !(item->dirty & ITEM_DIRTY) || + scoutfs_kvec_length(val) > scoutfs_kvec_length(item->val)); + + delta = scoutfs_kvec_length(val) - scoutfs_kvec_length(item->val); + scoutfs_kvec_memcpy_truncate(item->val, val); + update_dirty_item_counts(sb, 0, 0, delta); + + spin_unlock_irqrestore(&cac->lock, flags); +} + /* * Return the first dirty node in the subtree starting at the given node. */ diff --git a/kmod/src/item.h b/kmod/src/item.h index bd04ccbc..5825eb0f 100644 --- a/kmod/src/item.h +++ b/kmod/src/item.h @@ -36,6 +36,8 @@ int scoutfs_item_update(struct super_block *sb, struct scoutfs_key_buf *key, struct kvec *val, struct scoutfs_key_buf *end); void scoutfs_item_delete_dirty(struct super_block *sb, struct scoutfs_key_buf *key); +void scoutfs_item_update_dirty(struct super_block *sb, + struct scoutfs_key_buf *key, struct kvec *val); int scoutfs_item_delete(struct super_block *sb, struct scoutfs_key_buf *key, struct scoutfs_key_buf *end);