sunrpc: refactor pool_mode setting code

Allow the pool_mode setting code to be called from internal callers
so we can call it from a new netlink op. Add a new svc_pool_map_get
function to return the current setting. Change the existing module
parameter handling to use the new interfaces under the hood.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>

authored by Jeff Layton and committed by Chuck Lever 5f71f3c3 7f5c330b

+66 -21
+2
include/linux/sunrpc/svc.h
··· 399 399 /* 400 400 * Function prototypes. 401 401 */ 402 + int sunrpc_set_pool_mode(const char *val); 403 + int sunrpc_get_pool_mode(char *val, size_t size); 402 404 int svc_rpcb_setup(struct svc_serv *serv, struct net *net); 403 405 void svc_rpcb_cleanup(struct svc_serv *serv, struct net *net); 404 406 int svc_bind(struct svc_serv *serv, struct net *net);
+64 -21
net/sunrpc/svc.c
··· 72 72 static DEFINE_MUTEX(svc_pool_map_mutex);/* protects svc_pool_map.count only */ 73 73 74 74 static int 75 - param_set_pool_mode(const char *val, const struct kernel_param *kp) 75 + __param_set_pool_mode(const char *val, struct svc_pool_map *m) 76 76 { 77 - int *ip = (int *)kp->arg; 78 - struct svc_pool_map *m = &svc_pool_map; 79 - int err; 77 + int err, mode; 80 78 81 79 mutex_lock(&svc_pool_map_mutex); 82 80 83 - err = -EBUSY; 84 - if (m->count) 85 - goto out; 86 - 87 81 err = 0; 88 82 if (!strncmp(val, "auto", 4)) 89 - *ip = SVC_POOL_AUTO; 83 + mode = SVC_POOL_AUTO; 90 84 else if (!strncmp(val, "global", 6)) 91 - *ip = SVC_POOL_GLOBAL; 85 + mode = SVC_POOL_GLOBAL; 92 86 else if (!strncmp(val, "percpu", 6)) 93 - *ip = SVC_POOL_PERCPU; 87 + mode = SVC_POOL_PERCPU; 94 88 else if (!strncmp(val, "pernode", 7)) 95 - *ip = SVC_POOL_PERNODE; 89 + mode = SVC_POOL_PERNODE; 96 90 else 97 91 err = -EINVAL; 98 92 93 + if (err) 94 + goto out; 95 + 96 + if (m->count == 0) 97 + m->mode = mode; 98 + else if (mode != m->mode) 99 + err = -EBUSY; 99 100 out: 100 101 mutex_unlock(&svc_pool_map_mutex); 101 102 return err; 102 103 } 103 104 104 105 static int 105 - param_get_pool_mode(char *buf, const struct kernel_param *kp) 106 + param_set_pool_mode(const char *val, const struct kernel_param *kp) 106 107 { 107 - int *ip = (int *)kp->arg; 108 + struct svc_pool_map *m = kp->arg; 108 109 109 - switch (*ip) 110 + return __param_set_pool_mode(val, m); 111 + } 112 + 113 + int sunrpc_set_pool_mode(const char *val) 114 + { 115 + return __param_set_pool_mode(val, &svc_pool_map); 116 + } 117 + EXPORT_SYMBOL(sunrpc_set_pool_mode); 118 + 119 + /** 120 + * sunrpc_get_pool_mode - get the current pool_mode for the host 121 + * @buf: where to write the current pool_mode 122 + * @size: size of @buf 123 + * 124 + * Grab the current pool_mode from the svc_pool_map and write 125 + * the resulting string to @buf. Returns the number of characters 126 + * written to @buf (a'la snprintf()). 127 + */ 128 + int 129 + sunrpc_get_pool_mode(char *buf, size_t size) 130 + { 131 + struct svc_pool_map *m = &svc_pool_map; 132 + 133 + switch (m->mode) 110 134 { 111 135 case SVC_POOL_AUTO: 112 - return sysfs_emit(buf, "auto\n"); 136 + return snprintf(buf, size, "auto"); 113 137 case SVC_POOL_GLOBAL: 114 - return sysfs_emit(buf, "global\n"); 138 + return snprintf(buf, size, "global"); 115 139 case SVC_POOL_PERCPU: 116 - return sysfs_emit(buf, "percpu\n"); 140 + return snprintf(buf, size, "percpu"); 117 141 case SVC_POOL_PERNODE: 118 - return sysfs_emit(buf, "pernode\n"); 142 + return snprintf(buf, size, "pernode"); 119 143 default: 120 - return sysfs_emit(buf, "%d\n", *ip); 144 + return snprintf(buf, size, "%d", m->mode); 121 145 } 146 + } 147 + EXPORT_SYMBOL(sunrpc_get_pool_mode); 148 + 149 + static int 150 + param_get_pool_mode(char *buf, const struct kernel_param *kp) 151 + { 152 + char str[16]; 153 + int len; 154 + 155 + len = sunrpc_get_pool_mode(str, ARRAY_SIZE(str)); 156 + 157 + /* Ensure we have room for newline and NUL */ 158 + len = min_t(int, len, ARRAY_SIZE(str) - 2); 159 + 160 + /* tack on the newline */ 161 + str[len] = '\n'; 162 + str[len + 1] = '\0'; 163 + 164 + return sysfs_emit(buf, str); 122 165 } 123 166 124 167 module_param_call(pool_mode, param_set_pool_mode, param_get_pool_mode, 125 - &svc_pool_map.mode, 0644); 168 + &svc_pool_map, 0644); 126 169 127 170 /* 128 171 * Detect best pool mapping mode heuristically,