* Added fd_ops::set_flags() hook. It's only implemented by socket FDs

ATM.
* Changed common_fcntl() to also work for non-vnode-based FDs. Only the
  operations that require a vnode do fail now. F_SETFL uses the new
  fd_ops::set_flags() if available, falling back to the vnode respective
  operation.
* Changed some direct accesses to file_descriptor::u::vnode. It was safe
  in those cases, but might not be anymore if we ever change fd_vnode().

ftp can at least connect to servers again, now, but apparently we still
have a problem with syscall restarts -- downloads fail after one second,
when the timer goes off.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24917 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2008-04-11 19:21:14 +00:00
parent f156c25d14
commit 3118b3a7cb
3 changed files with 56 additions and 25 deletions
+1
View File
@@ -26,6 +26,7 @@ struct fd_ops {
status_t (*fd_write)(struct file_descriptor *, off_t pos, const void *buffer, size_t *length);
off_t (*fd_seek)(struct file_descriptor *, off_t pos, int seekType);
status_t (*fd_ioctl)(struct file_descriptor *, ulong op, void *buffer, size_t length);
status_t (*fd_set_flags)(struct file_descriptor *, int flags);
status_t (*fd_select)(struct file_descriptor *, uint8 event,
struct selectsync *sync);
status_t (*fd_deselect)(struct file_descriptor *, uint8 event,
+12
View File
@@ -214,6 +214,17 @@ socket_ioctl(struct file_descriptor *descriptor, ulong op, void *buffer,
}
static status_t
socket_set_flags(struct file_descriptor *descriptor, int flags)
{
// we ignore O_APPEND, but O_NONBLOCK we need to translate
uint32 op = (flags & O_NONBLOCK) != 0
? B_SET_NONBLOCKING_IO : B_SET_BLOCKING_IO;
return sStackInterface->ioctl(descriptor->u.socket, op, NULL, 0);
}
static status_t
socket_select(struct file_descriptor *descriptor, uint8 event,
struct selectsync *sync)
@@ -272,6 +283,7 @@ static struct fd_ops sSocketFDOps = {
&socket_write,
NULL, // fd_seek
&socket_ioctl,
&socket_set_flags,
&socket_select,
&socket_deselect,
NULL, // fd_read_dir
+43 -25
View File
@@ -292,6 +292,7 @@ static struct fd_ops sFileOps = {
file_write,
file_seek,
common_ioctl,
NULL, // set_flags
file_select,
file_deselect,
NULL, // read_dir()
@@ -307,6 +308,7 @@ static struct fd_ops sDirectoryOps = {
NULL, // write()
NULL, // seek()
common_ioctl,
NULL, // set_flags
NULL, // select()
NULL, // deselect()
dir_read,
@@ -322,6 +324,7 @@ static struct fd_ops sAttributeDirectoryOps = {
NULL, // write()
NULL, // seek()
common_ioctl,
NULL, // set_flags
NULL, // select()
NULL, // deselect()
attr_dir_read,
@@ -337,6 +340,7 @@ static struct fd_ops sAttributeOps = {
attr_write,
attr_seek,
common_ioctl,
NULL, // set_flags
NULL, // select()
NULL, // deselect()
NULL, // read_dir()
@@ -352,6 +356,7 @@ static struct fd_ops sIndexDirectoryOps = {
NULL, // write()
NULL, // seek()
NULL, // ioctl()
NULL, // set_flags
NULL, // select()
NULL, // deselect()
index_dir_read,
@@ -368,6 +373,7 @@ static struct fd_ops sIndexOps = {
NULL, // write()
NULL, // seek()
NULL, // ioctl()
NULL, // set_flags
NULL, // select()
NULL, // deselect()
NULL, // dir_read()
@@ -384,6 +390,7 @@ static struct fd_ops sQueryOps = {
NULL, // write()
NULL, // seek()
NULL, // ioctl()
NULL, // set_flags
NULL, // select()
NULL, // deselect()
query_read,
@@ -2435,7 +2442,8 @@ get_fd_and_vnode(int fd, struct vnode **_vnode, bool kernel)
if (descriptor == NULL)
return NULL;
if (fd_vnode(descriptor) == NULL) {
struct vnode* vnode = fd_vnode(descriptor);
if (vnode == NULL) {
put_fd(descriptor);
return NULL;
}
@@ -2443,7 +2451,7 @@ get_fd_and_vnode(int fd, struct vnode **_vnode, bool kernel)
// ToDo: when we can close a file descriptor at any point, investigate
// if this is still valid to do (accessing the vnode without ref_count
// or locking)
*_vnode = descriptor->u.vnode;
*_vnode = vnode;
return descriptor;
}
@@ -5121,17 +5129,18 @@ common_ioctl(struct file_descriptor *descriptor, ulong op, void *buffer,
static status_t
common_fcntl(int fd, int op, uint32 argument, bool kernel)
{
struct file_descriptor *descriptor;
struct vnode *vnode;
struct flock flock;
FUNCTION(("common_fcntl(fd = %d, op = %d, argument = %lx, %s)\n",
fd, op, argument, kernel ? "kernel" : "user"));
descriptor = get_fd_and_vnode(fd, &vnode, kernel);
struct file_descriptor *descriptor = get_fd(get_current_io_context(kernel),
fd);
if (descriptor == NULL)
return B_FILE_ERROR;
struct vnode* vnode = fd_vnode(descriptor);
status_t status = B_OK;
if (op == F_SETLK || op == F_SETLKW || op == F_GETLK) {
@@ -5175,19 +5184,23 @@ common_fcntl(int fd, int op, uint32 argument, bool kernel)
case F_SETFL:
// Set file descriptor open mode
if (HAS_FS_CALL(vnode, set_flags)) {
// we only accept changes to O_APPEND and O_NONBLOCK
argument &= O_APPEND | O_NONBLOCK;
// we only accept changes to O_APPEND and O_NONBLOCK
argument &= O_APPEND | O_NONBLOCK;
if (descriptor->ops->fd_set_flags != NULL) {
status = descriptor->ops->fd_set_flags(descriptor, argument);
} else if (vnode != NULL && HAS_FS_CALL(vnode, set_flags)) {
status = FS_CALL(vnode, set_flags, descriptor->cookie,
(int)argument);
if (status == B_OK) {
// update this descriptor's open_mode field
descriptor->open_mode = (descriptor->open_mode
& ~(O_APPEND | O_NONBLOCK)) | argument;
}
} else
status = EOPNOTSUPP;
if (status == B_OK) {
// update this descriptor's open_mode field
descriptor->open_mode = (descriptor->open_mode
& ~(O_APPEND | O_NONBLOCK)) | argument;
}
break;
case F_GETFL:
@@ -5211,12 +5224,15 @@ common_fcntl(int fd, int op, uint32 argument, bool kernel)
}
case F_GETLK:
status = get_advisory_lock(descriptor->u.vnode, &flock);
if (status == B_OK) {
// copy back flock structure
status = user_memcpy((struct flock *)argument, &flock,
sizeof(struct flock));
}
if (vnode != NULL) {
status = get_advisory_lock(vnode, &flock);
if (status == B_OK) {
// copy back flock structure
status = user_memcpy((struct flock *)argument, &flock,
sizeof(struct flock));
}
} else
status = B_BAD_VALUE;
break;
case F_SETLK:
@@ -5225,9 +5241,11 @@ common_fcntl(int fd, int op, uint32 argument, bool kernel)
if (status < B_OK)
break;
if (flock.l_type == F_UNLCK)
status = release_advisory_lock(descriptor->u.vnode, &flock);
else {
if (vnode == NULL) {
status = B_BAD_VALUE;
} else if (flock.l_type == F_UNLCK) {
status = release_advisory_lock(vnode, &flock);
} else {
// the open mode must match the lock type
if ((descriptor->open_mode & O_RWMASK) == O_RDONLY
&& flock.l_type == F_WRLCK
@@ -5235,7 +5253,7 @@ common_fcntl(int fd, int op, uint32 argument, bool kernel)
&& flock.l_type == F_RDLCK)
status = B_FILE_ERROR;
else {
status = acquire_advisory_lock(descriptor->u.vnode, -1,
status = acquire_advisory_lock(vnode, -1,
&flock, op == F_SETLKW);
}
}
@@ -8023,9 +8041,9 @@ _user_flock(int fd, int op)
flock.l_type = (op & LOCK_SH) != 0 ? F_RDLCK : F_WRLCK;
if ((op & LOCK_UN) != 0)
status = release_advisory_lock(descriptor->u.vnode, &flock);
status = release_advisory_lock(vnode, &flock);
else {
status = acquire_advisory_lock(descriptor->u.vnode,
status = acquire_advisory_lock(vnode,
thread_get_current_thread()->team->session_id, &flock,
(op & LOCK_NB) == 0);
}