scoutfs: add scoutfs_btree_hole() for finding keys

Directory entries found a hole in the key range between the first and
last possible hash value for a new entry's key.  The xattrs want
to do the same thing so let's extract this into a proper function.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2016-07-04 10:45:17 -07:00
parent 5c7ba5ed39
commit a64ca8018a
3 changed files with 39 additions and 13 deletions

View File

@@ -953,3 +953,38 @@ void scoutfs_btree_release(struct scoutfs_btree_cursor *curs)
}
curs->bl = NULL;
}
/*
* Find the first missing key between the caller's keys, inclusive. Set
* the caller's hole key and return 0 if we find a missing key. Return
* -ENOSPC if all the keys in the range were present or -errno on errors.
*
* The caller ensures that it's safe for us to be walking this region
* of the tree.
*/
int scoutfs_btree_hole(struct super_block *sb, struct scoutfs_key *first,
struct scoutfs_key *last, struct scoutfs_key *hole)
{
DECLARE_SCOUTFS_BTREE_CURSOR(curs);
int ret;
*hole = *first;
while ((ret = scoutfs_btree_next(sb, first, last, &curs)) > 0) {
/* return our expected hole if we skipped it */
if (scoutfs_key_cmp(hole, curs.key) < 0)
break;
*hole = *curs.key;
scoutfs_inc_key(hole);
}
scoutfs_btree_release(&curs);
if (ret >= 0) {
if (scoutfs_key_cmp(hole, last) <= 0)
ret = 0;
else
ret = -ENOSPC;
}
return ret;
}

View File

@@ -28,6 +28,8 @@ int scoutfs_btree_next(struct super_block *sb, struct scoutfs_key *first,
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_hole(struct super_block *sb, struct scoutfs_key *first,
struct scoutfs_key *last, struct scoutfs_key *hole);
void scoutfs_btree_release(struct scoutfs_btree_cursor *curs);

View File

@@ -341,21 +341,10 @@ static int scoutfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
scoutfs_set_key(&last, scoutfs_ino(dir), SCOUTFS_DIRENT_KEY,
last_dirent_key_offset(h));
/* find the first unoccupied key offset after the hashed name */
key = first;
while ((ret = scoutfs_btree_next(sb, &first, &last, &curs)) > 0) {
key = *curs.key;
scoutfs_inc_key(&key);
}
scoutfs_btree_release(&curs);
if (ret < 0)
ret = scoutfs_btree_hole(sb, &first, &last, &key);
if (ret)
goto out;
if (scoutfs_key_cmp(&key, &last) > 0) {
ret = -ENOSPC;
goto out;
}
ret = scoutfs_btree_insert(sb, &key, bytes, &curs);
if (ret)
goto out;