Problem with deleting directories on NFS in FreeBSD

Problem with deleting directories on NFS in FreeBSD

بذریعہ Marcin K. -
جوابات کی تعداد: 3

Hi,

I've tried to open issue on https://tracker.moodle.org/ but the system does not want to accept it اداس So I've decided to open topic on this forum. Maybe someone will find the problem important.

We have moodle installation on FreeBSD and recently we moved moodledata to NFS. After this we observed a problem with deleting directories from moodle.

I've started a topic on FreeBSD Forums: Problem wiith removing folders on NFS

The conclusion from the discusion is that this is definitely a problem of NFS client in FreeBSD but it can be solved at the Moodle's side. I think safely and system independently.

The essence of the problem is that directory handle changes while the entries are enumarated and deleted one by one. So one of the proposed solutions from the mentioned FreeBSD Forums topic was: list the directory content to the memory first and then delete all entries.

So I changed in moodlelib.php the contents of remove_dir function.

The originally there was:

    if (!$handle = opendir($dir)) {
        return false;
    }
    $result = true;
    while (false!==($item = readdir($handle))) {
        if ($item != '.' && $item != '..') {
            if (is_dir($dir.'/'.$item)) {
                $result = remove_dir($dir.'/'.$item) && $result;
            } else {
                $result = unlink($dir.'/'.$item) && $result;
            }
        }
    }

    closedir($handle);

I changed this to:

    if (!$handle = opendir($dir)) {
        return false;
    }
    $result = true;
    // First list all files in the directory ...
    $dirlist = [];
    while (false!==($item = readdir($handle))) {
        $dirlist[] = $item;
    }
    closedir($handle);
    // ... then delete all elements
    foreach ($dirlist as &$item) {
        if ($item != '.' && $item != '..') {
            if (is_dir($dir.'/'.$item)) {
                $result = remove_dir($dir.'/'.$item) && $result;
            } else {
                $result = unlink($dir.'/'.$item) && $result;
            }
        }
    }
    // Clear variables from memory...
    unset($item);
    unset($dirlist);

And it seems to work properly.

Can this change or similar (I'm not a professional PHP programmer) be included in the main Moodle code?

Regards,
Marcin


درجہ بندی کا اوسط:Useful (1)
Marcin K. کے جواب میں

Re: Problem with deleting directories on NFS in FreeBSD

بذریعہ Tim Hunt -
Core developers کی تصویر Documentation writers کی تصویر Particularly helpful Moodlers کی تصویر Peer reviewers کی تصویر Plugin developers کی تصویر
That second implementation seems more prone to race conditions, if two separate requests try to manipulate the same folder.
Tim Hunt کے جواب میں

Re: Problem with deleting directories on NFS in FreeBSD

بذریعہ Marcin K. -

Earlier in the remove_dir function we have:

    if (!$contentonly) {
        // Start by renaming the directory; this will guarantee that other processes don't write to it
        // while it is in the process of being deleted.
        $tempdir = rename_to_unused_name($dir);
        if ($tempdir) {
            // If the rename was successful then delete the $tempdir instead.
            $dir = $tempdir;
        }
        // If the rename fails, we will continue through and attempt to delete the directory
        // without renaming it since that is likely to at least delete most of the files.
    }

So if my solution is more prone to race conditions - I'm not sure, because some kind of race conditions pushed mi to make mofifications in moodlelib.php - maybe good solution is use my version in directory was renemed succesfully and original version otherwise?