[PATCH 13/13] NFS: Integrate support for processing nfs4 mount options in fs/nfs/super.c

2007-05-21 Thread Chuck Lever
Finally, hook in the new mount option parsing logic.

Signed-off-by: Chuck Lever [EMAIL PROTECTED]
---

 fs/nfs/super.c |   87 
 1 files changed, 19 insertions(+), 68 deletions(-)

diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index e0acd08..222bb49 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -13,6 +13,8 @@
  *
  *  Split from inode.c by David Howells [EMAIL PROTECTED]
  *
+ *  In-kernel mount option parsing by Chuck Lever [EMAIL PROTECTED]
+ *
  * - superblocks are indexed on server only - all inodes, dentries, etc. 
associated with a
  *   particular server are held in the same superblock
  * - NFS superblocks can have several effective roots to the dentry tree
@@ -1532,7 +1534,6 @@ static int nfs4_parse_options(char *raw, struct 
nfs4_mount_args *mnt)
if (len  80)
goto out_clntaddr_long;
match_strcpy(mnt-clientaddr, args);
-   mnt-nmd.client_addr.data = mnt-clientaddr;
mnt-nmd.client_addr.len = len;
break;
}
@@ -1605,10 +1606,8 @@ static struct nfs4_mount_data 
*nfs4_convert_mount_opts(const char *options)
args-nmd.acdirmax = 60;
 
args-nmd.auth_flavourlen = 0;
-   args-nmd.auth_flavours = args-authflavor;
 
args-nmd.host_addrlen = sizeof(args-addr);
-   args-nmd.host_addr = (struct sockaddr *) args-addr;
 
args-addr.sin_port = htons(NFS_PORT);
 
@@ -1652,6 +1651,7 @@ static int nfs4_validate_mount_data(struct 
nfs4_mount_data **options,
char *ip_addr)
 {
struct nfs4_mount_data *data = *options;
+   struct nfs4_mount_args *args;
char *c;
unsigned len;
 
@@ -1707,25 +1707,26 @@ static int nfs4_validate_mount_data(struct 
nfs4_mount_data **options,
if (IS_ERR(data))
return PTR_ERR(data);
*options = data;
+   args = (struct nfs4_mount_args *) data;
 
-   memcpy(addr, data-host_addr, sizeof(*addr));
-   if (!nfs_verify_server_address((struct sockaddr *) addr,
+   if (!nfs_verify_server_address((struct sockaddr *) args-addr,
data-host_addrlen))
return -EINVAL;
+   memcpy(addr, args-addr, sizeof(*addr));
 
switch (data-auth_flavourlen) {
case 0:
*authflavour = RPC_AUTH_UNIX;
break;
case 1:
-   *authflavour = (rpc_authflavor_t) 
data-auth_flavours[0];
+   *authflavour = (rpc_authflavor_t) args-authflavor;
break;
default:
goto out_inval_auth;
}
 
memset(ip_addr, '\0', data-client_addr.len + 1);
-   strncpy(ip_addr, data-client_addr.data, data-client_addr.len);
+   strncpy(ip_addr, args-clientaddr, data-client_addr.len);
 
/*
 * Split dev_name into hostname:mntpath.
@@ -1804,67 +1805,17 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
struct nfs_fh mntfh;
struct dentry *mntroot;
char *mntpath = NULL, *hostname = NULL, ip_addr[16];
-   void *p;
int error;
 
-   if (data == NULL) {
-   dprintk(%s: missing data argument\n, __FUNCTION__);
-   return -EINVAL;
-   }
-   if (data-version = 0 || data-version  NFS4_MOUNT_VERSION) {
-   dprintk(%s: bad mount version\n, __FUNCTION__);
-   return -EINVAL;
-   }
-
-   /* We now require that the mount process passes the remote address */
-   if (data-host_addrlen != sizeof(addr))
-   return -EINVAL;
-
-   if (copy_from_user(addr, data-host_addr, sizeof(addr)))
-   return -EFAULT;
-
-   if (!nfs_verify_server_address((struct sockaddr *) addr,
-   data-host_addrlen))
-   return -EINVAL;
-
-   /* RFC3530: The default port for NFS is 2049 */
-   if (addr.sin_port == 0)
-   addr.sin_port = htons(NFS_PORT);
-
-   /* Grab the authentication type */
-   authflavour = RPC_AUTH_UNIX;
-   if (data-auth_flavourlen != 0) {
-   if (data-auth_flavourlen != 1) {
-   dprintk(%s: Invalid number of RPC auth flavours %d.\n,
-   __FUNCTION__, data-auth_flavourlen);
-   error = -EINVAL;
-   goto out_err_noserver;
-   }
-
-   if (copy_from_user(authflavour, data-auth_flavours,
-  sizeof(authflavour))) {
-   error = -EFAULT;
-   goto out_err_noserver;
-   }
+   

[PATCH 06/13] NFS: Improve debugging output in NFS in-kernel mount client

2007-05-21 Thread Chuck Lever
Signed-off-by: Chuck Lever [EMAIL PROTECTED]
---

 fs/nfs/mount_clnt.c|   18 +-
 include/linux/nfs_fs.h |1 +
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index f8584ad..81ea782 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -16,7 +16,7 @@
 #include linux/nfs_fs.h
 
 #ifdef RPC_DEBUG
-# define NFSDBG_FACILITY   NFSDBG_ROOT
+# define NFSDBG_FACILITY   NFSDBG_MOUNT
 #endif
 
 static struct rpc_program  mnt_program;
@@ -72,8 +72,8 @@ int nfs_mount(struct sockaddr_in *addr, char *path, struct 
nfs_fh *fh,
charhostname[32];
int status;
 
-   dprintk(NFS:  nfs_mount(%08x:%s)\n,
-   (unsigned)ntohl(addr-sin_addr.s_addr), path);
+   dprintk(NFS: %s: mounting NIPQUAD_FMT :%s\n,
+   __FUNCTION__, NIPQUAD(addr-sin_addr.s_addr), path);
 
sprintf(hostname, NIPQUAD_FMT, NIPQUAD(addr-sin_addr.s_addr));
mnt_clnt = mnt_create(hostname, addr, version, protocol);
@@ -86,10 +86,18 @@ int nfs_mount(struct sockaddr_in *addr, char *path, struct 
nfs_fh *fh,
msg.rpc_proc = mnt_clnt-cl_procinfo[MNTPROC_MNT];
 
status = rpc_call_sync(mnt_clnt, msg, 0);
-   if (status  0)
+   if (status  0) {
+   dprintk(NFS: %s: rpc_call_sync returned %d\n,
+   __FUNCTION__, status);
return status;
-   if (result.status != 0)
+   }
+   if (result.status != 0) {
+   dprintk(NFS: %s: server returned %d\n,
+   __FUNCTION__, result.status);
return -EACCES;
+   }
+   dprintk(NFS: %s: mount request succeeded\n,
+   __FUNCTION__);
return 0;
 }
 
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 58f5b77..2f33ef7 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -555,6 +555,7 @@ extern void * nfs_root_data(void);
 #define NFSDBG_ROOT0x0080
 #define NFSDBG_CALLBACK0x0100
 #define NFSDBG_CLIENT  0x0200
+#define NFSDBG_MOUNT   0x0400
 #define NFSDBG_ALL 0x
 
 #ifdef __KERNEL__

-
To unsubscribe from this list: send the line unsubscribe linux-fsdevel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 09/13] NFS: Implement NFSv2/3 in-kernel mount option parsing

2007-05-21 Thread Chuck Lever
Signed-off-by: Chuck Lever [EMAIL PROTECTED]
---

 fs/nfs/super.c |  130 +++-
 1 files changed, 82 insertions(+), 48 deletions(-)

diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index a9f698b..7b7cacb 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -935,8 +935,6 @@ static struct nfs_mount_data *nfs_convert_mount_opts(const 
char *options)
if (args == NULL)
return ERR_PTR(-ENOMEM);
 
-   args-nmd.version = 7;
-
args-nmd.flags = (NFS_MOUNT_VER3 | NFS_MOUNT_TCP);
args-nmd.rsize = NFS_MAX_FILE_IO_SIZE;
args-nmd.wsize = NFS_MAX_FILE_IO_SIZE;
@@ -989,71 +987,74 @@ out_invalid:
  * Validate the NFS2/NFS3 mount data
  * - fills in the mount root filehandle
  */
-static int nfs_validate_mount_data(struct nfs_mount_data *data,
-  struct nfs_fh *mntfh)
+static int nfs_validate_mount_data(struct nfs_mount_data **options,
+  struct nfs_fh *mntfh,
+  const char *dev_name)
 {
-   if (data == NULL) {
-   dprintk(%s: missing data argument\n, __FUNCTION__);
-   return -EINVAL;
-   }
+   struct nfs_mount_data *data = *options;
+   unsigned int len;
+   char *c;
+   int status;
 
-   if (data-version = 0 || data-version  NFS_MOUNT_VERSION) {
-   dprintk(%s: bad mount version\n, __FUNCTION__);
-   return -EINVAL;
-   }
+   if (data == NULL)
+   goto out_no_data;
 
switch (data-version) {
-   case 1:
-   data-namlen = 0;
-   case 2:
-   data-bsize  = 0;
-   case 3:
-   if (data-flags  NFS_MOUNT_VER3) {
-   dprintk(%s: mount structure version %d does 
not support NFSv3\n,
-   __FUNCTION__,
-   data-version);
-   return -EINVAL;
-   }
-   data-root.size = NFS2_FHSIZE;
-   memcpy(data-root.data, data-old_root.data, 
NFS2_FHSIZE);
-   case 4:
-   if (data-flags  NFS_MOUNT_SECFLAVOUR) {
-   dprintk(%s: mount structure version %d does 
not support strong security\n,
-   __FUNCTION__,
-   data-version);
-   return -EINVAL;
-   }
-   case 5:
-   memset(data-context, 0, sizeof(data-context));
+   case 1:
+   data-namlen = 0;
+   case 2:
+   data-bsize  = 0;
+   case 3:
+   if (data-flags  NFS_MOUNT_VER3)
+   goto out_no_v3;
+   data-root.size = NFS2_FHSIZE;
+   memcpy(data-root.data, data-old_root.data, NFS2_FHSIZE);
+   case 4:
+   if (data-flags  NFS_MOUNT_SECFLAVOUR)
+   goto out_no_sec;
+   case 5:
+   memset(data-context, 0, sizeof(data-context));
+   case 6:
+   break;
+   default:
+   data = nfs_convert_mount_opts((char *) data);
+   if (IS_ERR(data))
+   return PTR_ERR(data);
+   *options = data;
+
+   c = strchr(dev_name, ':');
+   if (c == NULL)
+   return -EINVAL;
+   len = c - dev_name - 1;
+   if (len  256)
+   return -EINVAL;
+   strncpy(data-hostname, dev_name, len);
+
+   status = nfs_try_mount(data, ++c);
+   if (status)
+   return -EINVAL;
}
 
-   /* Set the pseudoflavor */
if (!(data-flags  NFS_MOUNT_SECFLAVOUR))
data-pseudoflavor = RPC_AUTH_UNIX;
 
 #ifndef CONFIG_NFS_V3
-   /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */
-   if (data-flags  NFS_MOUNT_VER3) {
-   dprintk(%s: NFSv3 not compiled into kernel\n, __FUNCTION__);
-   return -EPROTONOSUPPORT;
-   }
-#endif /* CONFIG_NFS_V3 */
+   if (data-flags  NFS_MOUNT_VER3)
+   goto out_v3_not_compiled;
+#endif /* !CONFIG_NFS_V3 */
 
/* We now require that the mount process passes the remote address */
if (!nfs_verify_server_address((struct sockaddr *) data-addr,
sizeof(data-addr)))
return -EINVAL;
 
-   /* Prepare the root filehandle */
if (data-flags  NFS_MOUNT_VER3)
mntfh-size = data-root.size;
else
mntfh-size = NFS2_FHSIZE;
 
-   if (mntfh-size  sizeof(mntfh-data)) {
-   dprintk(%s: invalid root filehandle\n, __FUNCTION__);
-   return 

[PATCH 01/13] NFS: Refactor IP address sanity checks in NFS client

2007-05-21 Thread Chuck Lever
Provide mechanism for adding IPv6 address support at some later point.

Signed-off-by: Chuck Lever [EMAIL PROTECTED]
Cc: Aurelien Charbon [EMAIL PROTECTED]
---

 fs/nfs/super.c |   39 ---
 1 files changed, 28 insertions(+), 11 deletions(-)

diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 1fce778..31f7313 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -436,6 +436,28 @@ static void nfs_umount_begin(struct vfsmount *vfsmnt, int 
flags)
 }
 
 /*
+ * Sanity-check a server address provided by the mount command
+ */
+static int nfs_verify_server_address(struct sockaddr *addr, size_t len)
+{
+   if (len  sizeof(struct sockaddr))
+   goto out_invalid;
+
+   switch (addr-sa_family) {
+   case AF_INET: {
+   struct sockaddr_in *sa = (struct sockaddr_in *) addr;
+   if (sa-sin_addr.s_addr != INADDR_ANY)
+   return 1;
+   break;
+   }
+   }
+
+out_invalid:
+   dprintk(NFS: mount program passed an invalid remote address\n);
+   return 0;
+}
+
+/*
  * Validate the NFS2/NFS3 mount data
  * - fills in the mount root filehandle
  */
@@ -490,11 +512,9 @@ static int nfs_validate_mount_data(struct nfs_mount_data 
*data,
 #endif /* CONFIG_NFS_V3 */
 
/* We now require that the mount process passes the remote address */
-   if (data-addr.sin_addr.s_addr == INADDR_ANY) {
-   dprintk(%s: mount program didn't pass remote address!\n,
-   __FUNCTION__);
-   return -EINVAL;
-   }
+   if (!nfs_verify_server_address((struct sockaddr *) data-addr,
+   sizeof(data-addr)))
+   return -EINVAL;
 
/* Prepare the root filehandle */
if (data-flags  NFS_MOUNT_VER3)
@@ -828,13 +848,10 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
if (copy_from_user(addr, data-host_addr, sizeof(addr)))
return -EFAULT;
 
-   if (addr.sin_family != AF_INET ||
-   addr.sin_addr.s_addr == INADDR_ANY
-   ) {
-   dprintk(%s: mount program didn't pass remote IP address!\n,
-   __FUNCTION__);
+   if (!nfs_verify_server_address((struct sockaddr *) addr,
+   data-host_addrlen))
return -EINVAL;
-   }
+
/* RFC3530: The default port for NFS is 2049 */
if (addr.sin_port == 0)
addr.sin_port = htons(NFS_PORT);

-
To unsubscribe from this list: send the line unsubscribe linux-fsdevel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 08/13] NFS: Add functions to parse nfs mount options to fs/nfs/super.c

2007-05-21 Thread Chuck Lever
For NFSv2 and NFSv3 mount options.

Signed-off-by: Chuck Lever [EMAIL PROTECTED]
---

 fs/nfs/super.c |  449 
 1 files changed, 449 insertions(+), 0 deletions(-)

diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 1974648..a9f698b 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -514,6 +514,455 @@ static void nfs_umount_begin(struct vfsmount *vfsmnt, int 
flags)
shrink_submounts(vfsmnt, nfs_automount_list);
 }
 
+
+static match_table_t nfs_tokens = {
+   {Opt_userspace, bg},
+   {Opt_userspace, fg},
+   {Opt_soft, soft},
+   {Opt_hard, hard},
+   {Opt_intr, intr},
+   {Opt_nointr, nointr},
+   {Opt_posix, posix},
+   {Opt_noposix, noposix},
+   {Opt_cto, cto},
+   {Opt_nocto, nocto},
+   {Opt_ac, ac},
+   {Opt_noac, noac},
+   {Opt_lock, lock},
+   {Opt_nolock, nolock},
+   {Opt_v2, v2},
+   {Opt_v3, v3},
+   {Opt_udp, udp},
+   {Opt_tcp, tcp},
+   {Opt_acl, acl},
+   {Opt_noacl, noacl},
+
+   {Opt_port, port=%u},
+   {Opt_rsize, rsize=%u},
+   {Opt_wsize, wsize=%u},
+   {Opt_timeo, timeo=%u},
+   {Opt_retrans, retrans=%u},
+   {Opt_acregmin, acregmin=%u},
+   {Opt_acregmax, acregmax=%u},
+   {Opt_acdirmin, acdirmin=%u},
+   {Opt_acdirmax, acdirmax=%u},
+   {Opt_actimeo, actimeo=%u},
+   {Opt_userspace, retry=%u},
+   {Opt_namelen, namlen=%u},
+   {Opt_mountport, mountport=%u},
+   {Opt_mountprog, mountprog=%u},
+   {Opt_mountvers, mountvers=%u},
+   {Opt_nfsprog, nfsprog=%u},
+   {Opt_nfsvers, nfsvers=%u},
+   {Opt_nfsvers, vers=%u},
+
+   {Opt_sec, sec=%s},
+   {Opt_proto, proto=%s},
+   {Opt_addr, addr=%s},
+   {Opt_mounthost, mounthost=%s},
+   {Opt_context, context=%s},
+
+   {Opt_err, NULL},
+};
+
+static int nfs_parse_options(char *raw, struct nfs_mount_args *mnt)
+{
+   char *p, *string;
+
+   if (!raw) {
+   dprintk(NFS: mount options string was NULL.\n);
+   return 1;
+   }
+
+   while ((p = strsep (raw, ,)) != NULL) {
+   substring_t args[MAX_OPT_ARGS];
+   int option, token;
+
+   if (!*p)
+   continue;
+   token = match_token(p, nfs_tokens, args);
+
+   dprintk(NFS:   nfs mount option '%s': parsing token %d\n,
+   p, token);
+
+   switch (token) {
+   case Opt_soft:
+   mnt-nmd.flags |= NFS_MOUNT_SOFT;
+   break;
+   case Opt_hard:
+   mnt-nmd.flags = ~NFS_MOUNT_SOFT;
+   break;
+   case Opt_intr:
+   mnt-nmd.flags |= NFS_MOUNT_INTR;
+   break;
+   case Opt_nointr:
+   mnt-nmd.flags = ~NFS_MOUNT_INTR;
+   break;
+   case Opt_posix:
+   mnt-nmd.flags |= NFS_MOUNT_POSIX;
+   break;
+   case Opt_noposix:
+   mnt-nmd.flags = ~NFS_MOUNT_POSIX;
+   break;
+   case Opt_cto:
+   mnt-nmd.flags = ~NFS_MOUNT_NOCTO;
+   break;
+   case Opt_nocto:
+   mnt-nmd.flags |= NFS_MOUNT_NOCTO;
+   break;
+   case Opt_ac:
+   mnt-nmd.flags = ~NFS_MOUNT_NOAC;
+   break;
+   case Opt_noac:
+   mnt-nmd.flags |= NFS_MOUNT_NOAC;
+   break;
+   case Opt_lock:
+   mnt-nmd.flags = ~NFS_MOUNT_NONLM;
+   break;
+   case Opt_nolock:
+   mnt-nmd.flags |= NFS_MOUNT_NONLM;
+   break;
+   case Opt_v2:
+   mnt-nmd.flags = ~NFS_MOUNT_VER3;
+   break;
+   case Opt_v3:
+   mnt-nmd.flags |= NFS_MOUNT_VER3;
+   break;
+   case Opt_udp:
+   mnt-nmd.flags = ~NFS_MOUNT_TCP;
+   break;
+   case Opt_tcp:
+   mnt-nmd.flags |= NFS_MOUNT_TCP;
+   break;
+   case Opt_acl:
+   mnt-nmd.flags = ~NFS_MOUNT_NOACL;
+   break;
+   case Opt_noacl:
+   mnt-nmd.flags |= NFS_MOUNT_NOACL;
+   break;
+
+   case Opt_port:
+   if (match_int(args, option))
+   return 0;
+   if (option  0 || option  65535)
+   return 0;
+   mnt-nmd.addr.sin_port = htonl(option);
+   break;
+   case Opt_rsize:
+  

[PATCH 10/13] NFS: Add functions to parse nfs4 mount options to fs/nfs/super.c

2007-05-21 Thread Chuck Lever
Add helpers required for parsing nfs4 mount options in the NFS
client.

Signed-off-by: Chuck Lever [EMAIL PROTECTED]
---

 fs/nfs/super.c |  290 
 1 files changed, 290 insertions(+), 0 deletions(-)

diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 7b7cacb..927c1c2 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -1332,6 +1332,296 @@ error_splat_super:
 
 #ifdef CONFIG_NFS_V4
 
+static match_table_t nfs4_tokens = {
+   {Opt_userspace, bg},
+   {Opt_userspace, fg},
+   {Opt_soft, soft},
+   {Opt_hard, hard},
+   {Opt_intr, intr},
+   {Opt_nointr, nointr},
+   {Opt_cto, cto},
+   {Opt_nocto, nocto},
+   {Opt_ac, ac},
+   {Opt_noac, noac},
+
+   {Opt_port, port=%u},
+   {Opt_rsize, rsize=%u},
+   {Opt_wsize, wsize=%u},
+   {Opt_timeo, timeo=%u},
+   {Opt_retrans, retrans=%u},
+   {Opt_acregmin, acregmin=%u},
+   {Opt_acregmax, acregmax=%u},
+   {Opt_acdirmin, acdirmin=%u},
+   {Opt_acdirmax, acdirmax=%u},
+   {Opt_actimeo, actimeo=%u},
+   {Opt_userspace, retry=%u},
+
+   {Opt_sec, sec=%s},
+   {Opt_proto, proto=%s},
+   {Opt_addr, addr=%s},
+   {Opt_clientaddr, clientaddr=%s},
+
+   {Opt_err, NULL},
+};
+
+static int nfs4_parse_options(char *raw, struct nfs4_mount_args *mnt)
+{
+   char *p, *string;
+
+   if (!raw)
+   return 1;
+
+   while ((p = strsep (raw, ,)) != NULL) {
+   substring_t args[MAX_OPT_ARGS];
+   int option, token;
+
+   if (!*p)
+   continue;
+   token = match_token(p, nfs4_tokens, args);
+
+   dprintk(NFS:   nfs4 mount option '%s': parsing token %d\n,
+   p, token);
+
+   switch (token) {
+   case Opt_soft:
+   mnt-nmd.flags |= NFS4_MOUNT_SOFT;
+   break;
+   case Opt_hard:
+   mnt-nmd.flags = ~NFS4_MOUNT_SOFT;
+   break;
+   case Opt_intr:
+   mnt-nmd.flags |= NFS4_MOUNT_INTR;
+   break;
+   case Opt_nointr:
+   mnt-nmd.flags = ~NFS4_MOUNT_INTR;
+   break;
+   case Opt_cto:
+   mnt-nmd.flags = ~NFS4_MOUNT_NOCTO;
+   break;
+   case Opt_nocto:
+   mnt-nmd.flags |= NFS4_MOUNT_NOCTO;
+   break;
+   case Opt_ac:
+   mnt-nmd.flags = ~NFS4_MOUNT_NOAC;
+   break;
+   case Opt_noac:
+   mnt-nmd.flags |= NFS4_MOUNT_NOAC;
+   break;
+
+   case Opt_port:
+   if (match_int(args, option))
+   return 0;
+   if (option  0 || option  65535)
+   return 0;
+   mnt-addr.sin_port = htonl(option);
+   break;
+   case Opt_rsize:
+   if (match_int(args, mnt-nmd.rsize))
+   return 0;
+   break;
+   case Opt_wsize:
+   if (match_int(args, mnt-nmd.wsize))
+   return 0;
+   break;
+   case Opt_timeo:
+   if (match_int(args, mnt-nmd.timeo))
+   return 0;
+   break;
+   case Opt_retrans:
+   if (match_int(args, mnt-nmd.retrans))
+   return 0;
+   break;
+   case Opt_acregmin:
+   if (match_int(args, mnt-nmd.acregmin))
+   return 0;
+   break;
+   case Opt_acregmax:
+   if (match_int(args, mnt-nmd.acregmax))
+   return 0;
+   break;
+   case Opt_acdirmin:
+   if (match_int(args, mnt-nmd.acdirmin))
+   return 0;
+   break;
+   case Opt_acdirmax:
+   if (match_int(args, mnt-nmd.acdirmax))
+   return 0;
+   break;
+   case Opt_actimeo:
+   if (match_int(args, option))
+   return 0;
+   if (option  0)
+   return 0;
+   mnt-nmd.acregmin =
+   mnt-nmd.acregmax =
+   mnt-nmd.acdirmin =
+   mnt-nmd.acdirmax = option;
+   break;
+
+   case Opt_proto: {
+   string = match_strdup(args);
+   if 

[PATCH 04/13] NFS: Remake nfsroot_mount as a permanent part of NFS client

2007-05-21 Thread Chuck Lever
In preparation for supporting NFSv2 and NFSv3 mount option handling in the
kernel NFS client, convert mount_clnt.c to be a permanent part of the NFS
client, instead of built only when CONFIG_ROOT_NFS is enabled.

Signed-off-by: Chuck Lever [EMAIL PROTECTED]
---

 fs/nfs/Makefile|4 ++--
 fs/nfs/mount_clnt.c|   18 +-
 fs/nfs/nfsroot.c   |2 +-
 include/linux/nfs_fs.h |4 +---
 4 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index f4580b4..b55cb23 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -6,8 +6,8 @@ obj-$(CONFIG_NFS_FS) += nfs.o
 
 nfs-y  := client.o dir.o file.o getroot.o inode.o super.o 
nfs2xdr.o \
   pagelist.o proc.o read.o symlink.o unlink.o \
-  write.o namespace.o
-nfs-$(CONFIG_ROOT_NFS) += nfsroot.o mount_clnt.o  
+  write.o namespace.o mount_clnt.o
+nfs-$(CONFIG_ROOT_NFS) += nfsroot.o
 nfs-$(CONFIG_NFS_V3)   += nfs3proc.o nfs3xdr.o
 nfs-$(CONFIG_NFS_V3_ACL)   += nfs3acl.o
 nfs-$(CONFIG_NFS_V4)   += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index ca5a266..82a8536 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -37,12 +37,20 @@ struct mnt_fhstatus {
struct nfs_fh * fh;
 };
 
-/*
- * Obtain an NFS file handle for the given host and path
+/**
+ * nfs_mount - Obtain an NFS file handle for the given host and path
+ * @addr: pointer to server's address
+ * @path: pointer to string containing export path to mount
+ * @fh: pointer to location to place returned file handle
+ * @version: mount version to use for this request
+ * @protocol: transport protocol to use for thie request
+ *
+ * Uses default timeout parameters specified by underlying transport.
+ *
+ * XXX: Needs to support IPv6
  */
-int
-nfsroot_mount(struct sockaddr_in *addr, char *path, struct nfs_fh *fh,
-   int version, int protocol)
+int nfs_mount(struct sockaddr_in *addr, char *path, struct nfs_fh *fh,
+ int version, int protocol)
 {
struct rpc_clnt *mnt_clnt;
struct mnt_fhstatus result = {
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index f0db470..a52c891 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -496,7 +496,7 @@ static int __init root_nfs_get_handle(void)
NFS_MNT3_VERSION : NFS_MNT_VERSION;
 
set_sockaddr(sin, servaddr, htons(mount_port));
-   status = nfsroot_mount(sin, nfs_path, fh, version, protocol);
+   status = nfs_mount(sin, nfs_path, fh, version, protocol);
if (status  0)
printk(KERN_ERR Root-NFS: Server returned error %d 
while mounting %s\n, status, nfs_path);
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 0543439..58f5b77 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -496,10 +496,8 @@ static inline void nfs3_forget_cached_acls(struct inode 
*inode)
 
 /*
  * linux/fs/mount_clnt.c
- * (Used only by nfsroot module)
  */
-extern int  nfsroot_mount(struct sockaddr_in *, char *, struct nfs_fh *,
-   int, int);
+extern int  nfs_mount(struct sockaddr_in *, char *, struct nfs_fh *, int, int);
 
 /*
  * inline functions

-
To unsubscribe from this list: send the line unsubscribe linux-fsdevel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 05/13] NFS: Clean up in-kernel NFS mount

2007-05-21 Thread Chuck Lever
Clean up white space and coding conventions.

Signed-off-by: Chuck Lever [EMAIL PROTECTED]
---

 fs/nfs/mount_clnt.c |  132 ---
 1 files changed, 63 insertions(+), 69 deletions(-)

diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index 82a8536..f8584ad 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -1,7 +1,5 @@
 /*
- * linux/fs/nfs/mount_clnt.c
- *
- * MOUNT client to support NFSroot.
+ * In-kernel MOUNT protocol client
  *
  * Copyright (C) 1997, Olaf Kirch [EMAIL PROTECTED]
  */
@@ -21,22 +19,33 @@
 # define NFSDBG_FACILITY   NFSDBG_ROOT
 #endif
 
-/*
-#define MOUNT_PROGRAM  15
-#define MOUNT_VERSION  1
-#define MOUNT_MNT  1
-#define MOUNT_UMNT 3
- */
-
-static struct rpc_clnt *   mnt_create(char *, struct sockaddr_in *,
-   int, int);
 static struct rpc_program  mnt_program;
 
 struct mnt_fhstatus {
-   unsigned intstatus;
-   struct nfs_fh * fh;
+   u32 status;
+   struct nfs_fh *fh;
 };
 
+static struct rpc_clnt *mnt_create(char *hostname,
+  struct sockaddr_in *srvaddr,
+  int version,
+  int protocol)
+{
+   struct rpc_create_args args = {
+   .protocol   = protocol,
+   .address= (struct sockaddr *)srvaddr,
+   .addrsize   = sizeof(*srvaddr),
+   .servername = hostname,
+   .program= mnt_program,
+   .version= version,
+   .authflavor = RPC_AUTH_UNIX,
+   .flags  = (RPC_CLNT_CREATE_ONESHOT |
+  RPC_CLNT_CREATE_INTR),
+   };
+
+   return rpc_create(args);
+}
+
 /**
  * nfs_mount - Obtain an NFS file handle for the given host and path
  * @addr: pointer to server's address
@@ -66,7 +75,7 @@ int nfs_mount(struct sockaddr_in *addr, char *path, struct 
nfs_fh *fh,
dprintk(NFS:  nfs_mount(%08x:%s)\n,
(unsigned)ntohl(addr-sin_addr.s_addr), path);
 
-   sprintf(hostname, %u.%u.%u.%u, NIPQUAD(addr-sin_addr.s_addr));
+   sprintf(hostname, NIPQUAD_FMT, NIPQUAD(addr-sin_addr.s_addr));
mnt_clnt = mnt_create(hostname, addr, version, protocol);
if (IS_ERR(mnt_clnt))
return PTR_ERR(mnt_clnt);
@@ -77,33 +86,18 @@ int nfs_mount(struct sockaddr_in *addr, char *path, struct 
nfs_fh *fh,
msg.rpc_proc = mnt_clnt-cl_procinfo[MNTPROC_MNT];
 
status = rpc_call_sync(mnt_clnt, msg, 0);
-   return status  0? status : (result.status? -EACCES : 0);
-}
-
-static struct rpc_clnt *
-mnt_create(char *hostname, struct sockaddr_in *srvaddr, int version,
-   int protocol)
-{
-   struct rpc_create_args args = {
-   .protocol   = protocol,
-   .address= (struct sockaddr *)srvaddr,
-   .addrsize   = sizeof(*srvaddr),
-   .servername = hostname,
-   .program= mnt_program,
-   .version= version,
-   .authflavor = RPC_AUTH_UNIX,
-   .flags  = (RPC_CLNT_CREATE_ONESHOT |
-  RPC_CLNT_CREATE_INTR),
-   };
-
-   return rpc_create(args);
+   if (status  0)
+   return status;
+   if (result.status != 0)
+   return -EACCES;
+   return 0;
 }
 
 /*
  * XDR encode/decode functions for MOUNT
  */
-static int
-xdr_encode_dirpath(struct rpc_rqst *req, __be32 *p, const char *path)
+static int xdr_encode_dirpath(struct rpc_rqst *req, __be32 *p,
+ const char *path)
 {
p = xdr_encode_string(p, path);
 
@@ -111,8 +105,8 @@ xdr_encode_dirpath(struct rpc_rqst *req, __be32 *p, const 
char *path)
return 0;
 }
 
-static int
-xdr_decode_fhstatus(struct rpc_rqst *req, __be32 *p, struct mnt_fhstatus *res)
+static int xdr_decode_fhstatus(struct rpc_rqst *req, __be32 *p,
+  struct mnt_fhstatus *res)
 {
struct nfs_fh *fh = res-fh;
 
@@ -123,8 +117,8 @@ xdr_decode_fhstatus(struct rpc_rqst *req, __be32 *p, struct 
mnt_fhstatus *res)
return 0;
 }
 
-static int
-xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p, struct mnt_fhstatus *res)
+static int xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p,
+   struct mnt_fhstatus *res)
 {
struct nfs_fh *fh = res-fh;
 
@@ -143,53 +137,53 @@ xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p, 
struct mnt_fhstatus *res)
 #define MNT_fhstatus_sz(1 + 8)
 #define MNT_fhstatus3_sz   (1 + 16)
 
-static struct rpc_procinfo mnt_procedures[] = {
-[MNTPROC_MNT] = {
- .p_proc   = MNTPROC_MNT,
- .p_encode = (kxdrproc_t) 

[PATCH 03/13] SUNRPC: Rename rpcb_getport to be consistent with new rpcb_getport_sync name

2007-05-21 Thread Chuck Lever
Clean up, for consistency.  Rename rpcb_getport as rpcb_getport_async, to
match the naming scheme of rpcb_getport_sync.

Signed-off-by: Chuck Lever [EMAIL PROTECTED]
---

 include/linux/sunrpc/clnt.h |2 +-
 net/sunrpc/rpcb_clnt.c  |   37 +++--
 net/sunrpc/xprtsock.c   |4 ++--
 3 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index c51bc8c..9bea7b5 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -124,8 +124,8 @@ int rpc_destroy_client(struct rpc_clnt *);
 void   rpc_release_client(struct rpc_clnt *);
 
 intrpcb_register(u32, u32, int, unsigned short, int *);
-void   rpcb_getport(struct rpc_task *);
 intrpcb_getport_sync(struct sockaddr_in *, __u32, __u32, int);
+void   rpcb_getport_async(struct rpc_task *);
 
 void   rpc_call_setup(struct rpc_task *, struct rpc_message *, int);
 
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 5a52604..905ba5a 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -298,13 +298,13 @@ int rpcb_getport_sync(struct sockaddr_in *sin, __u32 prog,
 EXPORT_SYMBOL_GPL(rpcb_getport_sync);
 
 /**
- * rpcb_getport - obtain the port for a given RPC service on a given host
+ * rpcb_getport_async - obtain the port for a given RPC service on a given host
  * @task: task that is waiting for portmapper request
  *
  * This one can be called for an ongoing RPC request, and can be used in
  * an async (rpciod) context.
  */
-void rpcb_getport(struct rpc_task *task)
+void rpcb_getport_async(struct rpc_task *task)
 {
struct rpc_clnt *clnt = task-tk_client;
int bind_version;
@@ -315,17 +315,17 @@ void rpcb_getport(struct rpc_task *task)
struct sockaddr addr;
int status;
 
-   dprintk(RPC: %5u rpcb_getport(%s, %u, %u, %d)\n,
-   task-tk_pid, clnt-cl_server,
-   clnt-cl_prog, clnt-cl_vers, xprt-prot);
+   dprintk(RPC: %5u %s(%s, %u, %u, %d)\n,
+   task-tk_pid, __FUNCTION__,
+   clnt-cl_server, clnt-cl_prog, clnt-cl_vers, xprt-prot);
 
/* Autobind on cloned rpc clients is discouraged */
BUG_ON(clnt-cl_parent != clnt);
 
if (xprt_test_and_set_binding(xprt)) {
status = -EACCES;   /* tell caller to check again */
-   dprintk(RPC: %5u rpcb_getport waiting for another binder\n,
-   task-tk_pid);
+   dprintk(RPC: %5u %s: waiting for another binder\n,
+   task-tk_pid, __FUNCTION__);
goto bailout_nowake;
}
 
@@ -336,27 +336,28 @@ void rpcb_getport(struct rpc_task *task)
/* Someone else may have bound if we slept */
if (xprt_bound(xprt)) {
status = 0;
-   dprintk(RPC: %5u rpcb_getport already bound\n, task-tk_pid);
+   dprintk(RPC: %5u %s: already bound\n,
+   task-tk_pid, __FUNCTION__);
goto bailout_nofree;
}
 
if (rpcb_next_version[xprt-bind_index].rpc_proc == NULL) {
xprt-bind_index = 0;
status = -EACCES;   /* tell caller to try again later */
-   dprintk(RPC: %5u rpcb_getport no more getport versions 
-   available\n, task-tk_pid);
+   dprintk(RPC: %5u %s: no more getport versions available\n,
+   task-tk_pid, __FUNCTION__);
goto bailout_nofree;
}
bind_version = rpcb_next_version[xprt-bind_index].rpc_vers;
 
-   dprintk(RPC: %5u rpcb_getport trying rpcbind version %u\n,
-   task-tk_pid, bind_version);
+   dprintk(RPC: %5u %s: trying rpcbind version %u\n,
+   task-tk_pid, __FUNCTION__, bind_version);
 
map = kzalloc(sizeof(struct rpcbind_args), GFP_ATOMIC);
if (!map) {
status = -ENOMEM;
-   dprintk(RPC: %5u rpcb_getport no memory available\n,
-   task-tk_pid);
+   dprintk(RPC: %5u %s: no memory available\n,
+   task-tk_pid, __FUNCTION__);
goto bailout_nofree;
}
map-r_prog = clnt-cl_prog;
@@ -374,16 +375,16 @@ void rpcb_getport(struct rpc_task *task)
rpcb_clnt = rpcb_create(clnt-cl_server, addr, xprt-prot, 
bind_version, 0);
if (IS_ERR(rpcb_clnt)) {
status = PTR_ERR(rpcb_clnt);
-   dprintk(RPC: %5u rpcb_getport rpcb_create failed, error %ld\n,
-   task-tk_pid, PTR_ERR(rpcb_clnt));
+   dprintk(RPC: %5u %s: rpcb_create failed, error %ld\n,
+   task-tk_pid, __FUNCTION__, PTR_ERR(rpcb_clnt));
goto bailout;
}
 
child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, 

[PATCH 07/13] NFS: New infrastructure for NFS client in-kernel mount option parsing

2007-05-21 Thread Chuck Lever
Add some data structures and definitions to support parsing NFS mount
options in the kernel NFS client.

Signed-off-by: Chuck Lever [EMAIL PROTECTED]
---

 fs/nfs/super.c |   79 
 1 files changed, 79 insertions(+), 0 deletions(-)

diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 31f7313..1974648 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -45,6 +45,7 @@
 #include linux/inet.h
 #include linux/nfs_xdr.h
 #include linux/magic.h
+#include linux/parser.h
 
 #include asm/system.h
 #include asm/uaccess.h
@@ -57,6 +58,84 @@
 
 #define NFSDBG_FACILITYNFSDBG_VFS
 
+
+struct nfs_mount_args {
+   struct nfs_mount_data nmd;
+   unsigned int nfsprog;
+   unsigned use_mnthost;
+   struct sockaddr_in mnthost;
+   unsigned int mntprog;
+   unsigned int mntvers;
+   unsigned short mntport;
+};
+
+struct nfs4_mount_args {
+   struct nfs4_mount_data nmd;
+   struct sockaddr_in addr;
+   char clientaddr[16];
+   int authflavor;
+};
+
+enum {
+   /* Mount options that take no arguments */
+   Opt_soft, Opt_hard,
+   Opt_intr, Opt_nointr,
+   Opt_posix, Opt_noposix,
+   Opt_cto, Opt_nocto,
+   Opt_ac, Opt_noac,
+   Opt_lock, Opt_nolock,
+   Opt_v2, Opt_v3,
+   Opt_udp, Opt_tcp,
+   Opt_acl, Opt_noacl,
+
+   /* Mount options that take integer arguments */
+   Opt_port,
+   Opt_rsize, Opt_wsize,
+   Opt_timeo, Opt_retrans,
+   Opt_acregmin, Opt_acregmax,
+   Opt_acdirmin, Opt_acdirmax,
+   Opt_actimeo,
+   Opt_namelen,
+   Opt_mountport,
+   Opt_mountprog, Opt_mountvers,
+   Opt_nfsprog, Opt_nfsvers,
+
+   /* Mount options that take string arguments */
+   Opt_sec, Opt_proto, Opt_addr,
+   Opt_mounthost, Opt_clientaddr, Opt_context,
+
+   /* Mount options that are ignored */
+   Opt_userspace, Opt_deprecated,
+
+   Opt_err,
+};
+
+enum {
+   Opt_sec_none, Opt_sec_sys,
+   Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
+   Opt_sec_lkey, Opt_sec_lkeyi, Opt_sec_lkeyp,
+   Opt_sec_spkm, Opt_sec_spkmi, Opt_sec_spkmp,
+
+   Opt_sec_err,
+};
+
+static match_table_t nfs_sec_tokens = {
+   {Opt_sec_none, none},
+   {Opt_sec_none, null},
+   {Opt_sec_sys, sys},
+
+   {Opt_sec_krb5, krb5},
+   {Opt_sec_krb5i, krb5i},
+   {Opt_sec_krb5p, krb5p},
+
+   {Opt_sec_lkey, lkey},
+   {Opt_sec_lkeyi, lkeyi},
+   {Opt_sec_lkeyp, lkeyp},
+
+   {Opt_sec_err, NULL},
+};
+
+
 static void nfs_umount_begin(struct vfsmount *, int);
 static int  nfs_statfs(struct dentry *, struct kstatfs *);
 static int  nfs_show_options(struct seq_file *, struct vfsmount *);

-
To unsubscribe from this list: send the line unsubscribe linux-fsdevel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 00/13] Support NFS mount option parsing in the kernel

2007-05-21 Thread Chuck Lever
This patch series introduces support for parsing NFS mount options in the
kernel, similar to support that exists for many other Linux file systems such
as ext3, autofs, fat, cifs, hfs, and ocfs2.

I'd like to integrate this patch set into -mm to encourage wide review and
perhaps get some penetration testing before moving forward with integration
into the mainline kernel.

Future enhancements might include caching connections to mountd so we don't
use up so many privileged ports during mount storms, removing similar
infrastructure in NFSROOT in favor of this implementation, and support for NFS
over IPv6 and RDMA.

-- 
corporate:chuck dot lever at oracle dot com
-
To unsubscribe from this list: send the line unsubscribe linux-fsdevel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 12/13] NFS: More nfs4 in-kernel mount option parsing infrastructure

2007-05-21 Thread Chuck Lever
Add function for switching between an nfs4_mount_data structure from user
space (the current nfs4 mount mechanism) and generating an nfs4_mount_data
structure from a text string containing nfs4 mount options.

Signed-off-by: Chuck Lever [EMAIL PROTECTED]
---

 fs/nfs/super.c |  123 
 1 files changed, 123 insertions(+), 0 deletions(-)

diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 8585fa5..e0acd08 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -1643,6 +1643,129 @@ static void *nfs_copy_user_string(char *dst, struct 
nfs_string *src, int maxlen)
return dst;
 }
 
+static int nfs4_validate_mount_data(struct nfs4_mount_data **options,
+   const char *dev_name,
+   struct sockaddr_in *addr,
+   rpc_authflavor_t *authflavour,
+   char **hostname,
+   char **mntpath,
+   char *ip_addr)
+{
+   struct nfs4_mount_data *data = *options;
+   char *c;
+   unsigned len;
+
+   if (data == NULL) {
+   dprintk(%s: missing data argument\n, __FUNCTION__);
+   return -EINVAL;
+   }
+
+   switch (data-version) {
+   case 1:
+   if (data-host_addrlen != sizeof(*addr))
+   return -EINVAL;
+   if (copy_from_user(addr, data-host_addr, sizeof(*addr)))
+   return -EFAULT;
+   if (addr-sin_port == 0)
+   addr-sin_port = htons(NFS_PORT);
+   if (!nfs_verify_server_address((struct sockaddr *) addr,
+  data-host_addrlen))
+   return -EINVAL;
+
+   switch (data-auth_flavourlen) {
+   case 0:
+   *authflavour = RPC_AUTH_UNIX;
+   break;
+   case 1:
+   if (copy_from_user(authflavour, data-auth_flavours,
+  sizeof(*authflavour)))
+   return -EFAULT;
+   default:
+   goto out_inval_auth;
+   }
+
+   c = nfs_copy_user_string(ip_addr, data-client_addr, 80);
+   if (IS_ERR(c))
+   return PTR_ERR(c);
+
+   c = nfs_copy_user_string(NULL, data-hostname, 256);
+   if (IS_ERR(c))
+   return PTR_ERR(c);
+   *hostname = c;
+
+   c = nfs_copy_user_string(NULL, data-mnt_path, 1024);
+   if (IS_ERR(c)) {
+   kfree(*hostname);
+   return PTR_ERR(c);
+   }
+   *mntpath = c;
+   dprintk(MNTPATH: %s\n, *mntpath);
+
+   return 0;
+   default:
+   data = nfs4_convert_mount_opts((char *) data);
+   if (IS_ERR(data))
+   return PTR_ERR(data);
+   *options = data;
+
+   memcpy(addr, data-host_addr, sizeof(*addr));
+   if (!nfs_verify_server_address((struct sockaddr *) addr,
+   data-host_addrlen))
+   return -EINVAL;
+
+   switch (data-auth_flavourlen) {
+   case 0:
+   *authflavour = RPC_AUTH_UNIX;
+   break;
+   case 1:
+   *authflavour = (rpc_authflavor_t) 
data-auth_flavours[0];
+   break;
+   default:
+   goto out_inval_auth;
+   }
+
+   memset(ip_addr, '\0', data-client_addr.len + 1);
+   strncpy(ip_addr, data-client_addr.data, data-client_addr.len);
+
+   /*
+* Split dev_name into hostname:mntpath.
+*/
+   c = strchr(dev_name, ':');
+   if (c == NULL)
+   return -EINVAL;
+   /* while calculating len, pretend ':' is '\0' */
+   len = c - dev_name;
+   if (len  256)
+   return -EINVAL;
+   *hostname = kzalloc(len, GFP_KERNEL);
+   if (*hostname == NULL)
+   return -ENOMEM;
+   strncpy(*hostname, dev_name, len - 1);
+
+   c++;/* step over the ':' */
+   len = strlen(c);
+   if (len  1023) {
+   kfree(*hostname);
+   return -EINVAL;
+   }
+   *mntpath = kzalloc(len + 1, GFP_KERNEL);
+   if (*mntpath == NULL) {
+   kfree(*hostname);
+   return -ENOMEM;
+   }
+   strncpy(*mntpath, c, len);
+
+   dprintk(MNTPATH: %s\n, *mntpath);
+
+

[PATCH 02/13] SUNRPC: Rename rpcb_getport_external routine

2007-05-21 Thread Chuck Lever
In preparation for handling NFS mount option parsing in the kernel,
rename rpcb_getport_external as rpcb_get_port_sync, and make it available
always (instead of only when CONFIG_ROOT_NFS is enabled).

Signed-off-by: Chuck Lever [EMAIL PROTECTED]
---

 fs/nfs/nfsroot.c|2 +-
 include/linux/sunrpc/clnt.h |7 ++-
 net/sunrpc/rpcb_clnt.c  |   21 +++--
 3 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index 49d1008..f0db470 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -428,7 +428,7 @@ static int __init root_nfs_getport(int program, int 
version, int proto)
printk(KERN_NOTICE Looking up port of RPC %d/%d on %u.%u.%u.%u\n,
program, version, NIPQUAD(servaddr));
set_sockaddr(sin, servaddr, 0);
-   return rpcb_getport_external(sin, program, version, proto);
+   return rpcb_getport_sync(sin, program, version, proto);
 }
 
 
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 6661142..c51bc8c 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -122,8 +122,10 @@ struct rpc_clnt *rpc_clone_client(struct rpc_clnt *);
 intrpc_shutdown_client(struct rpc_clnt *);
 intrpc_destroy_client(struct rpc_clnt *);
 void   rpc_release_client(struct rpc_clnt *);
+
 intrpcb_register(u32, u32, int, unsigned short, int *);
 void   rpcb_getport(struct rpc_task *);
+intrpcb_getport_sync(struct sockaddr_in *, __u32, __u32, int);
 
 void   rpc_call_setup(struct rpc_task *, struct rpc_message *, int);
 
@@ -142,10 +144,5 @@ intrpc_ping(struct rpc_clnt *clnt, int 
flags);
 size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t);
 char * rpc_peeraddr2str(struct rpc_clnt *, enum rpc_display_format_t);
 
-/*
- * Helper function for NFSroot support
- */
-intrpcb_getport_external(struct sockaddr_in *, __u32, __u32, int);
-
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SUNRPC_CLNT_H */
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 6c7aa8a..5a52604 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -12,6 +12,8 @@
  *  Copyright (C) 1996, Olaf Kirch [EMAIL PROTECTED]
  */
 
+#include linux/module.h
+
 #include linux/types.h
 #include linux/socket.h
 #include linux/kernel.h
@@ -246,21 +248,20 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned 
short port, int *okay)
return error;
 }
 
-#ifdef CONFIG_ROOT_NFS
 /**
- * rpcb_getport_external - obtain the port for an RPC service on a given host
+ * rpcb_getport_sync - obtain the port for an RPC service on a given host
  * @sin: address of remote peer
  * @prog: RPC program number to bind
  * @vers: RPC version number to bind
  * @prot: transport protocol to use to make this request
  *
  * Called from outside the RPC client in a synchronous task context.
+ * Uses default timeout parameters specified by underlying transport.
  *
- * For now, this supports only version 2 queries, but is used only by
- * mount_clnt for NFS_ROOT.
+ * XXX: Needs to support IPv6, and rpcbind versions 3 and 4
  */
-int rpcb_getport_external(struct sockaddr_in *sin, __u32 prog,
-   __u32 vers, int prot)
+int rpcb_getport_sync(struct sockaddr_in *sin, __u32 prog,
+ __u32 vers, int prot)
 {
struct rpcbind_args map = {
.r_prog = prog,
@@ -277,10 +278,10 @@ int rpcb_getport_external(struct sockaddr_in *sin, __u32 
prog,
char hostname[40];
int status;
 
-   dprintk(RPC:   rpcb_getport_external(%u.%u.%u.%u, %u, %u, %d)\n,
-   NIPQUAD(sin-sin_addr.s_addr), prog, vers, prot);
+   dprintk(RPC:   %s( NIPQUAD_FMT , %u, %u, %d)\n,
+   __FUNCTION__, NIPQUAD(sin-sin_addr.s_addr), prog, vers, prot);
 
-   sprintf(hostname, %u.%u.%u.%u, NIPQUAD(sin-sin_addr.s_addr));
+   sprintf(hostname, NIPQUAD_FMT, NIPQUAD(sin-sin_addr.s_addr));
rpcb_clnt = rpcb_create(hostname, (struct sockaddr *)sin, prot, 2, 0);
if (IS_ERR(rpcb_clnt))
return PTR_ERR(rpcb_clnt);
@@ -294,7 +295,7 @@ int rpcb_getport_external(struct sockaddr_in *sin, __u32 
prog,
}
return status;
 }
-#endif
+EXPORT_SYMBOL_GPL(rpcb_getport_sync);
 
 /**
  * rpcb_getport - obtain the port for a given RPC service on a given host

-
To unsubscribe from this list: send the line unsubscribe linux-fsdevel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 11/13] NFS: Move nfs_copy_user_string

2007-05-21 Thread Chuck Lever
Next patch will add a new function that calls nfs_copy_user_string.

Signed-off-by: Chuck Lever [EMAIL PROTECTED]
---

 fs/nfs/super.c |   42 +-
 1 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 927c1c2..8585fa5 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -1622,6 +1622,27 @@ out_err:
return ERR_PTR(-EINVAL);
 }
 
+static void *nfs_copy_user_string(char *dst, struct nfs_string *src, int 
maxlen)
+{
+   void *p = NULL;
+
+   if (!src-len)
+   return ERR_PTR(-EINVAL);
+   if (src-len  maxlen)
+   maxlen = src-len;
+   if (dst == NULL) {
+   p = dst = kmalloc(maxlen + 1, GFP_KERNEL);
+   if (p == NULL)
+   return ERR_PTR(-ENOMEM);
+   }
+   if (copy_from_user(dst, src-data, maxlen)) {
+   kfree(p);
+   return ERR_PTR(-EFAULT);
+   }
+   dst[maxlen] = '\0';
+   return dst;
+}
+
 /*
  * Finish setting up a cloned NFS4 superblock
  */
@@ -1646,27 +1667,6 @@ static void nfs4_fill_super(struct super_block *sb)
nfs_initialise_sb(sb);
 }
 
-static void *nfs_copy_user_string(char *dst, struct nfs_string *src, int 
maxlen)
-{
-   void *p = NULL;
-
-   if (!src-len)
-   return ERR_PTR(-EINVAL);
-   if (src-len  maxlen)
-   maxlen = src-len;
-   if (dst == NULL) {
-   p = dst = kmalloc(maxlen + 1, GFP_KERNEL);
-   if (p == NULL)
-   return ERR_PTR(-ENOMEM);
-   }
-   if (copy_from_user(dst, src-data, maxlen)) {
-   kfree(p);
-   return ERR_PTR(-EFAULT);
-   }
-   dst[maxlen] = '\0';
-   return dst;
-}
-
 /*
  * Get the superblock for an NFS4 mountpoint
  */

-
To unsubscribe from this list: send the line unsubscribe linux-fsdevel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 13/13] NFS: Integrate support for processing nfs4 mount options in fs/nfs/super.c

2007-05-21 Thread Andrew Morton
On Mon, 21 May 2007 12:10:25 -0400
Chuck Lever [EMAIL PROTECTED] wrote:

 Finally, hook in the new mount option parsing logic.

I fixed up a huge reject which this spat against Trond's devel tree.
Please check that the end result still works as intended.
-
To unsubscribe from this list: send the line unsubscribe linux-fsdevel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] eCryptfs: Delay writing 0's after llseek until write

2007-05-21 Thread Michael Halcrow
Delay writing 0's out in eCryptfs after a seek past the end of the
file until data is actually written.

Signed-off-by: Michael Halcrow [EMAIL PROTECTED]

diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 9881b5c..59288d8 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -33,63 +33,6 @@
 #include ecryptfs_kernel.h
 
 /**
- * ecryptfs_llseek
- * @file: File we are seeking in
- * @offset: The offset to seek to
- * @origin: 2 - offset from i_size; 1 - offset from f_pos
- *
- * Returns the position we have seeked to, or negative on error
- */
-static loff_t ecryptfs_llseek(struct file *file, loff_t offset, int origin)
-{
-   loff_t rv;
-   loff_t new_end_pos;
-   int rc;
-   int expanding_file = 0;
-   struct inode *inode = file-f_mapping-host;
-
-   /* If our offset is past the end of our file, we're going to
-* need to grow it so we have a valid length of 0's */
-   new_end_pos = offset;
-   switch (origin) {
-   case 2:
-   new_end_pos += i_size_read(inode);
-   expanding_file = 1;
-   break;
-   case 1:
-   new_end_pos += file-f_pos;
-   if (new_end_pos  i_size_read(inode)) {
-   ecryptfs_printk(KERN_DEBUG, new_end_pos(=[0x%.16x]) 
-i_size_read(inode)(=[0x%.16x])\n,
-   new_end_pos, i_size_read(inode));
-   expanding_file = 1;
-   }
-   break;
-   default:
-   if (new_end_pos  i_size_read(inode)) {
-   ecryptfs_printk(KERN_DEBUG, new_end_pos(=[0x%.16x]) 
-i_size_read(inode)(=[0x%.16x])\n,
-   new_end_pos, i_size_read(inode));
-   expanding_file = 1;
-   }
-   }
-   ecryptfs_printk(KERN_DEBUG, new_end_pos = [0x%.16x]\n, new_end_pos);
-   if (expanding_file) {
-   rc = ecryptfs_truncate(file-f_path.dentry, new_end_pos);
-   if (rc) {
-   rv = rc;
-   ecryptfs_printk(KERN_ERR, Error on attempt to 
-   truncate to (higher) offset [0x%.16x];
-rc = [%d]\n, new_end_pos, rc);
-   goto out;
-   }
-   }
-   rv = generic_file_llseek(file, offset, origin);
-out:
-   return rv;
-}
-
-/**
  * ecryptfs_read_update_atime
  *
  * generic_file_read updates the atime of upper layer inode.  But, it
@@ -425,7 +368,7 @@ const struct file_operations ecryptfs_dir_fops = {
 };
 
 const struct file_operations ecryptfs_main_fops = {
-   .llseek = ecryptfs_llseek,
+   .llseek = generic_file_llseek,
.read = do_sync_read,
.aio_read = ecryptfs_read_update_atime,
.write = do_sync_write,
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 88ea669..55cec98 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -376,9 +376,31 @@ out:
return 0;
 }
 
+/**
+ * eCryptfs does not currently support holes. When writing after a
+ * seek past the end of the file, eCryptfs fills in 0's through to the
+ * current location. The code to fill in the 0's to all the
+ * intermediate pages calls ecryptfs_prepare_write_no_truncate().
+ */
+static int
+ecryptfs_prepare_write_no_truncate(struct file *file, struct page *page,
+  unsigned from, unsigned to)
+{
+   int rc = 0;
+
+   if (from == 0  to == PAGE_CACHE_SIZE)
+   goto out;   /* If we are writing a full page, it will be
+  up to date. */
+   if (!PageUptodate(page))
+   rc = ecryptfs_do_readpage(file, page, page-index);
+out:
+   return rc;
+}
+
 static int ecryptfs_prepare_write(struct file *file, struct page *page,
  unsigned from, unsigned to)
 {
+   loff_t pos;
int rc = 0;
 
if (from == 0  to == PAGE_CACHE_SIZE)
@@ -386,6 +408,16 @@ static int ecryptfs_prepare_write(struct file *file, 
struct page *page,
   up to date. */
if (!PageUptodate(page))
rc = ecryptfs_do_readpage(file, page, page-index);
+   pos = ((loff_t)page-index  PAGE_CACHE_SHIFT) + to;
+   if (pos  i_size_read(page-mapping-host)) {
+   rc = ecryptfs_truncate(file-f_path.dentry, pos);
+   if (rc) {
+   printk(KERN_ERR Error on attempt to 
+  truncate to (higher) offset [%lld];
+   rc = [%d]\n, pos, rc);
+   goto out;
+   }
+   }
 out:
return rc;
 }
@@ -744,10 +776,10 @@ int write_zeros(struct file *file, pgoff_t index, int 
start, int num_zeros)
rc = PTR_ERR(tmp_page);
goto out;
}
-   

Re: [RFC][PATCH 10/14] In-kernel file copy between union mounted filesystems

2007-05-21 Thread Bharata B Rao
On Fri, May 18, 2007 at 09:47:31AM -0400, Shaya Potter wrote:
 Bharata B Rao wrote:
 
 
 Not really. This is called during copyup of a file residing in a lower
 layer. And that is done only for regular files.
 
 That is broken.

But it only breaks the semantics (in other cases we allow writes only to the
top layer files). So the question is why do we have to copy up the device
node ? What difference it makes to writing to the device itself ? Currently
we allow write to the device using the lower layer device node itself.

 
 You should be able to change the permissions on a device node on a layer 
 that is RO.
 

Hmm not sure why we need to touch the permissions of the device. See below.

 so it would copy it up (1. mknod, 2. copy attributes) and then the 
 appropriate attribute notification change would be called.

With union mount, when a regular file is opened for write, it is checked
if it resides in the lower layer and if so copied up to the topmost layer
and this new fd is returned from open. And any subsequent writes using this
fd will go to the newly created topmost file. (We are aware that we are not
yet copying the (extended) attributes to the newly created topmost file,
which we have to do).

Regards,
Bharata.
-
To unsubscribe from this list: send the line unsubscribe linux-fsdevel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] eCryptfs: Delay writing 0's after llseek until write

2007-05-21 Thread Andrew Morton
On Mon, 21 May 2007 18:00:21 -0500 Michael Halcrow [EMAIL PROTECTED] wrote:

 Delay writing 0's out in eCryptfs after a seek past the end of the
 file until data is actually written.

a) why?

b) what is the impact upon a user of them not having this patch?
-
To unsubscribe from this list: send the line unsubscribe linux-fsdevel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html