- /*
- * Before grabbing the four locks, we may need to get an iocount on the resource fork
- * vnodes in question, just like hfs_vnop_remove. If fvp and tvp are not
- * directories, then go ahead and grab the resource fork vnodes now
- * one at a time. We don't actively need the fvp_rsrc to do the rename operation,
- * but we need the iocount to prevent the vnode from getting recycled/reclaimed
- * during the middle of the VNOP.
- */
-
-
- if ((vnode_isreg(fvp)) || (vnode_islnk(fvp))) {
-
- if ((error = hfs_lock (VTOC(fvp), HFS_EXCLUSIVE_LOCK))) {
- return (error);
- }
- /*
- * We care if we race against rename/delete with this cp, so we'll error out
- * if the file becomes open-unlinked during this call.
- */
- error = hfs_vgetrsrc(VTOHFS(fvp), fvp, &fvp_rsrc, TRUE, TRUE);
- hfs_unlock (VTOC(fvp));
- if (error) {
- if (fvp_rsrc) {
- vnode_put(fvp_rsrc);
- }
- return error;
- }
- }
-
- if (tvp && (vnode_isreg(tvp) || vnode_islnk(tvp))) {
- /*
- * Lock failure is OK on tvp, since we may race with a remove on the dst.
- * But this shouldn't stop rename from proceeding, so only try to
- * grab the resource fork if the lock succeeded.
- */
- if (hfs_lock (VTOC(tvp), HFS_EXCLUSIVE_LOCK) == 0) {
- tcp = VTOC(tvp);
- /*
- * We only care if we get an open-unlinked file on the dst so we
- * know to null out tvp/tcp to make the rename operation act
- * as if they never existed. Because they're effectively out of the
- * namespace already it's fine to do this. If this is true, then
- * make sure to unlock the cnode and drop the iocount only after the unlock.
- */
-
- error = hfs_vgetrsrc(VTOHFS(tvp), tvp, &tvp_rsrc, TRUE, TRUE);
- hfs_unlock (tcp);
- if (error) {
- /*
- * Since we specify TRUE for error_on_unlinked in hfs_vgetrsrc,
- * we can get a rsrc fork vnode even if it returns an error.
- */
- tcp = NULL;
- tvp = NULL;
- if (tvp_rsrc) {
- vnode_put (tvp_rsrc);
- tvp_rsrc = NULL;
- }
- /* just bypass truncate lock and act as if we never got tcp/tvp */
- goto retry;
- }
- }
- }
-