int new_fd_etc(struct io_context *context, struct file_descriptor *descriptor, int firstIndex) { int fd = -1; uint32_t i; fssh_mutex_lock(&context->io_mutex); for (i = firstIndex; i < context->table_size; i++) { if (!context->fds[i]) { fd = i; break; } } if (fd < 0) { fd = FSSH_B_NO_MORE_FDS; goto err; } context->fds[fd] = descriptor; context->num_used_fds++; fssh_atomic_add(&descriptor->open_count, 1); err: fssh_mutex_unlock(&context->io_mutex); return fd; }
static int dup_fd(int fd, bool kernel) { struct io_context *context = get_current_io_context(kernel); struct file_descriptor *descriptor; int status; TRACE(("dup_fd: fd = %d\n", fd)); // Try to get the fd structure descriptor = get_fd(context, fd); if (descriptor == NULL) return FSSH_B_FILE_ERROR; // now put the fd in place status = new_fd(context, descriptor); if (status < 0) put_fd(descriptor); else { fssh_mutex_lock(&context->io_mutex); fd_set_close_on_exec(context, status, false); fssh_mutex_unlock(&context->io_mutex); } return status; }
static struct file_descriptor * remove_fd(struct io_context *context, int fd) { struct file_descriptor *descriptor = NULL; if (fd < 0) return NULL; fssh_mutex_lock(&context->io_mutex); if ((uint32_t)fd < context->table_size) descriptor = context->fds[fd]; if (descriptor) { // fd is valid context->fds[fd] = NULL; fd_set_close_on_exec(context, fd, false); context->num_used_fds--; if (descriptor->open_mode & FSSH_O_DISCONNECTED) descriptor = NULL; } fssh_mutex_unlock(&context->io_mutex); return descriptor; }
struct file_descriptor * get_fd(struct io_context *context, int fd) { struct file_descriptor *descriptor = NULL; if (fd < 0) return NULL; fssh_mutex_lock(&context->io_mutex); if ((uint32_t)fd < context->table_size) descriptor = context->fds[fd]; if (descriptor != NULL) { // Disconnected descriptors cannot be accessed anymore if (descriptor->open_mode & FSSH_O_DISCONNECTED) descriptor = NULL; else inc_fd_ref_count(descriptor); } fssh_mutex_unlock(&context->io_mutex); return descriptor; }
static int dup2_fd(int oldfd, int newfd, bool kernel) { struct file_descriptor *evicted = NULL; struct io_context *context; TRACE(("dup2_fd: ofd = %d, nfd = %d\n", oldfd, newfd)); // quick check if (oldfd < 0 || newfd < 0) return FSSH_B_FILE_ERROR; // Get current I/O context and lock it context = get_current_io_context(kernel); fssh_mutex_lock(&context->io_mutex); // Check if the fds are valid (mutex must be locked because // the table size could be changed) if ((uint32_t)oldfd >= context->table_size || (uint32_t)newfd >= context->table_size || context->fds[oldfd] == NULL) { fssh_mutex_unlock(&context->io_mutex); return FSSH_B_FILE_ERROR; } // Check for identity, note that it cannot be made above // because we always want to return an error on invalid // handles if (oldfd != newfd) { // Now do the work evicted = context->fds[newfd]; fssh_atomic_add(&context->fds[oldfd]->ref_count, 1); fssh_atomic_add(&context->fds[oldfd]->open_count, 1); context->fds[newfd] = context->fds[oldfd]; if (evicted == NULL) context->num_used_fds++; } fd_set_close_on_exec(context, newfd, false); fssh_mutex_unlock(&context->io_mutex); // Say bye bye to the evicted fd if (evicted) { close_fd(evicted); put_fd(evicted); } return newfd; }
static fssh_status_t read_from_file(file_cache_ref *ref, void *cookie, fssh_off_t offset, int32_t pageOffset, fssh_addr_t buffer, fssh_size_t bufferSize) { fssh_iovec vec; vec.iov_base = (void *)buffer; vec.iov_len = bufferSize; fssh_mutex_unlock(&ref->lock); fssh_status_t status = vfs_read_pages(ref->node, cookie, offset + pageOffset, &vec, 1, &bufferSize); fssh_mutex_lock(&ref->lock); return status; }