From: Michael Meffie <mmeffie@sinenomine.net>
Date: Mon, 14 Apr 2014 16:07:53 -0400
Subject: libafs: api to create and free vrequests

Add a pair of functions to allocate and free struct vrequests, which
are to be used to avoid having struct vrequests on the stack.

Reviewed-on: http://gerrit.openafs.org/11074
Reviewed-by: D Brashear <shadow@your-file-system.com>
Tested-by: D Brashear <shadow@your-file-system.com>
(cherry picked from commit 76ad941902c650a4a716168d3cbe68f62aef109f)

Change-Id: I08932256af58aeba31b2d5c11008658c419cf008
Reviewed-on: http://gerrit.openafs.org/11164
Reviewed-by: Perry Ruiter <pruiter@sinenomine.net>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Reviewed-by: Gergely Madarasz <madaraszg@gmail.com>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
(cherry picked from commit 17bf59ae6e426a7fd86f7edda040edb352729d2e)
---
 src/afs/afs_osi_pag.c    | 58 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/afs/afs_prototypes.h |  2 ++
 2 files changed, 60 insertions(+)

diff --git a/src/afs/afs_osi_pag.c b/src/afs/afs_osi_pag.c
index efce229..ea16fe7 100644
--- a/src/afs/afs_osi_pag.c
+++ b/src/afs/afs_osi_pag.c
@@ -487,6 +487,64 @@ afs_InitReq(struct vrequest *av, afs_ucred_t *acred)
     return 0;
 }
 
+/*!
+ * Allocate and setup a vrequest.
+ *
+ * \note The caller must free the allocated vrequest with
+ *       afs_DestroyReq() if this function returns successfully (zero).
+ *
+ * \note The GLOCK must be held on platforms which require the GLOCK
+ *       for osi_AllocSmallSpace() and osi_FreeSmallSpace().
+ *
+ * \param[out] avpp   address of the vrequest pointer
+ * \param[in]  acred  user credentials to setup the vrequest; may be NULL
+ * \return     0 on success
+ */
+int
+afs_CreateReq(struct vrequest **avpp, afs_ucred_t *acred)
+{
+    int code;
+    struct vrequest *treq = NULL;
+
+    if (afs_shuttingdown) {
+	return EIO;
+    }
+    if (!avpp) {
+	return EINVAL;
+    }
+    treq = osi_AllocSmallSpace(sizeof(struct vrequest));
+    if (!treq) {
+	return ENOMEM;
+    }
+    if (!acred) {
+	memset(treq, 0, sizeof(struct vrequest));
+    } else {
+	code = afs_InitReq(treq, acred);
+	if (code != 0) {
+	    osi_FreeSmallSpace(treq);
+	    return code;
+	}
+    }
+    *avpp = treq;
+    return 0;
+}
+
+/*!
+ * Deallocate a vrequest.
+ *
+ * \note The GLOCK must be held on platforms which require the GLOCK
+ *       for osi_FreeSmallSpace().
+ *
+ * \param[in]  av  pointer to the vrequest to free; may be NULL
+ */
+void
+afs_DestroyReq(struct vrequest *av)
+{
+    if (av) {
+	osi_FreeSmallSpace(av);
+    }
+}
+
 #ifndef AFS_LINUX26_ONEGROUP_ENV
 afs_uint32
 afs_get_pag_from_groups(gid_t g0a, gid_t g1a)
diff --git a/src/afs/afs_prototypes.h b/src/afs/afs_prototypes.h
index 3bab010..0b7e180 100644
--- a/src/afs/afs_prototypes.h
+++ b/src/afs/afs_prototypes.h
@@ -599,6 +599,8 @@ extern int AddPag(afs_proc_t *p, afs_int32 aval, afs_ucred_t **credpp);
 extern int AddPag(afs_int32 aval, afs_ucred_t **credpp);
 #endif
 extern int afs_InitReq(struct vrequest *av, afs_ucred_t *acred);
+extern int afs_CreateReq(struct vrequest **avpp, afs_ucred_t *acred);
+extern void afs_DestroyReq(struct vrequest *av);
 extern afs_uint32 afs_get_pag_from_groups(gid_t g0a, gid_t g1a);
 extern void afs_get_groups_from_pag(afs_uint32 pag, gid_t * g0p, gid_t * g1p);
 extern afs_int32 PagInCred(afs_ucred_t *cred);
