Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 7f59d6c in mainline


Ignore:
Timestamp:
2017-03-18T13:08:17Z (3 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
master
Children:
4f9ab1e
Parents:
39c3b7f9
Message:

Revert the order of link and unlink operations during rename

This changeset reverts the order of link and unlink operations that
occur within a single rename operation to be link first and unlink
second.

The file system implementations are not ready for the opposite ordering.

For example ext4fs decrements the the link count by 2 in total when
removing the last non-dot name of a directory, but increments only by 1
when adding the new name. This results in an assertion failure on the
next unlink, because the linkcount gets out of ballance.

In addition, this changeset fixes a node reference leak in error paths.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/vfs/vfs_ops.c

    r39c3b7f9 r7f59d6c  
    552552        /* Do not allow one path to be a prefix of the other. */
    553553        if (old[shared] == 0 || new[shared] == 0) {
     554                vfs_node_put(base);
    554555                return EINVAL;
    555556        }
     
    564565                rc = vfs_lookup_internal(base, old, L_DIRECTORY, &base_lr);
    565566                if (rc != EOK) {
     567                        vfs_node_put(base);
    566568                        fibril_rwlock_write_unlock(&namespace_rwlock);
    567569                        return rc;
     
    573575                old += shared;
    574576                new += shared;
     577        }
     578
     579        rc = vfs_lookup_internal(base, old, L_DISABLE_MOUNTS,
     580            &old_lr);
     581        if (rc != EOK) {
     582                vfs_node_put(base);
     583                fibril_rwlock_write_unlock(&namespace_rwlock);
     584                return rc;
    575585        }
    576586               
     
    584594                return rc;
    585595        }
    586        
     596
     597        rc = vfs_link_internal(base, new, &old_lr.triplet);
     598        if (rc != EOK) {
     599                vfs_link_internal(base, old, &old_lr.triplet);
     600                if (orig_unlinked) {
     601                        vfs_link_internal(base, new, &new_lr_orig.triplet);
     602                }
     603                vfs_node_put(base);
     604                fibril_rwlock_write_unlock(&namespace_rwlock);
     605                return rc;
     606        }
     607
    587608        rc = vfs_lookup_internal(base, old, L_UNLINK | L_DISABLE_MOUNTS,
    588609            &old_lr);
    589610        if (rc != EOK) {
    590                 if (orig_unlinked) {
    591                         vfs_link_internal(base, new, &new_lr_orig.triplet);
    592                 }
    593                 vfs_node_put(base);
    594                 fibril_rwlock_write_unlock(&namespace_rwlock);
    595                 return rc;
    596         }
    597        
    598         rc = vfs_link_internal(base, new, &old_lr.triplet);
    599         if (rc != EOK) {
    600                 vfs_link_internal(base, old, &old_lr.triplet);
    601611                if (orig_unlinked) {
    602612                        vfs_link_internal(base, new, &new_lr_orig.triplet);
Note: See TracChangeset for help on using the changeset viewer.