static int pvfs2_check_acl(struct inode *inode, int mask) { struct posix_acl *acl = NULL; gossip_debug(GOSSIP_ACL_DEBUG, "pvfs2_check_acl: called on inode %llu\n", llu(get_handle_from_ino(inode))); acl = pvfs2_get_acl(inode, ACL_TYPE_ACCESS); if (IS_ERR(acl)) { int error = PTR_ERR(acl); gossip_debug(GOSSIP_ACL_DEBUG, "pvfs2_check_acl: pvfs2_get_acl returned error %d\n", error); return error; } if (acl) { int error = posix_acl_permission(inode, acl, mask); posix_acl_release(acl); gossip_debug(GOSSIP_ACL_DEBUG, "pvfs2_check_acl: posix_acl_permission " " (inode %llu, acl %p, mask %x) returned %d\n", llu(get_handle_from_ino(inode)), acl, mask, error); return error; } gossip_debug(GOSSIP_ACL_DEBUG, "pvfs2_check_acl returning EAGAIN\n"); return -EAGAIN; }
int client_state_machine_terminate( struct PINT_smcb *smcb, job_status_s *js_p) { int ret; PINT_client_sm *sm_p; sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT); gossip_debug(GOSSIP_CLIENT_DEBUG, "client_state_machine_terminate smcb %p\n",smcb); if (!((PINT_smcb_op(smcb) == PVFS_SYS_IO) && (PINT_smcb_cancelled(smcb)) && (cancelled_io_jobs_are_pending(smcb))) && !PINT_smcb_immediate_completion(smcb)) { gossip_debug(GOSSIP_CLIENT_DEBUG, "client_state_machine_terminate smcb %p completing\n",smcb); PINT_EVENT_END(PINT_client_sys_event_id, pint_client_pid, NULL, sm_p->event_id, 0); PVFS_hint_free(sm_p->hints); sm_p->hints = NULL; gossip_debug(GOSSIP_CLIENT_DEBUG, "add smcb %p to completion list\n", smcb); ret = add_sm_to_completion_list(smcb); assert(ret == 0); } else { gossip_debug(GOSSIP_CLIENT_DEBUG, "client_state_machine_terminate smcb %p waiting for cancelled jobs\n",smcb); } return SM_ACTION_TERMINATE; }
static int iterate_root_squash_wildcards(struct filesystem_configuration_s *fsconfig, PVFS_BMI_addr_t client_addr) { int i; /* check exceptions first */ for (i = 0; i < fsconfig->root_squash_exceptions_count; i++) { gossip_debug(GOSSIP_SERVER_DEBUG, "BMI_query_addr_range %lld, %s, netmask: %i\n", lld(client_addr), fsconfig->root_squash_exceptions_hosts[i], fsconfig->root_squash_exceptions_netmasks[i]); if (BMI_query_addr_range(client_addr, fsconfig->root_squash_exceptions_hosts[i], fsconfig->root_squash_exceptions_netmasks[i]) == 1) { /* in the exception list, do not squash */ return 0; } } for (i = 0; i < fsconfig->root_squash_count; i++) { gossip_debug(GOSSIP_SERVER_DEBUG, "BMI_query_addr_range %lld, %s, netmask: %i\n", lld(client_addr), fsconfig->root_squash_hosts[i], fsconfig->root_squash_netmasks[i]); if (BMI_query_addr_range(client_addr, fsconfig->root_squash_hosts[i], fsconfig->root_squash_netmasks[i]) == 1) { return 1; } } return 0; }
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; }
static PINT_sm_action replace_datafile_handle( struct PINT_smcb *smcb, job_status_s *js_p) { struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT); int i; PVFS_single_dfile target_handle = s_op->req->u.setattr.attr.u.meta.metafile; gossip_debug(GOSSIP_SERVER_DEBUG,"migration happen: ar_predict_fun->global_forecast_load: 1 \n"); /* print data file handle array*/ for (i = 0; i < s_op->ds_attr.u.metafile.dfile_count; i++){ /* gossip_debug(GOSSIP_LB_DEBUG, */ /* "#%d handle=%llu,old handle: %llu, new handle: %llu\n", */ /* i, */ /* s_op->req->u.setattr.attr.u.meta.dfile_array[i], */ /* target_handle.old, */ /* target_handle.new); */ if (s_op->req->u.setattr.attr.u.meta.dfile_array[i] == target_handle.old){ s_op->req->u.setattr.attr.u.meta.dfile_array[i] = target_handle.new; gossip_debug(GOSSIP_LB_DEBUG, "#Replace %llu with %llu \n\n", target_handle.old, s_op->req->u.setattr.attr.u.meta.dfile_array[i]); break; } }
int pvfs2_mmap_ra_cache_initialize(void) { int ret = -1; if (!MMAP_RA_CACHE_INITIALIZED()) { s_key_to_data_table = qhash_init( hash_key_compare, hash_key, DEFAULT_MMAP_RA_CACHE_HTABLE_SIZE); if (!s_key_to_data_table) { goto return_error; } gossip_debug(GOSSIP_MMAP_RCACHE_DEBUG, "mmap_ra_cache_initialized\n"); ret = 0; } else { gossip_debug(GOSSIP_MMAP_RCACHE_DEBUG, "mmap readahead cache already " "initalized. returning success\n"); ret = 0; } return_error: return ret; }
static int flush_racache(struct inode *inode) { struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); struct orangefs_kernel_op_s *new_op; int ret; gossip_debug(GOSSIP_UTILS_DEBUG, "%s: %pU: Handle is %pU | fs_id %d\n", __func__, get_khandle_from_ino(inode), &orangefs_inode->refn.khandle, orangefs_inode->refn.fs_id); new_op = op_alloc(ORANGEFS_VFS_OP_RA_FLUSH); if (!new_op) return -ENOMEM; new_op->upcall.req.ra_cache_flush.refn = orangefs_inode->refn; ret = service_operation(new_op, "orangefs_flush_racache", get_interruptible_flag(inode)); gossip_debug(GOSSIP_UTILS_DEBUG, "%s: got return value of %d\n", __func__, ret); op_release(new_op); return ret; }
/** Change attributes of an object referenced by dentry. */ int pvfs2_setattr(struct dentry *dentry, struct iattr *iattr) { int ret = -EINVAL; struct inode *inode = dentry->d_inode; gossip_debug(GOSSIP_INODE_DEBUG, "pvfs2_setattr: called on %s\n", dentry->d_name.name); ret = inode_change_ok(inode, iattr); if (ret == 0) { ret = inode_setattr(inode, iattr); gossip_debug(GOSSIP_INODE_DEBUG, "pvfs2_setattr: inode_setattr returned %d\n", ret); if (ret == 0) { ret = pvfs2_inode_setattr(inode, iattr); #if !defined(PVFS2_LINUX_KERNEL_2_4) && defined(HAVE_GENERIC_GETXATTR) && defined(CONFIG_FS_POSIX_ACL) if (!ret && (iattr->ia_valid & ATTR_MODE)) { /* change mod on a file that has ACLs */ ret = pvfs2_acl_chmod(inode); } #endif } } gossip_debug(GOSSIP_INODE_DEBUG, "pvfs2_setattr: returning %d\n", ret); return ret; }
static int orangefs_readpages(struct file *file, struct address_space *mapping, struct list_head *pages, unsigned nr_pages) { int page_idx; int ret; gossip_debug(GOSSIP_INODE_DEBUG, "orangefs_readpages called\n"); for (page_idx = 0; page_idx < nr_pages; page_idx++) { struct page *page; page = list_entry(pages->prev, struct page, lru); list_del(&page->lru); if (!add_to_page_cache(page, mapping, page->index, readahead_gfp_mask(mapping))) { ret = read_one_page(page); gossip_debug(GOSSIP_INODE_DEBUG, "failure adding page to cache, read_one_page returned: %d\n", ret); } else { put_page(page); } } BUG_ON(!list_empty(pages)); return 0; }
int pvfs2_getattr_lite( struct vfsmount *mnt, struct dentry *dentry, struct kstat_lite *kstat_lite) { int ret = -ENOENT; struct inode *inode = dentry->d_inode; uint32_t mask; gossip_debug(GOSSIP_INODE_DEBUG, "pvfs2_getattr_lite: called on %s\n", dentry->d_name.name); /* * ->getattr_lite needs to refresh only certain fields * of the inode and that is indicated by the lite_mask * field of kstat_lite structure. */ mask = convert_to_pvfs2_mask(kstat_lite->lite_mask); ret = pvfs2_inode_getattr(inode, mask); if (ret == 0) { generic_fillattr_lite(inode, kstat_lite); } else { /* assume an I/O error and flag inode as bad */ gossip_debug(GOSSIP_INODE_DEBUG, "%s:%s:%d calling make bad inode\n", __FILE__, __func__, __LINE__); pvfs2_make_bad_inode(inode); } return ret; }
/* * Change attributes of an object referenced by dentry. */ int orangefs_setattr(struct dentry *dentry, struct iattr *iattr) { int ret = -EINVAL; struct inode *inode = dentry->d_inode; gossip_debug(GOSSIP_INODE_DEBUG, "orangefs_setattr: called on %pd\n", dentry); ret = setattr_prepare(dentry, iattr); if (ret) goto out; if (iattr->ia_valid & ATTR_SIZE) { ret = orangefs_setattr_size(inode, iattr); if (ret) goto out; } setattr_copy(inode, iattr); mark_inode_dirty(inode); ret = orangefs_inode_setattr(inode, iattr); gossip_debug(GOSSIP_INODE_DEBUG, "orangefs_setattr: inode_setattr returned %d\n", ret); if (!ret && (iattr->ia_valid & ATTR_MODE)) /* change mod on a file that has ACLs */ ret = posix_acl_chmod(inode, inode->i_mode); out: gossip_debug(GOSSIP_INODE_DEBUG, "orangefs_setattr: returning %d\n", ret); return ret; }
/* * Called to notify the module that there are no more references to * this file (i.e. no processes have it open). * * \note Not called when each file is closed. */ static int orangefs_file_release(struct inode *inode, struct file *file) { gossip_debug(GOSSIP_FILE_DEBUG, "orangefs_file_release: called on %pD\n", file); orangefs_flush_inode(inode); /* * remove all associated inode pages from the page cache and * readahead cache (if any); this forces an expensive refresh of * data for the next caller of mmap (or 'get_block' accesses) */ if (file_inode(file) && file_inode(file)->i_mapping && mapping_nrpages(&file_inode(file)->i_data)) { if (orangefs_features & ORANGEFS_FEATURE_READAHEAD) { gossip_debug(GOSSIP_INODE_DEBUG, "calling flush_racache on %pU\n", get_khandle_from_ino(inode)); flush_racache(inode); gossip_debug(GOSSIP_INODE_DEBUG, "flush_racache finished\n"); } truncate_inode_pages(file_inode(file)->i_mapping, 0); } return 0; }
/* pvfs_bufmap_finalize() * * shuts down the mapped buffer interface and releases any resources * associated with it * * no return value */ void pvfs_bufmap_finalize(void) { int i = 0; gossip_debug(GOSSIP_BUFMAP_DEBUG, "pvfs2_bufmap_finalize: called\n"); down_write(&bufmap_init_sem); if (bufmap_init == 0) { gossip_debug(GOSSIP_BUFMAP_DEBUG, "pvfs2_bufmap_finalize: not yet " "initialized; returning\n"); up_write(&bufmap_init_sem); return; } for(i = 0; i < bufmap_page_count; i++) { pvfs2_clear_page_reserved(bufmap_page_array[i]); page_cache_release(bufmap_page_array[i]); } kfree(bufmap_page_array); bufmap_init = 0; finalize_bufmap_descriptors(); up_write(&bufmap_init_sem); gossip_debug(GOSSIP_BUFMAP_DEBUG, "pvfs2_bufmap_finalize: exiting normally\n"); }
static int pvfs2_create( struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) #endif { int ret = -EINVAL; struct inode *inode = NULL; gossip_debug(GOSSIP_NAME_DEBUG, "pvfs2_create: called\n"); inode = pvfs2_create_entry( dir, dentry, NULL, mode, PVFS2_VFS_OP_CREATE, &ret); if (inode) { pvfs2_inode_t *dir_pinode = PVFS2_I(dir); SetMtimeFlag(dir_pinode); pvfs2_update_inode_time(dir); mark_inode_dirty_sync(dir); ret = 0; } gossip_debug(GOSSIP_NAME_DEBUG, "pvfs2_create: returning %d\n", ret); return ret; }
/* * Change the file pointer position for an instance of an open file. * * \note If .llseek is overriden, we must acquire lock as described in * Documentation/filesystems/Locking. * * Future upgrade could support SEEK_DATA and SEEK_HOLE but would * require much changes to the FS */ static loff_t orangefs_file_llseek(struct file *file, loff_t offset, int origin) { int ret = -EINVAL; struct inode *inode = file_inode(file); if (origin == SEEK_END) { /* * revalidate the inode's file size. * NOTE: We are only interested in file size here, * so we set mask accordingly. */ ret = orangefs_inode_getattr(file->f_mapping->host, 0, 1); if (ret == -ESTALE) ret = -EIO; if (ret) { gossip_debug(GOSSIP_FILE_DEBUG, "%s:%s:%d calling make bad inode\n", __FILE__, __func__, __LINE__); return ret; } } gossip_debug(GOSSIP_FILE_DEBUG, "orangefs_file_llseek: offset is %ld | origin is %d" " | inode size is %lu\n", (long)offset, origin, (unsigned long)i_size_read(inode)); return generic_file_llseek(file, offset, origin); }
/** * 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_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; }
static int orangefs_fill_sb(struct super_block *sb, struct orangefs_fs_mount_response *fs_mount, void *data, int silent) { int ret = -EINVAL; struct inode *root = NULL; struct dentry *root_dentry = NULL; struct orangefs_object_kref root_object; /* alloc and init our private orangefs sb info */ sb->s_fs_info = kzalloc(sizeof(struct orangefs_sb_info_s), GFP_KERNEL); if (!ORANGEFS_SB(sb)) return -ENOMEM; ORANGEFS_SB(sb)->sb = sb; ORANGEFS_SB(sb)->root_khandle = fs_mount->root_khandle; ORANGEFS_SB(sb)->fs_id = fs_mount->fs_id; ORANGEFS_SB(sb)->id = fs_mount->id; if (data) { ret = parse_mount_options(sb, data, silent); if (ret) return ret; } /* Hang the xattr handlers off the superblock */ sb->s_xattr = orangefs_xattr_handlers; sb->s_magic = ORANGEFS_SUPER_MAGIC; sb->s_op = &orangefs_s_ops; sb->s_d_op = &orangefs_dentry_operations; sb->s_blocksize = orangefs_bufmap_size_query(); sb->s_blocksize_bits = orangefs_bufmap_shift_query(); sb->s_maxbytes = MAX_LFS_FILESIZE; root_object.khandle = ORANGEFS_SB(sb)->root_khandle; root_object.fs_id = ORANGEFS_SB(sb)->fs_id; gossip_debug(GOSSIP_SUPER_DEBUG, "get inode %pU, fsid %d\n", &root_object.khandle, root_object.fs_id); root = orangefs_iget(sb, &root_object); if (IS_ERR(root)) return PTR_ERR(root); gossip_debug(GOSSIP_SUPER_DEBUG, "Allocated root inode [%p] with mode %x\n", root, root->i_mode); /* allocates and places root dentry in dcache */ root_dentry = d_make_root(root); if (!root_dentry) return -ENOMEM; sb->s_export_op = &orangefs_export_ops; sb->s_root = root_dentry; return 0; }
/* * 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; }
/* * Remount as initiated by pvfs2-client-core on restart. This is used to * repopulate mount information left from previous pvfs2-client-core. * * the idea here is that given a valid superblock, we're * re-initializing the user space client with the initial mount * information specified when the super block was first initialized. * this is very different than the first initialization/creation of a * superblock. we use the special service_priority_operation to make * sure that the mount gets ahead of any other pending operation that * is waiting for servicing. this means that the pvfs2-client won't * fail to start several times for all other pending operations before * the client regains all of the mount information from us. * NOTE: this function assumes that the request_mutex is already acquired! */ int orangefs_remount(struct orangefs_sb_info_s *orangefs_sb) { struct orangefs_kernel_op_s *new_op; int ret = -EINVAL; gossip_debug(GOSSIP_SUPER_DEBUG, "orangefs_remount: called\n"); new_op = op_alloc(ORANGEFS_VFS_OP_FS_MOUNT); if (!new_op) return -ENOMEM; strncpy(new_op->upcall.req.fs_mount.orangefs_config_server, orangefs_sb->devname, ORANGEFS_MAX_SERVER_ADDR_LEN); gossip_debug(GOSSIP_SUPER_DEBUG, "Attempting ORANGEFS Remount via host %s\n", new_op->upcall.req.fs_mount.orangefs_config_server); /* * we assume that the calling function has already acquired the * request_mutex to prevent other operations from bypassing * this one */ ret = service_operation(new_op, "orangefs_remount", ORANGEFS_OP_PRIORITY | ORANGEFS_OP_NO_MUTEX); gossip_debug(GOSSIP_SUPER_DEBUG, "orangefs_remount: mount got return value of %d\n", ret); if (ret == 0) { /* * store the id assigned to this sb -- it's just a * short-lived mapping that the system interface uses * to map this superblock to a particular mount entry */ orangefs_sb->id = new_op->downcall.resp.fs_mount.id; orangefs_sb->mount_pending = 0; } op_release(new_op); if (orangefs_userspace_version >= 20906) { new_op = op_alloc(ORANGEFS_VFS_OP_FEATURES); if (!new_op) return -ENOMEM; new_op->upcall.req.features.features = 0; ret = service_operation(new_op, "orangefs_features", ORANGEFS_OP_PRIORITY | ORANGEFS_OP_NO_MUTEX); if (!ret) orangefs_features = new_op->downcall.resp.features.features; else orangefs_features = 0; op_release(new_op); } else { orangefs_features = 0; } return ret; }
static int wait_for_a_slot(struct slot_args *slargs, int *buffer_index) { int ret = -1, i = 0; DECLARE_WAITQUEUE(my_wait, current); add_wait_queue_exclusive(slargs->slot_wq, &my_wait); while(1) { set_current_state(TASK_INTERRUPTIBLE); /* check for available desc */ spin_lock(slargs->slot_lock); for(i = 0; i < slargs->slot_count; i++) { if (slargs->slot_array[i] == 0) { slargs->slot_array[i] = 1; *buffer_index = i; ret = 0; break; } } spin_unlock(slargs->slot_lock); /* if we acquired a buffer, then break out of while */ if (ret == 0) { break; } if (!signal_pending(current)) { int timeout = MSECS_TO_JIFFIES(1000 * slot_timeout_secs); gossip_debug(GOSSIP_BUFMAP_DEBUG, "[BUFMAP]: waiting %d seconds for a slot\n", slot_timeout_secs); if (!schedule_timeout(timeout)) { gossip_debug(GOSSIP_BUFMAP_DEBUG, "*** wait_for_a_slot timed out\n"); ret = -ETIMEDOUT; break; } gossip_debug(GOSSIP_BUFMAP_DEBUG, "[BUFMAP]: acquired slot\n"); continue; } gossip_debug(GOSSIP_BUFMAP_DEBUG, "pvfs2: wait_for_a_slot() interrupted.\n"); ret = -EINTR; break; } set_current_state(TASK_RUNNING); remove_wait_queue(slargs->slot_wq, &my_wait); return ret; }
/* * 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; }
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; }
int PVFS_Request_free(PVFS_Request * req) { PVFS_Request reqp; if (req == NULL) { gossip_lerr("PVFS_Request_free: NULL pointer argument\n"); return PVFS_ERR_REQ; } if (*req == NULL) { gossip_lerr("PVFS_Request_free: pointer to NULL pointer argument\n"); return PVFS_ERR_REQ; } if ((*req)->refcount <= 0) { /* if refcount is 0 then it has already been freed */ /* if less than 0 it should not be freed */ /* can't be sure if this is users's variable or not */ gossip_debug(GOSSIP_REQUEST_DEBUG, "don't free special request\n"); return PVFS_SUCCESS; } PINT_REQUEST_REFDEC(*req); if ((*req)->refcount > 0) { /* not ready to free this yet */ *req = NULL; gossip_debug(GOSSIP_REQUEST_DEBUG, "don't free referenced request\n"); return PVFS_SUCCESS; } if (PINT_REQUEST_IS_PACKED(*req)) { /* these are contiguous and have no external refs */ free(*req); *req = NULL; gossip_debug(GOSSIP_REQUEST_DEBUG, "free packed request\n"); return PVFS_SUCCESS; } /* this deals with the sreq chain */ reqp = (*req)->sreq; while (reqp) { PVFS_Request reqp_next; PVFS_Request_free(&(reqp->ereq)); /* this is a little awkward but it works */ reqp_next = reqp->sreq; free(reqp); gossip_debug(GOSSIP_REQUEST_DEBUG, "free sreq linked request\n"); reqp = reqp_next; } /* now deal with the main struct */ PVFS_Request_free(&((*req)->ereq)); free(*req); *req = NULL; gossip_debug(GOSSIP_REQUEST_DEBUG, "free unpacked request\n"); return PVFS_SUCCESS; }
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; }
/* * NOTE: information filled in here is typically reflected in the * output of the system command 'df' */ static int orangefs_statfs(struct dentry *dentry, struct kstatfs *buf) { int ret = -ENOMEM; struct orangefs_kernel_op_s *new_op = NULL; int flags = 0; struct super_block *sb = NULL; sb = dentry->d_sb; gossip_debug(GOSSIP_SUPER_DEBUG, "orangefs_statfs: called on sb %p (fs_id is %d)\n", sb, (int)(ORANGEFS_SB(sb)->fs_id)); new_op = op_alloc(ORANGEFS_VFS_OP_STATFS); if (!new_op) return ret; new_op->upcall.req.statfs.fs_id = ORANGEFS_SB(sb)->fs_id; if (ORANGEFS_SB(sb)->flags & ORANGEFS_OPT_INTR) flags = ORANGEFS_OP_INTERRUPTIBLE; ret = service_operation(new_op, "orangefs_statfs", flags); if (new_op->downcall.status < 0) goto out_op_release; gossip_debug(GOSSIP_SUPER_DEBUG, "%s: got %ld blocks available | " "%ld blocks total | %ld block size | " "%ld files total | %ld files avail\n", __func__, (long)new_op->downcall.resp.statfs.blocks_avail, (long)new_op->downcall.resp.statfs.blocks_total, (long)new_op->downcall.resp.statfs.block_size, (long)new_op->downcall.resp.statfs.files_total, (long)new_op->downcall.resp.statfs.files_avail); buf->f_type = sb->s_magic; memcpy(&buf->f_fsid, &ORANGEFS_SB(sb)->fs_id, sizeof(buf->f_fsid)); buf->f_bsize = new_op->downcall.resp.statfs.block_size; buf->f_namelen = ORANGEFS_NAME_MAX; buf->f_blocks = (sector_t) new_op->downcall.resp.statfs.blocks_total; buf->f_bfree = (sector_t) new_op->downcall.resp.statfs.blocks_avail; buf->f_bavail = (sector_t) new_op->downcall.resp.statfs.blocks_avail; buf->f_files = (sector_t) new_op->downcall.resp.statfs.files_total; buf->f_ffree = (sector_t) new_op->downcall.resp.statfs.files_avail; buf->f_frsize = sb->s_blocksize; out_op_release: op_release(new_op); gossip_debug(GOSSIP_SUPER_DEBUG, "orangefs_statfs: returning %d\n", ret); return ret; }
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 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; }
/* * 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); }
/* 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; }