Overview
Comment: | Added more debugging, renamed appfs_terminate_interp for with more accurate name, fixed FUSE read/write to use pread/pwrite and return no short reads as is required by FUSE, added call to Tcl_FinalizeThread() on thread termination |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
d5bfe6710cf4e957ef16d3e5aabea6bc |
User & Date: | rkeene on 2014-11-15 16:46:19 |
Other Links: | manifest | tags |
Context
2014-11-15
| ||
17:20 | Updated to flush cache before exiting in exit path mode and allow short reads without returning an error as they seem to be expected check-in: 67735b9ee3 user: rkeene tags: trunk | |
16:46 | Added more debugging, renamed appfs_terminate_interp for with more accurate name, fixed FUSE read/write to use pread/pwrite and return no short reads as is required by FUSE, added call to Tcl_FinalizeThread() on thread termination check-in: d5bfe6710c user: rkeene tags: trunk | |
2014-11-14
| ||
21:46 | Updated to support unthreaded Tcl and fixed a memory leak with home directory determination check-in: 6af0168ed8 user: rkeene tags: trunk | |
Changes
Modified appfsd.c from [1768754e26] to [69177869fa].
︙ | ︙ | |||
21 22 23 24 25 26 27 | */ #ifndef APPFS_CACHEDIR #define APPFS_CACHEDIR "/var/cache/appfs" #endif /* Debugging macros */ #ifdef DEBUG | > | > > > > > > > > > > > > > > > > > | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | */ #ifndef APPFS_CACHEDIR #define APPFS_CACHEDIR "/var/cache/appfs" #endif /* Debugging macros */ #ifdef DEBUG int appfs_debug_fd = STDERR_FILENO; #define APPFS_DEBUG(x...) { \ char buf[8192]; \ int bufoff = 0; \ if (appfs_debug_fd == -1) { \ appfs_debug_fd = open("/tmp/appfsd.log", O_WRONLY | O_APPEND | O_CREAT, 0600); \ }; \ bufoff = snprintf(buf, sizeof(buf), "[debug] [t=%llx] %s:%i:%s: ", (unsigned long long) pthread_self(), __FILE__, __LINE__, __func__); \ if (bufoff < sizeof(buf)) { \ bufoff += snprintf(buf + bufoff, sizeof(buf) - bufoff, x); \ }; \ if (bufoff < sizeof(buf)) { \ bufoff += snprintf(buf + bufoff, sizeof(buf) - bufoff, "\n");\ } \ if (bufoff > sizeof(buf)) { \ bufoff = sizeof(buf); \ }; \ write(appfs_debug_fd, buf, bufoff); \ } #else #define APPFS_DEBUG(x...) /**/ #endif /* * SHA1 Tcl Package initializer, from sha1.o */ |
︙ | ︙ | |||
59 60 61 62 63 64 65 66 67 68 69 70 71 72 | /* * Handle unthreaded Tcl */ pthread_mutex_t appfs_tcl_big_global_lock = PTHREAD_MUTEX_INITIALIZER; #define appfs_call_libtcl_enter pthread_mutex_lock(&appfs_tcl_big_global_lock); #define appfs_call_libtcl_exit pthread_mutex_unlock(&appfs_tcl_big_global_lock); #else #define appfs_call_libtcl_enter /**/ #define appfs_call_libtcl_exit /**/ #endif #define appfs_call_libtcl(x...) appfs_call_libtcl_enter x appfs_call_libtcl_exit /* * Global variables for AppFS Tcl Interpreter restarting | > | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | /* * Handle unthreaded Tcl */ pthread_mutex_t appfs_tcl_big_global_lock = PTHREAD_MUTEX_INITIALIZER; #define appfs_call_libtcl_enter pthread_mutex_lock(&appfs_tcl_big_global_lock); #define appfs_call_libtcl_exit pthread_mutex_unlock(&appfs_tcl_big_global_lock); #else #warning Using a Threaded Tcl interpreter may cause memory leaks #define appfs_call_libtcl_enter /**/ #define appfs_call_libtcl_exit /**/ #endif #define appfs_call_libtcl(x...) appfs_call_libtcl_enter x appfs_call_libtcl_exit /* * Global variables for AppFS Tcl Interpreter restarting |
︙ | ︙ | |||
377 378 379 380 381 382 383 384 385 386 387 388 389 390 | thread_interp_reset_key = global_interp_reset_key; if (interp == NULL) { interp = appfs_create_TclInterp(NULL); if (interp == NULL) { return(NULL); } pthread_ret = pthread_setspecific(interpKey, interp); if (pthread_ret != 0) { APPFS_DEBUG("pthread_setspecific() failed. Terminating Tcl interpreter."); | > > | 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 | thread_interp_reset_key = global_interp_reset_key; if (interp == NULL) { interp = appfs_create_TclInterp(NULL); if (interp == NULL) { APPFS_DEBUG("Create interp failed, returningin failure."); return(NULL); } pthread_ret = pthread_setspecific(interpKey, interp); if (pthread_ret != 0) { APPFS_DEBUG("pthread_setspecific() failed. Terminating Tcl interpreter."); |
︙ | ︙ | |||
405 406 407 408 409 410 411 412 413 414 415 416 417 418 | Tcl_Obj **objv; const char *arg; va_list argp; int retval; int i; if (interp == NULL) { return(TCL_ERROR); } objv = (void *) ckalloc(sizeof(*objv) * objc); appfs_call_libtcl( objv[0] = Tcl_NewStringObj(cmd, -1); | > > | 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 | Tcl_Obj **objv; const char *arg; va_list argp; int retval; int i; if (interp == NULL) { APPFS_DEBUG("Invalid interpreter passed in, returning in failure."); return(TCL_ERROR); } objv = (void *) ckalloc(sizeof(*objv) * objc); appfs_call_libtcl( objv[0] = Tcl_NewStringObj(cmd, -1); |
︙ | ︙ | |||
474 475 476 477 478 479 480 481 482 483 484 485 486 487 | return(getuid()); } ctx = fuse_get_context(); if (ctx == NULL) { /* Unable to lookup user for some reason */ /* Return an unprivileged user ID */ return(1); } return(ctx->uid); } /* | > > | 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 | return(getuid()); } ctx = fuse_get_context(); if (ctx == NULL) { /* Unable to lookup user for some reason */ /* Return an unprivileged user ID */ APPFS_DEBUG("Unable to lookup user for some reason, returninng user ID of 1"); return(1); } return(ctx->uid); } /* |
︙ | ︙ | |||
496 497 498 499 500 501 502 503 504 505 506 507 508 509 | return(getgid()); } ctx = fuse_get_context(); if (ctx == NULL) { /* Unable to lookup user for some reason */ /* Return an unprivileged user ID */ return(1); } return(ctx->gid); } static void appfs_simulate_user_fs_enter(void) { | > > | 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 | return(getgid()); } ctx = fuse_get_context(); if (ctx == NULL) { /* Unable to lookup user for some reason */ /* Return an unprivileged user ID */ APPFS_DEBUG("Unable to lookup group for some reason, returninng group ID of 1"); return(1); } return(ctx->gid); } static void appfs_simulate_user_fs_enter(void) { |
︙ | ︙ | |||
670 671 672 673 674 675 676 677 678 679 680 681 682 683 | pthread_ret = pthread_mutex_unlock(&appfs_path_info_cache_mutex); if (pthread_ret != 0) { APPFS_DEBUG("Unable to unlock path_info cache mutex !"); return; } return; } static void appfs_get_path_info_cache_rm(const char *path, uid_t uid) { unsigned int hash_idx; int pthread_ret; | > | 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 | pthread_ret = pthread_mutex_unlock(&appfs_path_info_cache_mutex); if (pthread_ret != 0) { APPFS_DEBUG("Unable to unlock path_info cache mutex !"); return; } return; } static void appfs_get_path_info_cache_rm(const char *path, uid_t uid) { unsigned int hash_idx; int pthread_ret; |
︙ | ︙ | |||
773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 | retval = 0; fsuid = appfs_get_fsuid(); cache_ret = appfs_get_path_info_cache_get(path, fsuid, pathinfo); if (cache_ret == 0) { if (pathinfo->type == APPFS_PATHTYPE_DOES_NOT_EXIST) { return(-ENOENT); } if (pathinfo->type == APPFS_PATHTYPE_INVALID) { return(-EIO); } return(0); } interp = appfs_TclInterp(); if (interp == NULL) { return(-EIO); } appfs_call_libtcl(Tcl_Preserve(interp);) tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getattr", path); if (tcl_ret != TCL_OK) { | > > > > > > | 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 | retval = 0; fsuid = appfs_get_fsuid(); cache_ret = appfs_get_path_info_cache_get(path, fsuid, pathinfo); if (cache_ret == 0) { if (pathinfo->type == APPFS_PATHTYPE_DOES_NOT_EXIST) { APPFS_DEBUG("Returning from cache: does not exist \"%s\"", path); return(-ENOENT); } if (pathinfo->type == APPFS_PATHTYPE_INVALID) { APPFS_DEBUG("Returning from cache: invalid object \"%s\"", path); return(-EIO); } return(0); } interp = appfs_TclInterp(); if (interp == NULL) { APPFS_DEBUG("error: Unable to get an interpreter"); return(-EIO); } appfs_call_libtcl(Tcl_Preserve(interp);) tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getattr", path); if (tcl_ret != TCL_OK) { |
︙ | ︙ | |||
842 843 844 845 846 847 848 849 850 851 852 853 854 855 | appfs_call_libtcl(Tcl_Release(interp);) return(-EIO); } if (attr_value == NULL) { appfs_call_libtcl(Tcl_Release(interp);) return(-EIO); } pathinfo->packaged = 0; pathinfo->inode = appfs_get_path_inode(path); | > > | 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 | appfs_call_libtcl(Tcl_Release(interp);) return(-EIO); } if (attr_value == NULL) { APPFS_DEBUG("error: Unable to get type for \"%s\" from Tcl", path); appfs_call_libtcl(Tcl_Release(interp);) return(-EIO); } pathinfo->packaged = 0; pathinfo->inode = appfs_get_path_inode(path); |
︙ | ︙ | |||
935 936 937 938 939 940 941 942 943 944 945 946 947 948 | } Tcl_Release(interp); ) if (retval == 0) { appfs_get_path_info_cache_add(path, fsuid, pathinfo); } return(retval); } static char *appfs_prepare_to_create(const char *path) { Tcl_Interp *interp; | > > | 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 | } Tcl_Release(interp); ) if (retval == 0) { appfs_get_path_info_cache_add(path, fsuid, pathinfo); } else { APPFS_DEBUG("error: Invalid type for \"%s\" from Tcl", path); } return(retval); } static char *appfs_prepare_to_create(const char *path) { Tcl_Interp *interp; |
︙ | ︙ | |||
1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 | } #endif pathinfo.type = APPFS_PATHTYPE_INVALID; retval = appfs_get_path_info(path, &pathinfo); if (retval != 0) { return(retval); } memset(stbuf, 0, sizeof(struct stat)); stbuf->st_mtime = pathinfo.time; stbuf->st_ctime = pathinfo.time; | > > > > > > | 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 | } #endif pathinfo.type = APPFS_PATHTYPE_INVALID; retval = appfs_get_path_info(path, &pathinfo); if (retval != 0) { if (retval == -ENOENT) { APPFS_DEBUG("get_path_info returned ENOENT, returning it as well."); } else { APPFS_DEBUG("error: get_path_info failed"); } return(retval); } memset(stbuf, 0, sizeof(struct stat)); stbuf->st_mtime = pathinfo.time; stbuf->st_ctime = pathinfo.time; |
︙ | ︙ | |||
1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 | int children_count, idx; int tcl_ret; APPFS_DEBUG("Enter (path = %s, ...)", path); interp = appfs_TclInterp(); if (interp == NULL) { return(0); } appfs_call_libtcl(Tcl_Preserve(interp);) filler(buf, ".", NULL, 0); filler(buf, "..", NULL, 0); | > > | 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 | int children_count, idx; int tcl_ret; APPFS_DEBUG("Enter (path = %s, ...)", path); interp = appfs_TclInterp(); if (interp == NULL) { APPFS_DEBUG("error: Unable to get an interpreter"); return(0); } appfs_call_libtcl(Tcl_Preserve(interp);) filler(buf, ".", NULL, 0); filler(buf, "..", NULL, 0); |
︙ | ︙ | |||
1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 | APPFS_DEBUG("Enter (path = %s, ...)", path); gpi_ret = appfs_get_path_info(path, &pathinfo); if ((fi->flags & (O_WRONLY|O_CREAT)) == (O_CREAT|O_WRONLY)) { /* The file will be created if it does not exist */ if (gpi_ret != 0 && gpi_ret != -ENOENT) { return(gpi_ret); } mode = "create"; /* * We have to clear the cache here so that the number of * links gets maintained on the parent directory */ appfs_get_path_info_cache_flush(appfs_get_fsuid(), -1); } else { /* The file must already exist */ if (gpi_ret != 0) { return(gpi_ret); } mode = ""; if ((fi->flags & O_WRONLY) == O_WRONLY) { mode = "write"; } } if (pathinfo.type == APPFS_PATHTYPE_DIRECTORY) { return(-EISDIR); } interp = appfs_TclInterp(); if (interp == NULL) { return(-EIO); } appfs_call_libtcl(Tcl_Preserve(interp);) tcl_ret = appfs_Tcl_Eval(interp, 3, "::appfs::openpath", path, mode); if (tcl_ret != TCL_OK) { | > > > > > > > > | 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 | APPFS_DEBUG("Enter (path = %s, ...)", path); gpi_ret = appfs_get_path_info(path, &pathinfo); if ((fi->flags & (O_WRONLY|O_CREAT)) == (O_CREAT|O_WRONLY)) { /* The file will be created if it does not exist */ if (gpi_ret != 0 && gpi_ret != -ENOENT) { APPFS_DEBUG("error: get_path_info failed"); return(gpi_ret); } mode = "create"; /* * We have to clear the cache here so that the number of * links gets maintained on the parent directory */ appfs_get_path_info_cache_flush(appfs_get_fsuid(), -1); } else { /* The file must already exist */ if (gpi_ret != 0) { APPFS_DEBUG("error: get_path_info failed"); return(gpi_ret); } mode = ""; if ((fi->flags & O_WRONLY) == O_WRONLY) { mode = "write"; } } if (pathinfo.type == APPFS_PATHTYPE_DIRECTORY) { APPFS_DEBUG("error: Asked to open a directory."); return(-EISDIR); } interp = appfs_TclInterp(); if (interp == NULL) { APPFS_DEBUG("error: Unable to get an interpreter"); return(-EIO); } appfs_call_libtcl(Tcl_Preserve(interp);) tcl_ret = appfs_Tcl_Eval(interp, 3, "::appfs::openpath", path, mode); if (tcl_ret != TCL_OK) { |
︙ | ︙ | |||
1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 | appfs_call_libtcl( real_path = Tcl_GetStringResult(interp); ) appfs_call_libtcl(Tcl_Release(interp);) if (real_path == NULL) { return(-EIO); } APPFS_DEBUG("Translated request to open %s to opening %s (mode = \"%s\")", path, real_path, mode); fh = open(real_path, fi->flags, 0600); if (fh < 0) { | > > > > | > > | < > | > | > > | > > > | | | > | > > > > > > > > > > > > > > > | < > > | > > | > > > | | | > | > | > > > > > > > > > > | 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 | appfs_call_libtcl( real_path = Tcl_GetStringResult(interp); ) appfs_call_libtcl(Tcl_Release(interp);) if (real_path == NULL) { APPFS_DEBUG("error: real_path was NULL.") return(-EIO); } APPFS_DEBUG("Translated request to open %s to opening %s (mode = \"%s\")", path, real_path, mode); fh = open(real_path, fi->flags, 0600); if (fh < 0) { APPFS_DEBUG("error: open failed"); return(errno * -1); } fi->fh = fh; return(0); } static int appfs_fuse_close(const char *path, struct fuse_file_info *fi) { int close_ret; appfs_get_path_info_cache_rm(path, appfs_get_fsuid()); close_ret = close(fi->fh); if (close_ret != 0) { APPFS_DEBUG("error: close failed"); return(errno * -1); } return(0); } static int appfs_fuse_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { ssize_t read_ret; int retval; APPFS_DEBUG("Enter (path = %s, buf, %lli, %lli, fd=%lli)", path, (long long) size, (long long) offset, (long long) fi->fh); retval = 0; while (size != 0) { read_ret = pread(fi->fh, buf, size, offset); if (read_ret < 0) { APPFS_DEBUG("error: read failed"); return(errno * -1); } if (read_ret == 0) { break; } size -= read_ret; buf += read_ret; offset += read_ret; retval += read_ret; } if (size != 0) { APPFS_DEBUG("error: incomplete read (this is an error because FUSE will request the exact length of the file)"); return(0); } APPFS_DEBUG("Returning: %i", retval); return(retval); } static int appfs_fuse_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { ssize_t write_ret; int retval; APPFS_DEBUG("Enter (path = %s, ...)", path); appfs_get_path_info_cache_rm(path, appfs_get_fsuid()); retval = 0; while (size != 0) { write_ret = pwrite(fi->fh, buf, size, offset); if (write_ret < 0) { APPFS_DEBUG("error: write failed"); return(errno * -1); } if (write_ret == 0) { break; } size -= write_ret; buf += write_ret; offset += write_ret; retval += write_ret; } if (size != 0) { APPFS_DEBUG("error: incomplete write"); } return(retval); } static int appfs_fuse_mknod(const char *path, mode_t mode, dev_t device) { char *real_path; int mknod_ret; APPFS_DEBUG("Enter (path = %s, ...)", path); |
︙ | ︙ | |||
1764 1765 1766 1767 1768 1769 1770 | return; } /* * Terminate a thread */ | | > > | 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 | return; } /* * Terminate a thread */ static void appfs_terminate_interp_and_thread(void *_interp) { Tcl_Interp *interp; APPFS_DEBUG("Called: _interp = %p", _interp); if (_interp == NULL) { APPFS_DEBUG("Terminating thread with no interpreter"); return; } interp = _interp; APPFS_DEBUG("Terminating interpreter due to thread termination"); appfs_call_libtcl( Tcl_DeleteInterp(interp); ) Tcl_FinalizeThread(); return; } /* * FUSE operations structure */ |
︙ | ︙ | |||
1866 1867 1868 1869 1870 1871 1872 | Tcl_StaticPackage(NULL, "appfsd", Appfsd_Init, NULL); /* * Create a thread-specific-data (TSD) key for each thread to refer * to its own Tcl interpreter. Tcl interpreters must be unique per * thread and new threads are dynamically created by FUSE. */ | | | 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 | Tcl_StaticPackage(NULL, "appfsd", Appfsd_Init, NULL); /* * Create a thread-specific-data (TSD) key for each thread to refer * to its own Tcl interpreter. Tcl interpreters must be unique per * thread and new threads are dynamically created by FUSE. */ pthread_ret = pthread_key_create(&interpKey, appfs_terminate_interp_and_thread); if (pthread_ret != 0) { fprintf(stderr, "Unable to create TSD key for Tcl. Aborting.\n"); return(1); } /* |
︙ | ︙ |