* [PATCH 01/22] NFSD: clean up failover sysctl function naming
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
@ 2008-12-12 21:57 ` Chuck Lever
2008-12-12 21:57 ` [PATCH 02/22] NFSD: Fix a handful of coding style issues in write_filehandle() Chuck Lever
` (22 subsequent siblings)
23 siblings, 0 replies; 37+ messages in thread
From: Chuck Lever @ 2008-12-12 21:57 UTC (permalink / raw)
To: bfields; +Cc: aime.le-rouzic, linux-nfs
Clean up: Rename recently-added failover functions to match the naming
convention in fs/nfsd/nfsctl.c.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfsd/nfsctl.c | 13 ++++++-------
1 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index e3f9783..6ebc607 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -84,6 +84,8 @@ static ssize_t write_unexport(struct file *file, char *buf, size_t size);
static ssize_t write_getfd(struct file *file, char *buf, size_t size);
static ssize_t write_getfs(struct file *file, char *buf, size_t size);
static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
+static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size);
+static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size);
static ssize_t write_threads(struct file *file, char *buf, size_t size);
static ssize_t write_pool_threads(struct file *file, char *buf, size_t size);
static ssize_t write_versions(struct file *file, char *buf, size_t size);
@@ -94,9 +96,6 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
#endif
-static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size);
-static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size);
-
static ssize_t (*write_op[])(struct file *, char *, size_t) = {
[NFSD_Svc] = write_svc,
[NFSD_Add] = write_add,
@@ -106,8 +105,8 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
[NFSD_Getfd] = write_getfd,
[NFSD_Getfs] = write_getfs,
[NFSD_Fh] = write_filehandle,
- [NFSD_FO_UnlockIP] = failover_unlock_ip,
- [NFSD_FO_UnlockFS] = failover_unlock_fs,
+ [NFSD_FO_UnlockIP] = write_unlock_ip,
+ [NFSD_FO_UnlockFS] = write_unlock_fs,
[NFSD_Threads] = write_threads,
[NFSD_Pool_Threads] = write_pool_threads,
[NFSD_Versions] = write_versions,
@@ -309,7 +308,7 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
return err;
}
-static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size)
+static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)
{
struct sockaddr_in sin = {
.sin_family = AF_INET,
@@ -339,7 +338,7 @@ static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size)
return nlmsvc_unlock_all_by_ip((struct sockaddr *)&sin);
}
-static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size)
+static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size)
{
struct path path;
char *fo_path;
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH 02/22] NFSD: Fix a handful of coding style issues in write_filehandle()
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2008-12-12 21:57 ` [PATCH 01/22] NFSD: clean up failover sysctl function naming Chuck Lever
@ 2008-12-12 21:57 ` Chuck Lever
2008-12-12 21:57 ` [PATCH 03/22] NFSD: Replace open-coded integer with macro Chuck Lever
` (21 subsequent siblings)
23 siblings, 0 replies; 37+ messages in thread
From: Chuck Lever @ 2008-12-12 21:57 UTC (permalink / raw)
To: bfields; +Cc: aime.le-rouzic, linux-nfs
Clean up: follow kernel coding style.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfsd/nfsctl.c | 9 ++++++---
1 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 6ebc607..28d4966 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -390,11 +390,13 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
dname = mesg;
len = qword_get(&mesg, dname, size);
- if (len <= 0) return -EINVAL;
+ if (len <= 0)
+ return -EINVAL;
path = dname+len+1;
len = qword_get(&mesg, path, size);
- if (len <= 0) return -EINVAL;
+ if (len <= 0)
+ return -EINVAL;
len = get_int(&mesg, &maxsize);
if (len)
@@ -418,7 +420,8 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
if (len)
return len;
- mesg = buf; len = SIMPLE_TRANSACTION_LIMIT;
+ mesg = buf;
+ len = SIMPLE_TRANSACTION_LIMIT;
qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size);
mesg[-1] = '\n';
return mesg - buf;
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH 03/22] NFSD: Replace open-coded integer with macro
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2008-12-12 21:57 ` [PATCH 01/22] NFSD: clean up failover sysctl function naming Chuck Lever
2008-12-12 21:57 ` [PATCH 02/22] NFSD: Fix a handful of coding style issues in write_filehandle() Chuck Lever
@ 2008-12-12 21:57 ` Chuck Lever
2008-12-12 21:57 ` [PATCH 04/22] NFSD: Add documenting comments for nfsctl interface Chuck Lever
` (20 subsequent siblings)
23 siblings, 0 replies; 37+ messages in thread
From: Chuck Lever @ 2008-12-12 21:57 UTC (permalink / raw)
To: bfields; +Cc: aime.le-rouzic, linux-nfs
Clean up: Instead of open-coding 2049, use the NFS_PORT macro.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfsd/nfsctl.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 28d4966..f988c81 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -439,9 +439,9 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
rv = get_int(&mesg, &newthreads);
if (rv)
return rv;
- if (newthreads <0)
+ if (newthreads < 0)
return -EINVAL;
- rv = nfsd_svc(2049, newthreads);
+ rv = nfsd_svc(NFS_PORT, newthreads);
if (rv)
return rv;
}
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH 04/22] NFSD: Add documenting comments for nfsctl interface
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (2 preceding siblings ...)
2008-12-12 21:57 ` [PATCH 03/22] NFSD: Replace open-coded integer with macro Chuck Lever
@ 2008-12-12 21:57 ` Chuck Lever
2008-12-12 21:57 ` [PATCH 05/22] NFSD: Add helper functions for __write_ports() Chuck Lever
` (19 subsequent siblings)
23 siblings, 0 replies; 37+ messages in thread
From: Chuck Lever @ 2008-12-12 21:57 UTC (permalink / raw)
To: bfields; +Cc: aime.le-rouzic, linux-nfs
Document the NFSD sysctl interface laid out in fs/nfsd/nfsctl.c.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfsd/nfsctl.c | 453 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 437 insertions(+), 16 deletions(-)
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index f988c81..5c75f8a 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -175,10 +175,24 @@ static const struct file_operations exports_operations = {
/*----------------------------------------------------------------------------*/
/*
* payload - write methods
- * If the method has a response, the response should be put in buf,
- * and the length returned. Otherwise return 0 or and -error.
*/
+/**
+ * write_svc - Start kernel's NFSD server
+ *
+ * Deprecated. /proc/fs/nfsd/threads is preferred.
+ * Function remains to support old versions of nfs-utils.
+ *
+ * Input:
+ * buf: struct nfsctl_svc
+ * svc_port: port number of this
+ * server's listener
+ * svc_nthreads: number of threads to start
+ * size: size in bytes of passed in nfsctl_svc
+ * Output:
+ * On success: returns zero
+ * On error: return code is negative errno value
+ */
static ssize_t write_svc(struct file *file, char *buf, size_t size)
{
struct nfsctl_svc *data;
@@ -188,6 +202,30 @@ static ssize_t write_svc(struct file *file, char *buf, size_t size)
return nfsd_svc(data->svc_port, data->svc_nthreads);
}
+/**
+ * write_add - Add or modify client entry in auth unix cache
+ *
+ * Deprecated. /proc/net/rpc/auth.unix.ip is preferred.
+ * Function remains to support old versions of nfs-utils.
+ *
+ * Input:
+ * buf: struct nfsctl_client
+ * cl_ident: '\0'-terminated C string
+ * containing domain name
+ * of client
+ * cl_naddr: no. of items in cl_addrlist
+ * cl_addrlist: array of client addresses
+ * cl_fhkeytype: ignored
+ * cl_fhkeylen: ignored
+ * cl_fhkey: ignored
+ * size: size in bytes of passed in nfsctl_client
+ * Output:
+ * On success: returns zero
+ * On error: return code is negative errno value
+ *
+ * Note: Only AF_INET client addresses are passed in, since
+ * nfsctl_client.cl_addrlist contains only in_addr fields for addresses.
+ */
static ssize_t write_add(struct file *file, char *buf, size_t size)
{
struct nfsctl_client *data;
@@ -197,6 +235,30 @@ static ssize_t write_add(struct file *file, char *buf, size_t size)
return exp_addclient(data);
}
+/**
+ * write_del - Remove client from auth unix cache
+ *
+ * Deprecated. /proc/net/rpc/auth.unix.ip is preferred.
+ * Function remains to support old versions of nfs-utils.
+ *
+ * Input:
+ * buf: struct nfsctl_client
+ * cl_ident: '\0'-terminated C string
+ * containing domain name
+ * of client
+ * cl_naddr: ignored
+ * cl_addrlist: ignored
+ * cl_fhkeytype: ignored
+ * cl_fhkeylen: ignored
+ * cl_fhkey: ignored
+ * size: size in bytes of passed in nfsctl_client
+ * Output:
+ * On success: returns zero
+ * On error: return code is negative errno value
+ *
+ * Note: Only AF_INET client addresses are passed in, since
+ * nfsctl_client.cl_addrlist contains only in_addr fields for addresses.
+ */
static ssize_t write_del(struct file *file, char *buf, size_t size)
{
struct nfsctl_client *data;
@@ -206,6 +268,33 @@ static ssize_t write_del(struct file *file, char *buf, size_t size)
return exp_delclient(data);
}
+/**
+ * write_export - Export part or all of a local file system
+ *
+ * Deprecated. /proc/net/rpc/{nfsd.export,nfsd.fh} are preferred.
+ * Function remains to support old versions of nfs-utils.
+ *
+ * Input:
+ * buf: struct nfsctl_export
+ * ex_client: '\0'-terminated C string
+ * containing domain name
+ * of client allowed to access
+ * this export
+ * ex_path: '\0'-terminated C string
+ * containing pathname of
+ * directory in local file system
+ * ex_dev: fsid to use for this export
+ * ex_ino: ignored
+ * ex_flags: export flags for this export
+ * ex_anon_uid: UID to use for anonymous
+ * requests
+ * ex_anon_gid: GID to use for anonymous
+ * requests
+ * size: size in bytes of passed in nfsctl_export
+ * Output:
+ * On success: returns zero
+ * On error: return code is negative errno value
+ */
static ssize_t write_export(struct file *file, char *buf, size_t size)
{
struct nfsctl_export *data;
@@ -215,6 +304,31 @@ static ssize_t write_export(struct file *file, char *buf, size_t size)
return exp_export(data);
}
+/**
+ * write_unexport - Unexport a previously exported file system
+ *
+ * Deprecated. /proc/net/rpc/{nfsd.export,nfsd.fh} are preferred.
+ * Function remains to support old versions of nfs-utils.
+ *
+ * Input:
+ * buf: struct nfsctl_export
+ * ex_client: '\0'-terminated C string
+ * containing domain name
+ * of client no longer allowed
+ * to access this export
+ * ex_path: '\0'-terminated C string
+ * containing pathname of
+ * directory in local file system
+ * ex_dev: ignored
+ * ex_ino: ignored
+ * ex_flags: ignored
+ * ex_anon_uid: ignored
+ * ex_anon_gid: ignored
+ * size: size in bytes of passed in nfsctl_export
+ * Output:
+ * On success: returns zero
+ * On error: return code is negative errno value
+ */
static ssize_t write_unexport(struct file *file, char *buf, size_t size)
{
struct nfsctl_export *data;
@@ -225,6 +339,30 @@ static ssize_t write_unexport(struct file *file, char *buf, size_t size)
return exp_unexport(data);
}
+/**
+ * write_getfs - Get a variable-length NFS file handle by path
+ *
+ * Deprecated. /proc/fs/nfsd/filehandle is preferred.
+ * Function remains to support old versions of nfs-utils.
+ *
+ * Input:
+ * buf: struct nfsctl_fsparm
+ * gd_addr: socket address of client
+ * gd_path: '\0'-terminated C string
+ * containing pathname of
+ * directory in local file system
+ * gd_maxlen: maximum size of returned file
+ * handle
+ * size: size in bytes of passed in nfsctl_fsparm
+ * Output:
+ * On success: passed-in buffer filled with a knfsd_fh structure
+ * (a variable-length raw NFS file handle);
+ * return code is the size in bytes of the file handle
+ * On error: return code is negative errno value
+ *
+ * Note: Only AF_INET client addresses are passed in, since gd_addr
+ * is the same size as a struct sockaddr_in.
+ */
static ssize_t write_getfs(struct file *file, char *buf, size_t size)
{
struct nfsctl_fsparm *data;
@@ -264,6 +402,29 @@ static ssize_t write_getfs(struct file *file, char *buf, size_t size)
return err;
}
+/**
+ * write_getfd - Get a fixed-length NFS file handle by path (used by mountd)
+ *
+ * Deprecated. /proc/fs/nfsd/filehandle is preferred.
+ * Function remains to support old versions of nfs-utils.
+ *
+ * Input:
+ * buf: struct nfsctl_fdparm
+ * gd_addr: socket address of client
+ * gd_path: '\0'-terminated C string
+ * containing pathname of
+ * directory in local file system
+ * gd_version: fdparm structure version
+ * size: size in bytes of passed in nfsctl_fdparm
+ * Output:
+ * On success: passed-in buffer filled with nfsctl_res
+ * (a fixed-length raw NFS file handle);
+ * return code is the size in bytes of the file handle
+ * On error: return code is negative errno value
+ *
+ * Note: Only AF_INET client addresses are passed in, since gd_addr
+ * is the same size as a struct sockaddr_in.
+ */
static ssize_t write_getfd(struct file *file, char *buf, size_t size)
{
struct nfsctl_fdparm *data;
@@ -308,6 +469,22 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
return err;
}
+/**
+ * write_unlock_ip - Release all locks used by a client
+ *
+ * Experimental.
+ *
+ * Input:
+ * buf: '\n'-terminated C string containing a
+ * presentation format IPv4 address
+ * size: length of C string in @buf
+ * Output:
+ * On success: returns zero if all specified locks were released;
+ * returns one if one or more locks were not released
+ * On error: return code is negative errno value
+ *
+ * Note: Only AF_INET client addresses are passed in
+ */
static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)
{
struct sockaddr_in sin = {
@@ -338,6 +515,20 @@ static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)
return nlmsvc_unlock_all_by_ip((struct sockaddr *)&sin);
}
+/**
+ * write_unlock_fs - Release all locks on a local file system
+ *
+ * Experimental.
+ *
+ * Input:
+ * buf: '\n'-terminated C string containing the
+ * absolute pathname of a local file system
+ * size: length of C string in @buf
+ * Output:
+ * On success: returns zero if all specified locks were released;
+ * returns one if one or more locks were not released
+ * On error: return code is negative errno value
+ */
static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size)
{
struct path path;
@@ -359,21 +550,44 @@ static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size)
if (error)
return error;
+ /*
+ * XXX: Needs better sanity checking. Otherwise we could end up
+ * releasing locks on the wrong file system.
+ *
+ * For example:
+ * 1. Does the path refer to a directory?
+ * 2. Is that directory a mount point, or
+ * 3. Is that directory the root of an exported file system?
+ */
error = nlmsvc_unlock_all_by_sb(path.mnt->mnt_sb);
path_put(&path);
return error;
}
+/**
+ * write_filehandle - Get a variable-length NFS file handle by path
+ *
+ * On input, the buffer contains a '\n'-terminated C string comprised of
+ * three alphanumeric words separated by whitespace. The string may
+ * contain escape sequences.
+ *
+ * Input:
+ * buf:
+ * domain: client domain name
+ * path: export pathname
+ * maxsize: numeric maximum size of
+ * @buf
+ * size: length of C string in @buf
+ * Output:
+ * On success: passed-in buffer filled with '\n'-terminated C
+ * string containing a ASCII hex text version
+ * of the NFS file handle;
+ * return code is the size in bytes of the string
+ * On error: return code is negative errno value
+ */
static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
{
- /* request is:
- * domain path maxsize
- * response is
- * filehandle
- *
- * qword quoting is used, so filehandle will be \x....
- */
char *dname, *path;
int uninitialized_var(maxsize);
char *mesg = buf;
@@ -427,11 +641,36 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
return mesg - buf;
}
+/**
+ * write_threads - Start NFSD, or report the current number of running threads
+ *
+ * Input:
+ * buf: ignored
+ * size: zero
+ * Output:
+ * On success: passed-in buffer filled with '\n'-terminated C
+ * string numeric value representing the number of
+ * running NFSD threads;
+ * return code is the size in bytes of the string
+ * On error: return code is zero
+ *
+ * OR
+ *
+ * Input:
+ * buf: C string containing an unsigned
+ * integer value representing the
+ * number of NFSD threads to start
+ * size: non-zero length of C string in @buf
+ * Output:
+ * On success: NFS service is started;
+ * passed-in buffer filled with '\n'-terminated C
+ * string numeric value representing the number of
+ * running NFSD threads;
+ * return code is the size in bytes of the string
+ * On error: return code is zero or a negative errno value
+ */
static ssize_t write_threads(struct file *file, char *buf, size_t size)
{
- /* if size > 0, look for a number of threads and call nfsd_svc
- * then write out number of threads as reply
- */
char *mesg = buf;
int rv;
if (size > 0) {
@@ -449,6 +688,28 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
return strlen(buf);
}
+/**
+ * write_pool_threads - Set or report the current number of threads per pool
+ *
+ * Input:
+ * buf: ignored
+ * size: zero
+ *
+ * OR
+ *
+ * Input:
+ * buf: C string containing whitespace-
+ * separated unsigned integer values
+ * representing the number of NFSD
+ * threads to start in each pool
+ * size: non-zero length of C string in @buf
+ * Output:
+ * On success: passed-in buffer filled with '\n'-terminated C
+ * string containing integer values representing the
+ * number of NFSD threads in each pool;
+ * return code is the size in bytes of the string
+ * On error: return code is zero or a negative errno value
+ */
static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
{
/* if size > 0, look for an array of number of threads per node
@@ -519,10 +780,6 @@ out_free:
static ssize_t __write_versions(struct file *file, char *buf, size_t size)
{
- /*
- * Format:
- * [-/+]vers [-/+]vers ...
- */
char *mesg = buf;
char *vers, sign;
int len, num;
@@ -580,6 +837,38 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
return len;
}
+/**
+ * write_versions - Set or report the available NFS protocol versions
+ *
+ * Input:
+ * buf: ignored
+ * size: zero
+ * Output:
+ * On success: passed-in buffer filled with '\n'-terminated C
+ * string containing positive or negative integer
+ * values representing the current status of each
+ * protocol version;
+ * return code is the size in bytes of the string
+ * On error: return code is zero or a negative errno value
+ *
+ * OR
+ *
+ * Input:
+ * buf: C string containing whitespace-
+ * separated positive or negative
+ * integer values representing NFS
+ * protocol versions to enable ("+n")
+ * or disable ("-n")
+ * size: non-zero length of C string in @buf
+ * Output:
+ * On success: status of zero or more protocol versions has
+ * been updated; passed-in buffer filled with
+ * '\n'-terminated C string containing positive
+ * or negative integer values representing the
+ * current status of each protocol version;
+ * return code is the size in bytes of the string
+ * On error: return code is zero or a negative errno value
+ */
static ssize_t write_versions(struct file *file, char *buf, size_t size)
{
ssize_t rv;
@@ -689,6 +978,75 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size)
return -EINVAL;
}
+/**
+ * write_ports - Pass a socket file descriptor or transport name to listen on
+ *
+ * Input:
+ * buf: ignored
+ * size: zero
+ * Output:
+ * On success: passed-in buffer filled with a '\n'-terminated C
+ * string containing a whitespace-separated list of
+ * named NFSD listeners;
+ * return code is the size in bytes of the string
+ * On error: return code is zero or a negative errno value
+ *
+ * OR
+ *
+ * Input:
+ * buf: C string containing an unsigned
+ * integer value representing a bound
+ * but unconnected socket that is to be
+ * used as an NFSD listener
+ * size: non-zero length of C string in @buf
+ * Output:
+ * On success: NFS service is started;
+ * passed-in buffer filled with a '\n'-terminated C
+ * string containing a unique alphanumeric name of
+ * the listener;
+ * return code is the size in bytes of the string
+ * On error: return code is a negative errno value
+ *
+ * OR
+ *
+ * Input:
+ * buf: C string containing a "-" followed
+ * by an integer value representing a
+ * previously passed in socket file
+ * descriptor
+ * size: non-zero length of C string in @buf
+ * Output:
+ * On success: NFS service no longer listens on that socket;
+ * passed-in buffer filled with a '\n'-terminated C
+ * string containing a unique name of the listener;
+ * return code is the size in bytes of the string
+ * On error: return code is a negative errno value
+ *
+ * OR
+ *
+ * Input:
+ * buf: C string containing a transport
+ * name and an unsigned integer value
+ * representing the port to listen on,
+ * separated by whitespace
+ * size: non-zero length of C string in @buf
+ * Output:
+ * On success: returns zero; NFS service is started
+ * On error: return code is a negative errno value
+ *
+ * OR
+ *
+ * Input:
+ * buf: C string containing a "-" followed
+ * by a transport name and an unsigned
+ * integer value representing the port
+ * to listen on, separated by whitespace
+ * size: non-zero length of C string in @buf
+ * Output:
+ * On success: returns zero; NFS service no longer listens
+ * on that transport
+ * On error: return code is a negative errno value
+ */
static ssize_t write_ports(struct file *file, char *buf, size_t size)
{
ssize_t rv;
@@ -702,6 +1060,27 @@ static ssize_t write_ports(struct file *file, char *buf, size_t size)
int nfsd_max_blksize;
+/**
+ * write_maxblksize - Set or report the current NFS blksize
+ *
+ * Input:
+ * buf: ignored
+ * size: zero
+ *
+ * OR
+ *
+ * Input:
+ * buf: C string containing an unsigned
+ * integer value representing the new
+ * NFS blksize
+ * size: non-zero length of C string in @buf
+ * Output:
+ * On success: passed-in buffer filled with '\n'-terminated C string
+ * containing numeric value of the current NFS blksize
+ * setting;
+ * return code is the size in bytes of the string
+ * On error: return code is zero or a negative errno value
+ */
static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
{
char *mesg = buf;
@@ -754,6 +1133,27 @@ static ssize_t __write_leasetime(struct file *file, char *buf, size_t size)
return strlen(buf);
}
+/**
+ * write_leasetime - Set or report the current NFSv4 lease time
+ *
+ * Input:
+ * buf: ignored
+ * size: zero
+ *
+ * OR
+ *
+ * Input:
+ * buf: C string containing an unsigned
+ * integer value representing the new
+ * NFSv4 lease expiry time
+ * size: non-zero length of C string in @buf
+ * Output:
+ * On success: passed-in buffer filled with '\n'-terminated C
+ * string containing unsigned integer value of the
+ * current lease expiry time;
+ * return code is the size in bytes of the string
+ * On error: return code is zero or a negative errno value
+ */
static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
{
ssize_t rv;
@@ -790,6 +1190,27 @@ static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size)
return strlen(buf);
}
+/**
+ * write_recoverydir - Set or report the pathname of the recovery directory
+ *
+ * Input:
+ * buf: ignored
+ * size: zero
+ *
+ * OR
+ *
+ * Input:
+ * buf: C string containing the pathname
+ * of the directory on a local file
+ * system containing permanent NFSv4
+ * recovery data
+ * size: non-zero length of C string in @buf
+ * Output:
+ * On success: passed-in buffer filled with '\n'-terminated C string
+ * containing the current recovery pathname setting;
+ * return code is the size in bytes of the string
+ * On error: return code is zero or a negative errno value
+ */
static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
{
ssize_t rv;
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH 05/22] NFSD: Add helper functions for __write_ports()
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (3 preceding siblings ...)
2008-12-12 21:57 ` [PATCH 04/22] NFSD: Add documenting comments for nfsctl interface Chuck Lever
@ 2008-12-12 21:57 ` Chuck Lever
[not found] ` <20081212215742.24332.36578.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2008-12-12 21:57 ` [PATCH 06/22] NFSD: Refactor __write_ports() Chuck Lever
` (18 subsequent siblings)
23 siblings, 1 reply; 37+ messages in thread
From: Chuck Lever @ 2008-12-12 21:57 UTC (permalink / raw)
To: bfields; +Cc: aime.le-rouzic, linux-nfs
Clean up: I'd like to refactor __write_ports() to make it easier to
understand and maintain. Introduce a set of helper functions to
handle the details of the __write_ports() function.
New helpers are not used yet.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfsd/nfsctl.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 110 insertions(+), 0 deletions(-)
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 5c75f8a..0e64d92 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -879,6 +879,116 @@ static ssize_t write_versions(struct file *file, char *buf, size_t size)
return rv;
}
+/*
+ * Zero-length write. Return a list of NFSD's current listener
+ * transports.
+ */
+static ssize_t __write_ports_names(char *buf, size_t size)
+{
+ if (!nfsd_serv)
+ return 0;
+ return svc_xprt_names(nfsd_serv, buf, 0);
+}
+
+/*
+ * A single 'fd' number was written, in which case it must be for
+ * a socket of a supported family/protocol, and we use it as an
+ * nfsd listener.
+ */
+static ssize_t __write_ports_addfd(char *buf, size_t size)
+{
+ char *mesg = buf;
+ int fd, err;
+
+ err = get_int(&mesg, &fd);
+ if (err || fd < 0)
+ return -EINVAL;
+
+ err = nfsd_create_serv();
+ if (err)
+ return err;
+
+ err = svc_addsock(nfsd_serv, fd, buf);
+ if (err < 0)
+ return err;
+
+ err = lockd_up();
+ if (err < 0)
+ svc_sock_names(buf + strlen(buf) + 1, nfsd_serv, buf);
+
+ /* Decrease the count, but don't shut down the the service */
+ nfsd_serv->sv_nrthreads--;
+
+ return err < 0 ? err : 0;
+}
+
+/*
+ * A '-' followed by the 'name' of a socket means we close the socket.
+ */
+static ssize_t __write_ports_delfd(char *buf, size_t size)
+{
+ char *toclose;
+ int len = 0;
+
+ toclose = kstrdup(buf + 1, GFP_KERNEL);
+ if (!toclose)
+ return -ENOMEM;
+
+ if (nfsd_serv)
+ len = svc_sock_names(buf, nfsd_serv, toclose);
+ if (len >= 0)
+ lockd_down();
+
+ kfree(toclose);
+ return len;
+}
+
+/*
+ * A transport listener is added by writing it's transport name and
+ * a port number
+ */
+static ssize_t __write_ports_addxprt(char *buf, size_t size,
+ char *transport, unsigned short port)
+{
+ int err;
+
+ err = nfsd_create_serv();
+ if (err)
+ return err;
+
+ err = svc_create_xprt(nfsd_serv, transport, port, SVC_SOCK_ANONYMOUS);
+ if (err == -ENOENT)
+ /* Give a reasonable perror msg for
+ * bad transport string */
+ err = -EPROTONOSUPPORT;
+
+ return err < 0 ? err : 0;
+}
+
+/*
+ * A transport listener is removed by writing a "-", it's transport
+ * name, and it's port number
+ */
+static ssize_t __write_ports_delxprt(char *buf, size_t size,
+ char *transport, int port)
+{
+ struct svc_xprt *xprt;
+ int err = -EINVAL;
+
+ if (port == 0 || nfsd_serv == NULL)
+ return err;
+
+ xprt = svc_find_xprt(nfsd_serv, transport, AF_UNSPEC, port);
+ if (xprt) {
+ svc_close_xprt(xprt);
+ svc_xprt_put(xprt);
+ err = 0;
+ } else
+ err = -ENOTCONN;
+
+ return err < 0 ? err : 0;
+}
+
static ssize_t __write_ports(struct file *file, char *buf, size_t size)
{
if (size == 0) {
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH 06/22] NFSD: Refactor __write_ports()
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (4 preceding siblings ...)
2008-12-12 21:57 ` [PATCH 05/22] NFSD: Add helper functions for __write_ports() Chuck Lever
@ 2008-12-12 21:57 ` Chuck Lever
2008-12-12 21:57 ` [PATCH 07/22] NFSD: Prevent a buffer overflow in svc_xprt_names() Chuck Lever
` (17 subsequent siblings)
23 siblings, 0 replies; 37+ messages in thread
From: Chuck Lever @ 2008-12-12 21:57 UTC (permalink / raw)
To: bfields; +Cc: aime.le-rouzic, linux-nfs
Clean up: The __write_ports() function is a twisty little maze of
"if" statements, all alike.
The /proc/fs/nfsd/portlist file interface has grown in complexity
since it was first introduced. Use recently introduced helpers to
refactor the portlist file's parser function into something easier to
read and expand.
I don't intend to expand it, but subsequent patches will fix a few
bugs, and introduce IPv6 support.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfsd/nfsctl.c | 114 ++++++++++--------------------------------------------
1 files changed, 21 insertions(+), 93 deletions(-)
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 0e64d92..fa6441b 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -991,100 +991,28 @@ static ssize_t __write_ports_delxprt(char *buf, size_t size,
static ssize_t __write_ports(struct file *file, char *buf, size_t size)
{
- if (size == 0) {
- int len = 0;
+ char transport[16];
+ int port;
+
+ if (size == 0)
+ return __write_ports_names(buf, size);
+
+ if (isdigit(buf[0]))
+ return __write_ports_addfd(buf, size);
+
+ if (buf[0] == '-' && isdigit(buf[1]))
+ return __write_ports_delfd(buf, size);
+
+ if (isalpha(buf[0]))
+ if (sscanf(buf, "%15s %4u", transport, &port) == 2)
+ return __write_ports_addxprt(buf, size,
+ transport, port);
+
+ if (buf[0] == '-' && isalpha(buf[1]))
+ if (sscanf(&buf[1], "%15s %4u", transport, &port) == 2)
+ return __write_ports_delxprt(buf, size,
+ transport, port);
- if (nfsd_serv)
- len = svc_xprt_names(nfsd_serv, buf, 0);
- return len;
- }
- /* Either a single 'fd' number is written, in which
- * case it must be for a socket of a supported family/protocol,
- * and we use it as an nfsd socket, or
- * A '-' followed by the 'name' of a socket in which case
- * we close the socket.
- */
- if (isdigit(buf[0])) {
- char *mesg = buf;
- int fd;
- int err;
- err = get_int(&mesg, &fd);
- if (err)
- return -EINVAL;
- if (fd < 0)
- return -EINVAL;
- err = nfsd_create_serv();
- if (!err) {
- err = svc_addsock(nfsd_serv, fd, buf);
- if (err >= 0) {
- err = lockd_up();
- if (err < 0)
- svc_sock_names(buf+strlen(buf)+1, nfsd_serv, buf);
- }
- /* Decrease the count, but don't shutdown the
- * the service
- */
- nfsd_serv->sv_nrthreads--;
- }
- return err < 0 ? err : 0;
- }
- if (buf[0] == '-' && isdigit(buf[1])) {
- char *toclose = kstrdup(buf+1, GFP_KERNEL);
- int len = 0;
- if (!toclose)
- return -ENOMEM;
- if (nfsd_serv)
- len = svc_sock_names(buf, nfsd_serv, toclose);
- if (len >= 0)
- lockd_down();
- kfree(toclose);
- return len;
- }
- /*
- * Add a transport listener by writing it's transport name
- */
- if (isalpha(buf[0])) {
- int err;
- char transport[16];
- int port;
- if (sscanf(buf, "%15s %4d", transport, &port) == 2) {
- err = nfsd_create_serv();
- if (!err) {
- err = svc_create_xprt(nfsd_serv,
- transport, port,
- SVC_SOCK_ANONYMOUS);
- if (err == -ENOENT)
- /* Give a reasonable perror msg for
- * bad transport string */
- err = -EPROTONOSUPPORT;
- }
- return err < 0 ? err : 0;
- }
- }
- /*
- * Remove a transport by writing it's transport name and port number
- */
- if (buf[0] == '-' && isalpha(buf[1])) {
- struct svc_xprt *xprt;
- int err = -EINVAL;
- char transport[16];
- int port;
- if (sscanf(&buf[1], "%15s %4d", transport, &port) == 2) {
- if (port == 0)
- return -EINVAL;
- if (nfsd_serv) {
- xprt = svc_find_xprt(nfsd_serv, transport,
- AF_UNSPEC, port);
- if (xprt) {
- svc_close_xprt(xprt);
- svc_xprt_put(xprt);
- err = 0;
- } else
- err = -ENOTCONN;
- }
- return err < 0 ? err : 0;
- }
- }
return -EINVAL;
}
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH 07/22] NFSD: Prevent a buffer overflow in svc_xprt_names()
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (5 preceding siblings ...)
2008-12-12 21:57 ` [PATCH 06/22] NFSD: Refactor __write_ports() Chuck Lever
@ 2008-12-12 21:57 ` Chuck Lever
[not found] ` <20081212215757.24332.77904.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2008-12-12 21:58 ` [PATCH 08/22] SUNRPC: pass buffer size to svc_addsock() and svc_sock_names() Chuck Lever
` (16 subsequent siblings)
23 siblings, 1 reply; 37+ messages in thread
From: Chuck Lever @ 2008-12-12 21:57 UTC (permalink / raw)
To: bfields; +Cc: aime.le-rouzic, linux-nfs
The svc_xprt_names() function can overflow its buffer if it's so near
the end of the passed in buffer that the "name too long" string still
doesn't fit. Of course, it could never tell if it was near the end
of the passed in buffer, since its only caller passes in zero as the
buffer length.
Let's make this API a little safer.
Change svc_xprt_names() so it *always* checks for a buffer overflow,
and change its only caller to pass in the correct buffer length.
If svc_xprt_names() does overflow its buffer, just fail with a
reasonable errno code, instead of trying to write a message at the end
of the buffer. I don't like this much, but I can't figure out a safe
way to return some of the names, *and* an indication that the buffer
was not long enough.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfsd/nfsctl.c | 2 +-
net/sunrpc/svc_xprt.c | 53 ++++++++++++++++++++++++++++++++++---------------
2 files changed, 38 insertions(+), 17 deletions(-)
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index fa6441b..22fc8e5 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -887,7 +887,7 @@ static ssize_t __write_ports_names(char *buf, size_t size)
{
if (!nfsd_serv)
return 0;
- return svc_xprt_names(nfsd_serv, buf, 0);
+ return svc_xprt_names(nfsd_serv, buf, SIMPLE_TRANSACTION_LIMIT);
}
/*
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index bf5b5cd..eb546ce 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -1045,36 +1045,57 @@ struct svc_xprt *svc_find_xprt(struct svc_serv *serv, char *xcl_name,
}
EXPORT_SYMBOL_GPL(svc_find_xprt);
-/*
- * Format a buffer with a list of the active transports. A zero for
- * the buflen parameter disables target buffer overflow checking.
+static int svc_one_xprt_name(struct svc_xprt *xprt, char *pos, int remaining)
+{
+ int len;
+
+ len = snprintf(pos, remaining, "%s %u\n",
+ xprt->xpt_class->xcl_name,
+ svc_xprt_local_port(xprt));
+ if (len >= remaining)
+ return -ENAMETOOLONG;
+ return len;
+}
+
+/**
+ * svc_xprt_names - format a buffer with a list of transport names
+ * @serv: pointer to an RPC service
+ * @buf: pointer to a buffer to be filled in
+ * @buflen: length of buffer to be filled in
+ *
+ * Fills in @buf with a string containing a list of transport names,
+ * each name terminated with '\n'.
+ *
+ * Returns positive length of the filled-in string on success; otherwise
+ * a negative errno value is returned if an error occurs.
*/
int svc_xprt_names(struct svc_serv *serv, char *buf, int buflen)
{
struct svc_xprt *xprt;
- char xprt_str[64];
- int totlen = 0;
- int len;
+ int len, totlen;
+ char *pos;
/* Sanity check args */
if (!serv)
return 0;
spin_lock_bh(&serv->sv_lock);
+
+ pos = buf;
+ totlen = 0;
list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) {
- len = snprintf(xprt_str, sizeof(xprt_str),
- "%s %d\n", xprt->xpt_class->xcl_name,
- svc_xprt_local_port(xprt));
- /* If the string was truncated, replace with error string */
- if (len >= sizeof(xprt_str))
- strcpy(xprt_str, "name-too-long\n");
- /* Don't overflow buffer */
- len = strlen(xprt_str);
- if (buflen && (len + totlen >= buflen))
+ len = svc_one_xprt_name(xprt, pos, buflen - totlen);
+ if (len < 0) {
+ *buf = '\0';
+ totlen = len;
+ }
+ if (len <= 0)
break;
- strcpy(buf+totlen, xprt_str);
+
+ pos += len;
totlen += len;
}
+
spin_unlock_bh(&serv->sv_lock);
return totlen;
}
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH 08/22] SUNRPC: pass buffer size to svc_addsock() and svc_sock_names()
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (6 preceding siblings ...)
2008-12-12 21:57 ` [PATCH 07/22] NFSD: Prevent a buffer overflow in svc_xprt_names() Chuck Lever
@ 2008-12-12 21:58 ` Chuck Lever
[not found] ` <20081212215804.24332.24605.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2008-12-12 21:58 ` [PATCH 09/22] SUNRPC: Switch one_sock_name() to use snprintf() Chuck Lever
` (15 subsequent siblings)
23 siblings, 1 reply; 37+ messages in thread
From: Chuck Lever @ 2008-12-12 21:58 UTC (permalink / raw)
To: bfields; +Cc: aime.le-rouzic, linux-nfs
Pass the size of the output buffer to the RPC functions that construct
the list of socket names in that buffer. Add documenting comments to
these functions.
This is a cosmetic change for now. A subsequent patch will make sure
the buffer length is passed to one_sock_name(), where the length will
actually be useful.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfsd/nfsctl.c | 12 ++++++++----
include/linux/sunrpc/svcsock.h | 6 ++++--
net/sunrpc/svcsock.c | 34 +++++++++++++++++++++++++++++-----
3 files changed, 41 insertions(+), 11 deletions(-)
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 22fc8e5..19db9f4 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -898,7 +898,7 @@ static ssize_t __write_ports_names(char *buf, size_t size)
static ssize_t __write_ports_addfd(char *buf, size_t size)
{
char *mesg = buf;
- int fd, err;
+ int fd, err, len;
err = get_int(&mesg, &fd);
if (err || fd < 0)
@@ -908,13 +908,16 @@ static ssize_t __write_ports_addfd(char *buf, size_t size)
if (err)
return err;
- err = svc_addsock(nfsd_serv, fd, buf);
+ len = SIMPLE_TRANSACTION_LIMIT;
+ err = svc_addsock(nfsd_serv, fd, buf, len);
if (err < 0)
return err;
+ len -= err;
err = lockd_up();
if (err < 0)
- svc_sock_names(buf + strlen(buf) + 1, nfsd_serv, buf);
+ svc_sock_names(nfsd_serv, buf + strlen(buf) + 1,
+ len - strlen(buf) - 1, buf);
/* Decrease the count, but don't shut down the the service */
nfsd_serv->sv_nrthreads--;
@@ -935,7 +938,8 @@ static ssize_t __write_ports_delfd(char *buf, size_t size)
return -ENOMEM;
if (nfsd_serv)
- len = svc_sock_names(buf, nfsd_serv, toclose);
+ len = svc_sock_names(nfsd_serv, buf,
+ SIMPLE_TRANSACTION_LIMIT, toclose);
if (len >= 0)
lockd_down();
diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h
index 483e103..f57ce85 100644
--- a/include/linux/sunrpc/svcsock.h
+++ b/include/linux/sunrpc/svcsock.h
@@ -38,8 +38,10 @@ int svc_recv(struct svc_rqst *, long);
int svc_send(struct svc_rqst *);
void svc_drop(struct svc_rqst *);
void svc_sock_update_bufs(struct svc_serv *serv);
-int svc_sock_names(char *buf, struct svc_serv *serv, char *toclose);
-int svc_addsock(struct svc_serv *serv, int fd, char *name_return);
+int svc_sock_names(struct svc_serv *serv, char *buf, size_t buflen,
+ char *toclose);
+int svc_addsock(struct svc_serv *serv, int fd, char *name_return,
+ size_t len);
void svc_init_xprt_sock(void);
void svc_cleanup_xprt_sock(void);
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index a1951dc..39f5015 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -263,8 +263,23 @@ static int one_sock_name(char *buf, struct svc_sock *svsk)
return len;
}
-int
-svc_sock_names(char *buf, struct svc_serv *serv, char *toclose)
+/**
+ * svc_sock_names - construct a list of listener names in a string
+ * @serv: pointer to RPC service
+ * @buf: pointer to a buffer to fill in with socket names
+ * @buflen: size of the buffer to be filled
+ * @toclose: pointer to '\0'-terminated C string containing the name
+ * of a listener to be closed
+ *
+ * Fills in @buf with a '\n'-separated list of names of listener
+ * sockets. If @toclose is not NULL, the socket named by @toclose
+ * is closed, and is not included in the output list.
+ *
+ * Returns positive length of the socket name string, or a negative
+ * errno value on error.
+ */
+int svc_sock_names(struct svc_serv *serv, char *buf, size_t buflen,
+ char *toclose)
{
struct svc_sock *svsk, *closesk = NULL;
int len = 0;
@@ -1165,9 +1180,18 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
return svsk;
}
-int svc_addsock(struct svc_serv *serv,
- int fd,
- char *name_return)
+/**
+ * svc_addsock - add a listener socket to an RPC service
+ * @serv: pointer to RPC service to which to add a new listener
+ * @fd: file descriptor of the new listener
+ * @name_return: pointer to buffer to pass back name of listener
+ * @len: size of the buffer
+ *
+ * Fills in socket name and returns positive length of name if successful.
+ * Name is terminated with '\n'. On error, returns a negative errno
+ * value.
+ */
+int svc_addsock(struct svc_serv *serv, int fd, char *name_return, size_t len)
{
int err = 0;
struct socket *so = sockfd_lookup(fd, &err);
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH 09/22] SUNRPC: Switch one_sock_name() to use snprintf()
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (7 preceding siblings ...)
2008-12-12 21:58 ` [PATCH 08/22] SUNRPC: pass buffer size to svc_addsock() and svc_sock_names() Chuck Lever
@ 2008-12-12 21:58 ` Chuck Lever
2008-12-12 21:58 ` [PATCH 10/22] SUNRPC: Support AF_INET6 in one_sock_name() Chuck Lever
` (14 subsequent siblings)
23 siblings, 0 replies; 37+ messages in thread
From: Chuck Lever @ 2008-12-12 21:58 UTC (permalink / raw)
To: bfields; +Cc: aime.le-rouzic, linux-nfs
Use snprintf() in one_sock_name() to help prevent buffer overflows.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
net/sunrpc/svcsock.c | 23 +++++++++++++++++------
1 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 39f5015..fa11944 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -244,22 +244,27 @@ out:
/*
* Report socket names for nfsdfs
*/
-static int one_sock_name(char *buf, struct svc_sock *svsk)
+static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining)
{
int len;
switch(svsk->sk_sk->sk_family) {
case AF_INET:
- len = sprintf(buf, "ipv4 %s %u.%u.%u.%u %d\n",
+ len = snprintf(buf, remaining, "ipv4 %s %u.%u.%u.%u %d\n",
svsk->sk_sk->sk_protocol==IPPROTO_UDP?
"udp" : "tcp",
NIPQUAD(inet_sk(svsk->sk_sk)->rcv_saddr),
inet_sk(svsk->sk_sk)->num);
break;
default:
- len = sprintf(buf, "*unknown-%d*\n",
+ len = snprintf(buf, remaining, "*unknown-%d*\n",
svsk->sk_sk->sk_family);
}
+
+ if (len >= remaining) {
+ *buf = '\0';
+ return -ENAMETOOLONG;
+ }
return len;
}
@@ -286,15 +291,21 @@ int svc_sock_names(struct svc_serv *serv, char *buf, size_t buflen,
if (!serv)
return 0;
+
spin_lock_bh(&serv->sv_lock);
list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) {
- int onelen = one_sock_name(buf+len, svsk);
- if (toclose && strcmp(toclose, buf+len) == 0)
+ int onelen = svc_one_sock_name(svsk, buf + len, buflen - len);
+ if (onelen < 0) {
+ len = onelen;
+ break;
+ }
+ if (toclose && strcmp(toclose, buf + len) == 0)
closesk = svsk;
else
len += onelen;
}
spin_unlock_bh(&serv->sv_lock);
+
if (closesk)
/* Should unregister with portmap, but you cannot
* unregister just one protocol...
@@ -1231,7 +1242,7 @@ int svc_addsock(struct svc_serv *serv, int fd, char *name_return, size_t len)
sockfd_put(so);
return err;
}
- return one_sock_name(name_return, svsk);
+ return svc_one_sock_name(svsk, name_return, len);
}
EXPORT_SYMBOL_GPL(svc_addsock);
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH 10/22] SUNRPC: Support AF_INET6 in one_sock_name()
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (8 preceding siblings ...)
2008-12-12 21:58 ` [PATCH 09/22] SUNRPC: Switch one_sock_name() to use snprintf() Chuck Lever
@ 2008-12-12 21:58 ` Chuck Lever
2008-12-12 21:58 ` [PATCH 11/22] SUNRPC: Clean up one_sock_name() Chuck Lever
` (13 subsequent siblings)
23 siblings, 0 replies; 37+ messages in thread
From: Chuck Lever @ 2008-12-12 21:58 UTC (permalink / raw)
To: bfields; +Cc: aime.le-rouzic, linux-nfs
Add an arm to the switch statement in svc_one_sock_name() so it can
construct the name of PF_INET6 sockets properly.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Aime Le Rouzic <aime.le-rouzic@bull.net>
---
net/sunrpc/svcsock.c | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index fa11944..c148de9 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -256,6 +256,13 @@ static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining)
NIPQUAD(inet_sk(svsk->sk_sk)->rcv_saddr),
inet_sk(svsk->sk_sk)->num);
break;
+ case AF_INET6:
+ len = snprintf(buf, remaining, "ipv6 %s " NIP6_FMT " %d\n",
+ svsk->sk_sk->sk_protocol == IPPROTO_UDP ?
+ "udp" : "tcp",
+ NIP6(inet6_sk(svsk->sk_sk)->rcv_saddr),
+ inet_sk(svsk->sk_sk)->num);
+ break;
default:
len = snprintf(buf, remaining, "*unknown-%d*\n",
svsk->sk_sk->sk_family);
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH 11/22] SUNRPC: Clean up one_sock_name()
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (9 preceding siblings ...)
2008-12-12 21:58 ` [PATCH 10/22] SUNRPC: Support AF_INET6 in one_sock_name() Chuck Lever
@ 2008-12-12 21:58 ` Chuck Lever
2008-12-12 21:58 ` [PATCH 12/22] NFSD: Support AF_INET6 in svc_addsock() function Chuck Lever
` (12 subsequent siblings)
23 siblings, 0 replies; 37+ messages in thread
From: Chuck Lever @ 2008-12-12 21:58 UTC (permalink / raw)
To: bfields; +Cc: aime.le-rouzic, linux-nfs
Clean up svc_one_sock_name() by setting up automatic variables for
frequently used expressions.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
net/sunrpc/svcsock.c | 26 +++++++++++++++-----------
1 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index c148de9..e0d74f6 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -246,26 +246,30 @@ out:
*/
static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining)
{
+ struct sock *sk = svsk->sk_sk;
+ char *proto_name;
int len;
- switch(svsk->sk_sk->sk_family) {
+ proto_name = "tcp";
+ if (sk->sk_protocol == IPPROTO_UDP)
+ proto_name = "udp";
+
+ switch (sk->sk_family) {
case AF_INET:
- len = snprintf(buf, remaining, "ipv4 %s %u.%u.%u.%u %d\n",
- svsk->sk_sk->sk_protocol==IPPROTO_UDP?
- "udp" : "tcp",
- NIPQUAD(inet_sk(svsk->sk_sk)->rcv_saddr),
- inet_sk(svsk->sk_sk)->num);
+ len = snprintf(buf, remaining, "ipv4 %s " NIPQUAD_FMT " %d\n",
+ proto_name,
+ NIPQUAD(inet_sk(sk)->rcv_saddr),
+ inet_sk(sk)->num);
break;
case AF_INET6:
len = snprintf(buf, remaining, "ipv6 %s " NIP6_FMT " %d\n",
- svsk->sk_sk->sk_protocol == IPPROTO_UDP ?
- "udp" : "tcp",
- NIP6(inet6_sk(svsk->sk_sk)->rcv_saddr),
- inet_sk(svsk->sk_sk)->num);
+ proto_name,
+ NIP6(inet6_sk(sk)->rcv_saddr),
+ inet_sk(sk)->num);
break;
default:
len = snprintf(buf, remaining, "*unknown-%d*\n",
- svsk->sk_sk->sk_family);
+ sk->sk_family);
}
if (len >= remaining) {
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH 12/22] NFSD: Support AF_INET6 in svc_addsock() function
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (10 preceding siblings ...)
2008-12-12 21:58 ` [PATCH 11/22] SUNRPC: Clean up one_sock_name() Chuck Lever
@ 2008-12-12 21:58 ` Chuck Lever
2008-12-12 21:58 ` [PATCH 13/22] NFS: Move NFS client's IP address parser to nfs_common/ Chuck Lever
` (11 subsequent siblings)
23 siblings, 0 replies; 37+ messages in thread
From: Chuck Lever @ 2008-12-12 21:58 UTC (permalink / raw)
To: bfields; +Cc: aime.le-rouzic, linux-nfs
From: Aime Le Rouzic <aime.le-rouzic@bull.net>
Relax the address family check at the top of svc_addsock() to allow AF_INET6
listener sockets to be specified via /proc/fs/nfsd/portlist.
Signed-off-by: Aime Le Rouzic <aime.le-rouzic@bull.net>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
net/sunrpc/svcsock.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index e0d74f6..dd6e23b 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1221,7 +1221,7 @@ int svc_addsock(struct svc_serv *serv, int fd, char *name_return, size_t len)
if (!so)
return err;
- if (so->sk->sk_family != AF_INET)
+ if ((so->sk->sk_family != AF_INET) && (so->sk->sk_family != AF_INET6))
err = -EAFNOSUPPORT;
else if (so->sk->sk_protocol != IPPROTO_TCP &&
so->sk->sk_protocol != IPPROTO_UDP)
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH 13/22] NFS: Move NFS client's IP address parser to nfs_common/
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (11 preceding siblings ...)
2008-12-12 21:58 ` [PATCH 12/22] NFSD: Support AF_INET6 in svc_addsock() function Chuck Lever
@ 2008-12-12 21:58 ` Chuck Lever
[not found] ` <20081212215842.24332.47093.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2008-12-12 21:58 ` [PATCH 14/22] NFSD: Support IPv6 addresses in write_failover_ip() Chuck Lever
` (10 subsequent siblings)
23 siblings, 1 reply; 37+ messages in thread
From: Chuck Lever @ 2008-12-12 21:58 UTC (permalink / raw)
To: bfields; +Cc: aime.le-rouzic, linux-nfs
The kernel's NFS server also needs to parse presentation format IP
addresses. Since both the client and the server can reside in their own
modules, move the parser logic to nfs_common, which can be used by either.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfs/internal.h | 3 -
fs/nfs/nfs4namespace.c | 2 +
fs/nfs/super.c | 121 -------------------------------
fs/nfs_common/Makefile | 1
fs/nfs_common/nfs_addr_parse.c | 155 ++++++++++++++++++++++++++++++++++++++++
include/linux/nfs_addr_parse.h | 32 ++++++++
6 files changed, 191 insertions(+), 123 deletions(-)
create mode 100644 fs/nfs_common/nfs_addr_parse.c
create mode 100644 include/linux/nfs_addr_parse.h
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 4da6bbd..82d899f 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -167,7 +167,6 @@ extern void nfs4_clear_inode(struct inode *);
void nfs_zap_acl_cache(struct inode *inode);
/* super.c */
-void nfs_parse_ip_address(char *, size_t, struct sockaddr *, size_t *);
extern struct file_system_type nfs_xdev_fs_type;
#ifdef CONFIG_NFS_V4
extern struct file_system_type nfs4_xdev_fs_type;
@@ -291,8 +290,6 @@ unsigned int nfs_page_array_len(unsigned int base, size_t len)
PAGE_SIZE - 1) >> PAGE_SHIFT;
}
-#define IPV6_SCOPE_DELIMITER '%'
-
/*
* Set the port number in an address. Be agnostic about the address
* family.
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index 30befc3..660fc36 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4namespace.c
@@ -15,6 +15,8 @@
#include <linux/sunrpc/clnt.h>
#include <linux/vfs.h>
#include <linux/inet.h>
+#include <linux/nfs_addr_parse.h>
+
#include "internal.h"
#include "nfs4_fs.h"
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index d8e062f..54ffae3 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -51,6 +51,7 @@
#include <linux/nfs_xdr.h>
#include <linux/magic.h>
#include <linux/parser.h>
+#include <linux/nfs_addr_parse.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -700,126 +701,6 @@ static int nfs_verify_server_address(struct sockaddr *addr)
return 0;
}
-static void nfs_parse_ipv4_address(char *string, size_t str_len,
- struct sockaddr *sap, size_t *addr_len)
-{
- struct sockaddr_in *sin = (struct sockaddr_in *)sap;
- u8 *addr = (u8 *)&sin->sin_addr.s_addr;
-
- if (str_len <= INET_ADDRSTRLEN) {
- dfprintk(MOUNT, "NFS: parsing IPv4 address %*s\n",
- (int)str_len, string);
-
- sin->sin_family = AF_INET;
- *addr_len = sizeof(*sin);
- if (in4_pton(string, str_len, addr, '\0', NULL))
- return;
- }
-
- sap->sa_family = AF_UNSPEC;
- *addr_len = 0;
-}
-
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-static int nfs_parse_ipv6_scope_id(const char *string, const size_t str_len,
- const char *delim,
- struct sockaddr_in6 *sin6)
-{
- char *p;
- size_t len;
-
- if ((string + str_len) == delim)
- return 1;
-
- if (*delim != IPV6_SCOPE_DELIMITER)
- return 0;
-
- if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL))
- return 0;
-
- len = (string + str_len) - delim - 1;
- p = kstrndup(delim + 1, len, GFP_KERNEL);
- if (p) {
- unsigned long scope_id = 0;
- struct net_device *dev;
-
- dev = dev_get_by_name(&init_net, p);
- if (dev != NULL) {
- scope_id = dev->ifindex;
- dev_put(dev);
- } else {
- if (strict_strtoul(p, 10, &scope_id) == 0) {
- kfree(p);
- return 0;
- }
- }
-
- kfree(p);
-
- sin6->sin6_scope_id = scope_id;
- dfprintk(MOUNT, "NFS: IPv6 scope ID = %lu\n", scope_id);
- return 1;
- }
-
- return 0;
-}
-
-static void nfs_parse_ipv6_address(char *string, size_t str_len,
- struct sockaddr *sap, size_t *addr_len)
-{
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
- u8 *addr = (u8 *)&sin6->sin6_addr.in6_u;
- const char *delim;
-
- if (str_len <= INET6_ADDRSTRLEN) {
- dfprintk(MOUNT, "NFS: parsing IPv6 address %*s\n",
- (int)str_len, string);
-
- sin6->sin6_family = AF_INET6;
- *addr_len = sizeof(*sin6);
- if (in6_pton(string, str_len, addr,
- IPV6_SCOPE_DELIMITER, &delim) != 0) {
- if (nfs_parse_ipv6_scope_id(string, str_len,
- delim, sin6) != 0)
- return;
- }
- }
-
- sap->sa_family = AF_UNSPEC;
- *addr_len = 0;
-}
-#else
-static void nfs_parse_ipv6_address(char *string, size_t str_len,
- struct sockaddr *sap, size_t *addr_len)
-{
- sap->sa_family = AF_UNSPEC;
- *addr_len = 0;
-}
-#endif
-
-/*
- * Construct a sockaddr based on the contents of a string that contains
- * an IP address in presentation format.
- *
- * If there is a problem constructing the new sockaddr, set the address
- * family to AF_UNSPEC.
- */
-void nfs_parse_ip_address(char *string, size_t str_len,
- struct sockaddr *sap, size_t *addr_len)
-{
- unsigned int i, colons;
-
- colons = 0;
- for (i = 0; i < str_len; i++)
- if (string[i] == ':')
- colons++;
-
- if (colons >= 2)
- nfs_parse_ipv6_address(string, str_len, sap, addr_len);
- else
- nfs_parse_ipv4_address(string, str_len, sap, addr_len);
-}
-
/*
* Sanity check the NFS transport protocol.
*
diff --git a/fs/nfs_common/Makefile b/fs/nfs_common/Makefile
index f689ed8..032b4c5 100644
--- a/fs/nfs_common/Makefile
+++ b/fs/nfs_common/Makefile
@@ -2,6 +2,7 @@
# Makefile for Linux filesystem routines that are shared by client and server.
#
+obj-$(CONFIG_NFS_COMMON) += nfs_addr_parse.o
obj-$(CONFIG_NFS_ACL_SUPPORT) += nfs_acl.o
nfs_acl-objs := nfsacl.o
diff --git a/fs/nfs_common/nfs_addr_parse.c b/fs/nfs_common/nfs_addr_parse.c
new file mode 100644
index 0000000..afb64dd
--- /dev/null
+++ b/fs/nfs_common/nfs_addr_parse.c
@@ -0,0 +1,155 @@
+/*
+ * Convert presentation format IP address string to socket
+ * address.
+ *
+ * Copyright (C) 2008 Oracle Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+
+#include <linux/inet.h>
+#include <linux/in6.h>
+#include <net/ipv6.h>
+#include <linux/netdevice.h>
+
+#include <linux/nfs_addr_parse.h>
+
+static void nfs_parse_ipv4_address(char *buf, size_t buflen,
+ struct sockaddr *sap, size_t *salenp)
+{
+ struct sockaddr_in *sin = (struct sockaddr_in *)sap;
+ u8 *addr = (u8 *)&sin->sin_addr.s_addr;
+
+ if (buflen <= INET_ADDRSTRLEN) {
+ sin->sin_family = AF_INET;
+ *salenp = sizeof(*sin);
+ if (in4_pton(buf, buflen, addr, '\0', NULL))
+ return;
+ }
+
+ sap->sa_family = AF_UNSPEC;
+ *salenp = 0;
+}
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static int nfs_parse_ipv6_scope_id(const char *buf, const size_t buflen,
+ const char *delim,
+ struct sockaddr_in6 *sin6)
+{
+ char *p;
+ size_t len;
+
+ if ((buf + buflen) == delim)
+ return 1;
+
+ if (*delim != IPV6_SCOPE_DELIMITER)
+ return 0;
+
+ if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL))
+ return 0;
+
+ len = (buf + buflen) - delim - 1;
+ p = kstrndup(delim + 1, len, GFP_KERNEL);
+ if (p) {
+ unsigned long scope_id = 0;
+ struct net_device *dev;
+
+ dev = dev_get_by_name(&init_net, p);
+ if (dev != NULL) {
+ scope_id = dev->ifindex;
+ dev_put(dev);
+ } else {
+ if (strict_strtoul(p, 10, &scope_id) == 0) {
+ kfree(p);
+ return 0;
+ }
+ }
+
+ kfree(p);
+
+ sin6->sin6_scope_id = scope_id;
+ return 1;
+ }
+
+ return 0;
+}
+
+static void nfs_parse_ipv6_address(char *buf, size_t buflen,
+ struct sockaddr *sap, size_t *salenp)
+{
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
+ u8 *addr = (u8 *)&sin6->sin6_addr.in6_u;
+ const char *delim;
+
+ if (buflen <= INET6_ADDRSTRLEN) {
+ sin6->sin6_family = AF_INET6;
+ *salenp = sizeof(*sin6);
+ if (in6_pton(buf, buflen, addr,
+ IPV6_SCOPE_DELIMITER, &delim) != 0) {
+ if (nfs_parse_ipv6_scope_id(buf, buflen,
+ delim, sin6) != 0)
+ return;
+ }
+ }
+
+ sap->sa_family = AF_UNSPEC;
+ *salenp = 0;
+}
+#else
+static void nfs_parse_ipv6_address(char *buf, size_t buflen,
+ struct sockaddr *sap, size_t *salenp)
+{
+ sap->sa_family = AF_UNSPEC;
+ *salenp = 0;
+}
+#endif
+
+/**
+ * nfs_parse_ip_address - convert IP address string to sockaddr
+ * @buf: pointer to C string containing presentation format IP address
+ * @buflen: length of @buf in bytes
+ * @sap: pointer to buffer in which to construct sockaddr
+ * @salenp: IN: length of buffer in bytes
+ * OUT: size of address in bytes
+ *
+ * Construct a sockaddr based on the contents of a string that contains
+ * an IP address in presentation format.
+ *
+ * If there is a problem constructing the new sockaddr, set the address
+ * family to AF_UNSPEC.
+ */
+void nfs_parse_ip_address(char *buf, size_t buflen,
+ struct sockaddr *sap, size_t *salenp)
+{
+ unsigned int i, colons;
+
+ colons = 0;
+ for (i = 0; i < buflen; i++)
+ if (buf[i] == ':')
+ colons++;
+
+ if (colons >= 2)
+ nfs_parse_ipv6_address(buf, buflen, sap, salenp);
+ else
+ nfs_parse_ipv4_address(buf, buflen, sap, salenp);
+}
+EXPORT_SYMBOL_GPL(nfs_parse_ip_address);
diff --git a/include/linux/nfs_addr_parse.h b/include/linux/nfs_addr_parse.h
new file mode 100644
index 0000000..484f511
--- /dev/null
+++ b/include/linux/nfs_addr_parse.h
@@ -0,0 +1,32 @@
+/*
+ * include/linux/nfs_addr_parse.h
+ *
+ * Copyright (C) 2008 Oracle Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ */
+
+#ifndef __LINUX_NFS_ADDR_PARSE_H
+#define __LINUX_NFS_ADDR_PARSE_H
+
+#define IPV6_SCOPE_DELIMITER '%'
+
+void nfs_parse_ip_address(char *buf, size_t buflen,
+ struct sockaddr *sap,
+ size_t *salenp);
+
+#endif /* __LINUX_NFS_ADDR_PARSE_H */
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH 14/22] NFSD: Support IPv6 addresses in write_failover_ip()
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (12 preceding siblings ...)
2008-12-12 21:58 ` [PATCH 13/22] NFS: Move NFS client's IP address parser to nfs_common/ Chuck Lever
@ 2008-12-12 21:58 ` Chuck Lever
2008-12-12 21:58 ` [PATCH 15/22] NFSD: Enable NFS server use of AF_INET6 Chuck Lever
` (9 subsequent siblings)
23 siblings, 0 replies; 37+ messages in thread
From: Chuck Lever @ 2008-12-12 21:58 UTC (permalink / raw)
To: bfields; +Cc: aime.le-rouzic, linux-nfs
In write_failover_ip(), replace the sscanf() with a call to the common
NFS presentation address parser.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfsd/nfsctl.c | 22 ++++++++--------------
1 files changed, 8 insertions(+), 14 deletions(-)
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 19db9f4..a8e3f6b 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -38,6 +38,7 @@
#include <linux/nfsd/xdr.h>
#include <linux/nfsd/syscall.h>
#include <linux/lockd/lockd.h>
+#include <linux/nfs_addr_parse.h>
#include <asm/uaccess.h>
#include <net/ipv6.h>
@@ -476,22 +477,18 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
*
* Input:
* buf: '\n'-terminated C string containing a
- * presentation format IPv4 address
+ * presentation format IP address
* size: length of C string in @buf
* Output:
* On success: returns zero if all specified locks were released;
* returns one if one or more locks were not released
* On error: return code is negative errno value
- *
- * Note: Only AF_INET client addresses are passed in
*/
static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)
{
- struct sockaddr_in sin = {
- .sin_family = AF_INET,
- };
- int b1, b2, b3, b4;
- char c;
+ struct sockaddr_storage address;
+ struct sockaddr *sap = (struct sockaddr *)&address;
+ size_t salen = sizeof(address);
char *fo_path;
/* sanity check */
@@ -505,14 +502,11 @@ static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)
if (qword_get(&buf, fo_path, size) < 0)
return -EINVAL;
- /* get ipv4 address */
- if (sscanf(fo_path, NIPQUAD_FMT "%c", &b1, &b2, &b3, &b4, &c) != 4)
- return -EINVAL;
- if (b1 > 255 || b2 > 255 || b3 > 255 || b4 > 255)
+ nfs_parse_ip_address(fo_path, size, sap, &salen);
+ if (sap->sa_family == AF_UNSPEC)
return -EINVAL;
- sin.sin_addr.s_addr = htonl((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);
- return nlmsvc_unlock_all_by_ip((struct sockaddr *)&sin);
+ return nlmsvc_unlock_all_by_ip(sap);
}
/**
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH 15/22] NFSD: Enable NFS server use of AF_INET6
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (13 preceding siblings ...)
2008-12-12 21:58 ` [PATCH 14/22] NFSD: Support IPv6 addresses in write_failover_ip() Chuck Lever
@ 2008-12-12 21:58 ` Chuck Lever
2008-12-12 21:59 ` [PATCH 16/22] NFSD: Prevent buffer overflow in write_threads() Chuck Lever
` (8 subsequent siblings)
23 siblings, 0 replies; 37+ messages in thread
From: Chuck Lever @ 2008-12-12 21:58 UTC (permalink / raw)
To: bfields; +Cc: aime.le-rouzic, linux-nfs
If the kernel is configured to support IPv6 and the RPC server can register
services via rpcbindv4, we are all set to enable IPv6 support for NFSD.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Aime Le Rouzic <aime.le-rouzic@bull.net>
---
fs/nfsd/nfssvc.c | 13 ++++++++++++-
1 files changed, 12 insertions(+), 1 deletions(-)
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 07e4f5d..47e21d0 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -45,6 +45,17 @@ static unsigned long nfsd_last_call;
static DEFINE_SPINLOCK(nfsd_call_lock);
/*
+ * If the kernel has IPv6 support available, always listen for
+ * both AF_INET and AF_INET6 requests.
+ */
+#if (defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)) && \
+ defined(CONFIG_SUNRPC_REGISTER_V4)
+static const sa_family_t nfsd_family = AF_INET6;
+#else /* (CONFIG_IPV6 || CONFIG_IPV6_MODULE) && CONFIG_SUNRPC_REGISTER_V4 */
+static const sa_family_t nfsd_family = AF_INET;
+#endif /* (CONFIG_IPV6 || CONFIG_IPV6_MODULE) && CONFIG_SUNRPC_REGISTER_V4 */
+
+/*
* nfsd_mutex protects nfsd_serv -- both the pointer itself and the members
* of the svc_serv struct. In particular, ->sv_nrthreads but also to some
* extent ->sv_temp_socks and ->sv_permsocks. It also protects nfsdstats.th_cnt
@@ -229,7 +240,7 @@ int nfsd_create_serv(void)
atomic_set(&nfsd_busy, 0);
nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize,
- AF_INET,
+ nfsd_family,
nfsd_last_thread, nfsd, THIS_MODULE);
if (nfsd_serv == NULL)
err = -ENOMEM;
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH 16/22] NFSD: Prevent buffer overflow in write_threads()
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (14 preceding siblings ...)
2008-12-12 21:58 ` [PATCH 15/22] NFSD: Enable NFS server use of AF_INET6 Chuck Lever
@ 2008-12-12 21:59 ` Chuck Lever
2008-12-12 21:59 ` [PATCH 17/22] NFSD: Prevent buffer overflow in write_versions() Chuck Lever
` (7 subsequent siblings)
23 siblings, 0 replies; 37+ messages in thread
From: Chuck Lever @ 2008-12-12 21:59 UTC (permalink / raw)
To: bfields; +Cc: aime.le-rouzic, linux-nfs
Fix up write_threads() to eliminate the small possibility of
overflowing its output buffer.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfsd/nfsctl.c | 9 +++++----
1 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index a8e3f6b..f8a2a7f 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -666,9 +666,9 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
static ssize_t write_threads(struct file *file, char *buf, size_t size)
{
char *mesg = buf;
- int rv;
+
if (size > 0) {
- int newthreads;
+ int rv, newthreads;
rv = get_int(&mesg, &newthreads);
if (rv)
return rv;
@@ -678,8 +678,9 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
if (rv)
return rv;
}
- sprintf(buf, "%d\n", nfsd_nrthreads());
- return strlen(buf);
+
+ return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n",
+ nfsd_nrthreads());
}
/**
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH 17/22] NFSD: Prevent buffer overflow in write_versions()
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (15 preceding siblings ...)
2008-12-12 21:59 ` [PATCH 16/22] NFSD: Prevent buffer overflow in write_threads() Chuck Lever
@ 2008-12-12 21:59 ` Chuck Lever
2008-12-12 21:59 ` [PATCH 18/22] NFSD: Prevent buffer overflow in write_maxblksize() Chuck Lever
` (6 subsequent siblings)
23 siblings, 0 replies; 37+ messages in thread
From: Chuck Lever @ 2008-12-12 21:59 UTC (permalink / raw)
To: bfields; +Cc: aime.le-rouzic, linux-nfs
Fix up write_versions() to eliminate the possibility of overflowing
its output buffer.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfsd/nfsctl.c | 26 ++++++++++++++++++--------
1 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index f8a2a7f..41e09c6 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -777,7 +777,7 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
{
char *mesg = buf;
char *vers, sign;
- int len, num;
+ int len, num, remaining;
ssize_t tlen = 0;
char *sep;
@@ -818,18 +818,28 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
*/
nfsd_reset_versions();
}
+
/* Now write current state into reply buffer */
- len = 0;
+ tlen = 0;
sep = "";
- for (num=2 ; num <= 4 ; num++)
+ remaining = SIMPLE_TRANSACTION_LIMIT;
+ for (num = 2 ; num <= 4 ; num++)
if (nfsd_vers(num, NFSD_AVAIL)) {
- len += sprintf(buf+len, "%s%c%d", sep,
- nfsd_vers(num, NFSD_TEST)?'+':'-',
- num);
+ len = snprintf(buf, remaining, "%s%c%d", sep,
+ nfsd_vers(num, NFSD_TEST) ? '+' : '-',
+ num);
sep = " ";
+
+ if (len >= remaining - 1)
+ break;
+
+ remaining -= len;
+ buf += len;
+ tlen += len;
}
- len += sprintf(buf+len, "\n");
- return len;
+ snprintf(buf, remaining, "\n");
+
+ return tlen;
}
/**
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH 18/22] NFSD: Prevent buffer overflow in write_maxblksize()
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (16 preceding siblings ...)
2008-12-12 21:59 ` [PATCH 17/22] NFSD: Prevent buffer overflow in write_versions() Chuck Lever
@ 2008-12-12 21:59 ` Chuck Lever
2008-12-12 21:59 ` [PATCH 19/22] NFSD: Prevent buffer overflow in write_leasetime() Chuck Lever
` (5 subsequent siblings)
23 siblings, 0 replies; 37+ messages in thread
From: Chuck Lever @ 2008-12-12 21:59 UTC (permalink / raw)
To: bfields; +Cc: aime.le-rouzic, linux-nfs
Fix up write_maxblksize() to eliminate the slight possibility of
overflowing its output buffer.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfsd/nfsctl.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 41e09c6..0fad95c 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -1131,6 +1131,7 @@ int nfsd_max_blksize;
static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
{
char *mesg = buf;
+
if (size > 0) {
int bsize;
int rv = get_int(&mesg, &bsize);
@@ -1152,7 +1153,9 @@ static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
nfsd_max_blksize = bsize;
mutex_unlock(&nfsd_mutex);
}
- return sprintf(buf, "%d\n", nfsd_max_blksize);
+
+ return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n",
+ nfsd_max_blksize);
}
#ifdef CONFIG_NFSD_V4
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH 19/22] NFSD: Prevent buffer overflow in write_leasetime()
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (17 preceding siblings ...)
2008-12-12 21:59 ` [PATCH 18/22] NFSD: Prevent buffer overflow in write_maxblksize() Chuck Lever
@ 2008-12-12 21:59 ` Chuck Lever
2008-12-12 21:59 ` [PATCH 20/22] NFSD: Prevent buffer overflow in write_recoverydir() Chuck Lever
` (4 subsequent siblings)
23 siblings, 0 replies; 37+ messages in thread
From: Chuck Lever @ 2008-12-12 21:59 UTC (permalink / raw)
To: bfields; +Cc: aime.le-rouzic, linux-nfs
Fix up write_leasetime() to eliminate the small possibility of
overflowing its output buffer.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfsd/nfsctl.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 0fad95c..4c1bdd4 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -1179,8 +1179,9 @@ static ssize_t __write_leasetime(struct file *file, char *buf, size_t size)
return -EINVAL;
nfs4_reset_lease(lease);
}
- sprintf(buf, "%ld\n", nfs4_lease_time());
- return strlen(buf);
+
+ return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%ld\n",
+ nfs4_lease_time());
}
/**
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH 20/22] NFSD: Prevent buffer overflow in write_recoverydir()
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (18 preceding siblings ...)
2008-12-12 21:59 ` [PATCH 19/22] NFSD: Prevent buffer overflow in write_leasetime() Chuck Lever
@ 2008-12-12 21:59 ` Chuck Lever
2008-12-12 21:59 ` [PATCH 21/22] NLM: Refactor make_socks() function Chuck Lever
` (3 subsequent siblings)
23 siblings, 0 replies; 37+ messages in thread
From: Chuck Lever @ 2008-12-12 21:59 UTC (permalink / raw)
To: bfields; +Cc: aime.le-rouzic, linux-nfs
Fix up write_recoverydir() to eliminate the possibility of overflowing
its output buffer.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfsd/nfsctl.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 4c1bdd4..1f72fd1 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -1237,8 +1237,9 @@ static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size)
status = nfs4_reset_recoverydir(recdir);
}
- sprintf(buf, "%s\n", nfs4_recoverydir());
- return strlen(buf);
+
+ return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%s\n",
+ nfs4_recoverydir());
}
/**
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH 21/22] NLM: Refactor make_socks() function
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (19 preceding siblings ...)
2008-12-12 21:59 ` [PATCH 20/22] NFSD: Prevent buffer overflow in write_recoverydir() Chuck Lever
@ 2008-12-12 21:59 ` Chuck Lever
2008-12-12 21:59 ` [PATCH 22/22] NLM: Clean up flow of control in " Chuck Lever
` (2 subsequent siblings)
23 siblings, 0 replies; 37+ messages in thread
From: Chuck Lever @ 2008-12-12 21:59 UTC (permalink / raw)
To: bfields; +Cc: aime.le-rouzic, linux-nfs
Clean up: extract common logic in NLM's make_socks() function
into a helper.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/lockd/svc.c | 31 ++++++++++++++++---------------
1 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index fc7c453..4ccb70a 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -198,6 +198,19 @@ lockd(void *vrqstp)
return 0;
}
+static int create_lockd_listener(struct svc_serv *serv, char *name,
+ unsigned short port)
+{
+ struct svc_xprt *xprt;
+
+ xprt = svc_find_xprt(serv, name, 0, 0);
+ if (!xprt)
+ return svc_create_xprt(serv, name, port, SVC_SOCK_DEFAULTS);
+
+ svc_xprt_put(xprt);
+ return 0;
+}
+
/*
* Ensure there are active UDP and TCP listeners for lockd.
*
@@ -211,23 +224,11 @@ lockd(void *vrqstp)
static int make_socks(struct svc_serv *serv)
{
static int warned;
- struct svc_xprt *xprt;
int err = 0;
- xprt = svc_find_xprt(serv, "udp", 0, 0);
- if (!xprt)
- err = svc_create_xprt(serv, "udp", nlm_udpport,
- SVC_SOCK_DEFAULTS);
- else
- svc_xprt_put(xprt);
- if (err >= 0) {
- xprt = svc_find_xprt(serv, "tcp", 0, 0);
- if (!xprt)
- err = svc_create_xprt(serv, "tcp", nlm_tcpport,
- SVC_SOCK_DEFAULTS);
- else
- svc_xprt_put(xprt);
- }
+ err = create_lockd_listener(serv, "udp", nlm_udpport);
+ if (err >= 0)
+ err = create_lockd_listener(serv, "tcp", nlm_tcpport);
if (err >= 0) {
warned = 0;
err = 0;
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH 22/22] NLM: Clean up flow of control in make_socks() function
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (20 preceding siblings ...)
2008-12-12 21:59 ` [PATCH 21/22] NLM: Refactor make_socks() function Chuck Lever
@ 2008-12-12 21:59 ` Chuck Lever
2008-12-16 16:53 ` [PATCH 00/22] IPv6 support NFSD J. Bruce Fields
2008-12-25 5:01 ` J. Bruce Fields
23 siblings, 0 replies; 37+ messages in thread
From: Chuck Lever @ 2008-12-12 21:59 UTC (permalink / raw)
To: bfields; +Cc: aime.le-rouzic, linux-nfs
Clean up: Use Bruce's preferred control flow style in make_socks().
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/lockd/svc.c | 22 ++++++++++++++--------
1 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 4ccb70a..b667a27 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -224,17 +224,23 @@ static int create_lockd_listener(struct svc_serv *serv, char *name,
static int make_socks(struct svc_serv *serv)
{
static int warned;
- int err = 0;
+ int err;
err = create_lockd_listener(serv, "udp", nlm_udpport);
- if (err >= 0)
- err = create_lockd_listener(serv, "tcp", nlm_tcpport);
- if (err >= 0) {
- warned = 0;
- err = 0;
- } else if (warned++ == 0)
+ if (err < 0)
+ goto out_err;
+
+ err = create_lockd_listener(serv, "tcp", nlm_tcpport);
+ if (err < 0)
+ goto out_err;
+
+ warned = 0;
+ return 0;
+
+out_err:
+ if (warned++ == 0)
printk(KERN_WARNING
- "lockd_up: makesock failed, error=%d\n", err);
+ "lockd_up: makesock failed, error=%d\n", err);
return err;
}
^ permalink raw reply related [flat|nested] 37+ messages in thread* Re: [PATCH 00/22] IPv6 support NFSD
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (21 preceding siblings ...)
2008-12-12 21:59 ` [PATCH 22/22] NLM: Clean up flow of control in " Chuck Lever
@ 2008-12-16 16:53 ` J. Bruce Fields
2008-12-25 5:01 ` J. Bruce Fields
23 siblings, 0 replies; 37+ messages in thread
From: J. Bruce Fields @ 2008-12-16 16:53 UTC (permalink / raw)
To: Chuck Lever; +Cc: aime.le-rouzic, linux-nfs
On Fri, Dec 12, 2008 at 04:57:02PM -0500, Chuck Lever wrote:
> Hi Bruce-
>
> These 22 patches enable support for IPv6 in the kernel's NFSD. Please
> consider them for 2.6.29.
>
> Special thanks to Aime Le Rouzic and the Bull team for their prototype
> and testing efforts.
I've applied the first four, by the way, thanks (the nfsctl
documentation was long-overdue); may take me a few days to get to the
rest, but I'll get to them....
--b.
>
> ---
>
> Aime Le Rouzic (1):
> NFSD: Support AF_INET6 in svc_addsock() function
>
> Chuck Lever (21):
> NLM: Clean up flow of control in make_socks() function
> NLM: Refactor make_socks() function
> NFSD: Prevent buffer overflow in write_recoverydir()
> NFSD: Prevent buffer overflow in write_leasetime()
> NFSD: Prevent buffer overflow in write_maxblksize()
> NFSD: Prevent buffer overflow in write_versions()
> NFSD: Prevent buffer overflow in write_threads()
> NFSD: Enable NFS server use of AF_INET6
> NFSD: Support IPv6 addresses in write_failover_ip()
> NFS: Move NFS client's IP address parser to nfs_common/
> SUNRPC: Clean up one_sock_name()
> SUNRPC: Support AF_INET6 in one_sock_name()
> SUNRPC: Switch one_sock_name() to use snprintf()
> SUNRPC: pass buffer size to svc_addsock() and svc_sock_names()
> NFSD: Prevent a buffer overflow in svc_xprt_names()
> NFSD: Refactor __write_ports()
> NFSD: Add helper functions for __write_ports()
> NFSD: Add documenting comments for nfsctl interface
> NFSD: Replace open-coded integer with macro
> NFSD: Fix a handful of coding style issues in write_filehandle()
> NFSD: clean up failover sysctl function naming
>
>
> fs/lockd/svc.c | 49 +--
> fs/nfs/internal.h | 3
> fs/nfs/nfs4namespace.c | 2
> fs/nfs/super.c | 121 ------
> fs/nfs_common/Makefile | 1
> fs/nfs_common/nfs_addr_parse.c | 155 ++++++++
> fs/nfsd/nfsctl.c | 773 ++++++++++++++++++++++++++++++++--------
> fs/nfsd/nfssvc.c | 13 +
> include/linux/nfs_addr_parse.h | 32 ++
> include/linux/sunrpc/svcsock.h | 6
> net/sunrpc/svc_xprt.c | 53 ++-
> net/sunrpc/svcsock.c | 82 +++-
> 12 files changed, 960 insertions(+), 330 deletions(-)
> create mode 100644 fs/nfs_common/nfs_addr_parse.c
> create mode 100644 include/linux/nfs_addr_parse.h
>
> --
> Chuck Lever
^ permalink raw reply [flat|nested] 37+ messages in thread* Re: [PATCH 00/22] IPv6 support NFSD
[not found] ` <20081212215340.24332.88416.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (22 preceding siblings ...)
2008-12-16 16:53 ` [PATCH 00/22] IPv6 support NFSD J. Bruce Fields
@ 2008-12-25 5:01 ` J. Bruce Fields
23 siblings, 0 replies; 37+ messages in thread
From: J. Bruce Fields @ 2008-12-25 5:01 UTC (permalink / raw)
To: Chuck Lever; +Cc: aime.le-rouzic, linux-nfs
On Fri, Dec 12, 2008 at 04:57:02PM -0500, Chuck Lever wrote:
> Hi Bruce-
>
> These 22 patches enable support for IPv6 in the kernel's NFSD. Please
> consider them for 2.6.29.
>
> Special thanks to Aime Le Rouzic and the Bull team for their prototype
> and testing efforts.
Except for comments on specific patches, those look fine, thanks.
Resend if necessary and I'll take another look.
--b.
>
> ---
>
> Aime Le Rouzic (1):
> NFSD: Support AF_INET6 in svc_addsock() function
>
> Chuck Lever (21):
> NLM: Clean up flow of control in make_socks() function
> NLM: Refactor make_socks() function
> NFSD: Prevent buffer overflow in write_recoverydir()
> NFSD: Prevent buffer overflow in write_leasetime()
> NFSD: Prevent buffer overflow in write_maxblksize()
> NFSD: Prevent buffer overflow in write_versions()
> NFSD: Prevent buffer overflow in write_threads()
> NFSD: Enable NFS server use of AF_INET6
> NFSD: Support IPv6 addresses in write_failover_ip()
> NFS: Move NFS client's IP address parser to nfs_common/
> SUNRPC: Clean up one_sock_name()
> SUNRPC: Support AF_INET6 in one_sock_name()
> SUNRPC: Switch one_sock_name() to use snprintf()
> SUNRPC: pass buffer size to svc_addsock() and svc_sock_names()
> NFSD: Prevent a buffer overflow in svc_xprt_names()
> NFSD: Refactor __write_ports()
> NFSD: Add helper functions for __write_ports()
> NFSD: Add documenting comments for nfsctl interface
> NFSD: Replace open-coded integer with macro
> NFSD: Fix a handful of coding style issues in write_filehandle()
> NFSD: clean up failover sysctl function naming
>
>
> fs/lockd/svc.c | 49 +--
> fs/nfs/internal.h | 3
> fs/nfs/nfs4namespace.c | 2
> fs/nfs/super.c | 121 ------
> fs/nfs_common/Makefile | 1
> fs/nfs_common/nfs_addr_parse.c | 155 ++++++++
> fs/nfsd/nfsctl.c | 773 ++++++++++++++++++++++++++++++++--------
> fs/nfsd/nfssvc.c | 13 +
> include/linux/nfs_addr_parse.h | 32 ++
> include/linux/sunrpc/svcsock.h | 6
> net/sunrpc/svc_xprt.c | 53 ++-
> net/sunrpc/svcsock.c | 82 +++-
> 12 files changed, 960 insertions(+), 330 deletions(-)
> create mode 100644 fs/nfs_common/nfs_addr_parse.c
> create mode 100644 include/linux/nfs_addr_parse.h
>
> --
> Chuck Lever
^ permalink raw reply [flat|nested] 37+ messages in thread