Implemented disconnecting file descriptors: this will be used by the

force unmounting code.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15949 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2006-01-15 17:11:48 +00:00
parent e0ad7cc913
commit 128165101a
2 changed files with 50 additions and 6 deletions
+8 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2005, Axel Dörfler, [email protected].
* Copyright 2002-2006, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef _FD_H
@@ -61,6 +61,8 @@ enum fd_types {
FDTYPE_SOCKET
};
// additional open mode - kernel special
#define O_DISCONNECTED 0x80000000
/* Prototypes */
@@ -70,8 +72,11 @@ extern int new_fd(struct io_context *, struct file_descriptor *);
extern struct file_descriptor *get_fd(struct io_context *, int);
extern void close_fd(struct file_descriptor *descriptor);
extern void put_fd(struct file_descriptor *descriptor);
extern status_t select_fd(int fd, uint8 event, uint32 ref, struct select_sync *sync, bool kernel);
extern status_t deselect_fd(int fd, uint8 event, struct select_sync *sync, bool kernel);
extern void disconnect_fd(struct file_descriptor *descriptor);
extern status_t select_fd(int fd, uint8 event, uint32 ref,
struct select_sync *sync, bool kernel);
extern status_t deselect_fd(int fd, uint8 event, struct select_sync *sync,
bool kernel);
extern bool fd_is_valid(int fd, bool kernel);
extern struct vnode *fd_vnode(struct file_descriptor *descriptor);
+42 -3
View File
@@ -1,6 +1,6 @@
/* Operations on file descriptors
*
* Copyright 2002-2005, Axel Dörfler, [email protected].
* Copyright 2002-2006, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License.
*/
@@ -126,15 +126,36 @@ new_fd(struct io_context *context, struct file_descriptor *descriptor)
void
put_fd(struct file_descriptor *descriptor)
{
TRACE(("put_fd(descriptor = %p [ref = %ld, cookie = %p])\n", descriptor, descriptor->ref_count, descriptor->cookie));
int32 previous = atomic_add(&descriptor->ref_count, -1);
TRACE(("put_fd(descriptor = %p [ref = %ld, cookie = %p])\n",
descriptor, descriptor->ref_count, descriptor->cookie));
// free the descriptor if we don't need it anymore
if (atomic_add(&descriptor->ref_count, -1) == 1) {
if (previous == 1) {
// free the underlying object
if (descriptor->ops->fd_free)
descriptor->ops->fd_free(descriptor);
free(descriptor);
} else if ((descriptor->open_mode & O_DISCONNECTED) != 0
&& previous == descriptor->open_count) {
// the descriptor has been disconnected - it cannot
// be accessed anymore, let's close it (no one is
// currently accessing this descriptor)
if (descriptor->ops->fd_close)
descriptor->ops->fd_close(descriptor);
if (descriptor->ops->fd_free)
descriptor->ops->fd_free(descriptor);
// prevent this descriptor from being closed/freed again
descriptor->open_count = -1;
descriptor->ref_count = -1;
descriptor->u.vnode = NULL;
// the file descriptor is kept intact, so that it's not
// reused until someone explicetly closes it
}
}
@@ -153,6 +174,20 @@ close_fd(struct file_descriptor *descriptor)
}
/** This descriptor's underlying object will be closed and freed
* as soon as possible (in one of the next calls to put_fd() -
* get_fd() will no longer succeed on this descriptor).
* This is useful if the underlying object is gone, for instance
* when a (mounted) volume got removed unexpectedly.
*/
void
disconnect_fd(struct file_descriptor *descriptor)
{
descriptor->open_mode |= O_DISCONNECTED;
}
struct file_descriptor *
get_fd(struct io_context *context, int fd)
{
@@ -166,6 +201,10 @@ get_fd(struct io_context *context, int fd)
if ((uint32)fd < context->table_size)
descriptor = context->fds[fd];
// Disconnected descriptors cannot be accessed anymore
if (descriptor->open_mode & O_DISCONNECTED)
descriptor = NULL;
if (descriptor != NULL) // fd is valid
atomic_add(&descriptor->ref_count, 1);