Check-in [b6ea13d9c3]
Overview
Comment:Added support for hot-restart of AppFSd on SIGUP
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: b6ea13d9c3baa66fbacd50088fc0d8215f81afd0
User & Date: rkeene on 2014-11-11 17:43:57
Other Links: manifest | tags
Context
2014-11-11
17:48
Updated to not continue to reset interpreters forever after a restart request check-in: 65a6138eb6 user: rkeene tags: trunk
17:43
Added support for hot-restart of AppFSd on SIGUP check-in: b6ea13d9c3 user: rkeene tags: trunk
17:18
Added start of CPIO mode for appfs-mkfs check-in: 2e9fc0f81c user: rkeene tags: trunk
Changes

Modified appfsd.c from [5e5056a24c] to [2fbbb1d1a2].

1
2
3
4
5

6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
13





+







#define FUSE_USE_VERSION 26

#include <sys/fsuid.h>
#include <sys/types.h>
#include <pthread.h>
#include <signal.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
49
50
51
52
53
54
55





56
57
58
59
60
61
62
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68







+
+
+
+
+







/*
 * Global variables for AppFS caching
 */
pthread_mutex_t appfs_path_info_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
int appfs_path_info_cache_size = 8209;
struct appfs_pathinfo *appfs_path_info_cache = NULL;

/*
 * Global variables for AppFS Tcl Interpreter restarting
 */
int interp_reset_key = 0;

/*
 * AppFS Path Type:  Describes the type of path a given file is
 */
typedef enum {
	APPFS_PATHTYPE_INVALID,
	APPFS_PATHTYPE_DOES_NOT_EXIST,
	APPFS_PATHTYPE_FILE,
246
247
248
249
250
251
252

253
254








255
256
257
258
259
260
261
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276







+


+
+
+
+
+
+
+
+








/*
 * Return the thread-specific Tcl interpreter, creating it if needed
 */
static Tcl_Interp *appfs_TclInterp(void) {
	Tcl_Interp *interp;
	int pthread_ret;
	static __thread int thread_interp_reset_key = 0;

	interp = pthread_getspecific(interpKey);
	if (interp != NULL && thread_interp_reset_key != interp_reset_key) {
		APPFS_DEBUG("Terminating old interpreter and restarting due to reset request.");

		Tcl_DeleteInterp(interp);

		interp = NULL;
	}

	if (interp == NULL) {
		interp = appfs_create_TclInterp(NULL);

		if (interp == NULL) {
			return(NULL);
		}

307
308
309
310
311
312
313











314
315
316
317
318
319
320
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346







+
+
+
+
+
+
+
+
+
+
+








	if (retval != TCL_OK) {
		APPFS_DEBUG("Tcl command failed, ::errorInfo contains: %s\n", Tcl_GetVar(interp, "::errorInfo", 0));
	}

	return(retval);
}

/*
 * Request all Tcl interpreters restart
 */
static void appfs_tcl_ResetInterps(void) {
	APPFS_DEBUG("Requesting reset of all interpreters.");

	__sync_add_and_fetch(&interp_reset_key, 1);

	return;
}

/*
 * Determine the UID for the user making the current FUSE filesystem request.
 * This will be used to lookup the user's home directory so we can search for
 * locally modified files.
 */
static uid_t appfs_get_fsuid(void) {
553
554
555
556
557
558
559


560
561
562
563
564
565
566
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594







+
+








	return;
}

static void appfs_get_path_info_cache_flush(uid_t uid, int new_size) {
	unsigned int idx;
	int pthread_ret;

	APPFS_DEBUG("Flushing AppFS cache (uid = %lli, new_size = %i)", (long long) uid, new_size);

	pthread_ret = pthread_mutex_lock(&appfs_path_info_cache_mutex);
	if (pthread_ret != 0) {
		APPFS_DEBUG("Unable to lock path_info cache mutex !");

		return;
	}
1427
1428
1429
1430
1431
1432
1433



























1434
1435
1436
1437
1438
1439
1440
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	Tcl_CreateObjCommand(interp, "appfsd::simulate_user_fs_leave", tcl_appfs_simulate_user_fs_leave, NULL, NULL);
	Tcl_CreateObjCommand(interp, "appfsd::get_path_info_cache_flush", tcl_appfs_get_path_info_cache_flush, NULL, NULL);

	Tcl_PkgProvide(interp, "appfsd", "1.0");

	return(TCL_OK);
}

/*
 * Hot-restart support
 */
/* Initiate a hot-restart */
static void appfs_hot_restart(void) {
	appfs_tcl_ResetInterps();
	appfs_get_path_info_cache_flush(-1, -1);

	return;
}

/*
 * Signal handler to initiate a hot-restart
 */
static void appfs_signal_handler(int sig) {
	/* Do not handle signals until FUSE has been started */
	if (!appfs_fuse_started) {
		return;
	}

	if (sig == SIGHUP) {
		appfs_hot_restart();
	}

	return;
}

/*
 * FUSE operations structure
 */
static struct fuse_operations appfs_operations = {
	.getattr   = appfs_fuse_getattr,
	.readdir   = appfs_fuse_readdir,
1473
1474
1475
1476
1477
1478
1479

1480
1481
1482
1483
1484
1485
1486
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542







+







 * Entry point into this program.
 */
int main(int argc, char **argv) {
	Tcl_Interp *test_interp;
	char *test_interp_error;
	struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
	int pthread_ret;
	void *signal_ret;

	/*
	 * Skip passed program name
	 */
	if (argc == 0 || argv == NULL) {
		return(1);
	}
1559
1560
1561
1562
1563
1564
1565









1566
1567
1568
1569
1570
1571
1572
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637







+
+
+
+
+
+
+
+
+








		fprintf(stderr, "Unable to initialize Tcl interpreter for AppFSd:\n");
		fprintf(stderr, "%s\n", test_interp_error);

		return(1);
	}
	Tcl_DeleteInterp(test_interp);

	/*
	 * Register a signal handler for hot-restart requests
	 */
	signal_ret = signal(SIGHUP, appfs_signal_handler);
	if (signal_ret == SIG_ERR) {
		fprintf(stderr, "Unable to install signal handler for hot-restart\n");
		fprintf(stderr, "Hot-restart will not be available.\n");
	}

	/*
	 * Add FUSE arguments which we always supply
	 */
	fuse_opt_parse(&args, NULL, NULL, appfs_fuse_opt_cb);
	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");