diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-06 13:33:35 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-06 13:33:35 -0700 |
commit | 3940ee36a0565ea7fb848e3c798afe22efd0b90a (patch) | |
tree | dfcac08aa6d319a0b287c08d9bb76e09a5506c0b | |
parent | 95107b30be68953e3a4f1c3994c2233500502ccf (diff) | |
parent | f60fbdbf41c802e45c03e02ef824772c539ac965 (diff) | |
download | linux-3940ee36a0565ea7fb848e3c798afe22efd0b90a.tar.bz2 |
Merge tag 'for-linus-4.9-ofs1' of git://git.kernel.org/pub/scm/linux/kernel/git/hubcap/linux
Pull orangefs updates from Mike Marshall:
"Miscellaneous improvements:
- clean up debugfs globals
- remove dead code in sysfs
- reorganize duplicated sysfs attribute structs
- consolidate sysfs show and store functions
- remove duplicated sysfs_ops structures
- describe organization of sysfs
- make devreq_mutex static
- g_orangefs_stats -> orangefs_stats for consistency
- rename most remaining global variables
Feature negotiation:
- enable Orangefs userspace and kernel module to negotiate mutually
supported features"
* tag 'for-linus-4.9-ofs1' of git://git.kernel.org/pub/scm/linux/kernel/git/hubcap/linux:
Revert "orangefs: bump minimum userspace version"
orangefs: bump minimum userspace version
orangefs: rename most remaining global variables
orangefs: g_orangefs_stats -> orangefs_stats for consistency
orangefs: make devreq_mutex static
orangefs: describe organization of sysfs
orangefs: remove duplicated sysfs_ops structures
orangefs: consolidate sysfs show and store functions
orangefs: reorganize duplicated sysfs attribute structs
orangefs: remove dead code in sysfs
orangefs: clean up debugfs globals
orangefs: do not allow client readahead cache without feature bit
orangefs: add features op
orangefs: record userspace version for feature compatbility
orangefs: add readahead count and size to sysfs
orangefs: re-add flush_racache from out-of-tree
orangefs: turn param response value into union
orangefs: add missing param request ops
orangefs: rename remaining bits of mmap readahead cache
-rw-r--r-- | fs/orangefs/dcache.c | 2 | ||||
-rw-r--r-- | fs/orangefs/devorangefs-req.c | 164 | ||||
-rw-r--r-- | fs/orangefs/downcall.h | 11 | ||||
-rw-r--r-- | fs/orangefs/file.c | 45 | ||||
-rw-r--r-- | fs/orangefs/namei.c | 8 | ||||
-rw-r--r-- | fs/orangefs/orangefs-cache.c | 6 | ||||
-rw-r--r-- | fs/orangefs/orangefs-debugfs.c | 761 | ||||
-rw-r--r-- | fs/orangefs/orangefs-debugfs.h | 8 | ||||
-rw-r--r-- | fs/orangefs/orangefs-dev-proto.h | 6 | ||||
-rw-r--r-- | fs/orangefs/orangefs-kernel.h | 51 | ||||
-rw-r--r-- | fs/orangefs/orangefs-mod.c | 86 | ||||
-rw-r--r-- | fs/orangefs/orangefs-sysfs.c | 1287 | ||||
-rw-r--r-- | fs/orangefs/orangefs-utils.c | 403 | ||||
-rw-r--r-- | fs/orangefs/protocol.h | 25 | ||||
-rw-r--r-- | fs/orangefs/super.c | 31 | ||||
-rw-r--r-- | fs/orangefs/upcall.h | 18 | ||||
-rw-r--r-- | fs/orangefs/waitqueue.c | 10 |
17 files changed, 1216 insertions, 1706 deletions
diff --git a/fs/orangefs/dcache.c b/fs/orangefs/dcache.c index 00235bf644dc..1e8fe844e69f 100644 --- a/fs/orangefs/dcache.c +++ b/fs/orangefs/dcache.c @@ -73,7 +73,7 @@ static int orangefs_revalidate_lookup(struct dentry *dentry) } } - dentry->d_time = jiffies + dcache_timeout_msecs*HZ/1000; + dentry->d_time = jiffies + orangefs_dcache_timeout_msecs*HZ/1000; ret = 1; out_release_op: op_release(new_op); diff --git a/fs/orangefs/devorangefs-req.c b/fs/orangefs/devorangefs-req.c index a287a66d94e3..516ffb4dc9a0 100644 --- a/fs/orangefs/devorangefs-req.c +++ b/fs/orangefs/devorangefs-req.c @@ -11,14 +11,19 @@ #include "orangefs-kernel.h" #include "orangefs-dev-proto.h" #include "orangefs-bufmap.h" +#include "orangefs-debugfs.h" #include <linux/debugfs.h> #include <linux/slab.h> /* this file implements the /dev/pvfs2-req device node */ +uint32_t orangefs_userspace_version; + static int open_access_count; +static DEFINE_MUTEX(devreq_mutex); + #define DUMP_DEVICE_ERROR() \ do { \ gossip_err("*****************************************************\n");\ @@ -43,7 +48,7 @@ static void orangefs_devreq_add_op(struct orangefs_kernel_op_s *op) { int index = hash_func(op->tag, hash_table_size); - list_add_tail(&op->list, &htable_ops_in_progress[index]); + list_add_tail(&op->list, &orangefs_htable_ops_in_progress[index]); } /* @@ -57,20 +62,20 @@ static struct orangefs_kernel_op_s *orangefs_devreq_remove_op(__u64 tag) index = hash_func(tag, hash_table_size); - spin_lock(&htable_ops_in_progress_lock); + spin_lock(&orangefs_htable_ops_in_progress_lock); list_for_each_entry_safe(op, next, - &htable_ops_in_progress[index], + &orangefs_htable_ops_in_progress[index], list) { if (op->tag == tag && !op_state_purged(op) && !op_state_given_up(op)) { list_del_init(&op->list); - spin_unlock(&htable_ops_in_progress_lock); + spin_unlock(&orangefs_htable_ops_in_progress_lock); return op; } } - spin_unlock(&htable_ops_in_progress_lock); + spin_unlock(&orangefs_htable_ops_in_progress_lock); return NULL; } @@ -276,11 +281,11 @@ restart: if (ret != 0) goto error; - spin_lock(&htable_ops_in_progress_lock); + spin_lock(&orangefs_htable_ops_in_progress_lock); spin_lock(&cur_op->lock); if (unlikely(op_state_given_up(cur_op))) { spin_unlock(&cur_op->lock); - spin_unlock(&htable_ops_in_progress_lock); + spin_unlock(&orangefs_htable_ops_in_progress_lock); complete(&cur_op->waitq); goto restart; } @@ -298,7 +303,7 @@ restart: current->comm); orangefs_devreq_add_op(cur_op); spin_unlock(&cur_op->lock); - spin_unlock(&htable_ops_in_progress_lock); + spin_unlock(&orangefs_htable_ops_in_progress_lock); /* The client only asks to read one size buffer. */ return MAX_DEV_REQ_UPSIZE; @@ -387,6 +392,13 @@ static ssize_t orangefs_devreq_write_iter(struct kiocb *iocb, return -EPROTO; } + if (!orangefs_userspace_version) { + orangefs_userspace_version = head.version; + } else if (orangefs_userspace_version != head.version) { + gossip_err("Error: userspace version changes\n"); + return -EPROTO; + } + /* remove the op from the in progress hash table */ op = orangefs_devreq_remove_op(head.tag); if (!op) { @@ -527,6 +539,7 @@ static int orangefs_devreq_release(struct inode *inode, struct file *file) gossip_debug(GOSSIP_DEV_DEBUG, "pvfs2-client-core: device close complete\n"); open_access_count = 0; + orangefs_userspace_version = 0; mutex_unlock(&devreq_mutex); return 0; } @@ -576,8 +589,6 @@ static long dispatch_ioctl_command(unsigned int command, unsigned long arg) static __s32 max_down_size = MAX_DEV_REQ_DOWNSIZE; struct ORANGEFS_dev_map_desc user_desc; int ret = 0; - struct dev_mask_info_s mask_info = { 0 }; - struct dev_mask2_info_s mask2_info = { 0, 0 }; int upstream_kmod = 1; struct orangefs_sb_info_s *orangefs_sb; @@ -619,7 +630,7 @@ static long dispatch_ioctl_command(unsigned int command, unsigned long arg) * all of the remounts are serviced (to avoid ops between * mounts to fail) */ - ret = mutex_lock_interruptible(&request_mutex); + ret = mutex_lock_interruptible(&orangefs_request_mutex); if (ret < 0) return ret; gossip_debug(GOSSIP_DEV_DEBUG, @@ -654,7 +665,7 @@ static long dispatch_ioctl_command(unsigned int command, unsigned long arg) gossip_debug(GOSSIP_DEV_DEBUG, "%s: priority remount complete\n", __func__); - mutex_unlock(&request_mutex); + mutex_unlock(&orangefs_request_mutex); return ret; case ORANGEFS_DEV_UPSTREAM: @@ -668,134 +679,11 @@ static long dispatch_ioctl_command(unsigned int command, unsigned long arg) return ret; case ORANGEFS_DEV_CLIENT_MASK: - ret = copy_from_user(&mask2_info, - (void __user *)arg, - sizeof(struct dev_mask2_info_s)); - - if (ret != 0) - return -EIO; - - client_debug_mask.mask1 = mask2_info.mask1_value; - client_debug_mask.mask2 = mask2_info.mask2_value; - - pr_info("%s: client debug mask has been been received " - ":%llx: :%llx:\n", - __func__, - (unsigned long long)client_debug_mask.mask1, - (unsigned long long)client_debug_mask.mask2); - - return ret; - + return orangefs_debugfs_new_client_mask((void __user *)arg); case ORANGEFS_DEV_CLIENT_STRING: - ret = copy_from_user(&client_debug_array_string, - (void __user *)arg, - ORANGEFS_MAX_DEBUG_STRING_LEN); - /* - * The real client-core makes an effort to ensure - * that actual strings that aren't too long to fit in - * this buffer is what we get here. We're going to use - * string functions on the stuff we got, so we'll make - * this extra effort to try and keep from - * flowing out of this buffer when we use the string - * functions, even if somehow the stuff we end up - * with here is garbage. - */ - client_debug_array_string[ORANGEFS_MAX_DEBUG_STRING_LEN - 1] = - '\0'; - - if (ret != 0) { - pr_info("%s: CLIENT_STRING: copy_from_user failed\n", - __func__); - return -EIO; - } - - pr_info("%s: client debug array string has been received.\n", - __func__); - - if (!help_string_initialized) { - - /* Free the "we don't know yet" default string... */ - kfree(debug_help_string); - - /* build a proper debug help string */ - if (orangefs_prepare_debugfs_help_string(0)) { - gossip_err("%s: no debug help string \n", - __func__); - return -EIO; - } - - /* Replace the boilerplate boot-time debug-help file. */ - debugfs_remove(help_file_dentry); - - help_file_dentry = - debugfs_create_file( - ORANGEFS_KMOD_DEBUG_HELP_FILE, - 0444, - debug_dir, - debug_help_string, - &debug_help_fops); - - if (!help_file_dentry) { - gossip_err("%s: debugfs_create_file failed for" - " :%s:!\n", - __func__, - ORANGEFS_KMOD_DEBUG_HELP_FILE); - return -EIO; - } - } - - debug_mask_to_string(&client_debug_mask, 1); - - debugfs_remove(client_debug_dentry); - - orangefs_client_debug_init(); - - help_string_initialized++; - - return ret; - + return orangefs_debugfs_new_client_string((void __user *)arg); case ORANGEFS_DEV_DEBUG: - ret = copy_from_user(&mask_info, - (void __user *)arg, - sizeof(mask_info)); - - if (ret != 0) - return -EIO; - - if (mask_info.mask_type == KERNEL_MASK) { - if ((mask_info.mask_value == 0) - && (kernel_mask_set_mod_init)) { - /* - * the kernel debug mask was set when the - * kernel module was loaded; don't override - * it if the client-core was started without - * a value for ORANGEFS_KMODMASK. - */ - return 0; - } - debug_mask_to_string(&mask_info.mask_value, - mask_info.mask_type); - gossip_debug_mask = mask_info.mask_value; - pr_info("%s: kernel debug mask has been modified to " - ":%s: :%llx:\n", - __func__, - kernel_debug_string, - (unsigned long long)gossip_debug_mask); - } else if (mask_info.mask_type == CLIENT_MASK) { - debug_mask_to_string(&mask_info.mask_value, - mask_info.mask_type); - pr_info("%s: client debug mask has been modified to" - ":%s: :%llx:\n", - __func__, - client_debug_string, - llu(mask_info.mask_value)); - } else { - gossip_lerr("Invalid mask type....\n"); - return -EINVAL; - } - - return ret; - + return orangefs_debugfs_new_debug((void __user *)arg); default: return -ENOIOCTLCMD; } diff --git a/fs/orangefs/downcall.h b/fs/orangefs/downcall.h index 66b99210f1f9..3b8923f8bf21 100644 --- a/fs/orangefs/downcall.h +++ b/fs/orangefs/downcall.h @@ -83,7 +83,10 @@ struct orangefs_listxattr_response { }; struct orangefs_param_response { - __s64 value; + union { + __s64 value64; + __s32 value32[2]; + } u; }; #define PERF_COUNT_BUF_SIZE 4096 @@ -98,6 +101,11 @@ struct orangefs_fs_key_response { char fs_key[FS_KEY_BUF_SIZE]; }; +/* 2.9.6 */ +struct orangefs_features_response { + __u64 features; +}; + struct orangefs_downcall_s { __s32 type; __s32 status; @@ -119,6 +127,7 @@ struct orangefs_downcall_s { struct orangefs_param_response param; struct orangefs_perf_count_response perf_count; struct orangefs_fs_key_response fs_key; + struct orangefs_features_response features; } resp; }; diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c index 526040e09f78..3386886596d6 100644 --- a/fs/orangefs/file.c +++ b/fs/orangefs/file.c @@ -14,6 +14,32 @@ #include <linux/fs.h> #include <linux/pagemap.h> +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; +} + /* * Copy to client-core's address space from the buffers specified * by the iovec upto total_size bytes. @@ -386,7 +412,7 @@ ssize_t orangefs_inode_read(struct inode *inode, size_t bufmap_size; ssize_t ret = -EINVAL; - g_orangefs_stats.reads++; + orangefs_stats.reads++; bufmap_size = orangefs_bufmap_size_query(); if (count > bufmap_size) { @@ -427,7 +453,7 @@ static ssize_t orangefs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter gossip_debug(GOSSIP_FILE_DEBUG, "orangefs_file_read_iter\n"); - g_orangefs_stats.reads++; + orangefs_stats.reads++; rc = do_readv_writev(ORANGEFS_IO_READ, file, &pos, iter); iocb->ki_pos = pos; @@ -488,7 +514,7 @@ static ssize_t orangefs_file_write_iter(struct kiocb *iocb, struct iov_iter *ite } iocb->ki_pos = pos; - g_orangefs_stats.writes++; + orangefs_stats.writes++; out: @@ -591,15 +617,24 @@ static int orangefs_file_release(struct inode *inode, struct file *file) orangefs_flush_inode(inode); /* - * remove all associated inode pages from the page cache and mmap + * 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->f_path.dentry->d_inode && file->f_path.dentry->d_inode->i_mapping && - mapping_nrpages(&file->f_path.dentry->d_inode->i_data)) + mapping_nrpages(&file->f_path.dentry->d_inode->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->f_path.dentry->d_inode->i_mapping, 0); + } return 0; } diff --git a/fs/orangefs/namei.c b/fs/orangefs/namei.c index 62c525936ee8..35269e31de92 100644 --- a/fs/orangefs/namei.c +++ b/fs/orangefs/namei.c @@ -72,7 +72,7 @@ static int orangefs_create(struct inode *dir, d_instantiate(dentry, inode); unlock_new_inode(inode); - dentry->d_time = jiffies + dcache_timeout_msecs*HZ/1000; + dentry->d_time = jiffies + orangefs_dcache_timeout_msecs*HZ/1000; ORANGEFS_I(inode)->getattr_time = jiffies - 1; gossip_debug(GOSSIP_NAME_DEBUG, @@ -183,7 +183,7 @@ static struct dentry *orangefs_lookup(struct inode *dir, struct dentry *dentry, goto out; } - dentry->d_time = jiffies + dcache_timeout_msecs*HZ/1000; + dentry->d_time = jiffies + orangefs_dcache_timeout_msecs*HZ/1000; inode = orangefs_iget(dir->i_sb, &new_op->downcall.resp.lookup.refn); if (IS_ERR(inode)) { @@ -322,7 +322,7 @@ static int orangefs_symlink(struct inode *dir, d_instantiate(dentry, inode); unlock_new_inode(inode); - dentry->d_time = jiffies + dcache_timeout_msecs*HZ/1000; + dentry->d_time = jiffies + orangefs_dcache_timeout_msecs*HZ/1000; ORANGEFS_I(inode)->getattr_time = jiffies - 1; gossip_debug(GOSSIP_NAME_DEBUG, @@ -386,7 +386,7 @@ static int orangefs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode d_instantiate(dentry, inode); unlock_new_inode(inode); - dentry->d_time = jiffies + dcache_timeout_msecs*HZ/1000; + dentry->d_time = jiffies + orangefs_dcache_timeout_msecs*HZ/1000; ORANGEFS_I(inode)->getattr_time = jiffies - 1; gossip_debug(GOSSIP_NAME_DEBUG, diff --git a/fs/orangefs/orangefs-cache.c b/fs/orangefs/orangefs-cache.c index b6edbe9fb309..aa3830b741c7 100644 --- a/fs/orangefs/orangefs-cache.c +++ b/fs/orangefs/orangefs-cache.c @@ -73,8 +73,8 @@ char *get_opname_string(struct orangefs_kernel_op_s *new_op) return "OP_STATFS"; else if (type == ORANGEFS_VFS_OP_TRUNCATE) return "OP_TRUNCATE"; - else if (type == ORANGEFS_VFS_OP_MMAP_RA_FLUSH) - return "OP_MMAP_RA_FLUSH"; + else if (type == ORANGEFS_VFS_OP_RA_FLUSH) + return "OP_RA_FLUSH"; else if (type == ORANGEFS_VFS_OP_FS_MOUNT) return "OP_FS_MOUNT"; else if (type == ORANGEFS_VFS_OP_FS_UMOUNT) @@ -97,6 +97,8 @@ char *get_opname_string(struct orangefs_kernel_op_s *new_op) return "OP_FSYNC"; else if (type == ORANGEFS_VFS_OP_FSKEY) return "OP_FSKEY"; + else if (type == ORANGEFS_VFS_OP_FEATURES) + return "OP_FEATURES"; } return "OP_UNKNOWN?"; } diff --git a/fs/orangefs/orangefs-debugfs.c b/fs/orangefs/orangefs-debugfs.c index 1714a737d556..9b24107c82a8 100644 --- a/fs/orangefs/orangefs-debugfs.c +++ b/fs/orangefs/orangefs-debugfs.c @@ -43,36 +43,35 @@ #include "protocol.h" #include "orangefs-kernel.h" -static int orangefs_debug_disabled = 1; - -static int orangefs_debug_help_open(struct inode *, struct file *); +#define DEBUG_HELP_STRING_SIZE 4096 +#define HELP_STRING_UNINITIALIZED \ + "Client Debug Keywords are unknown until the first time\n" \ + "the client is started after boot.\n" +#define ORANGEFS_KMOD_DEBUG_HELP_FILE "debug-help" +#define ORANGEFS_KMOD_DEBUG_FILE "kernel-debug" +#define ORANGEFS_CLIENT_DEBUG_FILE "client-debug" +#define ORANGEFS_VERBOSE "verbose" +#define ORANGEFS_ALL "all" -const struct file_operations debug_help_fops = { - .open = orangefs_debug_help_open, - .read = seq_read, - .release = seq_release, - .llseek = seq_lseek, +/* + * An array of client_debug_mask will be built to hold debug keyword/mask + * values fetched from userspace. + */ +struct client_debug_mask { + char *keyword; + __u64 mask1; + __u64 mask2; }; +static int orangefs_kernel_debug_init(void); + +static int orangefs_debug_help_open(struct inode *, struct file *); static void *help_start(struct seq_file *, loff_t *); static void *help_next(struct seq_file *, void *, loff_t *); static void help_stop(struct seq_file *, void *); static int help_show(struct seq_file *, void *); -static const struct seq_operations help_debug_ops = { - .start = help_start, - .next = help_next, - .stop = help_stop, - .show = help_show, -}; - -/* - * Used to protect data in ORANGEFS_KMOD_DEBUG_FILE and - * ORANGEFS_KMOD_DEBUG_FILE. - */ -static DEFINE_MUTEX(orangefs_debug_lock); - -int orangefs_debug_open(struct inode *, struct file *); +static int orangefs_debug_open(struct inode *, struct file *); static ssize_t orangefs_debug_read(struct file *, char __user *, @@ -84,6 +83,43 @@ static ssize_t orangefs_debug_write(struct file *, size_t, loff_t *); +static int orangefs_prepare_cdm_array(char *); +static void debug_mask_to_string(void *, int); +static void do_k_string(void *, int); +static void do_c_string(void *, int); +static int keyword_is_amalgam(char *); +static int check_amalgam_keyword(void *, int); +static void debug_string_to_mask(char *, void *, int); +static void do_c_mask(int, char *, struct client_debug_mask **); +static void do_k_mask(int, char *, __u64 **); + +static char kernel_debug_string[ORANGEFS_MAX_DEBUG_STRING_LEN] = "none"; +static char *debug_help_string; +static char client_debug_string[ORANGEFS_MAX_DEBUG_STRING_LEN]; +static char client_debug_array_string[ORANGEFS_MAX_DEBUG_STRING_LEN]; + +static struct dentry *help_file_dentry; +static struct dentry *client_debug_dentry; +static struct dentry *debug_dir; + +static unsigned int kernel_mask_set_mod_init; +static int orangefs_debug_disabled = 1; +static int help_string_initialized; + +static const struct seq_operations help_debug_ops = { + .start = help_start, + .next = help_next, + .stop = help_stop, + .show = help_show, +}; + +const struct file_operations debug_help_fops = { + .open = orangefs_debug_help_open, + .read = seq_read, + .release = seq_release, + .llseek = seq_lseek, +}; + static const struct file_operations kernel_debug_fops = { .open = orangefs_debug_open, .read = orangefs_debug_read, @@ -91,15 +127,55 @@ static const struct file_operations kernel_debug_fops = { .llseek = generic_file_llseek, }; +static int client_all_index; +static int client_verbose_index; + +static struct client_debug_mask *cdm_array; +static int cdm_element_count; + +static struct client_debug_mask client_debug_mask; + +/* + * Used to protect data in ORANGEFS_KMOD_DEBUG_FILE and + * ORANGEFS_KMOD_DEBUG_FILE. + */ +static DEFINE_MUTEX(orangefs_debug_lock); + /* * initialize kmod debug operations, create orangefs debugfs dir and * ORANGEFS_KMOD_DEBUG_HELP_FILE. */ -int orangefs_debugfs_init(void) +int orangefs_debugfs_init(int debug_mask) { - int rc = -ENOMEM; + /* convert input debug mask to a 64-bit unsigned integer */ + orangefs_gossip_debug_mask = (unsigned long long)debug_mask; + + /* + * set the kernel's gossip debug string; invalid mask values will + * be ignored. + */ + debug_mask_to_string(&orangefs_gossip_debug_mask, 0); + + /* remove any invalid values from the mask */ + debug_string_to_mask(kernel_debug_string, &orangefs_gossip_debug_mask, + 0); + + /* + * if the mask has a non-zero value, then indicate that the mask + * was set when the kernel module was loaded. The orangefs dev ioctl + * command will look at this boolean to determine if the kernel's + * debug mask should be overwritten when the client-core is started. + */ + if (orangefs_gossip_debug_mask != 0) + kernel_mask_set_mod_init = true; + + pr_info("%s: called with debug mask: :%s: :%llx:\n", + __func__, + kernel_debug_string, + (unsigned long long)orangefs_gossip_debug_mask); + debug_dir = debugfs_create_dir("orangefs", NULL); if (!debug_dir) { pr_info("%s: debugfs_create_dir failed.\n", __func__); @@ -117,13 +193,58 @@ int orangefs_debugfs_init(void) } orangefs_debug_disabled = 0; + + rc = orangefs_kernel_debug_init(); + +out: + + return rc; +} + +/* + * initialize the kernel-debug file. + */ +static int orangefs_kernel_debug_init(void) +{ + int rc = -ENOMEM; + struct dentry *ret; + char *k_buffer = NULL; + + gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__); + + k_buffer = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL); + if (!k_buffer) + goto out; + + if (strlen(kernel_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) { + strcpy(k_buffer, kernel_debug_string); + strcat(k_buffer, "\n"); + } else { + strcpy(k_buffer, "none\n"); + pr_info("%s: overflow 1!\n", __func__); + } + + ret = debugfs_create_file(ORANGEFS_KMOD_DEBUG_FILE, + 0444, + debug_dir, + k_buffer, + &kernel_debug_fops); + if (!ret) { + pr_info("%s: failed to create %s.\n", + __func__, + ORANGEFS_KMOD_DEBUG_FILE); + goto out; + } + rc = 0; out: + gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: rc:%d:\n", __func__, rc); return rc; } + void orangefs_debugfs_cleanup(void) { debugfs_remove_recursive(debug_dir); @@ -196,49 +317,6 @@ static int help_show(struct seq_file *m, void *v) } /* - * initialize the kernel-debug file. - */ -int orangefs_kernel_debug_init(void) -{ - int rc = -ENOMEM; - struct dentry *ret; - char *k_buffer = NULL; - - gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__); - - k_buffer = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL); - if (!k_buffer) - goto out; - - if (strlen(kernel_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) { - strcpy(k_buffer, kernel_debug_string); - strcat(k_buffer, "\n"); - } else { - strcpy(k_buffer, "none\n"); - pr_info("%s: overflow 1!\n", __func__); - } - - ret = debugfs_create_file(ORANGEFS_KMOD_DEBUG_FILE, - 0444, - debug_dir, - k_buffer, - &kernel_debug_fops); - if (!ret) { - pr_info("%s: failed to create %s.\n", - __func__, - ORANGEFS_KMOD_DEBUG_FILE); - goto out; - } - - rc = 0; - -out: - - gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: rc:%d:\n", __func__, rc); - return rc; -} - -/* * initialize the client-debug file. */ int orangefs_client_debug_init(void) @@ -282,7 +360,7 @@ out: } /* open ORANGEFS_KMOD_DEBUG_FILE or ORANGEFS_CLIENT_DEBUG_FILE.*/ -int orangefs_debug_open(struct inode *inode, struct file *file) +static int orangefs_debug_open(struct inode *inode, struct file *file) { int rc = -ENODEV; @@ -384,8 +462,8 @@ static ssize_t orangefs_debug_write(struct file *file, */ if (!strcmp(file->f_path.dentry->d_name.name, ORANGEFS_KMOD_DEBUG_FILE)) { - debug_string_to_mask(buf, &gossip_debug_mask, 0); - debug_mask_to_string(&gossip_debug_mask, 0); + debug_string_to_mask(buf, &orangefs_gossip_debug_mask, 0); + debug_mask_to_string(&orangefs_gossip_debug_mask, 0); debug_string = kernel_debug_string; gossip_debug(GOSSIP_DEBUGFS_DEBUG, "New kernel debug string is %s\n", @@ -452,3 +530,546 @@ out: kfree(buf); return rc; } + +/* + * After obtaining a string representation of the client's debug + * keywords and their associated masks, this function is called to build an + * array of these values. + */ +static int orangefs_prepare_cdm_array(char *debug_array_string) +{ + int i; + int rc = -EINVAL; + char *cds_head = NULL; + char *cds_delimiter = NULL; + int keyword_len = 0; + + gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); + + /* + * figure out how many elements the cdm_array needs. + */ + for (i = 0; i < strlen(debug_array_string); i++) + if (debug_array_string[i] == '\n') + cdm_element_count++; + + if (!cdm_element_count) { + pr_info("No elements in client debug array string!\n"); + goto out; + } + + cdm_array = + kzalloc(cdm_element_count * sizeof(struct client_debug_mask), + GFP_KERNEL); + if (!cdm_array) { + pr_info("malloc failed for cdm_array!\n"); + rc = -ENOMEM; + goto out; + } + + cds_head = debug_array_string; + + for (i = 0; i < cdm_element_count; i++) { + cds_delimiter = strchr(cds_head, '\n'); + *cds_delimiter = '\0'; + + keyword_len = strcspn(cds_head, " "); + + cdm_array[i].keyword = kzalloc(keyword_len + 1, GFP_KERNEL); + if (!cdm_array[i].keyword) { + rc = -ENOMEM; + goto out; + } + + sscanf(cds_head, + "%s %llx %llx", + cdm_array[i].keyword, + (unsigned long long *)&(cdm_array[i].mask1), + (unsigned long long *)&(cdm_array[i].mask2)); + + if (!strcmp(cdm_array[i].keyword, ORANGEFS_VERBOSE)) + client_verbose_index = i; + + if (!strcmp(cdm_array[i].keyword, ORANGEFS_ALL)) + client_all_index = i; + + cds_head = cds_delimiter + 1; + } + + rc = cdm_element_count; + + gossip_debug(GOSSIP_UTILS_DEBUG, "%s: rc:%d:\n", __func__, rc); + +out: + + return rc; + +} + +/* + * /sys/kernel/debug/orangefs/debug-help can be catted to + * see all the available kernel and client debug keywords. + * + * When the kernel boots, we have no idea what keywords the + * client supports, nor their associated masks. + * + * We pass through this function once at boot and stamp a + * boilerplate "we don't know" message for the client in the + * debug-help file. We pass through here again when the client + * starts and then we can fill out the debug-help file fully. + * + * The client might be restarted any number of times between + * reboots, we only build the debug-help file the first time. + */ +int orangefs_prepare_debugfs_help_string(int at_boot) +{ + int rc = -EINVAL; + int i; + int byte_count = 0; + char *client_title = "Client Debug Keywords:\n"; + char *kernel_title = "Kernel Debug Keywords:\n"; + + gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); + + if (at_boot) { + byte_count += strlen(HELP_STRING_UNINITIALIZED); + client_title = HELP_STRING_UNINITIALIZED; + } else { + /* + * fill the client keyword/mask array and remember + * how many elements there were. + */ + cdm_element_count = + orangefs_prepare_cdm_array(client_debug_array_string); + if (cdm_element_count <= 0) + goto out; + + /* Count the bytes destined for debug_help_string. */ + byte_count += strlen(client_title); + + for (i = 0; i < cdm_element_count; i++) { + byte_count += strlen(cdm_array[i].keyword + 2); + if (byte_count >= DEBUG_HELP_STRING_SIZE) { + pr_info("%s: overflow 1!\n", __func__); + goto out; + } + } + + gossip_debug(GOSSIP_UTILS_DEBUG, + "%s: cdm_element_count:%d:\n", + __func__, + cdm_element_count); + } + + byte_count += strlen(kernel_title); + for (i = 0; i < num_kmod_keyword_mask_map; i++) { + byte_count += + strlen(s_kmod_keyword_mask_map[i].keyword + 2); + if (byte_count >= DEBUG_HELP_STRING_SIZE) { + pr_info("%s: overflow 2!\n", __func__); + goto out; + } + } + + /* build debug_help_string. */ + debug_help_string = kzalloc(DEBUG_HELP_STRING_SIZE, GFP_KERNEL); + if (!debug_help_string) { + rc = -ENOMEM; + goto out; + } + + strcat(debug_help_string, client_title); + + if (!at_boot) { + for (i = 0; i < cdm_element_count; i++) { + strcat(debug_help_string, "\t"); + strcat(debug_help_string, cdm_array[i].keyword); + strcat(debug_help_string, "\n"); + } + } + + strcat(debug_help_string, "\n"); + strcat(debug_help_string, kernel_title); + + for (i = 0; i < num_kmod_keyword_mask_map; i++) { + strcat(debug_help_string, "\t"); + strcat(debug_help_string, s_kmod_keyword_mask_map[i].keyword); + strcat(debug_help_string, "\n"); + } + + rc = 0; + +out: + + return rc; + +} + +/* + * kernel = type 0 + * client = type 1 + */ +static void debug_mask_to_string(void *mask, int type) +{ + int i; + int len = 0; + char *debug_string; + int element_count = 0; + + gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); + + if (type) { + debug_string = client_debug_string; + element_count = cdm_element_count; + } else { + debug_string = kernel_debug_string; + element_count = num_kmod_keyword_mask_map; + } + + memset(debug_string, 0, ORANGEFS_MAX_DEBUG_STRING_LEN); + + /* + * Some keywords, like "all" or "verbose", are amalgams of + * numerous other keywords. Make a special check for those + * before grinding through the whole mask only to find out + * later... + */ + if (check_amalgam_keyword(mask, type)) + goto out; + + /* Build the debug string. */ + for (i = 0; i < element_count; i++) + if (type) + do_c_string(mask, i); + else + do_k_string(mask, i); + + len = strlen(debug_string); + + if ((len) && (type)) + client_debug_string[len - 1] = '\0'; + else if (len) + kernel_debug_string[len - 1] = '\0'; + else if (type) + strcpy(client_debug_string, "none"); + else + strcpy(kernel_debug_string, "none"); + +out: +gossip_debug(GOSSIP_UTILS_DEBUG, "%s: string:%s:\n", __func__, debug_string); + + return; + +} + +static void do_k_string(void *k_mask, int index) +{ + __u64 *mask = (__u64 *) k_mask; + + if (keyword_is_amalgam((char *) s_kmod_keyword_mask_map[index].keyword)) + goto out; + + if (*mask & s_kmod_keyword_mask_map[index].mask_val) { + if ((strlen(kernel_debug_string) + + strlen(s_kmod_keyword_mask_map[index].keyword)) + < ORANGEFS_MAX_DEBUG_STRING_LEN - 1) { + strcat(kernel_debug_string, + s_kmod_keyword_mask_map[index].keyword); + strcat(kernel_debug_string, ","); + } else { + gossip_err("%s: overflow!\n", __func__); + strcpy(kernel_debug_string, ORANGEFS_ALL); + goto out; + } + } + +out: + + return; +} + +static void do_c_string(void *c_mask, int index) +{ + struct client_debug_mask *mask = (struct client_debug_mask *) c_mask; + + if (keyword_is_amalgam(cdm_array[index].keyword)) + goto out; + + if ((mask->mask1 & cdm_array[index].mask1) || + (mask->mask2 & cdm_array[index].mask2)) { + if ((strlen(client_debug_string) + + strlen(cdm_array[index].keyword) + 1) + < ORANGEFS_MAX_DEBUG_STRING_LEN - 2) { + strcat(client_debug_string, + cdm_array[index].keyword); + strcat(client_debug_string, ","); + } else { + gossip_err("%s: overflow!\n", __func__); + strcpy(client_debug_string, ORANGEFS_ALL); + goto out; + } + } +out: + return; +} + +static int keyword_is_amalgam(char *keyword) +{ + int rc = 0; + + if ((!strcmp(keyword, ORANGEFS_ALL)) || (!strcmp(keyword, ORANGEFS_VERBOSE))) + rc = 1; + + return rc; +} + +/* + * kernel = type 0 + * client = type 1 + * + * return 1 if we found an amalgam. + */ +static int check_amalgam_keyword(void *mask, int type) +{ + __u64 *k_mask; + struct client_debug_mask *c_mask; + int k_all_index = num_kmod_keyword_mask_map - 1; + int rc = 0; + + if (type) { + c_mask = (struct client_debug_mask *) mask; + + if ((c_mask->mask1 == cdm_array[client_all_index].mask1) && + (c_mask->mask2 == cdm_array[client_all_index].mask2)) { + strcpy(client_debug_string, ORANGEFS_ALL); + rc = 1; + goto out; + } + + if ((c_mask->mask1 == cdm_array[client_verbose_index].mask1) && + (c_mask->mask2 == cdm_array[client_verbose_index].mask2)) { + strcpy(client_debug_string, ORANGEFS_VERBOSE); + rc = 1; + goto out; + } + + } else { + k_mask = (__u64 *) mask; + + if (*k_mask >= s_kmod_keyword_mask_map[k_all_index].mask_val) { + strcpy(kernel_debug_string, ORANGEFS_ALL); + rc = 1; + goto out; + } + } + +out: + + return rc; +} + +/* + * kernel = type 0 + * client = type 1 + */ +static void debug_string_to_mask(char *debug_string, void *mask, int type) +{ + char *unchecked_keyword; + int i; + char *strsep_fodder = kstrdup(debug_string, GFP_KERNEL); + char *original_pointer; + int element_count = 0; + struct client_debug_mask *c_mask = NULL; + __u64 *k_mask = NULL; + + gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); + + if (type) { + c_mask = (struct client_debug_mask *)mask; + element_count = cdm_element_count; + } else { + k_mask = (__u64 *)mask; + *k_mask = 0; + element_count = num_kmod_keyword_mask_map; + } + + original_pointer = strsep_fodder; + while ((unchecked_keyword = strsep(&strsep_fodder, ","))) + if (strlen(unchecked_keyword)) { + for (i = 0; i < element_count; i++) + if (type) + do_c_mask(i, + unchecked_keyword, + &c_mask); + else + do_k_mask(i, + unchecked_keyword, + &k_mask); + } + + kfree(original_pointer); +} + +static void do_c_mask(int i, char *unchecked_keyword, + struct client_debug_mask **sane_mask) +{ + + if (!strcmp(cdm_array[i].keyword, unchecked_keyword)) { + (**sane_mask).mask1 = (**sane_mask).mask1 | cdm_array[i].mask1; + (**sane_mask).mask2 = (**sane_mask).mask2 | cdm_array[i].mask2; + } +} + +static void do_k_mask(int i, char *unchecked_keyword, __u64 **sane_mask) +{ + + if (!strcmp(s_kmod_keyword_mask_map[i].keyword, unchecked_keyword)) + **sane_mask = (**sane_mask) | + s_kmod_keyword_mask_map[i].mask_val; +} + +int orangefs_debugfs_new_client_mask(void __user *arg) +{ + struct dev_mask2_info_s mask2_info = {0}; + int ret; + + ret = copy_from_user(&mask2_info, + (void __user *)arg, + sizeof(struct dev_mask2_info_s)); + + if (ret != 0) + return -EIO; + + client_debug_mask.mask1 = mask2_info.mask1_value; + client_debug_mask.mask2 = mask2_info.mask2_value; + + pr_info("%s: client debug mask has been been received " + ":%llx: :%llx:\n", + __func__, + (unsigned long long)client_debug_mask.mask1, + (unsigned long long)client_debug_mask.mask2); + + return ret; +} + +int orangefs_debugfs_new_client_string(void __user *arg) +{ + int ret; + + ret = copy_from_user(&client_debug_array_string, + (void __user *)arg, + ORANGEFS_MAX_DEBUG_STRING_LEN); + if (ret != 0) + return -EIO; + + /* + * The real client-core makes an effort to ensure + * that actual strings that aren't too long to fit in + * this buffer is what we get here. We're going to use + * string functions on the stuff we got, so we'll make + * this extra effort to try and keep from + * flowing out of this buffer when we use the string + * functions, even if somehow the stuff we end up + * with here is garbage. + */ + client_debug_array_string[ORANGEFS_MAX_DEBUG_STRING_LEN - 1] = + '\0'; + + if (ret != 0) { + pr_info("%s: CLIENT_STRING: copy_from_user failed\n", + __func__); + return -EIO; + } + + pr_info("%s: client debug array string has been received.\n", + __func__); + + if (!help_string_initialized) { + + /* Free the "we don't know yet" default string... */ + kfree(debug_help_string); + + /* build a proper debug help string */ + if (orangefs_prepare_debugfs_help_string(0)) { + gossip_err("%s: no debug help string \n", + __func__); + return -EIO; + } + + /* Replace the boilerplate boot-time debug-help file. */ + debugfs_remove(help_file_dentry); + + help_file_dentry = + debugfs_create_file( + ORANGEFS_KMOD_DEBUG_HELP_FILE, + 0444, + debug_dir, + debug_help_string, + &debug_help_fops); + + if (!help_file_dentry) { + gossip_err("%s: debugfs_create_file failed for" + " :%s:!\n", + __func__, + ORANGEFS_KMOD_DEBUG_HELP_FILE); + return -EIO; + } + } + + debug_mask_to_string(&client_debug_mask, 1); + + debugfs_remove(client_debug_dentry); + + orangefs_client_debug_init(); + + help_string_initialized++; + + return ret; +} + +int orangefs_debugfs_new_debug(void __user *arg) +{ + struct dev_mask_info_s mask_info = {0}; + int ret; + + ret = copy_from_user(&mask_info, + (void __user *)arg, + sizeof(mask_info)); + + if (ret != 0) + return -EIO; + + if (mask_info.mask_type == KERNEL_MASK) { + if ((mask_info.mask_value == 0) + && (kernel_mask_set_mod_init)) { + /* + * the kernel debug mask was set when the + * kernel module was loaded; don't override + * it if the client-core was started without + * a value for ORANGEFS_KMODMASK. + */ + return 0; + } + debug_mask_to_string(&mask_info.mask_value, + mask_info.mask_type); + orangefs_gossip_debug_mask = mask_info.mask_value; + pr_info("%s: kernel debug mask has been modified to " + ":%s: :%llx:\n", + __func__, + kernel_debug_string, + (unsigned long long)orangefs_gossip_debug_mask); + } else if (mask_info.mask_type == CLIENT_MASK) { + debug_mask_to_string(&mask_info.mask_value, + mask_info.mask_type); + pr_info("%s: client debug mask has been modified to" + ":%s: :%llx:\n", + __func__, + client_debug_string, + llu(mask_info.mask_value)); + } else { + gossip_lerr("Invalid mask type....\n"); + return -EINVAL; + } + + return ret; +} diff --git a/fs/orangefs/orangefs-debugfs.h b/fs/orangefs/orangefs-debugfs.h index e4828c0e3ef9..803517269ba6 100644 --- a/fs/orangefs/orangefs-debugfs.h +++ b/fs/orangefs/orangefs-debugfs.h @@ -1,3 +1,7 @@ -int orangefs_debugfs_init(void); -int orangefs_kernel_debug_init(void); +int orangefs_debugfs_init(int); void orangefs_debugfs_cleanup(void); +int orangefs_client_debug_init(void); +int orangefs_prepare_debugfs_help_string(int); +int orangefs_debugfs_new_client_mask(void __user *); +int orangefs_debugfs_new_client_string(void __user *); +int orangefs_debugfs_new_debug(void __user *); diff --git a/fs/orangefs/orangefs-dev-proto.h b/fs/orangefs/orangefs-dev-proto.h index 9eac9d9a3f3a..a3d84ffee905 100644 --- a/fs/orangefs/orangefs-dev-proto.h +++ b/fs/orangefs/orangefs-dev-proto.h @@ -28,7 +28,7 @@ #define ORANGEFS_VFS_OP_RENAME 0xFF00000A #define ORANGEFS_VFS_OP_STATFS 0xFF00000B #define ORANGEFS_VFS_OP_TRUNCATE 0xFF00000C -#define ORANGEFS_VFS_OP_MMAP_RA_FLUSH 0xFF00000D +#define ORANGEFS_VFS_OP_RA_FLUSH 0xFF00000D #define ORANGEFS_VFS_OP_FS_MOUNT 0xFF00000E #define ORANGEFS_VFS_OP_FS_UMOUNT 0xFF00000F #define ORANGEFS_VFS_OP_GETXATTR 0xFF000010 @@ -41,6 +41,10 @@ #define ORANGEFS_VFS_OP_FSYNC 0xFF00EE01 #define ORANGEFS_VFS_OP_FSKEY 0xFF00EE02 #define ORANGEFS_VFS_OP_READDIRPLUS 0xFF00EE03 +#define ORANGEFS_VFS_OP_FEATURES 0xFF00EE05 /* 2.9.6 */ + +/* features is a 64-bit unsigned bitmask */ +#define ORANGEFS_FEATURE_READAHEAD 1 /* * Misc constants. Please retain them as multiples of 8! diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h index 633c07a6e3d8..0a82048f3aaf 100644 --- a/fs/orangefs/orangefs-kernel.h +++ b/fs/orangefs/orangefs-kernel.h @@ -100,16 +100,6 @@ enum orangefs_vfs_op_states { }; /* - * An array of client_debug_mask will be built to hold debug keyword/mask - * values fetched from userspace. - */ -struct client_debug_mask { - char *keyword; - __u64 mask1; - __u64 mask2; -}; - -/* * orangefs kernel memory related flags */ @@ -119,29 +109,6 @@ struct client_debug_mask { #define ORANGEFS_CACHE_CREATE_FLAGS 0 #endif /* ((defined ORANGEFS_KERNEL_DEBUG) && (defined CONFIG_DEBUG_SLAB)) */ -/* these functions are defined in orangefs-utils.c */ -int orangefs_prepare_cdm_array(char *debug_array_string); -int orangefs_prepare_debugfs_help_string(int); - -/* defined in orangefs-debugfs.c */ -int orangefs_client_debug_init(void); - -void debug_string_to_mask(char *, void *, int); -void do_c_mask(int, char *, struct client_debug_mask **); -void do_k_mask(int, char *, __u64 **); - -void debug_mask_to_string(void *, int); -void do_k_string(void *, int); -void do_c_string(void *, int); -int check_amalgam_keyword(void *, int); -int keyword_is_amalgam(char *); - -/*these variables are defined in orangefs-mod.c */ -extern char kernel_debug_string[ORANGEFS_MAX_DEBUG_STRING_LEN]; -extern char client_debug_string[ORANGEFS_MAX_DEBUG_STRING_LEN]; -extern char client_debug_array_string[ORANGEFS_MAX_DEBUG_STRING_LEN]; -extern unsigned int kernel_mask_set_mod_init; - extern int orangefs_init_acl(struct inode *inode, struct inode *dir); extern const struct xattr_handler *orangefs_xattr_handlers[]; @@ -331,7 +298,7 @@ struct orangefs_stats { unsigned long writes; }; -extern struct orangefs_stats g_orangefs_stats; +extern struct orangefs_stats orangefs_stats; /* * NOTE: See Documentation/filesystems/porting for information @@ -447,6 +414,8 @@ void purge_waiting_ops(void); /* * defined in super.c */ +extern uint64_t orangefs_features; + struct dentry *orangefs_mount(struct file_system_type *fst, int flags, const char *devname, @@ -506,6 +475,8 @@ ssize_t orangefs_inode_read(struct inode *inode, /* * defined in devorangefs-req.c */ +extern uint32_t orangefs_userspace_version; + int orangefs_dev_init(void); void orangefs_dev_cleanup(void); int is_daemon_in_service(void); @@ -543,20 +514,18 @@ bool orangefs_cancel_op_in_progress(struct orangefs_kernel_op_s *op); int orangefs_normalize_to_errno(__s32 error_code); -extern struct mutex devreq_mutex; -extern struct mutex request_mutex; -extern int debug; +extern struct mutex orangefs_request_mutex; extern int op_timeout_secs; extern int slot_timeout_secs; -extern int dcache_timeout_msecs; -extern int getattr_timeout_msecs; +extern int orangefs_dcache_timeout_msecs; +extern int orangefs_getattr_timeout_msecs; extern struct list_head orangefs_superblocks; extern spinlock_t orangefs_superblocks_lock; extern struct list_head orangefs_request_list; extern spinlock_t orangefs_request_list_lock; extern wait_queue_head_t orangefs_request_list_waitq; -extern struct list_head *htable_ops_in_progress; -extern spinlock_t htable_ops_in_progress_lock; +extern struct list_head *orangefs_htable_ops_in_progress; +extern spinlock_t orangefs_htable_ops_in_progress_lock; extern int hash_table_size; extern const struct address_space_operations orangefs_address_operations; diff --git a/fs/orangefs/orangefs-mod.c b/fs/orangefs/orangefs-mod.c index e9fd5755c05f..2e5b03065f34 100644 --- a/fs/orangefs/orangefs-mod.c +++ b/fs/orangefs/orangefs-mod.c @@ -21,34 +21,17 @@ * global variables declared here */ -/* array of client debug keyword/mask values */ -struct client_debug_mask *cdm_array; -int cdm_element_count; - -char kernel_debug_string[ORANGEFS_MAX_DEBUG_STRING_LEN] = "none"; -char client_debug_string[ORANGEFS_MAX_DEBUG_STRING_LEN]; -char client_debug_array_string[ORANGEFS_MAX_DEBUG_STRING_LEN]; - -char *debug_help_string; -int help_string_initialized; -struct dentry *help_file_dentry; -struct dentry *client_debug_dentry; -struct dentry *debug_dir; -int client_verbose_index; -int client_all_index; -struct orangefs_stats g_orangefs_stats; +struct orangefs_stats orangefs_stats; /* the size of the hash tables for ops in progress */ int hash_table_size = 509; static ulong module_parm_debug_mask; -__u64 gossip_debug_mask; -struct client_debug_mask client_debug_mask = { NULL, 0, 0 }; -unsigned int kernel_mask_set_mod_init; /* implicitly false */ +__u64 orangefs_gossip_debug_mask; int op_timeout_secs = ORANGEFS_DEFAULT_OP_TIMEOUT_SECS; int slot_timeout_secs = ORANGEFS_DEFAULT_SLOT_TIMEOUT_SECS; -int dcache_timeout_msecs = 50; -int getattr_timeout_msecs = 50; +int orangefs_dcache_timeout_msecs = 50; +int orangefs_getattr_timeout_msecs = 50; MODULE_LICENSE("GPL"); MODULE_AUTHOR("ORANGEFS Development Team"); @@ -71,20 +54,17 @@ module_param(module_parm_debug_mask, ulong, 0644); module_param(op_timeout_secs, int, 0); module_param(slot_timeout_secs, int, 0); -/* synchronizes the request device file */ -DEFINE_MUTEX(devreq_mutex); - /* * Blocks non-priority requests from being queued for servicing. This * could be used for protecting the request list data structure, but * for now it's only being used to stall the op addition to the request * list */ -DEFINE_MUTEX(request_mutex); +DEFINE_MUTEX(orangefs_request_mutex); /* hash table for storing operations waiting for matching downcall */ -struct list_head *htable_ops_in_progress; -DEFINE_SPINLOCK(htable_ops_in_progress_lock); +struct list_head *orangefs_htable_ops_in_progress; +DEFINE_SPINLOCK(orangefs_htable_ops_in_progress_lock); /* list for queueing upcall operations */ LIST_HEAD(orangefs_request_list); @@ -100,32 +80,6 @@ static int __init orangefs_init(void) int ret = -1; __u32 i = 0; - /* convert input debug mask to a 64-bit unsigned integer */ - gossip_debug_mask = (unsigned long long) module_parm_debug_mask; - - /* - * set the kernel's gossip debug string; invalid mask values will - * be ignored. - */ - debug_mask_to_string(&gossip_debug_mask, 0); - - /* remove any invalid values from the mask */ - debug_string_to_mask(kernel_debug_string, &gossip_debug_mask, 0); - - /* - * if the mask has a non-zero value, then indicate that the mask - * was set when the kernel module was loaded. The orangefs dev ioctl - * command will look at this boolean to determine if the kernel's - * debug mask should be overwritten when the client-core is started. - */ - if (gossip_debug_mask != 0) - kernel_mask_set_mod_init = true; - - pr_info("%s: called with debug mask: :%s: :%llx:\n", - __func__, - kernel_debug_string, - (unsigned long long)gossip_debug_mask); - ret = bdi_init(&orangefs_backing_dev_info); if (ret) @@ -146,9 +100,9 @@ static int __init orangefs_init(void) if (ret < 0) goto cleanup_op; - htable_ops_in_progress = + orangefs_htable_ops_in_progress = kcalloc(hash_table_size, sizeof(struct list_head), GFP_KERNEL); - if (!htable_ops_in_progress) { + if (!orangefs_htable_ops_in_progress) { gossip_err("Failed to initialize op hashtable"); ret = -ENOMEM; goto cleanup_inode; @@ -156,7 +110,7 @@ static int __init orangefs_init(void) /* initialize a doubly linked at each hash table index */ for (i = 0; i < hash_table_size; i++) - INIT_LIST_HEAD(&htable_ops_in_progress[i]); + INIT_LIST_HEAD(&orangefs_htable_ops_in_progress[i]); ret = fsid_key_table_initialize(); if (ret < 0) @@ -179,14 +133,10 @@ static int __init orangefs_init(void) if (ret) goto cleanup_key_table; - ret = orangefs_debugfs_init(); + ret = orangefs_debugfs_init(module_parm_debug_mask); if (ret) goto debugfs_init_failed; - ret = orangefs_kernel_debug_init(); - if (ret) - goto kernel_debug_init_failed; - ret = orangefs_sysfs_init(); if (ret) goto sysfs_init_failed; @@ -214,8 +164,6 @@ cleanup_device: sysfs_init_failed: -kernel_debug_init_failed: - debugfs_init_failed: orangefs_debugfs_cleanup(); @@ -223,7 +171,7 @@ cleanup_key_table: fsid_key_table_finalize(); cleanup_progress_table: - kfree(htable_ops_in_progress); + kfree(orangefs_htable_ops_in_progress); cleanup_inode: orangefs_inode_cache_finalize(); @@ -250,12 +198,12 @@ static void __exit orangefs_exit(void) orangefs_dev_cleanup(); BUG_ON(!list_empty(&orangefs_request_list)); for (i = 0; i < hash_table_size; i++) - BUG_ON(!list_empty(&htable_ops_in_progress[i])); + BUG_ON(!list_empty(&orangefs_htable_ops_in_progress[i])); orangefs_inode_cache_finalize(); op_cache_finalize(); - kfree(htable_ops_in_progress); + kfree(orangefs_htable_ops_in_progress); bdi_destroy(&orangefs_backing_dev_info); @@ -274,10 +222,10 @@ void purge_inprogress_ops(void) struct orangefs_kernel_op_s *op; struct orangefs_kernel_op_s *next; - spin_lock(&htable_ops_in_progress_lock); + spin_lock(&orangefs_htable_ops_in_progress_lock); list_for_each_entry_safe(op, next, - &htable_ops_in_progress[i], + &orangefs_htable_ops_in_progress[i], list) { set_op_state_purged(op); gossip_debug(GOSSIP_DEV_DEBUG, @@ -287,7 +235,7 @@ void purge_inprogress_ops(void) op->op_state, current->comm); } - spin_unlock(&htable_ops_in_progress_lock); + spin_unlock(&orangefs_htable_ops_in_progress_lock); } } diff --git a/fs/orangefs/orangefs-sysfs.c b/fs/orangefs/orangefs-sysfs.c index 375708c2db87..a799546a67f7 100644 --- a/fs/orangefs/orangefs-sysfs.c +++ b/fs/orangefs/orangefs-sysfs.c @@ -73,6 +73,24 @@ * Description: * Time getattr is valid in milliseconds. * + * What: /sys/fs/orangefs/readahead_count + * Date: Aug 2016 + * Contact: Martin Brandenburg <martin@omnibond.com> + * Description: + * Readahead cache buffer count. + * + * What: /sys/fs/orangefs/readahead_size + * Date: Aug 2016 + * Contact: Martin Brandenburg <martin@omnibond.com> + * Description: + * Readahead cache buffer size. + * + * What: /sys/fs/orangefs/readahead_count_size + * Date: Aug 2016 + * Contact: Martin Brandenburg <martin@omnibond.com> + * Description: + * Readahead cache buffer count and size. + * * What: /sys/fs/orangefs/acache/... * Date: Jun 2015 * Contact: Martin Brandenburg <martin@omnibond.com> @@ -121,159 +139,34 @@ #define PC_KOBJ_ID "pc" #define STATS_KOBJ_ID "stats" -struct orangefs_obj { - struct kobject kobj; - int op_timeout_secs; - int perf_counter_reset; - int perf_history_size; - int perf_time_interval_secs; - int slot_timeout_secs; - int dcache_timeout_msecs; - int getattr_timeout_msecs; -}; - -struct acache_orangefs_obj { - struct kobject kobj; - int hard_limit; - int reclaim_percentage; - int soft_limit; - int timeout_msecs; -}; - -struct capcache_orangefs_obj { - struct kobject kobj; - int hard_limit; - int reclaim_percentage; - int soft_limit; - int timeout_secs; -}; - -struct ccache_orangefs_obj { - struct kobject kobj; - int hard_limit; - int reclaim_percentage; - int soft_limit; - int timeout_secs; -}; - -struct ncache_orangefs_obj { - struct kobject kobj; - int hard_limit; - int reclaim_percentage; - int soft_limit; - int timeout_msecs; -}; - -struct pc_orangefs_obj { - struct kobject kobj; - char *acache; - char *capcache; - char *ncache; -}; - -struct stats_orangefs_obj { - struct kobject kobj; - int reads; - int writes; -}; +/* + * Every item calls orangefs_attr_show and orangefs_attr_store through + * orangefs_sysfs_ops. They look at the orangefs_attributes further below to + * call one of sysfs_int_show, sysfs_int_store, sysfs_service_op_show, or + * sysfs_service_op_store. + */ struct orangefs_attribute { struct attribute attr; - ssize_t (*show)(struct orangefs_obj *orangefs_obj, + ssize_t (*show)(struct kobject *kobj, struct orangefs_attribute *attr, char *buf); - ssize_t (*store)(struct orangefs_obj *orangefs_obj, + ssize_t (*store)(struct kobject *kobj, struct orangefs_attribute *attr, const char *buf, size_t count); }; -struct acache_orangefs_attribute { - struct attribute attr; - ssize_t (*show)(struct acache_orangefs_obj *acache_orangefs_obj, - struct acache_orangefs_attribute *attr, - char *buf); - ssize_t (*store)(struct acache_orangefs_obj *acache_orangefs_obj, - struct acache_orangefs_attribute *attr, - const char *buf, - size_t count); -}; - -struct capcache_orangefs_attribute { - struct attribute attr; - ssize_t (*show)(struct capcache_orangefs_obj *capcache_orangefs_obj, - struct capcache_orangefs_attribute *attr, - char *buf); - ssize_t (*store)(struct capcache_orangefs_obj *capcache_orangefs_obj, - struct capcache_orangefs_attribute *attr, - const char *buf, - size_t count); -}; - -struct ccache_orangefs_attribute { - struct attribute attr; - ssize_t (*show)(struct ccache_orangefs_obj *ccache_orangefs_obj, - struct ccache_orangefs_attribute *attr, - char *buf); - ssize_t (*store)(struct ccache_orangefs_obj *ccache_orangefs_obj, - struct ccache_orangefs_attribute *attr, - const char *buf, - size_t count); -}; - -struct ncache_orangefs_attribute { - struct attribute attr; - ssize_t (*show)(struct ncache_orangefs_obj *ncache_orangefs_obj, - struct ncache_orangefs_attribute *attr, - char *buf); - ssize_t (*store)(struct ncache_orangefs_obj *ncache_orangefs_obj, - struct ncache_orangefs_attribute *attr, - const char *buf, - size_t count); -}; - -struct pc_orangefs_attribute { - struct attribute attr; - ssize_t (*show)(struct pc_orangefs_obj *pc_orangefs_obj, - struct pc_orangefs_attribute *attr, - char *buf); - ssize_t (*store)(struct pc_orangefs_obj *pc_orangefs_obj, - struct pc_orangefs_attribute *attr, - const char *buf, - size_t count); -}; - -struct stats_orangefs_attribute { - struct attribute attr; - ssize_t (*show)(struct stats_orangefs_obj *stats_orangefs_obj, - struct stats_orangefs_attribute *attr, - char *buf); - ssize_t (*store)(struct stats_orangefs_obj *stats_orangefs_obj, - struct stats_orangefs_attribute *attr, - const char *buf, - size_t count); -}; - static ssize_t orangefs_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) { struct orangefs_attribute *attribute; - struct orangefs_obj *orangefs_obj; - int rc; attribute = container_of(attr, struct orangefs_attribute, attr); - orangefs_obj = container_of(kobj, struct orangefs_obj, kobj); - - if (!attribute->show) { - rc = -EIO; - goto out; - } - - rc = attribute->show(orangefs_obj, attribute, buf); - -out: - return rc; + if (!attribute->show) + return -EIO; + return attribute->show(kobj, attribute, buf); } static ssize_t orangefs_attr_store(struct kobject *kobj, @@ -282,24 +175,15 @@ static ssize_t orangefs_attr_store(struct kobject *kobj, size_t len) { struct orangefs_attribute *attribute; - struct orangefs_obj *orangefs_obj; - int rc; - gossip_debug(GOSSIP_SYSFS_DEBUG, - "orangefs_attr_store: start\n"); + if (!strcmp(kobj->name, PC_KOBJ_ID) || + !strcmp(kobj->name, STATS_KOBJ_ID)) + return -EPERM; attribute = container_of(attr, struct orangefs_attribute, attr); - orangefs_obj = container_of(kobj, struct orangefs_obj, kobj); - - if (!attribute->store) { - rc = -EIO; - goto out; - } - - rc = attribute->store(orangefs_obj, attribute, buf, len); - -out: - return rc; + if (!attribute->store) + return -EIO; + return attribute->store(kobj, attribute, buf, len); } static const struct sysfs_ops orangefs_sysfs_ops = { @@ -307,402 +191,58 @@ static const struct sysfs_ops orangefs_sysfs_ops = { .store = orangefs_attr_store, }; -static ssize_t acache_orangefs_attr_show(struct kobject *kobj, - struct attribute *attr, - char *buf) -{ - struct acache_orangefs_attribute *attribute; - struct acache_orangefs_obj *acache_orangefs_obj; - int rc; - - attribute = container_of(attr, struct acache_orangefs_attribute, attr); - acache_orangefs_obj = - container_of(kobj, struct acache_orangefs_obj, kobj); - - if (!attribute->show) { - rc = -EIO; - goto out; - } - - rc = attribute->show(acache_orangefs_obj, attribute, buf); - -out: - return rc; -} - -static ssize_t acache_orangefs_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, - size_t len) -{ - struct acache_orangefs_attribute *attribute; - struct acache_orangefs_obj *acache_orangefs_obj; - int rc; - - gossip_debug(GOSSIP_SYSFS_DEBUG, - "acache_orangefs_attr_store: start\n"); - - attribute = container_of(attr, struct acache_orangefs_attribute, attr); - acache_orangefs_obj = - container_of(kobj, struct acache_orangefs_obj, kobj); - - if (!attribute->store) { - rc = -EIO; - goto out; - } - - rc = attribute->store(acache_orangefs_obj, attribute, buf, len); - -out: - return rc; -} - -static const struct sysfs_ops acache_orangefs_sysfs_ops = { - .show = acache_orangefs_attr_show, - .store = acache_orangefs_attr_store, -}; - -static ssize_t capcache_orangefs_attr_show(struct kobject *kobj, - struct attribute *attr, - char *buf) -{ - struct capcache_orangefs_attribute *attribute; - struct capcache_orangefs_obj *capcache_orangefs_obj; - int rc; - - attribute = - container_of(attr, struct capcache_orangefs_attribute, attr); - capcache_orangefs_obj = - container_of(kobj, struct capcache_orangefs_obj, kobj); - - if (!attribute->show) { - rc = -EIO; - goto out; - } - - rc = attribute->show(capcache_orangefs_obj, attribute, buf); - -out: - return rc; -} - -static ssize_t capcache_orangefs_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, - size_t len) -{ - struct capcache_orangefs_attribute *attribute; - struct capcache_orangefs_obj *capcache_orangefs_obj; - int rc; - - gossip_debug(GOSSIP_SYSFS_DEBUG, - "capcache_orangefs_attr_store: start\n"); - - attribute = - container_of(attr, struct capcache_orangefs_attribute, attr); - capcache_orangefs_obj = - container_of(kobj, struct capcache_orangefs_obj, kobj); - - if (!attribute->store) { - rc = -EIO; - goto out; - } - - rc = attribute->store(capcache_orangefs_obj, attribute, buf, len); - -out: - return rc; -} - -static const struct sysfs_ops capcache_orangefs_sysfs_ops = { - .show = capcache_orangefs_attr_show, - .store = capcache_orangefs_attr_store, -}; - -static ssize_t ccache_orangefs_attr_show(struct kobject *kobj, - struct attribute *attr, - char *buf) -{ - struct ccache_orangefs_attribute *attribute; - struct ccache_orangefs_obj *ccache_orangefs_obj; - int rc; - - attribute = - container_of(attr, struct ccache_orangefs_attribute, attr); - ccache_orangefs_obj = - container_of(kobj, struct ccache_orangefs_obj, kobj); - - if (!attribute->show) { - rc = -EIO; - goto out; - } - - rc = attribute->show(ccache_orangefs_obj, attribute, buf); - -out: - return rc; -} - -static ssize_t ccache_orangefs_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, - size_t len) -{ - struct ccache_orangefs_attribute *attribute; - struct ccache_orangefs_obj *ccache_orangefs_obj; - int rc; - - gossip_debug(GOSSIP_SYSFS_DEBUG, - "ccache_orangefs_attr_store: start\n"); - - attribute = - container_of(attr, struct ccache_orangefs_attribute, attr); - ccache_orangefs_obj = - container_of(kobj, struct ccache_orangefs_obj, kobj); - - if (!attribute->store) { - rc = -EIO; - goto out; - } - - rc = attribute->store(ccache_orangefs_obj, attribute, buf, len); - -out: - return rc; -} - -static const struct sysfs_ops ccache_orangefs_sysfs_ops = { - .show = ccache_orangefs_attr_show, - .store = ccache_orangefs_attr_store, -}; - -static ssize_t ncache_orangefs_attr_show(struct kobject *kobj, - struct attribute *attr, - char *buf) -{ - struct ncache_orangefs_attribute *attribute; - struct ncache_orangefs_obj *ncache_orangefs_obj; - int rc; - - attribute = container_of(attr, struct ncache_orangefs_attribute, attr); - ncache_orangefs_obj = - container_of(kobj, struct ncache_orangefs_obj, kobj); - - if (!attribute->show) { - rc = -EIO; - goto out; - } - - rc = attribute->show(ncache_orangefs_obj, attribute, buf); - -out: - return rc; -} - -static ssize_t ncache_orangefs_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, - size_t len) -{ - struct ncache_orangefs_attribute *attribute; - struct ncache_orangefs_obj *ncache_orangefs_obj; - int rc; - - gossip_debug(GOSSIP_SYSFS_DEBUG, - "ncache_orangefs_attr_store: start\n"); - - attribute = container_of(attr, struct ncache_orangefs_attribute, attr); - ncache_orangefs_obj = - container_of(kobj, struct ncache_orangefs_obj, kobj); - - if (!attribute->store) { - rc = -EIO; - goto out; - } - - rc = attribute->store(ncache_orangefs_obj, attribute, buf, len); - -out: - return rc; -} - -static const struct sysfs_ops ncache_orangefs_sysfs_ops = { - .show = ncache_orangefs_attr_show, - .store = ncache_orangefs_attr_store, -}; - -static ssize_t pc_orangefs_attr_show(struct kobject *kobj, - struct attribute *attr, - char *buf) -{ - struct pc_orangefs_attribute *attribute; - struct pc_orangefs_obj *pc_orangefs_obj; - int rc; - - attribute = container_of(attr, struct pc_orangefs_attribute, attr); - pc_orangefs_obj = - container_of(kobj, struct pc_orangefs_obj, kobj); - - if (!attribute->show) { - rc = -EIO; - goto out; - } - - rc = attribute->show(pc_orangefs_obj, attribute, buf); - -out: - return rc; -} - -static const struct sysfs_ops pc_orangefs_sysfs_ops = { - .show = pc_orangefs_attr_show, -}; - -static ssize_t stats_orangefs_attr_show(struct kobject *kobj, - struct attribute *attr, - char *buf) -{ - struct stats_orangefs_attribute *attribute; - struct stats_orangefs_obj *stats_orangefs_obj; - int rc; - - attribute = container_of(attr, struct stats_orangefs_attribute, attr); - stats_orangefs_obj = - container_of(kobj, struct stats_orangefs_obj, kobj); - - if (!attribute->show) { - rc = -EIO; - goto out; - } - - rc = attribute->show(stats_orangefs_obj, attribute, buf); - -out: - return rc; -} - -static const struct sysfs_ops stats_orangefs_sysfs_ops = { - .show = stats_orangefs_attr_show, -}; - -static void orangefs_release(struct kobject *kobj) -{ - struct orangefs_obj *orangefs_obj; - - orangefs_obj = container_of(kobj, struct orangefs_obj, kobj); - kfree(orangefs_obj); -} - -static void acache_orangefs_release(struct kobject *kobj) -{ - struct acache_orangefs_obj *acache_orangefs_obj; - - acache_orangefs_obj = - container_of(kobj, struct acache_orangefs_obj, kobj); - kfree(acache_orangefs_obj); -} - -static void capcache_orangefs_release(struct kobject *kobj) -{ - struct capcache_orangefs_obj *capcache_orangefs_obj; - - capcache_orangefs_obj = - container_of(kobj, struct capcache_orangefs_obj, kobj); - kfree(capcache_orangefs_obj); -} - -static void ccache_orangefs_release(struct kobject *kobj) -{ - struct ccache_orangefs_obj *ccache_orangefs_obj; - - ccache_orangefs_obj = - container_of(kobj, struct ccache_orangefs_obj, kobj); - kfree(ccache_orangefs_obj); -} - -static void ncache_orangefs_release(struct kobject *kobj) -{ - struct ncache_orangefs_obj *ncache_orangefs_obj; - - ncache_orangefs_obj = - container_of(kobj, struct ncache_orangefs_obj, kobj); - kfree(ncache_orangefs_obj); -} - -static void pc_orangefs_release(struct kobject *kobj) -{ - struct pc_orangefs_obj *pc_orangefs_obj; - - pc_orangefs_obj = - container_of(kobj, struct pc_orangefs_obj, kobj); - kfree(pc_orangefs_obj); -} - -static void stats_orangefs_release(struct kobject *kobj) -{ - struct stats_orangefs_obj *stats_orangefs_obj; - - stats_orangefs_obj = - container_of(kobj, struct stats_orangefs_obj, kobj); - kfree(stats_orangefs_obj); -} - -static ssize_t sysfs_int_show(char *kobj_id, char *buf, void *attr) +static ssize_t sysfs_int_show(struct kobject *kobj, + struct orangefs_attribute *attr, char *buf) { int rc = -EIO; - struct orangefs_attribute *orangefs_attr; - struct stats_orangefs_attribute *stats_orangefs_attr; - gossip_debug(GOSSIP_SYSFS_DEBUG, "sysfs_int_show: id:%s:\n", kobj_id); + gossip_debug(GOSSIP_SYSFS_DEBUG, "sysfs_int_show: id:%s:\n", + kobj->name); - if (!strcmp(kobj_id, ORANGEFS_KOBJ_ID)) { - orangefs_attr = (struct orangefs_attribute *)attr; - - if (!strcmp(orangefs_attr->attr.name, "op_timeout_secs")) { + if (!strcmp(kobj->name, ORANGEFS_KOBJ_ID)) { + if (!strcmp(attr->attr.name, "op_timeout_secs")) { rc = scnprintf(buf, PAGE_SIZE, "%d\n", op_timeout_secs); goto out; - } else if (!strcmp(orangefs_attr->attr.name, + } else if (!strcmp(attr->attr.name, "slot_timeout_secs")) { rc = scnprintf(buf, PAGE_SIZE, "%d\n", slot_timeout_secs); goto out; - } else if (!strcmp(orangefs_attr->attr.name, + } else if (!strcmp(attr->attr.name, "dcache_timeout_msecs")) { rc = scnprintf(buf, PAGE_SIZE, "%d\n", - dcache_timeout_msecs); + orangefs_dcache_timeout_msecs); goto out; - } else if (!strcmp(orangefs_attr->attr.name, + } else if (!strcmp(attr->attr.name, "getattr_timeout_msecs")) { rc = scnprintf(buf, PAGE_SIZE, "%d\n", - getattr_timeout_msecs); + orangefs_getattr_timeout_msecs); goto out; } else { goto out; } - } else if (!strcmp(kobj_id, STATS_KOBJ_ID)) { - stats_orangefs_attr = (struct stats_orangefs_attribute *)attr; - - if (!strcmp(stats_orangefs_attr->attr.name, "reads")) { + } else if (!strcmp(kobj->name, STATS_KOBJ_ID)) { + if (!strcmp(attr->attr.name, "reads")) { rc = scnprintf(buf, PAGE_SIZE, "%lu\n", - g_orangefs_stats.reads); + orangefs_stats.reads); goto out; - } else if (!strcmp(stats_orangefs_attr->attr.name, "writes")) { + } else if (!strcmp(attr->attr.name, "writes")) { rc = scnprintf(buf, PAGE_SIZE, "%lu\n", - g_orangefs_stats.writes); + orangefs_stats.writes); goto out; } else { goto out; @@ -714,45 +254,13 @@ out: return rc; } -static ssize_t int_orangefs_show(struct orangefs_obj *orangefs_obj, - struct orangefs_attribute *attr, - char *buf) -{ - int rc; - - gossip_debug(GOSSIP_SYSFS_DEBUG, - "int_orangefs_show:start attr->attr.name:%s:\n", - attr->attr.name); - - rc = sysfs_int_show(ORANGEFS_KOBJ_ID, buf, (void *) attr); - - return rc; -} - -static ssize_t int_stats_show(struct stats_orangefs_obj *stats_orangefs_obj, - struct stats_orangefs_attribute *attr, - char *buf) -{ - int rc; - - gossip_debug(GOSSIP_SYSFS_DEBUG, - "int_stats_show:start attr->attr.name:%s:\n", - attr->attr.name); - - rc = sysfs_int_show(STATS_KOBJ_ID, buf, (void *) attr); - - return rc; -} - -static ssize_t int_store(struct orangefs_obj *orangefs_obj, - struct orangefs_attribute *attr, - const char *buf, - size_t count) +static ssize_t sysfs_int_store(struct kobject *kobj, + struct orangefs_attribute *attr, const char *buf, size_t count) { int rc = 0; gossip_debug(GOSSIP_SYSFS_DEBUG, - "int_store: start attr->attr.name:%s: buf:%s:\n", + "sysfs_int_store: start attr->attr.name:%s: buf:%s:\n", attr->attr.name, buf); if (!strcmp(attr->attr.name, "op_timeout_secs")) { @@ -762,10 +270,10 @@ static ssize_t int_store(struct orangefs_obj *orangefs_obj, rc = kstrtoint(buf, 0, &slot_timeout_secs); goto out; } else if (!strcmp(attr->attr.name, "dcache_timeout_msecs")) { - rc = kstrtoint(buf, 0, &dcache_timeout_msecs); + rc = kstrtoint(buf, 0, &orangefs_dcache_timeout_msecs); goto out; } else if (!strcmp(attr->attr.name, "getattr_timeout_msecs")) { - rc = kstrtoint(buf, 0, &getattr_timeout_msecs); + rc = kstrtoint(buf, 0, &orangefs_getattr_timeout_msecs); goto out; } else { goto out; @@ -783,24 +291,19 @@ out: /* * obtain attribute values from userspace with a service operation. */ -static int sysfs_service_op_show(char *kobj_id, char *buf, void *attr) +static ssize_t sysfs_service_op_show(struct kobject *kobj, + struct orangefs_attribute *attr, char *buf) { struct orangefs_kernel_op_s *new_op = NULL; int rc = 0; char *ser_op_type = NULL; - struct orangefs_attribute *orangefs_attr; - struct acache_orangefs_attribute *acache_attr; - struct capcache_orangefs_attribute *capcache_attr; - struct ccache_orangefs_attribute *ccache_attr; - struct ncache_orangefs_attribute *ncache_attr; - struct pc_orangefs_attribute *pc_attr; __u32 op_alloc_type; gossip_debug(GOSSIP_SYSFS_DEBUG, "sysfs_service_op_show: id:%s:\n", - kobj_id); + kobj->name); - if (strcmp(kobj_id, PC_KOBJ_ID)) + if (strcmp(kobj->name, PC_KOBJ_ID)) op_alloc_type = ORANGEFS_VFS_OP_PARAM; else op_alloc_type = ORANGEFS_VFS_OP_PERF_COUNT; @@ -818,124 +321,135 @@ static int sysfs_service_op_show(char *kobj_id, char *buf, void *attr) goto out; } - if (strcmp(kobj_id, PC_KOBJ_ID)) + if (strcmp(kobj->name, PC_KOBJ_ID)) new_op->upcall.req.param.type = ORANGEFS_PARAM_REQUEST_GET; - if (!strcmp(kobj_id, ORANGEFS_KOBJ_ID)) { - orangefs_attr = (struct orangefs_attribute *)attr; + if (!strcmp(kobj->name, ORANGEFS_KOBJ_ID)) { + /* Drop unsupported requests first. */ + if (!(orangefs_features & ORANGEFS_FEATURE_READAHEAD) && + (!strcmp(attr->attr.name, "readahead_count") || + !strcmp(attr->attr.name, "readahead_size") || + !strcmp(attr->attr.name, "readahead_count_size"))) { + rc = -EINVAL; + goto out; + } - if (!strcmp(orangefs_attr->attr.name, "perf_history_size")) + if (!strcmp(attr->attr.name, "perf_history_size")) new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_PERF_HISTORY_SIZE; - else if (!strcmp(orangefs_attr->attr.name, + else if (!strcmp(attr->attr.name, "perf_time_interval_secs")) new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_PERF_TIME_INTERVAL_SECS; - else if (!strcmp(orangefs_attr->attr.name, + else if (!strcmp(attr->attr.name, "perf_counter_reset")) new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_PERF_RESET; - } else if (!strcmp(kobj_id, ACACHE_KOBJ_ID)) { - acache_attr = (struct acache_orangefs_attribute *)attr; + else if (!strcmp(attr->attr.name, + "readahead_count")) + new_op->upcall.req.param.op = + ORANGEFS_PARAM_REQUEST_OP_READAHEAD_COUNT; + + else if (!strcmp(attr->attr.name, + "readahead_size")) + new_op->upcall.req.param.op = + ORANGEFS_PARAM_REQUEST_OP_READAHEAD_SIZE; - if (!strcmp(acache_attr->attr.name, "timeout_msecs")) + else if (!strcmp(attr->attr.name, + "readahead_count_size")) + new_op->upcall.req.param.op = + ORANGEFS_PARAM_REQUEST_OP_READAHEAD_COUNT_SIZE; + } else if (!strcmp(kobj->name, ACACHE_KOBJ_ID)) { + if (!strcmp(attr->attr.name, "timeout_msecs")) new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_ACACHE_TIMEOUT_MSECS; - if (!strcmp(acache_attr->attr.name, "hard_limit")) + if (!strcmp(attr->attr.name, "hard_limit")) new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_ACACHE_HARD_LIMIT; - if (!strcmp(acache_attr->attr.name, "soft_limit")) + if (!strcmp(attr->attr.name, "soft_limit")) new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_ACACHE_SOFT_LIMIT; - if (!strcmp(acache_attr->attr.name, "reclaim_percentage")) + if (!strcmp(attr->attr.name, "reclaim_percentage")) new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_ACACHE_RECLAIM_PERCENTAGE; - } else if (!strcmp(kobj_id, CAPCACHE_KOBJ_ID)) { - capcache_attr = (struct capcache_orangefs_attribute *)attr; - - if (!strcmp(capcache_attr->attr.name, "timeout_secs")) + } else if (!strcmp(kobj->name, CAPCACHE_KOBJ_ID)) { + if (!strcmp(attr->attr.name, "timeout_secs")) new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_CAPCACHE_TIMEOUT_SECS; - if (!strcmp(capcache_attr->attr.name, "hard_limit")) + if (!strcmp(attr->attr.name, "hard_limit")) new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_CAPCACHE_HARD_LIMIT; - if (!strcmp(capcache_attr->attr.name, "soft_limit")) + if (!strcmp(attr->attr.name, "soft_limit")) new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_CAPCACHE_SOFT_LIMIT; - if (!strcmp(capcache_attr->attr.name, "reclaim_percentage")) + if (!strcmp(attr->attr.name, "reclaim_percentage")) new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_CAPCACHE_RECLAIM_PERCENTAGE; - } else if (!strcmp(kobj_id, CCACHE_KOBJ_ID)) { - ccache_attr = (struct ccache_orangefs_attribute *)attr; - - if (!strcmp(ccache_attr->attr.name, "timeout_secs")) + } else if (!strcmp(kobj->name, CCACHE_KOBJ_ID)) { + if (!strcmp(attr->attr.name, "timeout_secs")) new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_CCACHE_TIMEOUT_SECS; - if (!strcmp(ccache_attr->attr.name, "hard_limit")) + if (!strcmp(attr->attr.name, "hard_limit")) new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_CCACHE_HARD_LIMIT; - if (!strcmp(ccache_attr->attr.name, "soft_limit")) + if (!strcmp(attr->attr.name, "soft_limit")) new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_CCACHE_SOFT_LIMIT; - if (!strcmp(ccache_attr->attr.name, "reclaim_percentage")) + if (!strcmp(attr->attr.name, "reclaim_percentage")) new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_CCACHE_RECLAIM_PERCENTAGE; - } else if (!strcmp(kobj_id, NCACHE_KOBJ_ID)) { - ncache_attr = (struct ncache_orangefs_attribute *)attr; - - if (!strcmp(ncache_attr->attr.name, "timeout_msecs")) + } else if (!strcmp(kobj->name, NCACHE_KOBJ_ID)) { + if (!strcmp(attr->attr.name, "timeout_msecs")) new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_NCACHE_TIMEOUT_MSECS; - if (!strcmp(ncache_attr->attr.name, "hard_limit")) + if (!strcmp(attr->attr.name, "hard_limit")) new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_NCACHE_HARD_LIMIT; - if (!strcmp(ncache_attr->attr.name, "soft_limit")) + if (!strcmp(attr->attr.name, "soft_limit")) new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_NCACHE_SOFT_LIMIT; - if (!strcmp(ncache_attr->attr.name, "reclaim_percentage")) + if (!strcmp(attr->attr.name, "reclaim_percentage")) new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_NCACHE_RECLAIM_PERCENTAGE; - } else if (!strcmp(kobj_id, PC_KOBJ_ID)) { - pc_attr = (struct pc_orangefs_attribute *)attr; - - if (!strcmp(pc_attr->attr.name, ACACHE_KOBJ_ID)) + } else if (!strcmp(kobj->name, PC_KOBJ_ID)) { + if (!strcmp(attr->attr.name, ACACHE_KOBJ_ID)) new_op->upcall.req.perf_count.type = ORANGEFS_PERF_COUNT_REQUEST_ACACHE; - if (!strcmp(pc_attr->attr.name, CAPCACHE_KOBJ_ID)) + if (!strcmp(attr->attr.name, CAPCACHE_KOBJ_ID)) new_op->upcall.req.perf_count.type = ORANGEFS_PERF_COUNT_REQUEST_CAPCACHE; - if (!strcmp(pc_attr->attr.name, NCACHE_KOBJ_ID)) + if (!strcmp(attr->attr.name, NCACHE_KOBJ_ID)) new_op->upcall.req.perf_count.type = ORANGEFS_PERF_COUNT_REQUEST_NCACHE; } else { gossip_err("sysfs_service_op_show: unknown kobj_id:%s:\n", - kobj_id); + kobj->name); rc = -EINVAL; goto out; } - if (strcmp(kobj_id, PC_KOBJ_ID)) + if (strcmp(kobj->name, PC_KOBJ_ID)) ser_op_type = "orangefs_param"; else ser_op_type = "orangefs_perf_count"; @@ -948,11 +462,18 @@ static int sysfs_service_op_show(char *kobj_id, char *buf, void *attr) out: if (!rc) { - if (strcmp(kobj_id, PC_KOBJ_ID)) { - rc = scnprintf(buf, - PAGE_SIZE, - "%d\n", - (int)new_op->downcall.resp.param.value); + if (strcmp(kobj->name, PC_KOBJ_ID)) { + if (new_op->upcall.req.param.op == + ORANGEFS_PARAM_REQUEST_OP_READAHEAD_COUNT_SIZE) { + rc = scnprintf(buf, PAGE_SIZE, "%d %d\n", + (int)new_op->downcall.resp.param.u. + value32[0], + (int)new_op->downcall.resp.param.u. + value32[1]); + } else { + rc = scnprintf(buf, PAGE_SIZE, "%d\n", + (int)new_op->downcall.resp.param.u.value64); + } } else { rc = scnprintf( buf, @@ -968,77 +489,6 @@ out: } -static ssize_t service_orangefs_show(struct orangefs_obj *orangefs_obj, - struct orangefs_attribute *attr, - char *buf) -{ - int rc = 0; - - rc = sysfs_service_op_show(ORANGEFS_KOBJ_ID, buf, (void *)attr); - - return rc; -} - -static ssize_t - service_acache_show(struct acache_orangefs_obj *acache_orangefs_obj, - struct acache_orangefs_attribute *attr, - char *buf) -{ - int rc = 0; - - rc = sysfs_service_op_show(ACACHE_KOBJ_ID, buf, (void *)attr); - - return rc; -} - -static ssize_t service_capcache_show(struct capcache_orangefs_obj - *capcache_orangefs_obj, - struct capcache_orangefs_attribute *attr, - char *buf) -{ - int rc = 0; - - rc = sysfs_service_op_show(CAPCACHE_KOBJ_ID, buf, (void *)attr); - - return rc; -} - -static ssize_t service_ccache_show(struct ccache_orangefs_obj - *ccache_orangefs_obj, - struct ccache_orangefs_attribute *attr, - char *buf) -{ - int rc = 0; - - rc = sysfs_service_op_show(CCACHE_KOBJ_ID, buf, (void *)attr); - - return rc; -} - -static ssize_t - service_ncache_show(struct ncache_orangefs_obj *ncache_orangefs_obj, - struct ncache_orangefs_attribute *attr, - char *buf) -{ - int rc = 0; - - rc = sysfs_service_op_show(NCACHE_KOBJ_ID, buf, (void *)attr); - - return rc; -} - -static ssize_t - service_pc_show(struct pc_orangefs_obj *pc_orangefs_obj, - struct pc_orangefs_attribute *attr, - char *buf) -{ - int rc = 0; - - rc = sysfs_service_op_show(PC_KOBJ_ID, buf, (void *)attr); - - return rc; -} - /* * pass attribute values back to userspace with a service operation. * @@ -1050,20 +500,16 @@ static ssize_t * We want to return 1 if we think everything went OK, and * EINVAL if not. */ -static int sysfs_service_op_store(char *kobj_id, const char *buf, void *attr) +static ssize_t sysfs_service_op_store(struct kobject *kobj, + struct orangefs_attribute *attr, const char *buf, size_t count) { struct orangefs_kernel_op_s *new_op = NULL; int val = 0; int rc = 0; - struct orangefs_attribute *orangefs_attr; - struct acache_orangefs_attribute *acache_attr; - struct capcache_orangefs_attribute *capcache_attr; - struct ccache_orangefs_attribute *ccache_attr; - struct ncache_orangefs_attribute *ncache_attr; gossip_debug(GOSSIP_SYSFS_DEBUG, "sysfs_service_op_store: id:%s:\n", - kobj_id); + kobj->name); new_op = op_alloc(ORANGEFS_VFS_OP_PARAM); if (!new_op) @@ -1079,16 +525,29 @@ static int sysfs_service_op_store(char *kobj_id, const char *buf, void *attr) } /* - * The value we want to send back to userspace is in buf. + * The value we want to send back to userspace is in buf, unless this + * there are two parameters, which is specially handled below. */ - rc = kstrtoint(buf, 0, &val); - if (rc) - goto out; + if (strcmp(kobj->name, ORANGEFS_KOBJ_ID) || + strcmp(attr->attr.name, "readahead_count_size")) { + rc = kstrtoint(buf, 0, &val); + if (rc) + goto out; + } - if (!strcmp(kobj_id, ORANGEFS_KOBJ_ID)) { - orangefs_attr = (struct orangefs_attribute *)attr; + new_op->upcall.req.param.type = ORANGEFS_PARAM_REQUEST_SET; + + if (!strcmp(kobj->name, ORANGEFS_KOBJ_ID)) { + /* Drop unsupported requests first. */ + if (!(orangefs_features & ORANGEFS_FEATURE_READAHEAD) && + (!strcmp(attr->attr.name, "readahead_count") || + !strcmp(attr->attr.name, "readahead_size") || + !strcmp(attr->attr.name, "readahead_count_size"))) { + rc = -EINVAL; + goto out; + } - if (!strcmp(orangefs_attr->attr.name, "perf_history_size")) { + if (!strcmp(attr->attr.name, "perf_history_size")) { if (val > 0) { new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_PERF_HISTORY_SIZE; @@ -1096,7 +555,7 @@ static int sysfs_service_op_store(char *kobj_id, const char *buf, void *attr) rc = 0; goto out; } - } else if (!strcmp(orangefs_attr->attr.name, + } else if (!strcmp(attr->attr.name, "perf_time_interval_secs")) { if (val > 0) { new_op->upcall.req.param.op = @@ -1105,7 +564,7 @@ static int sysfs_service_op_store(char *kobj_id, const char *buf, void *attr) rc = 0; goto out; } - } else if (!strcmp(orangefs_attr->attr.name, + } else if (!strcmp(attr->attr.name, "perf_counter_reset")) { if ((val == 0) || (val == 1)) { new_op->upcall.req.param.op = @@ -1114,12 +573,55 @@ static int sysfs_service_op_store(char *kobj_id, const char *buf, void *attr) rc = 0; goto out; } + } else if (!strcmp(attr->attr.name, + "readahead_count")) { + if ((val >= 0)) { + new_op->upcall.req.param.op = + ORANGEFS_PARAM_REQUEST_OP_READAHEAD_COUNT; + } else { + rc = 0; + goto out; + } + } else if (!strcmp(attr->attr.name, + "readahead_size")) { + if ((val >= 0)) { + new_op->upcall.req.param.op = + ORANGEFS_PARAM_REQUEST_OP_READAHEAD_SIZE; + } else { + rc = 0; + goto out; + } + } else if (!strcmp(attr->attr.name, + "readahead_count_size")) { + int val1, val2; + rc = sscanf(buf, "%d %d", &val1, &val2); + if (rc < 2) { + rc = 0; + goto out; + } + if ((val1 >= 0) && (val2 >= 0)) { + new_op->upcall.req.param.op = + ORANGEFS_PARAM_REQUEST_OP_READAHEAD_COUNT_SIZE; + } else { + rc = 0; + goto out; + } + new_op->upcall.req.param.u.value32[0] = val1; + new_op->upcall.req.param.u.value32[1] = val2; + goto value_set; + } else if (!strcmp(attr->attr.name, + "perf_counter_reset")) { + if ((val > 0)) { + new_op->upcall.req.param.op = + ORANGEFS_PARAM_REQUEST_OP_READAHEAD_COUNT_SIZE; + } else { + rc = 0; + goto out; + } } - } else if (!strcmp(kobj_id, ACACHE_KOBJ_ID)) { - acache_attr = (struct acache_orangefs_attribute *)attr; - - if (!strcmp(acache_attr->attr.name, "hard_limit")) { + } else if (!strcmp(kobj->name, ACACHE_KOBJ_ID)) { + if (!strcmp(attr->attr.name, "hard_limit")) { if (val > -1) { new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_ACACHE_HARD_LIMIT; @@ -1127,7 +629,7 @@ static int sysfs_service_op_store(char *kobj_id, const char *buf, void *attr) rc = 0; goto out; } - } else if (!strcmp(acache_attr->attr.name, "soft_limit")) { + } else if (!strcmp(attr->attr.name, "soft_limit")) { if (val > -1) { new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_ACACHE_SOFT_LIMIT; @@ -1135,7 +637,7 @@ static int sysfs_service_op_store(char *kobj_id, const char *buf, void *attr) rc = 0; goto out; } - } else if (!strcmp(acache_attr->attr.name, + } else if (!strcmp(attr->attr.name, "reclaim_percentage")) { if ((val > -1) && (val < 101)) { new_op->upcall.req.param.op = @@ -1144,7 +646,7 @@ static int sysfs_service_op_store(char *kobj_id, const char *buf, void *attr) rc = 0; goto out; } - } else if (!strcmp(acache_attr->attr.name, "timeout_msecs")) { + } else if (!strcmp(attr->attr.name, "timeout_msecs")) { if (val > -1) { new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_ACACHE_TIMEOUT_MSECS; @@ -1154,10 +656,8 @@ static int sysfs_service_op_store(char *kobj_id, const char *buf, void *attr) } } - } else if (!strcmp(kobj_id, CAPCACHE_KOBJ_ID)) { - capcache_attr = (struct capcache_orangefs_attribute *)attr; - - if (!strcmp(capcache_attr->attr.name, "hard_limit")) { + } else if (!strcmp(kobj->name, CAPCACHE_KOBJ_ID)) { + if (!strcmp(attr->attr.name, "hard_limit")) { if (val > -1) { new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_CAPCACHE_HARD_LIMIT; @@ -1165,7 +665,7 @@ static int sysfs_service_op_store(char *kobj_id, const char *buf, void *attr) rc = 0; goto out; } - } else if (!strcmp(capcache_attr->attr.name, "soft_limit")) { + } else if (!strcmp(attr->attr.name, "soft_limit")) { if (val > -1) { new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_CAPCACHE_SOFT_LIMIT; @@ -1173,7 +673,7 @@ static int sysfs_service_op_store(char *kobj_id, const char *buf, void *attr) rc = 0; goto out; } - } else if (!strcmp(capcache_attr->attr.name, + } else if (!strcmp(attr->attr.name, "reclaim_percentage")) { if ((val > -1) && (val < 101)) { new_op->upcall.req.param.op = @@ -1182,7 +682,7 @@ static int sysfs_service_op_store(char *kobj_id, const char *buf, void *attr) rc = 0; goto out; } - } else if (!strcmp(capcache_attr->attr.name, "timeout_secs")) { + } else if (!strcmp(attr->attr.name, "timeout_secs")) { if (val > -1) { new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_CAPCACHE_TIMEOUT_SECS; @@ -1192,10 +692,8 @@ static int sysfs_service_op_store(char *kobj_id, const char *buf, void *attr) } } - } else if (!strcmp(kobj_id, CCACHE_KOBJ_ID)) { - ccache_attr = (struct ccache_orangefs_attribute *)attr; - - if (!strcmp(ccache_attr->attr.name, "hard_limit")) { + } else if (!strcmp(kobj->name, CCACHE_KOBJ_ID)) { + if (!strcmp(attr->attr.name, "hard_limit")) { if (val > -1) { new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_CCACHE_HARD_LIMIT; @@ -1203,7 +701,7 @@ static int sysfs_service_op_store(char *kobj_id, const char *buf, void *attr) rc = 0; goto out; } - } else if (!strcmp(ccache_attr->attr.name, "soft_limit")) { + } else if (!strcmp(attr->attr.name, "soft_limit")) { if (val > -1) { new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_CCACHE_SOFT_LIMIT; @@ -1211,7 +709,7 @@ static int sysfs_service_op_store(char *kobj_id, const char *buf, void *attr) rc = 0; goto out; } - } else if (!strcmp(ccache_attr->attr.name, + } else if (!strcmp(attr->attr.name, "reclaim_percentage")) { if ((val > -1) && (val < 101)) { new_op->upcall.req.param.op = @@ -1220,7 +718,7 @@ static int sysfs_service_op_store(char *kobj_id, const char *buf, void *attr) rc = 0; goto out; } - } else if (!strcmp(ccache_attr->attr.name, "timeout_secs")) { + } else if (!strcmp(attr->attr.name, "timeout_secs")) { if (val > -1) { new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_CCACHE_TIMEOUT_SECS; @@ -1230,10 +728,8 @@ static int sysfs_service_op_store(char *kobj_id, const char *buf, void *attr) } } - } else if (!strcmp(kobj_id, NCACHE_KOBJ_ID)) { - ncache_attr = (struct ncache_orangefs_attribute *)attr; - - if (!strcmp(ncache_attr->attr.name, "hard_limit")) { + } else if (!strcmp(kobj->name, NCACHE_KOBJ_ID)) { + if (!strcmp(attr->attr.name, "hard_limit")) { if (val > -1) { new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_NCACHE_HARD_LIMIT; @@ -1241,7 +737,7 @@ static int sysfs_service_op_store(char *kobj_id, const char *buf, void *attr) rc = 0; goto out; } - } else if (!strcmp(ncache_attr->attr.name, "soft_limit")) { + } else if (!strcmp(attr->attr.name, "soft_limit")) { if (val > -1) { new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_NCACHE_SOFT_LIMIT; @@ -1249,7 +745,7 @@ static int sysfs_service_op_store(char *kobj_id, const char *buf, void *attr) rc = 0; goto out; } - } else if (!strcmp(ncache_attr->attr.name, + } else if (!strcmp(attr->attr.name, "reclaim_percentage")) { if ((val > -1) && (val < 101)) { new_op->upcall.req.param.op = @@ -1258,7 +754,7 @@ static int sysfs_service_op_store(char *kobj_id, const char *buf, void *attr) rc = 0; goto out; } - } else if (!strcmp(ncache_attr->attr.name, "timeout_msecs")) { + } else if (!strcmp(attr->attr.name, "timeout_msecs")) { if (val > -1) { new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_NCACHE_TIMEOUT_MSECS; @@ -1270,14 +766,13 @@ static int sysfs_service_op_store(char *kobj_id, const char *buf, void *attr) } else { gossip_err("sysfs_service_op_store: unknown kobj_id:%s:\n", - kobj_id); + kobj->name); rc = -EINVAL; goto out; } - new_op->upcall.req.param.type = ORANGEFS_PARAM_REQUEST_SET; - - new_op->upcall.req.param.value = val; + new_op->upcall.req.param.u.value64 = val; +value_set: /* * The service_operation will return a errno return code on @@ -1290,7 +785,7 @@ static int sysfs_service_op_store(char *kobj_id, const char *buf, void *attr) rc); rc = 0; } else { - rc = 1; + rc = count; } out: @@ -1302,127 +797,56 @@ out: return rc; } -static ssize_t - service_orangefs_store(struct orangefs_obj *orangefs_obj, - struct orangefs_attribute *attr, - const char *buf, - size_t count) -{ - int rc = 0; - - rc = sysfs_service_op_store(ORANGEFS_KOBJ_ID, buf, (void *) attr); - - /* rc should have an errno value if the service_op went bad. */ - if (rc == 1) - rc = count; - - return rc; -} - -static ssize_t - service_acache_store(struct acache_orangefs_obj *acache_orangefs_obj, - struct acache_orangefs_attribute *attr, - const char *buf, - size_t count) -{ - int rc = 0; - - rc = sysfs_service_op_store(ACACHE_KOBJ_ID, buf, (void *) attr); - - /* rc should have an errno value if the service_op went bad. */ - if (rc == 1) - rc = count; - - return rc; -} - -static ssize_t - service_capcache_store(struct capcache_orangefs_obj - *capcache_orangefs_obj, - struct capcache_orangefs_attribute *attr, - const char *buf, - size_t count) -{ - int rc = 0; - - rc = sysfs_service_op_store(CAPCACHE_KOBJ_ID, buf, (void *) attr); - - /* rc should have an errno value if the service_op went bad. */ - if (rc == 1) - rc = count; - - return rc; -} - -static ssize_t service_ccache_store(struct ccache_orangefs_obj - *ccache_orangefs_obj, - struct ccache_orangefs_attribute *attr, - const char *buf, - size_t count) -{ - int rc = 0; - - rc = sysfs_service_op_store(CCACHE_KOBJ_ID, buf, (void *) attr); - - /* rc should have an errno value if the service_op went bad. */ - if (rc == 1) - rc = count; - - return rc; -} - -static ssize_t - service_ncache_store(struct ncache_orangefs_obj *ncache_orangefs_obj, - struct ncache_orangefs_attribute *attr, - const char *buf, - size_t count) -{ - int rc = 0; - - rc = sysfs_service_op_store(NCACHE_KOBJ_ID, buf, (void *) attr); - - /* rc should have an errno value if the service_op went bad. */ - if (rc == 1) - rc = count; - - return rc; -} - static struct orangefs_attribute op_timeout_secs_attribute = - __ATTR(op_timeout_secs, 0664, int_orangefs_show, int_store); + __ATTR(op_timeout_secs, 0664, sysfs_int_show, sysfs_int_store); static struct orangefs_attribute slot_timeout_secs_attribute = - __ATTR(slot_timeout_secs, 0664, int_orangefs_show, int_store); + __ATTR(slot_timeout_secs, 0664, sysfs_int_show, sysfs_int_store); static struct orangefs_attribute dcache_timeout_msecs_attribute = - __ATTR(dcache_timeout_msecs, 0664, int_orangefs_show, int_store); + __ATTR(dcache_timeout_msecs, 0664, sysfs_int_show, sysfs_int_store); static struct orangefs_attribute getattr_timeout_msecs_attribute = - __ATTR(getattr_timeout_msecs, 0664, int_orangefs_show, int_store); + __ATTR(getattr_timeout_msecs, 0664, sysfs_int_show, sysfs_int_store); + +static struct orangefs_attribute readahead_count_attribute = + __ATTR(readahead_count, 0664, sysfs_service_op_show, + sysfs_service_op_store); + +static struct orangefs_attribute readahead_size_attribute = + __ATTR(readahead_size, 0664, sysfs_service_op_show, + sysfs_service_op_store); + +static struct orangefs_attribute readahead_count_size_attribute = + __ATTR(readahead_count_size, 0664, sysfs_service_op_show, + sysfs_service_op_store); static struct orangefs_attribute perf_counter_reset_attribute = __ATTR(perf_counter_reset, 0664, - service_orangefs_show, - service_orangefs_store); + sysfs_service_op_show, + sysfs_service_op_store); static struct orangefs_attribute perf_history_size_attribute = __ATTR(perf_history_size, 0664, - service_orangefs_show, - service_orangefs_store); + sysfs_service_op_show, + sysfs_service_op_store); static struct orangefs_attribute perf_time_interval_secs_attribute = __ATTR(perf_time_interval_secs, 0664, - service_orangefs_show, - service_orangefs_store); + sysfs_service_op_show, + sysfs_service_op_store); static struct attribute *orangefs_default_attrs[] = { &op_timeout_secs_attribute.attr, &slot_timeout_secs_attribute.attr, &dcache_timeout_msecs_attribute.attr, &getattr_timeout_msecs_attribute.attr, + &readahead_count_attribute.attr, + &readahead_size_attribute.attr, + &readahead_count_size_attribute.attr, &perf_counter_reset_attribute.attr, &perf_history_size_attribute.attr, &perf_time_interval_secs_attribute.attr, @@ -1431,33 +855,32 @@ static struct attribute *orangefs_default_attrs[] = { static struct kobj_type orangefs_ktype = { .sysfs_ops = &orangefs_sysfs_ops, - .release = orangefs_release, .default_attrs = orangefs_default_attrs, }; -static struct acache_orangefs_attribute acache_hard_limit_attribute = +static struct orangefs_attribute acache_hard_limit_attribute = __ATTR(hard_limit, 0664, - service_acache_show, - service_acache_store); + sysfs_service_op_show, + sysfs_service_op_store); -static struct acache_orangefs_attribute acache_reclaim_percent_attribute = +static struct orangefs_attribute acache_reclaim_percent_attribute = __ATTR(reclaim_percentage, 0664, - service_acache_show, - service_acache_store); + sysfs_service_op_show, + sysfs_service_op_store); -static struct acache_orangefs_attribute acache_soft_limit_attribute = +static struct orangefs_attribute acache_soft_limit_attribute = __ATTR(soft_limit, 0664, - service_acache_show, - service_acache_store); + sysfs_service_op_show, + sysfs_service_op_store); -static struct acache_orangefs_attribute acache_timeout_msecs_attribute = +static struct orangefs_attribute acache_timeout_msecs_attribute = __ATTR(timeout_msecs, 0664, - service_acache_show, - service_acache_store); + sysfs_service_op_show, + sysfs_service_op_store); static struct attribute *acache_orangefs_default_attrs[] = { &acache_hard_limit_attribute.attr, @@ -1468,34 +891,33 @@ static struct attribute *acache_orangefs_default_attrs[] = { }; static struct kobj_type acache_orangefs_ktype = { - .sysfs_ops = &acache_orangefs_sysfs_ops, - .release = acache_orangefs_release, + .sysfs_ops = &orangefs_sysfs_ops, .default_attrs = acache_orangefs_default_attrs, }; -static struct capcache_orangefs_attribute capcache_hard_limit_attribute = +static struct orangefs_attribute capcache_hard_limit_attribute = __ATTR(hard_limit, 0664, - service_capcache_show, - service_capcache_store); + sysfs_service_op_show, + sysfs_service_op_store); -static struct capcache_orangefs_attribute capcache_reclaim_percent_attribute = +static struct orangefs_attribute capcache_reclaim_percent_attribute = __ATTR(reclaim_percentage, 0664, - service_capcache_show, - service_capcache_store); + sysfs_service_op_show, + sysfs_service_op_store); -static struct capcache_orangefs_attribute capcache_soft_limit_attribute = +static struct orangefs_attribute capcache_soft_limit_attribute = __ATTR(soft_limit, 0664, - service_capcache_show, - service_capcache_store); + sysfs_service_op_show, + sysfs_service_op_store); -static struct capcache_orangefs_attribute capcache_timeout_secs_attribute = +static struct orangefs_attribute capcache_timeout_secs_attribute = __ATTR(timeout_secs, 0664, - service_capcache_show, - service_capcache_store); + sysfs_service_op_show, + sysfs_service_op_store); static struct attribute *capcache_orangefs_default_attrs[] = { &capcache_hard_limit_attribute.attr, @@ -1506,34 +928,33 @@ static struct attribute *capcache_orangefs_default_attrs[] = { }; static struct kobj_type capcache_orangefs_ktype = { - .sysfs_ops = &capcache_orangefs_sysfs_ops, - .release = capcache_orangefs_release, + .sysfs_ops = &orangefs_sysfs_ops, .default_attrs = capcache_orangefs_default_attrs, }; -static struct ccache_orangefs_attribute ccache_hard_limit_attribute = +static struct orangefs_attribute ccache_hard_limit_attribute = __ATTR(hard_limit, 0664, - service_ccache_show, - service_ccache_store); + sysfs_service_op_show, + sysfs_service_op_store); -static struct ccache_orangefs_attribute ccache_reclaim_percent_attribute = +static struct orangefs_attribute ccache_reclaim_percent_attribute = __ATTR(reclaim_percentage, 0664, - service_ccache_show, - service_ccache_store); + sysfs_service_op_show, + sysfs_service_op_store); -static struct ccache_orangefs_attribute ccache_soft_limit_attribute = +static struct orangefs_attribute ccache_soft_limit_attribute = __ATTR(soft_limit, 0664, - service_ccache_show, - service_ccache_store); + sysfs_service_op_show, + sysfs_service_op_store); -static struct ccache_orangefs_attribute ccache_timeout_secs_attribute = +static struct orangefs_attribute ccache_timeout_secs_attribute = __ATTR(timeout_secs, 0664, - service_ccache_show, - service_ccache_store); + sysfs_service_op_show, + sysfs_service_op_store); static struct attribute *ccache_orangefs_default_attrs[] = { &ccache_hard_limit_attribute.attr, @@ -1544,34 +965,33 @@ static struct attribute *ccache_orangefs_default_attrs[] = { }; static struct kobj_type ccache_orangefs_ktype = { - .sysfs_ops = &ccache_orangefs_sysfs_ops, - .release = ccache_orangefs_release, + .sysfs_ops = &orangefs_sysfs_ops, .default_attrs = ccache_orangefs_default_attrs, }; -static struct ncache_orangefs_attribute ncache_hard_limit_attribute = +static struct orangefs_attribute ncache_hard_limit_attribute = __ATTR(hard_limit, 0664, - service_ncache_show, - service_ncache_store); + sysfs_service_op_show, + sysfs_service_op_store); -static struct ncache_orangefs_attribute ncache_reclaim_percent_attribute = +static struct orangefs_attribute ncache_reclaim_percent_attribute = __ATTR(reclaim_percentage, 0664, - service_ncache_show, - service_ncache_store); + sysfs_service_op_show, + sysfs_service_op_store); -static struct ncache_orangefs_attribute ncache_soft_limit_attribute = +static struct orangefs_attribute ncache_soft_limit_attribute = __ATTR(soft_limit, 0664, - service_ncache_show, - service_ncache_store); + sysfs_service_op_show, + sysfs_service_op_store); -static struct ncache_orangefs_attribute ncache_timeout_msecs_attribute = +static struct orangefs_attribute ncache_timeout_msecs_attribute = __ATTR(timeout_msecs, 0664, - service_ncache_show, - service_ncache_store); + sysfs_service_op_show, + sysfs_service_op_store); static struct attribute *ncache_orangefs_default_attrs[] = { &ncache_hard_limit_attribute.attr, @@ -1582,27 +1002,26 @@ static struct attribute *ncache_orangefs_default_attrs[] = { }; static struct kobj_type ncache_orangefs_ktype = { - .sysfs_ops = &ncache_orangefs_sysfs_ops, - .release = ncache_orangefs_release, + .sysfs_ops = &orangefs_sysfs_ops, .default_attrs = ncache_orangefs_default_attrs, }; -static struct pc_orangefs_attribute pc_acache_attribute = +static struct orangefs_attribute pc_acache_attribute = __ATTR(acache, 0664, - service_pc_show, + sysfs_service_op_show, NULL); -static struct pc_orangefs_attribute pc_capcache_attribute = +static struct orangefs_attribute pc_capcache_attribute = __ATTR(capcache, 0664, - service_pc_show, + sysfs_service_op_show, NULL); -static struct pc_orangefs_attribute pc_ncache_attribute = +static struct orangefs_attribute pc_ncache_attribute = __ATTR(ncache, 0664, - service_pc_show, + sysfs_service_op_show, NULL); static struct attribute *pc_orangefs_default_attrs[] = { @@ -1613,21 +1032,20 @@ static struct attribute *pc_orangefs_default_attrs[] = { }; static struct kobj_type pc_orangefs_ktype = { - .sysfs_ops = &pc_orangefs_sysfs_ops, - .release = pc_orangefs_release, + .sysfs_ops = &orangefs_sysfs_ops, .default_attrs = pc_orangefs_default_attrs, }; -static struct stats_orangefs_attribute stats_reads_attribute = +static struct orangefs_attribute stats_reads_attribute = __ATTR(reads, 0664, - int_stats_show, + sysfs_int_show, NULL); -static struct stats_orangefs_attribute stats_writes_attribute = +static struct orangefs_attribute stats_writes_attribute = __ATTR(writes, 0664, - int_stats_show, + sysfs_int_show, NULL); static struct attribute *stats_orangefs_default_attrs[] = { @@ -1637,18 +1055,17 @@ static struct attribute *stats_orangefs_default_attrs[] = { }; static struct kobj_type stats_orangefs_ktype = { - .sysfs_ops = &stats_orangefs_sysfs_ops, - .release = stats_orangefs_release, + .sysfs_ops = &orangefs_sysfs_ops, .default_attrs = stats_orangefs_default_attrs, }; -static struct orangefs_obj *orangefs_obj; -static struct acache_orangefs_obj *acache_orangefs_obj; -static struct capcache_orangefs_obj *capcache_orangefs_obj; -static struct ccache_orangefs_obj *ccache_orangefs_obj; -static struct ncache_orangefs_obj *ncache_orangefs_obj; -static struct pc_orangefs_obj *pc_orangefs_obj; -static struct stats_orangefs_obj *stats_orangefs_obj; +static struct kobject *orangefs_obj; +static struct kobject *acache_orangefs_obj; +static struct kobject *capcache_orangefs_obj; +static struct kobject *ccache_orangefs_obj; +static struct kobject *ncache_orangefs_obj; +static struct kobject *pc_orangefs_obj; +static struct kobject *stats_orangefs_obj; int orangefs_sysfs_init(void) { @@ -1661,7 +1078,7 @@ int orangefs_sysfs_init(void) if (!orangefs_obj) goto out; - rc = kobject_init_and_add(&orangefs_obj->kobj, + rc = kobject_init_and_add(orangefs_obj, &orangefs_ktype, fs_kobj, ORANGEFS_KOBJ_ID); @@ -1669,7 +1086,7 @@ int orangefs_sysfs_init(void) if (rc) goto ofs_obj_bail; - kobject_uevent(&orangefs_obj->kobj, KOBJ_ADD); + kobject_uevent(orangefs_obj, KOBJ_ADD); /* create /sys/fs/orangefs/acache. */ acache_orangefs_obj = kzalloc(sizeof(*acache_orangefs_obj), GFP_KERNEL); @@ -1678,15 +1095,15 @@ int orangefs_sysfs_init(void) goto ofs_obj_bail; } - rc = kobject_init_and_add(&acache_orangefs_obj->kobj, + rc = kobject_init_and_add(acache_orangefs_obj, &acache_orangefs_ktype, - &orangefs_obj->kobj, + orangefs_obj, ACACHE_KOBJ_ID); if (rc) goto acache_obj_bail; - kobject_uevent(&acache_orangefs_obj->kobj, KOBJ_ADD); + kobject_uevent(acache_orangefs_obj, KOBJ_ADD); /* create /sys/fs/orangefs/capcache. */ capcache_orangefs_obj = @@ -1696,14 +1113,14 @@ int orangefs_sysfs_init(void) goto acache_obj_bail; } - rc = kobject_init_and_add(&capcache_orangefs_obj->kobj, + rc = kobject_init_and_add(capcache_orangefs_obj, &capcache_orangefs_ktype, - &orangefs_obj->kobj, + orangefs_obj, CAPCACHE_KOBJ_ID); if (rc) goto capcache_obj_bail; - kobject_uevent(&capcache_orangefs_obj->kobj, KOBJ_ADD); + kobject_uevent(capcache_orangefs_obj, KOBJ_ADD); /* create /sys/fs/orangefs/ccache. */ ccache_orangefs_obj = @@ -1713,14 +1130,14 @@ int orangefs_sysfs_init(void) goto capcache_obj_bail; } - rc = kobject_init_and_add(&ccache_orangefs_obj->kobj, + rc = kobject_init_and_add(ccache_orangefs_obj, &ccache_orangefs_ktype, - &orangefs_obj->kobj, + orangefs_obj, CCACHE_KOBJ_ID); if (rc) goto ccache_obj_bail; - kobject_uevent(&ccache_orangefs_obj->kobj, KOBJ_ADD); + kobject_uevent(ccache_orangefs_obj, KOBJ_ADD); /* create /sys/fs/orangefs/ncache. */ ncache_orangefs_obj = kzalloc(sizeof(*ncache_orangefs_obj), GFP_KERNEL); @@ -1729,15 +1146,15 @@ int orangefs_sysfs_init(void) goto ccache_obj_bail; } - rc = kobject_init_and_add(&ncache_orangefs_obj->kobj, + rc = kobject_init_and_add(ncache_orangefs_obj, &ncache_orangefs_ktype, - &orangefs_obj->kobj, + orangefs_obj, NCACHE_KOBJ_ID); if (rc) goto ncache_obj_bail; - kobject_uevent(&ncache_orangefs_obj->kobj, KOBJ_ADD); + kobject_uevent(ncache_orangefs_obj, KOBJ_ADD); /* create /sys/fs/orangefs/perf_counters. */ pc_orangefs_obj = kzalloc(sizeof(*pc_orangefs_obj), GFP_KERNEL); @@ -1746,15 +1163,15 @@ int orangefs_sysfs_init(void) goto ncache_obj_bail; } - rc = kobject_init_and_add(&pc_orangefs_obj->kobj, + rc = kobject_init_and_add(pc_orangefs_obj, &pc_orangefs_ktype, - &orangefs_obj->kobj, + orangefs_obj, "perf_counters"); if (rc) goto pc_obj_bail; - kobject_uevent(&pc_orangefs_obj->kobj, KOBJ_ADD); + kobject_uevent(pc_orangefs_obj, KOBJ_ADD); /* create /sys/fs/orangefs/stats. */ stats_orangefs_obj = kzalloc(sizeof(*stats_orangefs_obj), GFP_KERNEL); @@ -1763,37 +1180,31 @@ int orangefs_sysfs_init(void) goto pc_obj_bail; } - rc = kobject_init_and_add(&stats_orangefs_obj->kobj, + rc = kobject_init_and_add(stats_orangefs_obj, &stats_orangefs_ktype, - &orangefs_obj->kobj, + orangefs_obj, STATS_KOBJ_ID); if (rc) goto stats_obj_bail; - kobject_uevent(&stats_orangefs_obj->kobj, KOBJ_ADD); + kobject_uevent(stats_orangefs_obj, KOBJ_ADD); goto out; stats_obj_bail: - kobject_put(&stats_orangefs_obj->kobj); - + kobject_put(stats_orangefs_obj); pc_obj_bail: - kobject_put(&pc_orangefs_obj->kobj); - + kobject_put(pc_orangefs_obj); ncache_obj_bail: - kobject_put(&ncache_orangefs_obj->kobj); - + kobject_put(ncache_orangefs_obj); ccache_obj_bail: - kobject_put(&ccache_orangefs_obj->kobj); - + kobject_put(ccache_orangefs_obj); capcache_obj_bail: - kobject_put(&capcache_orangefs_obj->kobj); - + kobject_put(capcache_orangefs_obj); acache_obj_bail: - kobject_put(&acache_orangefs_obj->kobj); - + kobject_put(acache_orangefs_obj); ofs_obj_bail: - kobject_put(&orangefs_obj->kobj); + kobject_put(orangefs_obj); out: return rc; } @@ -1801,13 +1212,11 @@ out: void orangefs_sysfs_exit(void) { gossip_debug(GOSSIP_SYSFS_DEBUG, "orangefs_sysfs_exit: start\n"); - - kobject_put(&acache_orangefs_obj->kobj); - kobject_put(&capcache_orangefs_obj->kobj); - kobject_put(&ccache_orangefs_obj->kobj); - kobject_put(&ncache_orangefs_obj->kobj); - kobject_put(&pc_orangefs_obj->kobj); - kobject_put(&stats_orangefs_obj->kobj); - - kobject_put(&orangefs_obj->kobj); + kobject_put(acache_orangefs_obj); + kobject_put(capcache_orangefs_obj); + kobject_put(ccache_orangefs_obj); + kobject_put(ncache_orangefs_obj); + kobject_put(pc_orangefs_obj); + kobject_put(stats_orangefs_obj); + kobject_put(orangefs_obj); } diff --git a/fs/orangefs/orangefs-utils.c b/fs/orangefs/orangefs-utils.c index d13c7291fd05..06af81f71e10 100644 --- a/fs/orangefs/orangefs-utils.c +++ b/fs/orangefs/orangefs-utils.c @@ -50,7 +50,7 @@ __s32 fsid_of_op(struct orangefs_kernel_op_s *op) case ORANGEFS_VFS_OP_TRUNCATE: fsid = op->upcall.req.truncate.refn.fs_id; break; - case ORANGEFS_VFS_OP_MMAP_RA_FLUSH: + case ORANGEFS_VFS_OP_RA_FLUSH: fsid = op->upcall.req.ra_cache_flush.refn.fs_id; break; case ORANGEFS_VFS_OP_FS_UMOUNT: @@ -347,7 +347,8 @@ int orangefs_inode_getattr(struct inode *inode, int new, int bypass) inode->i_mode = type | (is_root_handle(inode) ? S_ISVTX : 0) | orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes); - orangefs_inode->getattr_time = jiffies + getattr_timeout_msecs*HZ/1000; + orangefs_inode->getattr_time = jiffies + + orangefs_getattr_timeout_msecs*HZ/1000; ret = 0; out: op_release(new_op); @@ -656,401 +657,3 @@ __s32 ORANGEFS_util_translate_mode(int mode) return ret; } #undef NUM_MODES - -/* - * After obtaining a string representation of the client's debug - * keywords and their associated masks, this function is called to build an - * array of these values. - */ -int orangefs_prepare_cdm_array(char *debug_array_string) -{ - int i; - int rc = -EINVAL; - char *cds_head = NULL; - char *cds_delimiter = NULL; - int keyword_len = 0; - - gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); - - /* - * figure out how many elements the cdm_array needs. - */ - for (i = 0; i < strlen(debug_array_string); i++) - if (debug_array_string[i] == '\n') - cdm_element_count++; - - if (!cdm_element_count) { - pr_info("No elements in client debug array string!\n"); - goto out; - } - - cdm_array = - kzalloc(cdm_element_count * sizeof(struct client_debug_mask), - GFP_KERNEL); - if (!cdm_array) { - pr_info("malloc failed for cdm_array!\n"); - rc = -ENOMEM; - goto out; - } - - cds_head = debug_array_string; - - for (i = 0; i < cdm_element_count; i++) { - cds_delimiter = strchr(cds_head, '\n'); - *cds_delimiter = '\0'; - - keyword_len = strcspn(cds_head, " "); - - cdm_array[i].keyword = kzalloc(keyword_len + 1, GFP_KERNEL); - if (!cdm_array[i].keyword) { - rc = -ENOMEM; - goto out; - } - - sscanf(cds_head, - "%s %llx %llx", - cdm_array[i].keyword, - (unsigned long long *)&(cdm_array[i].mask1), - (unsigned long long *)&(cdm_array[i].mask2)); - - if (!strcmp(cdm_array[i].keyword, ORANGEFS_VERBOSE)) - client_verbose_index = i; - - if (!strcmp(cdm_array[i].keyword, ORANGEFS_ALL)) - client_all_index = i; - - cds_head = cds_delimiter + 1; - } - - rc = cdm_element_count; - - gossip_debug(GOSSIP_UTILS_DEBUG, "%s: rc:%d:\n", __func__, rc); - -out: - - return rc; - -} - -/* - * /sys/kernel/debug/orangefs/debug-help can be catted to - * see all the available kernel and client debug keywords. - * - * When the kernel boots, we have no idea what keywords the - * client supports, nor their associated masks. - * - * We pass through this function once at boot and stamp a - * boilerplate "we don't know" message for the client in the - * debug-help file. We pass through here again when the client - * starts and then we can fill out the debug-help file fully. - * - * The client might be restarted any number of times between - * reboots, we only build the debug-help file the first time. - */ -int orangefs_prepare_debugfs_help_string(int at_boot) -{ - int rc = -EINVAL; - int i; - int byte_count = 0; - char *client_title = "Client Debug Keywords:\n"; - char *kernel_title = "Kernel Debug Keywords:\n"; - - gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); - - if (at_boot) { - byte_count += strlen(HELP_STRING_UNINITIALIZED); - client_title = HELP_STRING_UNINITIALIZED; - } else { - /* - * fill the client keyword/mask array and remember - * how many elements there were. - */ - cdm_element_count = - orangefs_prepare_cdm_array(client_debug_array_string); - if (cdm_element_count <= 0) - goto out; - - /* Count the bytes destined for debug_help_string. */ - byte_count += strlen(client_title); - - for (i = 0; i < cdm_element_count; i++) { - byte_count += strlen(cdm_array[i].keyword + 2); - if (byte_count >= DEBUG_HELP_STRING_SIZE) { - pr_info("%s: overflow 1!\n", __func__); - goto out; - } - } - - gossip_debug(GOSSIP_UTILS_DEBUG, - "%s: cdm_element_count:%d:\n", - __func__, - cdm_element_count); - } - - byte_count += strlen(kernel_title); - for (i = 0; i < num_kmod_keyword_mask_map; i++) { - byte_count += - strlen(s_kmod_keyword_mask_map[i].keyword + 2); - if (byte_count >= DEBUG_HELP_STRING_SIZE) { - pr_info("%s: overflow 2!\n", __func__); - goto out; - } - } - - /* build debug_help_string. */ - debug_help_string = kzalloc(DEBUG_HELP_STRING_SIZE, GFP_KERNEL); - if (!debug_help_string) { - rc = -ENOMEM; - goto out; - } - - strcat(debug_help_string, client_title); - - if (!at_boot) { - for (i = 0; i < cdm_element_count; i++) { - strcat(debug_help_string, "\t"); - strcat(debug_help_string, cdm_array[i].keyword); - strcat(debug_help_string, "\n"); - } - } - - strcat(debug_help_string, "\n"); - strcat(debug_help_string, kernel_title); - - for (i = 0; i < num_kmod_keyword_mask_map; i++) { - strcat(debug_help_string, "\t"); - strcat(debug_help_string, s_kmod_keyword_mask_map[i].keyword); - strcat(debug_help_string, "\n"); - } - - rc = 0; - -out: - - return rc; - -} - -/* - * kernel = type 0 - * client = type 1 - */ -void debug_mask_to_string(void *mask, int type) -{ - int i; - int len = 0; - char *debug_string; - int element_count = 0; - - gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); - - if (type) { - debug_string = client_debug_string; - element_count = cdm_element_count; - } else { - debug_string = kernel_debug_string; - element_count = num_kmod_keyword_mask_map; - } - - memset(debug_string, 0, ORANGEFS_MAX_DEBUG_STRING_LEN); - - /* - * Some keywords, like "all" or "verbose", are amalgams of - * numerous other keywords. Make a special check for those - * before grinding through the whole mask only to find out - * later... - */ - if (check_amalgam_keyword(mask, type)) - goto out; - - /* Build the debug string. */ - for (i = 0; i < element_count; i++) - if (type) - do_c_string(mask, i); - else - do_k_string(mask, i); - - len = strlen(debug_string); - - if ((len) && (type)) - client_debug_string[len - 1] = '\0'; - else if (len) - kernel_debug_string[len - 1] = '\0'; - else if (type) - strcpy(client_debug_string, "none"); - else - strcpy(kernel_debug_string, "none"); - -out: -gossip_debug(GOSSIP_UTILS_DEBUG, "%s: string:%s:\n", __func__, debug_string); - - return; - -} - -void do_k_string(void *k_mask, int index) -{ - __u64 *mask = (__u64 *) k_mask; - - if (keyword_is_amalgam((char *) s_kmod_keyword_mask_map[index].keyword)) - goto out; - - if (*mask & s_kmod_keyword_mask_map[index].mask_val) { - if ((strlen(kernel_debug_string) + - strlen(s_kmod_keyword_mask_map[index].keyword)) - < ORANGEFS_MAX_DEBUG_STRING_LEN - 1) { - strcat(kernel_debug_string, - s_kmod_keyword_mask_map[index].keyword); - strcat(kernel_debug_string, ","); - } else { - gossip_err("%s: overflow!\n", __func__); - strcpy(kernel_debug_string, ORANGEFS_ALL); - goto out; - } - } - -out: - - return; -} - -void do_c_string(void *c_mask, int index) -{ - struct client_debug_mask *mask = (struct client_debug_mask *) c_mask; - - if (keyword_is_amalgam(cdm_array[index].keyword)) - goto out; - - if ((mask->mask1 & cdm_array[index].mask1) || - (mask->mask2 & cdm_array[index].mask2)) { - if ((strlen(client_debug_string) + - strlen(cdm_array[index].keyword) + 1) - < ORANGEFS_MAX_DEBUG_STRING_LEN - 2) { - strcat(client_debug_string, - cdm_array[index].keyword); - strcat(client_debug_string, ","); - } else { - gossip_err("%s: overflow!\n", __func__); - strcpy(client_debug_string, ORANGEFS_ALL); - goto out; - } - } -out: - return; -} - -int keyword_is_amalgam(char *keyword) -{ - int rc = 0; - - if ((!strcmp(keyword, ORANGEFS_ALL)) || (!strcmp(keyword, ORANGEFS_VERBOSE))) - rc = 1; - - return rc; -} - -/* - * kernel = type 0 - * client = type 1 - * - * return 1 if we found an amalgam. - */ -int check_amalgam_keyword(void *mask, int type) -{ - __u64 *k_mask; - struct client_debug_mask *c_mask; - int k_all_index = num_kmod_keyword_mask_map - 1; - int rc = 0; - - if (type) { - c_mask = (struct client_debug_mask *) mask; - - if ((c_mask->mask1 == cdm_array[client_all_index].mask1) && - (c_mask->mask2 == cdm_array[client_all_index].mask2)) { - strcpy(client_debug_string, ORANGEFS_ALL); - rc = 1; - goto out; - } - - if ((c_mask->mask1 == cdm_array[client_verbose_index].mask1) && - (c_mask->mask2 == cdm_array[client_verbose_index].mask2)) { - strcpy(client_debug_string, ORANGEFS_VERBOSE); - rc = 1; - goto out; - } - - } else { - k_mask = (__u64 *) mask; - - if (*k_mask >= s_kmod_keyword_mask_map[k_all_index].mask_val) { - strcpy(kernel_debug_string, ORANGEFS_ALL); - rc = 1; - goto out; - } - } - -out: - - return rc; -} - -/* - * kernel = type 0 - * client = type 1 - */ -void debug_string_to_mask(char *debug_string, void *mask, int type) -{ - char *unchecked_keyword; - int i; - char *strsep_fodder = kstrdup(debug_string, GFP_KERNEL); - char *original_pointer; - int element_count = 0; - struct client_debug_mask *c_mask; - __u64 *k_mask; - - gossip_debug(GOSSIP_UTILS_DEBUG, "%s: start\n", __func__); - - if (type) { - c_mask = (struct client_debug_mask *)mask; - element_count = cdm_element_count; - } else { - k_mask = (__u64 *)mask; - *k_mask = 0; - element_count = num_kmod_keyword_mask_map; - } - - original_pointer = strsep_fodder; - while ((unchecked_keyword = strsep(&strsep_fodder, ","))) - if (strlen(unchecked_keyword)) { - for (i = 0; i < element_count; i++) - if (type) - do_c_mask(i, - unchecked_keyword, - &c_mask); - else - do_k_mask(i, - unchecked_keyword, - &k_mask); - } - - kfree(original_pointer); -} - -void do_c_mask(int i, - char *unchecked_keyword, - struct client_debug_mask **sane_mask) -{ - - if (!strcmp(cdm_array[i].keyword, unchecked_keyword)) { - (**sane_mask).mask1 = (**sane_mask).mask1 | cdm_array[i].mask1; - (**sane_mask).mask2 = (**sane_mask).mask2 | cdm_array[i].mask2; - } -} - -void do_k_mask(int i, char *unchecked_keyword, __u64 **sane_mask) -{ - - if (!strcmp(s_kmod_keyword_mask_map[i].keyword, unchecked_keyword)) - **sane_mask = (**sane_mask) | - s_kmod_keyword_mask_map[i].mask_val; -} diff --git a/fs/orangefs/protocol.h b/fs/orangefs/protocol.h index 3d7418c728f5..971307ad69be 100644 --- a/fs/orangefs/protocol.h +++ b/fs/orangefs/protocol.h @@ -4,26 +4,6 @@ #include <linux/slab.h> #include <linux/ioctl.h> -extern struct client_debug_mask *cdm_array; -extern char *debug_help_string; -extern int help_string_initialized; -extern struct dentry *debug_dir; -extern struct dentry *help_file_dentry; -extern struct dentry *client_debug_dentry; -extern const struct file_operations debug_help_fops; -extern int client_all_index; -extern int client_verbose_index; -extern int cdm_element_count; -#define DEBUG_HELP_STRING_SIZE 4096 -#define HELP_STRING_UNINITIALIZED \ - "Client Debug Keywords are unknown until the first time\n" \ - "the client is started after boot.\n" -#define ORANGEFS_KMOD_DEBUG_HELP_FILE "debug-help" -#define ORANGEFS_KMOD_DEBUG_FILE "kernel-debug" -#define ORANGEFS_CLIENT_DEBUG_FILE "client-debug" -#define ORANGEFS_VERBOSE "verbose" -#define ORANGEFS_ALL "all" - /* pvfs2-config.h ***********************************************************/ #define ORANGEFS_VERSION_MAJOR 2 #define ORANGEFS_VERSION_MINOR 9 @@ -426,13 +406,12 @@ do { \ printk(KERN_DEBUG fmt, ##__VA_ARGS__); \ } while (0) #else -extern __u64 gossip_debug_mask; -extern struct client_debug_mask client_debug_mask; +extern __u64 orangefs_gossip_debug_mask; /* try to avoid function call overhead by checking masks in macro */ #define gossip_debug(mask, fmt, ...) \ do { \ - if (gossip_debug_mask & (mask)) \ + if (orangefs_gossip_debug_mask & (mask)) \ printk(KERN_DEBUG fmt, ##__VA_ARGS__); \ } while (0) #endif /* GOSSIP_DISABLE_DEBUG */ diff --git a/fs/orangefs/super.c b/fs/orangefs/super.c index b9da9a0281c9..c48859f16e7b 100644 --- a/fs/orangefs/super.c +++ b/fs/orangefs/super.c @@ -33,6 +33,7 @@ static const match_table_t tokens = { { Opt_err, NULL } }; +uint64_t orangefs_features; static int parse_mount_options(struct super_block *sb, char *options, int silent) @@ -249,6 +250,19 @@ int orangefs_remount(struct orangefs_sb_info_s *orangefs_sb) } 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", 0); + orangefs_features = new_op->downcall.resp.features.features; + op_release(new_op); + } else { + orangefs_features = 0; + } + return ret; } @@ -492,6 +506,19 @@ struct dentry *orangefs_mount(struct file_system_type *fst, list_add_tail(&ORANGEFS_SB(sb)->list, &orangefs_superblocks); spin_unlock(&orangefs_superblocks_lock); op_release(new_op); + + if (orangefs_userspace_version >= 20906) { + new_op = op_alloc(ORANGEFS_VFS_OP_FEATURES); + if (!new_op) + return ERR_PTR(-ENOMEM); + new_op->upcall.req.features.features = 0; + ret = service_operation(new_op, "orangefs_features", 0); + orangefs_features = new_op->downcall.resp.features.features; + op_release(new_op); + } else { + orangefs_features = 0; + } + return dget(sb->s_root); free_op: @@ -530,8 +557,8 @@ void orangefs_kill_sb(struct super_block *sb) * make sure that ORANGEFS_DEV_REMOUNT_ALL loop that might've seen us * gets completed before we free the dang thing. */ - mutex_lock(&request_mutex); - mutex_unlock(&request_mutex); + mutex_lock(&orangefs_request_mutex); + mutex_unlock(&orangefs_request_mutex); /* free the orangefs superblock private data */ kfree(ORANGEFS_SB(sb)); diff --git a/fs/orangefs/upcall.h b/fs/orangefs/upcall.h index 001b20239407..af0b0e36d559 100644 --- a/fs/orangefs/upcall.h +++ b/fs/orangefs/upcall.h @@ -98,7 +98,7 @@ struct orangefs_truncate_request_s { __s64 size; }; -struct orangefs_mmap_ra_cache_flush_request_s { +struct orangefs_ra_cache_flush_request_s { struct orangefs_object_kref refn; }; @@ -179,12 +179,18 @@ enum orangefs_param_request_op { ORANGEFS_PARAM_REQUEST_OP_CAPCACHE_SOFT_LIMIT = 23, ORANGEFS_PARAM_REQUEST_OP_CAPCACHE_RECLAIM_PERCENTAGE = 24, ORANGEFS_PARAM_REQUEST_OP_TWO_MASK_VALUES = 25, + ORANGEFS_PARAM_REQUEST_OP_READAHEAD_SIZE = 26, + ORANGEFS_PARAM_REQUEST_OP_READAHEAD_COUNT = 27, + ORANGEFS_PARAM_REQUEST_OP_READAHEAD_COUNT_SIZE = 28, }; struct orangefs_param_request_s { enum orangefs_param_request_type type; enum orangefs_param_request_op op; - __s64 value; + union { + __s64 value64; + __s32 value32[2]; + } u; char s_value[ORANGEFS_MAX_DEBUG_STRING_LEN]; }; @@ -204,6 +210,11 @@ struct orangefs_fs_key_request_s { __s32 __pad1; }; +/* 2.9.6 */ +struct orangefs_features_request_s { + __u64 features; +}; + struct orangefs_upcall_s { __s32 type; __u32 uid; @@ -228,7 +239,7 @@ struct orangefs_upcall_s { struct orangefs_rename_request_s rename; struct orangefs_statfs_request_s statfs; struct orangefs_truncate_request_s truncate; - struct orangefs_mmap_ra_cache_flush_request_s ra_cache_flush; + struct orangefs_ra_cache_flush_request_s ra_cache_flush; struct orangefs_fs_mount_request_s fs_mount; struct orangefs_fs_umount_request_s fs_umount; struct orangefs_getxattr_request_s getxattr; @@ -240,6 +251,7 @@ struct orangefs_upcall_s { struct orangefs_param_request_s param; struct orangefs_perf_count_request_s perf_count; struct orangefs_fs_key_request_s fs_key; + struct orangefs_features_request_s features; } req; }; diff --git a/fs/orangefs/waitqueue.c b/fs/orangefs/waitqueue.c index 31635bc303fe..abcfa3fa9992 100644 --- a/fs/orangefs/waitqueue.c +++ b/fs/orangefs/waitqueue.c @@ -87,9 +87,9 @@ retry_servicing: */ if (!(flags & ORANGEFS_OP_NO_MUTEX)) { if (flags & ORANGEFS_OP_INTERRUPTIBLE) - ret = mutex_lock_interruptible(&request_mutex); + ret = mutex_lock_interruptible(&orangefs_request_mutex); else - ret = mutex_lock_killable(&request_mutex); + ret = mutex_lock_killable(&orangefs_request_mutex); /* * check to see if we were interrupted while waiting for * mutex @@ -129,7 +129,7 @@ retry_servicing: spin_unlock(&orangefs_request_list_lock); if (!(flags & ORANGEFS_OP_NO_MUTEX)) - mutex_unlock(&request_mutex); + mutex_unlock(&orangefs_request_mutex); ret = wait_for_matching_downcall(op, timeout, flags & ORANGEFS_OP_INTERRUPTIBLE); @@ -272,9 +272,9 @@ static void } else if (op_state_in_progress(op)) { /* op must be removed from the in progress htable */ spin_unlock(&op->lock); - spin_lock(&htable_ops_in_progress_lock); + spin_lock(&orangefs_htable_ops_in_progress_lock); list_del_init(&op->list); - spin_unlock(&htable_ops_in_progress_lock); + spin_unlock(&orangefs_htable_ops_in_progress_lock); gossip_debug(GOSSIP_WAIT_DEBUG, "Interrupted: Removed op %p" " from htable_ops_in_progress\n", |