Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2079c4aa authored by Ken Cox's avatar Ken Cox Committed by Greg Kroah-Hartman
Browse files

Staging: unisys: visorchipset: Remove filexfer.c



There is not any code using the functionality in filexfer.c so I removed it
and filexfer.h.

Signed-off-by: default avatarKen Cox <jkc@redhat.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent e40d1c8a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@

obj-$(CONFIG_UNISYS_VISORCHIPSET)	+= visorchipset.o

visorchipset-y := visorchipset_main.o controlvm_direct.o file.o filexfer.o \
visorchipset-y := visorchipset_main.o controlvm_direct.o file.o \
			parser.o

ccflags-y += -Idrivers/staging/unisys/include
+0 −506
Original line number Diff line number Diff line
/* filexfer.c
 *
 * Copyright © 2013 - 2013 UNISYS CORPORATION
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
 * NON INFRINGEMENT.  See the GNU General Public License for more
 * details.
 */

/* Code here-in is the "glue" that connects controlvm messages with the
 * sparfilexfer driver, which is used to transfer file contents as payload
 * across the controlvm channel.
 */

#include "globals.h"
#include "controlvm.h"
#include "visorchipset.h"
#include "filexfer.h"

#ifdef ENABLE_SPARFILEXFER /* sparfilexfer kernel module enabled in build */
#include "sparfilexfer.h"

/* Driver-global memory */
static LIST_HEAD(Request_list);	/* list of struct any_request *, via
				 * req_list memb */

/* lock for above pool for allocation of any_request structs, and pool
* name; note that kmem_cache_create requires that we keep the storage
* for the pool name for the life of the pool
 */
static DEFINE_SPINLOCK(Request_list_lock);

static struct kmem_cache *Request_memory_pool;
static const char Request_memory_pool_name[] = "filexfer_request_pool";
size_t Caller_req_context_bytes = 0;	/* passed to filexfer_constructor() */

/* This structure defines a single controlvm GETFILE conversation, which
 * consists of a single controlvm request message and 1 or more controlvm
 * response messages.
 */
struct getfile_request {
	CONTROLVM_MESSAGE_HEADER controlvm_header;
	atomic_t buffers_in_use;
	GET_CONTIGUOUS_CONTROLVM_PAYLOAD_FUNC get_contiguous_controlvm_payload;
	CONTROLVM_RESPOND_WITH_PAYLOAD_FUNC controlvm_respond_with_payload;
};

/* This structure defines a single controlvm PUTFILE conversation, which
 * consists of a single controlvm request with a filename, and additional
 * controlvm messages with file data.
 */
struct putfile_request {
	GET_CONTROLVM_FILEDATA_FUNC get_controlvm_filedata;
	CONTROLVM_RESPOND_FUNC controlvm_end_putFile;
};

/* This structure defines a single file transfer operation, which can either
 * be a GETFILE or PUTFILE.
 */
struct any_request {
	struct list_head req_list;
	ulong2 file_request_number;
	ulong2 data_sequence_number;
	TRANSMITFILE_DUMP_FUNC dump_func;
	BOOL is_get;
	union {
		struct getfile_request get;
		struct putfile_request put;
	};
	/* Size of caller_context_data will be
	 * <Caller_req_context_bytes> bytes.  I aligned this because I
	 * am paranoid about what happens when an arbitrary data
	 * structure with unknown alignment requirements gets copied
	 * here.  I want caller_context_data to be aligned to the
	 * coarsest possible alignment boundary that could be required
	 * for any user data structure.
	 */
	u8 caller_context_data[1] __aligned(sizeof(ulong2));
};

/*
 * Links the any_request into the global list of allocated requests
 * (<Request_list>).
 */
static void
unit_tracking_create(struct list_head *dev_list_link)
{
	unsigned long flags;
	spin_lock_irqsave(&Request_list_lock, flags);
	list_add(dev_list_link, &Request_list);
	spin_unlock_irqrestore(&Request_list_lock, flags);
}

/* Unlinks a any_request from the global list (<Request_list>).
 */
static void
unit_tracking_destroy(struct list_head *dev_list_link)
{
	unsigned long flags;
	spin_lock_irqsave(&Request_list_lock, flags);
	list_del(dev_list_link);
	spin_unlock_irqrestore(&Request_list_lock, flags);
}

/* Allocate memory for and return a new any_request struct, and
 * link it to the global list of outstanding requests.
 */
static struct any_request *
alloc_request(char *fn, int ln)
{
	struct any_request *req = (struct any_request *)
	    (visorchipset_cache_alloc(Request_memory_pool,
				      FALSE,
				      fn, ln));
	if (!req)
		return NULL;
	memset(req, 0, sizeof(struct any_request) + Caller_req_context_bytes);
	unit_tracking_create(&req->req_list);
	return req;
}

/* Book-end for alloc_request().
 */
static void
free_request(struct any_request *req, char *fn, int ln)
{
	unit_tracking_destroy(&req->req_list);
	visorchipset_cache_free(Request_memory_pool, req, fn, ln);
}

/* Constructor for filexfer.o.
 */
int
filexfer_constructor(size_t req_context_bytes)
{
	int rc = -1;

	Caller_req_context_bytes = req_context_bytes;
	Request_memory_pool =
	    kmem_cache_create(Request_memory_pool_name,
			      sizeof(struct any_request) +
			      Caller_req_context_bytes,
			      0, SLAB_HWCACHE_ALIGN, NULL);
	if (!Request_memory_pool) {
		LOGERR("failed to alloc Request_memory_pool");
		rc = -ENOMEM;
		goto Away;
	}
	rc = 0;
Away:
	if (rc < 0) {
		if (Request_memory_pool) {
			kmem_cache_destroy(Request_memory_pool);
			Request_memory_pool = NULL;
		}
	}
	return rc;
}

/* Destructor for filexfer.o.
 */
void
filexfer_destructor(void)
{
	if (Request_memory_pool) {
		kmem_cache_destroy(Request_memory_pool);
		Request_memory_pool = NULL;
	}
}

/* This function will obtain an available chunk from the controlvm payload area,
 * store the size in bytes of the chunk in <actual_size>, and return a pointer
 * to the chunk.  The function is passed to the sparfilexfer driver, which calls
 * it whenever payload space is required to copy file data into.
 */
static void *
get_empty_bucket_for_getfile_data(void *context,
				  ulong min_size, ulong max_size,
				  ulong *actual_size)
{
	void *bucket;
	struct any_request *req = (struct any_request *) context;

	if (!req->is_get) {
		LOGERR("%s - unexpected call", __func__);
		return NULL;
	}
	bucket = (*req->get.get_contiguous_controlvm_payload)
	    (min_size, max_size, actual_size);
	if (bucket != NULL) {
		atomic_inc(&req->get.buffers_in_use);
		DBGINF("%s - sent %lu-byte buffer", __func__, *actual_size);
	}
	return bucket;
}

/* This function will send a controlvm response with data in the payload
 * (whose space was obtained with get_empty_bucket_for_getfile_data).  The
 * function is passed to the sparfilexfer driver, which calls it whenever it
 * wants to send file data back across the controlvm channel.
 */
static int
send_full_getfile_data_bucket(void *context, void *bucket,
			      ulong bucket_actual_size, ulong bucket_used_size)
{
	struct any_request *req = (struct any_request *) context;

	if (!req->is_get) {
		LOGERR("%s - unexpected call", __func__);
		return 0;
	}
	DBGINF("sending buffer for %lu/%lu",
	       bucket_used_size, bucket_actual_size);
	if (!(*req->get.controlvm_respond_with_payload)
	    (&req->get.controlvm_header,
	     req->file_request_number,
	     req->data_sequence_number++,
	     0, bucket, bucket_actual_size, bucket_used_size, TRUE))
		atomic_dec(&req->get.buffers_in_use);
	return 0;
}

/* This function will send a controlvm response indicating the end of a
 * GETFILE transfer.  The function is passed to the sparfilexfer driver.
 */
static void
send_end_of_getfile_data(void *context, int status)
{
	struct any_request *req = (struct any_request *) context;
	if (!req->is_get) {
		LOGERR("%s - unexpected call", __func__);
		return;
	}
	LOGINF("status=%d", status);
	(*req->get.controlvm_respond_with_payload)
	    (&req->get.controlvm_header,
	     req->file_request_number,
	     req->data_sequence_number++, status, NULL, 0, 0, FALSE);
	free_request(req, __FILE__, __LINE__);
	module_put(THIS_MODULE);
}

/* This function supplies data for a PUTFILE transfer.
 * The function is passed to the sparfilexfer driver.
 */
static int
get_putfile_data(void *context, void *pbuf, size_t bufsize,
		 BOOL buf_is_userspace, size_t *bytes_transferred)
{
	struct any_request *req = (struct any_request *) context;
	if (req->is_get) {
		LOGERR("%s - unexpected call", __func__);
		return -1;
	}
	return (*req->put.get_controlvm_filedata) (&req->caller_context_data[0],
						   pbuf, bufsize,
						   buf_is_userspace,
						   bytes_transferred);
}

/* This function is called to indicate the end of a PUTFILE transfer.
 * The function is passed to the sparfilexfer driver.
 */
static void
end_putfile(void *context, int status)
{
	struct any_request *req = (struct any_request *) context;
	if (req->is_get) {
		LOGERR("%s - unexpected call", __func__);
		return;
	}
	(*req->put.controlvm_end_putFile) (&req->caller_context_data[0],
					   status);
	free_request(req, __FILE__, __LINE__);
	module_put(THIS_MODULE);
}

/* Refer to filexfer.h for description. */
BOOL
filexfer_getFile(CONTROLVM_MESSAGE_HEADER *msgHdr,
		 ulong2 file_request_number,
		 uint uplink_index,
		 uint disk_index,
		 char *file_name,
		 GET_CONTIGUOUS_CONTROLVM_PAYLOAD_FUNC
		 get_contiguous_controlvm_payload,
		 CONTROLVM_RESPOND_WITH_PAYLOAD_FUNC
		 controlvm_respond_with_payload,
		 TRANSMITFILE_DUMP_FUNC dump_func)
{
	BOOL use_count_up = FALSE;
	BOOL failed = TRUE;
	struct any_request *req = alloc_request(__FILE__, __LINE__);

	if (!req) {
		LOGERR("allocation of any_request failed");
		goto Away;
	}
	/* We need to increment this module's use count because we're handing
	 * off pointers to functions within this module to be used by
	 * another module.
	 */
	__module_get(THIS_MODULE);
	use_count_up = TRUE;
	req->is_get = TRUE;
	req->file_request_number = file_request_number;
	req->data_sequence_number = 0;
	req->dump_func = dump_func;
	req->get.controlvm_header = *msgHdr;
	atomic_set(&req->get.buffers_in_use, 0);
	req->get.get_contiguous_controlvm_payload =
	    get_contiguous_controlvm_payload;
	req->get.controlvm_respond_with_payload =
	    controlvm_respond_with_payload;
	if (sparfilexfer_local2remote(req,	/* context, passed to
						 * callback funcs */
				      file_name,
				      file_request_number,
				      uplink_index,
				      disk_index,
				      get_empty_bucket_for_getfile_data,
				      send_full_getfile_data_bucket,
				      send_end_of_getfile_data) < 0) {
		LOGERR("sparfilexfer_local2remote failed");
		goto Away;
	}
	failed = FALSE;
Away:
	if (failed) {
		if (use_count_up) {
			module_put(THIS_MODULE);
			use_count_up = FALSE;
		}
		if (req) {
			free_request(req, __FILE__, __LINE__);
			req = NULL;
		}
		return FALSE;
	} else {
		return TRUE;
		/* success; send callbacks will be called for responses */
	}
}

/* Refer to filexfer.h for description. */
void *
filexfer_putFile(CONTROLVM_MESSAGE_HEADER *msgHdr,
		 ulong2 file_request_number,
		 uint uplink_index,
		 uint disk_index,
		 char *file_name,
		 TRANSMITFILE_INIT_CONTEXT_FUNC init_context,
		 GET_CONTROLVM_FILEDATA_FUNC get_controlvm_filedata,
		 CONTROLVM_RESPOND_FUNC controlvm_end_putFile,
		 TRANSMITFILE_DUMP_FUNC dump_func)
{
	BOOL use_count_up = FALSE;
	BOOL failed = TRUE;
	struct any_request *req = alloc_request(__FILE__, __LINE__);
	void *caller_ctx = NULL;

	if (!req) {
		LOGERR("allocation of any_request failed");
		goto Away;
	}
	caller_ctx = (void *) (&(req->caller_context_data[0]));
	/* We need to increment this module's use count because we're handing
	 * off pointers to functions within this module to be used by
	 * another module.
	 */
	__module_get(THIS_MODULE);
	use_count_up = TRUE;
	req->is_get = FALSE;
	req->file_request_number = file_request_number;
	req->data_sequence_number = 0;
	req->dump_func = dump_func;
	req->put.get_controlvm_filedata = get_controlvm_filedata;
	req->put.controlvm_end_putFile = controlvm_end_putFile;
	(*init_context) (caller_ctx, msgHdr, file_request_number);
	if (sparfilexfer_remote2local(req,	/* context, passed to
						 * callback funcs */
				      file_name,
				      file_request_number,
				      uplink_index,
				      disk_index,
				      get_putfile_data, end_putfile) < 0) {
		LOGERR("sparfilexfer_remote2local failed");
		goto Away;
	}
	failed = FALSE;
Away:
	if (failed) {
		if (use_count_up) {
			module_put(THIS_MODULE);
			use_count_up = FALSE;
		}
		if (req) {
			free_request(req, __FILE__, __LINE__);
			req = NULL;
		}
		return NULL;
	} else {
		return caller_ctx;
		/* success; callbacks will be called for responses */
	}
}

static void
dump_get_request(struct seq_file *f, struct getfile_request *getreq)
{
	seq_printf(f, "  buffers_in_use=%d\n",
		   atomic_read(&getreq->buffers_in_use));
}

static void
dump_put_request(struct seq_file *f, struct putfile_request *putreq)
{
}

static void
dump_request(struct seq_file *f, struct any_request *req)
{
	seq_printf(f, "* %s id=%llu seq=%llu\n",
		   ((req->is_get) ? "Get" : "Put"),
		   req->file_request_number, req->data_sequence_number);
	if (req->is_get)
		dump_get_request(f, &req->get);
	else
		dump_put_request(f, &req->put);
	if (req->dump_func)
		(*req->dump_func) (f, &(req->caller_context_data[0]), "  ");
}

void
filexfer_dump(struct seq_file *f)
{
	ulong flags;
	struct list_head *entry;

	seq_puts(f, "Outstanding TRANSMIT_FILE requests:\n");
	spin_lock_irqsave(&Request_list_lock, flags);
	list_for_each(entry, &Request_list) {
		struct any_request *req;
		req = list_entry(entry, struct any_request, req_list);
		dump_request(f, req);
	}
	spin_unlock_irqrestore(&Request_list_lock, flags);
}

#else				/* ifdef ENABLE_SPARFILEXFER */
int
filexfer_constructor(size_t req_context_bytes)
{
	return 0;		/* success */
}

void
filexfer_destructor(void)
{
}

BOOL
filexfer_getFile(CONTROLVM_MESSAGE_HEADER *msgHdr,
		 u64 file_request_number,
		 uint uplink_index,
		 uint disk_index,
		 char *file_name,
		 GET_CONTIGUOUS_CONTROLVM_PAYLOAD_FUNC
		 get_contiguous_controlvm_payload,
		 CONTROLVM_RESPOND_WITH_PAYLOAD_FUNC
		 controlvm_respond_with_payload,
		 TRANSMITFILE_DUMP_FUNC dump_func)
{
	/* since no sparfilexfer module exists to call, we just fail */
	return FALSE;
}

void *
filexfer_putFile(CONTROLVM_MESSAGE_HEADER *msgHdr,
		 u64 file_request_number,
		 uint uplink_index,
		 uint disk_index,
		 char *file_name,
		 TRANSMITFILE_INIT_CONTEXT_FUNC init_context,
		 GET_CONTROLVM_FILEDATA_FUNC get_controlvm_filedata,
		 CONTROLVM_RESPOND_FUNC controlvm_end_putFile,
		 TRANSMITFILE_DUMP_FUNC dump_func)
{
	/* since no sparfilexfer module exists to call, we just fail */
	return NULL;
}

void
filexfer_dump(struct seq_file *f)
{
}

#endif				/* ifdef ENABLE_SPARFILEXFER */
+0 −147
Original line number Diff line number Diff line
/* filexfer.h
 *
 * Copyright © 2013 - 2013 UNISYS CORPORATION
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
 * NON INFRINGEMENT.  See the GNU General Public License for more
 * details.
 */

/* This header file defines the interface that filexfer.c provides to other
 * code in the visorchipset driver.
 */

#ifndef __FILEXFER_H__
#define __FILEXFER_H__

#include "globals.h"
#include "controlvmchannel.h"
#include <linux/seq_file.h>

typedef void *(*GET_CONTIGUOUS_CONTROLVM_PAYLOAD_FUNC) (ulong min_size,
							ulong max_size,
							ulong *actual_size);

typedef BOOL
(*CONTROLVM_RESPOND_WITH_PAYLOAD_FUNC) (CONTROLVM_MESSAGE_HEADER *msgHdr,
					u64 fileRequestNumber,
					u64 dataSequenceNumber,
					int response,
					void *bucket, ulong payloadChunkSize,
					ulong payloadUsedBytes, BOOL partial);

typedef void
(*TRANSMITFILE_INIT_CONTEXT_FUNC)(void *ctx,
				  const CONTROLVM_MESSAGE_HEADER *hdr,
				  u64 file_request_number);
typedef void (*TRANSMITFILE_DUMP_FUNC) (struct seq_file *f, void *ctx,
					const char *pfx);
typedef int (*GET_CONTROLVM_FILEDATA_FUNC) (void *ctx,
					    void *buf, size_t bufsize,
					    BOOL buf_is_userspace,
					    size_t *bytes_transferred);
typedef void (*CONTROLVM_RESPOND_FUNC) (void *ctx, int response);

/* Call once to initialize filexfer.o.
 * req_context_bytes number of bytes the caller needs to keep track of each file
 * transfer conversation.  The <ctx_init_value> passed to filexfer_putFile() is
 * assumed to be this many bytes in size.  Code within filexfer.o will copy this
 * into a dynamically-allocated area, and pass back a pointer to that area in
 * callback functions.
 */
int filexfer_constructor(size_t req_context_bytes);

/* Call once to clean up filexfer.o */
void filexfer_destructor(void);

/* Call this to dump diagnostic info about all outstanding getFiles/putFiles */
void filexfer_dump(struct seq_file *f);

/* Call to transfer a file from the local filesystem (i.e., from the environment
 * where this driver is running) across the controlvm channel to a remote
 * environment.  1 or more controlvm responses will be sent as a result, each
 * of which whose payload contains file data.  Only the last controlvm message
 * will have Flags.partialCompletion==0.
 *
 *   msgHdr      the controlvm message header of the GETFILE request which
 *               we just received
 *   file_request_number  this is all data from the GETFILE request that
 *   uplink_index         define which file is to be transferred
 *   disk_index
 *   file_name
 *   get_contiguous_controlvm_payload  function to call when space is needed
 *                                     in the payload area
 *   controlvm_respond_with_payload    function to call to send each controlvm
 *                                     response containing file data as the
 *                                     payload; returns FALSE only if the
 *				       payload buffer was freed inline
 *   dump_func                         function to dump context data in
 *                                     human-readable format
 *
 *  Returns TRUE iff the file transfer request has been successfully initiated,
 *  or FALSE to indicate failure.
 */
BOOL
filexfer_getFile(CONTROLVM_MESSAGE_HEADER *msgHdr,
		 u64 file_request_number,
		 uint uplink_index,
		 uint disk_index,
		 char *file_name,
		 GET_CONTIGUOUS_CONTROLVM_PAYLOAD_FUNC
		 get_contiguous_controlvm_payload,
		 CONTROLVM_RESPOND_WITH_PAYLOAD_FUNC
		 controlvm_respond_with_payload,
		 TRANSMITFILE_DUMP_FUNC dump_func);

/* Call to create a file in the local filesystem (i.e., in the environment
 * where this driver is running) from data received as payload in
 * controlvm channel messages from a remote environment.  1 or more controlvm
 * messages will be received for this transfer, and only the last will have
 * Flags.partialCompletion==0.
 *
 *   msgHdr      the controlvm message header of the PUTFILE request which
 *               we just received
 *   file_request_number  this is all data from the PUTFILE request that
 *   uplink_index         define which file is to be created in the local
 *   disk_index           filesystem
 *   file_name
 *   init_context         function to call to initialize the
 *                        <req_context_bytes>-sized storage area returned by
 *                        this func; note that it would NOT be sufficient to
 *                        allow the caller to initialize this upon return, as
 *                        the the other user-supplied callbacks might have
 *                        already been called by then
 *   get_controlvm_filedata   function to call to obtain more data for the file
 *                            being written; refer to get_controlvm_filedata()
 *                            in visorchipset_main.c for a complete description
 *                            of parameters
 *   controlvm_end_putFile    function to call to indicate that creation of the
 *                            local file has completed;  set <response> to a
 *                            negative value to indicate an error
 *   dump_func                function to dump context data in human-readable
 *                            format
 *
 *  Returns a pointer to a dynamically-allocated storage area of size
 *  <req_context_bytes> which the caller can use, or NULL for error.  The
 *  caller should NEVER free the returned pointer, but should expect to receive
 *  it as the <ctx> argument when callback functions are called.
 */
void *filexfer_putFile(CONTROLVM_MESSAGE_HEADER *msgHdr,
		       u64 file_request_number,
		       uint uplink_index,
		       uint disk_index,
		       char *file_name,
		       TRANSMITFILE_INIT_CONTEXT_FUNC init_context,
		       GET_CONTROLVM_FILEDATA_FUNC get_controlvm_filedata,
		       CONTROLVM_RESPOND_FUNC controlvm_end_putFile,
		       TRANSMITFILE_DUMP_FUNC dump_func);

#endif
+0 −8
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@
#include "uisutils.h"
#include "controlvmcompletionstatus.h"
#include "guestlinuxdebug.h"
#include "filexfer.h"

#include <linux/nls.h>
#include <linux/netdevice.h>
@@ -2773,12 +2772,6 @@ visorchipset_init(void)
			ProcDir, &parahotplug_proc_fops);
	memset(&g_DelDumpMsgHdr, 0, sizeof(CONTROLVM_MESSAGE_HEADER));

	if (filexfer_constructor(sizeof(struct putfile_request)) < 0) {
		ERRDRV("filexfer_constructor failed: (status=-1)\n");
		POSTCODE_LINUX_2(CHIPSET_INIT_FAILURE_PC, DIAG_SEVERITY_ERR);
		rc = -1;
		goto Away;
	}
	Putfile_buffer_list_pool =
	    kmem_cache_create(Putfile_buffer_list_pool_name,
			      sizeof(struct putfile_buffer_entry),
@@ -2862,7 +2855,6 @@ visorchipset_exit(void)
		kmem_cache_destroy(Putfile_buffer_list_pool);
		Putfile_buffer_list_pool = NULL;
	}
	filexfer_destructor();
	if (ControlVmObject) {
		visor_proc_DestroyObject(ControlVmObject);
		ControlVmObject = NULL;