Author: pjd
Date: Mon Aug 17 10:00:18 2009
New Revision: 196309
URL: http://svn.freebsd.org/changeset/base/196309

Log:
  getcwd() (when __getcwd() fails) works by stating current directory, going up
  (..), calling readdir and looking for previous directory inode.  In case of
  .zfs/ directory this doesn't work, because .zfs/ is hidden by default, so it
  won't be visible in readdir output.
  
  Fix this by implementing VPTOCNP for snapshot directories, so __getcwd()
  doesn't fail and getcwd() doesn't have to use readdir method.
  
  This fixes /bin/pwd from within .zfs/snapshot/<name>/.
  
  Suggested by: kib
  Approved by:  re (rwatson)

Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c    Mon Aug 
17 09:55:58 2009        (r196308)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c    Mon Aug 
17 10:00:18 2009        (r196309)
@@ -1195,6 +1195,48 @@ zfsctl_snapshot_lookup(ap)
        return (error);
 }
 
+static int
+zfsctl_snapshot_vptocnp(struct vop_vptocnp_args *ap)
+{
+       zfsvfs_t *zfsvfs = ap->a_vp->v_vfsp->vfs_data;
+       vnode_t *dvp, *vp;
+       zfsctl_snapdir_t *sdp;
+       zfs_snapentry_t *sep;
+       int error;
+
+       ASSERT(zfsvfs->z_ctldir != NULL);
+       error = zfsctl_root_lookup(zfsvfs->z_ctldir, "snapshot", &dvp,
+           NULL, 0, NULL, kcred, NULL, NULL, NULL);
+       if (error != 0)
+               return (error);
+       sdp = dvp->v_data;
+
+       mutex_enter(&sdp->sd_lock);
+       sep = avl_first(&sdp->sd_snaps);
+       while (sep != NULL) {
+               vp = sep->se_root;
+               if (vp == ap->a_vp)
+                       break;
+               sep = AVL_NEXT(&sdp->sd_snaps, sep);
+       }
+       if (sep == NULL) {
+               mutex_exit(&sdp->sd_lock);
+               error = ENOENT;
+       } else {
+               size_t len;
+
+               len = strlen(sep->se_name);
+               *ap->a_buflen -= len;
+               bcopy(sep->se_name, ap->a_buf + *ap->a_buflen, len);
+               mutex_exit(&sdp->sd_lock);
+               vhold(dvp);
+               *ap->a_vpp = dvp;
+       }
+       VN_RELE(dvp);
+
+       return (error);
+}
+
 /*
  * These VP's should never see the light of day.  They should always
  * be covered.
@@ -1206,6 +1248,7 @@ static struct vop_vector zfsctl_ops_snap
        .vop_reclaim =  zfsctl_common_reclaim,
        .vop_getattr =  zfsctl_snapshot_getattr,
        .vop_fid =      zfsctl_snapshot_fid,
+       .vop_vptocnp =  zfsctl_snapshot_vptocnp,
 };
 
 int
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to