VFS: Integrate zfs_znode_alloc()

Under Linux the convention for filesystem specific data structure is
to embed it along with the generic vfs data structure.  This differs
significantly from Solaris.

Since we want to integrates as cleanly with the Linux VFS as possible.
This changes modifies zfs_znode_alloc() to allocate a znode with an
embedded inode for use with the generic VFS.  This is done by calling
iget_locked() which will allocate a new inode if needed by calling
sb->alloc_inode().  This function allocates enough memory for a
znode_t by returns a pointer to the inode structure for Linux's VFS.
This function is also responsible for setting the callback
znode->z_set_ops_inodes() which is used to register the correct
handlers for the inode.
This commit is contained in:
Brian Behlendorf 2011-01-05 13:16:12 -08:00
parent 10c6047ea5
commit 7304b6e50f
2 changed files with 37 additions and 62 deletions

View File

@ -211,6 +211,8 @@ typedef struct znode {
list_node_t z_link_node; /* all znodes in fs link */ list_node_t z_link_node; /* all znodes in fs link */
sa_handle_t *z_sa_hdl; /* handle to sa data */ sa_handle_t *z_sa_hdl; /* handle to sa data */
boolean_t z_is_sa; /* are we native sa? */ boolean_t z_is_sa; /* are we native sa? */
void (*z_set_ops_inode) (struct inode *); /* set inode ops */
struct inode z_inode; /* generic vfs inode */
} znode_t; } znode_t;
@ -231,13 +233,18 @@ typedef struct znode {
*/ */
/* /*
* Convert between znode pointers and vnode pointers * Convert between znode pointers and inode pointers
*/ */
#define ZTOI(ZP) (&((ZP)->z_inode))
#define ITOZ(IP) (container_of((IP), znode_t, z_inode))
/* XXX - REMOVE ME ONCE THE OTHER BUILD ISSUES ARE RESOLVED */
#define ZTOV(ZP) ((ZP)->z_vnode) #define ZTOV(ZP) ((ZP)->z_vnode)
#define VTOZ(VP) ((znode_t *)(VP)->v_data) #define VTOZ(VP) ((znode_t *)(VP)->v_data)
/* /*
* ZFS_ENTER() is called on entry to each ZFS vnode and vfs operation. * ZFS_ENTER() is called on entry to each ZFS inode and vfs operation.
* ZFS_EXIT() must be called before exitting the vop. * ZFS_EXIT() must be called before exitting the vop.
* ZFS_VERIFY_ZP() verifies the znode is valid. * ZFS_VERIFY_ZP() verifies the znode is valid.
*/ */

View File

@ -425,7 +425,7 @@ zfs_znode_dmu_fini(znode_t *zp)
} }
/* /*
* Construct a new znode/vnode and intialize. * Construct a new znode+inode and initialize.
* *
* This does not do a call to dmu_set_user() that is * This does not do a call to dmu_set_user() that is
* up to the caller to do, in case you don't want to * up to the caller to do, in case you don't want to
@ -436,16 +436,19 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
dmu_object_type_t obj_type, sa_handle_t *hdl) dmu_object_type_t obj_type, sa_handle_t *hdl)
{ {
znode_t *zp; znode_t *zp;
#ifdef HAVE_ZPL struct inode *inode;
vnode_t *vp;
uint64_t mode;
uint64_t parent; uint64_t parent;
sa_bulk_attr_t bulk[9]; sa_bulk_attr_t bulk[9];
int count = 0; int count = 0;
#endif /* HAVE_ZPL */
zp = kmem_cache_alloc(znode_cache, KM_SLEEP); ASSERT(zfsvfs != NULL);
ASSERT(zfsvfs->z_vfs != NULL);
ASSERT(zfsvfs->z_vfs->mnt_sb != NULL);
inode = iget_locked(zfsvfs->z_vfs->mnt_sb, db->db_object);
zp = ITOZ(inode);
ASSERT(inode->i_state & I_NEW);
ASSERT(zp->z_dirlocks == NULL); ASSERT(zp->z_dirlocks == NULL);
ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs)); ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs));
zp->z_moved = 0; zp->z_moved = 0;
@ -463,21 +466,20 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
zp->z_seq = 0x7A4653; zp->z_seq = 0x7A4653;
zp->z_sync_cnt = 0; zp->z_sync_cnt = 0;
#ifdef HAVE_ZPL
vp = ZTOV(zp);
vn_reinit(vp);
zfs_znode_sa_init(zfsvfs, zp, db, obj_type, hdl); zfs_znode_sa_init(zfsvfs, zp, db, obj_type, hdl);
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL, &mode, 8); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL,
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GEN(zfsvfs), NULL, &zp->z_gen, 8); &zp->z_mode, 8);
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GEN(zfsvfs), NULL,
&zp->z_gen, 8);
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs), NULL, SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs), NULL,
&zp->z_size, 8); &zp->z_size, 8);
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zfsvfs), NULL, SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zfsvfs), NULL,
&zp->z_links, 8); &zp->z_links, 8);
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL, SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL,
&zp->z_pflags, 8); &zp->z_pflags, 8);
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_PARENT(zfsvfs), NULL, &parent, 8); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_PARENT(zfsvfs), NULL,
&parent, 8);
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zfsvfs), NULL, SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zfsvfs), NULL,
&zp->z_atime, 16); &zp->z_atime, 16);
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zfsvfs), NULL, SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zfsvfs), NULL,
@ -488,57 +490,23 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count) != 0 || zp->z_gen == 0) { if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count) != 0 || zp->z_gen == 0) {
if (hdl == NULL) if (hdl == NULL)
sa_handle_destroy(zp->z_sa_hdl); sa_handle_destroy(zp->z_sa_hdl);
kmem_cache_free(znode_cache, zp); iput(inode);
return (NULL); return (NULL);
} }
zp->z_mode = mode; inode->i_mode = (umode_t)zp->z_mode;
vp->v_vfsp = zfsvfs->z_parent->z_vfs; if ((S_ISCHR(inode->i_mode)) || (S_ISBLK(inode->i_mode))) {
uint64_t rdev;
vp->v_type = IFTOVT((mode_t)mode); VERIFY(sa_lookup(zp->z_sa_hdl, SA_ZPL_RDEV(zfsvfs),
&rdev, sizeof (rdev)) == 0);
switch (vp->v_type) { inode->i_rdev = zfs_cmpldev(rdev);
case VDIR:
if (zp->z_pflags & ZFS_XATTR) {
vn_setops(vp, zfs_xdvnodeops);
vp->v_flag |= V_XATTRDIR;
} else {
vn_setops(vp, zfs_dvnodeops);
}
zp->z_zn_prefetch = B_TRUE; /* z_prefetch default is enabled */
break;
case VBLK:
case VCHR:
{
uint64_t rdev;
VERIFY(sa_lookup(zp->z_sa_hdl, SA_ZPL_RDEV(zfsvfs),
&rdev, sizeof (rdev)) == 0);
vp->v_rdev = zfs_cmpldev(rdev);
}
/*FALLTHROUGH*/
case VFIFO:
case VSOCK:
case VDOOR:
vn_setops(vp, zfs_fvnodeops);
break;
case VREG:
vp->v_flag |= VMODSORT;
if (parent == zfsvfs->z_shares_dir) {
ASSERT(zp->z_uid == 0 && zp->z_gid == 0);
vn_setops(vp, zfs_sharevnodeops);
} else {
vn_setops(vp, zfs_fvnodeops);
}
break;
case VLNK:
vn_setops(vp, zfs_symvnodeops);
break;
default:
vn_setops(vp, zfs_evnodeops);
break;
} }
#endif /* HAVE_ZPL */
/* zp->z_set_ops_inode() must be set in sb->alloc_inode() */
ASSERT(zp->z_set_ops_inode != NULL);
zp->z_set_ops_inode(inode);
unlock_new_inode(inode);
mutex_enter(&zfsvfs->z_znodes_lock); mutex_enter(&zfsvfs->z_znodes_lock);
list_insert_tail(&zfsvfs->z_all_znodes, zp); list_insert_tail(&zfsvfs->z_all_znodes, zp);
membar_producer(); membar_producer();