mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
fs: fix locking in rename for fatfs and ext2
This commit is contained in:
@@ -1833,30 +1833,34 @@ static int ext2_rename(vnode_t *sourcedir, vnode_t *source, char *oldname, vnode
|
|||||||
if (replaced_vnode) {
|
if (replaced_vnode) {
|
||||||
// we are replacing an existing link
|
// we are replacing an existing link
|
||||||
// do some checks expected by posix
|
// do some checks expected by posix
|
||||||
// TODO add these to fatfs and tmpfs
|
|
||||||
if (source->type != V_TYPE_DIR && replaced_vnode->type == V_TYPE_DIR) {
|
if (source->type != V_TYPE_DIR && replaced_vnode->type == V_TYPE_DIR) {
|
||||||
|
VOP_UNLOCK(replaced_vnode);
|
||||||
VOP_RELEASE(replaced_vnode);
|
VOP_RELEASE(replaced_vnode);
|
||||||
return EISDIR;
|
return EISDIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source->type == V_TYPE_DIR && replaced_vnode->type != V_TYPE_DIR) {
|
if (source->type == V_TYPE_DIR && replaced_vnode->type != V_TYPE_DIR) {
|
||||||
|
VOP_UNLOCK(replaced_vnode);
|
||||||
VOP_RELEASE(replaced_vnode);
|
VOP_RELEASE(replaced_vnode);
|
||||||
return ENOTDIR;
|
return ENOTDIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (replaced_vnode->vfsmounted) {
|
if (replaced_vnode->vfsmounted) {
|
||||||
|
VOP_UNLOCK(replaced_vnode);
|
||||||
VOP_RELEASE(replaced_vnode);
|
VOP_RELEASE(replaced_vnode);
|
||||||
return EBUSY;
|
return EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = replaced_vnode->type == V_TYPE_DIR ? is_directory_empty(ext2_replaced_node) : 0;
|
err = replaced_vnode->type == V_TYPE_DIR ? is_directory_empty(ext2_replaced_node) : 0;
|
||||||
if (err) {
|
if (err) {
|
||||||
|
VOP_UNLOCK(replaced_vnode);
|
||||||
VOP_RELEASE(replaced_vnode);
|
VOP_RELEASE(replaced_vnode);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source == replaced_vnode) {
|
if (source == replaced_vnode) {
|
||||||
// POSIX says that if both are the same file, rename is a no-op
|
// POSIX says that if both are the same file, rename is a no-op
|
||||||
|
VOP_UNLOCK(replaced_vnode);
|
||||||
VOP_RELEASE(replaced_vnode);
|
VOP_RELEASE(replaced_vnode);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1873,9 +1877,11 @@ static int ext2_rename(vnode_t *sourcedir, vnode_t *source, char *oldname, vnode
|
|||||||
err = handleinodeunlink(fs, ext2targetdirnode, oldinode, ext2_replaced_node);
|
err = handleinodeunlink(fs, ext2targetdirnode, oldinode, ext2_replaced_node);
|
||||||
ext2sourcenode->inode.links += 1;
|
ext2sourcenode->inode.links += 1;
|
||||||
ASSERT_UNCLEAN(fs, writeinode(fs, &ext2sourcenode->inode, ext2sourcenode->id) == 0);
|
ASSERT_UNCLEAN(fs, writeinode(fs, &ext2sourcenode->inode, ext2sourcenode->id) == 0);
|
||||||
|
VOP_UNLOCK(replaced_vnode);
|
||||||
VOP_RELEASE(replaced_vnode);
|
VOP_RELEASE(replaced_vnode);
|
||||||
} else if (err) {
|
} else if (err) {
|
||||||
if (replaced_vnode) {
|
if (replaced_vnode) {
|
||||||
|
VOP_UNLOCK(replaced_vnode);
|
||||||
VOP_RELEASE(replaced_vnode);
|
VOP_RELEASE(replaced_vnode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -731,28 +731,33 @@ static int fatfs_rename(vnode_t *vsource_dir, vnode_t *vsource, char *old_name,
|
|||||||
// we are replacing an existing link
|
// we are replacing an existing link
|
||||||
// do some checks expected by posix
|
// do some checks expected by posix
|
||||||
if (vsource->type != V_TYPE_DIR && vtarget->type == V_TYPE_DIR) {
|
if (vsource->type != V_TYPE_DIR && vtarget->type == V_TYPE_DIR) {
|
||||||
|
VOP_UNLOCK(vtarget);
|
||||||
VOP_RELEASE(vtarget);
|
VOP_RELEASE(vtarget);
|
||||||
return EISDIR;
|
return EISDIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vsource->type == V_TYPE_DIR && vtarget->type != V_TYPE_DIR) {
|
if (vsource->type == V_TYPE_DIR && vtarget->type != V_TYPE_DIR) {
|
||||||
|
VOP_UNLOCK(vtarget);
|
||||||
VOP_RELEASE(vtarget);
|
VOP_RELEASE(vtarget);
|
||||||
return ENOTDIR;
|
return ENOTDIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vtarget->vfsmounted) {
|
if (vtarget->vfsmounted) {
|
||||||
|
VOP_UNLOCK(vtarget);
|
||||||
VOP_RELEASE(vtarget);
|
VOP_RELEASE(vtarget);
|
||||||
return EBUSY;
|
return EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = vtarget->type == V_TYPE_DIR ? is_directory_empty(target) : 0;
|
error = vtarget->type == V_TYPE_DIR ? is_directory_empty(target) : 0;
|
||||||
if (error) {
|
if (error) {
|
||||||
|
VOP_UNLOCK(vtarget);
|
||||||
VOP_RELEASE(vtarget);
|
VOP_RELEASE(vtarget);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source == target) {
|
if (source == target) {
|
||||||
// POSIX says that if both are the same file, rename is a no-op
|
// POSIX says that if both are the same file, rename is a no-op
|
||||||
|
VOP_UNLOCK(vtarget);
|
||||||
VOP_RELEASE(vtarget);
|
VOP_RELEASE(vtarget);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -782,6 +787,7 @@ static int fatfs_rename(vnode_t *vsource_dir, vnode_t *vsource, char *old_name,
|
|||||||
size_t written;
|
size_t written;
|
||||||
error = vfs_write(fatfs->backing, &new_dent, sizeof(new_dent), dent_disk_offset, &written, 0);
|
error = vfs_write(fatfs->backing, &new_dent, sizeof(new_dent), dent_disk_offset, &written, 0);
|
||||||
if (error) {
|
if (error) {
|
||||||
|
VOP_UNLOCK(vtarget);
|
||||||
VOP_RELEASE(vtarget);
|
VOP_RELEASE(vtarget);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@@ -796,13 +802,17 @@ static int fatfs_rename(vnode_t *vsource_dir, vnode_t *vsource, char *old_name,
|
|||||||
VOP_RELEASE(vtarget); // table hold
|
VOP_RELEASE(vtarget); // table hold
|
||||||
|
|
||||||
__assert(target->parent_dir == target_dir);
|
__assert(target->parent_dir == target_dir);
|
||||||
VOP_RELEASE(vtarget_dir)
|
VOP_RELEASE(vtarget_dir);
|
||||||
target->parent_dir = NULL;
|
target->parent_dir = NULL;
|
||||||
target->dent_disk_offset = 0;
|
target->dent_disk_offset = 0;
|
||||||
|
|
||||||
|
VOP_UNLOCK(vtarget);
|
||||||
VOP_RELEASE(vtarget); // lookup hold
|
VOP_RELEASE(vtarget); // lookup hold
|
||||||
} else {
|
} else {
|
||||||
VOP_RELEASE(vtarget);
|
if (vtarget) {
|
||||||
|
VOP_UNLOCK(vtarget);
|
||||||
|
VOP_RELEASE(vtarget);
|
||||||
|
}
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user