server: Store the opening options in the file descriptor instead of in the individual objects.

Allows moving the FD_FLAG_OVERLAPPED support to the generic
get_handle_fd request handling.
This commit is contained in:
Alexandre Julliard 2007-04-10 22:25:07 +02:00
parent 83cef86f29
commit f85437c57f
13 changed files with 61 additions and 93 deletions

View File

@ -793,7 +793,7 @@ static inline struct fd *create_inotify_fd( void )
unix_fd = inotify_init();
if (unix_fd<0)
return NULL;
return create_anonymous_fd( &inotify_fd_ops, unix_fd, NULL );
return create_anonymous_fd( &inotify_fd_ops, unix_fd, NULL, 0 );
}
static int map_flags( unsigned int filter )

View File

@ -166,6 +166,7 @@ struct fd
struct object *user; /* object using this file descriptor */
struct list locks; /* list of locks on this fd */
unsigned int access; /* file access (FILE_READ_DATA etc.) */
unsigned int options; /* file options (FILE_DELETE_ON_CLOSE, FILE_SYNCHRONOUS...) */
unsigned int sharing; /* file sharing mode */
int unix_fd; /* unix file descriptor */
int signaled :1; /* is the fd signaled? */
@ -1278,7 +1279,7 @@ void unlock_fd( struct fd *fd, file_pos_t start, file_pos_t count )
static void fd_dump( struct object *obj, int verbose )
{
struct fd *fd = (struct fd *)obj;
fprintf( stderr, "Fd unix_fd=%d user=%p", fd->unix_fd, fd->user );
fprintf( stderr, "Fd unix_fd=%d user=%p options=%08x", fd->unix_fd, fd->user, fd->options );
if (fd->inode) fprintf( stderr, " inode=%p unlink='%s'", fd->inode, fd->closed->unlink );
fprintf( stderr, "\n" );
}
@ -1359,6 +1360,7 @@ static struct fd *alloc_fd_object(void)
fd->inode = NULL;
fd->closed = NULL;
fd->access = 0;
fd->options = 0;
fd->sharing = 0;
fd->unix_fd = -1;
fd->signaled = 1;
@ -1463,6 +1465,7 @@ struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int acce
if (!(fd = alloc_fd_object())) return NULL;
fd->options = options;
if (options & FILE_DELETE_ON_CLOSE) unlink_name = name;
if (!(closed_fd = mem_alloc( sizeof(*closed_fd) + strlen(unlink_name) )))
{
@ -1570,7 +1573,8 @@ error:
/* create an fd for an anonymous file */
/* if the function fails the unix fd is closed */
struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops, int unix_fd, struct object *user )
struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops, int unix_fd, struct object *user,
unsigned int options )
{
struct fd *fd = alloc_fd_object();
@ -1578,6 +1582,7 @@ struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops, int unix_fd, s
{
set_fd_user( fd, fd_user_ops, user );
fd->unix_fd = unix_fd;
fd->options = options;
return fd;
}
close( unix_fd );
@ -1590,6 +1595,12 @@ void *get_fd_user( struct fd *fd )
return fd->user;
}
/* retrieve the opening options for the fd */
unsigned int get_fd_options( struct fd *fd )
{
return fd->options;
}
/* retrieve the unix fd for an object */
int get_unix_fd( struct fd *fd )
{
@ -1733,15 +1744,8 @@ void fd_reselect_async( struct fd *fd, struct async_queue *queue )
void default_fd_queue_async( struct fd *fd, const async_data_t *data, int type, int count )
{
int flags;
struct async *async;
fd->fd_ops->get_file_info( fd, &flags );
if (!(flags & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT)))
{
set_error( STATUS_INVALID_HANDLE );
return;
}
if ((async = fd_queue_async( fd, data, type, count )))
{
release_object( async );
@ -1907,6 +1911,8 @@ DECL_HANDLER(get_handle_fd)
reply->type = fd->fd_ops->get_file_info( fd, &reply->flags );
if (reply->type != FD_TYPE_INVALID)
{
if (!(fd->options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
reply->flags |= FD_FLAG_OVERLAPPED;
if (is_fd_removable(fd)) reply->flags |= FD_FLAG_REMOVABLE;
if (!req->cached)
{

View File

@ -58,7 +58,6 @@ struct file
struct object obj; /* object header */
struct fd *fd; /* file descriptor for this file */
unsigned int access; /* file access (FILE_READ_DATA etc.) */
unsigned int options; /* file options (FILE_DELETE_ON_CLOSE, FILE_SYNCHRONOUS...) */
};
static unsigned int generic_file_map_access( unsigned int access );
@ -102,7 +101,7 @@ static const struct fd_ops file_fd_ops =
static inline int is_overlapped( const struct file *file )
{
return !(file->options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT));
return !(get_fd_options( file->fd ) & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT));
}
/* create a file from a file descriptor */
@ -114,8 +113,8 @@ static struct file *create_file_for_fd( int fd, unsigned int access, unsigned in
if ((file = alloc_object( &file_ops )))
{
file->access = file_map_access( &file->obj, access );
file->options = FILE_SYNCHRONOUS_IO_NONALERT;
if (!(file->fd = create_anonymous_fd( &file_fd_ops, fd, &file->obj )))
if (!(file->fd = create_anonymous_fd( &file_fd_ops, fd, &file->obj,
FILE_SYNCHRONOUS_IO_NONALERT )))
{
release_object( file );
return NULL;
@ -124,13 +123,12 @@ static struct file *create_file_for_fd( int fd, unsigned int access, unsigned in
return file;
}
static struct object *create_file_obj( struct fd *fd, unsigned int access, unsigned int options )
static struct object *create_file_obj( struct fd *fd, unsigned int access )
{
struct file *file = alloc_object( &file_ops );
if (!file) return NULL;
file->access = access;
file->options = options;
file->fd = fd;
grab_object( fd );
set_fd_user( fd, &file_fd_ops, &file->obj );
@ -177,9 +175,9 @@ static struct object *create_file( const char *nameptr, data_size_t len, unsigne
if (S_ISDIR(mode))
obj = create_dir_obj( fd );
else if (S_ISCHR(mode) && is_serial_fd( fd ))
obj = create_serial( fd, options );
obj = create_serial( fd );
else
obj = create_file_obj( fd, access, options );
obj = create_file_obj( fd, access );
release_object( fd );
@ -215,7 +213,7 @@ static void file_dump( struct object *obj, int verbose )
{
struct file *file = (struct file *)obj;
assert( obj->ops == &file_ops );
fprintf( stderr, "File fd=%p options=%08x\n", file->fd, file->options );
fprintf( stderr, "File fd=%p\n", file->fd );
}
static int file_get_poll_events( struct fd *fd )
@ -236,10 +234,7 @@ static void file_flush( struct fd *fd, struct event **event )
static enum server_fd_type file_get_info( struct fd *fd, int *flags )
{
struct file *file = get_fd_user( fd );
*flags = 0;
if (is_overlapped( file )) *flags |= FD_FLAG_OVERLAPPED;
return FD_TYPE_FILE;
}

View File

@ -53,9 +53,10 @@ extern struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct obje
extern struct fd *open_fd( const char *name, int flags, mode_t *mode, unsigned int access,
unsigned int sharing, unsigned int options );
extern struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops,
int unix_fd, struct object *user );
int unix_fd, struct object *user, unsigned int options );
extern void *get_fd_user( struct fd *fd );
extern void set_fd_user( struct fd *fd, const struct fd_ops *ops, struct object *user );
extern unsigned int get_fd_options( struct fd *fd );
extern int get_unix_fd( struct fd *fd );
extern int is_same_file_fd( struct fd *fd1, struct fd *fd2 );
extern int is_fd_removable( struct fd *fd );
@ -123,7 +124,7 @@ extern struct object *create_dir_obj( struct fd *fd );
/* serial port functions */
extern int is_serial_fd( struct fd *fd );
extern struct object *create_serial( struct fd *fd, unsigned int options );
extern struct object *create_serial( struct fd *fd );
/* async I/O functions */
extern struct async_queue *create_async_queue( struct fd *fd );

View File

@ -215,7 +215,7 @@ static enum server_fd_type mailslot_get_info( struct fd *fd, int *flags )
{
struct mailslot *mailslot = get_fd_user( fd );
assert( mailslot->obj.ops == &mailslot_ops );
*flags = FD_FLAG_TIMEOUT | FD_FLAG_AVAILABLE;
*flags = 0;
return FD_TYPE_MAILSLOT;
}
@ -410,10 +410,10 @@ static struct mailslot *create_mailslot( struct directory *root,
fcntl( fds[0], F_SETFL, O_NONBLOCK );
fcntl( fds[1], F_SETFL, O_NONBLOCK );
shutdown( fds[0], SHUT_RD );
mailslot->fd = create_anonymous_fd( &mailslot_fd_ops,
fds[1], &mailslot->obj );
mailslot->write_fd = create_anonymous_fd( &mail_writer_fd_ops,
fds[0], &mailslot->obj );
mailslot->fd = create_anonymous_fd( &mailslot_fd_ops, fds[1], &mailslot->obj,
FILE_SYNCHRONOUS_IO_NONALERT );
mailslot->write_fd = create_anonymous_fd( &mail_writer_fd_ops, fds[0], &mailslot->obj,
FILE_SYNCHRONOUS_IO_NONALERT );
if (mailslot->fd && mailslot->write_fd) return mailslot;
}
else file_set_error();

View File

@ -557,19 +557,13 @@ static inline int is_overlapped( unsigned int options )
static enum server_fd_type pipe_server_get_info( struct fd *fd, int *flags )
{
struct pipe_server *server = get_fd_user( fd );
*flags = FD_FLAG_AVAILABLE;
if (is_overlapped( server->options )) *flags |= FD_FLAG_OVERLAPPED;
*flags = 0;
return FD_TYPE_PIPE;
}
static enum server_fd_type pipe_client_get_info( struct fd *fd, int *flags )
{
struct pipe_client *client = get_fd_user( fd );
*flags = FD_FLAG_AVAILABLE;
if (is_overlapped( client->flags )) *flags |= FD_FLAG_OVERLAPPED;
*flags = 0;
return FD_TYPE_PIPE;
}
@ -715,10 +709,8 @@ static struct object *named_pipe_open_file( struct object *obj, unsigned int acc
setsockopt( fds[1], SOL_SOCKET, SO_SNDBUF, &pipe->outsize, sizeof(pipe->outsize) );
}
client->fd = create_anonymous_fd( &pipe_client_fd_ops,
fds[1], &client->obj );
server->fd = create_anonymous_fd( &pipe_server_fd_ops,
fds[0], &server->obj );
client->fd = create_anonymous_fd( &pipe_client_fd_ops, fds[1], &client->obj, options );
server->fd = create_anonymous_fd( &pipe_server_fd_ops, fds[0], &server->obj, server->options );
if (client->fd && server->fd && res != 1)
{
if (server->state == ps_wait_open)

View File

@ -302,7 +302,7 @@ struct thread *create_process( int fd, struct thread *parent_thread, int inherit
close( fd );
goto error;
}
if (!(process->msg_fd = create_anonymous_fd( &process_fd_ops, fd, &process->obj ))) goto error;
if (!(process->msg_fd = create_anonymous_fd( &process_fd_ops, fd, &process->obj, 0 ))) goto error;
/* create the handle table */
if (!parent_thread) process->handles = alloc_handle_table( process, 0 );

View File

@ -1580,7 +1580,7 @@ DECL_HANDLER(set_queue_fd)
if ((unix_fd = get_file_unix_fd( file )) != -1)
{
if ((unix_fd = dup( unix_fd )) != -1)
queue->fd = create_anonymous_fd( &msg_queue_fd_ops, unix_fd, &queue->obj );
queue->fd = create_anonymous_fd( &msg_queue_fd_ops, unix_fd, &queue->obj, 0 );
else
file_set_error();
}

View File

@ -726,7 +726,7 @@ static void acquire_lock(void)
if (listen( fd, 5 ) == -1) fatal_perror( "listen" );
if (!(master_socket = alloc_object( &master_socket_ops )) ||
!(master_socket->fd = create_anonymous_fd( &master_socket_fd_ops, fd, &master_socket->obj )))
!(master_socket->fd = create_anonymous_fd( &master_socket_fd_ops, fd, &master_socket->obj, 0 )))
fatal_error( "out of memory\n" );
master_socket->timeout = NULL;
set_fd_events( master_socket->fd, POLLIN );

View File

@ -69,7 +69,6 @@ struct serial
{
struct object obj;
struct fd *fd;
unsigned int options;
/* timeout values */
unsigned int readinterval;
@ -122,18 +121,12 @@ int is_serial_fd( struct fd *fd )
}
/* create a serial object for a given fd */
struct object *create_serial( struct fd *fd, unsigned int options )
struct object *create_serial( struct fd *fd )
{
struct serial *serial;
int unix_fd = get_unix_fd( fd );
/* set the fd back to blocking if necessary */
if (options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT))
fcntl( unix_fd, F_SETFL, 0 );
if (!(serial = alloc_object( &serial_ops ))) return NULL;
serial->options = options;
serial->readinterval = 0;
serial->readmult = 0;
serial->readconst = 0;
@ -184,15 +177,6 @@ static enum server_fd_type serial_get_info( struct fd *fd, int *flags )
assert( serial->obj.ops == &serial_ops );
*flags = 0;
if (!(serial->options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
*flags |= FD_FLAG_OVERLAPPED;
else if (!(serial->readinterval == MAXDWORD &&
serial->readmult == 0 && serial->readconst == 0))
*flags |= FD_FLAG_TIMEOUT;
if (serial->readinterval == MAXDWORD &&
serial->readmult == 0 && serial->readconst == 0)
*flags |= FD_FLAG_AVAILABLE;
return FD_TYPE_SERIAL;
}

View File

@ -114,7 +114,7 @@ static struct handler *create_handler( signal_callback callback )
handler->pending = 0;
handler->callback = callback;
if (!(handler->fd = create_anonymous_fd( &handler_fd_ops, fd[0], &handler->obj )))
if (!(handler->fd = create_anonymous_fd( &handler_fd_ops, fd[0], &handler->obj, 0 )))
{
release_object( handler );
return NULL;

View File

@ -245,8 +245,6 @@ static void sock_wake_up( struct sock *sock, int pollev )
int i;
int async_active = 0;
if ( sock->flags & WSA_FLAG_OVERLAPPED )
{
if ( pollev & (POLLIN|POLLPRI) && async_waiting( sock->read_q ))
{
if (debug_level) fprintf( stderr, "activating read queue for socket %p\n", sock );
@ -259,7 +257,6 @@ static void sock_wake_up( struct sock *sock, int pollev )
async_wake_up( sock->write_q, STATUS_ALERTED );
async_active = 1;
}
}
/* Do not signal events if there are still pending asynchronous IO requests */
/* We need this to delay FD_CLOSE events until all pending overlapped requests are processed */
@ -485,10 +482,8 @@ static int sock_get_poll_events( struct fd *fd )
/* listening, wait for readable */
return (sock->hmask & FD_ACCEPT) ? 0 : POLLIN;
if (mask & (FD_READ) || (sock->flags & WSA_FLAG_OVERLAPPED && async_waiting( sock->read_q )))
ev |= POLLIN | POLLPRI;
if (mask & FD_WRITE || (sock->flags & WSA_FLAG_OVERLAPPED && async_waiting( sock->write_q )))
ev |= POLLOUT;
if (mask & FD_READ || async_waiting( sock->read_q )) ev |= POLLIN | POLLPRI;
if (mask & FD_WRITE || async_waiting( sock->write_q )) ev |= POLLOUT;
/* We use POLLIN with 0 bytes recv() as FD_CLOSE indication for stream sockets. */
if ( sock->type == SOCK_STREAM && ( sock->mask & ~sock->hmask & FD_CLOSE) )
ev |= POLLIN;
@ -501,8 +496,7 @@ static enum server_fd_type sock_get_info( struct fd *fd, int *flags )
struct sock *sock = get_fd_user( fd );
assert( sock->obj.ops == &sock_ops );
*flags = FD_FLAG_AVAILABLE;
if (sock->flags & WSA_FLAG_OVERLAPPED) *flags |= FD_FLAG_OVERLAPPED;
*flags = 0;
if ( sock->type != SOCK_STREAM || sock->state & FD_WINE_CONNECTED )
{
if ( !(sock->state & FD_READ ) ) *flags |= FD_FLAG_RECV_SHUTDOWN;
@ -519,12 +513,6 @@ static void sock_queue_async( struct fd *fd, const async_data_t *data, int type,
assert( sock->obj.ops == &sock_ops );
if ( !(sock->flags & WSA_FLAG_OVERLAPPED) )
{
set_error( STATUS_INVALID_HANDLE );
return;
}
switch (type)
{
case ASYNC_TYPE_READ:
@ -636,7 +624,8 @@ static struct object *create_socket( int family, int type, int protocol, unsigne
sock->deferred = NULL;
sock->read_q = NULL;
sock->write_q = NULL;
if (!(sock->fd = create_anonymous_fd( &sock_fd_ops, sockfd, &sock->obj )))
if (!(sock->fd = create_anonymous_fd( &sock_fd_ops, sockfd, &sock->obj,
(flags & WSA_FLAG_OVERLAPPED) ? 0 : FILE_SYNCHRONOUS_IO_NONALERT )))
{
release_object( sock );
return NULL;
@ -705,7 +694,8 @@ static struct sock *accept_socket( obj_handle_t handle )
acceptsock->deferred = NULL;
acceptsock->read_q = NULL;
acceptsock->write_q = NULL;
if (!(acceptsock->fd = create_anonymous_fd( &sock_fd_ops, acceptfd, &acceptsock->obj )))
if (!(acceptsock->fd = create_anonymous_fd( &sock_fd_ops, acceptfd, &acceptsock->obj,
get_fd_options( sock->fd ) )))
{
release_object( acceptsock );
release_object( sock );

View File

@ -206,7 +206,7 @@ struct thread *create_thread( int fd, struct process *process )
release_object( thread );
return NULL;
}
if (!(thread->request_fd = create_anonymous_fd( &thread_fd_ops, fd, &thread->obj )))
if (!(thread->request_fd = create_anonymous_fd( &thread_fd_ops, fd, &thread->obj, 0 )))
{
release_object( thread );
return NULL;
@ -993,7 +993,7 @@ DECL_HANDLER(init_thread)
if (reply_fd == -1 || fcntl( reply_fd, F_SETFL, O_NONBLOCK ) == -1) goto error;
current->reply_fd = create_anonymous_fd( &thread_fd_ops, reply_fd, &current->obj );
current->reply_fd = create_anonymous_fd( &thread_fd_ops, reply_fd, &current->obj, 0 );
reply_fd = -1;
if (!current->reply_fd) goto error;
@ -1002,7 +1002,7 @@ DECL_HANDLER(init_thread)
set_error( STATUS_TOO_MANY_OPENED_FILES ); /* most likely reason */
return;
}
if (!(current->wait_fd = create_anonymous_fd( &thread_fd_ops, wait_fd, &current->obj )))
if (!(current->wait_fd = create_anonymous_fd( &thread_fd_ops, wait_fd, &current->obj, 0 )))
return;
if (!is_valid_address(req->teb) || !is_valid_address(req->peb) || !is_valid_address(req->ldt_copy))