Diff

Differences From Artifact [5e5056a24c]:

To Artifact [2fbbb1d1a2]:


     1      1   #define FUSE_USE_VERSION 26
     2      2   
     3      3   #include <sys/fsuid.h>
     4      4   #include <sys/types.h>
     5      5   #include <pthread.h>
            6  +#include <signal.h>
     6      7   #include <string.h>
     7      8   #include <stdarg.h>
     8      9   #include <stdlib.h>
     9     10   #include <unistd.h>
    10     11   #include <errno.h>
    11     12   #include <fcntl.h>
    12     13   #include <stdio.h>
................................................................................
    49     50   /*
    50     51    * Global variables for AppFS caching
    51     52    */
    52     53   pthread_mutex_t appfs_path_info_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
    53     54   int appfs_path_info_cache_size = 8209;
    54     55   struct appfs_pathinfo *appfs_path_info_cache = NULL;
    55     56   
           57  +/*
           58  + * Global variables for AppFS Tcl Interpreter restarting
           59  + */
           60  +int interp_reset_key = 0;
           61  +
    56     62   /*
    57     63    * AppFS Path Type:  Describes the type of path a given file is
    58     64    */
    59     65   typedef enum {
    60     66   	APPFS_PATHTYPE_INVALID,
    61     67   	APPFS_PATHTYPE_DOES_NOT_EXIST,
    62     68   	APPFS_PATHTYPE_FILE,
................................................................................
   246    252   
   247    253   /*
   248    254    * Return the thread-specific Tcl interpreter, creating it if needed
   249    255    */
   250    256   static Tcl_Interp *appfs_TclInterp(void) {
   251    257   	Tcl_Interp *interp;
   252    258   	int pthread_ret;
          259  +	static __thread int thread_interp_reset_key = 0;
   253    260   
   254    261   	interp = pthread_getspecific(interpKey);
          262  +	if (interp != NULL && thread_interp_reset_key != interp_reset_key) {
          263  +		APPFS_DEBUG("Terminating old interpreter and restarting due to reset request.");
          264  +
          265  +		Tcl_DeleteInterp(interp);
          266  +
          267  +		interp = NULL;
          268  +	}
          269  +
   255    270   	if (interp == NULL) {
   256    271   		interp = appfs_create_TclInterp(NULL);
   257    272   
   258    273   		if (interp == NULL) {
   259    274   			return(NULL);
   260    275   		}
   261    276   
................................................................................
   307    322   
   308    323   	if (retval != TCL_OK) {
   309    324   		APPFS_DEBUG("Tcl command failed, ::errorInfo contains: %s\n", Tcl_GetVar(interp, "::errorInfo", 0));
   310    325   	}
   311    326   
   312    327   	return(retval);
   313    328   }
          329  +
          330  +/*
          331  + * Request all Tcl interpreters restart
          332  + */
          333  +static void appfs_tcl_ResetInterps(void) {
          334  +	APPFS_DEBUG("Requesting reset of all interpreters.");
          335  +
          336  +	__sync_add_and_fetch(&interp_reset_key, 1);
          337  +
          338  +	return;
          339  +}
   314    340   
   315    341   /*
   316    342    * Determine the UID for the user making the current FUSE filesystem request.
   317    343    * This will be used to lookup the user's home directory so we can search for
   318    344    * locally modified files.
   319    345    */
   320    346   static uid_t appfs_get_fsuid(void) {
................................................................................
   553    579   
   554    580   	return;
   555    581   }
   556    582   
   557    583   static void appfs_get_path_info_cache_flush(uid_t uid, int new_size) {
   558    584   	unsigned int idx;
   559    585   	int pthread_ret;
          586  +
          587  +	APPFS_DEBUG("Flushing AppFS cache (uid = %lli, new_size = %i)", (long long) uid, new_size);
   560    588   
   561    589   	pthread_ret = pthread_mutex_lock(&appfs_path_info_cache_mutex);
   562    590   	if (pthread_ret != 0) {
   563    591   		APPFS_DEBUG("Unable to lock path_info cache mutex !");
   564    592   
   565    593   		return;
   566    594   	}
................................................................................
  1427   1455   	Tcl_CreateObjCommand(interp, "appfsd::simulate_user_fs_leave", tcl_appfs_simulate_user_fs_leave, NULL, NULL);
  1428   1456   	Tcl_CreateObjCommand(interp, "appfsd::get_path_info_cache_flush", tcl_appfs_get_path_info_cache_flush, NULL, NULL);
  1429   1457   
  1430   1458   	Tcl_PkgProvide(interp, "appfsd", "1.0");
  1431   1459   
  1432   1460   	return(TCL_OK);
  1433   1461   }
         1462  +
         1463  +/*
         1464  + * Hot-restart support
         1465  + */
         1466  +/* Initiate a hot-restart */
         1467  +static void appfs_hot_restart(void) {
         1468  +	appfs_tcl_ResetInterps();
         1469  +	appfs_get_path_info_cache_flush(-1, -1);
         1470  +
         1471  +	return;
         1472  +}
         1473  +
         1474  +/*
         1475  + * Signal handler to initiate a hot-restart
         1476  + */
         1477  +static void appfs_signal_handler(int sig) {
         1478  +	/* Do not handle signals until FUSE has been started */
         1479  +	if (!appfs_fuse_started) {
         1480  +		return;
         1481  +	}
         1482  +
         1483  +	if (sig == SIGHUP) {
         1484  +		appfs_hot_restart();
         1485  +	}
         1486  +
         1487  +	return;
         1488  +}
  1434   1489   
  1435   1490   /*
  1436   1491    * FUSE operations structure
  1437   1492    */
  1438   1493   static struct fuse_operations appfs_operations = {
  1439   1494   	.getattr   = appfs_fuse_getattr,
  1440   1495   	.readdir   = appfs_fuse_readdir,
................................................................................
  1473   1528    * Entry point into this program.
  1474   1529    */
  1475   1530   int main(int argc, char **argv) {
  1476   1531   	Tcl_Interp *test_interp;
  1477   1532   	char *test_interp_error;
  1478   1533   	struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
  1479   1534   	int pthread_ret;
         1535  +	void *signal_ret;
  1480   1536   
  1481   1537   	/*
  1482   1538   	 * Skip passed program name
  1483   1539   	 */
  1484   1540   	if (argc == 0 || argv == NULL) {
  1485   1541   		return(1);
  1486   1542   	}
................................................................................
  1559   1615   
  1560   1616   		fprintf(stderr, "Unable to initialize Tcl interpreter for AppFSd:\n");
  1561   1617   		fprintf(stderr, "%s\n", test_interp_error);
  1562   1618   
  1563   1619   		return(1);
  1564   1620   	}
  1565   1621   	Tcl_DeleteInterp(test_interp);
         1622  +
         1623  +	/*
         1624  +	 * Register a signal handler for hot-restart requests
         1625  +	 */
         1626  +	signal_ret = signal(SIGHUP, appfs_signal_handler);
         1627  +	if (signal_ret == SIG_ERR) {
         1628  +		fprintf(stderr, "Unable to install signal handler for hot-restart\n");
         1629  +		fprintf(stderr, "Hot-restart will not be available.\n");
         1630  +	}
  1566   1631   
  1567   1632   	/*
  1568   1633   	 * Add FUSE arguments which we always supply
  1569   1634   	 */
  1570   1635   	fuse_opt_parse(&args, NULL, NULL, appfs_fuse_opt_cb);
  1571   1636   	fuse_opt_add_arg(&args, "-odefault_permissions,fsname=appfs,subtype=appfsd,use_ino,kernel_cache,entry_timeout=0,attr_timeout=0,intr,big_writes,hard_remove");
  1572   1637