/* * Dangling inodes can occur if processes are holding open descriptors on * deleted files as-of when a machine crashes. When we find one simply * acquire the inode and release it. The inode handling code will then * do the right thing. */ static void prune_check_nlinks(hammer_cursor_t cursor, hammer_btree_leaf_elm_t elm) { hammer_inode_t ip; int error; if (elm->base.rec_type != HAMMER_RECTYPE_INODE) return; if (elm->base.delete_tid != 0) return; if (hammer_btree_extract(cursor, HAMMER_CURSOR_GET_DATA)) return; if (cursor->data->inode.nlinks) return; hammer_cursor_downgrade(cursor); ip = hammer_get_inode(cursor->trans, NULL, elm->base.obj_id, HAMMER_MAX_TID, elm->base.localization & HAMMER_LOCALIZE_PSEUDOFS_MASK, 0, &error); if (ip) { if (hammer_debug_general & 0x0001) { kprintf("pruning disconnected inode %016llx\n", (long long)elm->base.obj_id); } hammer_rel_inode(ip, 0); hammer_inode_waitreclaims(cursor->trans); } else { kprintf("unable to prune disconnected inode %016llx\n", (long long)elm->base.obj_id); } }
/* * Iterate PFS ondisk data. * This function essentially does the same as hammer_load_pseudofs() * except that this function only retrieves PFS data without touching * hammer_pfs_rb_tree at all. * * NOTE: The ip used for ioctl is not necessarily related to the PFS * since this ioctl only requires PFS id (or upper 16 bits of ip localization). * * NOTE: The API was changed in DragonFly 4.7, due to design issues * this ioctl and libhammer (which is the only caller of this ioctl * within DragonFly source, but no longer maintained by anyone) had. */ int hammer_ioc_scan_pseudofs(hammer_transaction_t trans, hammer_inode_t ip, struct hammer_ioc_pseudofs_rw *pfs) { struct hammer_cursor cursor; hammer_inode_t dip; uint32_t localization; int error; if ((error = hammer_pfs_autodetect(pfs, ip)) != 0) return(error); localization = pfs_to_lo(pfs->pfs_id); pfs->bytes = sizeof(struct hammer_pseudofs_data); pfs->version = HAMMER_IOC_PSEUDOFS_VERSION; dip = hammer_get_inode(trans, NULL, HAMMER_OBJID_ROOT, HAMMER_MAX_TID, HAMMER_DEF_LOCALIZATION, 0, &error); error = hammer_init_cursor(trans, &cursor, (dip ? &dip->cache[1] : NULL), dip); if (error) goto fail; 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_beg.key = localization; cursor.asof = HAMMER_MAX_TID; cursor.flags |= HAMMER_CURSOR_ASOF; error = hammer_ip_lookup(&cursor); if (error == 0) { error = hammer_ip_resolve_data(&cursor); if (error == 0) { if (pfs->ondisk) copyout(cursor.data, pfs->ondisk, cursor.leaf->data_len); localization = cursor.leaf->base.key; pfs->pfs_id = lo_to_pfs(localization); } } hammer_done_cursor(&cursor); fail: if (dip) hammer_rel_inode(dip, 0); return(error); }
/* * Obtain a vnode for the specified inode number. An exclusively locked * vnode is returned. */ int hammer_vfs_vget(struct mount *mp, struct vnode *dvp, ino_t ino, struct vnode **vpp) { struct hammer_transaction trans; struct hammer_mount *hmp = (void *)mp->mnt_data; struct hammer_inode *ip; int error; u_int32_t localization; lwkt_gettoken(&hmp->fs_token); hammer_simple_transaction(&trans, hmp); /* * If a directory vnode is supplied (mainly NFS) then we can acquire * the PFS domain from it. Otherwise we would only be able to vget * inodes in the root PFS. */ if (dvp) { localization = HAMMER_DEF_LOCALIZATION + VTOI(dvp)->obj_localization; } else { localization = HAMMER_DEF_LOCALIZATION; } /* * Lookup the requested HAMMER inode. The structure must be * left unlocked while we manipulate the related vnode to avoid * a deadlock. */ ip = hammer_get_inode(&trans, NULL, ino, hmp->asof, localization, 0, &error); if (ip == NULL) { *vpp = NULL; } else { error = hammer_get_vnode(ip, vpp); hammer_rel_inode(ip, 0); } hammer_done_transaction(&trans); lwkt_reltoken(&hmp->fs_token); return (error); }
/* * Convert a file handle back to a vnode. * * Use rootvp to enforce PFS isolation when a PFS is exported via a * null mount. */ static int hammer_vfs_fhtovp(struct mount *mp, struct vnode *rootvp, struct fid *fhp, struct vnode **vpp) { hammer_mount_t hmp = (void *)mp->mnt_data; struct hammer_transaction trans; struct hammer_inode *ip; struct hammer_inode_info info; int error; u_int32_t localization; bcopy(fhp->fid_data + 0, &info.obj_id, sizeof(info.obj_id)); bcopy(fhp->fid_data + 8, &info.obj_asof, sizeof(info.obj_asof)); if (rootvp) localization = VTOI(rootvp)->obj_localization; else localization = (u_int32_t)fhp->fid_ext << 16; lwkt_gettoken(&hmp->fs_token); hammer_simple_transaction(&trans, hmp); /* * Get/allocate the hammer_inode structure. The structure must be * unlocked while we manipulate the related vnode to avoid a * deadlock. */ ip = hammer_get_inode(&trans, NULL, info.obj_id, info.obj_asof, localization, 0, &error); if (ip) { error = hammer_get_vnode(ip, vpp); hammer_rel_inode(ip, 0); } else { *vpp = NULL; } hammer_done_transaction(&trans); lwkt_reltoken(&hmp->fs_token); return (error); }
static inline int _vnode_validate(hammer_dedup_cache_t dcp, void *data, int *errorp) { struct hammer_transaction trans; hammer_inode_t ip; struct vnode *vp; struct buf *bp; /* off_t dooffset; */ int result, error; result = error = 0; *errorp = 0; hammer_simple_transaction(&trans, dcp->hmp); ip = hammer_get_inode(&trans, NULL, dcp->obj_id, HAMMER_MAX_TID, dcp->localization, 0, &error); if (ip == NULL) { kprintf("dedup: unable to find objid %016llx:%08x\n", (long long)dcp->obj_id, dcp->localization); *errorp = 1; goto failed2; } error = hammer_get_vnode(ip, &vp); if (error) { kprintf("dedup: unable to acquire vnode for %016llx:%08x\n", (long long)dcp->obj_id, dcp->localization); *errorp = 2; goto failed; } if ((bp = findblk(ip->vp, dcp->file_offset, FINDBLK_NBLOCK)) != NULL) { dfly_brelse(bp); /* bremfree(bp) */ /* XXX if (mapped to userspace) goto done, *errorp = 4 */ if ((bp->b_flags & B_CACHE) == 0 || bp->b_flags & B_DIRTY) { *errorp = 5; goto done; } /* XXX if (bp->b_bio2.bio_offset != dcp->data_offset) { error = VOP_BMAP(ip->vp, dcp->file_offset, &dooffset, NULL, NULL, BUF_CMD_READ); if (error) { *errorp = 6; goto done; } if (dooffset != dcp->data_offset) { *errorp = 7; goto done; } hammer_live_dedup_bmap_saves++; } */ if (bcmp(data, bp->b_data, dcp->bytes) == 0) result = 1; done: dfly_brelse(bp); /* XX free to buffer not kfree ... bqrelse(bp);*/ } else { *errorp = 3; } vput(vp); failed: hammer_rel_inode(ip, 0); failed2: hammer_done_transaction(&trans); return (result); }