[PVFS2-CVS]
commit by neill in pvfs2-1/src/apps/kernel/linux: module.mk.in
mount_pvfs2.sh pvfs2-client-core.c pvfs2-client.c umount_pvfs2.sh
CVS commit program
cvs at parl.clemson.edu
Tue May 25 18:38:48 EDT 2004
Update of /projects/cvsroot/pvfs2-1/src/apps/kernel/linux
In directory parlweb:/tmp/cvs-serv5496/src/apps/kernel/linux
Added Files:
module.mk.in mount_pvfs2.sh pvfs2-client-core.c pvfs2-client.c
umount_pvfs2.sh
Log Message:
- initial addition of linux kernel 2.4.x support code and build requirements
(thanks to Murali for working on a prototype and reviewing the merge)
--- /dev/null 2003-01-30 05:24:37.000000000 -0500
+++ module.mk.in 2004-05-25 17:38:48.000000000 -0400
@@ -0,0 +1,13 @@
+DIR := src/apps/kernel/linux
+
+KERNAPPSRC += \
+ $(DIR)/pvfs2-client-core.c \
+ $(DIR)/pvfs2-threaded-client-core.c \
+ $(DIR)/pvfs2-client.c
+
+# get kernel interface defines, and sysint client.h
+MODCFLAGS_$(DIR)/pvfs2-client-core.c = \
+ -I$(srcdir)/src/kernel/linux-2.6
+
+MODCFLAGS_$(DIR)/pvfs2-threaded-client-core.c = \
+ -I$(srcdir)/src/kernel/linux-2.6
--- /dev/null 2003-01-30 05:24:37.000000000 -0500
+++ mount_pvfs2.sh 2004-05-25 17:38:48.000000000 -0400
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+if [ "`echo $PATH | grep -c /usr/src/modtools/sbin`" = "0" ]; then
+ echo "Loading up bashrc to get latest mod-tools"
+ . ~/.bashrc
+fi
+
+if [ "`lsmod | grep -c pvfs2`" = "0" ]; then
+ echo "Loading the pvfs2 module"
+ insmod ../../../../src/kernel/linux-2.6/pvfs2.ko $1
+fi
+
+CUR_DEV="pvfs2-flow"
+for f in `cat /proc/devices | grep pvfs2 | awk '{print $1}'`; do
+ if [ ! -c /dev/$CUR_DEV ]; then
+ echo "Creating device file /dev/$CUR_DEV with major number $f"
+ mknod /dev/$CUR_DEV c $f 0 -m 666
+ fi
+ CUR_DEV="pvfs2-req"
+done
+
+if [ ! -d /tmp/mnt ]; then
+ echo "Creating /tmp/mnt"
+ mkdir /tmp/mnt
+fi
+
+echo "Starting pvfs2-client"
+./pvfs2-client -p ./pvfs2-client-core
+
+if [ "`mount | grep -c pvfs2`" = "0" ]; then
+ echo "Mounting pvfs2 on /tmp/mnt"
+# mount -t pvfs2 pvfs2 /tmp/mnt -o coll_id=9,root_handle=1048576
+ mount -t pvfs2 tcp://lain.mcs.anl.gov:3334/pvfs2-fs /tmp/mnt
+else
+ echo "Uh...I think pvfs2 is already mounted."
+fi
+
+
--- /dev/null 2003-01-30 05:24:37.000000000 -0500
+++ pvfs2-client-core.c 2004-05-25 17:38:48.000000000 -0400
@@ -0,0 +1,1413 @@
+/*
+ * (C) 2001 Clemson University and The University of Chicago
+ *
+ * See COPYING in top-level directory.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <assert.h>
+#include <errno.h>
+#include <sys/resource.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#include "pvfs2.h"
+#include "gossip.h"
+#include "pint-dev.h"
+#include "job.h"
+#include "acache.h"
+#include "pint-dev-shared.h"
+#include "pvfs2-dev-proto.h"
+#include "pvfs2-util.h"
+#include "pint-bucket.h"
+#include "pvfs2-sysint.h"
+
+#ifdef USE_MMAP_RA_CACHE
+#include "mmap-ra-cache.h"
+#endif
+
+/*
+ an arbitrary limit to the max number of items
+ we can write into the device file as a response
+*/
+#define MAX_LIST_SIZE 32
+
+#define MAX_NUM_UNEXPECTED 10
+
+/*
+ the block size to report in statfs as the blocksize (i.e. the
+ optimal i/o transfer size); regardless of this value, the fragment
+ size (underlying fs block size) in the kernel is fixed at 1024
+*/
+#define STATFS_DEFAULT_BLOCKSIZE PVFS2_BUFMAP_DEFAULT_DESC_SIZE
+
+/* small default attribute cache timeout; effectively disabled */
+#define ACACHE_TIMEOUT_MS 1
+
+/*
+ this client core *requires* pthreads now, regardless of if the pvfs2
+ system interface has threading enabled or not. we need it for async
+ remounts on restart to retrieve our dynamic mount information (if
+ any) from the kernel, which means we call a blocking ioctl that must
+ be serviced by our regular handlers. to do both, we use a thread
+ for the blocking ioctl.
+*/
+static pthread_t remount_thread;
+static pthread_mutex_t remount_mutex = PTHREAD_MUTEX_INITIALIZER;
+static int remount_complete = 0;
+
+void *exec_remount(void *ptr)
+{
+ int ret = 0;
+
+ pthread_mutex_lock(&remount_mutex);
+ /*
+ when the remount mutex is unlocked, tell the kernel to remount
+ any file systems that may have been mounted previously, which
+ will fill in our dynamic mount information by triggering mount
+ upcalls for each fs mounted by the kernel at this point
+ */
+ ret = PINT_dev_remount();
+ if (ret)
+ {
+ gossip_err("*** Failed to remount filesystems!\n");
+ }
+ pthread_mutex_unlock(&remount_mutex);
+ remount_complete = 1;
+ return (void *)0;
+}
+
+/* used for generating unique dynamic mount point names */
+static int dynamic_mount_id = 1;
+
+
+static int service_lookup_request(
+ pvfs2_upcall_t *in_upcall,
+ pvfs2_downcall_t *out_downcall)
+{
+ int ret = 1;
+ PVFS_sysresp_lookup response;
+ PVFS_object_ref parent_refn;
+
+ if (in_upcall && out_downcall)
+ {
+ memset(&response,0,sizeof(PVFS_sysresp_lookup));
+ memset(out_downcall,0,sizeof(pvfs2_downcall_t));
+
+ gossip_debug(
+ GOSSIP_CLIENT_DEBUG,
+ "Got a lookup request for %s (fsid %d | parent %Lu)\n",
+ in_upcall->req.lookup.d_name,
+ in_upcall->req.lookup.parent_refn.fs_id,
+ Lu(in_upcall->req.lookup.parent_refn.handle));
+
+ parent_refn = in_upcall->req.lookup.parent_refn;
+
+ ret = PVFS_sys_ref_lookup(parent_refn.fs_id,
+ in_upcall->req.lookup.d_name,
+ parent_refn, &in_upcall->credentials,
+ &response,
+ in_upcall->req.lookup.sym_follow);
+ if (ret < 0)
+ {
+ gossip_debug(
+ GOSSIP_CLIENT_DEBUG,
+ "Failed to lookup %s (fsid %d | parent is %Lu)!\n",
+ in_upcall->req.lookup.d_name,
+ parent_refn.fs_id, Lu(parent_refn.handle));
+ gossip_debug(GOSSIP_CLIENT_DEBUG,
+ "Lookup returned error code %d\n", ret);
+
+ /* we need to send a blank response */
+ out_downcall->type = PVFS2_VFS_OP_LOOKUP;
+ out_downcall->status = ret;
+ out_downcall->resp.lookup.refn.handle = 0;
+ out_downcall->resp.lookup.refn.fs_id = 0;
+ }
+ else
+ {
+ out_downcall->type = PVFS2_VFS_OP_LOOKUP;
+ out_downcall->status = 0;
+ out_downcall->resp.lookup.refn = response.ref;
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
+static int service_create_request(
+ pvfs2_upcall_t *in_upcall,
+ pvfs2_downcall_t *out_downcall)
+{
+ int ret = 1;
+ PVFS_sysresp_create response;
+ PVFS_object_ref parent_refn;
+ PVFS_sys_attr *attrs = NULL;
+
+ if (in_upcall && out_downcall)
+ {
+ memset(&response,0,sizeof(PVFS_sysresp_create));
+ memset(out_downcall,0,sizeof(pvfs2_downcall_t));
+
+ attrs = &in_upcall->req.create.attributes;
+ attrs->atime = attrs->mtime = attrs->ctime =
+ time(NULL);
+
+ parent_refn = in_upcall->req.create.parent_refn;
+
+ gossip_debug(
+ GOSSIP_CLIENT_DEBUG,
+ "Got a create request for %s (fsid %d | parent %Lu)\n",
+ in_upcall->req.create.d_name,parent_refn.fs_id,
+ Lu(parent_refn.handle));
+
+ ret = PVFS_sys_create(
+ in_upcall->req.create.d_name, parent_refn,
+ *attrs, &in_upcall->credentials, NULL, &response);
+ if (ret < 0)
+ {
+ /*
+ if the create failed because the file already exists,
+ do a (hopefully (d)cached) lookup here and return the
+ pinode_reference along with success.
+
+ this is useful for the case where the file was created
+ before the pvfs2-client crashes; we want to report
+ success on resume to the vfs that retried the operation.
+ */
+ if (ret == -PVFS_EEXIST)
+ {
+ PVFS_sysresp_lookup lk_response;
+ memset(&lk_response,0,sizeof(PVFS_sysresp_lookup));
+
+ ret = PVFS_sys_ref_lookup(
+ parent_refn.fs_id,
+ in_upcall->req.create.d_name,
+ parent_refn,
+ &in_upcall->credentials,
+ &lk_response,
+ PVFS2_LOOKUP_LINK_NO_FOLLOW);
+ if (ret != 0)
+ {
+ gossip_err("lookup on existing file failed; "
+ "aborting create\n");
+ goto create_failure;
+ }
+ else
+ {
+ /* copy out the looked up pinode reference */
+ response.ref = lk_response.ref;
+ goto create_lookup_success;
+ }
+ }
+ create_failure:
+ gossip_err("Failed to create %s under %Lu on fsid %d!\n",
+ in_upcall->req.create.d_name,
+ Lu(parent_refn.handle), parent_refn.fs_id);
+ gossip_err("Create returned error code %d\n",ret);
+ PVFS_perror("File creation failed", ret);
+
+ /* we need to send a blank response */
+ out_downcall->type = PVFS2_VFS_OP_CREATE;
+ out_downcall->status = ret;
+ out_downcall->resp.create.refn.handle = 0;
+ out_downcall->resp.create.refn.fs_id = 0;
+ }
+ else
+ {
+ create_lookup_success:
+ out_downcall->type = PVFS2_VFS_OP_CREATE;
+ out_downcall->status = 0;
+ out_downcall->resp.create.refn = response.ref;
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
+static int service_symlink_request(
+ pvfs2_upcall_t *in_upcall,
+ pvfs2_downcall_t *out_downcall)
+{
+ int ret = 1;
+ PVFS_sysresp_symlink response;
+ PVFS_object_ref parent_refn;
+ PVFS_sys_attr *attrs = NULL;
+
+ if (in_upcall && out_downcall)
+ {
+ memset(&response,0,sizeof(PVFS_sysresp_symlink));
+ memset(out_downcall,0,sizeof(pvfs2_downcall_t));
+
+ attrs = &in_upcall->req.sym.attributes;
+ attrs->atime = attrs->mtime = attrs->ctime =
+ time(NULL);
+
+ parent_refn = in_upcall->req.sym.parent_refn;
+
+ gossip_debug(
+ GOSSIP_CLIENT_DEBUG,
+ "Got a symlink request from %s (fsid %d | parent %Lu) to %s\n",
+ in_upcall->req.sym.entry_name,parent_refn.fs_id,
+ Lu(parent_refn.handle), in_upcall->req.sym.target);
+
+ ret = PVFS_sys_symlink(in_upcall->req.sym.entry_name, parent_refn,
+ in_upcall->req.sym.target, *attrs,
+ &in_upcall->credentials, &response);
+ if (ret < 0)
+ {
+ gossip_err("Failed to symlink %s to %s under %Lu on "
+ "fsid %d!\n", in_upcall->req.sym.entry_name,
+ in_upcall->req.sym.target,
+ Lu(parent_refn.handle), parent_refn.fs_id);
+ gossip_err("Symlink returned error code %d\n",ret);
+
+ /* we need to send a blank response */
+ out_downcall->type = PVFS2_VFS_OP_SYMLINK;
+ out_downcall->status = ret;
+ out_downcall->resp.sym.refn.handle = 0;
+ out_downcall->resp.sym.refn.fs_id = 0;
+ }
+ else
+ {
+ out_downcall->type = PVFS2_VFS_OP_SYMLINK;
+ out_downcall->status = 0;
+ out_downcall->resp.sym.refn = response.ref;
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
+#ifdef USE_MMAP_RA_CACHE
+static int service_io_readahead_request(
+ struct PVFS_dev_map_desc *desc,
+ pvfs2_upcall_t *in_upcall,
+ pvfs2_downcall_t *out_downcall)
+{
+ int ret = 1;
+ PVFS_sysresp_io response;
+ PVFS_Request file_req;
+ PVFS_Request mem_req;
+ void *buf = NULL, *tmp_buf = NULL;
+
+ if (desc && in_upcall && out_downcall)
+ {
+ memset(&response,0,sizeof(PVFS_sysresp_io));
+ memset(out_downcall,0,sizeof(pvfs2_downcall_t));
+
+ file_req = PVFS_BYTE;
+
+ assert((in_upcall->req.io.buf_index > -1) &&
+ (in_upcall->req.io.buf_index < PVFS2_BUFMAP_DESC_COUNT));
+
+ tmp_buf = malloc(in_upcall->req.io.readahead_size);
+ assert(tmp_buf);
+
+ if ((in_upcall->req.io.io_type == PVFS_IO_READ) &&
+ in_upcall->req.io.readahead_size)
+ {
+ int val = 0;
+
+ /* check readahead cache first */
+ if ((val = pvfs2_mmap_ra_cache_get_block(
+ in_upcall->req.io.refn, in_upcall->req.io.offset,
+ in_upcall->req.io.count, tmp_buf) == 0))
+ {
+ goto mmap_ra_cache_hit;
+ }
+ else if (val == -2)
+ {
+ /* check if we should flush stale cache data */
+ pvfs2_mmap_ra_cache_flush(in_upcall->req.io.refn);
+
+ free(tmp_buf);
+ return ret;
+ }
+
+ /* make the full-blown readahead sized request */
+ ret = PVFS_Request_contiguous(
+ in_upcall->req.io.readahead_size, PVFS_BYTE, &mem_req);
+ }
+ else
+ {
+ free(tmp_buf);
+ return ret;
+ }
+ assert(ret == 0);
+
+ ret = PVFS_sys_io(
+ in_upcall->req.io.refn, file_req, 0,
+ tmp_buf, mem_req, &in_upcall->credentials, &response,
+ in_upcall->req.io.io_type);
+ if (ret < 0)
+ {
+ /* report an error */
+ out_downcall->type = PVFS2_VFS_OP_FILE_IO;
+ out_downcall->status = ret;
+ }
+ else
+ {
+ /*
+ now that we've read the data, insert it into
+ the mmap_ra_cache here
+ */
+ pvfs2_mmap_ra_cache_register(
+ in_upcall->req.io.refn, tmp_buf,
+ in_upcall->req.io.readahead_size);
+
+ mmap_ra_cache_hit:
+
+ out_downcall->type = PVFS2_VFS_OP_FILE_IO;
+ out_downcall->status = 0;
+ out_downcall->resp.io.amt_complete =
+ in_upcall->req.io.count;
+
+ /*
+ get a shared kernel/userspace buffer for
+ the I/O transfer
+ */
+ buf = PINT_dev_get_mapped_buffer(
+ desc, in_upcall->req.io.buf_index);
+ assert(buf);
+
+ /* copy cached data into the shared user/kernel space */
+ memcpy(buf, tmp_buf, in_upcall->req.io.count);
+ free(tmp_buf);
+ ret = 0;
+ }
+ }
+ return(ret);
+}
+#endif /* USE_MMAP_RA_CACHE */
+
+static int service_io_request(
+ struct PVFS_dev_map_desc *desc,
+ pvfs2_upcall_t *in_upcall,
+ pvfs2_downcall_t *out_downcall)
+{
+ int ret = 1;
+ PVFS_sysresp_io response;
+ PVFS_Request file_req;
+ PVFS_Request mem_req;
+ void *buf = NULL;
+ size_t amt_completed = 0;
+
+ if (desc && in_upcall && out_downcall)
+ {
+#ifdef USE_MMAP_RA_CACHE
+ if ((in_upcall->req.io.readahead_size ==
+ PVFS2_MMAP_RACACHE_FLUSH))
+ {
+ pvfs2_mmap_ra_cache_flush(in_upcall->req.io.refn);
+ }
+ else if ((in_upcall->req.io.offset == (loff_t)0) &&
+ (in_upcall->req.io.readahead_size > 0) &&
+ (in_upcall->req.io.readahead_size <
+ PVFS2_MMAP_RACACHE_MAX_SIZE))
+ {
+ ret = service_io_readahead_request(
+ desc, in_upcall, out_downcall);
+
+ /*
+ if the readahead request succeeds, return.
+ otherwise fallback to normal servicing
+ */
+ if (ret == 0)
+ {
+ return ret;
+ }
+ }
+#endif /* USE_MMAP_RA_CACHE */
+
+ memset(&response,0,sizeof(PVFS_sysresp_io));
+ memset(out_downcall,0,sizeof(pvfs2_downcall_t));
+
+ file_req = PVFS_BYTE;
+
+ ret = PVFS_Request_contiguous(
+ (int32_t)in_upcall->req.io.count, PVFS_BYTE, &mem_req);
+ assert(ret == 0);
+
+ assert((in_upcall->req.io.buf_index > -1) &&
+ (in_upcall->req.io.buf_index < PVFS2_BUFMAP_DESC_COUNT));
+
+ /* get a shared kernel/userspace buffer for the I/O transfer */
+ buf = PINT_dev_get_mapped_buffer(
+ desc, in_upcall->req.io.buf_index);
+ assert(buf);
+
+ ret = PVFS_sys_io(
+ in_upcall->req.io.refn, file_req, in_upcall->req.io.offset,
+ buf, mem_req, &in_upcall->credentials, &response,
+ in_upcall->req.io.io_type);
+
+ amt_completed = (size_t)response.total_completed;
+
+ if (ret < 0)
+ {
+ /* report an error */
+ out_downcall->type = PVFS2_VFS_OP_FILE_IO;
+ out_downcall->status = ret;
+ }
+ else
+ {
+ out_downcall->type = PVFS2_VFS_OP_FILE_IO;
+ out_downcall->status = 0;
+ out_downcall->resp.io.amt_complete = amt_completed;
+ ret = 0;
+ }
+ }
+ return(ret);
+}
+
+static int service_getattr_request(
+ pvfs2_upcall_t *in_upcall,
+ pvfs2_downcall_t *out_downcall)
+{
+ int ret = 1;
+ PVFS_sysresp_getattr response;
+
+ if (in_upcall && out_downcall)
+ {
+ memset(&response,0,sizeof(PVFS_sysresp_getattr));
+ memset(out_downcall,0,sizeof(pvfs2_downcall_t));
+
+ gossip_debug(
+ GOSSIP_CLIENT_DEBUG,
+ "got a getattr request for fsid %d | handle %Lu\n",
+ in_upcall->req.getattr.refn.fs_id,
+ Lu(in_upcall->req.getattr.refn.handle));
+
+ ret = PVFS_sys_getattr(in_upcall->req.getattr.refn,
+ PVFS_ATTR_SYS_ALL,
+ &in_upcall->credentials, &response);
+ if (ret < 0)
+ {
+ gossip_err("failed to getattr handle %Lu on fsid %d!\n",
+ Lu(in_upcall->req.getattr.refn.handle),
+ in_upcall->req.getattr.refn.fs_id);
+ gossip_err("getattr returned error code %d\n",ret);
+ PVFS_perror("Getattr failed", ret);
+
+ /* we need to send a blank response */
+ out_downcall->type = PVFS2_VFS_OP_GETATTR;
+ out_downcall->status = ret;
+ }
+ else
+ {
+ out_downcall->type = PVFS2_VFS_OP_GETATTR;
+ out_downcall->status = 0;
+ out_downcall->resp.getattr.attributes = response.attr;
+
+ /*
+ free allocated attr memory if required; to
+ avoid copying the embedded link_target string inside
+ the sys_attr object passed down into the vfs, we
+ explicitly copy the link target (if any) into a
+ reserved string space in the getattr downcall object
+ */
+ if ((response.attr.objtype == PVFS_TYPE_SYMLINK) &&
+ (response.attr.mask & PVFS_ATTR_SYS_LNK_TARGET))
+ {
+ assert(response.attr.link_target);
+
+ snprintf(out_downcall->resp.getattr.link_target,
+ PVFS2_NAME_LEN, "%s", response.attr.link_target);
+
+ free(response.attr.link_target);
+ }
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
+static int service_setattr_request(
+ pvfs2_upcall_t *in_upcall,
+ pvfs2_downcall_t *out_downcall)
+{
+ int ret = 1;
+
+ if (in_upcall && out_downcall)
+ {
+ memset(out_downcall,0,sizeof(pvfs2_downcall_t));
+
+ gossip_debug(
+ GOSSIP_CLIENT_DEBUG,
+ "got a setattr request for fsid %d | handle %Lu\n",
+ in_upcall->req.setattr.refn.fs_id,
+ Lu(in_upcall->req.setattr.refn.handle));
+
+ ret = PVFS_sys_setattr(in_upcall->req.setattr.refn,
+ in_upcall->req.setattr.attributes,
+ &in_upcall->credentials);
+ if (ret < 0)
+ {
+ gossip_err("failed to setattr handle %Lu on fsid %d!\n",
+ Lu(in_upcall->req.setattr.refn.handle),
+ in_upcall->req.setattr.refn.fs_id);
+ gossip_err("setattr returned error code %d\n",ret);
+
+ /* we need to send a blank response */
+ out_downcall->type = PVFS2_VFS_OP_SETATTR;
+ out_downcall->status = ret;
+ }
+ else
+ {
+ out_downcall->type = PVFS2_VFS_OP_SETATTR;
+ out_downcall->status = 0;
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
+static int service_remove_request(
+ pvfs2_upcall_t *in_upcall,
+ pvfs2_downcall_t *out_downcall)
+{
+ int ret = 1;
+ PVFS_object_ref parent_refn;
+
+ if (in_upcall && out_downcall)
+ {
+ memset(out_downcall,0,sizeof(pvfs2_downcall_t));
+
+ parent_refn = in_upcall->req.remove.parent_refn;
+
+ gossip_debug(
+ GOSSIP_CLIENT_DEBUG,
+ "Got a remove request for %s under fsid %d and "
+ "handle %Lu\n", in_upcall->req.remove.d_name,
+ parent_refn.fs_id, Lu(parent_refn.handle));
+
+ ret = PVFS_sys_remove(in_upcall->req.remove.d_name,
+ parent_refn, &in_upcall->credentials);
+ if (ret < 0)
+ {
+ gossip_err("Failed to remove %s under handle %Lu "
+ "on fsid %d!\n", in_upcall->req.remove.d_name,
+ Lu(parent_refn.handle), parent_refn.fs_id);
+ gossip_err("Remove returned error code %d\n",ret);
+ PVFS_perror("Remove failed",ret);
+
+ /* we need to send a blank error response */
+ out_downcall->type = PVFS2_VFS_OP_REMOVE;
+ out_downcall->status = ret;
+ }
+ else
+ {
+ /* we need to send a blank success response */
+ out_downcall->type = PVFS2_VFS_OP_REMOVE;
+ out_downcall->status = 0;
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
+static int service_mkdir_request(
+ pvfs2_upcall_t *in_upcall,
+ pvfs2_downcall_t *out_downcall)
+{
+ int ret = 1;
+ PVFS_sysresp_mkdir response;
+ PVFS_object_ref parent_refn;
+ PVFS_sys_attr *attrs = NULL;
+
+ if (in_upcall && out_downcall)
+ {
+ memset(&response,0,sizeof(PVFS_sysresp_mkdir));
+ memset(out_downcall,0,sizeof(pvfs2_downcall_t));
+
+ attrs = &in_upcall->req.mkdir.attributes;
+ attrs->atime = attrs->mtime = attrs->ctime =
+ time(NULL);
+
+ parent_refn = in_upcall->req.mkdir.parent_refn;
+
+ gossip_debug(
+ GOSSIP_CLIENT_DEBUG,
+ "Got a mkdir request for %s (fsid %d | parent %Lu)\n",
+ in_upcall->req.mkdir.d_name,parent_refn.fs_id,
+ Lu(parent_refn.handle));
+
+ ret = PVFS_sys_mkdir(in_upcall->req.mkdir.d_name, parent_refn,
+ *attrs, &in_upcall->credentials, &response);
+ if (ret < 0)
+ {
+ gossip_err("Failed to mkdir %s under %Lu on fsid %d!\n",
+ in_upcall->req.mkdir.d_name,
+ Lu(parent_refn.handle), parent_refn.fs_id);
+ gossip_err("Mkdir returned error code %d\n",ret);
+
+ /* we need to send a blank response */
+ out_downcall->type = PVFS2_VFS_OP_MKDIR;
+ out_downcall->status = ret;
+ out_downcall->resp.mkdir.refn.handle = 0;
+ out_downcall->resp.mkdir.refn.fs_id = 0;
+ }
+ else
+ {
+ out_downcall->type = PVFS2_VFS_OP_MKDIR;
+ out_downcall->status = 0;
+ out_downcall->resp.mkdir.refn = response.ref;
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
+static int service_readdir_request(
+ pvfs2_upcall_t *in_upcall,
+ pvfs2_downcall_t *out_downcall)
+{
+ int ret = 1;
+ PVFS_sysresp_readdir response;
+ PVFS_object_ref refn;
+
+ if (in_upcall && out_downcall)
+ {
+ memset(&response,0,sizeof(PVFS_sysresp_readdir));
+ memset(out_downcall,0,sizeof(pvfs2_downcall_t));
+
+ refn = in_upcall->req.readdir.refn;
+
+ gossip_debug(
+ GOSSIP_CLIENT_DEBUG,
+ "Got a readdir request for fsid %d | parent %Lu "
+ "(token is %d)\n", refn.fs_id, Lu(refn.handle),
+ in_upcall->req.readdir.token);
+
+ ret = PVFS_sys_readdir(refn, in_upcall->req.readdir.token,
+ in_upcall->req.readdir.max_dirent_count,
+ &in_upcall->credentials, &response);
+ if (ret < 0)
+ {
+ gossip_err("Failed to readdir under %Lu on fsid %d!\n",
+ Lu(refn.handle), refn.fs_id);
+ gossip_err("Readdir returned error code %d\n",ret);
+
+ /* we need to send a blank response */
+ out_downcall->type = PVFS2_VFS_OP_READDIR;
+ out_downcall->status = ret;
+ out_downcall->resp.readdir.dirent_count = 0;
+ }
+ else
+ {
+ int i = 0, len = 0;
+ out_downcall->type = PVFS2_VFS_OP_READDIR;
+ out_downcall->status = 0;
+
+ out_downcall->resp.readdir.token = response.token;
+
+ for(i = 0; i < response.pvfs_dirent_outcount; i++)
+ {
+ out_downcall->resp.readdir.refn[i].handle =
+ response.dirent_array[i].handle;
+ out_downcall->resp.readdir.refn[i].fs_id = refn.fs_id;
+
+ len = strlen(response.dirent_array[i].d_name);
+ out_downcall->resp.readdir.d_name_len[i] = len;
+ strncpy(&out_downcall->resp.readdir.d_name[i][0],
+ response.dirent_array[i].d_name,len);
+
+ out_downcall->resp.readdir.dirent_count++;
+ }
+
+ if (out_downcall->resp.readdir.dirent_count ==
+ response.pvfs_dirent_outcount)
+ {
+ ret = 0;
+ }
+ else
+ {
+ gossip_err("DIRENT COUNTS DON'T MATCH (%d != %d)\n",
+ out_downcall->resp.readdir.dirent_count,
+ response.pvfs_dirent_outcount);
+ }
+ }
+ }
+ return ret;
+}
+
+static int service_rename_request(
+ pvfs2_upcall_t *in_upcall,
+ pvfs2_downcall_t *out_downcall)
+{
+ int ret = 1;
+ PVFS_object_ref old_parent_refn, new_parent_refn;
+
+ if (in_upcall && out_downcall)
+ {
+ memset(out_downcall,0,sizeof(pvfs2_downcall_t));
+
+ old_parent_refn = in_upcall->req.rename.old_parent_refn;
+ new_parent_refn = in_upcall->req.rename.new_parent_refn;
+
+ gossip_debug(
+ GOSSIP_CLIENT_DEBUG,
+ "Got a rename request for %s under fsid %d and "
+ "handle %Lu to be %s under fsid %d and handle %Lu\n",
+ in_upcall->req.rename.d_old_name,
+ old_parent_refn.fs_id, Lu(old_parent_refn.handle),
+ in_upcall->req.rename.d_new_name,
+ new_parent_refn.fs_id, Lu(new_parent_refn.handle));
+
+ ret = PVFS_sys_rename(in_upcall->req.rename.d_old_name,
+ in_upcall->req.rename.old_parent_refn,
+ in_upcall->req.rename.d_new_name,
+ in_upcall->req.rename.new_parent_refn,
+ &in_upcall->credentials);
+ if (ret < 0)
+ {
+ gossip_err("Failed to rename %s to %s\n",
+ in_upcall->req.rename.d_old_name,
+ in_upcall->req.rename.d_new_name);
+ gossip_err("Rename returned error code %d\n", ret);
+
+ /* we need to send a blank error response */
+ out_downcall->type = PVFS2_VFS_OP_RENAME;
+ out_downcall->status = ret;
+ }
+ else
+ {
+ /* we need to send a blank success response */
+ out_downcall->type = PVFS2_VFS_OP_RENAME;
+ out_downcall->status = 0;
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
+static int service_statfs_request(
+ pvfs2_upcall_t *in_upcall,
+ pvfs2_downcall_t *out_downcall)
+{
+ int ret = 1;
+ PVFS_sysresp_statfs resp_statfs;
+
+ if (in_upcall && out_downcall)
+ {
+ memset(&resp_statfs,0,sizeof(PVFS_sysresp_statfs));
+ memset(out_downcall,0,sizeof(pvfs2_downcall_t));
+
+ gossip_debug(GOSSIP_CLIENT_DEBUG, "Got a statfs request for fsid %d\n",
+ in_upcall->req.statfs.fs_id);
+
+ ret = PVFS_sys_statfs(in_upcall->req.statfs.fs_id,
+ &in_upcall->credentials,
+ &resp_statfs);
+ if (ret < 0)
+ {
+ gossip_err("Failed to statfs fsid %d\n",
+ in_upcall->req.statfs.fs_id);
+ gossip_err("Statfs returned error code %d\n",ret);
+
+ /* we need to send a blank response */
+ out_downcall->type = PVFS2_VFS_OP_STATFS;
+ out_downcall->status = ret;
+ }
+ else
+ {
+ out_downcall->type = PVFS2_VFS_OP_STATFS;
+ out_downcall->status = 0;
+
+ out_downcall->resp.statfs.block_size =
+ STATFS_DEFAULT_BLOCKSIZE;
+ out_downcall->resp.statfs.blocks_total = (long)
+ (resp_statfs.statfs_buf.bytes_total /
+ out_downcall->resp.statfs.block_size);
+ out_downcall->resp.statfs.blocks_avail = (long)
+ (resp_statfs.statfs_buf.bytes_available /
+ out_downcall->resp.statfs.block_size);
+ /*
+ these values really represent handle/inode counts
+ rather than an accurate number of files
+ */
+ out_downcall->resp.statfs.files_total = (long)
+ resp_statfs.statfs_buf.handles_total_count;
+ out_downcall->resp.statfs.files_avail = (long)
+ resp_statfs.statfs_buf.handles_available_count;
+
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
+static int service_truncate_request(
+ pvfs2_upcall_t *in_upcall,
+ pvfs2_downcall_t *out_downcall)
+{
+ int ret = 1;
+
+ if (in_upcall && out_downcall)
+ {
+ memset(out_downcall,0,sizeof(pvfs2_downcall_t));
+
+ gossip_debug(
+ GOSSIP_CLIENT_DEBUG,
+ "Got a truncate request for %Lu under fsid %d to be "
+ "size %Ld\n", Lu(in_upcall->req.truncate.refn.handle),
+ in_upcall->req.truncate.refn.fs_id,
+ Ld(in_upcall->req.truncate.size));
+
+ ret = PVFS_sys_truncate(in_upcall->req.truncate.refn,
+ in_upcall->req.truncate.size,
+ &in_upcall->credentials);
+ if (ret < 0)
+ {
+ gossip_err("Failed to truncate %Lu on %d\n",
+ Lu(in_upcall->req.truncate.refn.handle),
+ in_upcall->req.truncate.refn.fs_id);
+ gossip_err("Truncate returned error code %d\n", ret);
+
+ /* we need to send a blank error response */
+ out_downcall->type = PVFS2_VFS_OP_TRUNCATE;
+ out_downcall->status = ret;
+ }
+ else
+ {
+ /* we need to send a blank success response */
+ out_downcall->type = PVFS2_VFS_OP_TRUNCATE;
+ out_downcall->status = 0;
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
+#ifdef USE_MMAP_RA_CACHE
+static int service_mmap_ra_flush_request(
+ pvfs2_upcall_t *in_upcall,
+ pvfs2_downcall_t *out_downcall)
+{
+ int ret = 1;
+
+ if (in_upcall && out_downcall)
+ {
+ memset(out_downcall,0,sizeof(pvfs2_downcall_t));
+
+ gossip_debug(
+ GOSSIP_CLIENT_DEBUG,
+ "Got a mmap racache flush request for %Lu under fsid %d\n",
+ Lu(in_upcall->req.ra_cache_flush.refn.handle),
+ in_upcall->req.ra_cache_flush.refn.fs_id);
+
+ /* flush cached data if any */
+ pvfs2_mmap_ra_cache_flush(in_upcall->req.io.refn);
+
+ /* we need to send a blank success response */
+ out_downcall->type = PVFS2_VFS_OP_MMAP_RA_FLUSH;
+ out_downcall->status = 0;
+ ret = 0;
+ }
+ return ret;
+}
+#endif
+
+#define generate_upcall_mntent(mntent, in_upcall, mount) \
+do { \
+ /* \
+ generate a unique dynamic mount point; the id will be passed to \
+ the kernel via the downcall so we can match it with a proper \
+ unmount request at unmount time. if we're unmounting, use the \
+ passed in id from the upcall \
+ */ \
+ if (mount) \
+ snprintf(buf, PATH_MAX, "<DYNAMIC-%d>", dynamic_mount_id); \
+ else \
+ snprintf(buf, PATH_MAX, "<DYNAMIC-%d>", \
+ in_upcall->req.fs_umount.id); \
+ \
+ mntent.mnt_dir = strdup(buf); \
+ if (!mntent.mnt_dir) \
+ { \
+ ret = -PVFS_ENOMEM; \
+ goto fail_downcall; \
+ } \
+ \
+ gossip_debug(GOSSIP_CLIENT_DEBUG, "Using %s Point %s\n", \
+ (mount ? "Mount" : "Unmount"), mntent.mnt_dir); \
+ \
+ if (mount) \
+ ptr = rindex(in_upcall->req.fs_mount.pvfs2_config_server, \
+ (int)'/'); \
+ else \
+ ptr = rindex(in_upcall->req.fs_umount.pvfs2_config_server, \
+ (int)'/'); \
+ \
+ if (!ptr) \
+ { \
+ gossip_err("Configuration server MUST be of the form " \
+ "protocol://address/fs_name\n"); \
+ ret = -PVFS_EINVAL; \
+ goto fail_downcall; \
+ } \
+ *ptr = '\0'; \
+ ptr++; \
+ \
+ if (mount) \
+ mntent.pvfs_config_server = strdup( \
+ in_upcall->req.fs_mount.pvfs2_config_server); \
+ else \
+ mntent.pvfs_config_server = strdup( \
+ in_upcall->req.fs_umount.pvfs2_config_server); \
+ \
+ if (!mntent.pvfs_config_server) \
+ { \
+ ret = -PVFS_ENOMEM; \
+ goto fail_downcall; \
+ } \
+ \
+ gossip_debug( \
+ GOSSIP_CLIENT_DEBUG, "Got Configuration Server: %s " \
+ "(len=%d)\n", mntent.pvfs_config_server, \
+ strlen(mntent.pvfs_config_server)); \
+ \
+ mntent.pvfs_fs_name = strdup(ptr); \
+ if (!mntent.pvfs_config_server) \
+ { \
+ ret = -PVFS_ENOMEM; \
+ goto fail_downcall; \
+ } \
+ \
+ gossip_debug( \
+ GOSSIP_CLIENT_DEBUG, "Got FS Name: %s (len=%d)\n", \
+ mntent.pvfs_fs_name, strlen(mntent.pvfs_fs_name)); \
+ \
+ mntent.encoding = ENCODING_DEFAULT; \
+ mntent.flowproto = FLOWPROTO_DEFAULT; \
+ \
+ /* also fill in the fs_id for umount */ \
+ if (!mount) \
+ mntent.fs_id = in_upcall->req.fs_umount.fs_id; \
+ \
+ ret = 0; \
+} while(0)
+
+static int service_fs_mount_request(
+ pvfs2_upcall_t *in_upcall,
+ pvfs2_downcall_t *out_downcall)
+{
+ int ret = 1;
+ struct PVFS_sys_mntent mntent;
+ PVFS_handle root_handle;
+ char *ptr = NULL;
+ char buf[PATH_MAX] = {0};
+
+ if (in_upcall && out_downcall)
+ {
+ /*
+ since we got a mount request from the vfs, we know that some
+ mntent entries are not filled in, so add some defaults here
+ if they weren't passed in the options.
+ */
+ memset(&mntent, 0, sizeof(struct PVFS_sys_mntent));
+ memset(out_downcall,0,sizeof(pvfs2_downcall_t));
+
+ gossip_debug(GOSSIP_CLIENT_DEBUG,
+ "Got an fs mount request via host %s\n",
+ in_upcall->req.fs_mount.pvfs2_config_server);
+
+ generate_upcall_mntent(mntent, in_upcall, 1);
+
+ ret = PVFS_sys_fs_add(&mntent);
+
+ if (ret < 0)
+ {
+ fail_downcall:
+ gossip_err("Failed to mount via host %s\n",
+ in_upcall->req.fs_mount.pvfs2_config_server);
+ PVFS_perror("Mount failure", ret);
+
+ /* we need to send a blank error response */
+ out_downcall->type = PVFS2_VFS_OP_FS_MOUNT;
+ out_downcall->status = ret;
+ }
+ else
+ {
+ /*
+ we need to send a blank success response, but first we
+ need to resolve the root handle, given the previously
+ resolved fs_id
+ */
+ if (PINT_bucket_get_root_handle(mntent.fs_id, &root_handle))
+ {
+ gossip_err("Failed to retrieve root handle for "
+ "resolved fs_id %d\n",mntent.fs_id);
+ goto fail_downcall;
+ }
+
+ gossip_debug(GOSSIP_CLIENT_DEBUG,
+ "FS mount got root handle %Lu on fs id %d\n",
+ root_handle, mntent.fs_id);
+
+ out_downcall->type = PVFS2_VFS_OP_FS_MOUNT;
+ out_downcall->status = 0;
+ out_downcall->resp.fs_mount.fs_id = mntent.fs_id;
+ out_downcall->resp.fs_mount.root_handle = root_handle;
+ out_downcall->resp.fs_mount.id = dynamic_mount_id++;
+ ret = 0;
+ }
+
+ PVFS_sys_free_mntent(&mntent);
+ }
+ return ret;
+}
+
+static int service_fs_umount_request(
+ pvfs2_upcall_t *in_upcall,
+ pvfs2_downcall_t *out_downcall)
+{
+ int ret = -PVFS_ENODEV;
+ struct PVFS_sys_mntent mntent;
+ char *ptr = NULL;
+ char buf[PATH_MAX] = {0};
+
+ if (in_upcall && out_downcall)
+ {
+ /*
+ since we got a umount request from the vfs, we know that
+ some mntent entries are not filled in, so add some defaults
+ here if they weren't passed in the options.
+ */
+ memset(&mntent, 0, sizeof(struct PVFS_sys_mntent));
+ memset(out_downcall,0,sizeof(pvfs2_downcall_t));
+
+ gossip_debug(GOSSIP_CLIENT_DEBUG,
+ "Got an fs umount request via host %s\n",
+ in_upcall->req.fs_umount.pvfs2_config_server);
+
+ generate_upcall_mntent(mntent, in_upcall, 0);
+
+ ret = PVFS_sys_fs_remove(&mntent);
+
+ if (ret < 0)
+ {
+ fail_downcall:
+ gossip_err("Failed to umount via host %s\n",
+ in_upcall->req.fs_umount.pvfs2_config_server);
+ PVFS_perror("UMOUNT failure", ret);
+
+ /* we need to send a blank error response */
+ out_downcall->type = PVFS2_VFS_OP_FS_UMOUNT;
+ out_downcall->status = ret;
+ }
+ else
+ {
+ gossip_debug(GOSSIP_CLIENT_DEBUG, "FS umount ok\n");
+
+ out_downcall->type = PVFS2_VFS_OP_FS_MOUNT;
+ out_downcall->status = 0;
+ ret = 0;
+ }
+
+ PVFS_sys_free_mntent(&mntent);
+ }
+ return ret;
+}
+
+int write_device_response(
+ void *buffer_list,
+ int *size_list,
+ int list_size,
+ int total_size,
+ PVFS_id_gen_t tag,
+ job_id_t *job_id,
+ job_status_s *jstat,
+ job_context_id context)
+{
+ int ret = -1;
+ int outcount = 0;
+
+ if (buffer_list && size_list && list_size &&
+ total_size && (list_size < MAX_LIST_SIZE))
+ {
+ ret = job_dev_write_list(buffer_list, size_list, list_size,
+ total_size, tag, PINT_DEV_EXT_ALLOC,
+ NULL, 0, jstat, job_id, context);
+ if (ret < 0)
+ {
+ PVFS_perror("job_dev_write_list()", ret);
+ goto exit_point;
+ }
+ else if (ret == 0)
+ {
+ ret = job_test(*job_id, &outcount, NULL, jstat, -1, context);
+ if (ret < 0)
+ {
+ PVFS_perror("job_test()", ret);
+ goto exit_point;
+ }
+ }
+
+ if (jstat->error_code != 0)
+ {
+ PVFS_perror("job_bmi_write_list() error code",
+ jstat->error_code);
+ ret = -1;
+ }
+ }
+ exit_point:
+ return ret;
+}
+
+
+int main(int argc, char **argv)
+{
+ int ret = 1;
+ void* buffer_list[MAX_LIST_SIZE];
+ int size_list[MAX_LIST_SIZE];
+ int list_size = 0, total_size = 0;
+ struct rlimit lim = {0,0};
+
+ job_context_id context;
+
+ job_id_t job_id;
+ job_status_s jstat;
+ struct PINT_dev_unexp_info info;
+ struct PVFS_dev_map_desc desc;
+
+ unsigned long tag = 0;
+ pvfs2_upcall_t upcall;
+ pvfs2_downcall_t downcall;
+
+ /* set rlimit to prevent core files */
+ ret = setrlimit(RLIMIT_CORE, &lim);
+ if(ret < 0)
+ {
+ perror("rlimit");
+ fprintf(stderr, "continuing...\n");
+ }
+
+ /*
+ initialize pvfs system interface
+
+ NOTE: we do not rely on a pvfstab file at all in here, as
+ mounting a pvfs2 volume through the kernel interface now
+ requires you to specify a server and fs name in the form of:
+
+ protocol://server/fs_name
+
+ At mount time, we dynamically resolve and add the file
+ systems/mount information
+ */
+ ret = PVFS_sys_initialize(GOSSIP_NO_DEBUG);
+ if(ret < 0)
+ {
+ return(ret);
+ }
+
+#ifdef USE_MMAP_RA_CACHE
+ pvfs2_mmap_ra_cache_initialize();
+#endif
+
+ PINT_acache_set_timeout(ACACHE_TIMEOUT_MS);
+
+ ret = PINT_dev_initialize("/dev/pvfs2-req", 0);
+ if(ret < 0)
+ {
+ PVFS_perror("PINT_dev_initialize", ret);
+ return(-1);
+ }
+
+ /* setup a mapped region for I/O transfers */
+ memset(&desc, 0 , sizeof(struct PVFS_dev_map_desc));
+ ret = PINT_dev_get_mapped_region(&desc, PVFS2_BUFMAP_TOTAL_SIZE);
+ if (ret < 0)
+ {
+ PVFS_perror("PINT_dev_get_mapped_region", ret);
+ return(-1);
+ }
+
+ ret = job_open_context(&context);
+ if (ret < 0)
+ {
+ PVFS_perror("job_open_context", ret);
+ return(-1);
+ }
+
+ /*
+ lock the remount mutex to make sure the remount isn't started
+ until we're ready
+ */
+ pthread_mutex_lock(&remount_mutex);
+
+ if (pthread_create(&remount_thread, NULL, exec_remount, NULL))
+ {
+ gossip_err("Cannot create remount thread!");
+ return(-1);
+ }
+
+ while(1)
+ {
+ int outcount = 0;
+ static int remounted_already = 0;
+
+ /*
+ signal the remount thread to go ahead with the remount
+ attempts (and make sure it's done only once)
+ */
+ if (!remounted_already)
+ {
+ pthread_mutex_unlock(&remount_mutex);
+ remounted_already = 1;
+ }
+
+ ret = job_dev_unexp(&info, NULL, 0, &jstat, &job_id, context);
+ if (ret == 0)
+ {
+ ret = job_test(job_id, &outcount, NULL, &jstat, -1, context);
+ if (ret < 0)
+ {
+ PVFS_perror("job_test()", ret);
+ return(-1);
+ }
+ }
+ else if (ret < 0)
+ {
+ PVFS_perror("job_dev_unexp()", ret);
+ return(-1);
+ }
+
+ if (jstat.error_code != 0)
+ {
+ PVFS_perror("job error code", jstat.error_code);
+ return(-1);
+ }
+
+ gossip_debug(GOSSIP_CLIENT_DEBUG,
+ "Got message: size: %d, tag: %d, payload: %p\n",
+ info.size, (int)info.tag, info.buffer);
+
+ tag = (unsigned long)info.tag;
+ if (info.size >= sizeof(pvfs2_upcall_t))
+ {
+ memcpy(&upcall,info.buffer,sizeof(pvfs2_upcall_t));
+ }
+ else
+ {
+ gossip_err("Error! Short read from device -- "
+ "What does this mean?\n");
+ return(-1);
+ }
+
+ list_size = 0;
+ total_size = 0;
+
+ if (!remount_complete && (upcall.type != PVFS2_VFS_OP_FS_MOUNT))
+ {
+ gossip_debug(
+ GOSSIP_CLIENT_DEBUG, "Got an upcall operation of type "
+ "%x before mounting. ignoring.\n", upcall.type);
+ /*
+ if we don't have any mount information yet, just discard
+ the op, causing a kernel timeout/retry
+ */
+ PINT_dev_release_unexpected(&info);
+ continue;
+ }
+
+ switch(upcall.type)
+ {
+ case PVFS2_VFS_OP_LOOKUP:
+ service_lookup_request(&upcall,&downcall);
+ break;
+ case PVFS2_VFS_OP_CREATE:
+ service_create_request(&upcall,&downcall);
+ break;
+ case PVFS2_VFS_OP_SYMLINK:
+ service_symlink_request(&upcall,&downcall);
+ break;
+ case PVFS2_VFS_OP_GETATTR:
+ service_getattr_request(&upcall,&downcall);
+ break;
+ case PVFS2_VFS_OP_SETATTR:
+ service_setattr_request(&upcall,&downcall);
+ break;
+ case PVFS2_VFS_OP_REMOVE:
+ service_remove_request(&upcall,&downcall);
+ break;
+ case PVFS2_VFS_OP_MKDIR:
+ service_mkdir_request(&upcall,&downcall);
+ break;
+ case PVFS2_VFS_OP_READDIR:
+ service_readdir_request(&upcall,&downcall);
+ break;
+ case PVFS2_VFS_OP_FILE_IO:
+ service_io_request(&desc, &upcall, &downcall);
+ break;
+ case PVFS2_VFS_OP_RENAME:
+ service_rename_request(&upcall, &downcall);
+ break;
+ case PVFS2_VFS_OP_STATFS:
+ service_statfs_request(&upcall, &downcall);
+ break;
+ case PVFS2_VFS_OP_TRUNCATE:
+ service_truncate_request(&upcall, &downcall);
+ break;
+#ifdef USE_MMAP_RA_CACHE
+ case PVFS2_VFS_OP_MMAP_RA_FLUSH:
+ service_mmap_ra_flush_request(&upcall, &downcall);
+ break;
+#endif
+ case PVFS2_VFS_OP_FS_MOUNT:
+ service_fs_mount_request(&upcall, &downcall);
+ break;
+ case PVFS2_VFS_OP_FS_UMOUNT:
+ service_fs_umount_request(&upcall, &downcall);
+ break;
+ case PVFS2_VFS_OP_INVALID:
+ default:
+ gossip_err("Got an unrecognized vfs operation of "
+ "type %x.\n", upcall.type);
+ }
+
+ PINT_dev_release_unexpected(&info);
+
+ /* prepare to write response */
+ buffer_list[0] = &downcall;
+ size_list[0] = sizeof(pvfs2_downcall_t);
+ total_size = sizeof(pvfs2_downcall_t);
+ list_size = 1;
+
+ if (write_device_response(buffer_list,size_list,list_size,
+ total_size,(PVFS_id_gen_t)tag,
+ &job_id,&jstat,context) < 0)
+ {
+ gossip_err("write_device_response failed on tag %lu\n",tag);
+ }
+ }
+
+ /* join the remount thread, which should long be done by now */
+ pthread_join(remount_thread, NULL);
+
+ job_close_context(context);
+
+#ifdef USE_MMAP_RA_CACHE
+ pvfs2_mmap_ra_cache_finalize();
+#endif
+
+ if (PVFS_sys_finalize())
+ {
+ gossip_err("Failed to finalize PVFS\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Local variables:
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * End:
+ *
+ * vim: ts=8 sts=4 sw=4 noexpandtab
+ */
--- /dev/null 2003-01-30 05:24:37.000000000 -0500
+++ pvfs2-client.c 2004-05-25 17:38:48.000000000 -0400
@@ -0,0 +1,304 @@
+/*
+ * (C) 2001 Clemson University and The University of Chicago
+ *
+ * See COPYING in top-level directory.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#ifndef PVFS2_VERSION
+#define PVFS2_VERSION "Unknown"
+#endif
+
+#define PVFS2_CLIENT_CORE_NAME "pvfs2-client-core"
+
+typedef struct
+{
+ int verbose;
+ int foreground;
+ char *path;
+} options_t;
+
+static void client_sig_handler(int signum);
+static void parse_args(int argc, char **argv, options_t *opts);
+static int verify_pvfs2_client_path(options_t *opts);
+static int monitor_pvfs2_client(options_t *opts);
+
+
+int main(int argc, char **argv)
+{
+ pid_t new_pid = 0;
+ options_t opts;
+
+ memset(&opts, 0, sizeof(options_t));
+
+ parse_args(argc, argv, &opts);
+
+ if (opts.verbose)
+ {
+ printf("pvfs2-client starting\n");
+ }
+
+ umask(027);
+
+ if (!opts.foreground)
+ {
+ if (opts.verbose)
+ {
+ printf("Backgrounding pvfs2-client daemon\n");
+ }
+ new_pid = fork();
+ assert(new_pid != -1);
+
+ if (new_pid > 0)
+ {
+ exit(0);
+ }
+ else if (setsid() < 0)
+ {
+ exit(1);
+ }
+ }
+
+ signal(SIGHUP, client_sig_handler);
+ signal(SIGINT, client_sig_handler);
+ signal(SIGPIPE, client_sig_handler);
+ signal(SIGILL, client_sig_handler);
+ signal(SIGTERM, client_sig_handler);
+ signal(SIGSEGV, client_sig_handler);
+
+ return monitor_pvfs2_client(&opts);
+}
+
+static void client_sig_handler(int signum)
+{
+ kill(0, signum);
+ switch (signum)
+ {
+ case SIGPIPE:
+ case SIGILL:
+ case SIGSEGV:
+ exit(1);
+ case SIGHUP:
+ case SIGINT:
+ case SIGTERM:
+ exit(0);
+ }
+}
+
+static int verify_pvfs2_client_path(options_t *opts)
+{
+ int ret = -1;
+ struct stat statbuf;
+
+ if (opts)
+ {
+ memset(&statbuf, 0 , sizeof(struct stat));
+
+ if (stat(opts->path, &statbuf) == 0)
+ {
+ ret = ((S_ISREG(statbuf.st_mode) &&
+ (statbuf.st_mode & S_IXUSR)) ? 0 : 1);
+
+ }
+ }
+ return ret;
+}
+
+static int monitor_pvfs2_client(options_t *opts)
+{
+ int ret = 1, fd = 0;
+ pid_t new_pid = 0, wpid = 0;
+
+ assert(opts);
+
+ while(1)
+ {
+ if (opts->verbose)
+ {
+ printf("Spawning new child process\n");
+ }
+ new_pid = fork();
+ assert(new_pid != -1);
+
+ if (new_pid != 0)
+ {
+ if (opts->verbose)
+ {
+ printf("Waiting on child with pid %d\n", (int)new_pid);
+ }
+ wpid = waitpid(new_pid, &ret, 0);
+ assert(wpid != -1);
+
+ if (WIFEXITED(ret))
+ {
+ if (opts->verbose)
+ {
+ printf("Child process with pid %d exited with "
+ "value %d\n", new_pid, (int)WEXITSTATUS(ret));
+ }
+
+ if ((opts->path[0] != '/') && (opts->path [0] != '.'))
+ {
+ printf("*** The pvfs2-client-core has exited ***\n");
+ printf("If the pvfs2-client-core is not in your "
+ "configured PATH, please specify the\n full "
+ "path name (instead of \"%s\")\n",opts->path);
+ }
+ break;
+ }
+
+ if (WIFSIGNALED(ret))
+ {
+ if (opts->verbose)
+ {
+ printf("Child process with pid %d was killed by an "
+ "uncaught signal %d\n", new_pid,
+ WTERMSIG(ret));
+ }
+ continue;
+ }
+ }
+ else
+ {
+ if (opts->verbose)
+ {
+ printf("About to exec %s\n",opts->path);
+ }
+
+ for(fd = getdtablesize(); fd > -1; fd--)
+ {
+ close(fd);
+ }
+
+ freopen("/dev/null", "r", stdin);
+ freopen("/dev/null", "w", stdout);
+ freopen("/dev/null", "w", stderr);
+
+ ret = execvp(opts->path, NULL);
+ fprintf(stderr, "Could not exec %s, errno is %d\n",
+ opts->path, errno);
+ exit(1);
+ }
+ }
+ return ret;
+}
+
+static void print_help(char *progname)
+{
+ assert(progname);
+
+ printf("Usage: %s [OPTION]...[PATH]\n\n",progname);
+ printf("-h, --help display this help and exit\n");
+ printf("-v, --version display version and exit\n");
+ printf("-V, --verbose run in verbose output mode\n");
+ printf("-f, --foreground run in foreground mode\n");
+ printf("-p PATH, --path PATH execute pvfs2-client at PATH\n");
+}
+
+static void parse_args(int argc, char **argv, options_t *opts)
+{
+ int ret = 0, option_index = 0;
+ char *cur_option = NULL;
+
+ static struct option long_opts[] =
+ {
+ {"help",0,0,0},
+ {"version",0,0,0},
+ {"verbose",0,0,0},
+ {"foreground",0,0,0},
+ {"path",1,0,0},
+ {0,0,0,0}
+ };
+
+ assert(opts);
+
+ while((ret = getopt_long(argc, argv, "hvVfp:",
+ long_opts, &option_index)) != -1)
+ {
+ switch(ret)
+ {
+ case 0:
+ cur_option = (char *)long_opts[option_index].name;
+
+ if (strcmp("help", cur_option) == 0)
+ {
+ goto do_help;
+ }
+ else if (strcmp("version", cur_option) == 0)
+ {
+ goto do_version;
+ }
+ else if (strcmp("verbose", cur_option) == 0)
+ {
+ goto do_verbose;
+ }
+ else if (strcmp("foreground", cur_option) == 0)
+ {
+ goto do_foreground;
+ }
+ else if (strcmp("path", cur_option) == 0)
+ {
+ goto do_path;
+ }
+ break;
+ case 'h':
+ do_help:
+ print_help(argv[0]);
+ exit(0);
+ case 'v':
+ do_version:
+ printf("%s\n", PVFS2_VERSION);
+ exit(0);
+ case 'V':
+ do_verbose:
+ opts->verbose = 1;
+ break;
+ case 'f':
+ do_foreground:
+ opts->foreground = 1;
+ /* for now, foreground implies verbose */
+ goto do_verbose;
+ break;
+ case 'p':
+ do_path:
+ opts->path = optarg;
+ if (verify_pvfs2_client_path(opts))
+ {
+ fprintf(stderr, "Invalid pvfs2-client-core path: %s\n",
+ opts->path);
+ exit(1);
+ }
+ break;
+ default:
+ fprintf(stderr, "Unrecognized option. "
+ "Try --help for information.\n");
+ exit(1);
+ }
+ }
+ if (!opts->path)
+ {
+ /* Since they didn't specify a specific path, we're going
+ * to let execvp() sort things out later */
+ opts->path = PVFS2_CLIENT_CORE_NAME;
+ }
+}
+
+/*
+ * Local variables:
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * End:
+ *
+ * vim: ts=8 sts=4 sw=4 noexpandtab
+ */
--- /dev/null 2003-01-30 05:24:37.000000000 -0500
+++ umount_pvfs2.sh 2004-05-25 17:38:48.000000000 -0400
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+umount /tmp/mnt
+killall -TERM pvfs2-client
+sleep 1
+rmmod pvfs2
+
+
More information about the PVFS2-CVS
mailing list