diff --git a/kmod/src/btree.c b/kmod/src/btree.c index 57e9ffe9..d3a1c9d0 100644 --- a/kmod/src/btree.c +++ b/kmod/src/btree.c @@ -1114,30 +1114,39 @@ int scoutfs_btree_dirty(struct super_block *sb, struct scoutfs_key *key) } /* - * For this to be safe the caller has to have pinned the dirty blocks - * for the item in their transaction. + * This is guaranteed not to fail if the caller has already dirtied the + * block that contains the item in the current transaction. */ -void scoutfs_btree_update(struct super_block *sb, struct scoutfs_key *key, - struct scoutfs_btree_cursor *curs) +int scoutfs_btree_update(struct super_block *sb, struct scoutfs_key *key, + struct scoutfs_btree_cursor *curs) { struct scoutfs_btree_item *item; struct scoutfs_btree_block *bt; struct buffer_head *bh; int pos; int cmp; + int ret; BUG_ON(curs->bh); bh = btree_walk(sb, key, NULL, 0, 0, WALK_DIRTY); - BUG_ON(IS_ERR(bh)); + if (IS_ERR(bh)) + return PTR_ERR(bh); bt = bh_data(bh); pos = find_pos(bt, key, &cmp); - BUG_ON(cmp); + if (cmp == 0) { + item = pos_item(bt, pos); + item->seq = bt->hdr.seq; + set_cursor(curs, bh, pos, true); + ret = 0; + } else { + unlock_block(NULL, bh, true); + scoutfs_block_put(bh); + ret = -ENOENT; + } - item = pos_item(bt, pos); - item->seq = bt->hdr.seq; - set_cursor(curs, bh, pos, true); + return ret; } void scoutfs_btree_release(struct scoutfs_btree_cursor *curs) diff --git a/kmod/src/btree.h b/kmod/src/btree.h index a7faca87..60d4a0b5 100644 --- a/kmod/src/btree.h +++ b/kmod/src/btree.h @@ -27,8 +27,8 @@ int scoutfs_btree_next(struct super_block *sb, struct scoutfs_key *first, struct scoutfs_key *last, struct scoutfs_btree_cursor *curs); int scoutfs_btree_dirty(struct super_block *sb, struct scoutfs_key *key); -void scoutfs_btree_update(struct super_block *sb, struct scoutfs_key *key, - struct scoutfs_btree_cursor *curs); +int scoutfs_btree_update(struct super_block *sb, struct scoutfs_key *key, + struct scoutfs_btree_cursor *curs); int scoutfs_btree_hole(struct super_block *sb, struct scoutfs_key *first, struct scoutfs_key *last, struct scoutfs_key *hole); int scoutfs_btree_since(struct super_block *sb, struct scoutfs_key *first, diff --git a/kmod/src/inode.c b/kmod/src/inode.c index 6caaeb06..fcdbd455 100644 --- a/kmod/src/inode.c +++ b/kmod/src/inode.c @@ -249,10 +249,13 @@ void scoutfs_update_inode_item(struct inode *inode) DECLARE_SCOUTFS_BTREE_CURSOR(curs); struct super_block *sb = inode->i_sb; struct scoutfs_key key; + int err; scoutfs_set_key(&key, scoutfs_ino(inode), SCOUTFS_INODE_KEY, 0); - scoutfs_btree_update(sb, &key, &curs); + err = scoutfs_btree_update(sb, &key, &curs); + BUG_ON(err); + store_inode(curs.val, inode); scoutfs_btree_release(&curs); trace_scoutfs_update_inode(inode);