* Fixed two possible crashing bugs in the file system check code: the checker
was attached to the inode instead of the file descriptor, causing it to call BlockAllocator::StopChecking() whenever anyone closed the device's root node during the check. The other bug was that it tried to fix errors even if the device was read-only. * Added TODO that ioctl() accesses userland buffers unsafely. * Removed no longer valid or superfluous comments. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28869 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1189,6 +1189,11 @@ BlockAllocator::StopChecking(check_control* control)
|
|||||||
put_vnode(fVolume->FSVolume(), fVolume->ToVnode(cookie->current));
|
put_vnode(fVolume->FSVolume(), fVolume->ToVnode(cookie->current));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fVolume->IsReadOnly()) {
|
||||||
|
// We can't fix errors on this volume
|
||||||
|
control->flags &= ~BFS_FIX_BITMAP_ERRORS;
|
||||||
|
}
|
||||||
|
|
||||||
// if CheckNextNode() could completely work through, we can
|
// if CheckNextNode() could completely work through, we can
|
||||||
// fix any damages of the bitmap
|
// fix any damages of the bitmap
|
||||||
if (control != NULL && control->status == B_ENTRY_NOT_FOUND) {
|
if (control != NULL && control->status == B_ENTRY_NOT_FOUND) {
|
||||||
|
|||||||
@@ -223,8 +223,7 @@ enum inode_flags {
|
|||||||
|
|
||||||
INODE_WAS_WRITTEN = 0x00020000,
|
INODE_WAS_WRITTEN = 0x00020000,
|
||||||
// The rest is only used by the file system check functionality
|
// The rest is only used by the file system check functionality
|
||||||
INODE_DONT_FREE_SPACE = 0x00080000,
|
INODE_DONT_FREE_SPACE = 0x00080000
|
||||||
INODE_CHECK_RUNNING = 0x00200000
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//**************************************
|
//**************************************
|
||||||
@@ -235,6 +234,9 @@ struct file_cookie {
|
|||||||
int open_mode;
|
int open_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define BFS_OPEN_MODE_USER_MASK 0x7fffffff
|
||||||
|
#define BFS_OPEN_MODE_CHECKING 0x80000000
|
||||||
|
|
||||||
// notify every second if the file size has changed
|
// notify every second if the file size has changed
|
||||||
#define INODE_NOTIFICATION_INTERVAL 1000000LL
|
#define INODE_NOTIFICATION_INTERVAL 1000000LL
|
||||||
|
|
||||||
|
|||||||
@@ -584,7 +584,8 @@ bfs_ioctl(fs_volume* _volume, fs_vnode* _node, void* _cookie, ulong cmd,
|
|||||||
buffer, bufferLength));
|
buffer, bufferLength));
|
||||||
|
|
||||||
Volume* volume = (Volume*)_volume->private_volume;
|
Volume* volume = (Volume*)_volume->private_volume;
|
||||||
Inode* inode = (Inode*)_node->private_node;
|
|
||||||
|
// TODO: Access user buffers safely!
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case BFS_IOCTL_VERSION:
|
case BFS_IOCTL_VERSION:
|
||||||
@@ -602,8 +603,8 @@ bfs_ioctl(fs_volume* _volume, fs_vnode* _node, void* _cookie, ulong cmd,
|
|||||||
|
|
||||||
status_t status = allocator.StartChecking(control);
|
status_t status = allocator.StartChecking(control);
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
inode->Node().flags
|
file_cookie* cookie = (file_cookie*)_cookie;
|
||||||
|= HOST_ENDIAN_TO_BFS_INT32(INODE_CHECK_RUNNING);
|
cookie->open_mode |= BFS_OPEN_MODE_CHECKING;
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@@ -616,8 +617,8 @@ bfs_ioctl(fs_volume* _volume, fs_vnode* _node, void* _cookie, ulong cmd,
|
|||||||
|
|
||||||
status_t status = allocator.StopChecking(control);
|
status_t status = allocator.StopChecking(control);
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
inode->Node().flags
|
file_cookie* cookie = (file_cookie*)_cookie;
|
||||||
&= HOST_ENDIAN_TO_BFS_INT32(~INODE_CHECK_RUNNING);
|
cookie->open_mode &= ~BFS_OPEN_MODE_CHECKING;
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@@ -1164,7 +1165,7 @@ bfs_open(fs_volume* _volume, fs_vnode* _node, int openMode, void** _cookie)
|
|||||||
|
|
||||||
// opening a directory read-only is allowed, although you can't read
|
// opening a directory read-only is allowed, although you can't read
|
||||||
// any data from it.
|
// any data from it.
|
||||||
if (inode->IsDirectory() && openMode & O_RWMASK) {
|
if (inode->IsDirectory() && (openMode & O_RWMASK) != 0) {
|
||||||
openMode = openMode & ~O_RWMASK;
|
openMode = openMode & ~O_RWMASK;
|
||||||
// TODO: for compatibility reasons, we don't return an error here...
|
// TODO: for compatibility reasons, we don't return an error here...
|
||||||
// e.g. "copyattr" tries to do that
|
// e.g. "copyattr" tries to do that
|
||||||
@@ -1176,22 +1177,13 @@ bfs_open(fs_volume* _volume, fs_vnode* _node, int openMode, void** _cookie)
|
|||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
RETURN_ERROR(status);
|
RETURN_ERROR(status);
|
||||||
|
|
||||||
// We could actually use the cookie to keep track of:
|
|
||||||
// - the last block_run
|
|
||||||
// - the location in the data_stream (indirect, double indirect,
|
|
||||||
// position in block_run array)
|
|
||||||
//
|
|
||||||
// This could greatly speed up continuous reads of big files, especially
|
|
||||||
// in the indirect block section.
|
|
||||||
|
|
||||||
file_cookie* cookie = new(std::nothrow) file_cookie;
|
file_cookie* cookie = new(std::nothrow) file_cookie;
|
||||||
if (cookie == NULL)
|
if (cookie == NULL)
|
||||||
RETURN_ERROR(B_NO_MEMORY);
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
ObjectDeleter<file_cookie> cookieDeleter(cookie);
|
ObjectDeleter<file_cookie> cookieDeleter(cookie);
|
||||||
|
|
||||||
// initialize the cookie
|
// initialize the cookie
|
||||||
cookie->open_mode = openMode;
|
cookie->open_mode = openMode & BFS_OPEN_MODE_USER_MASK;
|
||||||
// needed by e.g. bfs_write() for O_APPEND
|
|
||||||
cookie->last_size = inode->Size();
|
cookie->last_size = inode->Size();
|
||||||
cookie->last_notification = system_time();
|
cookie->last_notification = system_time();
|
||||||
|
|
||||||
@@ -1381,7 +1373,7 @@ bfs_free_cookie(fs_volume* _volume, fs_vnode* _node, void* _cookie)
|
|||||||
if (status == B_OK)
|
if (status == B_OK)
|
||||||
transaction.Done();
|
transaction.Done();
|
||||||
|
|
||||||
if ((inode->Flags() & INODE_CHECK_RUNNING) != 0) {
|
if ((cookie->open_mode & BFS_OPEN_MODE_CHECKING) != 0) {
|
||||||
// "chkbfs" exited abnormally, so we have to stop it here...
|
// "chkbfs" exited abnormally, so we have to stop it here...
|
||||||
FATAL(("check process was aborted!\n"));
|
FATAL(("check process was aborted!\n"));
|
||||||
volume->Allocator().StopChecking(NULL);
|
volume->Allocator().StopChecking(NULL);
|
||||||
|
|||||||
Reference in New Issue
Block a user