Add item delete dirty and many interfaces

Add item functions for deleting items that we know to be dirty and add a
user in another function that deletes many items without leaving parial
deletions behind in the case of errors.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2017-01-25 11:08:43 -08:00
parent f139cf4a5e
commit 9a293bfa75
2 changed files with 78 additions and 4 deletions

View File

@@ -964,6 +964,23 @@ out:
return ret;
}
/*
* Turn an item that the caller has found while holding the lock into a
* deletion item. The caller will free whatever we put in the deletion
* value after releasing the lock.
*/
static void become_deletion_item(struct super_block *sb,
struct item_cache *cac,
struct cached_item *item,
struct kvec *del_val)
{
scoutfs_kvec_clone(del_val, item->val);
scoutfs_kvec_init_null(item->val);
item->deletion = 1;
mark_item_dirty(cac, item);
scoutfs_inc_counter(sb, item_delete);
}
/*
* Delete an existing item with the given key.
*
@@ -999,10 +1016,7 @@ int scoutfs_item_delete(struct super_block *sb, struct scoutfs_key_buf *key)
item = find_item(sb, &cac->items, key);
if (item) {
scoutfs_kvec_swap(item->val, del_val);
item->deletion = 1;
mark_item_dirty(cac, item);
scoutfs_inc_counter(sb, item_delete);
become_deletion_item(sb, cac, item, del_val);
ret = 0;
} else if (check_range(sb, &cac->ranges, key, end)) {
ret = -ENOENT;
@@ -1022,6 +1036,62 @@ out:
return ret;
}
/*
* Delete an item that the caller knows must be dirty because they hold
* locks and the transaction and have created or dirtied it. This can't
* fail.
*/
void scoutfs_item_delete_dirty(struct super_block *sb,
struct scoutfs_key_buf *key)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct item_cache *cac = sbi->item_cache;
SCOUTFS_DECLARE_KVEC(del_val);
struct cached_item *item;
unsigned long flags;
scoutfs_kvec_init_null(del_val);
spin_lock_irqsave(&cac->lock, flags);
item = find_item(sb, &cac->items, key);
if (item)
become_deletion_item(sb, cac, item, del_val);
spin_unlock_irqrestore(&cac->lock, flags);
scoutfs_kvec_kfree(del_val);
}
/*
* A helper that deletes a set of items. It first dirties the items
* will be pinned so that deletion won't fail as it tries to read and
* populate the items.
*
* It's a little cleaner to have this helper than have the caller
* iterate, but it could also give us the opportunity to reduce item
* searches if we remembered the items we dirtied.
*/
int scoutfs_item_delete_many(struct super_block *sb,
struct scoutfs_key_buf **keys, unsigned nr)
{
int ret = 0;
int i;
for (i = 0; i < nr; i++) {
ret = scoutfs_item_dirty(sb, keys[i]);
if (ret)
goto out;
}
for (i = 0; i < nr; i++)
scoutfs_item_delete_dirty(sb, keys[i]);
out:
trace_printk("ret %d\n", ret);
return ret;
}
/*
* Return the first dirty node in the subtree starting at the given node.
*/

View File

@@ -26,6 +26,10 @@ int scoutfs_item_create(struct super_block *sb, struct scoutfs_key_buf *key,
int scoutfs_item_dirty(struct super_block *sb, struct scoutfs_key_buf *key);
int scoutfs_item_update(struct super_block *sb, struct scoutfs_key_buf *key,
struct kvec *val);
void scoutfs_item_delete_dirty(struct super_block *sb,
struct scoutfs_key_buf *key);
int scoutfs_item_delete_many(struct super_block *sb,
struct scoutfs_key_buf **keys, unsigned nr);
int scoutfs_item_delete(struct super_block *sb, struct scoutfs_key_buf *key);
int scoutfs_item_add_batch(struct super_block *sb, struct list_head *list,