root/branches/Orange-Elaine-Distr-Dir-Branch/src/common/misc/server-config.c @ 8544

Revision 8544, 142.2 KB (checked in by elaine, 3 years ago)

Merged in changes from Orange-Branch. There were a number of bugs fixed there since this branch was created.

Line 
1/*
2 * (C) 2001 Clemson University and The University of Chicago
3 *
4 * See COPYING in top-level directory.
5 */
6
7#include <stdio.h>
8#include <string.h>
9#include <errno.h>
10#include <stdlib.h>
11#include <unistd.h>
12#include <sys/stat.h>
13#include <fcntl.h>
14#include <assert.h>
15#include <ctype.h>
16
17#include "src/common/dotconf/dotconf.h"
18#include "server-config.h"
19#include "pvfs2.h"
20#include "job.h"
21#include "trove.h"
22#include "gossip.h"
23#include "extent-utils.h"
24#include "mkspace.h"
25#include "pint-distribution.h"
26#include "pvfs2-config.h"
27#include "pvfs2-server.h"
28#include "pvfs2-internal.h"
29
30#ifdef WITH_OPENSSL
31#include "openssl/evp.h"
32#endif
33
34static const char * replace_old_keystring(const char * oldkey);
35
36static DOTCONF_CB(get_logstamp);
37static DOTCONF_CB(get_storage_path);
38static DOTCONF_CB(get_data_path);
39static DOTCONF_CB(get_meta_path);
40static DOTCONF_CB(enter_defaults_context);
41static DOTCONF_CB(exit_defaults_context);
42#ifdef USE_TRUSTED
43static DOTCONF_CB(enter_security_context);
44static DOTCONF_CB(exit_security_context);
45#endif
46static DOTCONF_CB(enter_aliases_context);
47static DOTCONF_CB(exit_aliases_context);
48static DOTCONF_CB(enter_filesystem_context);
49static DOTCONF_CB(exit_filesystem_context);
50static DOTCONF_CB(enter_storage_hints_context);
51static DOTCONF_CB(exit_storage_hints_context);
52static DOTCONF_CB(enter_export_options_context);
53static DOTCONF_CB(exit_export_options_context);
54static DOTCONF_CB(enter_server_options_context);
55static DOTCONF_CB(exit_server_options_context);
56static DOTCONF_CB(enter_mhranges_context);
57static DOTCONF_CB(exit_mhranges_context);
58static DOTCONF_CB(enter_dhranges_context);
59static DOTCONF_CB(exit_dhranges_context);
60static DOTCONF_CB(enter_distribution_context);
61static DOTCONF_CB(exit_distribution_context);
62static DOTCONF_CB(get_unexp_req);
63static DOTCONF_CB(get_tcp_buffer_send);
64static DOTCONF_CB(get_tcp_buffer_receive);
65static DOTCONF_CB(get_tcp_bind_specific);
66static DOTCONF_CB(get_perf_update_interval);
67static DOTCONF_CB(get_root_handle);
68static DOTCONF_CB(get_name);
69static DOTCONF_CB(get_logfile);
70static DOTCONF_CB(get_logtype);
71static DOTCONF_CB(get_event_logging_list);
72static DOTCONF_CB(get_event_tracing);
73static DOTCONF_CB(get_filesystem_collid);
74static DOTCONF_CB(get_alias_list);
75static DOTCONF_CB(check_this_server);
76#ifdef USE_TRUSTED
77static DOTCONF_CB(get_trusted_portlist);
78static DOTCONF_CB(get_trusted_network);
79#endif
80static DOTCONF_CB(get_range_list);
81static DOTCONF_CB(get_bmi_module_list);
82static DOTCONF_CB(get_flow_module_list);
83
84static DOTCONF_CB(get_root_squash);
85static DOTCONF_CB(get_root_squash_exceptions);
86static DOTCONF_CB(get_read_only);
87static DOTCONF_CB(get_all_squash);
88static DOTCONF_CB(get_anon_gid);
89static DOTCONF_CB(get_anon_uid);
90
91static DOTCONF_CB(get_handle_recycle_timeout_seconds);
92static DOTCONF_CB(get_flow_buffer_size_bytes);
93static DOTCONF_CB(get_flow_buffers_per_flow);
94static DOTCONF_CB(get_attr_cache_keywords_list);
95static DOTCONF_CB(get_attr_cache_size);
96static DOTCONF_CB(get_attr_cache_max_num_elems);
97static DOTCONF_CB(get_trove_sync_meta);
98static DOTCONF_CB(get_trove_sync_data);
99static DOTCONF_CB(get_file_stuffing);
100static DOTCONF_CB(get_db_cache_size_bytes);
101static DOTCONF_CB(get_trove_max_concurrent_io);
102static DOTCONF_CB(get_db_cache_type);
103static DOTCONF_CB(get_param);
104static DOTCONF_CB(get_value);
105static DOTCONF_CB(get_default_num_dfiles);
106static DOTCONF_CB(get_immediate_completion);
107static DOTCONF_CB(get_server_job_bmi_timeout);
108static DOTCONF_CB(get_server_job_flow_timeout);
109static DOTCONF_CB(get_client_job_bmi_timeout);
110static DOTCONF_CB(get_client_job_flow_timeout);
111static DOTCONF_CB(get_precreate_batch_size);
112static DOTCONF_CB(get_precreate_low_threshold);
113static DOTCONF_CB(get_client_retry_limit);
114static DOTCONF_CB(get_client_retry_delay);
115static DOTCONF_CB(get_secret_key);
116static DOTCONF_CB(get_coalescing_high_watermark);
117static DOTCONF_CB(get_coalescing_low_watermark);
118static DOTCONF_CB(get_trove_method);
119static DOTCONF_CB(get_small_file_size);
120static DOTCONF_CB(directio_thread_num);
121static DOTCONF_CB(directio_ops_per_queue);
122static DOTCONF_CB(directio_timeout);
123
124static FUNC_ERRORHANDLER(errorhandler);
125const char *contextchecker(command_t *cmd, unsigned long mask);
126
127/* internal helper functions */
128static int is_valid_alias(PINT_llist * host_aliases, char *str);
129static int is_valid_handle_range_description(char *h_range);
130static void free_host_handle_mapping(void *ptr);
131static void free_host_alias(void *ptr);
132static void free_filesystem(void *ptr);
133static void copy_filesystem(
134    struct filesystem_configuration_s *dest_fs,
135    struct filesystem_configuration_s *src_fs);
136static int cache_config_files(
137    struct server_configuration_s *config_s,
138    char *global_config_filename);
139static int is_populated_filesystem_configuration(
140    struct filesystem_configuration_s *fs);
141static int is_root_handle_in_a_meta_range(
142    struct server_configuration_s *config_s,
143    struct filesystem_configuration_s *fs);
144static int is_valid_filesystem_configuration(
145    struct server_configuration_s *config_s,
146    struct filesystem_configuration_s *fs);
147static char *get_handle_range_str(
148    struct server_configuration_s *config_s,
149    struct filesystem_configuration_s *fs,
150    int meta_handle_range);
151static host_alias_s *find_host_alias_ptr_by_alias(
152    struct server_configuration_s *config_s,
153    char *alias,
154    int *index);
155static struct host_handle_mapping_s *get_or_add_handle_mapping(
156    PINT_llist *list,
157    char *alias);
158static int build_extent_array(
159    char *handle_range_str,
160    PVFS_handle_extent_array *handle_extent_array);
161
162#ifdef __PVFS2_TROVE_SUPPORT__
163static int is_root_handle_in_my_range(
164    struct server_configuration_s *config_s,
165    struct filesystem_configuration_s *fs);
166#endif
167
168/* PVFS2 servers are deployed using configuration files that provide information
169 * about the file systems, storage locations and endpoints that each server
170 * manages.  For every pvfs2 deployment, there should be a global config file
171 * (<i>fs.conf</i>) shared across all of the pvfs2 servers. When the servers
172 * are started up, a command line parameter (server-alias) indicates what options
173 * are relevant and applicable for a particular server.
174 * This parameter will be used by the server to parse relevant options.
175 * Configuration options in the global config files have the following format:
176 *
177 * <pre>
178 * OptionName OptionValue
179 * </pre>
180 *
181 * An option cannot span more than one line, and only one option can
182 * be specified on each line.  The <i>OptionValue</i> should
183 * be formatted based on the option's type:
184 *
185 * <ul>
186 * <li>Integer - must be an integer value
187 * <li>String - must be a string without breaks (newlines)
188 * <li>List - a set of strings separated by commas
189 * </ul>
190 *
191 * Options are grouped together using contexts, and usually
192 * indented within a context for clarity.  A context is started
193 * with a context start tag, and ended with a context end tag:
194 *
195 * <pre>
196 * &lt;ContextName&gt;
197 *     Option1Name Option1Value
198 *     Option2Name Option2Value
199 * &lt;/ContextName&gt;
200 * </pre>
201 *
202 * Options are required to be defined within a specified context
203 * or set of contexts.
204 * Sub-contexts can also be specified, and must be defined within
205 * their specified parent context.  For example, the <i>Range</i> option is
206 * specified in either the <i>DataHandleRanges</i> or <i>MetaHandleRanges</i>
207 * contexts.  Both of
208 * those contexts are specified to be defined in the <i>FileSystem</i> context.
209 * Details of the required context an option or sub-context must be defined in
210 * are given in the <a href="#OptionDetails">Option Details</a> section.
211 *
212 * Options and contexts that appear in the top-level (not defined within
213 * another context) are considered to be defined in a special <i>Global</i>
214 * context.  Many options are only specified to appear within
215 * the <a name="Default">Default</a> context,
216 * which is a context that allows a default value to be specified for certain
217 * options.
218 *
219 * The options detailed below each specify their type, the context
220 * where they appear, a default value, and description.  The default
221 * value is used if the option is not specified in any of the config files.
222 * Options without default values are required to be defined in the
223 * config file.
224 */
225static const configoption_t options[] =
226{
227    /* Options specified within the Defaults context are used as
228     * default values over all the pvfs2 server specific config files.
229     */
230    {"<Defaults>",ARG_NONE, enter_defaults_context,NULL,CTX_GLOBAL,NULL},
231
232    /* Specifies the end-tag for the Defaults context.
233     */
234    {"</Defaults>",ARG_NONE, exit_defaults_context,NULL,CTX_DEFAULTS,NULL},
235
236#ifdef USE_TRUSTED
237    /* Options specified within the Security context are used to dictate
238     * whether the pvfs2
239     * servers will accept or handle file-system requests.
240     * This section is optional and does not need to be specified.
241     */
242    {"<Security>",ARG_NONE, enter_security_context,NULL,CTX_GLOBAL,NULL},
243
244    /* Specifies the end-tag for the Security context.
245     */
246    {"</Security>",ARG_NONE, exit_security_context,NULL,CTX_SECURITY,NULL},
247   
248    /* Specifies the range of ports in the form of a range of 2 integers
249     * from which the connections are going to be accepted and serviced.
250     * The format of the TrustedPorts option is:
251     *
252     * TrustedPorts StartPort-EndPort
253     *
254     * As an example:
255     *
256     * TrustedPorts 0-65535
257     */
258    {"TrustedPorts",ARG_STR, get_trusted_portlist,NULL,
259        CTX_SECURITY,NULL},
260   
261    /* Specifies the IP network and netmask in the form of 2 BMI addresses from
262     * which the connections are going to be accepted and serviced.
263     * The format of the TrustedNetwork option is:
264     *
265     * TrustedNetwork bmi-network-address@bmi-network-mask
266     *
267     * As an example:
268     *
269     * TrustedNetwork tcp://192.168.4.0@24
270     */
271    {"TrustedNetwork",ARG_LIST, get_trusted_network,NULL,
272        CTX_SECURITY,NULL},
273#endif
274
275    /* This groups the Alias mapping options.
276     *
277     * The Aliases context should be defined before any FileSystem contexts
278     * are defined, as options in the FileSystem context usually need to
279     * reference the aliases defined in this context.
280     */
281    {"<Aliases>",ARG_NONE, enter_aliases_context,NULL,CTX_GLOBAL,NULL},
282
283    /* Specifies the end-tag for the Aliases context.
284     */
285    {"</Aliases>",ARG_NONE, exit_aliases_context,NULL,CTX_ALIASES,NULL},
286
287    /* Specifies an alias in the form of a non-whitespace string that
288     * can be used to reference a BMI server address (a HostID).  This
289     * allows us to reference individual servers by an alias instead of their
290     * full HostID.  The format of the Alias option is:
291     *
292     * Alias {alias string} {bmi address}
293     *
294     * As an example:
295     *
296     * Alias mynode1 tcp://hostname1.clustername1.domainname:12345
297     */
298    {"Alias",ARG_LIST, get_alias_list,NULL,CTX_ALIASES,NULL},
299
300    /* Defines the server alias for the server specific options that
301     * are to be set within the ServerOptions context.
302     */
303    {"Server", ARG_STR, check_this_server, NULL, CTX_SERVER_OPTIONS, NULL},
304
305    /* This groups the Server specific options.
306     *
307     * The ServerOptions context should be defined after the Alias mappings
308     * have been defined. The reason is that the ServerOptions context is
309     * defined in terms of the aliases defined in that context.
310     *
311     * Default options applicable to all servers can be overridden on
312     * a per-server basis in the ServerOptions context.
313     * To illustrate:
314     * Suppose the Option name is X, its default value is Y,
315     * and one wishes to override the option for a server to Y'.
316     *
317     * <Defaults>
318     *     ..
319     *     X  Y
320     *     ..
321     * </Defaults>
322     *
323     * <ServerOptions>
324     *     Server {server alias}
325     *     ..
326     *     X Y'
327     *     ..
328     * </ServerOptions>
329     *
330     * The ServerOptions context REQUIRES the Server option specify
331     * the server alias, which sets the remaining options specified
332     * in the context for that server.
333    */
334    {"<ServerOptions>",ARG_NONE,enter_server_options_context,NULL,
335        CTX_GLOBAL, NULL},
336    /* Specifies the end-tag of the ServerOptions context.
337     */
338    {"</ServerOptions>",ARG_NONE,exit_server_options_context,NULL,
339        CTX_SERVER_OPTIONS,NULL},
340
341    /* This groups options specific to a filesystem.  A pvfs2 server may manage
342     * more than one filesystem, so a config file may have more than
343     * one Filesystem context, each defining the parameters of a different
344     * Filesystem.
345     */
346    {"<FileSystem>",ARG_NONE, enter_filesystem_context,NULL,CTX_GLOBAL,NULL},
347
348    /* Specifies the end-tag of a Filesystem context.
349     */
350    {"</FileSystem>",ARG_NONE, exit_filesystem_context,NULL,CTX_FILESYSTEM,
351        NULL},
352
353     /* Specifies the beginning of a ExportOptions context.
354      * This groups options specific to a filesystem and related to the behavior
355      * of how it gets exported to various clients. Most of these options
356      * will affect things like what uids get translated to and so on..
357      */
358     {"<ExportOptions>",ARG_NONE, enter_export_options_context, NULL,CTX_FILESYSTEM,
359         NULL},
360 
361     /* Specifies the end-tag of the ExportOptions context.
362      */
363     {"</ExportOptions>",ARG_NONE, exit_export_options_context, NULL,CTX_EXPORT,
364         NULL},
365 
366    /* This groups
367     * options specific to a filesystem and related to the behavior of the
368     * storage system.  Mostly these options are passed directly to the
369     * TROVE storage module which may or may not support them.  The
370     * DBPF module (currently the only TROVE module available) supports
371     * all of them.
372     */
373    {"<StorageHints>",ARG_NONE, enter_storage_hints_context,NULL,
374        CTX_FILESYSTEM,NULL},
375
376    /* Specifies the end-tag of the StorageHints context.
377     */
378    {"</StorageHints>",ARG_NONE, exit_storage_hints_context,NULL,
379        CTX_STORAGEHINTS,NULL},
380
381    /* This context groups together the Range options that define valid values
382     * for meta handles on a per-host basis for this filesystem.
383     *
384     * The MetaHandleRanges context is required to be present in a
385     * Filesystem context.
386     */
387    {"<MetaHandleRanges>",ARG_NONE, enter_mhranges_context,NULL,
388        CTX_FILESYSTEM,NULL},
389
390    /* Specifies the end-tag for the MetaHandleRanges context.
391     */
392    {"</MetaHandleRanges>",ARG_NONE, exit_mhranges_context,NULL,
393        CTX_METAHANDLERANGES,NULL},
394
395    /* This context groups together the Range options that define valid values
396     * for the data handles on a per-host basis for this filesystem.
397     *
398     * A DataHandleRanges context is required to be present in a
399     * Filesystem context.
400     */
401    {"<DataHandleRanges>",ARG_NONE, enter_dhranges_context,NULL,
402        CTX_FILESYSTEM,NULL},
403
404    /* Specifies the end-tag for the DataHandleRanges context.
405     */
406    {"</DataHandleRanges>",ARG_NONE, exit_dhranges_context,NULL,
407        CTX_DATAHANDLERANGES,NULL},
408
409    /* Provides a context for defining the filesystem's default
410     * distribution to use and the parameters to be set for that distribution.
411     *
412     * Valid options within the Distribution context are Name, Param, and Value.
413     *
414     * This context is an optional context within the Filesystem context.  If
415     * not specified, the filesystem defaults to the simple-stripe distribution.
416     */
417    {"<Distribution>",ARG_NONE, enter_distribution_context,NULL,
418        CTX_FILESYSTEM,NULL},
419
420    /* Specifies the end-tag for the Distribution context.
421     */
422    {"</Distribution>",ARG_NONE, exit_distribution_context,NULL,
423        CTX_DISTRIBUTION,NULL},
424
425    /* As logical files are created in pvfs, the data files and meta files
426     * that represent them are given filesystem unique handle values.  The
427     * user can specify a range of values (or set of ranges)
428     * to be allocated to data files and meta files for a particular server,
429     * using the Range option in the DataHandleRanges and MetaHandleRanges
430     * contexts.  Note that in most cases, its easier to let the
431     * pvfs2-genconfig script determine the best ranges to specify.
432     *
433     * This option specifies a range of handle values that can be used for
434     * a particular pvfs server in a particular context (meta handles
435     * or data handles).  The DataHandleRanges and MetaHandleRanges contexts
436     * should contain one or more Range options.  The format is:
437     *
438     * Range {alias} {min value1}-{max value1}[, {min value2}-{max value2},...]
439     *
440     * Where {alias} is one of the alias strings already specified in the
441     * Aliases context.
442     *
443     * {min value} and {max value} are positive integer values that specify
444     * the range of possible handles that can be given out for that particular
445     * host.  {max value} must be less than 18446744073709551615 (UINT64_MAX).
446     *
447     * As shown in the specified format, multiple ranges can be specified for
448     * the same alias.  The format requires that max value of a given range
449     * is less than the min value of the next one,
450     * i.e. {max value1}<{min value2}
451     *
452     * Example of a Range option for data handles:
453     *
454     * Range mynode1 2147483651-4294967297
455     */
456    {"Range",ARG_LIST, get_range_list,NULL,
457        CTX_METAHANDLERANGES|CTX_DATAHANDLERANGES,NULL},
458
459    /* Specifies the handle value for the root of the Filesystem.  This
460     * is a required option in the Filesystem context.  The format is:
461     *
462     * RootHandle {handle value}
463     *
464     * Where {handle value} is a positive integer no greater than
465     * 18446744073709551615 (UIN64_MAX).
466     *
467     * In general its best to let the pvfs-genconfig script specify a
468     * RootHandle value for the filesystem.
469     */
470    {"RootHandle",ARG_STR, get_root_handle,NULL,
471        CTX_FILESYSTEM,NULL},
472
473    /* This option specifies the name of the particular filesystem or
474     * distribution that its defined in.  It is a required option in
475     * Filesystem and Distribution contexts.
476     */
477    {"Name",ARG_STR, get_name,NULL,
478        CTX_FILESYSTEM|CTX_DISTRIBUTION,NULL},
479
480    /* A pvfs server may manage more than one filesystem, and so a
481     * unique identifier is used to represent each one. 
482     * This option specifies such an ID (sometimes called a 'collection
483     * id') for the filesystem it is defined in. 
484     *
485     * The ID value can be any positive integer, no greater than
486     * 2147483647 (INT32_MAX).  It is a required option in the Filesystem
487     * context.
488     */
489    {"ID",ARG_INT, get_filesystem_collid,NULL,
490        CTX_FILESYSTEM,NULL},
491
492    /* maximum number of AIO operations that Trove will allow to run
493     * concurrently
494     */
495    {"TroveMaxConcurrentIO", ARG_INT, get_trove_max_concurrent_io, NULL,
496        CTX_DEFAULTS|CTX_SERVER_OPTIONS,"16"},
497
498    /* The gossip interface in pvfs allows users to specify different
499     * levels of logging for the pvfs server.  The output of these
500     * different log levels is written to a file, which is specified in
501     * this option.  The value of the option must be the path pointing to a
502     * file with valid write permissions.  The Logfile option can be
503     * specified for all the pvfs servers in the Defaults context or for
504     * a particular server in the Global context.
505     */
506    {"LogFile",ARG_STR, get_logfile,NULL,
507        CTX_DEFAULTS|CTX_SERVER_OPTIONS,"/tmp/pvfs2-server.log"},
508
509    /* The LogType option can be used to control the destination of log
510     * messages from PVFS2 server.  The default value is "file", which causes
511     * all log messages to be written to the file specified by the LogFile
512     * parameter.  Another option is "syslog", which causes all log messages
513     * to be written to syslog.
514     */
515    {"LogType",ARG_STR, get_logtype,NULL,
516        CTX_DEFAULTS|CTX_SERVER_OPTIONS,"file"},
517
518    /* The gossip interface in pvfs allows users to specify different
519     * levels of logging for the pvfs server.  This option sets that level for
520     * either all servers (by being defined in the Defaults context) or for
521     * a particular server by defining it in the Global context.  Possible
522     * values for event logging are:
523     *
524     * __EVENTLOGGING__
525     *
526     * The value of the EventLogging option can be a comma separated list
527     * of the above values.  Individual values can also be negated with
528     * a '-'.  Examples of possible values are:
529     *
530     * EventLogging flow,msgpair,io
531     *
532     * EventLogging -storage
533     *
534     * EventLogging -flow,-flowproto
535     */
536    {"EventLogging",ARG_LIST, get_event_logging_list,NULL,
537        CTX_DEFAULTS|CTX_SERVER_OPTIONS,"none,"},
538
539    {"EnableTracing",ARG_STR, get_event_tracing,NULL,
540        CTX_DEFAULTS|CTX_SERVER_OPTIONS,"no"},
541
542    /* At startup each pvfs server allocates space for a set number
543     * of incoming requests to prevent the allocation delay at the beginning
544     * of each unexpected request.  This parameter specifies the number
545     * of requests for which to allocate space.
546     *
547     * A default value is set in the Defaults context which will be be used
548     * for all servers.
549     * However, the default value can also be overwritten by setting a separate value
550     * in the ServerOptions context using the Option tag.
551     */
552     {"UnexpectedRequests",ARG_INT, get_unexp_req,NULL,
553         CTX_DEFAULTS|CTX_SERVER_OPTIONS,"50"},
554
555    /* DEPRECATED
556     * Specifies the local path for the pvfs2 server to use as
557     * storage space for data files and metadata files. This option should not
558     * be used in conjuction with DataStorageSpace or MetadataStorageSpace.
559     * This option is only meant as a migration path for configurations where i
560     * users do not want (or don't expect to need to) modify their configuration
561     * to run this version.
562     *
563     * This option specifies the default path for all servers and will appear
564     * in the Defaults context.
565     *
566     * NOTE: This can be overridden in the <ServerOptions> tag on a per-server
567     * basis. Look at the "Option" tag for more details
568     * Example:
569     *
570     * StorageSpace /tmp/pvfs-data.storage
571     * DEPRECATED.
572     */
573    {"StorageSpace",ARG_STR, get_storage_path,NULL,
574        CTX_DEFAULTS|CTX_SERVER_OPTIONS,NULL},
575
576    /* Specifies the local path for the pvfs2 server to use as storage space
577     * for data files. This option specifies the default path for all servers
578     * and will appear in the Defaults context.
579     *
580     * NOTE: This can be overridden in the <ServerOptions> tag on a per-server
581     * basis. Look at the "Option" tag for more details
582     * Example:
583     *
584     * DataStorageSpace /tmp/pvfs-data.storage
585     */
586    {"DataStorageSpace",ARG_STR, get_data_path,NULL,
587        CTX_DEFAULTS|CTX_SERVER_OPTIONS,NULL},
588
589    /* Specifies the local path for the pvfs2 server to use as storage space
590     * for metadata files. This option specifies the default path for all
591     * servers and will appear in the Defaults context.
592     *
593     * NOTE: This can be overridden in the <ServerOptions> tag on a per-server
594     * basis. Look at the "Option" tag for more details
595     * Example:
596     *
597     * MetadataStorageSpace /tmp/pvfs-meta.storage
598     */
599    {"MetadataStorageSpace",ARG_STR, get_meta_path,NULL,
600        CTX_DEFAULTS|CTX_SERVER_OPTIONS,NULL},
601
602     /* Current implementations of TCP on most systems use a window
603      * size that is too small for almost all uses of pvfs. 
604      * We recommend administators
605      * should consider tuning the linux kernel maximum send and
606      * receive buffer sizes via the /proc settings.  The
607      * <a href="http://www.psc.edu/networking/projects/tcptune/#Linux">
608      * PSC tcp tuning section for linux</a> has good information
609      * on how to do this. 
610      *
611      * The <i>TCPBufferSend</i> and
612      * <i>TCPBufferReceive</i> options allows setting the tcp window
613      * sizes for the pvfs clients and servers, if using the
614      * system wide settings is unacceptable.  The values should be
615      * large enough to hold the full bandwidth delay product (BDP)
616      * of the network.  Note that setting these values disables
617      * tcp autotuning.  See the
618      * <a href="http://www.psc.edu/networking/projects/tcptune/#options">
619      * PSC networking options</a> for details.
620      */
621     {"TCPBufferSend",ARG_INT, get_tcp_buffer_send,NULL,
622         CTX_DEFAULTS,"0"},
623
624     /* See the <a href="#TCPBufferSend">TCPBufferSend</a> option.
625      */
626      {"TCPBufferReceive",ARG_INT, get_tcp_buffer_receive,NULL,
627         CTX_DEFAULTS,"0"},
628
629     /* If enabled, specifies that the server should bind its port only on
630      * the specified address (rather than INADDR_ANY)
631      */
632     {"TCPBindSpecific",ARG_STR, get_tcp_bind_specific,NULL,
633        CTX_DEFAULTS|CTX_SERVER_OPTIONS,"no"},
634
635     /* Specifies the timeout value in seconds for BMI jobs on the server.
636      */
637     {"ServerJobBMITimeoutSecs",ARG_INT, get_server_job_bmi_timeout,NULL,
638         CTX_DEFAULTS|CTX_SERVER_OPTIONS, "300"},
639     
640     /* Specifies the timeout value in seconds for TROVE jobs on the server.
641      */
642     {"ServerJobFlowTimeoutSecs",ARG_INT, get_server_job_flow_timeout,NULL,
643         CTX_DEFAULTS|CTX_SERVER_OPTIONS, "300"},
644     
645     /* Specifies the timeout value in seconds for BMI jobs on the client.
646      */
647     {"ClientJobBMITimeoutSecs",ARG_INT, get_client_job_bmi_timeout,NULL,
648         CTX_DEFAULTS, "300"},
649
650     /* Specifies the timeout value in seconds for FLOW jobs on the client.
651      */
652     {"ClientJobFlowTimeoutSecs",ARG_INT, get_client_job_flow_timeout,NULL,
653         CTX_DEFAULTS, "300"},
654
655     /* Specifies the number of retry attempts for operations (when possible)
656      */
657     {"ClientRetryLimit",ARG_INT, get_client_retry_limit,NULL,
658         CTX_DEFAULTS, "5"},
659
660     /* Specifies the delay in milliseconds to wait between retries.
661      */
662     {"ClientRetryDelayMilliSecs",ARG_INT, get_client_retry_delay,NULL,
663         CTX_DEFAULTS, "2000"},
664
665     /* Specifies the number of handles to be preceated at a time from each
666      * server using the batch create request. One value is specified for each
667      * type of DS handle. Order is important, it matches the order the types
668      * are defined in the PVFS_ds_type enum, which lives in
669      * include/pvfs2-types.h. If that enum changes, it must be changed here
670      * to match. Currently, this parameter follows the order:
671      * 
672      *  PVFS_TYPE_NONE
673      *  PVFS_TYPE_METAFILE
674      *  PVFS_TYPE_DATAFILE
675      *  PVFS_TYPE_DIRECTORY
676      *  PVFS_TYPE_SYMLINK
677      *  PVFS_TYPE_DIRDATA
678      *  PVFS_TYPE_INTERNAL
679      *
680      */
681     {"PrecreateBatchSize",ARG_LIST, get_precreate_batch_size,NULL,
682         CTX_DEFAULTS|CTX_SERVER_OPTIONS, "0, 32, 512, 32, 32, 32, 0" },
683 
684     /* Precreate pools will be "topped off" if they fall below this value.
685      * One value is specified for each DS handle type. This parameter operates
686      * the same as the PrecreateBatchSize in that each count coorespends to
687      * one DS handle type. The order of types is identical to the
688      * PrecreateBatchSize defined above.  */
689     {"PrecreateLowThreshold",ARG_LIST, get_precreate_low_threshold,NULL,
690         CTX_DEFAULTS|CTX_SERVER_OPTIONS, "0, 16, 256, 16, 16, 16, 0"},
691
692    /* Specifies if file stuffing should be enabled or not.  Default is
693     * enabled; this option is only provided for benchmarking purposes
694     */
695    {"FileStuffing",ARG_STR, get_file_stuffing, NULL,
696        CTX_FILESYSTEM,"yes"},
697
698     /* This specifies the frequency (in milliseconds)
699      * that performance monitor should be updated
700      * when the pvfs server is running in admin mode.
701      *
702      * Can be set in either Default or ServerOptions contexts.
703      */
704    {"PerfUpdateInterval",ARG_INT, get_perf_update_interval,NULL,
705        CTX_DEFAULTS,"1000"},
706
707    /* List the BMI modules to load when the server is started.  At present,
708     * only tcp, infiniband, and myrinet are valid BMI modules. 
709     * The format of the list is a comma separated list of one of:
710     *
711     * bmi_tcp
712     * bmi_ib
713     * bmi_gm
714     *
715     * For example:
716     *
717     * BMIModules bmi_tcp,bmi_ib
718     *
719     * Note that only the bmi modules compiled into pvfs should be
720     * specified in this list.  The BMIModules option can be specified
721     * in either the Defaults or ServerOptions contexts.
722     */
723    {"BMIModules",ARG_LIST, get_bmi_module_list,NULL, CTX_DEFAULTS,NULL},
724
725    /* List the flow modules to load when the server is started.  The modules
726     * available for loading currently are:
727     *
728     * flowproto_multiqueue - A flow module that handles all the possible flows,
729     * bmi->trove, trove->bmi, mem->bmi, bmi->mem.  At present, this is the
730     * default and only available flow for production use.
731     *
732     * flowproto_bmi_cache - A flow module that enables the use of the NCAC
733     * (network-centric adaptive cache) in the pvfs server.  Since the NCAC
734     * is currently disable and unsupported, this module exists as a proof
735     * of concept only.
736     *
737     * flowproto_dump_offsets - Used for debugging, this module allows the
738     * developer to see what/when flows are being posted, without making
739     * any actual BMI or TROVE requests.  This should only be used if you
740     * know what you're doing.
741     *
742     */
743    {"FlowModules",ARG_LIST, get_flow_module_list,NULL,
744        CTX_DEFAULTS,"flowproto_multiqueue,"},
745
746    /* Specifies the format of the date/timestamp that events will have
747     * in the event log.  Possible values are:
748     *
749     * usec: [%H:%M:%S.%U]
750     *
751     * datetime: [%m/%d/%Y %H:%M:%S]
752     *
753     * thread: [%H:%M:%S.%U (%lu)]
754     *
755     * none
756     *
757     * The format of the option is one of the above values.  For example,
758     *
759     * LogStamp datetime
760     */
761    {"LogStamp",ARG_STR, get_logstamp,NULL,
762        CTX_DEFAULTS|CTX_SERVER_OPTIONS,"usec"},
763
764    /* --- end default options for all servers */
765   
766
767    /* buffer size to use for bulk data transfers */
768    {"FlowBufferSizeBytes", ARG_INT,
769         get_flow_buffer_size_bytes, NULL, CTX_FILESYSTEM,"262144"},
770
771    /* number of buffers to use for bulk data transfers */
772    {"FlowBuffersPerFlow", ARG_INT,
773         get_flow_buffers_per_flow, NULL, CTX_FILESYSTEM,"8"},
774
775    /*
776     * File-system export options
777     *
778     * Define options that will influence the way a file-system gets exported
779     * to the rest of the world.
780     */
781
782    /* RootSquash option specifies whether the exported file-system needs to
783    *  squash accesses by root. This is an optional parameter that needs
784    *  to be specified as part of the ExportOptions
785     * context and is a list of BMI URL specification of client addresses
786     * for which RootSquash has to be enforced.
787     *
788     * RootSquash tcp://192.168.2.0@24 tcp://10.0.0.* tcp://192.168.* ...
789     */
790    {"RootSquash", ARG_LIST, get_root_squash, NULL,
791        CTX_EXPORT, ""},
792 
793    /* RootSquashExceptions option specifies exceoptions to the RootSquash
794     * list. This is an optional parameter that needs to be specified as
795     * part of the ExportOptions context and is a list of BMI URL
796     * specification of client addresses for which RootSquash
797     * has to be enforced.
798     * RootSquash tcp://192.168.2.0@24 tcp://10.0.0.* tcp://192.168.* ...
799     */
800    {"RootSquashExceptions", ARG_LIST, get_root_squash_exceptions, NULL,
801        CTX_EXPORT, ""},
802
803    /* ReadOnly option specifies whether the exported file-system needs to
804    *  disallow write accesses from clients or anything that modifies the
805    *  state of the file-system.
806     * This is an optional parameter that needs to be specified as part of
807     * the ExportOptions context and is a list of BMI URL specification of
808     * client addresses for which ReadOnly has to be enforced.
809     * An example:
810     *
811     * ReadOnly tcp://192.168.2.0@24 tcp://10.0.0.* tcp://192.168.* ...
812     */
813    {"ReadOnly", ARG_LIST,  get_read_only,    NULL,
814        CTX_EXPORT, ""},
815
816    /* AllSquash option specifies whether the exported file-system needs to
817    *  squash all accesses to the file-system to a specified uid/gid!
818     * This is an optional parameter that needs to be specified as part of
819     * the ExportOptions context and is a list of BMI URL specification of client
820     * addresses for which AllSquash has to be enforced.
821     * An example:
822     *
823     * AllSquash tcp://192.168.2.0@24 tcp://10.0.0.* tcp://192.168.* ...
824     */
825    {"AllSquash", ARG_LIST, get_all_squash,   NULL,
826        CTX_EXPORT, ""},
827
828    /* AnonUID and AnonGID are 2 integers that tell the servers to translate
829    *  the requesting clients' uid/gid to the specified ones whenever AllSquash
830    *  is specified!
831     * If these are not specified and AllSquash is specified then the uid used
832     * will be that of nobody and gid that of nobody.
833     * An example:
834     *
835     * AnonUID 3454
836     * AnonGID 3454
837     */
838
839    {"AnonUID",  ARG_STR,  get_anon_uid,     NULL,
840        CTX_EXPORT, "65534"},
841    {"AnonGID",  ARG_STR,  get_anon_gid,     NULL,
842        CTX_EXPORT, "65534"},
843
844    /* The TROVE storage layer has a management component that deals with
845     * allocating handle values for new metafiles and datafiles.  The underlying
846     * trove module can be given a hint to tell it how long to wait before
847     * reusing handle values that have become freed up (only deleting files will
848     * free up a handle).  The HandleRecycleTimeoutSecs option specifies
849     * the number of seconds to wait for each filesystem.  This is an
850     * optional parameter that can be specified in the StorageHints context.
851     */
852    {"HandleRecycleTimeoutSecs", ARG_INT,
853         get_handle_recycle_timeout_seconds, NULL,
854         CTX_STORAGEHINTS,"360"},
855   
856    /* The TROVE layer (server side storage layer)
857     * has an attribute caching component that
858     * caches stored attributes.  This is used to improve the performance of
859     * metadata accesses.  The AttrCacheKeywords option is a list of the
860     * object types that should get cached in the attribute cache. 
861     * The possible values for this option are:
862     *
863     * dh - (datafile handles) This will cache the array of datafile handles for
864     *      each logical file in this filesystem
865     *
866     * md - (metafile distribution) This will cache (for each logical file)
867     *      the file distribution information used to create/manage
868     *      the datafiles. 
869     *
870     * de - (directory entries) This will cache the handles of
871     *      the directory entries in this filesystem
872     *
873     * st - (symlink target) This will cache the target path
874     *      for the symbolic links in this filesystem
875     *
876     * The format of this option is a comma-separated list of one or more
877     * of the above values.  For example:
878     *
879     * AttrCacheKeywords dh,md,de,st
880     */
881    {"AttrCacheKeywords",ARG_LIST, get_attr_cache_keywords_list,NULL,
882        CTX_STORAGEHINTS,
883        DATAFILE_HANDLES_KEYSTR","METAFILE_DIST_KEYSTR","
884        DIRECTORY_ENTRY_KEYSTR","SYMLINK_TARGET_KEYSTR},
885   
886    /* The attribute cache in the TROVE layer mentioned in the documentation
887     * for the AttrCacheKeywords option is managed as a hashtable.  The
888     * AttrCacheSize adjusts the number of buckets that this hashtable contains.
889     * This value can be adjusted for better performance.  A good hashtable
890     * size should always be a prime number.
891     */
892    {"AttrCacheSize",ARG_INT, get_attr_cache_size, NULL,
893        CTX_STORAGEHINTS,"511"},
894
895    /* This option specifies the max cache size of the attribute cache
896     * in the TROVE layer mentioned in the documentation
897     * for the AttrCacheKeywords option.  This value can be adjusted for
898     * better performance.
899     */
900    {"AttrCacheMaxNumElems",ARG_INT,get_attr_cache_max_num_elems,NULL,
901        CTX_STORAGEHINTS,"1024"},
902   
903    /* The TroveSyncMeta option allows users to turn off metadata
904     * synchronization with every metadata write.  This can greatly improve
905     * performance.  In general, this value should probably be set to yes,
906     * otherwise metadata transaction could be lost in the event of server
907     * failover.
908     */
909    {"TroveSyncMeta",ARG_STR, get_trove_sync_meta, NULL,
910        CTX_STORAGEHINTS,"yes"},
911
912    /* The TroveSyncData option allows users to turn off datafile
913     * synchronization with every write operation.  This can greatly improve
914     * performance, but may cause lost data in the event of server failover.
915     */
916    {"TroveSyncData",ARG_STR, get_trove_sync_data, NULL,
917        CTX_STORAGEHINTS,"yes"},
918
919    {"DBCacheSizeBytes", ARG_INT, get_db_cache_size_bytes, NULL,
920        CTX_STORAGEHINTS,"0"},
921
922    /* cache type for berkeley db environment.  "sys" and "mmap" are valid
923     * value for this option
924     */
925    {"DBCacheType", ARG_STR, get_db_cache_type, NULL,
926        CTX_STORAGEHINTS, "sys"},
927
928    /* This option specifies a parameter name to be passed to the
929     * distribution to be used.  This option should be immediately
930     * followed by a Value option.
931     */
932    {"Param", ARG_STR, get_param, NULL,
933        CTX_DISTRIBUTION,NULL},
934   
935    /* This option specifies the value of the parameter who's name
936     * was specified in the previous option.
937     */
938    {"Value", ARG_INT, get_value, NULL,
939        CTX_DISTRIBUTION,NULL},
940   
941    /* This option specifies the default number of datafiles to use
942     * when a new file is created.  The value is passed to the distribution
943     * and it determines whether to use that value or not.
944     */
945    {"DefaultNumDFiles", ARG_INT, get_default_num_dfiles, NULL,
946        CTX_FILESYSTEM,"0"},
947
948    {"ImmediateCompletion", ARG_STR, get_immediate_completion, NULL,
949        CTX_STORAGEHINTS, "no"},
950
951    {"CoalescingHighWatermark", ARG_STR, get_coalescing_high_watermark, NULL,
952        CTX_STORAGEHINTS, "8"},
953
954    {"CoalescingLowWatermark", ARG_INT, get_coalescing_low_watermark, NULL,
955        CTX_STORAGEHINTS, "1"},
956
957    /* This option specifies the method used for trove.  The method specifies
958     * how both metadata and data are stored and managed by the PVFS servers.
959     * Currently the
960     * alt-aio method is the default.  Possible methods are:
961     * <ul>
962     * <li>alt-aio.  This uses a thread-based implementation of Asynchronous IO.
963     * <li>directio.  This uses a direct I/O implementation to perform I/O
964     * operations to datafiles.  This method may give significant performance
965     * improvement if PVFS servers are running over shared storage, especially
966     * for large I/O accesses.  For local storage, including RAID setups,
967     * the alt-aio method is recommended.
968     *
969     * <li>null-aio.  This method is an implementation
970     * that does no disk I/O at all
971     * and is only useful for development or debugging purposes.  It can
972     * be used to test the performance of the network without doing I/O to disk.
973     * <li>dbpf.  Uses the system's Linux AIO implementation.  No longer
974     * recommended in production environments.
975     * </ul>
976     *
977     * Note that this option can be specified in either the <a href="#Defaults">
978     * Defaults</a> context of the main fs.conf, or in a filesystem specific
979     * <a href="#StorageHints">StorageHints</a>
980     * context, but the semantics of TroveMethod in the
981     * <a href="#Defaults">Defaults</a>
982     * context is different from other options.  The TroveMethod in the
983     * <a href="#Defaults">Defaults</a> context only specifies which
984     * method is used at
985     * server initialization.  It does not specify the default TroveMethod
986     * for all the filesystems the server supports.  To set the TroveMethod
987     * for a filesystem, the TroveMethod must be placed in the
988     * <a href="#StorageHints">StorageHints</a> context for that filesystem.
989     */
990    {"TroveMethod", ARG_STR, get_trove_method, NULL,
991        CTX_DEFAULTS|CTX_STORAGEHINTS, "alt-aio"},
992
993    /* Specifies the file system's key for use in HMAC-based digests of
994     * client operations.
995     */
996    {"SecretKey",ARG_STR, get_secret_key,NULL,CTX_FILESYSTEM,NULL},
997
998    /* Specifies the size of the small file transition point */
999    {"SmallFileSize", ARG_INT, get_small_file_size, NULL, CTX_FILESYSTEM, NULL},
1000
1001    /* Specifies the number of threads that should be started to service
1002     * Direct I/O operations.  This defaults to 30.
1003     */
1004    {"DirectIOThreadNum", ARG_INT, directio_thread_num, NULL,
1005        CTX_STORAGEHINTS, "30"},
1006
1007    /* Specifies the number of operations to service at once in Direct I/O mode.
1008     */
1009    {"DirectIOOpsPerQueue", ARG_INT, directio_ops_per_queue, NULL,
1010        CTX_STORAGEHINTS, "10"},
1011
1012    /* Specifies the timeout in Direct I/O to wait before checking the next queue. */
1013    {"DirectIOTimeout", ARG_INT, directio_timeout, NULL,
1014        CTX_STORAGEHINTS, "1000"},
1015
1016    LAST_OPTION
1017};
1018
1019/*
1020 * Function: PINT_parse_config
1021 *
1022 * Params:   struct server_configuration_s*,
1023 *           global_config_filename - common config file for all servers
1024 *                                    and clients
1025 *           server_alias_name      - alias (if any) provided for this server
1026 *                                    (ignored on client side)
1027 *
1028 * Returns:  0 on success; 1 on failure
1029 *
1030 */
1031int PINT_parse_config(
1032    struct server_configuration_s *config_obj,
1033    char *global_config_filename,
1034    char *server_alias_name)
1035{
1036    struct server_configuration_s *config_s;
1037    configfile_t *configfile = (configfile_t *)0;
1038
1039    if (!config_obj)
1040    {
1041        gossip_err("Invalid server_configuration_s object\n");
1042        return 1;
1043    }
1044
1045    /* static global assignment */
1046    config_s = config_obj;
1047    memset(config_s, 0, sizeof(struct server_configuration_s));
1048
1049    config_s->server_alias = server_alias_name;
1050    /* set some global defaults for optional parameters */
1051    config_s->logstamp_type = GOSSIP_LOGSTAMP_DEFAULT;
1052    config_s->server_job_bmi_timeout = PVFS2_SERVER_JOB_BMI_TIMEOUT_DEFAULT;
1053    config_s->server_job_flow_timeout = PVFS2_SERVER_JOB_FLOW_TIMEOUT_DEFAULT;
1054    config_s->client_job_bmi_timeout = PVFS2_CLIENT_JOB_BMI_TIMEOUT_DEFAULT;
1055    config_s->client_job_flow_timeout = PVFS2_CLIENT_JOB_FLOW_TIMEOUT_DEFAULT;
1056    config_s->client_retry_limit = PVFS2_CLIENT_RETRY_LIMIT_DEFAULT;
1057    config_s->client_retry_delay_ms = PVFS2_CLIENT_RETRY_DELAY_MS_DEFAULT;
1058    config_s->trove_max_concurrent_io = 16;
1059
1060    if (cache_config_files(config_s, global_config_filename))
1061    {
1062        return 1;
1063    }
1064    assert(config_s->fs_config_buflen && config_s->fs_config_buf);
1065
1066    /* read in the fs.conf defaults config file */
1067    config_s->configuration_context = CTX_GLOBAL;
1068    configfile = PINT_dotconf_create(config_s->fs_config_filename,
1069                                     options, (void *)config_s,
1070                                     CASE_INSENSITIVE);
1071    if (!configfile)
1072    {
1073        gossip_err("Error opening config file %s\n",
1074                   config_s->fs_config_filename);
1075        return 1;
1076    }
1077    config_s->private_data = configfile;
1078    configfile->errorhandler = (dotconf_errorhandler_t)errorhandler;
1079    configfile->contextchecker = (dotconf_contextchecker_t)contextchecker;
1080   
1081    if(PINT_dotconf_command_loop(configfile) == 0)
1082    {
1083        /* NOTE: dotconf error handler will log message */
1084        return 1;
1085    }
1086    PINT_dotconf_cleanup(configfile);
1087
1088    if (server_alias_name)
1089    {
1090        struct host_alias_s *halias;
1091        halias = find_host_alias_ptr_by_alias(
1092                                config_s, server_alias_name, &config_s->host_index);
1093        if (!halias || !halias->bmi_address)
1094        {
1095            gossip_err("Configuration file error. "
1096                       "No host ID specified for alias %s.\n", server_alias_name);
1097            return 1;
1098        }
1099        config_s->host_id = strdup(halias->bmi_address);
1100    }
1101
1102    if (server_alias_name && !config_s->data_path)
1103    {
1104        gossip_err("Configuration file error. "
1105                   "No data storage path specified for alias %s.\n", server_alias_name);
1106        return 1;
1107    }
1108
1109    if (server_alias_name && !config_s->meta_path)
1110    {
1111        gossip_err("Configuration file error. "
1112                   "No metadata storage path specified for alias %s.\n", server_alias_name);
1113        return 1;
1114    }
1115
1116    if (!config_s->bmi_modules)
1117    {
1118        gossip_err("Configuration file error. "
1119                   "No BMI modules specified.\n");
1120        return 1;
1121    }
1122
1123    /* We set to the default flow module since there's only one.
1124    */
1125    if (!config_s->flow_modules)
1126    {
1127        gossip_err("Configuration file error. No flow module specified\n");
1128        return 1;
1129    }
1130   
1131    /* Users don't need to learn about this unless they want to
1132    */
1133    if (!config_s->perf_update_interval)
1134    {
1135        gossip_err("Configuration file error.  "
1136                   "No PerfUpdateInterval specified.\n");
1137        return 1;
1138    }
1139   
1140    return 0;
1141}
1142
1143const char *contextchecker(command_t *cmd, unsigned long mask)
1144{
1145    struct server_configuration_s *config_s = cmd->context;
1146
1147    if(!(mask & config_s->configuration_context))
1148    {
1149        return "Option can't be defined in that context";
1150    }
1151    return NULL;
1152}
1153   
1154FUNC_ERRORHANDLER(errorhandler)
1155{
1156    gossip_err("Error: %s line %ld: %s", configfile->filename,
1157        configfile->line, msg);
1158    return(1);
1159}
1160
1161DOTCONF_CB(get_logstamp)
1162{
1163    struct server_configuration_s *config_s =
1164        (struct server_configuration_s *)cmd->context;
1165
1166    if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
1167       config_s->my_server_options == 0)
1168    {
1169        return NULL;
1170    }
1171    if(!strcmp(cmd->data.str, "none"))
1172    {
1173        config_s->logstamp_type = GOSSIP_LOGSTAMP_NONE;
1174    }
1175    else if(!strcmp(cmd->data.str, "usec"))
1176    {
1177        config_s->logstamp_type = GOSSIP_LOGSTAMP_USEC;
1178    }
1179    else if(!strcmp(cmd->data.str, "datetime"))
1180    {
1181        config_s->logstamp_type = GOSSIP_LOGSTAMP_DATETIME;
1182    }
1183    else if(!strcmp(cmd->data.str, "thread"))
1184    {
1185        config_s->logstamp_type = GOSSIP_LOGSTAMP_THREAD;
1186    }
1187    else
1188    {
1189        return("LogStamp tag (if specified) must have one of the following values: none, usec, or datetime.\n");
1190    }
1191
1192    return NULL;
1193}
1194
1195
1196DOTCONF_CB(get_storage_path)
1197{
1198    struct server_configuration_s *config_s =
1199        (struct server_configuration_s *)cmd->context;
1200    if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
1201       config_s->my_server_options == 0)
1202    {
1203        return NULL;
1204    }
1205
1206    if( config_s->data_path )
1207    {
1208        free(config_s->data_path);
1209    }
1210
1211    if( config_s->meta_path )
1212    {
1213        free(config_s->meta_path);
1214    }
1215
1216    config_s->data_path =
1217        (cmd->data.str ? strdup(cmd->data.str) : NULL);
1218    config_s->meta_path =
1219        (cmd->data.str ? strdup(cmd->data.str) : NULL);
1220    return NULL;
1221}
1222
1223DOTCONF_CB(get_data_path)
1224{
1225    struct server_configuration_s *config_s =
1226        (struct server_configuration_s *)cmd->context;
1227    if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
1228       config_s->my_server_options == 0)
1229    {
1230        return NULL;
1231    }
1232    if (config_s->data_path)
1233    {
1234        free(config_s->data_path);
1235    }
1236
1237    config_s->data_path =
1238        (cmd->data.str ? strdup(cmd->data.str) : NULL);
1239    return NULL;
1240}
1241
1242DOTCONF_CB(get_meta_path)
1243{
1244    struct server_configuration_s *config_s =
1245        (struct server_configuration_s *)cmd->context;
1246    if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
1247       config_s->my_server_options == 0)
1248    {
1249        return NULL;
1250    }
1251    if (config_s->meta_path)
1252    {
1253        free(config_s->meta_path);
1254    }
1255
1256    config_s->meta_path =
1257        (cmd->data.str ? strdup(cmd->data.str) : NULL);
1258    return NULL;
1259}
1260
1261DOTCONF_CB(enter_defaults_context)
1262{
1263    struct server_configuration_s *config_s =
1264        (struct server_configuration_s *)cmd->context;
1265    config_s->configuration_context = CTX_DEFAULTS;
1266
1267    return PINT_dotconf_set_defaults(
1268        cmd->configfile, CTX_DEFAULTS);
1269}
1270
1271DOTCONF_CB(exit_defaults_context)
1272{
1273    struct server_configuration_s *config_s =
1274        (struct server_configuration_s *)cmd->context;
1275    config_s->configuration_context = CTX_GLOBAL;
1276    return NULL;
1277}
1278
1279#ifdef USE_TRUSTED
1280DOTCONF_CB(enter_security_context)
1281{
1282    struct server_configuration_s *config_s =
1283        (struct server_configuration_s *)cmd->context;
1284    config_s->configuration_context = CTX_SECURITY;
1285    return NULL;
1286}
1287
1288DOTCONF_CB(exit_security_context)
1289{
1290    struct server_configuration_s *config_s =
1291        (struct server_configuration_s *)cmd->context;
1292    config_s->configuration_context = CTX_GLOBAL;
1293    return NULL;
1294}
1295#endif
1296
1297DOTCONF_CB(enter_aliases_context)
1298{
1299    struct server_configuration_s *config_s =
1300        (struct server_configuration_s *)cmd->context;
1301    config_s->configuration_context = CTX_ALIASES;
1302    return NULL;
1303}
1304
1305DOTCONF_CB(exit_aliases_context)
1306{
1307    struct server_configuration_s *config_s =
1308        (struct server_configuration_s *)cmd->context;
1309    config_s->configuration_context = CTX_GLOBAL;
1310    return NULL;
1311}
1312
1313DOTCONF_CB(enter_filesystem_context)
1314{
1315    struct server_configuration_s *config_s =
1316        (struct server_configuration_s *)cmd->context;
1317    struct filesystem_configuration_s *fs_conf = NULL;
1318
1319    if (config_s->host_aliases == NULL)
1320    {
1321        return("Error in context.  Filesystem tag cannot "
1322                   "be declared before an Aliases tag.\n");
1323    }
1324
1325    fs_conf = (struct filesystem_configuration_s *)
1326        malloc(sizeof(struct filesystem_configuration_s));
1327    assert(fs_conf);
1328    memset(fs_conf,0,sizeof(struct filesystem_configuration_s));
1329
1330    /* fill any fs defaults here */
1331    fs_conf->flowproto = FLOWPROTO_DEFAULT;
1332    fs_conf->encoding = ENCODING_DEFAULT;
1333    fs_conf->trove_sync_meta = TROVE_SYNC;
1334    fs_conf->trove_sync_data = TROVE_SYNC;
1335    fs_conf->fp_buffer_size = -1;
1336    fs_conf->fp_buffers_per_flow = -1;
1337    fs_conf->file_stuffing = 1;
1338
1339    if (!config_s->file_systems)
1340    {
1341        config_s->file_systems = PINT_llist_new();
1342    }
1343    PINT_llist_add_to_head(config_s->file_systems,(void *)fs_conf);
1344    assert(PINT_llist_head(config_s->file_systems) == (void *)fs_conf);
1345    config_s->configuration_context = CTX_FILESYSTEM;
1346
1347    return PINT_dotconf_set_defaults(
1348        cmd->configfile,
1349        CTX_FILESYSTEM);
1350}
1351
1352DOTCONF_CB(exit_filesystem_context)
1353{
1354    struct filesystem_configuration_s *fs_conf = NULL;
1355    struct server_configuration_s *config_s =
1356        (struct server_configuration_s *)cmd->context;
1357
1358    fs_conf = (struct filesystem_configuration_s *)
1359        PINT_llist_head(config_s->file_systems);
1360    assert(fs_conf);
1361
1362    /*
1363      make sure last fs config object is valid
1364      (i.e. has all required values filled in)
1365    */
1366    if (!is_populated_filesystem_configuration(fs_conf))
1367    {
1368        gossip_err("Error: Filesystem configuration is invalid!\n");
1369        return("Possible Error in context.  Cannot have /Filesystem "
1370                   "tag before all filesystem attributes are declared.\n");
1371    }
1372
1373    config_s->configuration_context = CTX_GLOBAL;
1374    return NULL;
1375}
1376
1377DOTCONF_CB(enter_storage_hints_context)
1378{
1379    struct server_configuration_s *config_s =
1380        (struct server_configuration_s *)cmd->context;
1381    config_s->configuration_context = CTX_STORAGEHINTS;
1382
1383    return PINT_dotconf_set_defaults(
1384        cmd->configfile, CTX_STORAGEHINTS);
1385}
1386
1387DOTCONF_CB(exit_storage_hints_context)
1388{
1389    struct server_configuration_s *config_s =
1390        (struct server_configuration_s *)cmd->context;
1391    config_s->configuration_context = CTX_FILESYSTEM;
1392    return NULL;
1393}
1394
1395DOTCONF_CB(enter_export_options_context)
1396{
1397    struct server_configuration_s *config_s =
1398        (struct server_configuration_s *)cmd->context;
1399    config_s->configuration_context = CTX_EXPORT;
1400
1401    return PINT_dotconf_set_defaults(
1402        cmd->configfile, CTX_EXPORT);
1403}
1404
1405DOTCONF_CB(exit_export_options_context)
1406{
1407    struct server_configuration_s *config_s =
1408        (struct server_configuration_s *)cmd->context;
1409    config_s->configuration_context = CTX_FILESYSTEM;
1410    return NULL;
1411}
1412
1413DOTCONF_CB(enter_server_options_context)
1414{
1415    struct server_configuration_s *config_s =
1416        (struct server_configuration_s *)cmd->context;
1417    config_s->configuration_context = CTX_SERVER_OPTIONS;
1418
1419    return PINT_dotconf_set_defaults(
1420        cmd->configfile, CTX_SERVER_OPTIONS);
1421}
1422
1423DOTCONF_CB(exit_server_options_context)
1424{
1425    struct server_configuration_s *config_s =
1426        (struct server_configuration_s *)cmd->context;
1427    config_s->configuration_context = CTX_GLOBAL;
1428    config_s->my_server_options = 0;
1429    return NULL;
1430}
1431
1432DOTCONF_CB(check_this_server)
1433{
1434    struct server_configuration_s *config_s =
1435        (struct server_configuration_s *)cmd->context;
1436
1437    if(is_valid_alias(config_s->host_aliases, cmd->data.str))
1438    {
1439        /* if the Server option specifies our alias, enable setting
1440         * of server specific options
1441         */
1442        if(config_s->server_alias &&
1443           strcmp(config_s->server_alias, cmd->data.str) == 0)
1444        {
1445            config_s->my_server_options = 1;
1446        }
1447    }
1448    else
1449    {
1450        return "Unrecognized alias specified.\n";
1451    }
1452    return NULL;
1453}
1454
1455DOTCONF_CB(enter_mhranges_context)
1456{
1457    struct server_configuration_s *config_s =
1458        (struct server_configuration_s *)cmd->context;
1459    config_s->configuration_context = CTX_METAHANDLERANGES;
1460    return NULL;
1461}
1462
1463DOTCONF_CB(exit_mhranges_context)
1464{
1465    struct server_configuration_s *config_s =
1466        (struct server_configuration_s *)cmd->context;
1467    struct filesystem_configuration_s *fs_conf = NULL;
1468
1469    fs_conf = (struct filesystem_configuration_s *)
1470        PINT_llist_head(config_s->file_systems);
1471    assert(fs_conf);
1472
1473    if (!fs_conf->meta_handle_ranges)
1474    {
1475        return("No valid mhandle ranges added to file system.\n");
1476    }
1477    config_s->configuration_context = CTX_FILESYSTEM;
1478    return NULL;
1479}
1480
1481DOTCONF_CB(enter_dhranges_context)
1482{
1483    struct server_configuration_s *config_s =
1484        (struct server_configuration_s *)cmd->context;
1485    config_s->configuration_context = CTX_DATAHANDLERANGES;
1486    return NULL;
1487}
1488
1489DOTCONF_CB(exit_dhranges_context)
1490{
1491    struct server_configuration_s *config_s =
1492        (struct server_configuration_s *)cmd->context;
1493    struct filesystem_configuration_s *fs_conf = NULL;
1494
1495    fs_conf = (struct filesystem_configuration_s *)
1496        PINT_llist_head(config_s->file_systems);
1497    assert(fs_conf);
1498
1499    if (!fs_conf->data_handle_ranges)
1500    {
1501        return("No valid dhandle ranges added to file system.\n");
1502    }
1503    config_s->configuration_context = CTX_FILESYSTEM;
1504    return NULL;
1505}
1506
1507DOTCONF_CB(enter_distribution_context)
1508{
1509    struct server_configuration_s *config_s =
1510        (struct server_configuration_s *)cmd->context;
1511    config_s->configuration_context = CTX_DISTRIBUTION;
1512    return NULL;
1513}
1514
1515DOTCONF_CB(exit_distribution_context)
1516{
1517    struct server_configuration_s *config_s =
1518        (struct server_configuration_s *)cmd->context;
1519    config_s->configuration_context = CTX_FILESYSTEM;
1520    return NULL;
1521}
1522
1523DOTCONF_CB(get_unexp_req)
1524{
1525    struct server_configuration_s *config_s =
1526        (struct server_configuration_s *)cmd->context;
1527    if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
1528       config_s->my_server_options == 0)
1529    {
1530        return NULL;
1531    }
1532    config_s->initial_unexpected_requests = cmd->data.value;
1533    return NULL;
1534}
1535
1536DOTCONF_CB(get_tcp_buffer_receive)
1537{
1538    struct server_configuration_s *config_s =
1539        (struct server_configuration_s *)cmd->context;
1540    config_s->tcp_buffer_size_receive = cmd->data.value;
1541    return NULL;
1542}
1543
1544DOTCONF_CB(get_tcp_buffer_send)
1545{
1546    struct server_configuration_s *config_s =
1547        (struct server_configuration_s *)cmd->context;
1548    config_s->tcp_buffer_size_send = cmd->data.value;
1549    return NULL;
1550}
1551
1552DOTCONF_CB(get_tcp_bind_specific)
1553{
1554    struct server_configuration_s *config_s =
1555        (struct server_configuration_s *)cmd->context;
1556
1557    if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
1558       config_s->my_server_options == 0)
1559    {
1560        return NULL;
1561    }
1562    if(strcasecmp(cmd->data.str, "yes") == 0)
1563    {
1564        config_s->tcp_bind_specific = 1;
1565    }
1566    else if(strcasecmp(cmd->data.str, "no") == 0)
1567    {
1568        config_s->tcp_bind_specific = 0;
1569    }
1570    else
1571    {
1572        return("TCPBindSpecific value must be 'yes' or 'no'.\n");
1573    }
1574
1575    return NULL;
1576}
1577
1578DOTCONF_CB(get_server_job_bmi_timeout)
1579{
1580    struct server_configuration_s *config_s =
1581        (struct server_configuration_s *)cmd->context;
1582    if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
1583       config_s->my_server_options == 0)
1584    {
1585        return NULL;
1586    }
1587    config_s->server_job_bmi_timeout = cmd->data.value;
1588    return NULL;
1589}
1590
1591DOTCONF_CB(get_precreate_batch_size)
1592{
1593    struct server_configuration_s *config_s =
1594        (struct server_configuration_s *)cmd->context;
1595    int i = 0, j = 0, token_count = 0, counts[7], count_count=0;
1596    char **tokens;
1597
1598    if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
1599       config_s->my_server_options == 0)
1600    {
1601        return NULL;
1602    }
1603
1604    if (config_s->precreate_batch_size != NULL)
1605    {
1606        free(config_s->precreate_batch_size);
1607        config_s->precreate_batch_size = NULL;
1608    }
1609
1610    /* so this seems silly but a config option of type ARG_LIST doesn't
1611     * split on commas (which is claimed to be the delimiter) but on white
1612     * space. That could possibly be fixed. So, until it is we have to handle
1613     * the possibility of multiple arguments with some number of values per
1614     * argument. */
1615    for(i = 0; i < cmd->arg_count; i++)
1616    {
1617        token_count = PINT_split_string_list( &tokens, cmd->data.list[i]);
1618        for(j = 0; j < token_count; ++j)
1619        {
1620            counts[count_count++] = atoi(tokens[j]);
1621        }
1622        PINT_free_string_list(tokens, token_count);
1623    }
1624
1625    /* make sure we scrounged up the right number of values */
1626    if( count_count != PVFS_DS_TYPE_COUNT )
1627    {
1628        return "PrecreateBatchSize must contain counts for each DS "
1629               "type in the order NONE, METAFILE, DATAFILE, DIRECTORY, "
1630               "SYMLINK, DIRDATA, INTERNAL\n";
1631    }
1632
1633    config_s->precreate_batch_size = calloc( PVFS_DS_TYPE_COUNT, sizeof(int));
1634    if( config_s->precreate_batch_size == NULL )
1635    {
1636        return "PrecreateBatchSize malloc failure";
1637    }
1638
1639    for( i = 0; i < count_count; i++ )
1640    {
1641        config_s->precreate_batch_size[i] = counts[i];
1642    }
1643
1644    return NULL;
1645}
1646
1647DOTCONF_CB(get_precreate_low_threshold)
1648{
1649    struct server_configuration_s *config_s =
1650        (struct server_configuration_s *)cmd->context;
1651    int i = 0, j = 0, token_count = 0, counts[7], count_count=0;
1652    char **tokens;
1653
1654    if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
1655       config_s->my_server_options == 0)
1656    {
1657        return NULL;
1658    }
1659
1660    if (config_s->precreate_low_threshold != NULL)
1661    {
1662        free(config_s->precreate_low_threshold);
1663        config_s->precreate_low_threshold = NULL;
1664    }
1665
1666    /* handle multiple values per arguments, gross */
1667    for(i = 0; i < cmd->arg_count; i++)
1668    {
1669        token_count = PINT_split_string_list( &tokens, cmd->data.list[i]);
1670        for(j = 0; j < token_count; ++j)
1671        {
1672            counts[count_count++] = atoi(tokens[j]);
1673        }
1674        PINT_free_string_list(tokens, token_count);
1675    }
1676
1677    /* make sure we scrounged up the right number of values */
1678    if( count_count != PVFS_DS_TYPE_COUNT )
1679    {
1680        return "PrecreateLowThreshold must contain counts for each DS "
1681               "type in the order NONE, METAFILE, DATAFILE, DIRECTORY, "
1682               "SYMLINK, DIRDATA, INTERNAL\n";
1683    }
1684
1685    config_s->precreate_low_threshold =
1686        calloc( PVFS_DS_TYPE_COUNT, sizeof(int));
1687    if( config_s->precreate_low_threshold == NULL )
1688    {
1689        return "PrecreateLowThreshold malloc failure";
1690    }
1691
1692    for( i = 0; i < count_count; i++ )
1693    {
1694        config_s->precreate_low_threshold[i] = counts[i];
1695    }
1696
1697    return NULL;
1698}
1699
1700DOTCONF_CB(get_server_job_flow_timeout)
1701{
1702    struct server_configuration_s *config_s =
1703        (struct server_configuration_s *)cmd->context;
1704    if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
1705       config_s->my_server_options == 0)
1706    {
1707        return NULL;
1708    }
1709    config_s->server_job_flow_timeout = cmd->data.value;
1710    return NULL;
1711}
1712
1713DOTCONF_CB(get_client_job_bmi_timeout)
1714{
1715    struct server_configuration_s *config_s =
1716        (struct server_configuration_s *)cmd->context;
1717    config_s->client_job_bmi_timeout = cmd->data.value;
1718    return NULL;
1719}
1720
1721DOTCONF_CB(get_client_job_flow_timeout)
1722{
1723    struct server_configuration_s *config_s =
1724        (struct server_configuration_s *)cmd->context;
1725    config_s->client_job_flow_timeout = cmd->data.value;
1726    return NULL;
1727}
1728
1729DOTCONF_CB(get_client_retry_limit)
1730{
1731    struct server_configuration_s *config_s =
1732        (struct server_configuration_s *)cmd->context;
1733    config_s->client_retry_limit = cmd->data.value;
1734    return NULL;
1735}
1736
1737DOTCONF_CB(get_client_retry_delay)
1738{
1739    struct server_configuration_s *config_s =
1740        (struct server_configuration_s *)cmd->context;
1741    config_s->client_retry_delay_ms = cmd->data.value;
1742    return NULL;
1743}
1744
1745DOTCONF_CB(get_perf_update_interval)
1746{
1747    struct server_configuration_s *config_s =
1748        (struct server_configuration_s *)cmd->context;
1749    config_s->perf_update_interval = cmd->data.value;
1750    return NULL;
1751}
1752
1753DOTCONF_CB(get_logfile)
1754{
1755    struct server_configuration_s *config_s =
1756        (struct server_configuration_s *)cmd->context;
1757    /* free whatever was added in set_defaults phase */
1758    if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
1759       config_s->my_server_options == 0)
1760    {
1761        return NULL;
1762    }
1763    if (config_s->logfile)
1764        free(config_s->logfile);
1765    config_s->logfile = (cmd->data.str ? strdup(cmd->data.str) : NULL);
1766    return NULL;
1767}
1768
1769DOTCONF_CB(get_logtype)
1770{
1771    struct server_configuration_s *config_s =
1772        (struct server_configuration_s *)cmd->context;
1773    /* free whatever was added in set_defaults phase */
1774    if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
1775       config_s->my_server_options == 0)
1776    {
1777        return NULL;
1778    }
1779    if (config_s->logtype)
1780        free(config_s->logtype);
1781    config_s->logtype = (cmd->data.str ? strdup(cmd->data.str) : NULL);
1782    return NULL;
1783}
1784
1785
1786DOTCONF_CB(get_event_logging_list)
1787{
1788    struct server_configuration_s *config_s =
1789        (struct server_configuration_s *)cmd->context;
1790    int i = 0, len = 0;
1791    char buf[512] = {0};
1792    char *ptr = buf;
1793
1794    if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
1795       config_s->my_server_options == 0)
1796    {
1797        return NULL;
1798    }
1799    if (config_s->event_logging != NULL)
1800    {
1801        free(config_s->event_logging);
1802        config_s->event_logging = NULL;
1803    }
1804    for(i = 0; i < cmd->arg_count; i++)
1805    {
1806        strncat(ptr, cmd->data.list[i], 512 - len);
1807        len += strlen(cmd->data.list[i]);
1808    }
1809    config_s->event_logging = strdup(buf);
1810    return NULL;
1811}
1812
1813DOTCONF_CB(get_event_tracing)
1814{
1815    struct server_configuration_s *config_s =
1816        (struct server_configuration_s *)cmd->context;
1817    if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
1818       config_s->my_server_options == 0)
1819    {
1820        return NULL;
1821    }
1822    if(!strcmp(cmd->data.str, "yes"))
1823    {
1824        config_s->enable_events = 1;
1825    }
1826    else
1827    {
1828        config_s->enable_events = 0;
1829    }
1830    return NULL;
1831}
1832
1833DOTCONF_CB(get_flow_module_list)
1834{
1835    int i = 0, len = 0;
1836    char buf[512] = {0};
1837    char *ptr = buf;
1838
1839    struct server_configuration_s *config_s =
1840        (struct server_configuration_s *)cmd->context;
1841
1842    if (config_s->flow_modules != NULL)
1843    {
1844        free(config_s->flow_modules);
1845        config_s->flow_modules = NULL;
1846    }
1847    for(i = 0; i < cmd->arg_count; i++)
1848    {
1849        strncat(ptr, cmd->data.list[i], 512 - len);
1850        len += strlen(cmd->data.list[i]);
1851    }
1852    config_s->flow_modules = strdup(buf);
1853    return NULL;
1854}
1855
1856static void free_list_of_strings(int list_count, char ***new_list)
1857{
1858    int i;
1859
1860    if (new_list && *new_list != NULL)
1861    {
1862        for (i = 0; i < list_count; i++)
1863        {
1864            free((*new_list)[i]);
1865            (*new_list)[i] = NULL;
1866        }
1867        free(*new_list);
1868        *new_list = NULL;
1869    }
1870    return;
1871}
1872
1873/*
1874 * Given a parsed_list containing list_count number of strings,
1875 * create a new array of pointers which holds a duplicate list
1876 * of all the strings present in the original parsed list.
1877 * Used as a helper function by all the routines/keywords that require a list
1878 * of strings as their options/arguments.
1879 */
1880static int get_list_of_strings(int list_count, char **parsed_list,
1881        char ***new_list)
1882{
1883    int i;
1884
1885    *new_list = (char **) calloc(list_count, sizeof(char *));
1886    if (*new_list == NULL)
1887    {
1888        errno = ENOMEM;
1889        return -1;
1890    }
1891    for (i = 0; i < list_count; i++)
1892    {
1893        (*new_list)[i] = strdup(parsed_list[i]);
1894        if ((*new_list)[i] == NULL)
1895        {
1896            break;
1897        }
1898    }
1899    if (i != list_count)
1900    {
1901        int j;
1902        for (j = 0; j < i; j++)
1903        {
1904            free((*new_list)[j]);
1905            (*new_list)[j] = NULL;
1906        }
1907        free(*new_list);
1908        *new_list = NULL;
1909        errno = ENOMEM;
1910        return -1;
1911    }
1912    return 0;
1913}
1914
1915/*
1916 * Given a set/list of BMI addresses suffixed with @ and a netmask,
1917 * this function will populate a netmasks array that contains
1918 * the integer subsqeuent to the @ symbol.
1919 * i.e given tcp://192.168.2.0@24 we will have tcp://192.168.2.0, 24 as the netmask
1920 */
1921static int setup_netmasks(int count, char **bmi_address, int *netmasks)
1922{
1923    int i;
1924    for (i = 0; i < count; i++)
1925    {
1926        /*
1927         * if we find a @ then we parse the
1928         * chars at the end of it and make sure
1929         * that it is less than equal to 32,
1930         * else we check if there is a wildcard (*)
1931         * present in which case we set it to -1
1932         * else we assume that it is equal to 32.
1933         */
1934        char *special_char = strchr(bmi_address[i], '@'), *ptr = NULL;
1935        if (special_char == NULL)
1936        {
1937            special_char = strchr(bmi_address[i], '*');
1938            if (special_char == NULL)
1939                netmasks[i] = 32;
1940            else
1941                netmasks[i] = -1;
1942        }
1943        else
1944        {
1945            *special_char = '\0';
1946            netmasks[i] = strtol(special_char + 1, &ptr, 10);
1947            if (*ptr != '\0' || netmasks[i] < 0
1948                    || netmasks[i] > 32)
1949                return -1;
1950        }
1951        gossip_debug(GOSSIP_SERVER_DEBUG, "Parsed %s:%d\n", bmi_address[i], netmasks[i]);
1952    }
1953    return 0;
1954}
1955
1956DOTCONF_CB(get_root_squash)
1957{
1958    struct filesystem_configuration_s *fs_conf = NULL;
1959    struct server_configuration_s *config_s =
1960        (struct server_configuration_s *)cmd->context;
1961
1962    fs_conf = (struct filesystem_configuration_s *)
1963        PINT_llist_head(config_s->file_systems);
1964    assert(fs_conf);
1965
1966    if (cmd->arg_count == 0)
1967    {
1968        fs_conf->exp_flags &= ~TROVE_EXP_ROOT_SQUASH;
1969    }
1970    else
1971    {
1972        fs_conf->exp_flags |= TROVE_EXP_ROOT_SQUASH;
1973        fs_conf->root_squash_netmasks = (int *) calloc(cmd->arg_count, sizeof(int));
1974        if (fs_conf->root_squash_netmasks == NULL)
1975        {
1976            fs_conf->root_squash_count = 0;
1977            return("Could not allocate memory for root_squash_netmasks\n");
1978        }
1979        if (get_list_of_strings(cmd->arg_count, cmd->data.list,
1980                    &fs_conf->root_squash_hosts) < 0)
1981        {
1982            free(fs_conf->root_squash_netmasks);
1983            fs_conf->root_squash_netmasks = NULL;
1984            fs_conf->root_squash_count = 0;
1985            return("Could not allocate memory for root_squash_hosts\n");
1986        }
1987        fs_conf->root_squash_count = cmd->arg_count;
1988        /* Setup the netmasks */
1989        if (setup_netmasks(fs_conf->root_squash_count, fs_conf->root_squash_hosts,
1990                    fs_conf->root_squash_netmasks) < 0)
1991        {
1992            free(fs_conf->root_squash_netmasks);
1993            fs_conf->root_squash_netmasks = NULL;
1994            free_list_of_strings(fs_conf->root_squash_count, &fs_conf->root_squash_hosts);
1995            fs_conf->root_squash_count = 0;
1996            return("Could not setup netmasks for root_squash_hosts\n");
1997        }
1998        gossip_debug(GOSSIP_SERVER_DEBUG, "Parsed %d RootSquash wildcard entries\n",
1999                cmd->arg_count);
2000    }
2001    return NULL;
2002}
2003
2004DOTCONF_CB(get_root_squash_exceptions)
2005{
2006    struct filesystem_configuration_s *fs_conf = NULL;
2007    struct server_configuration_s *config_s =
2008        (struct server_configuration_s *)cmd->context;
2009
2010    fs_conf = (struct filesystem_configuration_s *)
2011        PINT_llist_head(config_s->file_systems);
2012    assert(fs_conf);
2013
2014    if (cmd->arg_count != 0)
2015    {
2016        fs_conf->root_squash_exceptions_netmasks = (int *) calloc(cmd->arg_count, sizeof(int));
2017        if (fs_conf->root_squash_exceptions_netmasks == NULL)
2018        {
2019            fs_conf->root_squash_exceptions_count = 0;
2020            return("Could not allocate memory for root_squash_exceptions_netmasks\n");
2021        }
2022        if (get_list_of_strings(cmd->arg_count, cmd->data.list,
2023                    &fs_conf->root_squash_exceptions_hosts) < 0)
2024        {
2025            free(fs_conf->root_squash_exceptions_netmasks);
2026            fs_conf->root_squash_exceptions_netmasks = NULL;
2027            fs_conf->root_squash_exceptions_count = 0;
2028            return("Could not allocate memory for root_squash_exceptions_hosts\n");
2029        }
2030        fs_conf->root_squash_exceptions_count = cmd->arg_count;
2031        /* Setup the netmasks */
2032        if (setup_netmasks(fs_conf->root_squash_exceptions_count, fs_conf->root_squash_exceptions_hosts,
2033                    fs_conf->root_squash_exceptions_netmasks) < 0)
2034        {
2035            free(fs_conf->root_squash_exceptions_netmasks);
2036            fs_conf->root_squash_exceptions_netmasks = NULL;
2037            free_list_of_strings(fs_conf->root_squash_exceptions_count, &fs_conf->root_squash_exceptions_hosts);
2038            fs_conf->root_squash_exceptions_count = 0;
2039            return("Could not setup netmasks for root_squash_exceptions_hosts\n");
2040        }
2041        gossip_debug(GOSSIP_SERVER_DEBUG, "Parsed %d RootSquashExceptions wildcard entries\n",
2042                cmd->arg_count);
2043    }
2044    return NULL;
2045}
2046
2047
2048DOTCONF_CB(get_read_only)
2049{
2050    struct filesystem_configuration_s *fs_conf = NULL;
2051    struct server_configuration_s *config_s =
2052        (struct server_configuration_s *)cmd->context;
2053
2054    fs_conf = (struct filesystem_configuration_s *)
2055        PINT_llist_head(config_s->file_systems);
2056    assert(fs_conf);
2057   
2058    if (cmd->arg_count == 0)
2059    {
2060        fs_conf->exp_flags &= ~TROVE_EXP_READ_ONLY;
2061    }
2062    else
2063    {
2064        fs_conf->exp_flags |= TROVE_EXP_READ_ONLY;
2065        fs_conf->ro_netmasks = (int *) calloc(cmd->arg_count, sizeof(int));
2066        if (fs_conf->ro_netmasks == NULL)
2067        {
2068            fs_conf->ro_count = 0;
2069            return("Could not allocate memory for ro_netmasks\n");
2070        }
2071        if (get_list_of_strings(cmd->arg_count, cmd->data.list,
2072                    &fs_conf->ro_hosts) < 0)
2073        {
2074            free(fs_conf->ro_netmasks);
2075            fs_conf->ro_netmasks = NULL;
2076            fs_conf->ro_count = 0;
2077            return("Could not allocate memory for ro_hosts\n");
2078        }
2079        fs_conf->ro_count  = cmd->arg_count;
2080        if (setup_netmasks(fs_conf->ro_count, fs_conf->ro_hosts, fs_conf->ro_netmasks) < 0)
2081        {
2082            free(fs_conf->ro_netmasks);
2083            fs_conf->ro_netmasks = NULL;
2084            free_list_of_strings(fs_conf->ro_count, &fs_conf->ro_hosts);
2085            fs_conf->ro_count = 0;
2086            return("Could not setup netmasks for ro_netmasks\n");
2087        }
2088        gossip_debug(GOSSIP_SERVER_DEBUG, "Parsed %d ro wildcard entries\n",
2089                cmd->arg_count);
2090    }
2091    return NULL;
2092}
2093
2094DOTCONF_CB(get_all_squash)
2095{
2096    struct filesystem_configuration_s *fs_conf = NULL;
2097    struct server_configuration_s *config_s =
2098        (struct server_configuration_s *)cmd->context;
2099
2100    fs_conf = (struct filesystem_configuration_s *)
2101        PINT_llist_head(config_s->file_systems);
2102    assert(fs_conf);
2103
2104    if (cmd->arg_count == 0)
2105    {
2106        fs_conf->exp_flags &= ~TROVE_EXP_ALL_SQUASH;
2107    }
2108    else
2109    {
2110        fs_conf->exp_flags |= TROVE_EXP_ALL_SQUASH;
2111        fs_conf->all_squash_netmasks = (int *) calloc(cmd->arg_count, sizeof(int));
2112        if (fs_conf->all_squash_netmasks == NULL)
2113        {
2114            fs_conf->all_squash_count = 0;
2115            return("Could not allocate memory for all_squash_netmasks\n");
2116        }
2117        if (get_list_of_strings(cmd->arg_count, cmd->data.list,
2118                    &fs_conf->all_squash_hosts) < 0)
2119        {
2120            free(fs_conf->all_squash_netmasks);
2121            fs_conf->all_squash_netmasks = NULL;
2122            fs_conf->all_squash_count = 0;
2123            return("Could not allocate memory for all_squash_hosts\n");
2124        }
2125        fs_conf->all_squash_count = cmd->arg_count;
2126        if (setup_netmasks(fs_conf->all_squash_count, fs_conf->all_squash_hosts,
2127                    fs_conf->all_squash_netmasks) < 0)
2128        {
2129            free(fs_conf->all_squash_netmasks);
2130            fs_conf->all_squash_netmasks = NULL;
2131            free_list_of_strings(fs_conf->all_squash_count, &fs_conf->all_squash_hosts);
2132            fs_conf->all_squash_count = 0;
2133            return("Could not setup netmasks for all_squash_hosts\n");
2134        }
2135        gossip_debug(GOSSIP_SERVER_DEBUG, "Parsed %d AllSquash wildcard entries\n",
2136                cmd->arg_count);
2137    }
2138    return NULL;
2139}
2140
2141DOTCONF_CB(get_anon_uid)
2142{
2143    struct filesystem_configuration_s *fs_conf = NULL;
2144    unsigned int tmp_var;
2145    int ret = -1;
2146    struct server_configuration_s *config_s =
2147        (struct server_configuration_s *)cmd->context;
2148
2149    fs_conf = (struct filesystem_configuration_s *)
2150        PINT_llist_head(config_s->file_systems);
2151    assert(fs_conf);
2152    ret = sscanf(cmd->data.str, "%u", &tmp_var);
2153    if(ret != 1)
2154    {
2155        return("AnonUID does not have a long long unsigned value.\n");
2156    }
2157    fs_conf->exp_anon_uid = tmp_var;
2158    return NULL;
2159}
2160
2161DOTCONF_CB(get_anon_gid)
2162{
2163    struct filesystem_configuration_s *fs_conf = NULL;
2164    unsigned int tmp_var;
2165    int ret = -1;
2166    struct server_configuration_s *config_s =
2167        (struct server_configuration_s *)cmd->context;
2168
2169    fs_conf = (struct filesystem_configuration_s *)
2170        PINT_llist_head(config_s->file_systems);
2171    assert(fs_conf);
2172    ret = sscanf(cmd->data.str, "%u", &tmp_var);
2173    if(ret != 1)
2174    {
2175        return("AnonGID does not have a unsigned value.\n");
2176    }
2177    fs_conf->exp_anon_gid = tmp_var;
2178    return NULL;
2179}
2180
2181DOTCONF_CB(get_bmi_module_list)
2182{
2183    int i = 0, len = 0;
2184    char buf[512] = {0};
2185    char *ptr = buf;
2186
2187    struct server_configuration_s *config_s =
2188        (struct server_configuration_s *)cmd->context;
2189
2190    if (config_s->bmi_modules != NULL)
2191    {
2192        free(config_s->bmi_modules);
2193        config_s->bmi_modules = NULL;
2194    }
2195    for(i = 0; i < cmd->arg_count; i++)
2196    {
2197        strncat(ptr, cmd->data.list[i], 512 - len);
2198        len += strlen(cmd->data.list[i]);
2199    }
2200    config_s->bmi_modules = strdup(buf);
2201    return NULL;
2202}
2203
2204#ifdef USE_TRUSTED
2205
2206DOTCONF_CB(get_trusted_portlist)
2207{
2208    long port1, port2;
2209    char *separator = NULL, *option = NULL, *endptr = NULL;
2210    struct server_configuration_s *config_s =
2211        (struct server_configuration_s *)cmd->context;
2212
2213    option = strdup(cmd->data.str);
2214    if (option == NULL)
2215    {
2216        return("Could not allocate memory\n");
2217    }
2218    separator = strchr(option, '-');
2219    if (separator == NULL)
2220    {
2221        free(option);
2222        return("Portlist should be of the form <Port1-Port2>\n");
2223    }
2224    *separator = '\0';
2225    port1 = strtol(option, &endptr, 10);
2226    if (port1 < 0 || *endptr != '\0')
2227    {
2228        free(option);
2229        return("Portlist should be of the form <Port1-Port2>\n");
2230    }
2231    endptr = NULL;
2232    port2 = strtol(separator + 1, &endptr, 10);
2233    if (port2 < 0 || *endptr != '\0')
2234    {
2235        free(option);
2236        return("Portlist should be of the form <Port1-Port2>\n");
2237    }
2238    free(option);
2239    if (port2 < port1)
2240    {
2241        return("Portlist should be of the form <Port1-Port2> (Port1 <= Port2)\n");
2242    }
2243    config_s->allowed_ports[0] = port1;
2244    config_s->allowed_ports[1] = port2;
2245    /* okay, we enable trusted ports */
2246    config_s->ports_enabled = 1;
2247    return NULL;
2248}
2249
2250DOTCONF_CB(get_trusted_network)
2251{
2252    struct server_configuration_s *config_s =
2253        (struct server_configuration_s *)cmd->context;
2254
2255    if (cmd->arg_count == 0)
2256    {
2257      return NULL;
2258    }
2259
2260    config_s->allowed_masks = (int *) calloc(cmd->arg_count, sizeof(int));
2261    if (config_s->allowed_masks == NULL)
2262    {
2263        config_s->allowed_networks_count = 0;
2264        return("Could not allocate memory for allowed netmasks\n");
2265    }
2266    if (get_list_of_strings(cmd->arg_count, cmd->data.list,
2267                &config_s->allowed_networks) < 0)
2268    {
2269        free(config_s->allowed_masks);
2270        config_s->allowed_masks = NULL;
2271        config_s->allowed_networks_count = 0;
2272        return("Could not allocate memory for trusted networks\n");
2273    }
2274    config_s->allowed_networks_count = cmd->arg_count;
2275    /* Setup netmasks */
2276    if (setup_netmasks(config_s->allowed_networks_count, config_s->allowed_networks,
2277                config_s->allowed_masks) < 0)
2278    {
2279        free(config_s->allowed_masks);
2280        config_s->allowed_masks = NULL;
2281        free_list_of_strings(config_s->allowed_networks_count, &config_s->allowed_networks);
2282        config_s->allowed_networks_count = 0;
2283        return("Parse error in netmask specification\n");
2284    }
2285
2286    /* okay, we enable trusted network as well */
2287    config_s->network_enabled = 1;
2288    return NULL;
2289}
2290
2291#endif
2292
2293DOTCONF_CB(get_handle_recycle_timeout_seconds)
2294{
2295    struct filesystem_configuration_s *fs_conf = NULL;
2296    struct server_configuration_s *config_s =
2297        (struct server_configuration_s *)cmd->context;
2298
2299    fs_conf = (struct filesystem_configuration_s *)
2300        PINT_llist_head(config_s->file_systems);
2301    assert(fs_conf);
2302
2303    fs_conf->handle_recycle_timeout_sec.tv_sec = (int)cmd->data.value;
2304    fs_conf->handle_recycle_timeout_sec.tv_usec = 0;
2305
2306    return NULL;
2307}
2308
2309static const char * replace_old_keystring(const char * oldkey)
2310{
2311    /* check for old keyval strings */
2312    if(!strcmp(oldkey, "dir_ent"))
2313    {
2314        return "de";
2315    }
2316    else if(!strcmp(oldkey, "datafile_handles"))
2317    {
2318        return "dh";
2319    }
2320    else if(!strcmp(oldkey, "metafile_dist"))
2321    {
2322        return "md";
2323    }
2324    else if(!strcmp(oldkey, "symlink_target"))
2325    {
2326        return "st";
2327    }
2328
2329    return oldkey;
2330}
2331
2332
2333DOTCONF_CB(get_flow_buffer_size_bytes)
2334{
2335    struct filesystem_configuration_s *fs_conf = NULL;
2336    struct server_configuration_s *config_s =
2337        (struct server_configuration_s *)cmd->context;
2338
2339    fs_conf = (struct filesystem_configuration_s *)
2340        PINT_llist_head(config_s->file_systems);
2341    fs_conf->fp_buffer_size = cmd->data.value;
2342    return NULL;
2343}
2344
2345DOTCONF_CB(get_flow_buffers_per_flow)
2346{
2347    struct filesystem_configuration_s *fs_conf = NULL;
2348    struct server_configuration_s *config_s =
2349        (struct server_configuration_s *)cmd->context;
2350
2351    fs_conf = (struct filesystem_configuration_s *)
2352        PINT_llist_head(config_s->file_systems);
2353    fs_conf->fp_buffers_per_flow = cmd->data.value;
2354    if(fs_conf->fp_buffers_per_flow < 2)
2355    {
2356        return("Error: FlowBuffersPerFlow must be at least 2.\n");
2357    }
2358
2359    return NULL;
2360}
2361
2362DOTCONF_CB(get_attr_cache_keywords_list)
2363{
2364    int i = 0, len = 0;
2365    char buf[512] = {0};
2366    char *ptr = buf;
2367    const char * rtok;
2368    struct filesystem_configuration_s *fs_conf = NULL;
2369
2370    struct server_configuration_s *config_s =
2371        (struct server_configuration_s *)cmd->context;
2372
2373    fs_conf = (struct filesystem_configuration_s *)
2374        PINT_llist_head(config_s->file_systems);
2375    assert(fs_conf);
2376
2377    if (fs_conf->attr_cache_keywords != NULL)
2378    {
2379        char ** tokens;
2380        int token_count, j;
2381       
2382        token_count = PINT_split_string_list(
2383            &tokens, fs_conf->attr_cache_keywords);
2384
2385        for(j = 0; j < token_count; ++j)
2386        {
2387            rtok = replace_old_keystring(tokens[j]);
2388            if(!strstr(buf, rtok))
2389            {
2390                len = strlen(rtok);
2391                strncat(ptr, rtok, len);
2392                strncat(ptr, ",", 1);
2393                ptr += len + 1;
2394            }
2395        }
2396                       
2397        PINT_free_string_list(tokens, token_count);
2398        free(fs_conf->attr_cache_keywords);
2399    }
2400
2401    for(i = 0; i < cmd->arg_count; i++)
2402    {
2403        char ** tokens;
2404        int token_count, j;
2405       
2406        token_count = PINT_split_string_list(
2407            &tokens, cmd->data.list[i]);
2408
2409        for(j = 0; j < token_count; ++j)
2410        {
2411            rtok = replace_old_keystring(tokens[j]);
2412            if(!strstr(buf, rtok))
2413            {
2414                len = strlen(rtok);
2415                strncat(ptr, rtok, len);
2416                strncat(ptr, ",", 1);
2417                ptr += len + 1;
2418            }
2419        }
2420
2421        PINT_free_string_list(tokens, token_count);
2422    }
2423
2424    *ptr = '\0';
2425    fs_conf->attr_cache_keywords = strdup(buf);
2426    return NULL;
2427}
2428
2429DOTCONF_CB(get_attr_cache_size)
2430{
2431    struct filesystem_configuration_s *fs_conf = NULL;
2432
2433    struct server_configuration_s *config_s =
2434        (struct server_configuration_s *)cmd->context;
2435
2436    fs_conf = (struct filesystem_configuration_s *)
2437        PINT_llist_head(config_s->file_systems);
2438    assert(fs_conf);
2439
2440    fs_conf->attr_cache_size = (int)cmd->data.value;
2441    return NULL;
2442}
2443
2444DOTCONF_CB(get_attr_cache_max_num_elems)
2445{
2446    struct filesystem_configuration_s *fs_conf = NULL;
2447    struct server_configuration_s *config_s =
2448        (struct server_configuration_s *)cmd->context;
2449
2450    fs_conf = (struct filesystem_configuration_s *)
2451        PINT_llist_head(config_s->file_systems);
2452    assert(fs_conf);
2453
2454    fs_conf->attr_cache_max_num_elems = (int)cmd->data.value;
2455    return NULL;
2456}
2457
2458DOTCONF_CB(get_file_stuffing)
2459{
2460    struct filesystem_configuration_s *fs_conf = NULL;
2461    struct server_configuration_s *config_s =
2462        (struct server_configuration_s *)cmd->context;
2463
2464    fs_conf = (struct filesystem_configuration_s *)
2465        PINT_llist_head(config_s->file_systems);
2466    assert(fs_conf);
2467
2468    if(strcasecmp(cmd->data.str, "yes") == 0)
2469    {
2470        fs_conf->file_stuffing = 1;
2471    }
2472    else if(strcasecmp(cmd->data.str, "no") == 0)
2473    {
2474        fs_conf->file_stuffing = 0;
2475    }
2476    else
2477    {
2478        return("FileStuffing value must be 'yes' or 'no'.\n");
2479    }
2480
2481    return NULL;
2482}
2483
2484
2485DOTCONF_CB(get_trove_sync_meta)
2486{
2487    struct filesystem_configuration_s *fs_conf = NULL;
2488    struct server_configuration_s *config_s =
2489        (struct server_configuration_s *)cmd->context;
2490
2491    fs_conf = (struct filesystem_configuration_s *)
2492        PINT_llist_head(config_s->file_systems);
2493    assert(fs_conf);
2494
2495    if(strcasecmp(cmd->data.str, "yes") == 0)
2496    {
2497        fs_conf->trove_sync_meta = TROVE_SYNC;
2498    }
2499    else if(strcasecmp(cmd->data.str, "no") == 0)
2500    {
2501        fs_conf->trove_sync_meta = 0;
2502    }
2503    else
2504    {
2505        return("TroveSyncMeta value must be 'yes' or 'no'.\n");
2506    }
2507#ifndef HAVE_DB_DIRTY_READ
2508    if (fs_conf->trove_sync_meta != TROVE_SYNC)
2509    {
2510        gossip_err("WARNING: Forcing TroveSyncMeta to be yes instead of %s\n",
2511                   cmd->data.str);
2512        gossip_err("WARNING: Non-sync mode is NOT supported without "
2513                   "DB_DIRTY_READ support.\n");
2514        fs_conf->trove_sync_meta = TROVE_SYNC;
2515    }
2516#endif
2517
2518    return NULL;
2519}
2520
2521DOTCONF_CB(get_trove_sync_data)
2522{
2523    struct filesystem_configuration_s *fs_conf = NULL;
2524    struct server_configuration_s *config_s =
2525        (struct server_configuration_s *)cmd->context;
2526
2527    fs_conf = (struct filesystem_configuration_s *)
2528        PINT_llist_head(config_s->file_systems);
2529    assert(fs_conf);
2530
2531    if(strcasecmp(cmd->data.str, "yes") == 0)
2532    {
2533        fs_conf->trove_sync_data = TROVE_SYNC;
2534    }
2535    else if(strcasecmp(cmd->data.str, "no") == 0)
2536    {
2537        fs_conf->trove_sync_data = 0;
2538    }
2539    else
2540    {
2541        return("TroveSyncData value must be 'yes' or 'no'.\n");
2542    }
2543
2544    return NULL;
2545}
2546
2547DOTCONF_CB(get_db_cache_size_bytes)
2548{
2549    struct server_configuration_s *config_s =
2550        (struct server_configuration_s *)cmd->context;
2551    config_s->db_cache_size_bytes = cmd->data.value;
2552    return NULL;
2553}
2554
2555DOTCONF_CB(get_trove_max_concurrent_io)
2556{
2557    struct server_configuration_s *config_s =
2558        (struct server_configuration_s *)cmd->context;
2559
2560    if(config_s->configuration_context == CTX_SERVER_OPTIONS &&
2561       config_s->my_server_options == 0)
2562    {
2563        return NULL;
2564    }
2565    config_s->trove_max_concurrent_io = cmd->data.value;
2566    return NULL;
2567}
2568
2569DOTCONF_CB(get_db_cache_type)
2570{
2571    struct server_configuration_s *config_s =
2572        (struct server_configuration_s *)cmd->context;
2573   
2574    if(strcmp(cmd->data.str, "sys") && strcmp(cmd->data.str, "mmap"))
2575    {
2576        return "Unsupported parameter supplied to DBCacheType option, must "
2577               "be either \"sys\" or \"mmap\"\n";
2578    }
2579
2580    if (config_s->db_cache_type)
2581        free(config_s->db_cache_type);
2582    config_s->db_cache_type = strdup(cmd->data.str);
2583    if(!config_s->db_cache_type)
2584    {
2585        return "strdup() failure";
2586    }
2587
2588    return NULL;
2589}
2590
2591DOTCONF_CB(get_root_handle)
2592{
2593    struct filesystem_configuration_s *fs_conf = NULL;
2594    unsigned long long int tmp_var;
2595    int ret = -1;
2596    struct server_configuration_s *config_s =
2597        (struct server_configuration_s *)cmd->context;
2598
2599    fs_conf = (struct filesystem_configuration_s *)
2600        PINT_llist_head(config_s->file_systems);
2601    assert(fs_conf);
2602    ret = sscanf(cmd->data.str, "%llu", &tmp_var);
2603    if(ret != 1)
2604    {
2605        return("RootHandle does not have a long long unsigned value.\n");
2606    }
2607    fs_conf->root_handle = (PVFS_handle)tmp_var;
2608    return NULL;
2609}
2610
2611DOTCONF_CB(get_name)
2612{
2613    struct server_configuration_s *config_s =
2614        (struct server_configuration_s *)cmd->context;
2615    if (config_s->configuration_context == CTX_FILESYSTEM)
2616    {
2617        struct filesystem_configuration_s *fs_conf = NULL;
2618
2619        fs_conf = (struct filesystem_configuration_s *)
2620            PINT_llist_head(config_s->file_systems);
2621        if (fs_conf->file_system_name)
2622        {
2623            gossip_err("WARNING: Overwriting %s with %s\n",
2624                       fs_conf->file_system_name,cmd->data.str);
2625        }
2626        fs_conf->file_system_name =
2627            (cmd->data.str ? strdup(cmd->data.str) : NULL);
2628    }
2629    else if (config_s->configuration_context == CTX_DISTRIBUTION)
2630    {
2631        if (0 == config_s->default_dist_config.name)
2632        {
2633            config_s->default_dist_config.name =
2634                (cmd->data.str ? strdup(cmd->data.str) : NULL);
2635            config_s->default_dist_config.param_list = PINT_llist_new();
2636        }
2637        else
2638        {
2639            return "Only one distribution configuration is allowed.\n";
2640        }
2641    }
2642    return NULL;
2643}
2644
2645DOTCONF_CB(get_filesystem_collid)
2646{
2647    struct filesystem_configuration_s *fs_conf = NULL;
2648    struct server_configuration_s *config_s =
2649        (struct server_configuration_s *)cmd->context;
2650
2651    fs_conf = (struct filesystem_configuration_s *)
2652        PINT_llist_head(config_s->file_systems);
2653    if (fs_conf->coll_id)
2654    {
2655        gossip_err("WARNING: Overwriting %d with %d\n",
2656                   (int)fs_conf->coll_id,(int)cmd->data.value);
2657    }
2658    fs_conf->coll_id = (PVFS_fs_id)cmd->data.value;
2659    return NULL;
2660}
2661
2662static int compare_aliases(void * vkey,
2663                           void * valias2)
2664{
2665    char * hostaliaskey1 = (char *)vkey;
2666    host_alias_s * alias2 = (host_alias_s *)valias2;
2667   
2668    return strcmp(hostaliaskey1, alias2->host_alias);
2669}
2670
2671DOTCONF_CB(get_alias_list)
2672{
2673    struct server_configuration_s *config_s =
2674        (struct server_configuration_s *)cmd->context;
2675    struct host_alias_s *cur_alias = NULL;
2676
2677    assert(cmd->arg_count == 2);
2678
2679    /* prevent users from adding the same alias twice */
2680    if(config_s->host_aliases &&
2681       PINT_llist_search(config_s->host_aliases,
2682                      (void *)cmd->data.list[0],
2683                      compare_aliases))
2684    {
2685        return "Error: alias already defined";
2686    }
2687
2688    cur_alias = (host_alias_s *)
2689        malloc(sizeof(host_alias_s));
2690    cur_alias->host_alias = strdup(cmd->data.list[0]);
2691    cur_alias->bmi_address = strdup(cmd->data.list[1]);
2692
2693    if (!config_s->host_aliases)
2694    {
2695        config_s->host_aliases = PINT_llist_new();
2696    }
2697   
2698    PINT_llist_add_to_tail(config_s->host_aliases,(void *)cur_alias);
2699    return NULL;
2700}
2701
2702DOTCONF_CB(get_range_list)
2703{
2704    int i = 0, is_new_handle_mapping = 0;
2705    struct filesystem_configuration_s *fs_conf = NULL;
2706    struct host_handle_mapping_s *handle_mapping = NULL;
2707    PINT_llist **handle_range_list = NULL;
2708    struct server_configuration_s *config_s =
2709        (struct server_configuration_s *)cmd->context;
2710
2711    fs_conf = (struct filesystem_configuration_s *)
2712        PINT_llist_head(config_s->file_systems);
2713    assert(fs_conf);
2714
2715    handle_range_list = ((config_s->configuration_context ==
2716                          CTX_METAHANDLERANGES) ?
2717                         &fs_conf->meta_handle_ranges :
2718                         &fs_conf->data_handle_ranges);
2719
2720    if (*handle_range_list == NULL)
2721    {
2722        *handle_range_list = PINT_llist_new();
2723    }
2724
2725    for(i = 0; i < cmd->arg_count; i += 2)
2726    {
2727        if (is_valid_alias(config_s->host_aliases, cmd->data.list[i]))
2728        {
2729            i++;
2730            assert(cmd->data.list[i]);
2731
2732            if (is_valid_handle_range_description(cmd->data.list[i]))
2733            {
2734                handle_mapping = get_or_add_handle_mapping(
2735                    *handle_range_list, cmd->data.list[i-1]);
2736                if (!handle_mapping)
2737                {
2738                    return("Error: Alias allocation failed; "
2739                               "aborting alias handle range addition!\n");
2740                }
2741
2742                if (!handle_mapping->alias_mapping)
2743                {
2744                    is_new_handle_mapping = 1;
2745                    handle_mapping->alias_mapping =
2746                        find_host_alias_ptr_by_alias(
2747                            config_s, cmd->data.list[i-1], NULL);
2748                }
2749
2750                assert(handle_mapping->alias_mapping ==
2751                       find_host_alias_ptr_by_alias(
2752                           config_s, cmd->data.list[i-1], NULL));
2753
2754                if (!handle_mapping->handle_range &&
2755                    !handle_mapping->handle_extent_array.extent_array)
2756                {
2757                    handle_mapping->handle_range =
2758                        strdup(cmd->data.list[i]);
2759
2760                    /* build the extent array, based on range */
2761                    build_extent_array(
2762                        handle_mapping->handle_range,
2763                        &handle_mapping->handle_extent_array);
2764                }
2765                else
2766                {
2767                    char *new_handle_range = PINT_merge_handle_range_strs(
2768                        handle_mapping->handle_range, cmd->data.list[i]);
2769                    free(handle_mapping->handle_range);
2770                    handle_mapping->handle_range = new_handle_range;
2771
2772                    /* re-build the extent array, based on range */
2773                    free(handle_mapping->handle_extent_array.extent_array);
2774                    build_extent_array(handle_mapping->handle_range,
2775                                       &handle_mapping->handle_extent_array);
2776                }
2777
2778                if (is_new_handle_mapping)
2779                {
2780                    PINT_llist_add_to_tail(*handle_range_list,
2781                                      (void *)handle_mapping);
2782                }
2783            }
2784            else
2785            {
2786                return("Error in handle range description.\n");
2787            }
2788        }
2789        else
2790        {
2791            return("Unrecognized alias.\n");
2792        }
2793    }
2794    return NULL;
2795}
2796
2797DOTCONF_CB(get_param)
2798{
2799    struct server_configuration_s *config_s =
2800        (struct server_configuration_s *)cmd->context;
2801    distribution_param_configuration* param =
2802        malloc(sizeof(distribution_param_configuration));
2803
2804    if (NULL != param)
2805    {
2806        memset(param, 0, sizeof(param));
2807        param->name = (cmd->data.str ? strdup(cmd->data.str) : NULL);
2808        PINT_llist_add_to_tail(config_s->default_dist_config.param_list,
2809                               param);
2810    }
2811    return NULL;
2812}
2813
2814DOTCONF_CB(get_value)
2815{
2816    struct server_configuration_s *config_s =
2817        (struct server_configuration_s *)cmd->context;
2818    distribution_param_configuration* param;
2819    param = (distribution_param_configuration*)PINT_llist_tail(
2820        config_s->default_dist_config.param_list);
2821    if (NULL != param)
2822    {
2823        param->value = (PVFS_size)cmd->data.value;
2824    }
2825    return NULL;
2826}
2827
2828DOTCONF_CB(get_default_num_dfiles)
2829{
2830    struct server_configuration_s *config_s =
2831        (struct server_configuration_s *)cmd->context;
2832    struct filesystem_configuration_s *fs_conf = NULL;
2833
2834    fs_conf = (struct filesystem_configuration_s *)
2835        PINT_llist_head(config_s->file_systems);
2836
2837    fs_conf->default_num_dfiles = (int)cmd->data.value;
2838    if(fs_conf->default_num_dfiles < 0)
2839    {
2840        return("Error DefaultNumDFiles must be positive.\n");
2841    }
2842    return NULL;
2843}
2844
2845DOTCONF_CB(get_secret_key)
2846{
2847    struct server_configuration_s *config_s =
2848        (struct server_configuration_s *)cmd->context;
2849    struct filesystem_configuration_s *fs_conf = NULL;
2850
2851    fs_conf = (struct filesystem_configuration_s *)
2852        PINT_llist_head(config_s->file_systems);
2853
2854    fs_conf->secret_key = strdup(cmd->data.str);
2855    return NULL;
2856}
2857
2858DOTCONF_CB(get_immediate_completion)
2859{
2860    struct server_configuration_s *config_s =
2861        (struct server_configuration_s *)cmd->context;
2862    struct filesystem_configuration_s *fs_conf = NULL;
2863
2864    fs_conf = (struct filesystem_configuration_s *)
2865        PINT_llist_head(config_s->file_systems);
2866
2867    if(!strcmp((char *)cmd->data.str, "yes"))
2868    {
2869        fs_conf->immediate_completion = 1;
2870    }
2871    else
2872    {
2873        fs_conf->immediate_completion = 0;
2874    }
2875
2876    return NULL;
2877}
2878
2879DOTCONF_CB(get_coalescing_high_watermark)
2880{
2881    struct server_configuration_s *config_s =
2882        (struct server_configuration_s *)cmd->context;
2883    struct filesystem_configuration_s *fs_conf = NULL;
2884
2885    fs_conf = (struct filesystem_configuration_s *)
2886        PINT_llist_head(config_s->file_systems);
2887
2888    if(!strcmp((char *)cmd->data.str, "infinity"))
2889    {
2890        fs_conf->coalescing_high_watermark = -1;
2891    }
2892    else
2893    {
2894        sscanf(cmd->data.str, "%d", &fs_conf->coalescing_high_watermark);
2895    }
2896    return NULL;
2897}
2898
2899DOTCONF_CB(get_coalescing_low_watermark)
2900{
2901    struct server_configuration_s *config_s =
2902        (struct server_configuration_s *)cmd->context;
2903    struct filesystem_configuration_s *fs_conf = NULL;
2904
2905    fs_conf = (struct filesystem_configuration_s *)
2906        PINT_llist_head(config_s->file_systems);
2907
2908    fs_conf->coalescing_low_watermark = cmd->data.value;
2909    return NULL;
2910}
2911
2912DOTCONF_CB(get_trove_method)
2913{
2914    int * method;
2915    struct server_configuration_s *config_s =
2916        (struct server_configuration_s *)cmd->context;
2917
2918    method = &config_s->trove_method;
2919    if(config_s->configuration_context == CTX_STORAGEHINTS)
2920    {
2921        /* we must be in a storagehints inside a filesystem context */
2922        struct filesystem_configuration_s *fs_conf =
2923            (struct filesystem_configuration_s *)
2924            PINT_llist_head(config_s->file_systems);
2925
2926        method = &fs_conf->trove_method;
2927    }
2928
2929    if(!strcmp(cmd->data.str, "dbpf"))
2930    {
2931        *method = TROVE_METHOD_DBPF;
2932    }
2933    else if(!strcmp(cmd->data.str, "alt-aio"))
2934    {
2935        *method = TROVE_METHOD_DBPF_ALTAIO;
2936    }
2937    else if(!strcmp(cmd->data.str, "null-aio"))
2938    {
2939        *method = TROVE_METHOD_DBPF_NULLAIO;
2940    }
2941    else if(!strcmp(cmd->data.str, "directio"))
2942    {
2943        *method = TROVE_METHOD_DBPF_DIRECTIO;
2944    }
2945    else
2946    {
2947        return "Error unknown TroveMethod option\n";
2948    }
2949    return NULL;
2950}
2951
2952DOTCONF_CB(get_small_file_size)
2953{
2954    struct server_configuration_s *config_s =
2955        (struct server_configuration_s *)cmd->context;
2956
2957    /* we must be in a storagehints inside a filesystem context */
2958    struct filesystem_configuration_s *fs_conf =
2959        (struct filesystem_configuration_s *) PINT_llist_head(config_s->file_systems);
2960
2961    fs_conf->small_file_size = cmd->data.value;
2962    return NULL;
2963}
2964
2965DOTCONF_CB(directio_thread_num)
2966{
2967    struct server_configuration_s *config_s =
2968        (struct server_configuration_s *)cmd->context;
2969
2970    struct filesystem_configuration_s *fs_conf =
2971        (struct filesystem_configuration_s *)
2972        PINT_llist_head(config_s->file_systems);
2973
2974    fs_conf->directio_thread_num = cmd->data.value;
2975
2976    return NULL;
2977}
2978
2979DOTCONF_CB(directio_ops_per_queue)
2980{
2981    struct server_configuration_s *config_s =
2982        (struct server_configuration_s *)cmd->context;
2983
2984    struct filesystem_configuration_s *fs_conf =
2985        (struct filesystem_configuration_s *)
2986        PINT_llist_head(config_s->file_systems);
2987
2988    fs_conf->directio_ops_per_queue = cmd->data.value;
2989
2990    return NULL;
2991}
2992
2993DOTCONF_CB(directio_timeout)
2994{
2995    struct server_configuration_s *config_s =
2996        (struct server_configuration_s *)cmd->context;
2997
2998    struct filesystem_configuration_s *fs_conf =
2999        (struct filesystem_configuration_s *)
3000        PINT_llist_head(config_s->file_systems);
3001
3002    fs_conf->directio_timeout = cmd->data.value;
3003
3004    return NULL;
3005}
3006
3007/*
3008 * Function: PINT_config_release
3009 *
3010 * Params:   struct server_configuration_s*
3011 *
3012 * Returns:  void
3013 *
3014 * Synopsis: De-allocates memory consumed internally
3015 *           by the specified server_configuration_s
3016 *           
3017 */
3018void PINT_config_release(struct server_configuration_s *config_s)
3019{
3020    if (config_s)
3021    {
3022        if (config_s->host_id)
3023        {
3024            free(config_s->host_id);
3025            config_s->host_id = NULL;
3026        }
3027
3028        if (config_s->data_path)
3029        {
3030            free(config_s->data_path);
3031            config_s->data_path = NULL;
3032        }
3033
3034        if (config_s->meta_path)
3035        {
3036            free(config_s->meta_path);
3037            config_s->meta_path = NULL;
3038        }
3039
3040        if (config_s->fs_config_filename)
3041        {
3042            free(config_s->fs_config_filename);
3043            config_s->fs_config_filename = NULL;
3044        }
3045
3046        if (config_s->fs_config_buf)
3047        {
3048            free(config_s->fs_config_buf);
3049            config_s->fs_config_buf = NULL;
3050        }
3051
3052        if(config_s->precreate_batch_size)
3053        {
3054            free(config_s->precreate_batch_size);
3055            config_s->precreate_batch_size = NULL;
3056        }
3057
3058        if(config_s->precreate_low_threshold)
3059        {
3060            free(config_s->precreate_low_threshold);
3061            config_s->precreate_low_threshold = NULL;
3062        }
3063
3064        if (config_s->logfile)
3065        {
3066            free(config_s->logfile);
3067            config_s->logfile = NULL;
3068        }
3069
3070        if (config_s->logtype)
3071        {
3072            free(config_s->logtype);
3073            config_s->logtype = NULL;
3074        }
3075
3076        if (config_s->event_logging)
3077        {
3078            free(config_s->event_logging);
3079            config_s->event_logging = NULL;
3080        }
3081
3082        if (config_s->bmi_modules)
3083        {
3084            free(config_s->bmi_modules);
3085            config_s->bmi_modules = NULL;
3086        }
3087
3088        if (config_s->flow_modules)
3089        {
3090            free(config_s->flow_modules);
3091            config_s->flow_modules = NULL;
3092        }
3093#ifdef USE_TRUSTED
3094        if (config_s->allowed_networks)
3095        {
3096            int i;
3097            for (i = 0; i < config_s->allowed_networks_count; i++)
3098            {
3099                free(config_s->allowed_networks[i]);
3100                config_s->allowed_networks[i] = NULL;
3101            }
3102            free(config_s->allowed_networks);
3103            config_s->allowed_networks = NULL;
3104        }
3105        if (config_s->allowed_masks)
3106        {
3107            free(config_s->allowed_masks);
3108            config_s->allowed_masks = NULL;
3109        }
3110        if (config_s->security && config_s->security_dtor)
3111        {
3112            config_s->security_dtor(config_s->security);
3113            config_s->security = NULL;
3114        }
3115#endif
3116        /* free all filesystem objects */
3117        if (config_s->file_systems)
3118        {
3119            PINT_llist_free(config_s->file_systems,free_filesystem);
3120            config_s->file_systems = NULL;
3121        }
3122
3123        /* free all host alias objects */
3124        if (config_s->host_aliases)
3125        {
3126            PINT_llist_free(config_s->host_aliases,free_host_alias);
3127            config_s->host_aliases = NULL;
3128        }
3129
3130        if (config_s->db_cache_type)
3131        {
3132            free(config_s->db_cache_type);
3133            config_s->db_cache_type = NULL;
3134        }
3135    }
3136}
3137
3138static int is_valid_alias(PINT_llist * host_aliases, char *str)
3139{
3140    int ret = 0;
3141    PINT_llist *cur = NULL;
3142    struct host_alias_s *cur_alias;
3143
3144    if (str)
3145    {
3146        cur = host_aliases;
3147        while(cur)
3148        {
3149            cur_alias = PINT_llist_head(cur);
3150            if (!cur_alias)
3151            {
3152                break;
3153            }
3154            assert(cur_alias->host_alias);
3155            assert(cur_alias->bmi_address);
3156
3157            if (strcmp(str,cur_alias->host_alias) == 0)
3158            {
3159                ret = 1;
3160                break;
3161            }
3162            cur = PINT_llist_next(cur);
3163        }
3164    }
3165    return ret;
3166}
3167
3168static int is_valid_handle_range_description(char *h_range)
3169{
3170    int ret = 0;
3171    int len = 0;
3172    char *ptr = (char *)0;
3173    char *end = (char *)0;
3174
3175    if (h_range)
3176    {
3177        len = strlen(h_range);
3178        end = (h_range + len);
3179
3180        for(ptr = h_range; ptr < end; ptr++)
3181        {
3182            if (!isdigit((int)*ptr) && (*ptr != ',') &&
3183                (*ptr != ' ') && (*ptr != '-'))
3184            {
3185                break;
3186            }
3187        }
3188        if (ptr == end)
3189        {
3190            ret = 1;
3191        }
3192    }
3193    return ret;
3194}
3195
3196static int is_populated_filesystem_configuration(
3197    struct filesystem_configuration_s *fs)
3198{
3199    return ((fs && fs->coll_id && fs->file_system_name &&
3200             fs->meta_handle_ranges && fs->data_handle_ranges &&
3201             fs->root_handle) ? 1 : 0);
3202}
3203   
3204static int is_root_handle_in_a_meta_range(
3205    struct server_configuration_s *config,
3206    struct filesystem_configuration_s *fs)
3207{
3208    int ret = 0;
3209    PINT_llist *cur = NULL;
3210    PINT_llist *extent_list = NULL;
3211    char *cur_host_id = (char *)0;
3212    host_handle_mapping_s *cur_h_mapping = NULL;
3213
3214    if (config && is_populated_filesystem_configuration(fs))
3215    {
3216        /*
3217          check if the root handle is within one of the
3218          specified meta host's handle ranges for this fs;
3219          a root handle can't exist in a data handle range!
3220        */
3221        cur = fs->meta_handle_ranges;
3222        while(cur)
3223        {
3224            cur_h_mapping = PINT_llist_head(cur);
3225            if (!cur_h_mapping)
3226            {
3227                break;
3228            }
3229            assert(cur_h_mapping->alias_mapping);
3230            assert(cur_h_mapping->alias_mapping->host_alias);
3231            assert(cur_h_mapping->alias_mapping->bmi_address);
3232            assert(cur_h_mapping->handle_range);
3233
3234            cur_host_id = cur_h_mapping->alias_mapping->bmi_address;
3235            if (!cur_host_id)
3236            {
3237                gossip_err("Invalid host ID for alias %s.\n",
3238                           cur_h_mapping->alias_mapping->host_alias);
3239                break;
3240            }
3241
3242            extent_list = PINT_create_extent_list(
3243                cur_h_mapping->handle_range);
3244            if (!extent_list)
3245            {
3246                gossip_err("Failed to create extent list.\n");
3247                break;
3248            }
3249
3250            ret = PINT_handle_in_extent_list(
3251                extent_list,fs->root_handle);
3252            PINT_release_extent_list(extent_list);
3253            if (ret == 1)
3254            {
3255                break;
3256            }
3257            cur = PINT_llist_next(cur);
3258        }
3259    }
3260    return ret;
3261}
3262
3263static int is_valid_filesystem_configuration(
3264    struct server_configuration_s *config,
3265    struct filesystem_configuration_s *fs)
3266{
3267    int ret = is_root_handle_in_a_meta_range(config,fs);
3268    if (ret == 0)
3269    {
3270        gossip_err("RootHandle (%llu) is NOT within the meta handle "
3271                   "ranges specified for this filesystem (%s).\n",
3272                   llu(fs->root_handle),fs->file_system_name);
3273    }
3274    return ret;
3275}
3276
3277static void free_host_handle_mapping(void *ptr)
3278{
3279    struct host_handle_mapping_s *h_mapping =
3280        (struct host_handle_mapping_s *)ptr;
3281    if (h_mapping)
3282    {
3283        /*
3284          NOTE: h_mapping->alias_mapping is freed by free_host_alias,
3285          as the pointer points into the config_s->host_aliases list;
3286          it's not copied.
3287        */
3288        h_mapping->alias_mapping = NULL;
3289
3290        free(h_mapping->handle_range);
3291        h_mapping->handle_range = NULL;
3292
3293        free(h_mapping->handle_extent_array.extent_array);
3294        h_mapping->handle_extent_array.extent_count = 0;
3295        h_mapping->handle_extent_array.extent_array = NULL;
3296
3297        free(h_mapping);
3298        h_mapping = NULL;
3299    }
3300}
3301
3302static void free_host_alias(void *ptr)
3303{
3304    struct host_alias_s *alias = (struct host_alias_s *)ptr;
3305    if (alias)
3306    {
3307        free(alias->host_alias);
3308        alias->host_alias = NULL;
3309
3310        free(alias->bmi_address);
3311        alias->bmi_address = NULL;
3312
3313        free(alias);
3314        alias = NULL;
3315    }
3316}
3317
3318static void free_filesystem(void *ptr)
3319{
3320    struct filesystem_configuration_s *fs =
3321        (struct filesystem_configuration_s *)ptr;
3322
3323    if (fs)
3324    {
3325        free(fs->file_system_name);
3326        fs->file_system_name = NULL;
3327
3328        /* free all handle ranges */
3329        PINT_llist_free(fs->meta_handle_ranges,free_host_handle_mapping);
3330        PINT_llist_free(fs->data_handle_ranges,free_host_handle_mapping);
3331
3332        /* if the optional hints are used, free them */
3333        if (fs->attr_cache_keywords)
3334        {
3335            free(fs->attr_cache_keywords);
3336            fs->attr_cache_keywords = NULL;
3337        }
3338        if(fs->secret_key)
3339        {
3340            free(fs->secret_key);
3341        }
3342        /* free all ro_hosts specifications */
3343        if (fs->ro_hosts)
3344        {
3345            free_list_of_strings(fs->ro_count, &fs->ro_hosts);
3346            fs->ro_count = 0;
3347        }
3348        if (fs->ro_netmasks)
3349        {
3350            free(fs->ro_netmasks);
3351            fs->ro_netmasks = NULL;
3352        }
3353        /* free all root_squash_exception_hosts specifications */
3354        if (fs->root_squash_exceptions_hosts)
3355        {
3356            free_list_of_strings(fs->root_squash_exceptions_count, &fs->root_squash_exceptions_hosts);
3357            fs->root_squash_exceptions_count = 0;
3358        }
3359        if (fs->root_squash_exceptions_netmasks)
3360        {
3361            free(fs->root_squash_exceptions_netmasks);
3362            fs->root_squash_exceptions_netmasks = NULL;
3363        }
3364        /* free all root_squash_hosts specifications */
3365        if (fs->root_squash_hosts)
3366        {
3367            free_list_of_strings(fs->root_squash_count, &fs->root_squash_hosts);
3368            fs->root_squash_count = 0;
3369        }
3370        if (fs->root_squash_netmasks)
3371        {
3372            free(fs->root_squash_netmasks);
3373            fs->root_squash_netmasks = NULL;
3374        }
3375        /* free all all_squash_hosts specifications */
3376        if (fs->all_squash_hosts)
3377        {
3378            free_list_of_strings(fs->all_squash_count, &fs->all_squash_hosts);
3379            fs->all_squash_count = 0;
3380        }
3381        if (fs->all_squash_netmasks)
3382        {
3383            free(fs->all_squash_netmasks);
3384            fs->all_squash_netmasks = NULL;
3385        }
3386        free(fs);
3387        fs = NULL;
3388    }
3389}
3390
3391static void copy_filesystem(
3392    struct filesystem_configuration_s *dest_fs,
3393    struct filesystem_configuration_s *src_fs)
3394{
3395    PINT_llist *cur = NULL;
3396    struct host_handle_mapping_s *cur_h_mapping = NULL;
3397    struct host_handle_mapping_s *new_h_mapping = NULL;
3398
3399    if (dest_fs && src_fs)
3400    {
3401        dest_fs->file_system_name = strdup(src_fs->file_system_name);
3402        assert(dest_fs->file_system_name);
3403
3404        dest_fs->coll_id = src_fs->coll_id;
3405        dest_fs->root_handle = src_fs->root_handle;
3406        dest_fs->default_num_dfiles = src_fs->default_num_dfiles;
3407
3408        dest_fs->flowproto = src_fs->flowproto;
3409        dest_fs->encoding = src_fs->encoding;
3410
3411        dest_fs->meta_handle_ranges = PINT_llist_new();
3412        dest_fs->data_handle_ranges = PINT_llist_new();
3413
3414        if(src_fs->secret_key)
3415        {
3416            dest_fs->secret_key = strdup(src_fs->secret_key);
3417        }
3418
3419        assert(dest_fs->meta_handle_ranges);
3420        assert(dest_fs->data_handle_ranges);
3421
3422        /* copy all meta handle ranges */
3423        cur = src_fs->meta_handle_ranges;
3424        while(cur)
3425        {
3426            cur_h_mapping = PINT_llist_head(cur);
3427            if (!cur_h_mapping)
3428            {
3429                break;
3430            }
3431
3432            new_h_mapping = (struct host_handle_mapping_s *)
3433                malloc(sizeof(struct host_handle_mapping_s));
3434            assert(new_h_mapping);
3435
3436            /* these are pointers into another struct with a different
3437             * lifetime, do not copy */
3438            new_h_mapping->alias_mapping = cur_h_mapping->alias_mapping;
3439
3440            new_h_mapping->handle_range =
3441                strdup(cur_h_mapping->handle_range);
3442            assert(new_h_mapping->handle_range);
3443
3444            build_extent_array(new_h_mapping->handle_range,
3445                               &new_h_mapping->handle_extent_array);
3446
3447            PINT_llist_add_to_tail(
3448                dest_fs->meta_handle_ranges, new_h_mapping);
3449
3450            cur = PINT_llist_next(cur);
3451        }
3452
3453        /* copy all data handle ranges */
3454        cur = src_fs->data_handle_ranges;
3455        while(cur)
3456        {
3457            cur_h_mapping = PINT_llist_head(cur);
3458            if (!cur_h_mapping)
3459            {
3460                break;
3461            }
3462
3463            new_h_mapping = (struct host_handle_mapping_s *)
3464                malloc(sizeof(struct host_handle_mapping_s));
3465            assert(new_h_mapping);
3466
3467            new_h_mapping->alias_mapping = cur_h_mapping->alias_mapping;
3468
3469            new_h_mapping->handle_range =
3470                strdup(cur_h_mapping->handle_range);
3471            assert(new_h_mapping->handle_range);
3472
3473            build_extent_array(new_h_mapping->handle_range,
3474                               &new_h_mapping->handle_extent_array);
3475
3476            PINT_llist_add_to_tail(
3477                dest_fs->data_handle_ranges, new_h_mapping);
3478
3479            cur = PINT_llist_next(cur);
3480        }
3481
3482        /* if the optional hints are used, copy them too */
3483        if (src_fs->attr_cache_keywords)
3484        {
3485            dest_fs->attr_cache_keywords =
3486                strdup(src_fs->attr_cache_keywords);
3487            assert(dest_fs->attr_cache_keywords);
3488        }
3489
3490        dest_fs->handle_recycle_timeout_sec =
3491            src_fs->handle_recycle_timeout_sec;
3492        dest_fs->attr_cache_size = src_fs->attr_cache_size;
3493        dest_fs->attr_cache_max_num_elems =
3494            src_fs->attr_cache_max_num_elems;
3495        dest_fs->trove_sync_meta = src_fs->trove_sync_meta;
3496        dest_fs->trove_sync_data = src_fs->trove_sync_data;
3497 
3498        /* copy all relevant export options */
3499        dest_fs->exp_flags    = src_fs->exp_flags;
3500        dest_fs->ro_count     = src_fs->ro_count;
3501        dest_fs->root_squash_count = src_fs->root_squash_count;
3502        dest_fs->all_squash_count = src_fs->all_squash_count;
3503        if (src_fs->ro_count > 0 && src_fs->ro_hosts)
3504        {
3505            int i;
3506            dest_fs->ro_hosts = (char **) calloc(src_fs->ro_count, sizeof(char *));
3507            assert(dest_fs->ro_hosts);
3508            for (i = 0; i < src_fs->ro_count; i++)
3509            {
3510                dest_fs->ro_hosts[i] = strdup(src_fs->ro_hosts[i]);
3511                assert(dest_fs->ro_hosts[i]);
3512            }
3513        }
3514        if (src_fs->ro_count > 0 && src_fs->ro_netmasks)
3515        {
3516            dest_fs->ro_netmasks = (int *) calloc(src_fs->ro_count, sizeof(int));
3517            assert(dest_fs->ro_netmasks);
3518            memcpy(dest_fs->ro_netmasks, src_fs->ro_netmasks, src_fs->ro_count * sizeof(int));
3519        }
3520        if (src_fs->root_squash_count > 0 && src_fs->root_squash_hosts)
3521        {
3522            int i;
3523            dest_fs->root_squash_hosts = (char **) calloc(src_fs->root_squash_count, sizeof(char *));
3524            assert(dest_fs->root_squash_hosts);
3525            for (i = 0; i < src_fs->root_squash_count; i++)
3526            {
3527                dest_fs->root_squash_hosts[i] = strdup(src_fs->root_squash_hosts[i]);
3528                assert(dest_fs->root_squash_hosts[i]);
3529            }
3530        }
3531        if (src_fs->root_squash_count > 0 && src_fs->root_squash_netmasks)
3532        {
3533            dest_fs->root_squash_netmasks = (int *) calloc(src_fs->root_squash_count, sizeof(int));
3534            assert(dest_fs->root_squash_netmasks);
3535            memcpy(dest_fs->root_squash_netmasks, src_fs->root_squash_netmasks, src_fs->root_squash_count * sizeof(int));
3536        }
3537        if (src_fs->all_squash_count > 0 && src_fs->all_squash_hosts)
3538        {
3539            int i;
3540            dest_fs->all_squash_hosts = (char **) calloc(src_fs->all_squash_count, sizeof(char *));
3541            assert(dest_fs->all_squash_hosts);
3542            for (i = 0; i < src_fs->all_squash_count; i++)
3543            {
3544                dest_fs->all_squash_hosts[i] = strdup(src_fs->all_squash_hosts[i]);
3545                assert(dest_fs->all_squash_hosts[i]);
3546            }
3547        }
3548        if (src_fs->all_squash_count > 0 && src_fs->all_squash_netmasks)
3549        {
3550            dest_fs->all_squash_netmasks = (int *) calloc(src_fs->all_squash_count, sizeof(int));
3551            assert(dest_fs->all_squash_netmasks);
3552            memcpy(dest_fs->all_squash_netmasks, src_fs->all_squash_netmasks, src_fs->all_squash_count * sizeof(int));
3553        }
3554        dest_fs->exp_anon_uid = src_fs->exp_anon_uid;
3555        dest_fs->exp_anon_gid = src_fs->exp_anon_gid;
3556
3557        dest_fs->fp_buffer_size = src_fs->fp_buffer_size;
3558        dest_fs->fp_buffers_per_flow = src_fs->fp_buffers_per_flow;
3559    }
3560}
3561
3562
3563static host_alias_s *find_host_alias_ptr_by_alias(
3564    struct server_configuration_s *config_s,
3565    char *alias,
3566    int *index)
3567{
3568    PINT_llist *cur = NULL;
3569    struct host_alias_s *ret = NULL;
3570    struct host_alias_s *cur_alias = NULL;
3571    int ind = 0;
3572
3573    if (config_s && alias)
3574    {
3575        cur = config_s->host_aliases;
3576        while(cur)
3577        {
3578            ind++;
3579            cur_alias = PINT_llist_head(cur);
3580            if (!cur_alias)
3581            {
3582                break;
3583            }
3584            assert(cur_alias->host_alias);
3585            assert(cur_alias->bmi_address);
3586
3587            if (strcmp(cur_alias->host_alias,alias) == 0)
3588            {
3589                ret = cur_alias;
3590                break;
3591            }
3592            cur = PINT_llist_next(cur);
3593        }
3594    }
3595    if(index) *index = ind - 1;
3596    return ret;
3597}
3598
3599static struct host_handle_mapping_s *get_or_add_handle_mapping(
3600    PINT_llist *list,
3601    char *alias)
3602{
3603    PINT_llist *cur = list;
3604    struct host_handle_mapping_s *ret = NULL;
3605    struct host_handle_mapping_s *handle_mapping = NULL;
3606
3607    while(cur)
3608    {
3609        handle_mapping = PINT_llist_head(cur);
3610        if (!handle_mapping)
3611        {
3612            break;
3613        }
3614        assert(handle_mapping->alias_mapping);
3615        assert(handle_mapping->alias_mapping->host_alias);
3616        assert(handle_mapping->handle_range);
3617
3618        if (strcmp(handle_mapping->alias_mapping->host_alias,
3619                   alias) == 0)
3620        {
3621            ret = handle_mapping;
3622            break;
3623        }
3624        cur = PINT_llist_next(cur);
3625    }
3626
3627    if (!ret)
3628    {
3629        ret = (host_handle_mapping_s *)
3630            malloc(sizeof(struct host_handle_mapping_s));
3631        if (ret)
3632        {
3633            memset(ret,0,sizeof(struct host_handle_mapping_s));
3634        }
3635    }
3636    return ret;
3637}
3638
3639static int build_extent_array(
3640    char *handle_range_str,
3641    PVFS_handle_extent_array *handle_extent_array)
3642{
3643    int i = 0, status = 0, num_extents = 0;
3644    PVFS_handle_extent cur_extent;
3645
3646    if (handle_range_str && handle_extent_array)
3647    {
3648        /* first pass, find out how many extents there are total */
3649        while(PINT_parse_handle_ranges(handle_range_str,
3650                                       &cur_extent, &status))
3651        {
3652            num_extents++;
3653        }
3654
3655        if (num_extents)
3656        {
3657            handle_extent_array->extent_count = num_extents;
3658            handle_extent_array->extent_array = (PVFS_handle_extent *)
3659                malloc(num_extents * sizeof(PVFS_handle_extent));
3660            if (!handle_extent_array->extent_array)
3661            {
3662                gossip_err("Error: failed to alloc %d extents\n",
3663                           handle_extent_array->extent_count);
3664                return -1;
3665            }
3666            memset(handle_extent_array->extent_array,0,
3667                   (num_extents * sizeof(PVFS_handle_extent)));
3668
3669            /* reset opaque handle parsing state for next iteration */
3670            status = 0;
3671
3672            /* second pass, fill in the extent array */
3673            while(PINT_parse_handle_ranges(handle_range_str,
3674                                           &cur_extent, &status))
3675            {
3676                handle_extent_array->extent_array[i] = cur_extent;
3677                i++;
3678            }
3679        }
3680    }
3681    return 0;
3682}
3683
3684#ifdef USE_TRUSTED
3685/*
3686 * Function: PINT_config_get_allowed_ports
3687 *
3688 * Params:   struct server_configuration_s          *server_config
3689 *           int           *enabled
3690 *           unsigned long *ports (OUT)
3691 *
3692 * Returns:  by filling up *ports from the allowed_ports array
3693 *           0 on success and -1 on failure
3694 *
3695 * Synopsis: Retrieve the list of allowed ports (i.e. range)
3696 */
3697int PINT_config_get_allowed_ports(
3698    struct server_configuration_s *config_s,
3699    int *enabled,
3700    unsigned long *allowed_ports)
3701{
3702    int ret = -1;
3703
3704    if (config_s)
3705    {
3706        *enabled = config_s->ports_enabled;
3707        if (*enabled == 1)
3708        {
3709            allowed_ports[0] = config_s->allowed_ports[0];
3710            allowed_ports[1] = config_s->allowed_ports[1];
3711        }
3712        ret = 0;
3713    }
3714    return ret;
3715}
3716
3717/*
3718 * Function: PINT_config_get_allowed_networks
3719 *
3720 * Params:   struct server_configuration_s *server_config
3721 *           int  *enabled
3722 *           int  *allowed_network_count (OUT)
3723 *           char **allowed_networks (OUT)
3724 *           int *allowed_netmasks (OUT)
3725 *
3726 * Returns:  Fills up *allowed_network_count, *allowed_networks and *allowed_netmasks
3727 *           and returns 0 on success and -1 on failure
3728 *
3729 * Synopsis: Retrieve the list of allowed network addresses and netmasks
3730 */
3731
3732int PINT_config_get_allowed_networks(
3733    struct server_configuration_s *config_s,
3734    int  *enabled,
3735    int  *allowed_networks_count,
3736    char ***allowed_networks,
3737    int  **allowed_masks)
3738{
3739    int ret = -1;
3740
3741    if (config_s)
3742    {
3743        *enabled = config_s->network_enabled;
3744        if (*enabled == 1)
3745        {
3746            *allowed_networks_count = config_s->allowed_networks_count;
3747            *allowed_networks = config_s->allowed_networks;
3748            *allowed_masks    = config_s->allowed_masks;
3749        }
3750        ret = 0;
3751    }
3752    return ret;
3753}
3754
3755#endif
3756
3757/*
3758 * Function: PINT_config_get_host_addr_ptr
3759 *
3760 * Params:   struct server_configuration_s*,
3761 *           char *alias
3762 *
3763 * Returns:  char * (bmi_address) on success; NULL on failure
3764 *
3765 * Synopsis: retrieve the bmi_address matching the specified alias
3766 *           
3767 */
3768char *PINT_config_get_host_addr_ptr(
3769    struct server_configuration_s *config_s,
3770    char *alias)
3771{
3772    char *ret = (char *)0;
3773    PINT_llist *cur = NULL;
3774    struct host_alias_s *cur_alias = NULL;
3775
3776    if (config_s && alias)
3777    {
3778        cur = config_s->host_aliases;
3779        while(cur)
3780        {
3781            cur_alias = PINT_llist_head(cur);
3782            if (!cur_alias)
3783            {
3784                break;
3785            }
3786            assert(cur_alias->host_alias);
3787            assert(cur_alias->bmi_address);
3788
3789            if (strcmp(cur_alias->host_alias,alias) == 0)
3790            {
3791                ret = cur_alias->bmi_address;
3792                break;
3793            }
3794            cur = PINT_llist_next(cur);
3795        }
3796    }
3797    return ret;
3798}
3799
3800/*
3801 * Function: PINT_config_get_host_alias_ptr
3802 *
3803 * Params:   struct server_configuration_s*,
3804 *           char *bmi_address
3805 *
3806 * Returns:  char * (alias) on success; NULL on failure
3807 *
3808 * Synopsis: retrieve the alias matching the specified bmi_address
3809 *           
3810 */
3811char *PINT_config_get_host_alias_ptr(
3812    struct server_configuration_s *config_s,
3813    char *bmi_address)
3814{
3815    char *ret = (char *)0;
3816    PINT_llist *cur = NULL;
3817    struct host_alias_s *cur_alias = NULL;
3818
3819    if (config_s && bmi_address)
3820    {
3821        cur = config_s->host_aliases;
3822        while(cur)
3823        {
3824            cur_alias = PINT_llist_head(cur);
3825            if (!cur_alias)
3826            {
3827                break;
3828            }
3829            assert(cur_alias->host_alias);
3830            assert(cur_alias->bmi_address);
3831
3832            if (strcmp(cur_alias->bmi_address,bmi_address) == 0)
3833            {
3834                ret = cur_alias->host_alias;
3835                break;
3836            }
3837            cur = PINT_llist_next(cur);
3838        }
3839    }
3840    return ret;
3841}
3842
3843/*
3844 * Function: PINT_config_get_meta_handle_range_str
3845 *
3846 * Params:   struct server_configuration_s*,
3847 *           struct filesystem_configuration_s *fs
3848 *
3849 * Returns:  char * (handle range) on success; NULL on failure
3850 *
3851 * Synopsis: return the meta handle range (string) on the specified
3852 *           filesystem that matches the host specific configuration
3853 *           
3854 */
3855char *PINT_config_get_meta_handle_range_str(
3856    struct server_configuration_s *config_s,
3857    struct filesystem_configuration_s *fs)
3858{
3859    return get_handle_range_str(config_s,fs,1);
3860}
3861
3862int PINT_config_get_meta_handle_extent_array(
3863    struct server_configuration_s *config_s,
3864    PVFS_fs_id fs_id,
3865    PVFS_handle_extent_array *extent_array)
3866{
3867    int ret = -1;
3868    PINT_llist *cur = NULL;
3869    char *my_alias = NULL;
3870    filesystem_configuration_s *cur_fs = NULL;
3871    struct host_handle_mapping_s *cur_h_mapping = NULL;
3872
3873    if (config_s && extent_array)
3874    {
3875        cur = config_s->file_systems;
3876        while(cur)
3877        {
3878            cur_fs = PINT_llist_head(cur);
3879            if (!cur_fs)
3880            {
3881                break;
3882            }
3883
3884            if (cur_fs->coll_id == fs_id)
3885            {
3886                break;
3887            }
3888            cur = PINT_llist_next(cur);
3889        }
3890
3891        if (cur_fs)
3892        {
3893            my_alias = PINT_config_get_host_alias_ptr(
3894                config_s, config_s->host_id);
3895            if (my_alias)
3896            {
3897                cur = cur_fs->meta_handle_ranges;
3898
3899                while(cur)
3900                {
3901                    cur_h_mapping = PINT_llist_head(cur);
3902                    if (!cur_h_mapping)
3903                    {
3904                        break;
3905                    }
3906
3907                    assert(cur_h_mapping->handle_range);
3908                    assert(cur_h_mapping->alias_mapping);
3909                    assert(cur_h_mapping->alias_mapping->host_alias);
3910
3911                    if (strcmp(cur_h_mapping->alias_mapping->host_alias,
3912                               my_alias) == 0)
3913                    {
3914                        extent_array->extent_count =
3915                            cur_h_mapping->handle_extent_array.extent_count;
3916                        extent_array->extent_array = malloc(
3917                            (extent_array->extent_count *
3918                             sizeof(PVFS_handle_extent)));
3919                        assert(extent_array->extent_array);
3920                        memcpy(extent_array->extent_array,
3921                               cur_h_mapping->handle_extent_array.extent_array,
3922                               (extent_array->extent_count *
3923                                sizeof(PVFS_handle_extent)));
3924
3925                        ret = 0;
3926                        break;
3927                    }
3928                    cur = PINT_llist_next(cur);
3929                }
3930            }
3931        }
3932    }
3933    return ret;
3934}
3935
3936
3937/*
3938 * Function: PINT_config_get_data_handle_range_str
3939 *
3940 * Params:   struct server_configuration_s*,
3941 *           struct filesystem_configuration_s *fs
3942 *
3943 * Returns:  char * (handle range) on success; NULL on failure
3944 *
3945 * Synopsis: return the data handle range (string) on the specified
3946 *           filesystem that matches the host specific configuration
3947 *           
3948 */
3949char *PINT_config_get_data_handle_range_str(
3950    struct server_configuration_s *config_s,
3951    struct filesystem_configuration_s *fs)
3952{
3953    return get_handle_range_str(config_s,fs,0);
3954}
3955
3956/*
3957 * Function: PINT_config_get_merged_handle_range_str
3958 *
3959 * Params:   struct server_configuration_s*,
3960 *           struct filesystem_configuration_s *fs
3961 *
3962 * Returns:  char * (handle range) on success; NULL on failure
3963 *           NOTE: The returned string MUST be freed by the caller
3964 *           if it's a non-NULL value
3965 *
3966 * Synopsis: return the meta handle range and data handle range strings
3967 *           on the specified filesystem that matches the host specific
3968 *           configuration merged as one single handle range
3969 *           
3970 */
3971char *PINT_config_get_merged_handle_range_str(
3972    struct server_configuration_s *config_s,
3973    struct filesystem_configuration_s *fs)
3974{
3975    char *merged_range = NULL;
3976    char *mrange = get_handle_range_str(config_s,fs,1);
3977    char *drange = get_handle_range_str(config_s,fs,0);
3978
3979    if (mrange && drange)
3980    {
3981        merged_range = PINT_merge_handle_range_strs(mrange, drange);
3982    }
3983    else if (mrange)
3984    {
3985        merged_range = strdup(mrange);
3986    }
3987    else if (drange)
3988    {
3989        merged_range = strdup(drange);
3990    }
3991    return merged_range;
3992}
3993
3994/*
3995  verify that the config file exists.  if so, cache it in RAM so
3996  that getconfig will not have to re-read the file contents each time.
3997  returns 0 on success; 1 on failure.
3998
3999  even if this call fails half way into it, a PINT_config_release
4000  call should properly de-alloc all consumed memory.
4001*/
4002static int cache_config_files(
4003    struct server_configuration_s *config_s,
4004    char *global_config_filename)
4005{
4006    int fd = 0, nread = 0;
4007    struct stat statbuf;
4008    char *working_dir = NULL;
4009    char *my_global_fn = NULL;
4010    char buf[512] = {0};
4011
4012    assert(config_s);
4013
4014    working_dir = getenv("PWD");
4015
4016    /* pick some filenames if not provided */
4017    my_global_fn = ((global_config_filename != NULL) ?
4018                    global_config_filename : "fs.conf");
4019
4020open_global_config:
4021    memset(&statbuf, 0, sizeof(struct stat));
4022    if (stat(my_global_fn, &statbuf) == 0)
4023    {
4024        if (statbuf.st_size == 0)
4025        {
4026            gossip_err("Invalid config file %s.  This "
4027                       "file is 0 bytes in length!\n", my_global_fn);
4028            goto error_exit;
4029        }
4030        config_s->fs_config_filename = strdup(my_global_fn);
4031        config_s->fs_config_buflen = statbuf.st_size + 1;
4032    }
4033    else if (errno == ENOENT)
4034    {
4035        gossip_err("Failed to find global config file %s.  This "
4036                   "file does not exist!\n", my_global_fn);
4037        goto error_exit;
4038    }
4039    else
4040    {
4041        assert(working_dir);
4042        snprintf(buf, 512, "%s/%s",working_dir, my_global_fn);
4043        my_global_fn = buf;
4044        goto open_global_config;
4045    }
4046
4047    if (!config_s->fs_config_filename ||
4048        (config_s->fs_config_buflen == 0))
4049    {
4050        gossip_err("Failed to stat fs config file.  Please make sure that ");
4051        gossip_err("the file %s\nexists, is not a zero file size, and has\n",
4052                   config_s->fs_config_filename);
4053        gossip_err("permissions suitable for opening and reading it.\n");
4054        goto error_exit;
4055    }
4056
4057    if ((fd = open(my_global_fn, O_RDONLY)) == -1)
4058    {
4059        gossip_err("Failed to open fs config file %s.\n",
4060                   my_global_fn);
4061        goto error_exit;
4062    }
4063
4064    config_s->fs_config_buf = (char *) malloc(config_s->fs_config_buflen);
4065    if (!config_s->fs_config_buf)
4066    {
4067        gossip_err("Failed to allocate %d bytes for caching the fs "
4068                   "config file\n", (int) config_s->fs_config_buflen);
4069        goto close_fd_fail;
4070    }
4071
4072    memset(config_s->fs_config_buf, 0, config_s->fs_config_buflen);
4073    nread = read(fd, config_s->fs_config_buf,
4074                 (config_s->fs_config_buflen - 1));
4075    if (nread != (config_s->fs_config_buflen - 1))
4076    {
4077        gossip_err("Failed to read fs config file %s "
4078                   "(nread is %d | config_buflen is %d)\n",
4079                   my_global_fn, nread, (int)(config_s->fs_config_buflen - 1));
4080        goto close_fd_fail;
4081    }
4082    close(fd);
4083
4084    return 0;
4085
4086  close_fd_fail:
4087    close(fd);
4088
4089  error_exit:
4090    return 1;
4091}
4092
4093static char *get_handle_range_str(
4094    struct server_configuration_s *config_s,
4095    struct filesystem_configuration_s *fs,
4096    int meta_handle_range)
4097{
4098    char *ret = (char *)0;
4099    char *my_alias = (char *)0;
4100    PINT_llist *cur = NULL;
4101    struct host_handle_mapping_s *cur_h_mapping = NULL;
4102
4103    if (config_s && config_s->host_id && fs)
4104    {
4105        my_alias = PINT_config_get_host_alias_ptr(
4106            config_s,config_s->host_id);
4107        if (my_alias)
4108        {
4109            cur = (meta_handle_range ? fs->meta_handle_ranges :
4110                   fs->data_handle_ranges);
4111            while(cur)
4112            {
4113                cur_h_mapping = PINT_llist_head(cur);
4114                if (!cur_h_mapping)
4115                {
4116                    break;
4117                }
4118                assert(cur_h_mapping->alias_mapping);
4119                assert(cur_h_mapping->alias_mapping->host_alias);
4120                assert(cur_h_mapping->handle_range);
4121
4122                if (strcmp(cur_h_mapping->alias_mapping->host_alias,
4123                           my_alias) == 0)
4124                {
4125                    ret = cur_h_mapping->handle_range;
4126                    break;
4127                }
4128                cur = PINT_llist_next(cur);
4129            }
4130        }
4131    }
4132    return ret;
4133}
4134
4135/*
4136  returns 1 if the specified configuration object is valid
4137  (i.e. contains values that make sense); 0 otherwise
4138*/
4139int PINT_config_is_valid_configuration(
4140    struct server_configuration_s *config_s)
4141{
4142    int ret = 0, fs_count = 0;
4143    PINT_llist *cur = NULL;
4144    struct filesystem_configuration_s *cur_fs = NULL;
4145   
4146    if (config_s && config_s->bmi_modules && config_s->event_logging &&
4147        config_s->logfile)
4148    {
4149        cur = config_s->file_systems;
4150        while(cur)
4151        {
4152            cur_fs = PINT_llist_head(cur);
4153            if (!cur_fs)
4154            {
4155                break;
4156            }
4157
4158            ret += is_valid_filesystem_configuration(config_s,cur_fs);
4159            fs_count++;
4160
4161            cur = PINT_llist_next(cur);
4162        }
4163        ret = ((ret == fs_count) ? 1 : 0);
4164    }
4165    return ret;
4166}
4167
4168
4169/*
4170  returns 1 if the specified coll_id is valid based on
4171  the specified server_configuration struct; 0 otherwise
4172*/
4173int PINT_config_is_valid_collection_id(
4174    struct server_configuration_s *config_s,
4175    PVFS_fs_id fs_id)
4176{
4177    int ret = 0;
4178    PINT_llist *cur = NULL;
4179    struct filesystem_configuration_s *cur_fs = NULL;
4180
4181    if (config_s)
4182    {
4183        cur = config_s->file_systems;
4184        while(cur)
4185        {
4186            cur_fs = PINT_llist_head(cur);
4187            if (!cur_fs)
4188            {
4189                break;
4190            }
4191            if (cur_fs->coll_id == fs_id)
4192            {
4193                ret = 1;
4194                break;
4195            }
4196            cur = PINT_llist_next(cur);
4197        }
4198    }
4199    return ret;
4200}
4201
4202/*
4203  returns pointer to fs config if the config object has information on
4204  the specified filesystem; NULL otherwise
4205*/
4206struct filesystem_configuration_s* PINT_config_find_fs_name(
4207    struct server_configuration_s *config_s,
4208    char *fs_name)
4209{
4210    PINT_llist *cur = NULL;
4211    struct filesystem_configuration_s *cur_fs = NULL;
4212
4213    if (config_s && fs_name)
4214    {
4215        cur = config_s->file_systems;
4216        while(cur)
4217        {
4218            cur_fs = PINT_llist_head(cur);
4219            if (!cur_fs)
4220            {
4221                break;
4222            }
4223            assert(cur_fs->file_system_name);
4224            if (strcmp(cur_fs->file_system_name,fs_name) == 0)
4225            {
4226                return(cur_fs);
4227            }
4228            cur = PINT_llist_next(cur);
4229        }
4230    }
4231    return(NULL);
4232}
4233
4234/* PINT_config_find_fs()
4235 *
4236 * searches the given server configuration information to find a file
4237 * system configuration that matches the fs_id
4238 *
4239 * returns pointer to file system config struct on success, NULL on failure
4240 */
4241struct filesystem_configuration_s* PINT_config_find_fs_id(
4242    struct server_configuration_s* config_s,
4243    PVFS_fs_id fs_id)
4244{
4245    PINT_llist *cur = NULL;
4246    struct filesystem_configuration_s *cur_fs = NULL;
4247
4248    if (config_s)
4249    {
4250        cur = config_s->file_systems;
4251        while(cur)
4252        {
4253            cur_fs = PINT_llist_head(cur);
4254            if (!cur_fs)
4255            {
4256                break;
4257            }
4258            if (cur_fs->coll_id == fs_id)
4259            {
4260                return(cur_fs);
4261            }
4262            cur = PINT_llist_next(cur);
4263        }
4264    }
4265    return(NULL);
4266}
4267
4268PVFS_fs_id PINT_config_get_fs_id_by_fs_name(
4269    struct server_configuration_s *config_s,
4270    char *fs_name)
4271{
4272    PVFS_fs_id fs_id = 0;
4273    struct filesystem_configuration_s *fs =
4274        PINT_config_find_fs_name(config_s, fs_name);
4275    if (fs)
4276    {
4277        fs_id = fs->coll_id;
4278    }
4279    return fs_id;
4280}
4281
4282/* PINT_config_get_filesystems()
4283 *
4284 * returns a PINT_llist of all filesystems registered in the
4285 * specified configuration object
4286 *
4287 * returns pointer to a list of file system config structs on success,
4288 * NULL on failure
4289 */
4290PINT_llist *PINT_config_get_filesystems(
4291    struct server_configuration_s *config_s)
4292{
4293    return (config_s ? config_s->file_systems : NULL);
4294}
4295
4296/*
4297  given a configuration object, weed out all information about other
4298  filesystems if the fs_id does not match that of the specifed fs_id
4299*/
4300int PINT_config_trim_filesystems_except(
4301    struct server_configuration_s *config_s,
4302    PVFS_fs_id fs_id)
4303{
4304    int ret = -PVFS_EINVAL;
4305    PINT_llist *cur = NULL, *new_fs_list = NULL;
4306    struct filesystem_configuration_s *cur_fs = NULL, *new_fs = NULL;
4307
4308    if (config_s)
4309    {
4310        new_fs_list = PINT_llist_new();
4311        if (!new_fs_list)
4312        {
4313            return -PVFS_ENOMEM;
4314        }
4315
4316        cur = config_s->file_systems;
4317        while(cur)
4318        {
4319            cur_fs = PINT_llist_head(cur);
4320            if (!cur_fs)
4321            {
4322                break;
4323            }
4324
4325            if (cur_fs->coll_id == fs_id)
4326            {
4327                new_fs = (struct filesystem_configuration_s *)malloc(
4328                    sizeof(struct filesystem_configuration_s));
4329                assert(new_fs);
4330
4331                memset(new_fs, 0,
4332                       sizeof(struct filesystem_configuration_s));
4333
4334                copy_filesystem(new_fs, cur_fs);
4335                PINT_llist_add_to_head(new_fs_list, (void *)new_fs);
4336                break;
4337            }
4338            cur = PINT_llist_next(cur);
4339        }
4340
4341        PINT_llist_free(config_s->file_systems,free_filesystem);
4342        config_s->file_systems = new_fs_list;
4343
4344        if (PINT_llist_count(config_s->file_systems) == 1)
4345        {
4346            ret = 0;
4347        }
4348    }
4349    return ret;
4350}
4351
4352int PINT_config_get_fs_key(
4353    struct server_configuration_s *config,
4354    PVFS_fs_id fs_id,
4355    char ** key,
4356    int * length)
4357{
4358#ifndef WITH_OPENSSL
4359    *key = NULL;
4360    *length = 0;
4361    return -PVFS_ENOSYS;
4362#else
4363    int len, b64len;
4364    char *b64buf;
4365    struct filesystem_configuration_s *fs_conf = NULL;
4366    BIO *b64 = NULL;
4367    BIO *mem = NULL;
4368    BIO *bio = NULL;
4369
4370    if (config)
4371    {
4372        fs_conf = PINT_config_find_fs_id(config, fs_id);
4373    }
4374   
4375    if(!fs_conf)
4376    {
4377        gossip_err("Could not locate fs_conf for fs_id %d\n", fs_id);
4378        return -PVFS_EINVAL;
4379    }
4380    /* This is actually ok since an FS may not have secret key */
4381    if (!fs_conf->secret_key)
4382    {
4383        *length = 0;
4384        *key = NULL;
4385        return 0;
4386    }
4387   
4388    b64len = strlen(fs_conf->secret_key);
4389    b64buf = malloc(b64len+1);
4390    if(!b64buf)
4391    {
4392        return -PVFS_ENOMEM;
4393    }
4394    memcpy(b64buf, fs_conf->secret_key, b64len);
4395
4396    /* for some reason openssl's base64 decoding needs a newline at the end */
4397    b64buf[b64len] = '\n';
4398
4399    b64 = BIO_new(BIO_f_base64());
4400    mem = BIO_new_mem_buf(b64buf, b64len+1);
4401    bio = BIO_push(b64, mem);
4402
4403    len = BIO_pending(bio);
4404    *key = malloc(len);
4405    if(!*key)
4406    {
4407        BIO_free_all(bio);
4408        return -PVFS_ENOMEM;
4409   }
4410   
4411    *length = BIO_read(bio, *key, len);
4412
4413    free(b64buf);
4414   
4415    BIO_free_all(bio);
4416    return 0;
4417#endif /* WITH_OPENSSL */
4418}
4419
4420#ifdef __PVFS2_TROVE_SUPPORT__
4421static int is_root_handle_in_my_range(
4422    struct server_configuration_s *config,
4423    struct filesystem_configuration_s *fs)
4424{
4425    int ret = 0;
4426    PINT_llist *cur = NULL;
4427    PINT_llist *extent_list = NULL;
4428    char *cur_host_id = (char *)0;
4429    host_handle_mapping_s *cur_h_mapping = NULL;
4430
4431    if (config && is_populated_filesystem_configuration(fs))
4432    {
4433        /*
4434          check if the root handle is within one of the
4435          specified meta host's handle ranges for this fs;
4436          a root handle can't exist in a data handle range!
4437        */
4438        cur = fs->meta_handle_ranges;
4439        while(cur)
4440        {
4441            cur_h_mapping = PINT_llist_head(cur);
4442            if (!cur_h_mapping)
4443            {
4444                break;
4445            }
4446            assert(cur_h_mapping->alias_mapping);
4447            assert(cur_h_mapping->alias_mapping->host_alias);
4448            assert(cur_h_mapping->alias_mapping->bmi_address);
4449            assert(cur_h_mapping->handle_range);
4450
4451            cur_host_id = cur_h_mapping->alias_mapping->bmi_address;
4452            if (!cur_host_id)
4453            {
4454                gossip_err("Invalid host ID for alias %s.\n",
4455                           cur_h_mapping->alias_mapping->host_alias);
4456                break;
4457            }
4458
4459            /* only check if this is *our* range */
4460            if (strcmp(config->host_id,cur_host_id) == 0)
4461            {
4462                extent_list = PINT_create_extent_list(
4463                    cur_h_mapping->handle_range);
4464                if (!extent_list)
4465                {
4466                    gossip_err("Failed to create extent list.\n");
4467                    break;
4468                }
4469
4470                ret = PINT_handle_in_extent_list(
4471                    extent_list,fs->root_handle);
4472                PINT_release_extent_list(extent_list);
4473                if (ret == 1)
4474                {
4475                    break;
4476                }
4477            }
4478            cur = PINT_llist_next(cur);
4479        }
4480    }
4481    return ret;
4482}
4483
4484/*
4485  create a storage space based on configuration settings object
4486  with the particular host settings local to the caller
4487*/
4488int PINT_config_pvfs2_mkspace(
4489    struct server_configuration_s *config)
4490{
4491    int ret = 1;
4492    PVFS_handle root_handle = 0;
4493    int create_collection_only = 0;
4494    PINT_llist *cur = NULL;
4495    char *cur_meta_handle_range, *cur_data_handle_range = NULL;
4496    filesystem_configuration_s *cur_fs = NULL;
4497
4498    if (config)
4499    {
4500        cur = config->file_systems;
4501        while(cur)
4502        {
4503            cur_fs = PINT_llist_head(cur);
4504            if (!cur_fs)
4505            {
4506                break;
4507            }
4508
4509            cur_meta_handle_range = PINT_config_get_meta_handle_range_str(
4510                config, cur_fs);
4511            cur_data_handle_range = PINT_config_get_data_handle_range_str(
4512                config, cur_fs);
4513
4514            /*
4515              make sure have either a meta or data handle range (or
4516              both).  if we have no handle range, the config is
4517              broken.
4518            */
4519            if (!cur_meta_handle_range && !cur_data_handle_range)
4520            {
4521                gossip_err("Could not find handle range for host %s\n",
4522                           config->host_id);
4523                gossip_err("Please make sure that the host names in "
4524                           "%s are consistent\n",
4525                           config->fs_config_filename);
4526                break;
4527            }
4528
4529            /*
4530              check if root handle is in our handle range for this fs.
4531              if it is, we're responsible for creating it on disk when
4532              creating the storage space
4533            */
4534            root_handle = (is_root_handle_in_my_range(config, cur_fs) ?
4535                           cur_fs->root_handle : PVFS_HANDLE_NULL);
4536
4537            /*
4538              for the first fs/collection we encounter, create the
4539              storage space if it doesn't exist.
4540            */
4541            gossip_debug(
4542                GOSSIP_SERVER_DEBUG,"\n*****************************\n");
4543            gossip_debug(
4544                GOSSIP_SERVER_DEBUG, "Creating new PVFS2 %s\n",
4545                (create_collection_only ? "collection" :
4546                 "storage space"));
4547
4548            ret = pvfs2_mkspace(
4549                config->data_path, config->meta_path, cur_fs->file_system_name,
4550                cur_fs->coll_id, root_handle, cur_meta_handle_range,
4551                cur_data_handle_range, create_collection_only, 1);
4552
4553            gossip_debug(
4554                GOSSIP_SERVER_DEBUG,"\n*****************************\n");
4555
4556            /*
4557              now that the storage space is created, set the
4558              create_collection_only variable so that subsequent
4559              calls to pvfs2_mkspace will not fail when it finds
4560              that the storage space already exists; this causes
4561              pvfs2_mkspace to only add the collection to the
4562              already existing storage space.
4563            */
4564            create_collection_only = 1;
4565
4566            cur = PINT_llist_next(cur);
4567        }
4568    }
4569    return ret;
4570}
4571
4572/*
4573  remove a storage space based on configuration settings object
4574  with the particular host settings local to the caller
4575*/
4576int PINT_config_pvfs2_rmspace(
4577    struct server_configuration_s *config)
4578{
4579    int ret = 1;
4580    int remove_collection_only = 0;
4581    PINT_llist *cur = NULL;
4582    filesystem_configuration_s *cur_fs = NULL;
4583
4584    if (config)
4585    {
4586        cur = config->file_systems;
4587        while(cur)
4588        {
4589            cur_fs = PINT_llist_head(cur);
4590            if (!cur_fs)
4591            {
4592                break;
4593            }
4594
4595            cur = PINT_llist_next(cur);
4596            remove_collection_only = (PINT_llist_head(cur) ? 1 : 0);
4597
4598            gossip_debug(
4599                GOSSIP_SERVER_DEBUG,"\n*****************************\n");
4600            gossip_debug(
4601                GOSSIP_SERVER_DEBUG,"Removing existing PVFS2 %s\n",
4602                (remove_collection_only ? "collection" :
4603                 "storage space"));
4604            ret = pvfs2_rmspace(config->data_path,
4605                                config->meta_path,
4606                                cur_fs->file_system_name,
4607                                cur_fs->coll_id,
4608                                remove_collection_only,
4609                                1);
4610            gossip_debug(
4611                GOSSIP_SERVER_DEBUG,"\n*****************************\n");
4612        }
4613    }
4614    return ret;
4615}
4616
4617/*
4618  returns the metadata sync mode (storage hint) for the specified
4619  fs_id if valid; TROVE_SYNC otherwise
4620*/
4621int PINT_config_get_trove_sync_meta(
4622    struct server_configuration_s *config,
4623    PVFS_fs_id fs_id)
4624{
4625    struct filesystem_configuration_s *fs_conf = NULL;
4626
4627    if (config)
4628    {
4629        fs_conf = PINT_config_find_fs_id(config, fs_id);
4630    }
4631    return (fs_conf ? fs_conf->trove_sync_meta : TROVE_SYNC);
4632}
4633
4634/*
4635  returns the data sync mode (storage hint) for the specified
4636  fs_id if valid; TROVE_SYNC otherwise
4637*/
4638int PINT_config_get_trove_sync_data(
4639    struct server_configuration_s *config,
4640    PVFS_fs_id fs_id)
4641{
4642    struct filesystem_configuration_s *fs_conf = NULL;
4643
4644    if (config)
4645    {
4646        fs_conf = PINT_config_find_fs_id(config, fs_id);
4647    }
4648    return (fs_conf ? fs_conf->trove_sync_data : TROVE_SYNC);
4649}
4650
4651#endif
4652
4653/*
4654 * Local variables:
4655 *  c-indent-level: 4
4656 *  c-basic-offset: 4
4657 * End:
4658 *
4659 * vim: ts=8 sts=4 sw=4 expandtab
4660 */
Note: See TracBrowser for help on using the browser.