Skip to content

Instantly share code, notes, and snippets.

@pdrakeweb
Last active August 29, 2015 14:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pdrakeweb/ae046b4c70a42309be43 to your computer and use it in GitHub Desktop.
Save pdrakeweb/ae046b4c70a42309be43 to your computer and use it in GitHub Desktop.
Gluster 3.4.1 directory permissions bug
#!/usr/bin/env php
<?php
/**
* Usage:
*
* Execute this script simultaneously on two separate gluster clients and you
* will see errors. Set the $gluster_path variables below as needed for your
* environment. You may set $gluster_path to a non-gluster local path and then
* execute two copies of this on the same machine to prove that the problem does
* not occur with local filesystems.
*/
// Set these values for your environment.
$uid = 9999;
$username = 'testuser';
$gid = 9999;
$groupname = 'testgroup';
$gluster_path = '/mnt/gfs';
$wait_for_gluster = 20;
// Set up the target directory if it doesn't exist.
if (!is_dir("$gluster_path/test-target")) { mkdir("$gluster_path/test-target"); }
// Sync the system time, since we want to execute our actions as closely aligned
// as possible.
$sync_results = exec('ntpdate -u time-c.nist.gov');
echo "Synced system time: $sync_results\n";
// Set up users
exec("groupadd -g $gid $groupname");
exec("useradd -u $uid -g $gid $username");
// Run the directory creation test.
$success = test_dircreate(300, $uid, $gid, FALSE, "$gluster_path/test-target", $wait_for_gluster);
exit($success);
/**
* Once each 1/10 second, on 1/10 second, create a directory.
*
* @param int $n
* The number of iterations to perform.
* @param int $uid
* The number of iterations to perform.
* @param int $gid
* The number of iterations to perform.
* @param bool $clearstatcache
* Whether we should clear the stat cache.
* @param string $gluster_path
* Path to a gluster mount or directory on a gluster mount.
*/
function test_dircreate($n, $uid, $gid, $clearstatcache, $test_root_path, $wait_for_gluster) {
$old_testpath = NULL;
$i = 0;
$final_count = 0;
$reported_count = 0;
while($i < $n) {
// Set up our file path.
$testpath = "$test_root_path/test" . round(microtime(TRUE), 1);
// Only run if the time has changed and we're at the start of a new 1/10 second.
if ($testpath != $old_testpath) {
$old_testpath = $testpath;
$i++;
// If the symlink on gluster doesn't exist, attempt to create it.
if ($clearstatcache) { clearstatcache(); }
if (!is_dir($testpath)) {
@mkdir($testpath, 0550);
chown($testpath, $uid);
chgrp($testpath, $gid);
if (fileowner($testpath) != $uid || filegroup($testpath) != $gid) {
echo "Failed to create properly permissioned dir: $testpath.\n";
$reported_count++;
continue;
}
else {
echo "Create properly permissioned dir: $testpath.\n";
}
}
}
}
// Wait for gluster to finish doing stuff, in case it is planning to be
// eventually consistent.
sleep($wait_for_gluster);
foreach(glob("$test_root_path/*") as $testpath) {
if (fileowner($testpath) != $uid || filegroup($testpath) != $gid) {
echo "Actually failed to create properly permissioned dir: $testpath.\n";
$final_count++;
continue;
}
}
// Output the results.
echo "\n\nClear Stat Cache: " . ($clearstatcache ? "TRUE" : "FALSE") . "\nAttempts: $i\nReported Inconsistencies: $reported_count\nFinal Inconsistencies: $final_count\n\n";
return ($final_count == 0) ? 0 : 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment