From f2ee3b759593c184f1249e03d613a84b4b69db2b Mon Sep 17 00:00:00 2001 From: Martin Brandenburg Date: Tue, 9 Aug 2016 15:59:26 -0400 Subject: orangefs: record userspace version for feature compatbility The client reports its version to the kernel on startup. We already test that it is above the minimum version. Now we record it in a global variable so code elsewhere can consult it before making a request the client may not understand. Signed-off-by: Martin Brandenburg --- fs/orangefs/devorangefs-req.c | 10 ++++++++++ fs/orangefs/orangefs-kernel.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/fs/orangefs/devorangefs-req.c b/fs/orangefs/devorangefs-req.c index a287a66d94e3..7c40e653e526 100644 --- a/fs/orangefs/devorangefs-req.c +++ b/fs/orangefs/devorangefs-req.c @@ -17,6 +17,8 @@ /* this file implements the /dev/pvfs2-req device node */ +uint32_t userspace_version; + static int open_access_count; #define DUMP_DEVICE_ERROR() \ @@ -387,6 +389,13 @@ static ssize_t orangefs_devreq_write_iter(struct kiocb *iocb, return -EPROTO; } + if (!userspace_version) { + userspace_version = head.version; + } else if (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 +536,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; + userspace_version = 0; mutex_unlock(&devreq_mutex); return 0; } diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h index 633c07a6e3d8..ff3566a8388f 100644 --- a/fs/orangefs/orangefs-kernel.h +++ b/fs/orangefs/orangefs-kernel.h @@ -506,6 +506,8 @@ ssize_t orangefs_inode_read(struct inode *inode, /* * defined in devorangefs-req.c */ +extern uint32_t userspace_version; + int orangefs_dev_init(void); void orangefs_dev_cleanup(void); int is_daemon_in_service(void); -- cgit v1.2.3-59-g8ed1b From 482664ddba81b3a5404fd083bb9697dfffc0b6a4 Mon Sep 17 00:00:00 2001 From: Martin Brandenburg Date: Fri, 12 Aug 2016 12:02:31 -0400 Subject: orangefs: add features op This is a new userspace operation, which will be done if the client-core version is greater than or equal to 2.9.6. This will provide a way to implement optional features and to determine which features are supported by the client-core. If the client-core version is older than 2.9.6, no optional features are supported and the op will not be done. The intent is to allow protocol extensions without relying on the client-core's current behavior of ignoring what it doesn't understand. Signed-off-by: Martin Brandenburg --- fs/orangefs/devorangefs-req.c | 10 +++++----- fs/orangefs/downcall.h | 6 ++++++ fs/orangefs/orangefs-cache.c | 2 ++ fs/orangefs/orangefs-dev-proto.h | 4 ++++ fs/orangefs/orangefs-kernel.h | 4 +++- fs/orangefs/super.c | 27 +++++++++++++++++++++++++++ fs/orangefs/upcall.h | 6 ++++++ 7 files changed, 53 insertions(+), 6 deletions(-) diff --git a/fs/orangefs/devorangefs-req.c b/fs/orangefs/devorangefs-req.c index 7c40e653e526..ec1a5ff1d843 100644 --- a/fs/orangefs/devorangefs-req.c +++ b/fs/orangefs/devorangefs-req.c @@ -17,7 +17,7 @@ /* this file implements the /dev/pvfs2-req device node */ -uint32_t userspace_version; +uint32_t orangefs_userspace_version; static int open_access_count; @@ -389,9 +389,9 @@ static ssize_t orangefs_devreq_write_iter(struct kiocb *iocb, return -EPROTO; } - if (!userspace_version) { - userspace_version = head.version; - } else if (userspace_version != head.version) { + 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; } @@ -536,7 +536,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; - userspace_version = 0; + orangefs_userspace_version = 0; mutex_unlock(&devreq_mutex); return 0; } diff --git a/fs/orangefs/downcall.h b/fs/orangefs/downcall.h index db6e8722a89e..3b8923f8bf21 100644 --- a/fs/orangefs/downcall.h +++ b/fs/orangefs/downcall.h @@ -101,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; @@ -122,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/orangefs-cache.c b/fs/orangefs/orangefs-cache.c index eb0b6e00b519..aa3830b741c7 100644 --- a/fs/orangefs/orangefs-cache.c +++ b/fs/orangefs/orangefs-cache.c @@ -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-dev-proto.h b/fs/orangefs/orangefs-dev-proto.h index 71902899b1da..a3d84ffee905 100644 --- a/fs/orangefs/orangefs-dev-proto.h +++ b/fs/orangefs/orangefs-dev-proto.h @@ -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 ff3566a8388f..6cf3f467fd89 100644 --- a/fs/orangefs/orangefs-kernel.h +++ b/fs/orangefs/orangefs-kernel.h @@ -447,6 +447,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,7 +508,7 @@ ssize_t orangefs_inode_read(struct inode *inode, /* * defined in devorangefs-req.c */ -extern uint32_t userspace_version; +extern uint32_t orangefs_userspace_version; int orangefs_dev_init(void); void orangefs_dev_cleanup(void); diff --git a/fs/orangefs/super.c b/fs/orangefs/super.c index b9da9a0281c9..3e484a667340 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: diff --git a/fs/orangefs/upcall.h b/fs/orangefs/upcall.h index 7c29fdf08ec5..af0b0e36d559 100644 --- a/fs/orangefs/upcall.h +++ b/fs/orangefs/upcall.h @@ -210,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; @@ -246,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; }; -- cgit v1.2.3-59-g8ed1b From c51e012942a7594f59db5611db14fa4a29624a10 Mon Sep 17 00:00:00 2001 From: Martin Brandenburg Date: Fri, 12 Aug 2016 16:12:09 -0400 Subject: orangefs: do not allow client readahead cache without feature bit Signed-off-by: Martin Brandenburg --- fs/orangefs/file.c | 13 ++++++++----- fs/orangefs/orangefs-sysfs.c | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c index 43c08b5c7168..fe5e1eac9561 100644 --- a/fs/orangefs/file.c +++ b/fs/orangefs/file.c @@ -624,11 +624,14 @@ static int orangefs_file_release(struct inode *inode, struct file *file) 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)) { - 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"); + 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); } diff --git a/fs/orangefs/orangefs-sysfs.c b/fs/orangefs/orangefs-sysfs.c index 2fe9a3a2117b..ed5ee33d0f7e 100644 --- a/fs/orangefs/orangefs-sysfs.c +++ b/fs/orangefs/orangefs-sysfs.c @@ -842,6 +842,16 @@ static int sysfs_service_op_show(char *kobj_id, char *buf, void *attr) if (!strcmp(kobj_id, ORANGEFS_KOBJ_ID)) { orangefs_attr = (struct orangefs_attribute *)attr; + /* Drop unsupported requests first. */ + if (!(orangefs_features & ORANGEFS_FEATURE_READAHEAD) && + (!strcmp(orangefs_attr->attr.name, "readahead_count") || + !strcmp(orangefs_attr->attr.name, "readahead_size") || + !strcmp(orangefs_attr->attr.name, + "readahead_count_size"))) { + rc = -EINVAL; + goto out; + } + if (!strcmp(orangefs_attr->attr.name, "perf_history_size")) new_op->upcall.req.param.op = ORANGEFS_PARAM_REQUEST_OP_PERF_HISTORY_SIZE; @@ -1133,6 +1143,15 @@ static int sysfs_service_op_store(char *kobj_id, const char *buf, void *attr) if (!strcmp(kobj_id, ORANGEFS_KOBJ_ID)) { orangefs_attr = (struct orangefs_attribute *)attr; + /* Drop unsupported requests first. */ + if (!(orangefs_features & ORANGEFS_FEATURE_READAHEAD) && + (!strcmp(orangefs_attr->attr.name, "readahead_count") || + !strcmp(orangefs_attr->attr.name, "readahead_size") || + !strcmp(orangefs_attr->attr.name, + "readahead_count_size"))) { + rc = -EINVAL; + goto out; + } if (!strcmp(orangefs_attr->attr.name, "perf_history_size")) { if (val > 0) { -- cgit v1.2.3-59-g8ed1b From 0c95ad76361f1d75a1ffdf82deafbcec44d19c42 Mon Sep 17 00:00:00 2001 From: Martin Brandenburg Date: Wed, 21 Sep 2016 12:37:23 -0400 Subject: orangefs: bump minimum userspace version OrangeFS 2.9.6 was released without support for the features op. Thus OrangeFS 2.9.7 will be required to use it. Signed-off-by: Martin Brandenburg --- fs/orangefs/super.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/orangefs/super.c b/fs/orangefs/super.c index 3e484a667340..b4ab1c1e8278 100644 --- a/fs/orangefs/super.c +++ b/fs/orangefs/super.c @@ -251,7 +251,7 @@ int orangefs_remount(struct orangefs_sb_info_s *orangefs_sb) op_release(new_op); - if (orangefs_userspace_version >= 20906) { + if (orangefs_userspace_version >= 20907) { new_op = op_alloc(ORANGEFS_VFS_OP_FEATURES); if (!new_op) return -ENOMEM; @@ -507,7 +507,7 @@ struct dentry *orangefs_mount(struct file_system_type *fst, spin_unlock(&orangefs_superblocks_lock); op_release(new_op); - if (orangefs_userspace_version >= 20906) { + if (orangefs_userspace_version >= 20907) { new_op = op_alloc(ORANGEFS_VFS_OP_FEATURES); if (!new_op) return ERR_PTR(-ENOMEM); -- cgit v1.2.3-59-g8ed1b