Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 17 Jan 2007 02:43:09 GMT
From:      Adam Martin <adamartin@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 113041 for review
Message-ID:  <200701170243.l0H2h9OI048176@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=113041

Change 113041 by adamartin@adamartin_hobbes on 2007/01/17 02:43:01

	Added datastream parser, and state machine code to the protocol handler
	sections of AutoFS.  TemplateFS now has a proper dynamic instance
	allocation mechanism.  Code cleanups for better look, all around.
	(TemplateFS stays in style(9), and AutoFS is now in ADAM style.  I'll
	fix it later.)
	
	AutoFS also suffered a major cleanup of internal structure linking.
	(Now all structures are linked through an AutoFS instance pointer.
	There are accompanying macros to make accessing useful structures
	simple.)

Affected files ...

.. //depot/projects/soc2006/adamartin_autofs/autofs/autofs_ctl.c#9 edit
.. //depot/projects/soc2006/adamartin_autofs/autofs/autofs_dev.c#9 edit
.. //depot/projects/soc2006/adamartin_autofs/autofs/autofs_dev.h#7 edit
.. //depot/projects/soc2006/adamartin_autofs/autofs/autofs_tfsops.c#3 edit
.. //depot/projects/soc2006/adamartin_autofs/autofs/autofs_types.h#4 edit
.. //depot/projects/soc2006/adamartin_autofs/autofs/protocol.c#8 edit
.. //depot/projects/soc2006/adamartin_autofs/autofs/protocol.h#8 edit
.. //depot/projects/soc2006/adamartin_autofs/templatefs/templatefs.c#3 edit
.. //depot/projects/soc2006/adamartin_autofs/templatefs/templatefs.h#2 edit

Differences ...

==== //depot/projects/soc2006/adamartin_autofs/autofs/autofs_ctl.c#9 (text+ko) ====

@@ -49,19 +49,36 @@
 #include "autofs_subr.h"
 #include "debug.h"
 
+#include "../templatefs/templatefs.h"
+
+#define AUTOFS_NAME	"autofs_dev"
+
 struct cdev *autofs_ctl_dev;
 struct autofs_ctl_state autofs_ctl_state;
 
 static d_ioctl_t autofs_ctl_ioctl;
 
-struct cdevsw autofs_ctl_devops = {
-	.d_version= D_VERSION,
-	.d_open= NULL,
-	.d_close= NULL,
-	.d_read= NULL,
-	.d_write= NULL,
-	.d_name= AUTOFS_CTL_DEV_NAME,
-	.d_ioctl= autofs_ctl_ioctl,
+struct cdevsw autofs_ctl_devops=
+{
+	.d_version=	D_VERSION,
+	.d_open=	NULL,
+	.d_close=	NULL,
+	.d_read=	NULL,
+	.d_write=	NULL,
+	.d_poll=	NULL,
+	.d_name=	AUTOFS_CTL_DEV_NAME,
+	.d_ioctl=	autofs_ctl_ioctl,
+};
+
+static struct cdevsw autofs_device_devops=
+{
+	.d_open=	autofs_dev_open,
+	.d_close=	autofs_dev_close,
+	.d_read=	autofs_dev_read,
+	.d_write=	autofs_dev_write,
+	.d_poll=	autofs_dev_poll,
+	.d_version=	D_VERSION,
+	.d_name=	AUTOFS_NAME,
 };
 
 int
@@ -72,13 +89,20 @@
 	return 0;
 }
 
-MALLOC_DECLARE( M_AUTOFS_DEV );
-MALLOC_DEFINE( M_AUTOFS_DEV, "autofs_dev", "autofs device structure" );
+
+MALLOC_DECLARE( M_AUTOFS_INSTANCE );
+MALLOC_DEFINE( M_AUTOFS_INSTANCE, "autofs_instance", "autofs instance data" );
 
 MALLOC_DECLARE( M_AUTOFS_DEV_BUFFERS );
-MALLOC_DEFINE( M_AUTOFS_DEV_BUFFERS, "autofs_dev_buffers", "autofs device io buffers" );
+MALLOC_DEFINE( M_AUTOFS_DEV_BUFFERS, "autofs_dev_bufs",
+		"autofs device io buffers" );
+
+MALLOC_DECLARE( M_AUTOFS_PROTOCOL_STATE );
+MALLOC_DEFINE( M_AUTOFS_PROTOCOL_STATE, "autofs_protocol_state",
+		"buffer for autofs protocol state tracking" );
 
-MALLOC_DEFINE( M_AUTOFS_DEV_LOCKS, "autofs_dev_lock", "Autofs mutex locks for individual devices..." );
+/* MALLOC_DEFINE( M_AUTOFS_DEV_LOCKS, "autofs_dev_lock",
+		"Autofs mutex locks for individual devices..." ); */
 
 
 static int
@@ -93,39 +117,90 @@
 }
 
 static int
-create_autofs_node( int num, autofs_instance_t *instance )
+create_autofs_node( int num, autofs_instance_t **instance_p )
 {
-	int error;
-	struct cdevsw *autofs_cdevsw;
-	struct cdev *autofs_cdev;
-	struct autofs_dev_bufs *autofs_dev_data;
+	$cleanup_init;
+
+	int				error;
+	struct cdevsw			*devsw;
+	struct cdev			*device;
+	struct autofs_dev_bufs		*buffers;
+	struct autofs_instance		*instance;
+	struct tfs_info			*ti;
+	struct autofs_protocol_state	*prot_state;
 
 	error= 0;
 
-	autofs_cdevsw= malloc( sizeof( struct cdevsw ), M_AUTOFS_DEV, M_WAITOK );
-	autofs_dev_data= malloc( sizeof( struct autofs_dev_bufs ),
-			M_AUTOFS_DEV_BUFFERS, M_WAITOK );
+	instance_p= NULL;
+
+	/*
+	 * Allocate all autofs buffers, and setup a new TemplateFS instance.
+	 */
+
+	instance= malloc( sizeof( autofs_instance_t ), M_AUTOFS_INSTANCE,
+			M_WAITOK | M_ZERO );
+	$cleanup( free( instance, M_AUTOFS_INSTANCE ); );
+
+
+	buffers= malloc( sizeof( struct autofs_dev_bufs ), M_AUTOFS_DEV_BUFFERS,
+			M_WAITOK | M_ZERO );
+	$cleanup( free( buffers, M_AUTOFS_DEV_BUFFERS ); );
+
+	prot_state= malloc( sizeof( struct autofs_protocol_state ),
+			M_AUTOFS_PROTOCOL_STATE, M_WAITOK | M_ZERO );
+	$cleanup( free( prot_state, M_AUTOFS_PROTOCOL_STATE ); );
+
+	devsw= &autofs_device_devops;
+
+	error= tfs_create_instance( &ti );
+	if( error != 0 )
+	{
+		$return ( error );
+	}
+#	if 0
+		$cleanup( tfs_destroy_instance( ti ););
+#	endif
+
+	/*
+	 * Associate TemplateFS data structures together
+	 */
+
+
+
+	prot_state->message= NULL;
+	prot_state->current_state= PROTOCOL_WAITING;
+	prot_state->bytes_read= 0;
+
+	buffers->input= autofs_queue_init();
+	buffers->output= autofs_queue_init();
+	buffers->instances= 0;
+
+
+	/*
+	 * Make the device, and lock it.
+	 */
 
+	device= make_dev( devsw, num, UID_ROOT, GID_WHEEL, 0600,
+			"autofs%d", num );
 
-	autofs_dev_data->input= autofs_queue_init();
-	autofs_dev_data->output= autofs_queue_init();
-	autofs_dev_data->instances= 0;
-	autofs_dev_data->this_instance= instance;
+	/* Possible race?  Locking the device? */
+	/* How to lock it? */
 
-	autofs_cdevsw->d_open= autofs_dev_open;
-	autofs_cdevsw->d_close= autofs_dev_close;
-	autofs_cdevsw->d_read= autofs_dev_read;
-	autofs_cdevsw->d_write= autofs_dev_write;
-	autofs_cdevsw->d_poll= autofs_dev_poll;
-	autofs_cdevsw->d_version= D_VERSION;
-	autofs_cdevsw->d_name= "autofs_dev";
 
-	autofs_cdev= make_dev( autofs_cdevsw, num, UID_ROOT, GID_WHEEL, 0600, "autofs%d", num );
-	if( autofs_cdev == NULL )
+	/* Check the device, and then associate the device to the instance */
+	if( device == NULL )
 	{
-		panic( "Bad autofs_cdev\n" );
+		panic( "Bad device in %s:%d\n", __FILE__, __LINE__ );
 	}
-	autofs_cdev->si_priv= (struct cdev_priv *) autofs_dev_data;
+	prot_state->instance= instance;
+	buffers->this_instance= instance;
+	ti->ti_priv= (void *) instance;
+	device->si_priv= (struct cdev_priv *) instance;
+
+	/*
+	 * Don't deallocate the resources --
+	 * they're for the working filesystem
+	 */
 
 	return error;
 }
@@ -173,7 +248,7 @@
 			)
 			*/
 			arg= autofs_ctl_state.next_assignable_node++;
-			error= create_autofs_node( arg, instance );
+			error= create_autofs_node( arg, &instance );
 
 			$do_cleanup;
 

==== //depot/projects/soc2006/adamartin_autofs/autofs/autofs_dev.c#9 (text+ko) ====

@@ -56,14 +56,7 @@
 int
 write_buffer( queue *q, void *data, int len )
 {
-	$cleanup_init_size( 8 );
-	int error;
-	error= 0;
-
-	autofs_queue_write( q, data, len );
-
-	//parse_user_message();
-	$return error;
+	return autofs_queue_write( q, data, len );
 }
 
 
@@ -155,7 +148,7 @@
 		 * right now.
 		 */
 	}
-	while( remains > 0 ); /** FIXME: Shouldn't this be == **/
+	while( remains == 0 ); /** FIXME: Shouldn't this be == **/
 
 	amt= MIN( remains, amt );
 	autofs_queue_read( q, out_buf, amt );
@@ -170,16 +163,19 @@
 autofs_dev_write( struct cdev *dev, struct uio *uio, int ioflag )
 {
 	struct autofs_dev_bufs *bufs;
-	queue *q;
 	int amt;
 	int error;
 	unsigned char in_buf[ AUTOFS_IO_BUF_SIZE ]; /* No more than a page! */
+	struct autofs_protocol_state	*prot;
+	queue *in_q;
 
 	error= 0;
+
+	prot= AUTOFS_GET_PROTOCOL( DEV, dev );
 	amt= MIN( uio->uio_resid, AUTOFS_IO_BUF_SIZE );
 
 	bufs= AUTOFS_GET_BUFFERS( DEV, dev );
-	q= bufs->input;
+	in_q= bufs->input;
 
 
 	error= uiomove( in_buf, amt, uio );
@@ -189,7 +185,9 @@
 	}
 
 
-	autofs_queue_write( q, in_buf, amt );
+	autofs_queue_write( in_q, in_buf, amt );
+
+	parse_user_message( prot );
 
 
 	return error;

==== //depot/projects/soc2006/adamartin_autofs/autofs/autofs_dev.h#7 (text+ko) ====


==== //depot/projects/soc2006/adamartin_autofs/autofs/autofs_tfsops.c#3 (text+ko) ====

@@ -136,7 +136,7 @@
 
 	//if( take_autofs_lock( instance, node ) )
 	//{
-		send_mount_request( &msg, buffers->output );
+		send_mount_request( &msg, buffers );
 	//}
 	
 	return 1;

==== //depot/projects/soc2006/adamartin_autofs/autofs/autofs_types.h#4 (text+ko) ====

@@ -23,6 +23,7 @@
 struct autofs_transaction;
 struct autofs_dev_bufs;
 struct autofs_mount;
+struct autofs_protocol_state;
 
 struct message_header;
 
@@ -33,6 +34,7 @@
 typedef struct autofs_transaction autofs_transaction_t;
 typedef struct autofs_dev_bufs autofs_dev_bufs_t;
 typedef struct autofs_mount autofs_mount_t;
+typedef struct autofs_protocol_state autofs_protocol_state_t;
 
 /************** END FORWARD DEFINITIONS *****************/
 
@@ -54,6 +56,7 @@
 	autofs_mount_t		*mount_list; /** This will be a hash **/
 	autofs_transaction_t	*in_flight; /** A hash of inflight
 						transactions **/
+	autofs_protocol_state_t *protocol_state;
 
 	void			*extensions;
 };
@@ -104,6 +107,33 @@
 
 
 
+struct autofs_protocol_state
+{
+	/*
+	 * The protocol state can be:
+	 *
+	 *	Undefined - should never be this state
+	 *	Waiting - waiting for a new command
+	 *	Reading - reading a command (id is current_command)
+	 *	Error - final state in the chain, reached on an error
+	 */
+	int			current_state;
+#	define			PROTOCOL_UNDEFINED	( 0x00 )
+#	define			PROTOCOL_WAITING	( 0x01 )
+#	define			PROTOCOL_READING	( 0x02 )
+#	define			PROTOCOL_ERROR		( 0x03 )
+
+
+	int			curr_cmd_id; /* Used to determine length */
+	int			bytes_read; /* How many bytes read thus far */
+	int			max_bytes_to_read; /* Adjusted as we read */
+
+	autofs_instance_t	*instance;
+
+	struct message_header 	*message;
+
+};
+
 /***************************************************************************
 The GET* macros get a piece of autofs state, from a "holder", where
 holder is DEV, NODE, INSTANCE or ROOT:
@@ -112,12 +142,14 @@
 	NODE - a node (mountpoint) within the AutoFS system
 	INSTANCE - the instance descriptor of an AutoFS system
 	ROOT - the tfs_info (vfs_info) descriptor of the underlying templatefs
+	PROTOCOL - the autofs protocol state tracking structure
+	BUFFERS - the device input output buffers of the autofs protocol
 
 E.G.: AUTOFS_GET_BUFFERS( ROOT, autofs_tfs_info )
 E.G.: AUTOFS_GET_TXNS( DEV, autofs_cdevsw )
 
 one can get:
-	BUFFERS, DEV, TXNS, INSTANCE
+	BUFFERS, DEV, TXNS, INSTANCE, PROTOCOL
 
 ****************************************************************************/
 
@@ -137,6 +169,10 @@
 	( (struct cdev *) ( AUTOFS_GET_INSTANCE( TYPE, __datum__ )->\
 			device_struct ) )
 
+#define AUTOFS_GET_PROTOCOL( TYPE, __datum__ )\
+	( (struct autofs_protocol_state *) ( AUTOFS_GET_INSTANCE( TYPE, \
+			__datum__ )->protocol_state ) )
+
 
 #define AUTOFS_DEV_GET_INSTANCE( dev )\
 	( ( dev )->si_priv )
@@ -150,4 +186,10 @@
 #define AUTOFS_INSTANCE_GET_INSTANCE( instance )\
 	( ( instance ) )
 
+#define AUTOFS_PROTOCOL_GET_INSTANCE( protocol )\
+	( ( protocol )->instance )
+
+#define AUTOFS_BUFFERS_GET_INSTANCE( protocol )\
+	( ( protocol )->this_instance )
+
 #endif	/*** __AUTOFS_TYPES_H__ ***/

==== //depot/projects/soc2006/adamartin_autofs/autofs/protocol.c#8 (text+ko) ====

@@ -38,14 +38,230 @@
 
 #include "autofs_types.h"
 
+#include "debug.h"
+
+#define BOGUS ( 0xDEADBEEF )
+
+#ifndef MAX
+#define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
+#endif
+
+#ifndef MIN
+#define MIN( a, b ) ( ( ( b ) > ( b ) ) ? ( a ) : ( b ) )
+#endif
+
+
+MALLOC_DECLARE( M_AUTOFS_TRANSACTION_BUFFER );
+MALLOC_DEFINE( M_AUTOFS_TRANSACTION_BUFFER, "autofs_txn_buf",
+		"AutoFS transaction processing buffer" );
+
+#ifdef	TRIM_NEEDED
+#define	TRIM_SIZE	( sizeof( void * ) )
+#else
+#define	TRIM_SIZE	( ( 0 ) )
+#endif
+
+static int
+command_sizes[]=
+{
+	0x00,						/* INVALID */
+	sizeof( struct mount_request ) - TRIM_SIZE,	/* MOUNT_REQUEST */
+	sizeof( struct mount_done ),			/* MOUNT_DONE */
+	sizeof( struct hello ),				/* HELLO */
+	sizeof( struct greeting ) - TRIM_SIZE,		/* AUTOFS_GREETING */
+	sizeof( struct greeting_response ) - TRIM_SIZE,	/* GREETING_RESPONSE */
+	sizeof( struct modify_mounts ) - TRIM_SIZE,	/* MODIFY_MOUNTS */ 
+	sizeof( struct modify_mounts_acknowledge ) - TRIM_SIZE, /* MM_ACK */
+};
+
+static void command_dispatch( autofs_protocol_state_t *protocol );
+
+static int
+adjust_inqueue( int cmd )
+{
+	return command_sizes[ cmd ];
+}
+
+
+/*
+ * XXX: FIXME: This is a big nasty. (ADAM)
+ * This parses input from the data buffers (queues),
+ * and dispatches out the results to complete command handlers.
+ * This could DEFINATELY be fixed up by somebody at some point.
+ */
+
+void
+parse_user_message( autofs_protocol_state_t *protocol )
+{
+	$cleanup_init_size( 8 );
 
+	autofs_instance_t	*instance;
+	autofs_dev_bufs_t	*buffers;
+	autofs_transaction_t	*txns;
+	queue			*q;
+
+	struct message_header	*mesg;
+
+	int error;
+	int cnt;
+
+	error= 0;
+	cnt=0;
+
+
+	instance=	AUTOFS_GET_INSTANCE( PROTOCOL, protocol );
+	buffers=	AUTOFS_GET_BUFFERS( PROTOCOL, protocol );
+	txns=		AUTOFS_GET_TXNS( PROTOCOL, protocol );
+
+	q=		buffers->input;
+
+	
+
+	/** use state machine here. **/
+	switch( protocol->current_state )
+	{
+		case PROTOCOL_WAITING:
+			/* Allocate a message header */
+			mesg= malloc( sizeof( struct message_header ),
+					M_AUTOFS_TRANSACTION_BUFFER,
+					M_WAITOK | M_ZERO );
+			$cleanup
+			(
+				free( mesg, M_AUTOFS_TRANSACTION_BUFFER );
+				protocol->message= NULL;
+			);
+			protocol->message= mesg;
+
+			if( autofs_queue_remaining( q ) <
+					( sizeof( struct message_header ) -
+					TRIM_SIZE ) )
+			{
+				$return;
+			}
+			autofs_queue_read( q, (void *) mesg,
+					sizeof( struct message_header ) -
+					sizeof( void * ) );
+
+			protocol->curr_cmd_id= mesg->message_type;
+			protocol->bytes_read= sizeof( struct message_header ) -
+					sizeof( void * );
+			protocol->max_bytes_to_read= sizeof( struct
+					message_header ) - sizeof( void * );
+
+			protocol->max_bytes_to_read+= adjust_inqueue(
+					protocol->curr_cmd_id );
+
+			/** FALLTHROUGH **/
+		case PROTOCOL_READING:
+			mesg= protocol->message;
+			
+			while( ( autofs_queue_remaining( q ) != 0) &&
+					( protocol->bytes_read <
+					protocol->max_bytes_to_read ) )
+			{
+				cnt= MIN( ( protocol->max_bytes_to_read -
+						protocol->bytes_read ),
+						autofs_queue_remaining( q ) );
+
+				autofs_queue_read( q, (void *) &( (char *)
+						mesg )[ protocol->bytes_read ],
+						cnt );
+				protocol->bytes_read+= cnt;
+			}
+
+			/*
+			 * Command dispatch will parse what is read so far
+			 * and see if we need to do any more parsing.  It
+			 * will adjust the protocol fields appropriately, and
+			 * also free the message buffer on success.
+			 */
+			
+			command_dispatch( protocol );
+
+			break;
+
+			
+			
+
+		case PROTOCOL_ERROR:
+			panic( "Autofs protocol halted!" );
+			break;
+
+		case PROTOCOL_UNDEFINED:
+
+			DEBUG EPRINTF( "AutoFS protocol error!\n" ); 
+
+			/** FALLTHROUGH **/
+		default:
+			/** NOTREACHED **/
+
+			panic( "Autofs protocol invalid state!" );
+			break;
+	}
+
+	return;
+}
+
+
+static void
+command_dispatch( autofs_protocol_state_t *protocol )
+{
+	autofs_instance_t		*instance;
+	int		cnt;
+
+	cnt= 0;
+	instance=	AUTOFS_GET_INSTANCE( PROTOCOL, protocol );
+
+	if( protocol->bytes_read < protocol->max_bytes_to_read )
+	{
+		/* Nothing to do yet.  Not done reading! */
+		DEBUG9	EPRINTF( "Stalling out, incomplete message.\n" );
+		return;
+	}
+
+	DEBUG9 EPRINTF( "Command encountered, with sufficient length, run "
+			"more tests...\n" );
+
+	switch( protocol->curr_cmd_id )
+	{
+		case COMMAND_ACK:
+			DEBUG4 EPRINTF( "Encountered an ACK command.\n" );
+			/* Do Ack appropriate stuff */
+			break;
+
+		case COMMAND_MOUNT_REQUEST:
+			DEBUG6 EPRINTF( "Encountered MOUNT_DONE command.\n" );
+			break;
+
+		case COMMAND_GREETING_RESPONSE:
+			DEBUG6 EPRINTF( "Encountered GREETING_RESPONSE command."
+					"  Number of mountpoints:\n" );
+			break;
+
+
+		default:
+			/** NOTREACHED **/
+
+			DEBUG4 EPRINTF( "Encountered an unknown command id: "
+					"%d!\n", protocol->curr_cmd_id );
+
+			protocol->current_state= PROTOCOL_ERROR;
+			break;
+	}
+}
+
+
 int process_mount_complete( struct message_header *, autofs_instance_t * );
 
 
 int
-send_mount_request( struct message_header *req, queue *out_buffer )
+send_mount_request( struct message_header *req, autofs_dev_bufs_t *buffers )
 {
-	struct mount_request *mb= (struct mount_request *) req->message_data;
+	struct mount_request *mb;
+	queue *out_buffer;
+
+	out_buffer= buffers->output;
+	mb= (struct mount_request *) req->message_data;
 
 	write_buffer( out_buffer, (void *) req,
 			sizeof( struct message_header ) );
@@ -59,7 +275,6 @@
 }
 
 
-#define BOGUS ( 0xDEADBEEF )
 
 int
 process_mount_complete( struct message_header *req,

==== //depot/projects/soc2006/adamartin_autofs/autofs/protocol.h#8 (text+ko) ====

@@ -226,10 +226,13 @@
 };
 
 
+#ifdef	_KERNEL
+#include "autofs_types.h"
 #include "autofs_subr.h"
 
-int send_mount_request( struct message_header *req, queue *q );
+int send_mount_request( struct message_header *req, autofs_dev_bufs_t *buffer );
 
-int parse_user_message( void );
+void parse_user_message( autofs_protocol_state_t *protocol );
+#endif
 
 #endif	/*** AUTOFS_PROTOCOL_HEADER ***/

==== //depot/projects/soc2006/adamartin_autofs/templatefs/templatefs.c#3 (text+ko) ====

@@ -77,6 +77,9 @@
 
 static MALLOC_DEFINE(M_TFSNODES, "tfs_nodes", "templatefs nodes");
 
+MALLOC_DECLARE(M_TFSINFO);
+MALLOC_DEFINE(M_TFSINFO, "tfs_info", "Template fs superblock info");
+
 SYSCTL_NODE(_vfs, OID_AUTO, tfs, CTLFLAG_RW, 0,
     "templatefs");
 
@@ -84,6 +87,8 @@
 #error "TFS_FSNAMELEN is not equal to MFSNAMELEN"
 #endif
 
+#define		SLASH		( '/' )
+
 /*
  * Add a node to a directory
  */
@@ -286,7 +291,7 @@
 }
 
 /*
- * Mount a pseudofs instance
+ * Mount a templatefs instance
  */
 int
 tfs_mount(struct tfs_info *ti, struct mount *mp, struct thread *td)
@@ -318,7 +323,7 @@
 }
 
 /*
- * Unmount a pseudofs instance
+ * Unmount a templatefs instance
  */
 int
 tfs_unmount(struct mount *mp, int mntflags, struct thread *td)
@@ -358,48 +363,118 @@
 	return (0);
 }
 
+
 /*
- * Initialize a (static) pseudofs instance
+ * Create an on-the-fly independent instance of a TemplateFS derivative
+ */
+
+int
+tfs_create_instance(struct tfs_info **pti)
+{
+	struct tfs_node *root;
+	struct tfs_info *ti;
+	int error;
+
+	error= 0;
+
+	/* Insulate against returning free'd memory in case of error. */
+	*pti= NULL;
+
+	ti = malloc(sizeof (struct tfs_info), M_TFSINFO, M_WAITOK|M_ZERO);
+	/* Don't set the pti value here...  wait for the rest to go kosher. */
+
+	mtx_init(&ti->ti_mutex, "templatefs", NULL, MTX_DEF);
+
+	/*
+	 * TODO: Must populate the tfs_info struct, beyond just
+	 * the root-vnode
+	 */
+
+
+	/* XXX: What else from tfs_init is needed? */
+	MALLOC(root, struct tfs_node *, sizeof *root,
+	    M_TFSNODES, M_WAITOK|M_ZERO);
+
+	root->tn_type = tfstype_root;
+	root->tn_name[0] = SLASH;
+	root->tn_info = ti;
+	if (_tfs_fixup_dir(root) != 0) {
+		FREE(root, M_TFSNODES);
+		return (ENODEV);	/** XXX Based upon tfs_init's errno **/
+	}
+	ti->ti_root = root;
+	tfs_fileno_init(ti);
+
+	/* Finally we can set the pti, since we know all is good. */
+	*pti= ti; 
+	return 0;
+}
+
+/*
+ * Initialize a (static) templatefs instance
  * ADAM -- if it's static, then this is bad... we need it at dynamic time.
  */
 int
 tfs_init(struct tfs_info *ti, struct vfsconf *vfc)
 {
-	struct tfs_node *root;
+	/* XXX: Removed, because tfs_create_instance() does this! */
+	/* struct tfs_node *root; */
 	int error;
 
-	mtx_init(&ti->ti_mutex, "pseudofs", NULL, MTX_DEF);
+	error = 0;
+
+	mtx_init(&ti->ti_mutex, "templatefs", NULL, MTX_DEF);
 
 	/** TODO, should this be moved to mount?  How much of it? **/
 	/* set up the root diretory */
+
+	#ifdef KEEP_TFS_INIT_VNODE
 	MALLOC(root, struct tfs_node *, sizeof *root,
 	    M_TFSNODES, M_WAITOK|M_ZERO);
 	root->tn_type = tfstype_root;
-	root->tn_name[0] = '/';
+	root->tn_name[0] = SLASH;
 	root->tn_info = ti;
 	if (_tfs_fixup_dir(root) != 0) {
 		FREE(root, M_TFSNODES);
 		return (ENODEV); /* XXX not really the right errno */
 	}
 	ti->ti_root = root;
+	#else
+	ti->ti_root = NULL;
+	#endif
 
 	/* construct file hierarchy */
-	error = (ti->ti_init)(ti, vfc);
+	/* error = (ti->ti_init)(ti, vfc); */
 	if (error) {
-		tfs_destroy(root);
+		/* tfs_destroy(root); */
 		ti->ti_root = NULL;
 		mtx_destroy(&ti->ti_mutex);
 		return (error);
 	}
 
+	#ifdef KEEP_TFS_INIT_VNODE
 	tfs_fileno_init(ti);
+	#endif
 	if (bootverbose)
 		printf("%s registered\n", ti->ti_name);
 	return (0);
 }
 
 /*
- * Destroy a pseudofs instance
+ * Destroy a templatefs instance 
+ */
+
+int
+tfs_destroy_instance(struct tfs_info **pti)
+{
+	printf("Bugaboo!  Unsure what to do here.\n");
+	/* See what from uninit is needed. */
+
+	return ENOSYS;
+}
+
+/*
+ * Destroy a templatefs instance (Static, again!)
  */
 int
 tfs_uninit(struct tfs_info *ti, struct vfsconf *vfc)

==== //depot/projects/soc2006/adamartin_autofs/templatefs/templatefs.h#2 (text+ko) ====

@@ -270,6 +270,14 @@
 int		 tfs_init	(struct tfs_info *ti, struct vfsconf *vfc);
 int		 tfs_uninit	(struct tfs_info *ti, struct vfsconf *vfc);
 
+
+/*
+ * TemplateFS initialization, and instantiation primitives (and cleanup)
+ */
+
+int tfs_create_instance(struct tfs_info **pti);
+int tfs_destroy_instance(struct tfs_info **pti);
+
 /*
  * Directory structure construction and manipulation
  */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200701170243.l0H2h9OI048176>