afs: refactor PNewStatMount and PFlushMount
[openafs.git] / src / afs / afs_pioctl.c
index 4a705cc..66c7f12 100644 (file)
@@ -312,7 +312,7 @@ DECL_PIOCTL(PNFSNukeCreds);
 DECL_PIOCTL(PNewUuid);
 DECL_PIOCTL(PPrecache);
 DECL_PIOCTL(PGetPAG);
-#if defined(AFS_CACHE_BYPASS) && defined(AFS_LINUX24_ENV)
+#if defined(AFS_CACHE_BYPASS) && defined(AFS_LINUX_ENV)
 DECL_PIOCTL(PSetCachingThreshold);
 #endif
 
@@ -436,7 +436,7 @@ static pioctlFunction CpioctlSw[] = {
 static pioctlFunction OpioctlSw[]  = {
     PBogus,                    /* 0 */
     PNFSNukeCreds,             /* 1 -- nuke all creds for NFS client */
-#if defined(AFS_CACHE_BYPASS) && defined(AFS_LINUX24_ENV)
+#if defined(AFS_CACHE_BYPASS) && defined(AFS_LINUX_ENV)
     PSetCachingThreshold        /* 2 -- get/set cache-bypass size threshold */
 #else
     PNoop                       /* 2 -- get/set cache-bypass size threshold */
@@ -708,7 +708,7 @@ afs_xioctl(struct afs_ioctl_sys *uap, rval_t *rvp)
 
     return (code);
 }
-#elif defined(AFS_LINUX22_ENV)
+#elif defined(AFS_LINUX_ENV)
 struct afs_ioctl_sys {
     unsigned int com;
     unsigned long arg;
@@ -1019,7 +1019,7 @@ afs_pioctl(afs_proc_t *p, void *args, int *retval)
 #endif
 
 /* macro to avoid adding any more #ifdef's to pioctl code. */
-#if defined(AFS_LINUX22_ENV) || defined(AFS_AIX41_ENV)
+#if defined(AFS_LINUX_ENV) || defined(AFS_AIX41_ENV)
 #define PIOCTL_FREE_CRED() crfree(credp)
 #else
 #define PIOCTL_FREE_CRED()
@@ -1045,7 +1045,7 @@ afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
 #ifdef AFS_NEED_CLIENTCONTEXT
     afs_ucred_t *tmpcred = NULL;
 #endif
-#if defined(AFS_NEED_CLIENTCONTEXT) || defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+#if defined(AFS_NEED_CLIENTCONTEXT) || defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
     afs_ucred_t *foreigncreds = NULL;
 #endif
     afs_int32 code = 0;
@@ -1053,7 +1053,7 @@ afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
 #ifdef AFS_AIX41_ENV
     struct ucred *credp = crref();     /* don't free until done! */
 #endif
-#ifdef AFS_LINUX22_ENV
+#ifdef AFS_LINUX_ENV
     cred_t *credp = crref();   /* don't free until done! */
     struct dentry *dp;
 #endif
@@ -1071,7 +1071,7 @@ afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
     }
     if ((com & 0xff) == PSetClientContext) {
 #ifdef AFS_NEED_CLIENTCONTEXT
-#if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
+#if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX_ENV)
        code = HandleClientContext(&data, &com, &foreigncreds, credp);
 #else
        code = HandleClientContext(&data, &com, &foreigncreds, osi_curcred());
@@ -1101,7 +1101,7 @@ afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
         * like afs_osi_suser(cred) which, I think, is better since it
         * generalizes and supports multi cred environments...
         */
-#if defined(AFS_SUN5_ENV) || defined(AFS_LINUX22_ENV)
+#if defined(AFS_SUN5_ENV) || defined(AFS_LINUX_ENV)
        tmpcred = credp;
        credp = foreigncreds;
 #elif defined(AFS_AIX41_ENV)
@@ -1124,7 +1124,7 @@ afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
     if ((com & 0xff00) >> 8 == 'V' && (com & 0xff) == 15) {
        /* special case prefetch so entire pathname eval occurs in helper process.
         * otherwise, the pioctl call is essentially useless */
-#if    defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+#if    defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
        code =
            Prefetch(path, &data, follow,
                     foreigncreds ? foreigncreds : credp);
@@ -1144,13 +1144,13 @@ afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
            lookupname(path, USR, follow, NULL, &vp,
                       foreigncreds ? foreigncreds : credp);
 #else
-#ifdef AFS_LINUX22_ENV
+#ifdef AFS_LINUX_ENV
        code = gop_lookupname_user(path, AFS_UIOUSER, follow, &dp);
        if (!code)
            vp = (struct vnode *)dp->d_inode;
 #else
        code = gop_lookupname_user(path, AFS_UIOUSER, follow, &vp);
-#endif /* AFS_LINUX22_ENV */
+#endif /* AFS_LINUX_ENV */
 #endif /* AFS_AIX41_ENV */
        AFS_GLOCK();
        if (code) {
@@ -1211,7 +1211,7 @@ afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
            credp = OSI_GET_CURRENT_CRED();
            code = afs_HandlePioctl(vp, com, &data, follow, &credp);
        }
-#elif defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+#elif defined(AFS_LINUX_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
        code = afs_HandlePioctl(vp, com, &data, follow, &credp);
 #elif defined(UKERNEL)
        code = afs_HandlePioctl(vp, com, &data, follow,
@@ -1237,7 +1237,7 @@ afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
        set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
 #elif  defined(AFS_SGI_ENV)
        OSI_SET_CURRENT_CRED(tmpcred);  /* restore original credentials */
-#elif  defined(AFS_SUN5_ENV) || defined(AFS_LINUX22_ENV)
+#elif  defined(AFS_SUN5_ENV) || defined(AFS_LINUX_ENV)
        credp = tmpcred;                /* restore original credentials */
 #else
        osi_curcred() = tmpcred;        /* restore original credentials */
@@ -1247,7 +1247,7 @@ afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
     }
 #endif /* AFS_NEED_CLIENTCONTEXT */
     if (vp) {
-#ifdef AFS_LINUX22_ENV
+#ifdef AFS_LINUX_ENV
        /*
         * Holding the global lock when calling dput can cause a deadlock
         * when the kernel calls back into afs_dentry_iput
@@ -1830,7 +1830,7 @@ _settok_tokenCell(char *cellName, int *cellNum, int *primary) {
 }
 
 
-#if defined(AFS_LINUX26_ENV)
+#if defined(AFS_LINUX_ENV)
 static_inline int
 _settok_setParentPag(afs_ucred_t **cred)
 {
@@ -2188,6 +2188,73 @@ DECL_PIOCTL(PFlush)
 }
 
 /*!
+ * Lookup name in the directory associated with given vcache.
+ *
+ * \param[in]  avc     vcache associated with directory
+ * \param[in]  areq    request to be passed on
+ * \param[in]  aname   name to be searched
+ * \param[out] asys    resolved name (replace @sys by system type)
+ * \param[out] afid    fid associated with aname
+ *
+ * \return 0 on success; non-zero otherwise.
+ *
+ * \notes  The caller must free asys->name (checking if asys->allocked == 1).
+ */
+static int
+afs_LookupName(struct vcache *avc, struct vrequest *areq, char *aname,
+              struct sysname_info *asys, struct VenusFid *afid)
+{
+    int code;
+    struct dcache *tdc;
+    afs_size_t offset, len;
+
+    memset(asys, 0, sizeof(*asys));
+    memset(afid, 0, sizeof(*afid));
+
+    if (!avc || !areq || !aname || !asys || !afid) {
+       afs_warn("afs: Internal error, bad args to afs_LookupName: %p, %p, %p, "
+                "%p, %p.\n", avc, areq, aname, asys, afid);
+       code = EIO;
+       goto done;
+    }
+
+    /* check if vcache is up to date */
+    code = afs_VerifyVCache(avc, areq);
+    if (code != 0) {
+       goto done;
+    }
+
+    /* must be a directory */
+    if (vType(avc) != VDIR) {
+       code = ENOTDIR;
+       goto done;
+    }
+
+    tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1);
+    if (!tdc) {
+       code = EIO;
+       goto done;
+    }
+
+    /* if @sys is present, replace it by the machine's system type */
+    Check_AtSys(avc, aname, asys, areq);
+    ObtainReadLock(&tdc->lock);
+
+    do {
+       /*
+        * Lookup name in the appropriate directory. If name is not found, try
+        * again with the next sysname from the @sys list.
+        */
+       code = afs_dir_Lookup(tdc, asys->name, &afid->Fid);
+    } while (code == ENOENT && Next_AtSys(avc, areq, asys));
+
+    ReleaseReadLock(&tdc->lock);
+    afs_PutDCache(tdc);
+ done:
+    return code;
+}
+
+/*!
  * VIOC_AFS_STAT_MT_PT (29) - Stat mount point
  *
  * \ingroup pioctl
@@ -2208,40 +2275,26 @@ DECL_PIOCTL(PNewStatMount)
 {
     afs_int32 code;
     struct vcache *tvc;
-    struct dcache *tdc;
     struct VenusFid tfid;
     char *bufp;
     char *name;
     struct sysname_info sysState;
-    afs_size_t offset, len;
 
     AFS_STATCNT(PNewStatMount);
+    memset(&sysState, 0, sizeof(sysState));
+
     if (!avc)
        return EINVAL;
 
     if (afs_pd_getStringPtr(ain, &name) != 0)
        return EINVAL;
 
-    code = afs_VerifyVCache(avc, areq);
-    if (code)
-       return code;
-    if (vType(avc) != VDIR) {
-       return ENOTDIR;
-    }
-    tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
-    if (!tdc)
-       return EIO;
-    Check_AtSys(avc, name, &sysState, areq);
-    ObtainReadLock(&tdc->lock);
-    do {
-       code = afs_dir_Lookup(tdc, sysState.name, &tfid.Fid);
-    } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
-    ReleaseReadLock(&tdc->lock);
-    afs_PutDCache(tdc);                /* we're done with the data */
-    bufp = sysState.name;
+    code = afs_LookupName(avc, areq, name, &sysState, &tfid);
     if (code) {
        goto out;
     }
+
+    bufp = sysState.name;
     tfid.Cell = avc->f.fid.Cell;
     tfid.Fid.Volume = avc->f.fid.Fid.Volume;
     if (!tfid.Fid.Unique && (avc->f.states & CForeign)) {
@@ -2276,7 +2329,7 @@ DECL_PIOCTL(PNewStatMount)
     afs_PutVCache(tvc);
   out:
     if (sysState.allocked)
-       osi_FreeLargeSpace(bufp);
+       osi_FreeLargeSpace(sysState.name);
     return code;
 }
 
@@ -4614,7 +4667,7 @@ HandleClientContext(struct afs_ioctl *ablob, int *com,
 #ifdef AFS_AIX51_ENV
     newcred->cr_groupset.gs_union.un_groups[0] = g0;
     newcred->cr_groupset.gs_union.un_groups[1] = g1;
-#elif defined(AFS_LINUX26_ENV)
+#elif defined(AFS_LINUX_ENV)
 # ifdef AFS_PAG_ONEGROUP_ENV
     afs_set_cr_group_info(newcred, groups_alloc(1)); /* nothing sets this */
     l = (((g0-0x3f00) & 0x3fff) << 14) | ((g1-0x3f00) & 0x3fff);
@@ -4641,8 +4694,8 @@ HandleClientContext(struct afs_ioctl *ablob, int *com,
 #endif
 #ifdef AFS_AIX_ENV
     newcred->cr_ngrps = 2;
-#elif !defined(AFS_LINUX26_ENV) && !defined(AFS_SUN510_ENV)
-# if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_FBSD_ENV)
+#elif !defined(AFS_LINUX_ENV) && !defined(AFS_SUN510_ENV)
+# if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_LINUX_ENV) || defined(AFS_FBSD_ENV)
     newcred->cr_ngroups = 2;
 # else
     for (i = 2; i < NGROUPS; i++)
@@ -4824,40 +4877,26 @@ DECL_PIOCTL(PFlushMount)
 {
     afs_int32 code;
     struct vcache *tvc;
-    struct dcache *tdc;
     struct VenusFid tfid;
     char *bufp;
     char *mount;
     struct sysname_info sysState;
-    afs_size_t offset, len;
 
     AFS_STATCNT(PFlushMount);
+    memset(&sysState, 0, sizeof(sysState));
+
     if (!avc)
        return EINVAL;
 
     if (afs_pd_getStringPtr(ain, &mount) != 0)
        return EINVAL;
 
-    code = afs_VerifyVCache(avc, areq);
-    if (code)
-       return code;
-    if (vType(avc) != VDIR) {
-       return ENOTDIR;
-    }
-    tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
-    if (!tdc)
-       return EIO;
-    Check_AtSys(avc, mount, &sysState, areq);
-    ObtainReadLock(&tdc->lock);
-    do {
-       code = afs_dir_Lookup(tdc, sysState.name, &tfid.Fid);
-    } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
-    ReleaseReadLock(&tdc->lock);
-    afs_PutDCache(tdc);                /* we're done with the data */
-    bufp = sysState.name;
+    code = afs_LookupName(avc, areq, mount, &sysState, &tfid);
     if (code) {
        goto out;
     }
+
+    bufp = sysState.name;
     tfid.Cell = avc->f.fid.Cell;
     tfid.Fid.Volume = avc->f.fid.Fid.Volume;
     if (!tfid.Fid.Unique && (avc->f.states & CForeign)) {
@@ -4887,7 +4926,7 @@ DECL_PIOCTL(PFlushMount)
     afs_PutVCache(tvc);
   out:
     if (sysState.allocked)
-       osi_FreeLargeSpace(bufp);
+       osi_FreeLargeSpace(sysState.name);
     return code;
 }
 
@@ -5124,7 +5163,7 @@ DECL_PIOCTL(PNewUuid)
     return 0;
 }
 
-#if defined(AFS_CACHE_BYPASS) && defined(AFS_LINUX24_ENV)
+#if defined(AFS_CACHE_BYPASS) && defined(AFS_LINUX_ENV)
 
 DECL_PIOCTL(PSetCachingThreshold)
 {