[PATCH 13/13] NFS: Integrate support for processing nfs4 mount options in fs/nfs/super.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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