+/* __create_vx_info()
+
+ * create the requested context
+ * get(), claim() and hash it */
+
+static struct vx_info * __create_vx_info(int id)
+{
+ struct vx_info *new, *vxi = NULL;
+
+ vxdprintk(VXD_CBIT(xid, 1), "create_vx_info(%d)*", id);
+
+ if (!(new = __alloc_vx_info(id)))
+ return ERR_PTR(-ENOMEM);
+
+ /* required to make dynamic xids unique */
+ spin_lock(&vx_info_hash_lock);
+
+ /* dynamic context requested */
+ if (id == VX_DYNAMIC_ID) {
+#ifdef CONFIG_VSERVER_DYNAMIC_IDS
+ id = __vx_dynamic_id();
+ if (!id) {
+ printk(KERN_ERR "no dynamic context available.\n");
+ vxi = ERR_PTR(-EAGAIN);
+ goto out_unlock;
+ }
+ new->vx_id = id;
+#else
+ printk(KERN_ERR "dynamic contexts disabled.\n");
+ vxi = ERR_PTR(-EINVAL);
+ goto out_unlock;
+#endif
+ }
+ /* static context requested */
+ else if ((vxi = __lookup_vx_info(id))) {
+ vxdprintk(VXD_CBIT(xid, 0),
+ "create_vx_info(%d) = %p (already there)", id, vxi);
+ if (vx_info_flags(vxi, VXF_STATE_SETUP, 0))
+ vxi = ERR_PTR(-EBUSY);
+ else
+ vxi = ERR_PTR(-EEXIST);
+ goto out_unlock;
+ }
+#ifdef CONFIG_VSERVER_DYNAMIC_IDS
+ /* dynamic xid creation blocker */
+ else if (id >= MIN_D_CONTEXT) {
+ vxdprintk(VXD_CBIT(xid, 0),
+ "create_vx_info(%d) (dynamic rejected)", id);
+ vxi = ERR_PTR(-EINVAL);
+ goto out_unlock;
+ }
+#endif
+
+ /* new context */
+ vxdprintk(VXD_CBIT(xid, 0),
+ "create_vx_info(%d) = %p (new)", id, new);
+ claim_vx_info(new, NULL);
+ __hash_vx_info(get_vx_info(new));
+ vxi = new, new = NULL;
+
+out_unlock:
+ spin_unlock(&vx_info_hash_lock);
+ vxh_create_vx_info(IS_ERR(vxi)?NULL:vxi, id);
+ if (new)
+ __dealloc_vx_info(new);
+ return vxi;
+}
+
+
+/* exported stuff */
+
+
+void unhash_vx_info(struct vx_info *vxi)
+{
+ __shutdown_vx_info(vxi);
+ spin_lock(&vx_info_hash_lock);
+ __unhash_vx_info(vxi);
+ spin_unlock(&vx_info_hash_lock);
+ __wakeup_vx_info(vxi);
+}
+
+
+/* lookup_vx_info()
+
+ * search for a vx_info and get() it
+ * negative id means current */
+
+struct vx_info *lookup_vx_info(int id)
+{
+ struct vx_info *vxi = NULL;
+
+ if (id < 0) {
+ vxi = get_vx_info(current->vx_info);
+ } else if (id > 1) {
+ spin_lock(&vx_info_hash_lock);
+ vxi = get_vx_info(__lookup_vx_info(id));
+ spin_unlock(&vx_info_hash_lock);
+ }
+ return vxi;
+}
+
+/* xid_is_hashed()
+
+ * verify that xid is still hashed */
+
+int xid_is_hashed(xid_t xid)
+{
+ int hashed;
+
+ spin_lock(&vx_info_hash_lock);
+ hashed = (__lookup_vx_info(xid) != NULL);
+ spin_unlock(&vx_info_hash_lock);
+ return hashed;
+}
+
+#ifdef CONFIG_VSERVER_LEGACY
+
+struct vx_info *lookup_or_create_vx_info(int id)