From 198ec2ed5b2036e4cb9c9799c1f2b72ebf9b66ba Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Tue, 9 Aug 2016 17:01:00 -0700 Subject: [PATCH] scoutfs: have btree_update return errors We can certainly have btree update callers that haven't yet dirtied the blocks but who can deal with errors. So make it return errors and have its only current caller freak out if it fails. This will let the file data block mapping code attempt to get a dirty item without first dirtying. Signed-off-by: Zach Brown --- kmod/src/btree.c | 27 ++++++++++++++++++--------- kmod/src/btree.h | 4 ++-- kmod/src/inode.c | 5 ++++- 3 files changed, 24 insertions(+), 12 deletions(-) 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);