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:
@@ -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.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef _FD_H
|
#ifndef _FD_H
|
||||||
@@ -61,6 +61,8 @@ enum fd_types {
|
|||||||
FDTYPE_SOCKET
|
FDTYPE_SOCKET
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// additional open mode - kernel special
|
||||||
|
#define O_DISCONNECTED 0x80000000
|
||||||
|
|
||||||
/* Prototypes */
|
/* 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 struct file_descriptor *get_fd(struct io_context *, int);
|
||||||
extern void close_fd(struct file_descriptor *descriptor);
|
extern void close_fd(struct file_descriptor *descriptor);
|
||||||
extern void put_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 void disconnect_fd(struct file_descriptor *descriptor);
|
||||||
extern status_t deselect_fd(int fd, uint8 event, struct select_sync *sync, bool kernel);
|
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 bool fd_is_valid(int fd, bool kernel);
|
||||||
extern struct vnode *fd_vnode(struct file_descriptor *descriptor);
|
extern struct vnode *fd_vnode(struct file_descriptor *descriptor);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Operations on file descriptors
|
/* 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.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -126,15 +126,36 @@ new_fd(struct io_context *context, struct file_descriptor *descriptor)
|
|||||||
void
|
void
|
||||||
put_fd(struct file_descriptor *descriptor)
|
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
|
// 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
|
// free the underlying object
|
||||||
if (descriptor->ops->fd_free)
|
if (descriptor->ops->fd_free)
|
||||||
descriptor->ops->fd_free(descriptor);
|
descriptor->ops->fd_free(descriptor);
|
||||||
|
|
||||||
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 *
|
struct file_descriptor *
|
||||||
get_fd(struct io_context *context, int fd)
|
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)
|
if ((uint32)fd < context->table_size)
|
||||||
descriptor = context->fds[fd];
|
descriptor = context->fds[fd];
|
||||||
|
|
||||||
|
// Disconnected descriptors cannot be accessed anymore
|
||||||
|
if (descriptor->open_mode & O_DISCONNECTED)
|
||||||
|
descriptor = NULL;
|
||||||
|
|
||||||
if (descriptor != NULL) // fd is valid
|
if (descriptor != NULL) // fd is valid
|
||||||
atomic_add(&descriptor->ref_count, 1);
|
atomic_add(&descriptor->ref_count, 1);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user