[ccache] patch: workaround for NFS issues
John Coiner
john.coiner at amd.com
Sat Mar 24 21:19:16 GMT 2007
Here is a second attempt at an NFS workaround.
This patch applies to ccache-2.4. The CCACHE_NFS_WORKAROUND variable
enables the workaround. This workaround requires the existence of the
"lockfile" program on the $PATH.
Here's what I think is going on, when NFS corruption occurs:
* Process X writes object A into the cache.
* Process Y starts reading object A.
* Process Z writes a new copy of object A into the cache, renaming
over the original A, while Y is still reading.
A local filesystem will keep the original object A around until Y closes
the file. But on NFS, which is a stateless protocol, the server
immediately forgets that the original A ever existed. When process Y
comes back requesting the next chunk of the original A, it is gone.
This patch prevents overwriting an object that's already in the cache.
It seems to work, YMMV.
- John
diff -u ccache-2.4/ccache.c ccache-2.4-fix/ccache.c
--- ccache-2.4/ccache.c Mon Sep 13 06:38:30 2004
+++ ccache-2.4-fix/ccache.c Sat Mar 24 15:43:45 2007
@@ -158,6 +158,30 @@
struct stat st1, st2;
int status;
+ char *workaround = getenv("CCACHE_NFS_WORKAROUND");
+ char *lockfile, *lock_cmd;
+ struct stat st;
+
+ if( workaround )
+ {
+ /* acquire lock -- permission to create the cache entry. */
+ x_asprintf( &lockfile, "%s.lock", hashname );
+ x_asprintf( &lock_cmd, "lockfile -l 600 %s", lockfile );
+ if( 0 != system( lock_cmd ) )
+ {
+ cc_log( "failed to get lockfile %s\n", lockfile );
+ failed();
+ }
+
+ /* got lock -- is the file there now? */
+ if( stat( hashname, &st ) == 0 )
+ {
+ /* another ccache process built it. Just return. */
+ unlink( lockfile );
+ return;
+ }
+ }
+
x_asprintf(&tmp_stdout, "%s/tmp.stdout.%s", temp_dir, tmp_string());
x_asprintf(&tmp_stderr, "%s/tmp.stderr.%s", temp_dir, tmp_string());
x_asprintf(&tmp_hashname, "%s/tmp.hash.%s.o", temp_dir, tmp_string());
@@ -187,6 +211,8 @@
unlink(tmp_stdout);
unlink(tmp_stderr);
unlink(tmp_hashname);
+ if( workaround )
+ unlink(lockfile);
failed();
}
unlink(tmp_stdout);
@@ -196,6 +222,9 @@
cc_log("compile of %s gave status = %d\n", output_file, status);
stats_update(STATS_STATUS);
+ if( workaround )
+ unlink( lockfile );
+
fd = open(tmp_stderr, O_RDONLY | O_BINARY);
if (fd != -1) {
if (strcmp(output_file, "/dev/null") == 0 ||
@@ -236,11 +265,20 @@
rename(tmp_stderr, path_stderr) != 0) {
cc_log("failed to rename tmp files - %s\n", strerror(errno));
stats_update(STATS_ERROR);
+ if( workaround )
+ unlink( lockfile );
failed();
}
cc_log("Placed %s into cache\n", output_file);
stats_tocache(file_size(&st1) + file_size(&st2));
+
+ if( workaround )
+ {
+ unlink( lockfile );
+ free( lockfile );
+ free( lock_cmd );
+ }
free(tmp_hashname);
free(tmp_stderr);
More information about the ccache
mailing list