diff --git a/sys/vfs/hammer/hammer_ioctl.c b/sys/vfs/hammer/hammer_ioctl.c index 267ded3..894622b 100644 --- a/sys/vfs/hammer/hammer_ioctl.c +++ b/sys/vfs/hammer/hammer_ioctl.c @@ -48,6 +48,8 @@ static int hammer_ioc_set_version(hammer_transaction_t trans, struct hammer_ioc_version *ver); static int hammer_ioc_get_info(hammer_transaction_t trans, struct hammer_ioc_info *info); +static int hammer_ioc_get_pfs_btree(hammer_transaction_t trans, uint32_t *curloc); + static int hammer_ioc_add_snapshot(hammer_transaction_t trans, hammer_inode_t ip, struct hammer_ioc_snapshot *snap); static int hammer_ioc_del_snapshot(hammer_transaction_t trans, hammer_inode_t ip, @@ -228,6 +230,12 @@ hammer_ioctl(hammer_inode_t ip, u_long com, caddr_t data, int fflag, &trans, ip, (struct hammer_ioc_data *)data); } break; + case HAMMERIOC_GETPFS_BTREE: + if (error == 0) { + error = hammer_ioc_get_pfs_btree( + &trans, (uint32_t *)data); + } + break; default: error = EOPNOTSUPP; break; @@ -978,7 +986,6 @@ again: leaf.base.localization = ip->obj_localization + HAMMER_LOCALIZE_INODE; leaf.base.key = 0; /* page 0 */ leaf.data_len = sizeof(struct hammer_config_data); - cursor.key_beg = leaf.base; cursor.asof = HAMMER_MAX_TID; @@ -1020,6 +1027,71 @@ again: static int +hammer_ioc_get_pfs_btree(hammer_transaction_t trans, uint32_t *curloc) +{ + struct hammer_cursor cursor; + hammer_inode_t ip; + int error; + + ip = hammer_get_inode(trans, NULL, HAMMER_OBJID_ROOT, HAMMER_MAX_TID, + HAMMER_DEF_LOCALIZATION, 0, &error); + + error = hammer_init_cursor(trans, &cursor, &ip->cache[1], ip); + if (error) { + hammer_done_cursor(&cursor); + return error; + } + + cursor.key_beg.localization = HAMMER_DEF_LOCALIZATION + + HAMMER_LOCALIZE_MISC; + cursor.key_beg.obj_id = HAMMER_OBJID_ROOT; + cursor.key_beg.create_tid = 0; + cursor.key_beg.delete_tid = 0; + cursor.key_beg.rec_type = HAMMER_RECTYPE_PFS; + cursor.key_beg.obj_type = 0; + cursor.key_end = cursor.key_beg; + cursor.key_end.key = HAMMER_MAX_KEY; + cursor.asof = HAMMER_MAX_TID; + cursor.flags |= HAMMER_CURSOR_ASOF; + + if (*curloc == -1) { /* PFS#0 requested */ + cursor.key_beg.key = 0; + error = hammer_ip_first(&cursor); + if (error) + goto out; + } else { + /* + * Attempt to find out the next PFS by going to the last known + * PFS passed in from userland and iterating it once. + */ + cursor.key_beg.key = (*curloc << 16); + error = hammer_ip_first(&cursor); + if (error) + goto out; + error = hammer_ip_next(&cursor); + if (error) + goto out; + error = hammer_ip_resolve_data(&cursor); + if (error) + goto out; + if (cursor.data->pfsd.mirror_flags & HAMMER_PFSD_DELETED) { + error = hammer_ip_next(&cursor); + if (error) + goto out; + } + + } + + *curloc = (u_int32_t)(cursor.leaf->base.key >> 16); +out: + hammer_done_cursor(&cursor); + hammer_rel_inode(ip, 0); + + return (error); +} + +static +int hammer_ioc_get_data(hammer_transaction_t trans, hammer_inode_t ip, struct hammer_ioc_data *data) { diff --git a/sys/vfs/hammer/hammer_ioctl.h b/sys/vfs/hammer/hammer_ioctl.h index 6db417a..ac89ea0 100644 --- a/sys/vfs/hammer/hammer_ioctl.h +++ b/sys/vfs/hammer/hammer_ioctl.h @@ -495,6 +495,6 @@ struct hammer_ioc_data { #define HAMMERIOC_DEDUP _IOWR('h',25,struct hammer_ioc_dedup) #define HAMMERIOC_GET_DATA _IOWR('h',26,struct hammer_ioc_data) #define HAMMERIOC_LIST_VOLUMES _IOWR('h',27,struct hammer_ioc_volume_list) +#define HAMMERIOC_GETPFS_BTREE _IOWR('h',28,uint32_t) #endif -