diff options
author | maybee <none@none> | 2005-12-20 09:47:24 -0800 |
---|---|---|
committer | maybee <none@none> | 2005-12-20 09:47:24 -0800 |
commit | 5422900b426b0077b9c2720a47bf829be8225830 (patch) | |
tree | 871023931b4b73cb81919c2bf422765c89feeccb /usr/src/uts/common/fs/zfs/zfs_ctldir.c | |
parent | 95b97885737f6c068bf0c5187e14f4441fd48acd (diff) | |
download | illumos-gate-5422900b426b0077b9c2720a47bf829be8225830.tar.gz |
6359739 panic in zfsctl_snapshot_zname()
Diffstat (limited to 'usr/src/uts/common/fs/zfs/zfs_ctldir.c')
-rw-r--r-- | usr/src/uts/common/fs/zfs/zfs_ctldir.c | 43 |
1 files changed, 25 insertions, 18 deletions
diff --git a/usr/src/uts/common/fs/zfs/zfs_ctldir.c b/usr/src/uts/common/fs/zfs/zfs_ctldir.c index 8e01d2e62b..29e5e7ad89 100644 --- a/usr/src/uts/common/fs/zfs/zfs_ctldir.c +++ b/usr/src/uts/common/fs/zfs/zfs_ctldir.c @@ -397,9 +397,9 @@ zfsctl_snapshot_zname(vnode_t *vp, const char *name, int len, char *zname) objset_t *os = ((zfsvfs_t *)((vp)->v_vfsp->vfs_data))->z_os; dmu_objset_name(os, zname); - (void) strcat(zname, "@"); - if (strlen(zname) + strlen(name) >= len) + if (strlen(zname) + 1 + strlen(name) >= len) return (ENAMETOOLONG); + (void) strcat(zname, "@"); (void) strcat(zname, name); return (0); } @@ -438,7 +438,7 @@ zfsctl_unmount_snap(vnode_t *dvp, const char *name, int force, cred_t *cr) } -static int +static void zfsctl_rename_snap(zfsctl_snapdir_t *sdp, zfs_snapentry_t *sep, const char *nm) { avl_index_t where; @@ -447,7 +447,6 @@ zfsctl_rename_snap(zfsctl_snapdir_t *sdp, zfs_snapentry_t *sep, const char *nm) char newpath[MAXNAMELEN]; const char *oldpath; char *tail; - int err; ASSERT(MUTEX_HELD(&sdp->sd_lock)); ASSERT(sep != NULL); @@ -455,8 +454,7 @@ zfsctl_rename_snap(zfsctl_snapdir_t *sdp, zfs_snapentry_t *sep, const char *nm) vfsp = vn_mountedvfs(sep->se_root); ASSERT(vfsp != NULL); - if (err = vfs_lock(vfsp)) - return (err); + vfs_lock_wait(vfsp); /* * Change the name in the AVL tree. @@ -492,7 +490,6 @@ zfsctl_rename_snap(zfsctl_snapdir_t *sdp, zfs_snapentry_t *sep, const char *nm) vfs_setresource(vfsp, newpath); vfs_unlock(vfsp); - return (0); } static int @@ -505,7 +502,9 @@ zfsctl_snapdir_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, char from[MAXNAMELEN], to[MAXNAMELEN]; int err; - VERIFY(zfsctl_snapshot_zname(sdvp, snm, MAXNAMELEN, from) == 0); + err = zfsctl_snapshot_zname(sdvp, snm, MAXNAMELEN, from); + if (err) + return (err); err = zfs_secpolicy_write(from, NULL, cr); if (err) return (err); @@ -519,20 +518,21 @@ zfsctl_snapdir_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, if (strcmp(snm, tnm) == 0) return (0); + err = zfsctl_snapshot_zname(tdvp, tnm, MAXNAMELEN, to); + if (err) + return (err); + mutex_enter(&sdp->sd_lock); search.se_name = (char *)snm; - if ((sep = avl_find(&sdp->sd_snaps, &search, &where)) != NULL) { - err = zfsctl_rename_snap(sdp, sep, tnm); - if (err) { - mutex_exit(&sdp->sd_lock); - return (err); - } + if ((sep = avl_find(&sdp->sd_snaps, &search, &where)) == NULL) { + mutex_exit(&sdp->sd_lock); + return (ENOENT); } - - VERIFY(zfsctl_snapshot_zname(tdvp, tnm, MAXNAMELEN, to) == 0); err = dmu_objset_rename(from, to); + if (err == 0) + zfsctl_rename_snap(sdp, sep, tnm); mutex_exit(&sdp->sd_lock); @@ -547,7 +547,9 @@ zfsctl_snapdir_remove(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr) char snapname[MAXNAMELEN]; int err; - VERIFY(zfsctl_snapshot_zname(dvp, name, MAXNAMELEN, snapname) == 0); + err = zfsctl_snapshot_zname(dvp, name, MAXNAMELEN, snapname); + if (err) + return (err); err = zfs_secpolicy_write(snapname, NULL, cr); if (err) return (err); @@ -624,7 +626,12 @@ zfsctl_snapdir_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, pathname_t *pnp, /* * The requested snapshot is not currently mounted, look it up. */ - VERIFY(zfsctl_snapshot_zname(dvp, nm, MAXNAMELEN, snapname) == 0); + err = zfsctl_snapshot_zname(dvp, nm, MAXNAMELEN, snapname); + if (err) { + mutex_exit(&sdp->sd_lock); + ZFS_EXIT(zfsvfs); + return (err); + } if (dmu_objset_open(snapname, DMU_OST_ZFS, DS_MODE_STANDARD | DS_MODE_READONLY, &snap) != 0) { mutex_exit(&sdp->sd_lock); |