Support for changes to OS X Mavericks VNOP_SYMLINK() function.
authorKen Hornstein <kenh@cmf.nrl.navy.mil>
Wed, 20 Nov 2013 18:37:52 +0000 (13:37 -0500)
committerDerrick Brashear <shadow@your-file-system.com>
Thu, 21 Nov 2013 22:15:27 +0000 (14:15 -0800)
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

Change-Id: I33b2f51cd10f76689eb9868eb05800ab493087c4
Reviewed-on: http://gerrit.openafs.org/10474
Reviewed-by: Derrick Brashear <shadow@your-file-system.com>
Tested-by: BuildBot <buildbot@rampaginggeek.com>

13 files changed:
src/afs/AIX/osi_vnodeops.c
src/afs/DARWIN/osi_vnodeops.c
src/afs/FBSD/osi_vnodeops.c
src/afs/HPUX/osi_vnodeops.c
src/afs/LINUX/osi_vnodeops.c
src/afs/LINUX24/osi_vnodeops.c
src/afs/NBSD/osi_vnodeops.c
src/afs/OBSD/osi_vnodeops.c
src/afs/SOLARIS/osi_vnodeops.c
src/afs/UKERNEL/afs_usrops.c
src/afs/UKERNEL/sysincludes.h
src/afs/VNOPS/afs_vnop_symlink.c
src/afs/afs_prototypes.h

index 0e40001..b86347e 100644 (file)
@@ -1420,7 +1420,7 @@ afs_gn_symlink(struct vnode *vp,
     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);
index 421215a..d49c96d 100644 (file)
@@ -1655,19 +1655,25 @@ afs_vop_symlink(ap)
                                 * } */ *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;
 }
 
index 9797249..024e2d1 100644 (file)
@@ -1365,7 +1365,8 @@ afs_vop_symlink(struct vop_symlink_args *ap)
     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) {
index f113596..dd644fe 100644 (file)
@@ -502,7 +502,7 @@ mp_afs_symlink(struct vnode *adp, char *aname, struct vattr *attrs,
     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);
 }
index 2a29625..28841c8 100644 (file)
@@ -1596,7 +1596,8 @@ afs_linux_symlink(struct inode *dip, struct dentry *dp, const char *target)
 
     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);
index 4e00559..cfbcca3 100644 (file)
@@ -1431,7 +1431,8 @@ afs_linux_symlink(struct inode *dip, struct dentry *dp, const char *target)
 
     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);
index 4c172aa..b4899dc 100644 (file)
@@ -1076,7 +1076,7 @@ afs_nbsd_symlink(void *v)
     name = cnstrdup(cnp);
     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);
     if (code == 0) {
        code = afs_lookup(VTOAFS(dvp), name, &vcp, cnp->cn_cred);
index d3b85fd..022504e 100644 (file)
@@ -845,7 +845,8 @@ afs_obsd_symlink(void *v)
     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();
index 9f99157..55415ff 100644 (file)
@@ -1622,7 +1622,7 @@ gafs_symlink(struct vcache *adp, char *aname, struct vattr *attrs,
     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);
 }
index f6195b9..e0ad0bb 100644 (file)
@@ -3059,7 +3059,8 @@ uafs_symlink_r(char *target, char *source)
     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;
index e401956..38904cc 100644 (file)
@@ -1252,7 +1252,7 @@ struct usr_vnodeops {
     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);
index 13591ce..dfb9e4c 100644 (file)
@@ -66,7 +66,7 @@ afs_DisconCreateSymlink(struct vcache *avc, char *aname,
 /* 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;
@@ -284,7 +284,10 @@ afs_symlink(OSI_VC_DECL(adp), char *aname, struct vattr *attrs,
     }
     ReleaseWriteLock(&tvc->lock);
     ReleaseWriteLock(&afs_xvcache);
-    afs_PutVCache(tvc);
+    if (tvcp)
+       *tvcp = tvc;
+    else
+       afs_PutVCache(tvc);
     code = 0;
   done:
     afs_PutFakeStat(&fakestate);
index f98aef2..ae8a3b1 100644 (file)
@@ -1327,7 +1327,7 @@ extern int afs_UFSHandleLink(struct vcache *avc,
                             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);