Пример #1
0
/*
 * 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);
	}
}
Пример #2
0
// corresponds to hammer_vfs_vget
struct inode *hammerfs_iget(struct super_block *sb, ino_t ino) 
{
    struct hammer_transaction trans;
    struct hammer_mount *hmp = (void*)sb->s_fs_info;
    struct hammer_inode *ip;
    struct inode *inode;
    int error = 0;
   
    hammer_simple_transaction(&trans, hmp); 

   /*
    * 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, HAMMER_DEF_LOCALIZATION, 
                          0, &error);
    if (ip == NULL) {
        hammer_done_transaction(&trans);
        goto failed;
    }
    error = hammerfs_get_inode(sb, ip, &inode);
//    hammer_rel_inode(ip, 0);
    hammer_done_transaction(&trans);

    return inode;
failed:
    iget_failed(inode);
    return ERR_PTR(error);
}
Пример #3
0
/*
 * 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);
}
Пример #6
0
/* corresponds to hammer_vop_nresolve */
struct dentry *hammerfs_inode_lookup(struct inode *parent_inode,
					struct dentry *dentry,
					struct nameidata *nameidata)
{
	struct hammer_transaction trans;
	struct super_block *sb;
	struct inode *inode;
	hammer_inode_t dip;
	hammer_inode_t ip;
	hammer_tid_t asof;
	struct hammer_cursor cursor;
	int64_t namekey;
	u_int32_t max_iterations;
	int64_t obj_id;
	int nlen;
	int flags;
	int error;
	u_int32_t localization;

	printk(KERN_INFO "hammerfs_inode_lookup(parent_inode->i_ino=%lu, dentry->d_name.name=%s)\n",
		parent_inode->i_ino, dentry->d_name.name);

	sb = parent_inode->i_sb;
	dip = (hammer_inode_t)parent_inode->i_private;
	asof = dip->obj_asof;
	localization = dip->obj_localization;   /* for code consistency */
	nlen = dentry->d_name.len;
	flags = dip->flags & HAMMER_INODE_RO;

	hammer_simple_transaction(&trans, dip->hmp);

   /*
    * Calculate the namekey and setup the key range for the scan.  This
    * works kinda like a chained hash table where the lower 32 bits
    * of the namekey synthesize the chain.
    *
    * The key range is inclusive of both key_beg and key_end.
    */
	namekey = hammer_directory_namekey(dip, dentry->d_name.name, nlen,
						&max_iterations);

	error = hammer_init_cursor(&trans, &cursor, &dip->cache[1], dip);
	cursor.key_beg.localization = dip->obj_localization +
			HAMMER_LOCALIZE_MISC;
	cursor.key_beg.obj_id = dip->obj_id;
	cursor.key_beg.key = namekey;
	cursor.key_beg.create_tid = 0;
	cursor.key_beg.delete_tid = 0;
	cursor.key_beg.rec_type = HAMMER_RECTYPE_DIRENTRY;
	cursor.key_beg.obj_type = 0;

	cursor.key_end = cursor.key_beg;
	cursor.key_end.key += max_iterations;
	cursor.asof = asof;
	cursor.flags |= HAMMER_CURSOR_END_INCLUSIVE | HAMMER_CURSOR_ASOF;

   /*
    * Scan all matching records (the chain), locate the one matching
    * the requested path component.
    *
    * The hammer_ip_*() functions merge in-memory records with on-disk
    * records for the purposes of the search.
    */
	obj_id = 0;
	localization = HAMMER_DEF_LOCALIZATION;

	if (error == 0) {
		error = hammer_ip_first(&cursor);
		while (error == 0) {
			error = hammer_ip_resolve_data(&cursor);
			if (error)
				break;
			if (nlen == cursor.leaf->data_len -
				HAMMER_ENTRY_NAME_OFF &&
				bcmp(dentry->d_name.name,
				cursor.data->entry.name, nlen) == 0) {
				obj_id = cursor.data->entry.obj_id;
				localization = cursor.data->entry.localization;
				break;
			}
			error = hammer_ip_next(&cursor);
		}
	}
	hammer_done_cursor(&cursor);
	if (error == 0) {
		ip = hammer_get_inode(&trans, dip, obj_id,
				asof, localization,
				flags, &error);
		if (error == 0)
			error = hammerfs_get_inode(sb, ip, &inode);
			/* hammer_rel_inode(ip, 0); */
		else
			ip = NULL;
		if (error == 0)
			d_add(dentry, inode);
		goto done;
	}
done:
	/*hammer_done_transaction(&trans);*/
	return NULL;
}
Пример #7
0
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);
}