Add support for an extra argument to afs_symlink() to return the
newly-created symlink vnode if requested (this is needed on OS X
Mavericks). On OS X Mavericks return the newly-created symlink vnode in
the symlink vnops functions, on all other platforms ignore it.
It turns out that technically OS X has required the symlink to be
created for a while, but code inside of symlink() would call namei() on
the symlink name if the returned vnode point was NULL. The difference
is that on Mavericks the Manditory Access Control Framework has been
enabled, and that turns on some extra code which unconditionally calls
vnode_mount() on the returned vnode pointer, which ends up causing a
panic
Reviewed-on: http://gerrit.openafs.org/10474
Reviewed-by: Derrick Brashear <shadow@your-file-system.com>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
(cherry picked from commit
3f4c1099b7b2d1467b1f5b701ea2f953fec20dc0)
Change-Id: Ib8bac6fd4ed8fe5c2e9567431f7d03fdab50cd50
Reviewed-on: http://gerrit.openafs.org/10519
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
AFS_STATCNT(afs_gn_symlink);
VATTR_NULL(&va);
va.va_mode = 0777;
- error = afs_symlink(vp, link, &va, target, cred);
+ error = afs_symlink(vp, link, &va, target, NULL, cred);
afs_Trace4(afs_iclSetp, CM_TRACE_GSYMLINK, ICL_TYPE_POINTER, vp,
ICL_TYPE_STRING, link, ICL_TYPE_STRING, target, ICL_TYPE_LONG,
error);
* } */ *ap;
{
struct vnode *dvp = ap->a_dvp;
+ struct vcache *vpp = NULL;
int error = 0;
- /* NFS ignores a_vpp; so do we. */
GETNAME();
AFS_GLOCK();
- error =
- afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, vop_cn_cred);
+ error = afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, &vpp,
+ vop_cn_cred);
AFS_GUNLOCK();
- DROPNAME();
#ifndef AFS_DARWIN80_ENV
FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
vput(dvp);
#endif
+ *ap->a_vpp = NULL;
+ if (!error) {
+ error = afs_darwin_finalizevnode(vpp, dvp, ap->a_cnp, 0, 0);
+ if (! error)
+ *ap->a_vpp = AFSTOV(vpp);
+ }
+ DROPNAME();
return error;
}
newvp = NULL;
error =
- afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, cnp->cn_cred);
+ afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, NULL,
+ cnp->cn_cred);
if (error == 0) {
error = afs_lookup(VTOAFS(dvp), name, &vcp, cnp->cn_cred);
if (error == 0) {
int code;
AFS_GLOCK();
- code = afs_symlink(adp, aname, attrs, atargetName, acred);
+ code = afs_symlink(adp, aname, attrs, atargetName, NULL, acred);
AFS_GUNLOCK();
return (code);
}
VATTR_NULL(&vattr);
AFS_GLOCK();
- code = afs_symlink(VTOAFS(dip), (char *)name, &vattr, (char *)target, credp);
+ code = afs_symlink(VTOAFS(dip), (char *)name, &vattr, (char *)target, NULL,
+ credp);
AFS_GUNLOCK();
crfree(credp);
return afs_convert_code(code);
VATTR_NULL(&vattr);
AFS_GLOCK();
- code = afs_symlink(VTOAFS(dip), (char *)name, &vattr, (char *)target, credp);
+ code = afs_symlink(VTOAFS(dip), (char *)name, &vattr, (char *)target, NULL,
+ credp);
AFS_GUNLOCK();
crfree(credp);
return afs_convert_code(code);
GETNAME();
AFS_GLOCK();
code =
- afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target,
+ afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, NULL,
cnp->cn_cred);
AFS_GUNLOCK();
DROPCNP(cnp);
GETNAME();
AFS_GLOCK();
code =
- afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, cnp->cn_cred);
+ afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, NULL,
+ cnp->cn_cred);
AFS_GUNLOCK();
DROPCNP(cnp);
DROPNAME();
int code;
AFS_GLOCK();
- code = afs_symlink(adp, aname, attrs, atargetName, acred);
+ code = afs_symlink(adp, aname, attrs, atargetName, NULL, acred);
AFS_GUNLOCK();
return (code);
}
attrs.va_mode = 0777;
attrs.va_uid = afs_cr_uid(get_user_struct()->u_cred);
attrs.va_gid = afs_cr_gid(get_user_struct()->u_cred);
- code = afs_symlink(VTOAFS(dirP), nameP, &attrs, target, get_user_struct()->u_cred);
+ code = afs_symlink(VTOAFS(dirP), nameP, &attrs, target, NULL,
+ get_user_struct()->u_cred);
VN_RELE(dirP);
if (code != 0) {
errno = code;
int (*vn_rmdir) (struct vcache *adp, char *, afs_ucred_t *);
int (*vn_readdir) (struct vcache *avc, struct uio *, afs_ucred_t *);
int (*vn_symlink) (struct vcache *adp, char *, struct vattr *, char *,
- afs_ucred_t *);
+ struct vcache **vpp, afs_ucred_t *);
int (*vn_readlink) (struct vcache *avc, struct uio *, afs_ucred_t *);
int (*vn_fsync) (struct vcache *avc, afs_ucred_t *);
int (*vn_inactive) (struct vcache *avc, afs_ucred_t *acred);
/* don't set CDirty in here because RPC is called synchronously */
int
afs_symlink(OSI_VC_DECL(adp), char *aname, struct vattr *attrs,
- char *atargetName, afs_ucred_t *acred)
+ char *atargetName, struct vcache **tvcp, afs_ucred_t *acred)
{
afs_uint32 now = 0;
struct vrequest treq;
}
ReleaseWriteLock(&tvc->lock);
ReleaseWriteLock(&afs_xvcache);
- afs_PutVCache(tvc);
+ if (tvcp)
+ *tvcp = tvc;
+ else
+ afs_PutVCache(tvc);
code = 0;
done:
afs_PutFakeStat(&fakestate);
struct vrequest *areq);
extern int afs_symlink(OSI_VC_DECL(adp), char *aname,
struct vattr *attrs, char *atargetName,
- afs_ucred_t *acred);
+ struct vcache **tvcp, afs_ucred_t *acred);
extern int afs_readlink(OSI_VC_DECL(avc), struct uio *auio,
afs_ucred_t *acred);