static ssize_t orangefs_file_write_iter(struct kiocb *iocb, struct iov_iter *iter) { struct file *file = iocb->ki_filp; loff_t pos; ssize_t rc; BUG_ON(iocb->private); gossip_debug(GOSSIP_FILE_DEBUG, "orangefs_file_write_iter\n"); inode_lock(file->f_mapping->host); /* Make sure generic_write_checks sees an up to date inode size. */ if (file->f_flags & O_APPEND) { rc = orangefs_inode_getattr(file->f_mapping->host, 0, 1); if (rc == -ESTALE) rc = -EIO; if (rc) { gossip_err("%s: orangefs_inode_getattr failed, " "rc:%zd:.\n", __func__, rc); goto out; } } if (file->f_pos > i_size_read(file->f_mapping->host)) orangefs_i_size_write(file->f_mapping->host, file->f_pos); rc = generic_write_checks(iocb, iter); if (rc <= 0) { gossip_err("%s: generic_write_checks failed, rc:%zd:.\n", __func__, rc); goto out; } /* * if we are appending, generic_write_checks would have updated * pos to the end of the file, so we will wait till now to set * pos... */ pos = *(&iocb->ki_pos); rc = do_readv_writev(ORANGEFS_IO_WRITE, file, &pos, iter); if (rc < 0) { gossip_err("%s: do_readv_writev failed, rc:%zd:.\n", __func__, rc); goto out; } iocb->ki_pos = pos; g_orangefs_stats.writes++; out: inode_unlock(file->f_mapping->host); return rc; }
/* * Copy to client-core's address space from the buffers specified * by the iovec upto total_size bytes. * NOTE: the iovector can either contain addresses which * can futher be kernel-space or user-space addresses. * or it can pointers to struct page's */ static int precopy_buffers(int buffer_index, struct iov_iter *iter, size_t total_size) { int ret = 0; /* * copy data from application/kernel by pulling it out * of the iovec. */ if (total_size) { ret = orangefs_bufmap_copy_from_iovec(iter, buffer_index, total_size); if (ret < 0) gossip_err("%s: Failed to copy-in buffers. Please make sure that the pvfs2-client is running. %ld\n", __func__, (long)ret); } if (ret < 0) gossip_err("%s: Failed to copy-in buffers. Please make sure that the pvfs2-client is running. %ld\n", __func__, (long)ret); return ret; }
/** * Routines that retrieve and/or set ACLs for PVFS2 files. */ static struct posix_acl * pvfs2_get_acl(struct inode *inode, int type) { struct posix_acl *acl; int ret; char *key = NULL, *value = NULL; /* Won't work if you don't mount with the right set of options */ if (get_acl_flag(inode) == 0) { gossip_debug(GOSSIP_ACL_DEBUG, "pvfs2_get_acl: ACL options disabled on " "this FS!\n"); return NULL; } switch (type) { case ACL_TYPE_ACCESS: key = PVFS2_XATTR_NAME_ACL_ACCESS; break; case ACL_TYPE_DEFAULT: key = PVFS2_XATTR_NAME_ACL_DEFAULT; break; default: gossip_err("pvfs2_get_acl: bogus value of type %d\n", type); return ERR_PTR(-EINVAL); } /* * Rather than incurring a network call just to determine the exact length of * the attribute, I just allocate a max length to save on the network call * Conceivably, we could pass NULL to pvfs2_inode_getxattr() to probe the length * of the value, but I don't do that for now. */ value = (char *) kmalloc(PVFS_MAX_XATTR_VALUELEN, GFP_KERNEL); if (value == NULL) { gossip_err("pvfs2_get_acl: Could not allocate value ptr\n"); return ERR_PTR(-ENOMEM); } gossip_debug(GOSSIP_ACL_DEBUG, "inode %llu, key %s, type %d\n", llu(get_handle_from_ino(inode)), key, type); ret = pvfs2_inode_getxattr(inode, "", key, value, PVFS_MAX_XATTR_VALUELEN); /* if the key exists, convert it to an in-memory rep */ if (ret > 0) { acl = pvfs2_acl_decode(value, ret); } else if (ret == -ENODATA || ret == -ENOSYS) { acl = NULL; } else { gossip_err("inode %llu retrieving acl's failed with error %d\n", llu(get_handle_from_ino(inode)), ret); acl = ERR_PTR(ret); } if (value) { kfree(value); } return acl; }
static int pvfs2_xattr_set_acl(struct inode *inode, int type, const void *value, size_t size) { struct posix_acl *acl; int error; #ifdef HAVE_CURRENT_FSUID int fsuid = current_fsuid(); #else int fsuid = current->fsuid; #endif gossip_debug(GOSSIP_ACL_DEBUG, "pvfs2_xattr_set_acl called with size %ld\n", (long)size); /* if we have not been mounted with acl option, ignore this */ if (get_acl_flag(inode) == 0) { gossip_debug(GOSSIP_ACL_DEBUG, "pvfs2_xattr_set_acl: ACL options " "disabled on this FS!\n"); return -EOPNOTSUPP; } /* Are we capable of setting acls on a file for which we should not be? */ if ((fsuid != inode->i_uid) && !capable(CAP_FOWNER)) { gossip_err("pvfs2_xattr_set_acl: operation not permitted " "(current->fsuid %d), (inode->owner %d)\n", fsuid, inode->i_uid); return -EPERM; } if (value) { acl = posix_acl_from_xattr(value, size); if (IS_ERR(acl)) { error = PTR_ERR(acl); gossip_err("pvfs2_xattr_set_acl: posix_acl_from_xattr returned " "error %d\n", error); goto err; } else if (acl) { error = posix_acl_valid(acl); if (error) { gossip_err("pvfs2_xattr_set_acl: posix_acl_valid returned " "error %d\n", error); goto out; } } } else { acl = NULL; } error = pvfs2_set_acl(inode, type, acl); gossip_debug(GOSSIP_ACL_DEBUG, "pvfs2_set_acl returned error %d\n", error); out: posix_acl_release(acl); err: return error; }
void dbpf_open_cache_initialize(void) { int i = 0, ret = 0; gen_mutex_lock(&cache_mutex); /* run through preallocated cache elements to initialize * and put them on the free list */ if (OPEN_CACHE_SIZE == 0) { gossip_err("Warning: dbpf_open_cache disabled.\n"); } for (i = 0; i < OPEN_CACHE_SIZE; i++) { prealloc[i].fd = -1; qlist_add(&prealloc[i].queue_link, &free_list); } gen_mutex_unlock(&cache_mutex); /* Initialize and create the worker thread for threaded deletes */ INIT_QLIST_HEAD(&dbpf_unlink_context.global_list); pthread_mutex_init(&dbpf_unlink_context.mutex, NULL); pthread_cond_init(&dbpf_unlink_context.data_available, NULL); ret = pthread_create(&dbpf_unlink_context.thread_id, NULL, unlink_bstream, (void*)&dbpf_unlink_context); if(ret) { gossip_err("dbpf_open_cache_initialize: failed [%d]\n", ret); return; } }
/* * Used by both encode functions, request and response, to set * up the one buffer which will hold the encoded message. */ static int encode_common(struct PINT_encoded_msg *target_msg, int maxsize) { int ret = 0; void *buf = NULL; gossip_debug(GOSSIP_ENDECODE_DEBUG,"encode_common\n"); /* this encoder always uses just one buffer */ BF_ENCODE_TARGET_MSG_INIT(target_msg); /* allocate the max size buffer to avoid the work of calculating it */ buf = (initializing_sizes ? malloc(maxsize) : BMI_memalloc(target_msg->dest, maxsize, BMI_SEND)); if (!buf) { gossip_err("Error: failed to BMI_malloc memory for response.\n"); gossip_err("Error: is BMI address %llu still valid?\n", llu(target_msg->dest)); ret = -PVFS_ENOMEM; goto out; } target_msg->buffer_list[0] = buf; target_msg->alloc_size_list[0] = maxsize; target_msg->ptr_current = buf; /* generic header */ memcpy(target_msg->ptr_current, le_bytefield_table.generic_header, PINT_ENC_GENERIC_HEADER_SIZE); target_msg->ptr_current += PINT_ENC_GENERIC_HEADER_SIZE; out: return ret; }
/* * pvfs_bufmap_copy_from_pages() * * Copies data to the mapped buffer from the specified set of target * pages (typically the kernel's page-cache) * for a given size and number of pages. * NOTE: iovec is expected to store pointers to struct page. * * Returns 0 on success and -errno on failure. */ int pvfs_bufmap_copy_from_pages(int buffer_index, const struct iovec *vec, unsigned long nr_segs, size_t size) { size_t amt_copied = 0, amt_remaining = 0, cur_copy_size = 0; int to_page_index = 0; void *from_kaddr = NULL, *to_kaddr = NULL; struct pvfs_bufmap_desc *to = &desc_array[buffer_index]; struct page *page; gossip_debug(GOSSIP_BUFMAP_DEBUG, "pvfs_bufmap_copy_from_pages: nr_pages %lu " "index %d, size %zd\n", nr_segs, buffer_index, size); down_read(&bufmap_init_sem); if (bufmap_init == 0) { gossip_err("pvfs_bufmap_copy_from_pages: not yet " "initialized.\n"); gossip_err("pvfs2: please confirm that pvfs2-client is running.\n"); up_read(&bufmap_init_sem); return -EIO; } while (amt_copied < size) { if (to_page_index >= nr_segs) { gossip_err("pvfs_bufmap_copy_from_pages: count cannot exceed number of" "pages(%lu)\n", nr_segs); up_read(&bufmap_init_sem); return -EIO; } page = (struct page *) vec[to_page_index].iov_base; if (page == NULL) { gossip_err("pvfs_bufmap_copy_from_pages: invalid page pointer\n"); up_read(&bufmap_init_sem); return -EIO; } amt_remaining = (size - amt_copied); cur_copy_size = ((amt_remaining > PAGE_SIZE) ? PAGE_SIZE : amt_remaining); gossip_debug(GOSSIP_BUFMAP_DEBUG, "pvfs_bufmap_copy_from_pages:" "from_page: %p, to_page: %p\n", page, to->page_array[to_page_index]); to_kaddr = pvfs2_kmap(to->page_array[to_page_index]); from_kaddr = pvfs2_kmap(page); #if 0 gossip_debug(GOSSIP_BUFMAP_DEBUG, "pvfs_bufmap_copy_from_pages -> " "to_kaddr: %p, from_kaddr:%p, cur_copy_size: %d\n", to_kaddr, from_kaddr, cur_copy_size); #endif memcpy(to_kaddr, from_kaddr, cur_copy_size); pvfs2_kunmap(page); pvfs2_kunmap(to->page_array[to_page_index]); amt_copied += cur_copy_size; to_page_index++; } up_read(&bufmap_init_sem); return 0; }
static PINT_sm_action test_recv_one_msg_f( struct PINT_smcb *smcb, job_status_s *js_p) { struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT); int ret; gossip_debug(GOSSIP_SERVER_DEBUG, "\n\n%s: entry\n\n", __func__); s_op->msgarray_op.msgpair.max_resp_sz = PINT_encode_calc_max_size( PINT_ENCODE_RESP, PVFS_SERV_WRITE_COMPLETION, ENCODING_LE_BFIELD); s_op->msgarray_op.msgpair.encoded_resp_p = BMI_memalloc( s_op->addr, //s_op->msgarray_op.msgpair.svr_addr, s_op->msgarray_op.msgpair.max_resp_sz, BMI_RECV); if (!s_op->msgarray_op.msgpair.encoded_resp_p) { gossip_err("BMI_memalloc (for write ack) failed\n"); return -PVFS_ENOMEM; } //gossip_debug(GOSSIP_LB_DEBUG, "bmi memalloc success\n"); /* pre-post this recv with an infinite timeout and adjust it after the flow completes since we don't know how long a flow can take at this point */ ret = job_bmi_recv( s_op->addr, //s_op->msgarray_op.msgpair.svr_addr, s_op->msgarray_op.msgpair.encoded_resp_p, s_op->msgarray_op.msgpair.max_resp_sz, 5, BMI_PRE_ALLOC, smcb, IO_SM_PHASE_FINAL_ACK, js_p, &s_op->msgarray_op.msgpair.recv_id, server_job_context, JOB_TIMEOUT_INF, NULL); if (ret < 0) { gossip_err("job_bmi_recv (write ack) failed\n"); }else{ gossip_debug(GOSSIP_LB_DEBUG, "job_bmi_recv correct:ret = %d\n", ret); } return ret; // assert(ret == 0); }
/* pvfs_bufmap_copy_from_user() * * copies data from a user space address to a mapped buffer * * returns 0 on success, -errno on failure */ int pvfs_bufmap_copy_from_user(int buffer_index, void __user *from, size_t size) { size_t ret = 0, amt_copied = 0, amt_remaining = 0, cur_copy_size = 0; void __user *from_kaddr = from; void *to_kaddr = NULL; int to_page_index = 0; struct pvfs_bufmap_desc *to = &desc_array[buffer_index]; char* tmp_printer = NULL; int tmp_int = 0; gossip_debug(GOSSIP_BUFMAP_DEBUG, "pvfs_bufmap_copy_from_user: from %p, index %d, " "size %zd\n", from, buffer_index, size); down_read(&bufmap_init_sem); if (bufmap_init == 0) { gossip_err("pvfs_bufmap_copy_from_user: not yet " "initialized.\n"); gossip_err("pvfs2: please confirm that pvfs2-client daemon is running.\n"); up_read(&bufmap_init_sem); return -EIO; } while(amt_copied < size) { amt_remaining = (size - amt_copied); cur_copy_size = ((amt_remaining > PAGE_SIZE) ? PAGE_SIZE : amt_remaining); to_kaddr = pvfs2_kmap(to->page_array[to_page_index]); ret = copy_from_user(to_kaddr, from_kaddr, cur_copy_size); if (!tmp_printer) { tmp_printer = (char*)(to_kaddr); tmp_int += tmp_printer[0]; gossip_debug(GOSSIP_BUFMAP_DEBUG, "First character (integer value) in pvfs_bufmap_copy_from_user: %d\n", tmp_int); } pvfs2_kunmap(to->page_array[to_page_index]); if (ret) { gossip_debug(GOSSIP_BUFMAP_DEBUG, "Failed to copy data from user space\n"); up_read(&bufmap_init_sem); return -EFAULT; } from_kaddr += cur_copy_size; amt_copied += cur_copy_size; to_page_index++; } up_read(&bufmap_init_sem); return 0; }
/* * PVFS2 ACL encode * What this does is encode the posix_acl structure * into little-endian bytefirst using the htobmi* macros * and stuffs it into a buffer for storage. */ static void * pvfs2_acl_encode(const struct posix_acl *acl, size_t *size) { char *e, *ptr; size_t n; *size = acl->a_count * sizeof(pvfs2_acl_entry); gossip_debug(GOSSIP_ACL_DEBUG, "pvfs2_acl_encode: acl encoded %ld bytes " " (%d entries)\n", (long) *size, acl->a_count); e = (char *)kmalloc(*size, GFP_KERNEL); if (!e) { gossip_err("pvfs2_acl_encode: Could not allocate %d bytes " "for acl encode\n", (int) *size); return ERR_PTR(-ENOMEM); } ptr = e; for (n = 0; n < acl->a_count; n++) { pvfs2_acl_entry *entry = (pvfs2_acl_entry *)e; entry->p_tag = htobmi32(acl->a_entries[n].e_tag); entry->p_perm = htobmi32(acl->a_entries[n].e_perm); switch (acl->a_entries[n].e_tag) { case ACL_USER: case ACL_GROUP: entry->p_id = htobmi32(acl->a_entries[n].e_id); e += sizeof(pvfs2_acl_entry); break; case ACL_USER_OBJ: case ACL_GROUP_OBJ: case ACL_MASK: case ACL_OTHER: entry->p_id = htobmi32(ACL_UNDEFINED_ID); e += sizeof(pvfs2_acl_entry); break; default: gossip_err("pvfs2_acl_encode: bogus value of e_tag %d\n", acl->a_entries[n].e_tag); goto fail; } gossip_debug(GOSSIP_ACL_DEBUG, "Encoded acl entry %zd " "(p_tag %d, p_perm %d, p_id %d)\n", n, acl->a_entries[n].e_tag, acl->a_entries[n].e_perm, acl->a_entries[n].e_id); } return (char *) ptr; fail: kfree(ptr); gossip_err("pvfs2_acl_encode: returning EINVAL\n"); return ERR_PTR(-EINVAL); }
struct posix_acl *orangefs_get_acl(struct inode *inode, int type) { struct posix_acl *acl; int ret; char *key = NULL, *value = NULL; switch (type) { case ACL_TYPE_ACCESS: key = XATTR_NAME_POSIX_ACL_ACCESS; break; case ACL_TYPE_DEFAULT: key = XATTR_NAME_POSIX_ACL_DEFAULT; break; default: gossip_err("orangefs_get_acl: bogus value of type %d\n", type); return ERR_PTR(-EINVAL); } /* * Rather than incurring a network call just to determine the exact * length of the attribute, I just allocate a max length to save on * the network call. Conceivably, we could pass NULL to * orangefs_inode_getxattr() to probe the length of the value, but * I don't do that for now. */ value = kmalloc(ORANGEFS_MAX_XATTR_VALUELEN, GFP_KERNEL); if (!value) return ERR_PTR(-ENOMEM); gossip_debug(GOSSIP_ACL_DEBUG, "inode %pU, key %s, type %d\n", get_khandle_from_ino(inode), key, type); ret = orangefs_inode_getxattr(inode, key, value, ORANGEFS_MAX_XATTR_VALUELEN); /* if the key exists, convert it to an in-memory rep */ if (ret > 0) { acl = posix_acl_from_xattr(&init_user_ns, value, ret); } else if (ret == -ENODATA || ret == -ENOSYS) { acl = NULL; } else { gossip_err("inode %pU retrieving acl's failed with error %d\n", get_khandle_from_ino(inode), ret); acl = ERR_PTR(ret); } /* kfree(NULL) is safe, so don't worry if value ever got used */ kfree(value); return acl; }
/* * Handles the case when a chmod is done for an inode that may have an * access control list. * The inode->i_mode field is updated to the desired value by the caller * before calling this function which returns 0 on success and a -ve * number on failure. */ int pvfs2_acl_chmod(struct inode *inode) { struct posix_acl *acl, *clone; int error; if (get_acl_flag(inode) == 0) { gossip_debug(GOSSIP_ACL_DEBUG, "pvfs2_acl_chmod: ACL options " "disabled on this FS!\n"); return 0; } if (S_ISLNK(inode->i_mode)) { gossip_err("pvfs2_acl_chmod: operation not permitted on symlink!\n"); error = -EACCES; goto out; } acl = pvfs2_get_acl(inode, ACL_TYPE_ACCESS); if (IS_ERR(acl)) { error = PTR_ERR(acl); gossip_err("pvfs2_acl_chmod: get acl (access) failed with %d\n", error); goto out; } if(!acl) { error = 0; goto out; } clone = posix_acl_clone(acl, GFP_KERNEL); posix_acl_release(acl); if (!clone) { gossip_err("pvfs2_acl_chmod failed with ENOMEM\n"); error = -ENOMEM; goto out; } error = posix_acl_chmod_masq(clone, inode->i_mode); if (!error) { error = pvfs2_set_acl(inode, ACL_TYPE_ACCESS, clone); gossip_debug(GOSSIP_ACL_DEBUG, "pvfs2_acl_chmod: pvfs2 set acl " "(access) returned %d\n", error); } posix_acl_release(clone); out: return error; }
static struct inode *orangefs_alloc_inode(struct super_block *sb) { struct orangefs_inode_s *orangefs_inode; orangefs_inode = kmem_cache_alloc(orangefs_inode_cache, GFP_KERNEL); if (orangefs_inode == NULL) { gossip_err("Failed to allocate orangefs_inode\n"); return NULL; } /* * We want to clear everything except for rw_semaphore and the * vfs_inode. */ memset(&orangefs_inode->refn.khandle, 0, 16); orangefs_inode->refn.fs_id = ORANGEFS_FS_ID_NULL; orangefs_inode->last_failed_block_index_read = 0; memset(orangefs_inode->link_target, 0, sizeof(orangefs_inode->link_target)); orangefs_inode->pinode_flags = 0; gossip_debug(GOSSIP_SUPER_DEBUG, "orangefs_alloc_inode: allocated %p\n", &orangefs_inode->vfs_inode); return &orangefs_inode->vfs_inode; }
int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type) { int error; struct iattr iattr; int rc; if (type == ACL_TYPE_ACCESS && acl) { /* * posix_acl_update_mode checks to see if the permissions * described by the ACL can be encoded into the * object's mode. If so, it sets "acl" to NULL * and "mode" to the new desired value. It is up to * us to propagate the new mode back to the server... */ error = posix_acl_update_mode(inode, &iattr.ia_mode, &acl); if (error) { gossip_err("%s: posix_acl_update_mode err: %d\n", __func__, error); return error; } if (acl) { rc = __orangefs_set_acl(inode, acl, type); } else { iattr.ia_valid = ATTR_MODE; rc = orangefs_inode_setattr(inode, &iattr); } return rc; } else { return -EINVAL; } }
static int pvfs2_xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size) { struct posix_acl *acl; int error; /* if we have not been mounted with acl option, ignore this */ if (get_acl_flag(inode) == 0) { gossip_debug(GOSSIP_ACL_DEBUG, "pvfs2_xattr_get_acl: ACL options " "disabled on this FS!\n"); return -EOPNOTSUPP; } acl = pvfs2_get_acl(inode, type); if (IS_ERR(acl)) { error = PTR_ERR(acl); gossip_err("pvfs2_get_acl failed with error %d\n", error); goto out; } if (acl == NULL) { error = -ENODATA; goto out; } error = posix_acl_to_xattr(acl, buffer, size); posix_acl_release(acl); gossip_debug(GOSSIP_ACL_DEBUG, "pvfs2_xattr_get_acl: posix_acl_to_xattr " "returned %d\n", error); out: return error; }
/* PINT_serv_msgpair_array_resolve_addrs() * * fills in BMI address of server for each entry in the msgpair array, * based on the handle and fsid * * returns 0 on success, -PVFS_error on failure */ int PINT_serv_msgpairarray_resolve_addrs( PINT_sm_msgarray_op *mop) { int i = 0; int ret = -PVFS_EINVAL; if ((mop->count > 0) && mop->msgarray) { for(i = 0; i < mop->count; i++) { PINT_sm_msgpair_state *msg_p = &mop->msgarray[i]; assert(msg_p); ret = PINT_cached_config_map_to_server( &msg_p->svr_addr, msg_p->handle, msg_p->fs_id); if (ret != 0) { gossip_err("Failed to map server address to handle\n"); break; } gossip_debug(GOSSIP_MSGPAIR_DEBUG, " mapped handle %llu to server %lld\n", llu(msg_p->handle), lld(msg_p->svr_addr)); } } return ret; }
static PINT_sm_action remove_datafile_remove_failure( struct PINT_smcb *smcb, job_status_s *js_p) { struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT); gossip_err("Error: failed removing one or more datafiles associated with the meta handle %llu\n", llu(sm_p->object_ref.handle)); HANDLE_REMOVE_ERROR("datafile_remove_failure"); return SM_ACTION_COMPLETE; }
static int queues_post(struct PINT_manager_s *manager, PINT_worker_inst *inst, PINT_queue_id id, PINT_operation_t *operation) { struct PINT_worker_queues_s *w; int ret; PINT_worker_id wid; struct PINT_queue_s *queue; PINT_queue_id queue_id; w = &inst->queues; gen_mutex_lock(&w->mutex); if(qlist_empty(&w->queues)) { gossip_err("%s: cannot post an operation without first adding queues " "to the queue worker\n", __func__); gen_mutex_unlock(&w->mutex); return -PVFS_EINVAL; } id_gen_fast_register(&wid, w); /* if the queue_id is zero, then assume that there's * only one queue maintained by this worker and use that */ if(id == 0) { /* a dirty hack to check that the list of queues only has one element */ if(w->queues.next->next != &w->queues) { gossip_err("%s: no queue id was specified and there's more than " "one queue being managed by this worker\n", __func__); gen_mutex_unlock(&w->mutex); return -PVFS_EINVAL; } /* there must be only one queue, so just use that */ queue = qlist_entry(w->queues.next, struct PINT_queue_s, link); queue_id = queue->id; } else {
/* pvfs_bufmap_copy_to_user() * * copies data out of a mapped buffer to a user space address * * returns 0 on success, -errno on failure */ int pvfs_bufmap_copy_to_user(void __user *to, int buffer_index, size_t size) { size_t ret = 0, amt_copied = 0, amt_remaining = 0, cur_copy_size = 0; int from_page_index = 0; void *from_kaddr = NULL; void __user *to_kaddr = to; struct pvfs_bufmap_desc *from = &desc_array[buffer_index]; gossip_debug(GOSSIP_BUFMAP_DEBUG, "pvfs_bufmap_copy_to_user: to %p, from %p, index %d, " "size %zd\n", to, from, buffer_index, size); down_read(&bufmap_init_sem); if (bufmap_init == 0) { gossip_err("pvfs_bufmap_copy_to_user: not yet " "initialized.\n"); gossip_err("pvfs2: please confirm that pvfs2-client daemon is running.\n"); up_read(&bufmap_init_sem); return -EIO; } while(amt_copied < size) { amt_remaining = (size - amt_copied); cur_copy_size = ((amt_remaining > PAGE_SIZE) ? PAGE_SIZE : amt_remaining); from_kaddr = pvfs2_kmap(from->page_array[from_page_index]); ret = copy_to_user(to_kaddr, from_kaddr, cur_copy_size); pvfs2_kunmap(from->page_array[from_page_index]); if (ret) { gossip_debug(GOSSIP_BUFMAP_DEBUG, "Failed to copy data to user space %zd\n", ret); up_read(&bufmap_init_sem); return -EFAULT; } to_kaddr += cur_copy_size; amt_copied += cur_copy_size; from_page_index++; } up_read(&bufmap_init_sem); return 0; }
/* * Perform a miscellaneous operation on a file. */ static long orangefs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int ret = -ENOTTY; __u64 val = 0; unsigned long uval; gossip_debug(GOSSIP_FILE_DEBUG, "orangefs_ioctl: called with cmd %d\n", cmd); /* * we understand some general ioctls on files, such as the immutable * and append flags */ if (cmd == FS_IOC_GETFLAGS) { val = 0; ret = orangefs_inode_getxattr(file_inode(file), ORANGEFS_XATTR_NAME_DEFAULT_PREFIX, "user.pvfs2.meta_hint", &val, sizeof(val)); if (ret < 0 && ret != -ENODATA) return ret; else if (ret == -ENODATA) val = 0; uval = val; gossip_debug(GOSSIP_FILE_DEBUG, "orangefs_ioctl: FS_IOC_GETFLAGS: %llu\n", (unsigned long long)uval); return put_user(uval, (int __user *)arg); } else if (cmd == FS_IOC_SETFLAGS) { ret = 0; if (get_user(uval, (int __user *)arg)) return -EFAULT; /* * ORANGEFS_MIRROR_FL is set internally when the mirroring mode * is turned on for a file. The user is not allowed to turn * on this bit, but the bit is present if the user first gets * the flags and then updates the flags with some new * settings. So, we ignore it in the following edit. bligon. */ if ((uval & ~ORANGEFS_MIRROR_FL) & (~(FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NOATIME_FL))) { gossip_err("orangefs_ioctl: the FS_IOC_SETFLAGS only supports setting one of FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NOATIME_FL\n"); return -EINVAL; } val = uval; gossip_debug(GOSSIP_FILE_DEBUG, "orangefs_ioctl: FS_IOC_SETFLAGS: %llu\n", (unsigned long long)val); ret = orangefs_inode_setxattr(file_inode(file), ORANGEFS_XATTR_NAME_DEFAULT_PREFIX, "user.pvfs2.meta_hint", &val, sizeof(val), 0); } return ret; }
/* perf_update_error() * * cleans up any resources consumed by this state machine and ends * execution of the machine */ static PINT_sm_action perf_update_error( struct PINT_smcb *smcb, job_status_s *js_p) { gossip_err("Error: stopping server performance monitoring.\n"); PINT_perf_finalize(PINT_server_pc); return(server_state_machine_complete(smcb)); }
static int orangefs_setattr_size(struct inode *inode, struct iattr *iattr) { struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); struct orangefs_kernel_op_s *new_op; loff_t orig_size; int ret = -EINVAL; gossip_debug(GOSSIP_INODE_DEBUG, "%s: %pU: Handle is %pU | fs_id %d | size is %llu\n", __func__, get_khandle_from_ino(inode), &orangefs_inode->refn.khandle, orangefs_inode->refn.fs_id, iattr->ia_size); /* Ensure that we have a up to date size, so we know if it changed. */ ret = orangefs_inode_getattr(inode, 0, 1); if (ret == -ESTALE) ret = -EIO; if (ret) { gossip_err("%s: orangefs_inode_getattr failed, ret:%d:.\n", __func__, ret); return ret; } orig_size = i_size_read(inode); truncate_setsize(inode, iattr->ia_size); new_op = op_alloc(ORANGEFS_VFS_OP_TRUNCATE); if (!new_op) return -ENOMEM; new_op->upcall.req.truncate.refn = orangefs_inode->refn; new_op->upcall.req.truncate.size = (__s64) iattr->ia_size; ret = service_operation(new_op, __func__, get_interruptible_flag(inode)); /* * the truncate has no downcall members to retrieve, but * the status value tells us if it went through ok or not */ gossip_debug(GOSSIP_INODE_DEBUG, "orangefs: orangefs_truncate got return value of %d\n", ret); op_release(new_op); if (ret != 0) return ret; if (orig_size != i_size_read(inode)) iattr->ia_valid |= ATTR_CTIME | ATTR_MTIME; return ret; }
/* * op_list_dump() * * dumps the contents of the op list to stderr * * returns 0 on success, -errno on failure */ void op_list_dump(op_list_p olp) { op_list_p tmp_entry = NULL; gossip_err("op_list_dump():\n"); qlist_for_each(tmp_entry, olp) { gossip_print_op(qlist_entry(tmp_entry, struct method_op, op_list_entry)); }
static PINT_sm_action readdir_msg_setup_msgpair( struct PINT_smcb *smcb, job_status_s *js_p) { struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT); int ret = -PVFS_EINVAL; PINT_sm_msgpair_state *msg_p = NULL; gossip_debug(GOSSIP_CLIENT_DEBUG, "readdir state: " "readdir_msg_setup_msgpair\n"); if (js_p->error_code) { return SM_ACTION_COMPLETE; } js_p->error_code = 0; gossip_debug(GOSSIP_READDIR_DEBUG," readdir: posting readdir req\n"); gossip_debug( GOSSIP_READDIR_DEBUG, "%llu|%d | token is %llu | limit is %d\n", llu(sm_p->object_ref.handle), sm_p->object_ref.fs_id, llu(sm_p->readdir.pos_token), sm_p->readdir.dirent_limit); PINT_msgpair_init(&sm_p->msgarray_op); msg_p = &sm_p->msgarray_op.msgpair; PINT_SERVREQ_READDIR_FILL( msg_p->req, *sm_p->cred_p, sm_p->object_ref.fs_id, sm_p->object_ref.handle, sm_p->u.readdir.pos_token, sm_p->u.readdir.dirent_limit, sm_p->hints); msg_p->fs_id = sm_p->object_ref.fs_id; msg_p->handle = sm_p->object_ref.handle; msg_p->retry_flag = PVFS_MSGPAIR_RETRY; msg_p->comp_fn = readdir_msg_comp_fn; ret = PINT_cached_config_map_to_server( &msg_p->svr_addr, sm_p->object_ref.handle, sm_p->object_ref.fs_id); if (ret) { gossip_err("Failed to map meta server address\n"); js_p->error_code = ret; } PINT_sm_push_frame(smcb, 0, &sm_p->msgarray_op); return SM_ACTION_COMPLETE; }
/* socket_collection_init() * * creates a new socket collection. It also acquires the server socket * from the caller if it is available. Passing in a negative value * indicates that this is being used on a client node and there is no * server socket. * * returns a pointer to the collection on success, NULL on failure. */ socket_collection_p BMI_socket_collection_init(int new_server_socket) { struct epoll_event event; socket_collection_p tmp_scp = NULL; int ret = -1; tmp_scp = (struct socket_collection*) malloc(sizeof(struct socket_collection)); if(!tmp_scp) { return(NULL); } memset(tmp_scp, 0, sizeof(struct socket_collection)); tmp_scp->epfd = epoll_create(EPOLL_CREATE_SIZE); if(tmp_scp->epfd < 0) { gossip_err("Error: epoll_create() failure: %s.\n", strerror(errno)); free(tmp_scp); return(NULL); } tmp_scp->server_socket = new_server_socket; if(new_server_socket > -1) { memset(&event, 0, sizeof(event)); event.events = (EPOLLIN|EPOLLERR|EPOLLHUP); event.data.ptr = NULL; ret = epoll_ctl(tmp_scp->epfd, EPOLL_CTL_ADD, new_server_socket, &event); if(ret < 0 && errno != EEXIST) { gossip_err("Error: epoll_ctl() failure: %s.\n", strerror(errno)); free(tmp_scp); return(NULL); } } return (tmp_scp); }
static int pvfs2_xattr_set_acl_default(struct inode *inode, const char *name, const void *buffer, size_t size, int flags) { gossip_debug(GOSSIP_ACL_DEBUG, "pvfs2_xattr_set_acl_default: %s\n", name); if (strcmp(name, "") != 0) { gossip_err("set_acl_default invalid name %s\n", name); return -EINVAL; } return pvfs2_xattr_set_acl(inode, ACL_TYPE_DEFAULT, buffer, size); }
static int __orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type) { int error = 0; void *value = NULL; size_t size = 0; const char *name = NULL; switch (type) { case ACL_TYPE_ACCESS: name = XATTR_NAME_POSIX_ACL_ACCESS; break; case ACL_TYPE_DEFAULT: name = XATTR_NAME_POSIX_ACL_DEFAULT; break; default: gossip_err("%s: invalid type %d!\n", __func__, type); return -EINVAL; } gossip_debug(GOSSIP_ACL_DEBUG, "%s: inode %pU, key %s type %d\n", __func__, get_khandle_from_ino(inode), name, type); if (acl) { size = posix_acl_xattr_size(acl->a_count); value = kmalloc(size, GFP_KERNEL); if (!value) return -ENOMEM; error = posix_acl_to_xattr(&init_user_ns, acl, value, size); if (error < 0) goto out; } gossip_debug(GOSSIP_ACL_DEBUG, "%s: name %s, value %p, size %zd, acl %p\n", __func__, name, value, size, acl); /* * Go ahead and set the extended attribute now. NOTE: Suppose acl * was NULL, then value will be NULL and size will be 0 and that * will xlate to a removexattr. However, we don't want removexattr * complain if attributes does not exist. */ error = orangefs_inode_setxattr(inode, name, value, size, 0); out: kfree(value); if (!error) set_cached_acl(inode, type, acl); return error; }
static int pvfs2_xattr_get_acl_access(struct inode *inode, const char *name, void *buffer, size_t size) { gossip_debug(GOSSIP_ACL_DEBUG, "pvfs2_xattr_get_acl_access %s\n", name); if (strcmp(name, "") != 0) { gossip_err("get_acl_access invalid name %s\n", name); return -EINVAL; } return pvfs2_xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size); }
static PINT_sm_action setattr_msg_setup_msgpair( struct PINT_smcb *smcb, job_status_s *js_p) { struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT); int ret = -PVFS_EINVAL; PINT_sm_msgpair_state *msg_p = NULL; PVFS_ds_type objtype; js_p->error_code = 0; gossip_debug(GOSSIP_CLIENT_DEBUG," setattr: posting setattr req\n"); PINT_msgpair_init(&sm_p->msgarray_op); msg_p = &sm_p->msgarray_op.msgpair; objtype = ((sm_p->u.setattr.sys_attr.mask & PVFS_ATTR_SYS_TYPE) ? sm_p->u.setattr.sys_attr.objtype : PVFS_TYPE_NONE); PINT_SERVREQ_SETATTR_FILL( msg_p->req, *sm_p->cred_p, sm_p->object_ref.fs_id, sm_p->object_ref.handle, objtype, sm_p->u.setattr.sys_attr, 0, sm_p->hints); /* clients should not be able to mess with dfile and distribution * information here. Those parameters should only be set at create time. * Maybe at some point we'll have a utility to adjust those attributes. At * this time if they somehow get changed we'll have garbage on disk */ msg_p->fs_id = sm_p->object_ref.fs_id; msg_p->handle = sm_p->object_ref.handle; msg_p->retry_flag = PVFS_MSGPAIR_RETRY; msg_p->comp_fn = setattr_msg_comp_fn; gossip_debug( GOSSIP_CLIENT_DEBUG, "setattr attr mask sent to server: 0x%x\n", (int)sm_p->u.setattr.sys_attr.mask); ret = PINT_cached_config_map_to_server( &msg_p->svr_addr, msg_p->handle, msg_p->fs_id); if (ret) { gossip_err("Failed to map meta server address\n"); js_p->error_code = ret; } PINT_sm_push_frame(smcb, 0, &sm_p->msgarray_op); return SM_ACTION_COMPLETE; }
int PINT_serv_decode_resp(PVFS_fs_id fs_id, void *encoded_resp_p, struct PINT_decoded_msg *decoded_resp_p, PVFS_BMI_addr_t *svr_addr_p, int actual_resp_sz, struct PVFS_server_resp **resp_out_pp) { int ret = -1, server_type = 0; const char *server_string; ret = PINT_decode(encoded_resp_p, PINT_DECODE_RESP, decoded_resp_p, /* holds data on decoded resp */ *svr_addr_p, actual_resp_sz); if (ret > -1) { *resp_out_pp = (struct PVFS_server_resp *)decoded_resp_p->buffer; if ((*resp_out_pp)->op == PVFS_SERV_PROTO_ERROR) { gossip_err("Error: server does not seem to understand " "the protocol that this client is using.\n"); gossip_err(" Please check server logs for more " "information.\n"); if (fs_id != PVFS_FS_ID_NULL) { server_string = PINT_cached_config_map_addr( fs_id, *svr_addr_p, &server_type); gossip_err(" Server: %s.\n", server_string); } else { gossip_err(" Server: unknown; probably an error " "contacting server listed in pvfs2tab " "file.\n"); } return(-EPROTONOSUPPORT); } } return ret; }