X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=module%2Fzfs%2Fzfs_znode.c;h=17a5821eb415c7e8e4db019b2850281b436070bf;hb=f0b2486034f6a4d8cd1a139ff4604e6b9629a64e;hp=1fe88499b555ffe16712e75a8bbd7cae3d0e78a4;hpb=d6bd8eaae4bdbce8e162414bb6c84ac95fd456b4;p=zfs.git diff --git a/module/zfs/zfs_znode.c b/module/zfs/zfs_znode.c index 1fe8849..17a5821 100644 --- a/module/zfs/zfs_znode.c +++ b/module/zfs/zfs_znode.c @@ -278,7 +278,7 @@ zfs_inode_destroy(struct inode *ip) static void zfs_inode_set_ops(zfs_sb_t *zsb, struct inode *ip) { - uint64_t rdev; + uint64_t rdev = 0; switch (ip->i_mode & S_IFMT) { case S_IFREG: @@ -297,12 +297,16 @@ zfs_inode_set_ops(zfs_sb_t *zsb, struct inode *ip) ip->i_op = &zpl_symlink_inode_operations; break; + /* + * rdev is only stored in a SA only for device files. + */ case S_IFCHR: case S_IFBLK: - case S_IFIFO: - case S_IFSOCK: VERIFY(sa_lookup(ITOZ(ip)->z_sa_hdl, SA_ZPL_RDEV(zsb), &rdev, sizeof (rdev)) == 0); + /*FALLTHROUGH*/ + case S_IFIFO: + case S_IFSOCK: init_special_inode(ip, ip->i_mode, rdev); ip->i_op = &zpl_special_inode_operations; break; @@ -322,7 +326,8 @@ zfs_inode_set_ops(zfs_sb_t *zsb, struct inode *ip) */ static znode_t * zfs_znode_alloc(zfs_sb_t *zsb, dmu_buf_t *db, int blksz, - dmu_object_type_t obj_type, uint64_t obj, sa_handle_t *hdl) + dmu_object_type_t obj_type, uint64_t obj, sa_handle_t *hdl, + struct dentry *dentry) { znode_t *zp; struct inode *ip; @@ -372,13 +377,15 @@ zfs_znode_alloc(zfs_sb_t *zsb, dmu_buf_t *db, int blksz, } ip->i_ino = obj; - ip->i_mode = zp->z_mode; - ip->i_mtime = ip->i_atime = ip->i_ctime = CURRENT_TIME_SEC; + zfs_inode_update(zp); zfs_inode_set_ops(zsb, ip); if (insert_inode_locked(ip)) goto error; + if (dentry) + d_instantiate(dentry, ip); + mutex_enter(&zsb->z_znodes_lock); list_insert_tail(&zsb->z_all_znodes, zp); membar_producer(); @@ -553,8 +560,7 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr, size = links = 0; } - if (S_ISBLK(vap->va_mode) || S_ISCHR(vap->va_mode) || - S_ISFIFO(vap->va_mode) || S_ISSOCK(vap->va_mode)) + if (S_ISBLK(vap->va_mode) || S_ISCHR(vap->va_mode)) rdev = vap->va_rdev; parent = dzp->z_id; @@ -645,8 +651,7 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr, &empty_xattr, 8); } if (obj_type == DMU_OT_ZNODE || - (S_ISBLK(vap->va_mode) || S_ISCHR(vap->va_mode) || - S_ISFIFO(vap->va_mode) || S_ISSOCK(vap->va_mode))) { + (S_ISBLK(vap->va_mode) || S_ISCHR(vap->va_mode))) { SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_RDEV(zsb), NULL, &rdev, 8); } @@ -675,7 +680,8 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr, VERIFY(sa_replace_all_by_template(sa_hdl, sa_attrs, cnt, tx) == 0); if (!(flag & IS_ROOT_NODE)) { - *zpp = zfs_znode_alloc(zsb, db, 0, obj_type, obj, sa_hdl); + *zpp = zfs_znode_alloc(zsb, db, 0, obj_type, obj, sa_hdl, + vap->va_dentry); ASSERT(*zpp != NULL); ASSERT(dzp != NULL); err = zpl_xattr_security_init(ZTOI(*zpp), ZTOI(dzp)); @@ -806,14 +812,19 @@ zfs_zget(zfs_sb_t *zsb, uint64_t obj_num, znode_t **zpp) znode_t *zp; int err; sa_handle_t *hdl; + struct inode *ip; *zpp = NULL; +again: + ip = ilookup(zsb->z_sb, obj_num); + ZFS_OBJ_HOLD_ENTER(zsb, obj_num); err = sa_buf_hold(zsb->z_os, obj_num, NULL, &db); if (err) { ZFS_OBJ_HOLD_EXIT(zsb, obj_num); + iput(ip); return (err); } @@ -824,13 +835,27 @@ zfs_zget(zfs_sb_t *zsb, uint64_t obj_num, znode_t **zpp) doi.doi_bonus_size < sizeof (znode_phys_t)))) { sa_buf_rele(db, NULL); ZFS_OBJ_HOLD_EXIT(zsb, obj_num); + iput(ip); return (EINVAL); } hdl = dmu_buf_get_user(db); if (hdl != NULL) { - zp = sa_get_userdata(hdl); + if (ip == NULL) { + /* + * ilookup returned NULL, which means + * the znode is dying - but the SA handle isn't + * quite dead yet, we need to drop any locks + * we're holding, re-schedule the task and try again. + */ + sa_buf_rele(db, NULL); + ZFS_OBJ_HOLD_EXIT(zsb, obj_num); + + schedule(); + goto again; + } + zp = sa_get_userdata(hdl); /* * Since "SA" does immediate eviction we @@ -852,9 +877,12 @@ zfs_zget(zfs_sb_t *zsb, uint64_t obj_num, znode_t **zpp) sa_buf_rele(db, NULL); mutex_exit(&zp->z_lock); ZFS_OBJ_HOLD_EXIT(zsb, obj_num); + iput(ip); return (err); } + ASSERT3P(ip, ==, NULL); + /* * Not found create new znode/vnode but only if file exists. * @@ -866,7 +894,7 @@ zfs_zget(zfs_sb_t *zsb, uint64_t obj_num, znode_t **zpp) * bonus buffer. */ zp = zfs_znode_alloc(zsb, db, doi.doi_data_block_size, - doi.doi_bonus_type, obj_num, NULL); + doi.doi_bonus_type, obj_num, NULL, NULL); if (zp == NULL) { err = ENOENT; } else { @@ -1091,22 +1119,6 @@ zfs_grow_blocksize(znode_t *zp, uint64_t size, dmu_tx_t *tx) dmu_object_size_from_db(sa_get_db(zp->z_sa_hdl), &zp->z_blksz, &dummy); } -#ifdef HAVE_MMAP -/* - * This is a dummy interface used when pvn_vplist_dirty() should *not* - * be calling back into the fs for a putpage(). E.g.: when truncating - * a file, the pages being "thrown away* don't need to be written out. - */ -/* ARGSUSED */ -static int -zfs_no_putpage(vnode_t *vp, page_t *pp, u_offset_t *offp, size_t *lenp, - int flags, cred_t *cr) -{ - ASSERT(0); - return (0); -} -#endif /* HAVE_MMAP */ - /* * Increase the file length *