* [PATCH 0/9] nfs3 support @ 2014-02-06 16:40 Uwe Kleine-König 2014-02-06 16:40 ` [PATCH 1/9] net: net_read_uint32: assert that only 32 bit are read Uwe Kleine-König ` (8 more replies) 0 siblings, 9 replies; 20+ messages in thread From: Uwe Kleine-König @ 2014-02-06 16:40 UTC (permalink / raw) To: barebox Hello, this series switches barebox from using nfs2 to nfs3. The added benefit (apart from nfs3 being newer and probably better tested on the server side) is that it now also works with unfs3 implementing the server side. The first two patches are fixes, up to you if you want to apply them before 2014.03.0. Uwe Kleine-König (9): net: net_read_uint32: assert that only 32 bit are read nfs: skip over stale rpc packets nfs: shorten and simplify rpc_add_credentials a bit nfs: simplify rpc_lookup_req nfs: drop an unneeded variable from nfs_do_open() net: new function net_read_uint64 mount: support filesystem options passed via -o nfs: switch to nfs3 nfs: parse nfsport and mount port from file system options arch/arm/boards/raspberry-pi/rpi.c | 2 +- arch/arm/mach-omap/omap_generic.c | 2 +- arch/arm/mach-omap/xload.c | 4 +- arch/arm/mach-socfpga/generic.c | 2 +- commands/mount.c | 19 +- commands/tftp.c | 2 +- common/blspec.c | 2 +- common/startup.c | 4 +- fs/fs.c | 19 +- fs/nfs.c | 970 +++++++++++++++++++++++++------------ include/fs.h | 6 +- include/net.h | 15 +- lib/bootstrap/disk.c | 2 +- 13 files changed, 721 insertions(+), 328 deletions(-) -- 1.8.5.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 1/9] net: net_read_uint32: assert that only 32 bit are read 2014-02-06 16:40 [PATCH 0/9] nfs3 support Uwe Kleine-König @ 2014-02-06 16:40 ` Uwe Kleine-König 2014-02-06 16:40 ` [PATCH 2/9] nfs: skip over stale rpc packets Uwe Kleine-König ` (7 subsequent siblings) 8 siblings, 0 replies; 20+ messages in thread From: Uwe Kleine-König @ 2014-02-06 16:40 UTC (permalink / raw) To: barebox On some architectures (e.g. alpha, amd64, arm64, ia64, s390x, mips64) sizeof(ulong) is 8 which made net_read_uint32 actually read too much and even returned the wrong value on big endian machines. (Note the second issue isn't that critical though, because the only architecture from the list above that uses big endian byte order is s390x ...) Also change the argument to void * because the pointer is not necessarily properly aligned. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> --- include/net.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/net.h b/include/net.h index a4cfec712374..8388e2f12ebe 100644 --- a/include/net.h +++ b/include/net.h @@ -269,11 +269,11 @@ static inline IPaddr_t net_read_ip(void *from) } /* return uint32 *in network byteorder* */ -static inline uint32_t net_read_uint32(uint32_t *from) +static inline uint32_t net_read_uint32(void *from) { - ulong l; - memcpy((void*)&l, (void*)from, sizeof(l)); - return l; + uint32_t tmp; + memcpy(&tmp, from, sizeof(tmp)); + return tmp; } /* write IP *in network byteorder* */ -- 1.8.5.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 2/9] nfs: skip over stale rpc packets 2014-02-06 16:40 [PATCH 0/9] nfs3 support Uwe Kleine-König 2014-02-06 16:40 ` [PATCH 1/9] net: net_read_uint32: assert that only 32 bit are read Uwe Kleine-König @ 2014-02-06 16:40 ` Uwe Kleine-König 2014-02-07 8:20 ` Uwe Kleine-König 2014-02-06 16:40 ` [PATCH 3/9] nfs: shorten and simplify rpc_add_credentials a bit Uwe Kleine-König ` (6 subsequent siblings) 8 siblings, 1 reply; 20+ messages in thread From: Uwe Kleine-König @ 2014-02-06 16:40 UTC (permalink / raw) To: barebox When a former transaction was aborted by hitting Ctrl-C the old reply might still hang in the ethernet controller making all further transactions fail. So just skip over old replies. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> --- An alternative would be to drain the ethernet queue before a new request is sent. Don't know how that works and I don't see much benefit, so I didn't try to find out :-) --- fs/nfs.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/nfs.c b/fs/nfs.c index 717326435189..e9a6eede06bd 100644 --- a/fs/nfs.c +++ b/fs/nfs.c @@ -275,8 +275,13 @@ static int rpc_check_reply(unsigned char *pkt, int rpc_prog, unsigned long rpc_i memcpy(&rpc, pkt, sizeof(rpc)); - if (ntohl(rpc.id) != rpc_id) + if (ntohl(rpc.id) != rpc_id) { + if (ntohl(rpc.id) < rpc_id) + /* stale packet, wait a bit longer */ + return 0; + return -EINVAL; + } if (rpc.rstatus || rpc.verifier || -- 1.8.5.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 2/9] nfs: skip over stale rpc packets 2014-02-06 16:40 ` [PATCH 2/9] nfs: skip over stale rpc packets Uwe Kleine-König @ 2014-02-07 8:20 ` Uwe Kleine-König 0 siblings, 0 replies; 20+ messages in thread From: Uwe Kleine-König @ 2014-02-07 8:20 UTC (permalink / raw) To: barebox Hello, On Thu, Feb 06, 2014 at 05:40:47PM +0100, Uwe Kleine-König wrote: > When a former transaction was aborted by hitting Ctrl-C the old reply might > still hang in the ethernet controller making all further transactions fail. > > So just skip over old replies. > > Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> > --- > An alternative would be to drain the ethernet queue before a new request is > sent. Don't know how that works and I don't see much benefit, so I didn't > try to find out :-) > --- > fs/nfs.c | 7 ++++++- > 1 file changed, 6 insertions(+), 1 deletion(-) > > diff --git a/fs/nfs.c b/fs/nfs.c > index 717326435189..e9a6eede06bd 100644 > --- a/fs/nfs.c > +++ b/fs/nfs.c > @@ -275,8 +275,13 @@ static int rpc_check_reply(unsigned char *pkt, int rpc_prog, unsigned long rpc_i > > memcpy(&rpc, pkt, sizeof(rpc)); > > - if (ntohl(rpc.id) != rpc_id) > + if (ntohl(rpc.id) != rpc_id) { > + if (ntohl(rpc.id) < rpc_id) > + /* stale packet, wait a bit longer */ > + return 0; > + > return -EINVAL; > + } I have thought about this once more. Just compare using < is very lax and fails when rpc_id overflows. I suggest to use if (rpc_id - ntohl(rpc.id) == 1) instead. (Or draining the eth queue.) Will fix accordingly in a v2 once I addressed all concerns. Uwe -- Pengutronix e.K. | Uwe Kleine-König | Industrial Linux Solutions | http://www.pengutronix.de/ | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 3/9] nfs: shorten and simplify rpc_add_credentials a bit 2014-02-06 16:40 [PATCH 0/9] nfs3 support Uwe Kleine-König 2014-02-06 16:40 ` [PATCH 1/9] net: net_read_uint32: assert that only 32 bit are read Uwe Kleine-König 2014-02-06 16:40 ` [PATCH 2/9] nfs: skip over stale rpc packets Uwe Kleine-König @ 2014-02-06 16:40 ` Uwe Kleine-König 2014-02-06 16:40 ` [PATCH 4/9] nfs: simplify rpc_lookup_req Uwe Kleine-König ` (5 subsequent siblings) 8 siblings, 0 replies; 20+ messages in thread From: Uwe Kleine-König @ 2014-02-06 16:40 UTC (permalink / raw) To: barebox Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> --- fs/nfs.c | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/fs/nfs.c b/fs/nfs.c index e9a6eede06bd..a6a47f22934c 100644 --- a/fs/nfs.c +++ b/fs/nfs.c @@ -224,34 +224,18 @@ out_overflow: */ static uint32_t *rpc_add_credentials(uint32_t *p) { - int hl; - int hostnamelen = 0; - /* - * Here's the executive summary on authentication requirements of the - * various NFS server implementations: Linux accepts both AUTH_NONE - * and AUTH_UNIX authentication (also accepts an empty hostname field - * in the AUTH_UNIX scheme). *BSD refuses AUTH_NONE, but accepts - * AUTH_UNIX (also accepts an empty hostname field in the AUTH_UNIX - * scheme). To be safe, use AUTH_UNIX and pass the hostname if we have - * it (if the BOOTP/DHCP reply didn't give one, just use an empty - * hostname). + * *BSD refuses AUTH_NONE, so use AUTH_UNIX. An empty hostname is OK for + * both Linux and *BSD. */ - hl = (hostnamelen + 3) & ~3; - /* Provide an AUTH_UNIX credential. */ *p++ = htonl(1); /* AUTH_UNIX */ - *p++ = htonl(hl + 20); /* auth length */ + *p++ = htonl(20); /* auth length: 20 + strlen(hostname) */ *p++ = htonl(0); /* stamp */ - *p++ = htonl(hostnamelen); /* hostname string */ - - if (hostnamelen & 3) - *(p + hostnamelen / 4) = 0; /* add zero padding */ - - /* memcpy(p, hostname, hostnamelen); */ /* empty hostname */ + *p++ = htonl(0); /* hostname string length */ + /* memcpy(p, "", 0); p += 0; <- empty host name */ - p += hl / 4; *p++ = 0; /* uid */ *p++ = 0; /* gid */ *p++ = 0; /* auxiliary gid list */ -- 1.8.5.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 4/9] nfs: simplify rpc_lookup_req 2014-02-06 16:40 [PATCH 0/9] nfs3 support Uwe Kleine-König ` (2 preceding siblings ...) 2014-02-06 16:40 ` [PATCH 3/9] nfs: shorten and simplify rpc_add_credentials a bit Uwe Kleine-König @ 2014-02-06 16:40 ` Uwe Kleine-König 2014-02-06 16:40 ` [PATCH 5/9] nfs: drop an unneeded variable from nfs_do_open() Uwe Kleine-König ` (4 subsequent siblings) 8 siblings, 0 replies; 20+ messages in thread From: Uwe Kleine-König @ 2014-02-06 16:40 UTC (permalink / raw) To: barebox Instead of letting rpc_lookup_req set mount_port and nfs_port, let it return the port found and let the caller use that information. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> --- fs/nfs.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/fs/nfs.c b/fs/nfs.c index a6a47f22934c..f1643feebbf9 100644 --- a/fs/nfs.c +++ b/fs/nfs.c @@ -374,22 +374,8 @@ static int rpc_lookup_req(struct nfs_priv *npriv, int prog, int ver) if (ret) return ret; - port = net_read_uint32((uint32_t *)(nfs_packet + sizeof(struct rpc_reply))); - - switch (prog) { - case PROG_MOUNT: - npriv->mount_port = ntohl(port); - debug("mount port: %d\n", npriv->mount_port); - break; - case PROG_NFS: - npriv->nfs_port = ntohl(port); - debug("nfs port: %d\n", npriv->nfs_port); - break; - default: - return -EINVAL; - } - - return 0; + port = ntohl(net_read_uint32(nfs_packet + sizeof(struct rpc_reply))); + return port; } /* @@ -1000,16 +986,18 @@ static int nfs_probe(struct device_d *dev) net_udp_bind(npriv->con, 1000); ret = rpc_lookup_req(npriv, PROG_MOUNT, 1); - if (ret) { + if (ret < 0) { printf("lookup mount port failed with %d\n", ret); goto err2; } + npriv->mount_port = ret; ret = rpc_lookup_req(npriv, PROG_NFS, 2); - if (ret) { + if (ret < 0) { printf("lookup nfs port failed with %d\n", ret); goto err2; } + npriv->nfs_port = ret; ret = nfs_mount_req(npriv); if (ret) { -- 1.8.5.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 5/9] nfs: drop an unneeded variable from nfs_do_open() 2014-02-06 16:40 [PATCH 0/9] nfs3 support Uwe Kleine-König ` (3 preceding siblings ...) 2014-02-06 16:40 ` [PATCH 4/9] nfs: simplify rpc_lookup_req Uwe Kleine-König @ 2014-02-06 16:40 ` Uwe Kleine-König 2014-02-06 16:40 ` [PATCH 6/9] net: new function net_read_uint64 Uwe Kleine-König ` (3 subsequent siblings) 8 siblings, 0 replies; 20+ messages in thread From: Uwe Kleine-König @ 2014-02-06 16:40 UTC (permalink / raw) To: barebox While at it also fix the type of flen holding a string length (int -> size_t). Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> --- fs/nfs.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/fs/nfs.c b/fs/nfs.c index f1643feebbf9..373159d6ffb7 100644 --- a/fs/nfs.c +++ b/fs/nfs.c @@ -616,7 +616,7 @@ static struct file_priv *nfs_do_open(struct device_d *dev, const char *filename) struct file_priv *priv; struct nfs_priv *npriv = dev->priv; int ret; - const char *fname, *tok; + const char *tok; priv = xzalloc(sizeof(*priv)); @@ -629,25 +629,23 @@ static struct file_priv *nfs_do_open(struct device_d *dev, const char *filename) filename++; - fname = filename; - memcpy(priv->filefh, npriv->rootfh, NFS_FHSIZE); - while (*fname) { - int flen; + while (*filename) { + size_t flen; - tok = strchr(fname, '/'); + tok = strchr(filename, '/'); if (tok) - flen = tok - fname; + flen = tok - filename; else - flen = strlen(fname); + flen = strlen(filename); - ret = nfs_lookup_req(priv, fname, flen); + ret = nfs_lookup_req(priv, filename, flen); if (ret) goto out; if (tok) - fname += flen + 1; + filename += flen + 1; else break; } -- 1.8.5.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 6/9] net: new function net_read_uint64 2014-02-06 16:40 [PATCH 0/9] nfs3 support Uwe Kleine-König ` (4 preceding siblings ...) 2014-02-06 16:40 ` [PATCH 5/9] nfs: drop an unneeded variable from nfs_do_open() Uwe Kleine-König @ 2014-02-06 16:40 ` Uwe Kleine-König 2014-02-07 8:17 ` Uwe Kleine-König 2014-02-06 16:40 ` [PATCH 7/9] mount: support filesystem options passed via -o Uwe Kleine-König ` (2 subsequent siblings) 8 siblings, 1 reply; 20+ messages in thread From: Uwe Kleine-König @ 2014-02-06 16:40 UTC (permalink / raw) To: barebox; +Cc: Uwe Kleine-König From: Uwe Kleine-König <uwe@kleine-koenig.org> This is needed for nfs3 support as some types became bigger compared to nfs2. Signed-off-by: Uwe Kleine-König <uwe@kleine-koenig.org> --- include/net.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/net.h b/include/net.h index 8388e2f12ebe..6c86947d9ca3 100644 --- a/include/net.h +++ b/include/net.h @@ -276,6 +276,13 @@ static inline uint32_t net_read_uint32(void *from) return tmp; } +static inline uint64_t net_read_uint64(void *from) +{ + uint64_t tmp; + memcpy(&tmp, from, sizeof(tmp)); + return tmp; +} + /* write IP *in network byteorder* */ static inline void net_write_ip(void *to, IPaddr_t ip) { -- 1.8.5.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 6/9] net: new function net_read_uint64 2014-02-06 16:40 ` [PATCH 6/9] net: new function net_read_uint64 Uwe Kleine-König @ 2014-02-07 8:17 ` Uwe Kleine-König 0 siblings, 0 replies; 20+ messages in thread From: Uwe Kleine-König @ 2014-02-07 8:17 UTC (permalink / raw) To: barebox; +Cc: Uwe Kleine-König On Thu, Feb 06, 2014 at 05:40:51PM +0100, Uwe Kleine-König wrote: > From: Uwe Kleine-König <uwe@kleine-koenig.org> This was added by mistake. Sascha, can you please drop it and use my pengutronix.de address instead. Ditto for the S-o-b line and patch 7 in this series. Thanks Uwe > This is needed for nfs3 support as some types became bigger compared to > nfs2. > > Signed-off-by: Uwe Kleine-König <uwe@kleine-koenig.org> > --- > include/net.h | 7 +++++++ > 1 file changed, 7 insertions(+) > > diff --git a/include/net.h b/include/net.h > index 8388e2f12ebe..6c86947d9ca3 100644 > --- a/include/net.h > +++ b/include/net.h > @@ -276,6 +276,13 @@ static inline uint32_t net_read_uint32(void *from) > return tmp; > } > > +static inline uint64_t net_read_uint64(void *from) > +{ > + uint64_t tmp; > + memcpy(&tmp, from, sizeof(tmp)); > + return tmp; > +} > + > /* write IP *in network byteorder* */ > static inline void net_write_ip(void *to, IPaddr_t ip) > { > -- > 1.8.5.2 > > > _______________________________________________ > barebox mailing list > barebox@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/barebox -- Pengutronix e.K. | Uwe Kleine-König | Industrial Linux Solutions | http://www.pengutronix.de/ | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 7/9] mount: support filesystem options passed via -o 2014-02-06 16:40 [PATCH 0/9] nfs3 support Uwe Kleine-König ` (5 preceding siblings ...) 2014-02-06 16:40 ` [PATCH 6/9] net: new function net_read_uint64 Uwe Kleine-König @ 2014-02-06 16:40 ` Uwe Kleine-König 2014-02-06 16:40 ` [PATCH 8/9] nfs: switch to nfs3 Uwe Kleine-König 2014-02-06 16:40 ` [PATCH 9/9] nfs: parse nfsport and mount port from file system options Uwe Kleine-König 8 siblings, 0 replies; 20+ messages in thread From: Uwe Kleine-König @ 2014-02-06 16:40 UTC (permalink / raw) To: barebox; +Cc: Uwe Kleine-König From: Uwe Kleine-König <uwe@kleine-koenig.org> Similar to mount(8) the barebox command mount now supports passing a string to the file system driver via -o. This is used in on of the next commits to let the user specify port numbers for nfs mounts. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> --- arch/arm/boards/raspberry-pi/rpi.c | 2 +- arch/arm/mach-omap/omap_generic.c | 2 +- arch/arm/mach-omap/xload.c | 4 ++-- arch/arm/mach-socfpga/generic.c | 2 +- commands/mount.c | 19 ++++++++++++------- commands/tftp.c | 2 +- common/blspec.c | 2 +- common/startup.c | 4 ++-- fs/fs.c | 19 +++++++++++++------ include/fs.h | 6 ++++-- lib/bootstrap/disk.c | 2 +- 11 files changed, 39 insertions(+), 25 deletions(-) diff --git a/arch/arm/boards/raspberry-pi/rpi.c b/arch/arm/boards/raspberry-pi/rpi.c index 0997124c01ec..03a16d75619d 100644 --- a/arch/arm/boards/raspberry-pi/rpi.c +++ b/arch/arm/boards/raspberry-pi/rpi.c @@ -126,7 +126,7 @@ static int rpi_env_init(void) } mkdir("/boot", 0666); - ret = mount(diskdev, "fat", "/boot"); + ret = mount(diskdev, "fat", "/boot", NULL); if (ret) { printf("failed to mount %s\n", diskdev); return 0; diff --git a/arch/arm/mach-omap/omap_generic.c b/arch/arm/mach-omap/omap_generic.c index bedb4d8d2618..060c59277f4e 100644 --- a/arch/arm/mach-omap/omap_generic.c +++ b/arch/arm/mach-omap/omap_generic.c @@ -136,7 +136,7 @@ static int omap_env_init(void) } mkdir("/boot", 0666); - ret = mount(diskdev, "fat", "/boot"); + ret = mount(diskdev, "fat", "/boot", NULL); if (ret) { printf("failed to mount %s\n", diskdev); return 0; diff --git a/arch/arm/mach-omap/xload.c b/arch/arm/mach-omap/xload.c index 69e3e42df69d..a30945010990 100644 --- a/arch/arm/mach-omap/xload.c +++ b/arch/arm/mach-omap/xload.c @@ -110,7 +110,7 @@ static void *omap_xload_boot_mmc(void) partname = asprintf("%s.0", diskdev); - ret = mount(partname, "fat", "/"); + ret = mount(partname, "fat", "/", NULL); free(partname); @@ -170,7 +170,7 @@ static void *omap4_xload_boot_usb(void){ void *buf; int len; - ret = mount("omap4_usbboot", "omap4_usbbootfs", "/"); + ret = mount("omap4_usbboot", "omap4_usbbootfs", "/", NULL); if (ret) { printf("Unable to mount omap4_usbbootfs (%d)\n", ret); return NULL; diff --git a/arch/arm/mach-socfpga/generic.c b/arch/arm/mach-socfpga/generic.c index 0d958d23af60..62593549d6e4 100644 --- a/arch/arm/mach-socfpga/generic.c +++ b/arch/arm/mach-socfpga/generic.c @@ -97,7 +97,7 @@ static int socfpga_env_init(void) } mkdir("/boot", 0666); - ret = mount(partname, "fat", "/boot"); + ret = mount(partname, "fat", "/boot", NULL); if (ret) { printf("failed to mount %s\n", diskdev); goto out_free; diff --git a/commands/mount.c b/commands/mount.c index 2e9d4bef5e3f..691bc2911e8f 100644 --- a/commands/mount.c +++ b/commands/mount.c @@ -33,26 +33,31 @@ static int do_mount(int argc, char *argv[]) { int opt; int ret = 0, verbose = 0; - struct fs_device_d *fsdev; struct driver_d *drv; const char *type = NULL; const char *mountpoint, *dev; + const char *fsoptions = NULL; - while ((opt = getopt(argc, argv, "t:va")) > 0) { + while ((opt = getopt(argc, argv, "ao:t:v")) > 0) { switch (opt) { + case 'a': + mount_all(); + break; case 't': type = optarg; break; + case 'o': + fsoptions = optarg; + break; case 'v': verbose++; break; - case 'a': - mount_all(); - break; } } if (argc == optind) { + struct fs_device_d *fsdev; + for_each_fs_device(fsdev) { printf("%s on %s type %s\n", fsdev->backingstore ? fsdev->backingstore : "none", @@ -84,7 +89,7 @@ static int do_mount(int argc, char *argv[]) if (!cdev) return -ENOENT; - path = cdev_mount_default(cdev); + path = cdev_mount_default(cdev, fsoptions); if (IS_ERR(path)) return PTR_ERR(path); @@ -108,7 +113,7 @@ static int do_mount(int argc, char *argv[]) mountpoint = argv[optind + 1]; } - if ((ret = mount(dev, type, mountpoint))) { + if ((ret = mount(dev, type, mountpoint, fsoptions))) { perror("mount"); return 1; } diff --git a/commands/tftp.c b/commands/tftp.c index c83d1740e2f0..64cab2f0451d 100644 --- a/commands/tftp.c +++ b/commands/tftp.c @@ -72,7 +72,7 @@ static int do_tftpb(int argc, char *argv[]) goto err_free; ip = net_get_serverip(); - ret = mount(ip_to_string(ip), "tftp", TFTP_MOUNT_PATH); + ret = mount(ip_to_string(ip), "tftp", TFTP_MOUNT_PATH, NULL); if (ret) goto err_rmdir; diff --git a/common/blspec.c b/common/blspec.c index 2244d5a8a868..df3c9c3c65da 100644 --- a/common/blspec.c +++ b/common/blspec.c @@ -276,7 +276,7 @@ static int blspec_scan_cdev(struct blspec *blspec, struct cdev *cdev) if (type == filetype_mbr || type == filetype_gpt) return -EINVAL; - rootpath = cdev_mount_default(cdev); + rootpath = cdev_mount_default(cdev, NULL); if (IS_ERR(rootpath)) return PTR_ERR(rootpath); diff --git a/common/startup.c b/common/startup.c index e8b9ea0216fe..0b5fe46adb50 100644 --- a/common/startup.c +++ b/common/startup.c @@ -89,9 +89,9 @@ device_initcall(register_default_env); #if defined CONFIG_FS_RAMFS && defined CONFIG_FS_DEVFS static int mount_root(void) { - mount("none", "ramfs", "/"); + mount("none", "ramfs", "/", NULL); mkdir("/dev", 0); - mount("none", "devfs", "/dev"); + mount("none", "devfs", "/dev", NULL); return 0; } fs_initcall(mount_root); diff --git a/fs/fs.c b/fs/fs.c index 32dba8cf0abe..7a57bc0670bc 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -1242,6 +1242,7 @@ static void fs_remove(struct device_d *dev) } free(fsdev->path); + free(fsdev->options); if (fsdev == fs_dev_root) fs_dev_root = NULL; @@ -1316,13 +1317,18 @@ int fsdev_open_cdev(struct fs_device_d *fsdev) * We do this by registering a new device on which the filesystem * driver will match. */ -int mount(const char *device, const char *fsname, const char *_path) +int mount(const char *device, const char *fsname, const char *_path, + const char *fsoptions) { struct fs_device_d *fsdev; int ret; char *path = normalise_path(_path); - debug("mount: %s on %s type %s\n", device, path, fsname); + if (!fsoptions) + fsoptions = ""; + + debug("mount: %s on %s type %s, options=%s\n", + device, path, fsname, fsoptions); if (fs_dev_root) { fsdev = get_fsdevice_by_path(path); @@ -1354,6 +1360,7 @@ int mount(const char *device, const char *fsname, const char *_path) fsdev->dev.id = get_free_deviceid(fsdev->dev.name); fsdev->path = xstrdup(path); fsdev->dev.bus = &fs_bus; + fsdev->options = xstrdup(fsoptions); ret = register_device(&fsdev->dev); if (ret) @@ -1711,7 +1718,7 @@ const char *cdev_get_mount_path(struct cdev *cdev) * mount it to /mnt/<cdevname> and return the path. Returns an error pointer * on failure. */ -const char *cdev_mount_default(struct cdev *cdev) +const char *cdev_mount_default(struct cdev *cdev, const char *fsoptions) { const char *path; char *newpath, *devpath; @@ -1720,7 +1727,7 @@ const char *cdev_mount_default(struct cdev *cdev) /* * If this cdev is already mounted somewhere use this path * instead of mounting it again to avoid corruption on the - * filesystem. + * filesystem. Note this ignores eventual fsoptions though. */ path = cdev_get_mount_path(cdev); if (path) @@ -1731,7 +1738,7 @@ const char *cdev_mount_default(struct cdev *cdev) devpath = asprintf("/dev/%s", cdev->name); - ret = mount(devpath, NULL, newpath); + ret = mount(devpath, NULL, newpath, fsoptions); free(devpath); @@ -1761,6 +1768,6 @@ void mount_all(void) struct cdev *cdev = &bdev->cdev; list_for_each_entry(cdev, &bdev->dev->cdevs, devices_list) - cdev_mount_default(cdev); + cdev_mount_default(cdev, NULL); } } diff --git a/include/fs.h b/include/fs.h index 856e00abb043..073641c74746 100644 --- a/include/fs.h +++ b/include/fs.h @@ -99,6 +99,7 @@ struct fs_device_d { char *path; struct device_d *parent_device; struct list_head list; + char *options; }; #define drv_to_fs_driver(d) container_of(d, struct fs_driver_d, drv) @@ -140,7 +141,8 @@ int closedir(DIR *dir); int symlink(const char *pathname, const char *newpath); int readlink(const char *path, char *buf, size_t bufsiz); -int mount (const char *device, const char *fsname, const char *path); +int mount (const char *device, const char *fsname, const char *path, + const char *fsoptions); int umount(const char *pathname); /* not-so-standard functions */ @@ -197,7 +199,7 @@ int unlink_recursive(const char *path, char **failedpath); int fsdev_open_cdev(struct fs_device_d *fsdev); const char *cdev_get_mount_path(struct cdev *cdev); -const char *cdev_mount_default(struct cdev *cdev); +const char *cdev_mount_default(struct cdev *cdev, const char *fsoptions); void mount_all(void); #endif /* __FS_H */ diff --git a/lib/bootstrap/disk.c b/lib/bootstrap/disk.c index 879d3315e8e3..527e4308979c 100644 --- a/lib/bootstrap/disk.c +++ b/lib/bootstrap/disk.c @@ -20,7 +20,7 @@ void* bootstrap_read_disk(char *dev, char *fstype) int len; char *path = "/"; - ret = mount(dev, fstype, path); + ret = mount(dev, fstype, path, NULL); if (ret) { bootstrap_err("mounting %s failed with %d\n", dev, ret); return NULL; -- 1.8.5.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 8/9] nfs: switch to nfs3 2014-02-06 16:40 [PATCH 0/9] nfs3 support Uwe Kleine-König ` (6 preceding siblings ...) 2014-02-06 16:40 ` [PATCH 7/9] mount: support filesystem options passed via -o Uwe Kleine-König @ 2014-02-06 16:40 ` Uwe Kleine-König 2014-02-07 6:48 ` Jean-Christophe PLAGNIOL-VILLARD 2014-02-06 16:40 ` [PATCH 9/9] nfs: parse nfsport and mount port from file system options Uwe Kleine-König 8 siblings, 1 reply; 20+ messages in thread From: Uwe Kleine-König @ 2014-02-06 16:40 UTC (permalink / raw) To: barebox This was tested against nfs-kernel-server and unfs3. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> --- fs/nfs.c | 859 ++++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 608 insertions(+), 251 deletions(-) diff --git a/fs/nfs.c b/fs/nfs.c index 373159d6ffb7..8eec63078dd3 100644 --- a/fs/nfs.c +++ b/fs/nfs.c @@ -1,10 +1,12 @@ /* * nfs.c - barebox NFS driver * + * Copyright (c) 2014 Uwe Kleine-König, Pengutronix * Copyright (c) 2012 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix * Copyright (c) Masami Komiya <mkomiya@sonare.it> 2004 * - * Based on U-Boot NFS code which is based on NetBSD code + * Based on U-Boot NFS code which is based on NetBSD code with + * major changes to support nfs3. * * See file CREDITS for list of people who contributed to this * project. @@ -17,7 +19,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * */ #include <common.h> @@ -34,6 +35,9 @@ #include <kfifo.h> #include <sizes.h> +#define ntohll(val) __be64_to_cpu(val) +#define htonll(val) __cpu_to_be64(val) + #define SUNRPC_PORT 111 #define PROG_PORTMAP 100000 @@ -48,34 +52,54 @@ #define MOUNT_ADDENTRY 1 #define MOUNT_UMOUNT 3 -#define NFS_GETATTR 1 -#define NFS_LOOKUP 4 -#define NFS_READLINK 5 -#define NFS_READ 6 -#define NFS_READDIR 16 - -#define NFS_FHSIZE 32 - -enum nfs_stat { - NFS_OK = 0, - NFSERR_PERM = 1, - NFSERR_NOENT = 2, - NFSERR_IO = 5, - NFSERR_NXIO = 6, - NFSERR_ACCES = 13, - NFSERR_EXIST = 17, - NFSERR_NODEV = 19, - NFSERR_NOTDIR = 20, - NFSERR_ISDIR = 21, - NFSERR_FBIG = 27, - NFSERR_NOSPC = 28, - NFSERR_ROFS = 30, - NFSERR_NAMETOOLONG=63, - NFSERR_NOTEMPTY = 66, - NFSERR_DQUOT = 69, - NFSERR_STALE = 70, - NFSERR_WFLUSH = 99, -}; +#define NFSPROC3_GETATTR 1 +#define NFSPROC3_LOOKUP 3 +#define NFSPROC3_READLINK 5 +#define NFSPROC3_READ 6 +#define NFSPROC3_READDIR 16 + +#define NFS3_FHSIZE 64 +#define NFS3_COOKIEVERFSIZE 8 + +/* values of enum ftype3 */ +#define NF3REG 1 +#define NF3DIR 2 +#define NF3BLK 3 +#define NF3CHR 4 +#define NF3LNK 5 +#define NF3SOCK 6 +#define NF3FIFO 7 + +/* values for enum nfsstat3 */ +#define NFS3_OK 0 +#define NFS3ERR_PERM 1 +#define NFS3ERR_NOENT 2 +#define NFS3ERR_IO 5 +#define NFS3ERR_NXIO 6 +#define NFS3ERR_ACCES 13 +#define NFS3ERR_EXIST 17 +#define NFS3ERR_XDEV 18 +#define NFS3ERR_NODEV 19 +#define NFS3ERR_NOTDIR 20 +#define NFS3ERR_ISDIR 21 +#define NFS3ERR_INVAL 22 +#define NFS3ERR_FBIG 27 +#define NFS3ERR_NOSPC 28 +#define NFS3ERR_ROFS 30 +#define NFS3ERR_MLINK 31 +#define NFS3ERR_NAMETOOLONG 63 +#define NFS3ERR_NOTEMPTY 66 +#define NFS3ERR_DQUOT 69 +#define NFS3ERR_STALE 70 +#define NFS3ERR_REMOTE 71 +#define NFS3ERR_BADHANDLE 10001 +#define NFS3ERR_NOT_SYNC 10002 +#define NFS3ERR_BAD_COOKIE 10003 +#define NFS3ERR_NOTSUPP 10004 +#define NFS3ERR_TOOSMALL 10005 +#define NFS3ERR_SERVERFAULT 10006 +#define NFS3ERR_BADTYPE 10007 +#define NFS3ERR_JUKEBOX 10008 static void *nfs_packet; static int nfs_len; @@ -107,51 +131,96 @@ struct nfs_priv { struct net_connection *con; IPaddr_t server; char *path; - int mount_port; - int nfs_port; - unsigned long rpc_id; - char rootfh[NFS_FHSIZE]; + unsigned short mount_port; + unsigned short nfs_port; + uint32_t rpc_id; + uint32_t rootfh_len; + char rootfh[NFS3_FHSIZE]; }; struct file_priv { struct kfifo *fifo; void *buf; - char filefh[NFS_FHSIZE]; + uint32_t filefh_len; + char filefh[NFS3_FHSIZE]; struct nfs_priv *npriv; }; static uint64_t nfs_timer_start; -static int nfs_state; +static int nfs_state; #define STATE_DONE 1 #define STATE_START 2 -enum ftype { - NFNON = 0, - NFREG = 1, - NFDIR = 2, - NFBLK = 3, - NFCHR = 4, - NFLNK = 5 -}; - -struct fattr { - uint32_t type; - uint32_t mode; - uint32_t nlink; - uint32_t uid; - uint32_t gid; - uint32_t size; - uint32_t blocksize; - uint32_t rdev; - uint32_t blocks; -}; - -struct readdirargs { - char filefh[NFS_FHSIZE]; - uint32_t cookie; - uint32_t count; -}; +/* + * common types used in more than one request: + * + * typedef uint32 count3; + * typedef uint32 gid3; + * typedef uint32 mode3; + * typedef uint32 uid3; + * + * typedef uint64 cookie3; + * typedef uint64 fileid3; + * typedef uint64 size3; + * + * typedef string filename3<>; + * typedef string nfspath3<>; + * + * typedef opaque cookieverf3[NFS3_COOKIEVERFSIZE]; + * + * enum ftype3 { + * NF3REG = 1, + * NF3DIR = 2, + * NF3BLK = 3, + * NF3CHR = 4, + * NF3LNK = 5, + * NF3SOCK = 6, + * NF3FIFO = 7 + * }; + * + * struct specdata3 { + * uint32 specdata1; + * uint32 specdata2; + * }; + * + * struct nfs_fh3 { + * opaque data<NFS3_FHSIZE>; + * } + * + * struct nfstime3 { + * uint32 seconds; + * uint32 nseconds; + * }; + * + * struct fattr3 { + * ftype3 type; + * mode3 mode; + * uint32_t nlink; + * uid3 uid; + * gid3 gid; + * size3 size; + * size3 used; + * specdata3 rdev; + * uint64_t fsid; + * fileid3 fileid; + * nfstime3 atime; + * nfstime3 mtime; + * nfstime3 ctime; + * }; + * + * struct diropargs3 { + * nfs_fh3 dir; + * filename3 name; + * } + * + * union post_op_attr switch (bool attributes_follow) { + * case TRUE: + * fattr3 attributes; + * case FALSE: + * void; + * }; + */ struct xdr_stream { __be32 *p; @@ -162,6 +231,20 @@ struct xdr_stream { #define xdr_zero 0 #define XDR_QUADLEN(l) (((l) + 3) >> 2) +struct nfs_dir { + DIR dir; + + /* + * stream points to the next entry3 in the reply member of READDIR3res + * (if any, to the end indicator otherwise). + */ + struct xdr_stream stream; + struct dirent ent; + struct file_priv *priv; + uint64_t cookie; + char cookieverf[NFS3_COOKIEVERFSIZE]; +}; + static void xdr_init(struct xdr_stream *stream, void *buf, int len) { stream->p = stream->buf = buf; @@ -192,8 +275,10 @@ static __be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes) return p; } -static int decode_filename(struct xdr_stream *xdr, - char *name, u32 *length) +/* + * name is expected to point to a buffer with a size of at least 256 bytes. + */ +static int decode_filename(struct xdr_stream *xdr, char *name, u32 *length) { __be32 *p; u32 count; @@ -201,7 +286,7 @@ static int decode_filename(struct xdr_stream *xdr, p = xdr_inline_decode(xdr, 4); if (!p) goto out_overflow; - count = be32_to_cpup(p); + count = ntohl(net_read_uint32(p)); if (count > 255) goto out_nametoolong; p = xdr_inline_decode(xdr, count); @@ -211,11 +296,13 @@ static int decode_filename(struct xdr_stream *xdr, name[count] = 0; *length = count; return 0; + out_nametoolong: - printk("NFS: returned filename too long: %u\n", count); + printf("%s: returned a too long filename: %u\n", __func__, count); return -ENAMETOOLONG; + out_overflow: - printf("%s overflow\n",__func__); + printf("%s: premature end of packet\n", __func__); return -EIO; } @@ -247,7 +334,8 @@ static uint32_t *rpc_add_credentials(uint32_t *p) return p; } -static int rpc_check_reply(unsigned char *pkt, int rpc_prog, unsigned long rpc_id, int *nfserr) +static int rpc_check_reply(unsigned char *pkt, + int rpc_prog, uint32_t rpc_id, int *nfserr) { uint32_t *data; struct rpc_reply rpc; @@ -292,37 +380,41 @@ static int rpc_req(struct nfs_priv *npriv, int rpc_prog, int rpc_proc, uint32_t *data, int datalen) { struct rpc_call pkt; - unsigned long id; - int dport; + unsigned short dport; int ret; unsigned char *payload = net_udp_get_payload(npriv->con); int nfserr; int tries = 0; npriv->rpc_id++; - id = npriv->rpc_id; - pkt.id = htonl(id); + pkt.id = htonl(npriv->rpc_id); pkt.type = htonl(MSG_CALL); pkt.rpcvers = htonl(2); /* use RPC version 2 */ pkt.prog = htonl(rpc_prog); - pkt.vers = htonl(2); /* portmapper is version 2 */ pkt.proc = htonl(rpc_proc); - memcpy(payload, &pkt, sizeof(pkt)); - memcpy(payload + sizeof(pkt), data, datalen * sizeof(uint32_t)); + debug("%s: prog: %d, proc: %d\n", __func__, rpc_prog, rpc_proc); - if (rpc_prog == PROG_PORTMAP) + if (rpc_prog == PROG_PORTMAP) { dport = SUNRPC_PORT; - else if (rpc_prog == PROG_MOUNT) + pkt.vers = htonl(2); + } else if (rpc_prog == PROG_MOUNT) { dport = npriv->mount_port; - else + pkt.vers = htonl(3); + } else { dport = npriv->nfs_port; + pkt.vers = htonl(3); + } + + memcpy(payload, &pkt, sizeof(pkt)); + memcpy(payload + sizeof(pkt), data, datalen * sizeof(uint32_t)); npriv->con->udp->uh_dport = htons(dport); again: - ret = net_udp_send(npriv->con, sizeof(pkt) + datalen * sizeof(uint32_t)); + ret = net_udp_send(npriv->con, + sizeof(pkt) + datalen * sizeof(uint32_t)); nfs_timer_start = get_time_ns(); @@ -357,7 +449,7 @@ again: /* * rpc_lookup_req - Lookup RPC Port numbers */ -static int rpc_lookup_req(struct nfs_priv *npriv, int prog, int ver) +static int rpc_lookup_req(struct nfs_priv *npriv, uint32_t prog, uint32_t ver) { uint32_t data[16]; int ret; @@ -378,6 +470,135 @@ static int rpc_lookup_req(struct nfs_priv *npriv, int prog, int ver) return port; } +static uint32_t *nfs_add_uint32(uint32_t *p, uint32_t val) +{ + *p++ = htonl(val); + return p; +} + +static uint32_t *nfs_add_uint64(uint32_t *p, uint64_t val) +{ + uint64_t nval = htonll(val); + memcpy(p, &nval, 8); + return p + 2; +} + +static uint32_t *nfs_add_fh3(uint32_t *p, unsigned fh_len, const char *fh) +{ + *p++ = htonl(fh_len); + + /* zero padding */ + if (fh_len & 3) + p[fh_len / 4] = 0; + + memcpy(p, fh, fh_len); + p += DIV_ROUND_UP(fh_len, 4); + return p; +} + +static uint32_t *nfs_add_filename(uint32_t *p, + uint32_t filename_len, const char *filename) +{ + *p++ = htonl(filename_len); + + /* zero padding */ + if (filename_len & 3) + p[filename_len / 4] = 0; + + memcpy(p, filename, filename_len); + p += DIV_ROUND_UP(filename_len, 4); + return p; +} + +/* This is a 1:1 mapping for Linux, the compiler optimizes it out */ +static const struct { + uint32_t nfsmode; + unsigned short statmode; +} nfs3_mode_bits[] = { + { 0x00001, S_IXOTH }, + { 0x00002, S_IWOTH }, + { 0x00004, S_IROTH }, + { 0x00008, S_IXGRP }, + { 0x00010, S_IWGRP }, + { 0x00020, S_IRGRP }, + { 0x00040, S_IXUSR }, + { 0x00080, S_IWUSR }, + { 0x00100, S_IRUSR }, + { 0x00200, S_ISVTX }, + { 0x00400, S_ISGID }, + { 0x00800, S_ISUID }, +}; + +static int nfs_fattr3_to_stat(uint32_t *p, struct stat *s) +{ + uint32_t mode; + size_t i; + + /* offsetof(struct fattr3, type) = 0 */ + switch (ntohl(net_read_uint32(p + 0))) { + case NF3REG: + s->st_mode = S_IFREG; + break; + case NF3DIR: + s->st_mode = S_IFDIR; + break; + case NF3BLK: + s->st_mode = S_IFBLK; + break; + case NF3CHR: + s->st_mode = S_IFCHR; + break; + case NF3LNK: + s->st_mode = S_IFLNK; + break; + case NF3SOCK: + s->st_mode = S_IFSOCK; + break; + case NF3FIFO: + s->st_mode = S_IFIFO; + break; + default: + printf("%s: invalid mode %x\n", + __func__, ntohl(net_read_uint32(p + 0))); + return -EIO; + } + + /* offsetof(struct fattr3, mode) = 4 */ + mode = ntohl(net_read_uint32(p + 1)); + for (i = 0; i < ARRAY_SIZE(nfs3_mode_bits); ++i) { + if (mode & nfs3_mode_bits[i].nfsmode) + s->st_mode |= nfs3_mode_bits[i].statmode; + } + + /* offsetof(struct fattr3, size) = 20 */ + s->st_size = ntohll(net_read_uint64(p + 5)); + + return 0; +} + +static uint32_t *nfs_read_post_op_attr(uint32_t *p, struct stat **s) +{ + struct stat dummy; + /* + * union post_op_attr switch (bool attributes_follow) { + * case TRUE: + * fattr3 attributes; + * case FALSE: + * void; + * }; + */ + + if (ntohl(net_read_uint32(p++))) { + nfs_fattr3_to_stat(p, s ? *s : &dummy); + p += 21; + } else if (s) { + /* no attributes available */ + *s = NULL; + } + + return p; +} + /* * nfs_mount_req - Mount an NFS Filesystem */ @@ -409,7 +630,16 @@ static int nfs_mount_req(struct nfs_priv *npriv) if (ret) return ret; - memcpy(npriv->rootfh, nfs_packet + sizeof(struct rpc_reply) + 4, NFS_FHSIZE); + p = nfs_packet + sizeof(struct rpc_reply) + 4; + + npriv->rootfh_len = ntohl(net_read_uint32(p++)); + if (npriv->rootfh_len > NFS3_FHSIZE) { + printf("%s: file handle too big: %lu\n", __func__, + (unsigned long)npriv->rootfh_len); + return -EIO; + } + memcpy(npriv->rootfh, p, npriv->rootfh_len); + p += DIV_ROUND_UP(npriv->rootfh_len, 4); return 0; } @@ -429,12 +659,7 @@ static void nfs_umount_req(struct nfs_priv *npriv) p = &(data[0]); p = rpc_add_credentials(p); - *p++ = htonl(pathlen); - if (pathlen & 3) - *(p + pathlen / 4) = 0; - - memcpy (p, npriv->path, pathlen); - p += (pathlen + 3) / 4; + p = nfs_add_filename(p, pathlen, npriv->path); len = p - &(data[0]); @@ -443,36 +668,68 @@ static void nfs_umount_req(struct nfs_priv *npriv) /* * nfs_lookup_req - Lookup Pathname + * + * *s is set to NULL if LOOKUP3resok doesn't contain obj_attributes. */ -static int nfs_lookup_req(struct file_priv *priv, const char *filename, - int fnamelen) +static int nfs_lookup_req(struct file_priv *priv, + uint32_t filename_len, const char *filename, struct stat **s) { uint32_t data[1024]; uint32_t *p; int len; int ret; + /* + * struct LOOKUP3args { + * diropargs3 what; + * }; + * + * struct LOOKUP3resok { + * nfs_fh3 object; + * post_op_attr obj_attributes; + * post_op_attr dir_attributes; + * }; + * + * struct LOOKUP3resfail { + * post_op_attr dir_attributes; + * }; + * + * union LOOKUP3res switch (nfsstat3 status) { + * case NFS3_OK: + * LOOKUP3resok resok; + * default: + * LOOKUP3resfail resfail; + * }; + */ + p = &(data[0]); p = rpc_add_credentials(p); - memcpy(p, priv->filefh, NFS_FHSIZE); - - p += (NFS_FHSIZE / 4); - *p++ = htonl(fnamelen); + /* what.dir */ + p = nfs_add_fh3(p, priv->filefh_len, priv->filefh); - if (fnamelen & 3) - *(p + fnamelen / 4) = 0; - - memcpy(p, filename, fnamelen); - p += (fnamelen + 3) / 4; + /* what.name */ + p = nfs_add_filename(p, filename_len, filename); len = p - &(data[0]); - ret = rpc_req(priv->npriv, PROG_NFS, NFS_LOOKUP, data, len); + ret = rpc_req(priv->npriv, PROG_NFS, NFSPROC3_LOOKUP, data, len); if (ret) return ret; - memcpy(priv->filefh, nfs_packet + sizeof(struct rpc_reply) + 4, NFS_FHSIZE); + p = nfs_packet + sizeof(struct rpc_reply) + 4; + + priv->filefh_len = ntohl(net_read_uint32(p++)); + if (priv->filefh_len > NFS3_FHSIZE) { + debug("%s: file handle too big: %lu\n", __func__, + (unsigned long)priv->filefh_len); + return -EIO; + } + memcpy(priv->filefh, p, priv->filefh_len); + p += DIV_ROUND_UP(priv->filefh_len, 4); + + if (s) + nfs_read_post_op_attr(p, s); return 0; } @@ -483,33 +740,48 @@ static int nfs_attr_req(struct file_priv *priv, struct stat *s) uint32_t *p; int len; int ret; - struct fattr *fattr; - uint32_t type; + + /* + * struct GETATTR3args { + * nfs_fh3 object; + * } + * + * struct GETATTR3resok { + * fattr3 obj_attributes; + * }; + * + * union GETATTR3res switch (nfsstat3 status) { + * case NFS3_OK: + * GETATTR3resok resok; + * default: + * void; + * } + */ p = &(data[0]); p = rpc_add_credentials(p); - memcpy(p, priv->filefh, NFS_FHSIZE); - p += (NFS_FHSIZE / 4); - *p++ = 0; + /* object */ + p = nfs_add_fh3(p, priv->filefh_len, priv->filefh); len = p - &(data[0]); - ret = rpc_req(priv->npriv, PROG_NFS, NFS_GETATTR, data, len); + ret = rpc_req(priv->npriv, PROG_NFS, NFSPROC3_GETATTR, data, len); if (ret) return ret; - fattr = nfs_packet + sizeof(struct rpc_reply) + 4; - - type = ntohl(net_read_uint32(&fattr->type)); + p = nfs_packet + sizeof(struct rpc_reply) + 4; - s->st_size = ntohl(net_read_uint32(&fattr->size)); - s->st_mode = ntohl(net_read_uint32(&fattr->mode)); + nfs_fattr3_to_stat(p, s); return 0; } -static void *nfs_readdirattr_req(struct file_priv *priv, int *plen, uint32_t cookie) +/* + * returns with dir->stream pointing to the first entry + * of dirlist3 res.resok.reply + */ +static void *nfs_readdirattr_req(struct file_priv *priv, struct nfs_dir *dir) { uint32_t data[1024]; uint32_t *p; @@ -517,26 +789,79 @@ static void *nfs_readdirattr_req(struct file_priv *priv, int *plen, uint32_t coo int ret; void *buf; + /* + * struct READDIR3args { + * nfs_fh3 dir; + * cookie3 cookie; + * cookieverf3 cookieverf; + * count3 count; + * }; + * + * struct entry3 { + * fileid3 fileid; + * filename3 name; + * cookie3 cookie; + * entry3 *nextentry; + * }; + * + * struct dirlist3 { + * entry3 *entries; + * bool eof; + * }; + * + * struct READDIR3resok { + * post_op_attr dir_attributes; + * cookieverf3 cookieverf; + * dirlist3 reply; + * }; + * + * struct READDIR3resfail { + * post_op_attr dir_attributes; + * }; + * + * union READDIR3res switch (nfsstat3 status) { + * case NFS3_OK: + * READDIR3resok resok; + * default: + * READDIR3resfail resfail; + * }; + */ + p = &(data[0]); p = rpc_add_credentials(p); - memcpy(p, priv->filefh, NFS_FHSIZE); - p += (NFS_FHSIZE / 4); - *p++ = htonl(cookie); /* cookie */ - *p++ = htonl(1024); /* count */ - *p++ = 0; + p = nfs_add_fh3(p, priv->filefh_len, priv->filefh); + p = nfs_add_uint64(p, dir->cookie); - len = p - &(data[0]); + memcpy(p, dir->cookieverf, NFS3_COOKIEVERFSIZE); + p += NFS3_COOKIEVERFSIZE / 4; + + p = nfs_add_uint32(p, 1024); /* count */ - ret = rpc_req(priv->npriv, PROG_NFS, NFS_READDIR, data, len); + ret = rpc_req(priv->npriv, PROG_NFS, NFSPROC3_READDIR, data, p - data); if (ret) return NULL; - *plen = nfs_len - sizeof(struct rpc_reply) + 4; + p = nfs_packet + sizeof(struct rpc_reply) + 4; + p = nfs_read_post_op_attr(p, NULL); - buf = xzalloc(*plen); + /* update cookieverf */ + memcpy(dir->cookieverf, p, NFS3_COOKIEVERFSIZE); + p += NFS3_COOKIEVERFSIZE / 4; - memcpy(buf, nfs_packet + sizeof(struct rpc_reply) + 4, *plen); + len = nfs_packet + nfs_len - (void *)p; + if (!len) { + printf("%s: huh, no payload left\n", __func__); + return NULL; + } + + buf = xzalloc(len); + + memcpy(buf, p, len); + + xdr_init(&dir->stream, buf, len); + + /* now xdr points to dirlist3 res.resok.reply */ return buf; } @@ -544,35 +869,74 @@ static void *nfs_readdirattr_req(struct file_priv *priv, int *plen, uint32_t coo /* * nfs_read_req - Read File on NFS Server */ -static int nfs_read_req(struct file_priv *priv, int offset, int readlen) +static int nfs_read_req(struct file_priv *priv, uint64_t offset, + uint32_t readlen) { uint32_t data[1024]; uint32_t *p; - uint32_t *filedata; int len; int ret; - int rlen; + uint32_t rlen, eof; + /* + * struct READ3args { + * nfs_fh3 file; + * offset3 offset; + * count3 count; + * }; + * + * struct READ3resok { + * post_op_attr file_attributes; + * count3 count; + * bool eof; + * opaque data<>; + * }; + * + * struct READ3resfail { + * post_op_attr file_attributes; + * }; + * + * union READ3res switch (nfsstat3 status) { + * case NFS3_OK: + * READ3resok resok; + * default: + * READ3resfail resfail; + * }; + */ p = &(data[0]); p = rpc_add_credentials(p); - memcpy (p, priv->filefh, NFS_FHSIZE); - p += (NFS_FHSIZE / 4); - *p++ = htonl(offset); - *p++ = htonl(readlen); - *p++ = 0; + p = nfs_add_fh3(p, priv->filefh_len, priv->filefh); + p = nfs_add_uint64(p, offset); + p = nfs_add_uint32(p, readlen); len = p - &(data[0]); - ret = rpc_req(priv->npriv, PROG_NFS, NFS_READ, data, len); + ret = rpc_req(priv->npriv, PROG_NFS, NFSPROC3_READ, data, len); if (ret) return ret; - filedata = (uint32_t *)(nfs_packet + sizeof(struct rpc_reply)); + p = nfs_packet + sizeof(struct rpc_reply) + 4; + + p = nfs_read_post_op_attr(p, NULL); + + rlen = ntohl(net_read_uint32(p)); + + /* skip over count */ + p += 1; - rlen = ntohl(net_read_uint32(filedata + 18)); + eof = ntohl(net_read_uint32(p)); - kfifo_put(priv->fifo, (char *)(filedata + 19), rlen); + /* + * skip over eof and count embedded in the representation of data + * assuming it equals rlen above. + */ + p += 2; + + if (readlen && !rlen && !eof) + return -EIO; + + kfifo_put(priv->fifo, (char *)p, rlen); return 0; } @@ -611,25 +975,29 @@ static int nfs_truncate(struct device_d *dev, FILE *f, ulong size) return -ENOSYS; } -static struct file_priv *nfs_do_open(struct device_d *dev, const char *filename) +static struct file_priv *nfs_do_open(struct device_d *dev, + const char *filename, struct stat **s) { struct file_priv *priv; struct nfs_priv *npriv = dev->priv; int ret; const char *tok; + debug("%s: filename = %s\n", __func__, filename); priv = xzalloc(sizeof(*priv)); priv->npriv = npriv; if (!*filename) { - memcpy(priv->filefh, npriv->rootfh, NFS_FHSIZE); + priv->filefh_len = npriv->rootfh_len; + memcpy(priv->filefh, npriv->rootfh, npriv->rootfh_len); return priv; } filename++; - memcpy(priv->filefh, npriv->rootfh, NFS_FHSIZE); + priv->filefh_len = npriv->rootfh_len; + memcpy(priv->filefh, npriv->rootfh, NFS3_FHSIZE); while (*filename) { size_t flen; @@ -640,7 +1008,7 @@ static struct file_priv *nfs_do_open(struct device_d *dev, const char *filename) else flen = strlen(filename); - ret = nfs_lookup_req(priv, filename, flen); + ret = nfs_lookup_req(priv, flen, filename, s); if (ret) goto out; @@ -666,19 +1034,28 @@ static void nfs_do_close(struct file_priv *priv) free(priv); } -static struct file_priv *nfs_do_stat(struct device_d *dev, const char *filename, struct stat *s) +static struct file_priv *nfs_do_stat(struct device_d *dev, + const char *filename, struct stat *s) { struct file_priv *priv; int ret; + struct stat **sptr = &s; - priv = nfs_do_open(dev, filename); + debug("%s: filename = %s\n", __func__, filename); + priv = nfs_do_open(dev, filename, sptr); if (IS_ERR(priv)) return priv; - ret = nfs_attr_req(priv, s); - if (ret) { - nfs_do_close(priv); - return ERR_PTR(ret); + if (!*sptr) { + /* + * The nfs server didn't provide obj_attributes in the lookup + * reply, so ask for them explicitly. + */ + ret = nfs_attr_req(priv, s); + if (ret) { + nfs_do_close(priv); + return ERR_PTR(ret); + } } return priv; @@ -688,35 +1065,52 @@ static int nfs_readlink_req(struct file_priv *priv, char* buf, size_t size) { uint32_t data[1024]; uint32_t *p; - int len; + uint32_t len; int ret; - char *path; - uint32_t *filedata; + /* + * struct READLINK3args { + * nfs_fh3 symlink; + * }; + * + * struct READLINK3resok { + * post_op_attr symlink_attributes; + * nfspath3 data; + * }; + * + * struct READLINK3resfail { + * post_op_attr symlink_attributes; + * } + * + * union READLINK3res switch (nfsstat3 status) { + * case NFS3_OK: + * READLINK3resok resok; + * default: + * READLINK3resfail resfail; + * }; + */ p = &(data[0]); p = rpc_add_credentials(p); - memcpy(p, priv->filefh, NFS_FHSIZE); - p += (NFS_FHSIZE / 4); + p = nfs_add_fh3(p, priv->filefh_len, priv->filefh); len = p - &(data[0]); - ret = rpc_req(priv->npriv, PROG_NFS, NFS_READLINK, data, len); + ret = rpc_req(priv->npriv, PROG_NFS, NFSPROC3_READLINK, data, len); if (ret) return ret; - filedata = nfs_packet + sizeof(struct rpc_reply); - filedata++; + p = nfs_packet + sizeof(struct rpc_reply) + 4; - len = ntohl(net_read_uint32(filedata)); /* new path length */ - filedata++; + p = nfs_read_post_op_attr(p, NULL); - path = (char *)filedata; + len = ntohl(net_read_uint32(p)); /* new path length */ + p++; if (len > size) - len = size; + return -ENOMEM; - memcpy(buf, path, len); + memcpy(buf, p, len); return 0; } @@ -726,9 +1120,8 @@ static int nfs_readlink(struct device_d *dev, const char *filename, { struct file_priv *priv; int ret; - struct stat s; - priv = nfs_do_stat(dev, filename, &s); + priv = nfs_do_open(dev, filename, NULL); if (IS_ERR(priv)) return PTR_ERR(priv); @@ -780,32 +1173,17 @@ static int nfs_write(struct device_d *_dev, FILE *file, const void *inbuf, static int nfs_read(struct device_d *dev, FILE *file, void *buf, size_t insize) { struct file_priv *priv = file->inode; - int now, outsize = 0, ret, pos = file->pos; - - while (insize) { - now = kfifo_get(priv->fifo, buf, insize); - outsize += now; - buf += now; - insize -= now; - - if (insize) { - /* do not use min as insize is a size_t */ - if (insize < 1024) - now = insize; - else - now = 1024; - - if (pos + now > file->size) - now = file->size - pos; - - ret = nfs_read_req(priv, pos, now); - if (ret) - return ret; - pos += now; - } + + if (insize > 1024) + insize = 1024; + + if (insize && !kfifo_len(priv->fifo)) { + int ret = nfs_read_req(priv, file->pos, insize); + if (ret) + return ret; } - return outsize; + return kfifo_get(priv->fifo, buf, insize); } static loff_t nfs_lseek(struct device_d *dev, FILE *file, loff_t pos) @@ -818,110 +1196,89 @@ static loff_t nfs_lseek(struct device_d *dev, FILE *file, loff_t pos) return file->pos; } -struct nfs_dir { - DIR dir; - struct xdr_stream stream; - struct dirent ent; - struct file_priv *priv; - uint32_t cookie; -}; - static DIR *nfs_opendir(struct device_d *dev, const char *pathname) { struct file_priv *priv; - struct stat s; - int ret; - void *buf; + void *buf = NULL; struct nfs_dir *dir; - int len; - priv = nfs_do_open(dev, pathname); + priv = nfs_do_open(dev, pathname, NULL); if (IS_ERR(priv)) return NULL; - ret = nfs_attr_req(priv, &s); - if (ret) - return NULL; - - if (!S_ISDIR(s.st_mode)) - return NULL; - dir = xzalloc(sizeof(*dir)); dir->priv = priv; - buf = nfs_readdirattr_req(priv, &len, 0); - if (!buf) - return NULL; - - xdr_init(&dir->stream, buf, len); + /* cookie == 0 and cookieverf == 0 means start of dir */ + buf = nfs_readdirattr_req(priv, dir); + if (!buf) { + debug("%s: nfs_readdirattr_req failed\n", __func__); + goto err; + } return &dir->dir; + +err: + free(buf); + free(dir); + nfs_do_close(priv); + return NULL; } static struct dirent *nfs_readdir(struct device_d *dev, DIR *dir) { - struct nfs_dir *ndir = (void *)dir; - __be32 *p; + struct nfs_dir *ndir = container_of(dir, struct nfs_dir, dir); + uint32_t *p; int ret; int len; struct xdr_stream *xdr = &ndir->stream; again: p = xdr_inline_decode(xdr, 4); - if (!p) - goto out_overflow; + if (!p) { + printf("%s: premature end of packet\n", __func__); + return NULL; + } - if (*p++ == xdr_zero) { + if (!net_read_uint32(p)) { + /* eof? */ p = xdr_inline_decode(xdr, 4); - if (!p) - goto out_overflow; - if (*p++ == xdr_zero) { - void *buf; - int len; - - /* - * End of current entries, read next chunk. - */ + if (!p) { + printf("%s: premature end of packet\n", __func__); + return NULL; + } + if (net_read_uint32(p)) + return NULL; - free(ndir->stream.buf); + if (!nfs_readdirattr_req(ndir->priv, ndir)) { + printf("%s: nfs_readdirattr_req failed\n", __func__); + return NULL; + } - buf = nfs_readdirattr_req(ndir->priv, &len, ndir->cookie); - if (!buf) - return NULL; + goto again; + } - xdr_init(&ndir->stream, buf, len); + /* there is another entry available in the last reply */ - goto again; - } - return NULL; /* -EINVAL */ + /* skip over fileid */ + p = xdr_inline_decode(xdr, 8); + if (!p) { + printf("%s: premature end of packet\n", __func__); + return NULL; } - p = xdr_inline_decode(xdr, 4); - if (!p) - goto out_overflow; - ret = decode_filename(xdr, ndir->ent.d_name, &len); if (ret) return NULL; - /* - * The type (size and byte order) of nfscookie isn't defined in - * RFC 1094. This implementation assumes that it's an XDR uint32. - */ - p = xdr_inline_decode(xdr, 4); - if (!p) - goto out_overflow; - - ndir->cookie = be32_to_cpup(p); + p = xdr_inline_decode(xdr, 8); + if (!p) { + printf("%s: premature end of packet\n", __func__); + return NULL; + } + ndir->cookie = ntohll(net_read_uint64(p)); return &ndir->ent; - -out_overflow: - - printf("nfs: overflow error\n"); - - return NULL; - } static int nfs_closedir(struct device_d *dev, DIR *dir) @@ -990,7 +1347,7 @@ static int nfs_probe(struct device_d *dev) } npriv->mount_port = ret; - ret = rpc_lookup_req(npriv, PROG_NFS, 2); + ret = rpc_lookup_req(npriv, PROG_NFS, 3); if (ret < 0) { printf("lookup nfs port failed with %d\n", ret); goto err2; -- 1.8.5.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 8/9] nfs: switch to nfs3 2014-02-06 16:40 ` [PATCH 8/9] nfs: switch to nfs3 Uwe Kleine-König @ 2014-02-07 6:48 ` Jean-Christophe PLAGNIOL-VILLARD 2014-02-07 8:52 ` Uwe Kleine-König 0 siblings, 1 reply; 20+ messages in thread From: Jean-Christophe PLAGNIOL-VILLARD @ 2014-02-07 6:48 UTC (permalink / raw) To: Uwe Kleine-K??nig; +Cc: barebox On 17:40 Thu 06 Feb , Uwe Kleine-K??nig wrote: > This was tested against nfs-kernel-server and unfs3. > > Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> > --- > fs/nfs.c | 859 ++++++++++++++++++++++++++++++++++++++++++++------------------- > 1 file changed, 608 insertions(+), 251 deletions(-) > > diff --git a/fs/nfs.c b/fs/nfs.c > index 373159d6ffb7..8eec63078dd3 100644 > --- a/fs/nfs.c > +++ b/fs/nfs.c > @@ -1,10 +1,12 @@ > /* > * nfs.c - barebox NFS driver > * > + * Copyright (c) 2014 Uwe Kleine-König, Pengutronix > * Copyright (c) 2012 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix > * Copyright (c) Masami Komiya <mkomiya@sonare.it> 2004 > * > - * Based on U-Boot NFS code which is based on NetBSD code > + * Based on U-Boot NFS code which is based on NetBSD code with > + * major changes to support nfs3. > * > * See file CREDITS for list of people who contributed to this > * project. > @@ -17,7 +19,6 @@ > * but WITHOUT ANY WARRANTY; without even the implied warranty of > * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > * GNU General Public License for more details. > - * > */ > > #include <common.h> > @@ -34,6 +35,9 @@ > #include <kfifo.h> > #include <sizes.h> > > +#define ntohll(val) __be64_to_cpu(val) > +#define htonll(val) __cpu_to_be64(val) use the cpu_to and to_cpu directly as if we have the standard define in any header later this will cause issues > + > #define SUNRPC_PORT 111 > > #define PROG_PORTMAP 100000 > @@ -48,34 +52,54 @@ > #define MOUNT_ADDENTRY 1 > #define MOUNT_UMOUNT 3 > > -#define NFS_GETATTR 1 > -#define NFS_LOOKUP 4 > -#define NFS_READLINK 5 > -#define NFS_READ 6 > -#define NFS_READDIR 16 > - > -#define NFS_FHSIZE 32 > - > -enum nfs_stat { > - NFS_OK = 0, > - NFSERR_PERM = 1, > - NFSERR_NOENT = 2, > - NFSERR_IO = 5, > - NFSERR_NXIO = 6, > - NFSERR_ACCES = 13, > - NFSERR_EXIST = 17, > - NFSERR_NODEV = 19, > - NFSERR_NOTDIR = 20, > - NFSERR_ISDIR = 21, > - NFSERR_FBIG = 27, > - NFSERR_NOSPC = 28, > - NFSERR_ROFS = 30, > - NFSERR_NAMETOOLONG=63, > - NFSERR_NOTEMPTY = 66, > - NFSERR_DQUOT = 69, > - NFSERR_STALE = 70, > - NFSERR_WFLUSH = 99, > -}; > +#define NFSPROC3_GETATTR 1 > +#define NFSPROC3_LOOKUP 3 > +#define NFSPROC3_READLINK 5 > +#define NFSPROC3_READ 6 > +#define NFSPROC3_READDIR 16 > + > +#define NFS3_FHSIZE 64 > +#define NFS3_COOKIEVERFSIZE 8 > + > +/* values of enum ftype3 */ > +#define NF3REG 1 > +#define NF3DIR 2 > +#define NF3BLK 3 > +#define NF3CHR 4 > +#define NF3LNK 5 > +#define NF3SOCK 6 > +#define NF3FIFO 7 > + > +/* values for enum nfsstat3 */ > +#define NFS3_OK 0 > +#define NFS3ERR_PERM 1 > +#define NFS3ERR_NOENT 2 > +#define NFS3ERR_IO 5 > +#define NFS3ERR_NXIO 6 > +#define NFS3ERR_ACCES 13 > +#define NFS3ERR_EXIST 17 > +#define NFS3ERR_XDEV 18 > +#define NFS3ERR_NODEV 19 > +#define NFS3ERR_NOTDIR 20 > +#define NFS3ERR_ISDIR 21 > +#define NFS3ERR_INVAL 22 > +#define NFS3ERR_FBIG 27 > +#define NFS3ERR_NOSPC 28 > +#define NFS3ERR_ROFS 30 > +#define NFS3ERR_MLINK 31 > +#define NFS3ERR_NAMETOOLONG 63 > +#define NFS3ERR_NOTEMPTY 66 > +#define NFS3ERR_DQUOT 69 > +#define NFS3ERR_STALE 70 > +#define NFS3ERR_REMOTE 71 > +#define NFS3ERR_BADHANDLE 10001 > +#define NFS3ERR_NOT_SYNC 10002 > +#define NFS3ERR_BAD_COOKIE 10003 > +#define NFS3ERR_NOTSUPP 10004 > +#define NFS3ERR_TOOSMALL 10005 > +#define NFS3ERR_SERVERFAULT 10006 > +#define NFS3ERR_BADTYPE 10007 > +#define NFS3ERR_JUKEBOX 10008 > > static void *nfs_packet; > static int nfs_len; > @@ -107,51 +131,96 @@ struct nfs_priv { > struct net_connection *con; > IPaddr_t server; > char *path; > - int mount_port; > - int nfs_port; > - unsigned long rpc_id; > - char rootfh[NFS_FHSIZE]; > + unsigned short mount_port; > + unsigned short nfs_port; > + uint32_t rpc_id; > + uint32_t rootfh_len; > + char rootfh[NFS3_FHSIZE]; > }; > > struct file_priv { > struct kfifo *fifo; > void *buf; > - char filefh[NFS_FHSIZE]; > + uint32_t filefh_len; > + char filefh[NFS3_FHSIZE]; > struct nfs_priv *npriv; > }; > > static uint64_t nfs_timer_start; > > -static int nfs_state; > +static int nfs_state; > #define STATE_DONE 1 > #define STATE_START 2 > > -enum ftype { > - NFNON = 0, > - NFREG = 1, > - NFDIR = 2, > - NFBLK = 3, > - NFCHR = 4, > - NFLNK = 5 > -}; > - > -struct fattr { > - uint32_t type; > - uint32_t mode; > - uint32_t nlink; > - uint32_t uid; > - uint32_t gid; > - uint32_t size; > - uint32_t blocksize; > - uint32_t rdev; > - uint32_t blocks; > -}; > - > -struct readdirargs { > - char filefh[NFS_FHSIZE]; > - uint32_t cookie; > - uint32_t count; > -}; > +/* > + * common types used in more than one request: > + * > + * typedef uint32 count3; > + * typedef uint32 gid3; > + * typedef uint32 mode3; > + * typedef uint32 uid3; > + * > + * typedef uint64 cookie3; > + * typedef uint64 fileid3; > + * typedef uint64 size3; > + * > + * typedef string filename3<>; > + * typedef string nfspath3<>; > + * > + * typedef opaque cookieverf3[NFS3_COOKIEVERFSIZE]; > + * > + * enum ftype3 { > + * NF3REG = 1, > + * NF3DIR = 2, > + * NF3BLK = 3, > + * NF3CHR = 4, > + * NF3LNK = 5, > + * NF3SOCK = 6, > + * NF3FIFO = 7 > + * }; > + * > + * struct specdata3 { > + * uint32 specdata1; > + * uint32 specdata2; > + * }; > + * > + * struct nfs_fh3 { > + * opaque data<NFS3_FHSIZE>; > + * } > + * > + * struct nfstime3 { > + * uint32 seconds; > + * uint32 nseconds; > + * }; > + * > + * struct fattr3 { > + * ftype3 type; > + * mode3 mode; > + * uint32_t nlink; > + * uid3 uid; > + * gid3 gid; > + * size3 size; > + * size3 used; > + * specdata3 rdev; > + * uint64_t fsid; > + * fileid3 fileid; > + * nfstime3 atime; > + * nfstime3 mtime; > + * nfstime3 ctime; > + * }; > + * > + * struct diropargs3 { > + * nfs_fh3 dir; > + * filename3 name; > + * } > + * > + * union post_op_attr switch (bool attributes_follow) { > + * case TRUE: > + * fattr3 attributes; > + * case FALSE: > + * void; > + * }; > + */ > > struct xdr_stream { > __be32 *p; > @@ -162,6 +231,20 @@ struct xdr_stream { > #define xdr_zero 0 > #define XDR_QUADLEN(l) (((l) + 3) >> 2) > > +struct nfs_dir { > + DIR dir; > + > + /* > + * stream points to the next entry3 in the reply member of READDIR3res > + * (if any, to the end indicator otherwise). > + */ > + struct xdr_stream stream; > + struct dirent ent; > + struct file_priv *priv; > + uint64_t cookie; > + char cookieverf[NFS3_COOKIEVERFSIZE]; > +}; > + > static void xdr_init(struct xdr_stream *stream, void *buf, int len) > { > stream->p = stream->buf = buf; > @@ -192,8 +275,10 @@ static __be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes) > return p; > } > > -static int decode_filename(struct xdr_stream *xdr, > - char *name, u32 *length) > +/* > + * name is expected to point to a buffer with a size of at least 256 bytes. > + */ > +static int decode_filename(struct xdr_stream *xdr, char *name, u32 *length) > { > __be32 *p; > u32 count; > @@ -201,7 +286,7 @@ static int decode_filename(struct xdr_stream *xdr, > p = xdr_inline_decode(xdr, 4); > if (!p) > goto out_overflow; > - count = be32_to_cpup(p); > + count = ntohl(net_read_uint32(p)); > if (count > 255) > goto out_nametoolong; > p = xdr_inline_decode(xdr, count); > @@ -211,11 +296,13 @@ static int decode_filename(struct xdr_stream *xdr, > name[count] = 0; > *length = count; > return 0; > + > out_nametoolong: > - printk("NFS: returned filename too long: %u\n", count); > + printf("%s: returned a too long filename: %u\n", __func__, count); can we use dev_xx for message > return -ENAMETOOLONG; > + > out_overflow: > - printf("%s overflow\n",__func__); > + printf("%s: premature end of packet\n", __func__); > return -EIO; > } > > @@ -247,7 +334,8 @@ static uint32_t *rpc_add_credentials(uint32_t *p) > return p; > } > > -static int rpc_check_reply(unsigned char *pkt, int rpc_prog, unsigned long rpc_id, int *nfserr) > +static int rpc_check_reply(unsigned char *pkt, > + int rpc_prog, uint32_t rpc_id, int *nfserr) > { > uint32_t *data; > struct rpc_reply rpc; > @@ -292,37 +380,41 @@ static int rpc_req(struct nfs_priv *npriv, int rpc_prog, int rpc_proc, > uint32_t *data, int datalen) > { > struct rpc_call pkt; > - unsigned long id; > - int dport; > + unsigned short dport; > int ret; > unsigned char *payload = net_udp_get_payload(npriv->con); > int nfserr; > int tries = 0; > > npriv->rpc_id++; > - id = npriv->rpc_id; > > - pkt.id = htonl(id); > + pkt.id = htonl(npriv->rpc_id); > pkt.type = htonl(MSG_CALL); > pkt.rpcvers = htonl(2); /* use RPC version 2 */ > pkt.prog = htonl(rpc_prog); > - pkt.vers = htonl(2); /* portmapper is version 2 */ > pkt.proc = htonl(rpc_proc); > > - memcpy(payload, &pkt, sizeof(pkt)); > - memcpy(payload + sizeof(pkt), data, datalen * sizeof(uint32_t)); > + debug("%s: prog: %d, proc: %d\n", __func__, rpc_prog, rpc_proc); > > - if (rpc_prog == PROG_PORTMAP) > + if (rpc_prog == PROG_PORTMAP) { > dport = SUNRPC_PORT; > - else if (rpc_prog == PROG_MOUNT) > + pkt.vers = htonl(2); > + } else if (rpc_prog == PROG_MOUNT) { > dport = npriv->mount_port; > - else > + pkt.vers = htonl(3); > + } else { > dport = npriv->nfs_port; > + pkt.vers = htonl(3); > + } > + > + memcpy(payload, &pkt, sizeof(pkt)); > + memcpy(payload + sizeof(pkt), data, datalen * sizeof(uint32_t)); > > npriv->con->udp->uh_dport = htons(dport); > > again: > - ret = net_udp_send(npriv->con, sizeof(pkt) + datalen * sizeof(uint32_t)); > + ret = net_udp_send(npriv->con, > + sizeof(pkt) + datalen * sizeof(uint32_t)); > > nfs_timer_start = get_time_ns(); > > @@ -357,7 +449,7 @@ again: > /* > * rpc_lookup_req - Lookup RPC Port numbers > */ > -static int rpc_lookup_req(struct nfs_priv *npriv, int prog, int ver) > +static int rpc_lookup_req(struct nfs_priv *npriv, uint32_t prog, uint32_t ver) > { > uint32_t data[16]; > int ret; > @@ -378,6 +470,135 @@ static int rpc_lookup_req(struct nfs_priv *npriv, int prog, int ver) > return port; > } > > +static uint32_t *nfs_add_uint32(uint32_t *p, uint32_t val) > +{ > + *p++ = htonl(val); > + return p; > +} > + > +static uint32_t *nfs_add_uint64(uint32_t *p, uint64_t val) > +{ > + uint64_t nval = htonll(val); missing blank line > + memcpy(p, &nval, 8); > + return p + 2; > +} > + > +static uint32_t *nfs_add_fh3(uint32_t *p, unsigned fh_len, const char *fh) > +{ > + *p++ = htonl(fh_len); > + > + /* zero padding */ > + if (fh_len & 3) > + p[fh_len / 4] = 0; > + > + memcpy(p, fh, fh_len); > + p += DIV_ROUND_UP(fh_len, 4); > + return p; > +} > + > +static uint32_t *nfs_add_filename(uint32_t *p, > + uint32_t filename_len, const char *filename) > +{ > + *p++ = htonl(filename_len); > + > + /* zero padding */ > + if (filename_len & 3) > + p[filename_len / 4] = 0; > + > + memcpy(p, filename, filename_len); > + p += DIV_ROUND_UP(filename_len, 4); > + return p; > +} > + what is the difference with the function upper? > +/* This is a 1:1 mapping for Linux, the compiler optimizes it out */ > +static const struct { > + uint32_t nfsmode; > + unsigned short statmode; > +} nfs3_mode_bits[] = { > + { 0x00001, S_IXOTH }, > + { 0x00002, S_IWOTH }, > + { 0x00004, S_IROTH }, > + { 0x00008, S_IXGRP }, > + { 0x00010, S_IWGRP }, > + { 0x00020, S_IRGRP }, > + { 0x00040, S_IXUSR }, > + { 0x00080, S_IWUSR }, > + { 0x00100, S_IRUSR }, > + { 0x00200, S_ISVTX }, > + { 0x00400, S_ISGID }, > + { 0x00800, S_ISUID }, > +}; > + > +static int nfs_fattr3_to_stat(uint32_t *p, struct stat *s) > +{ > + uint32_t mode; > + size_t i; > + > + /* offsetof(struct fattr3, type) = 0 */ > + switch (ntohl(net_read_uint32(p + 0))) { > + case NF3REG: > + s->st_mode = S_IFREG; > + break; > + case NF3DIR: > + s->st_mode = S_IFDIR; > + break; > + case NF3BLK: > + s->st_mode = S_IFBLK; > + break; > + case NF3CHR: > + s->st_mode = S_IFCHR; > + break; > + case NF3LNK: > + s->st_mode = S_IFLNK; > + break; > + case NF3SOCK: > + s->st_mode = S_IFSOCK; > + break; > + case NF3FIFO: > + s->st_mode = S_IFIFO; > + break; > + default: > + printf("%s: invalid mode %x\n", > + __func__, ntohl(net_read_uint32(p + 0))); > + return -EIO; > + } > + > + /* offsetof(struct fattr3, mode) = 4 */ > + mode = ntohl(net_read_uint32(p + 1)); > + for (i = 0; i < ARRAY_SIZE(nfs3_mode_bits); ++i) { > + if (mode & nfs3_mode_bits[i].nfsmode) > + s->st_mode |= nfs3_mode_bits[i].statmode; > + } > + > + /* offsetof(struct fattr3, size) = 20 */ > + s->st_size = ntohll(net_read_uint64(p + 5)); > + > + return 0; > +} > + > +static uint32_t *nfs_read_post_op_attr(uint32_t *p, struct stat **s) > +{ > + struct stat dummy; > + /* > + * union post_op_attr switch (bool attributes_follow) { > + * case TRUE: > + * fattr3 attributes; > + * case FALSE: > + * void; > + * }; > + */ > + > + if (ntohl(net_read_uint32(p++))) { > + nfs_fattr3_to_stat(p, s ? *s : &dummy); > + p += 21; > + } else if (s) { > + /* no attributes available */ > + *s = NULL; > + } > + > + return p; > +} > + > /* > * nfs_mount_req - Mount an NFS Filesystem > */ > @@ -409,7 +630,16 @@ static int nfs_mount_req(struct nfs_priv *npriv) > if (ret) > return ret; > > - memcpy(npriv->rootfh, nfs_packet + sizeof(struct rpc_reply) + 4, NFS_FHSIZE); > + p = nfs_packet + sizeof(struct rpc_reply) + 4; > + > + npriv->rootfh_len = ntohl(net_read_uint32(p++)); > + if (npriv->rootfh_len > NFS3_FHSIZE) { > + printf("%s: file handle too big: %lu\n", __func__, > + (unsigned long)npriv->rootfh_len); > + return -EIO; really EIO? > + } > + memcpy(npriv->rootfh, p, npriv->rootfh_len); > + p += DIV_ROUND_UP(npriv->rootfh_len, 4); > > return 0; > } > @@ -429,12 +659,7 @@ static void nfs_umount_req(struct nfs_priv *npriv) > p = &(data[0]); > p = rpc_add_credentials(p); > > - *p++ = htonl(pathlen); > - if (pathlen & 3) > - *(p + pathlen / 4) = 0; > - > - memcpy (p, npriv->path, pathlen); > - p += (pathlen + 3) / 4; > + p = nfs_add_filename(p, pathlen, npriv->path); > > len = p - &(data[0]); > > @@ -443,36 +668,68 @@ static void nfs_umount_req(struct nfs_priv *npriv) > > /* > * nfs_lookup_req - Lookup Pathname > + * > + * *s is set to NULL if LOOKUP3resok doesn't contain obj_attributes. > */ > -static int nfs_lookup_req(struct file_priv *priv, const char *filename, > - int fnamelen) > +static int nfs_lookup_req(struct file_priv *priv, > + uint32_t filename_len, const char *filename, struct stat **s) > { .... > static struct dirent *nfs_readdir(struct device_d *dev, DIR *dir) > { > - struct nfs_dir *ndir = (void *)dir; > - __be32 *p; > + struct nfs_dir *ndir = container_of(dir, struct nfs_dir, dir); > + uint32_t *p; > int ret; > int len; > struct xdr_stream *xdr = &ndir->stream; > > again: > p = xdr_inline_decode(xdr, 4); > - if (!p) > - goto out_overflow; > + if (!p) { > + printf("%s: premature end of packet\n", __func__); > + return NULL; > + } > > - if (*p++ == xdr_zero) { > + if (!net_read_uint32(p)) { > + /* eof? */ > p = xdr_inline_decode(xdr, 4); > - if (!p) > - goto out_overflow; > - if (*p++ == xdr_zero) { > - void *buf; > - int len; > - > - /* > - * End of current entries, read next chunk. > - */ > + if (!p) { > + printf("%s: premature end of packet\n", __func__); > + return NULL; > + } > + if (net_read_uint32(p)) > + return NULL; > > - free(ndir->stream.buf); > + if (!nfs_readdirattr_req(ndir->priv, ndir)) { > + printf("%s: nfs_readdirattr_req failed\n", __func__); > + return NULL; > + } > > - buf = nfs_readdirattr_req(ndir->priv, &len, ndir->cookie); > - if (!buf) > - return NULL; > + goto again; > + } > > - xdr_init(&ndir->stream, buf, len); > + /* there is another entry available in the last reply */ > > - goto again; > - } > - return NULL; /* -EINVAL */ > + /* skip over fileid */ > + p = xdr_inline_decode(xdr, 8); > + if (!p) { > + printf("%s: premature end of packet\n", __func__); > + return NULL; > } > > - p = xdr_inline_decode(xdr, 4); > - if (!p) > - goto out_overflow; > - > ret = decode_filename(xdr, ndir->ent.d_name, &len); > if (ret) > return NULL; > > - /* > - * The type (size and byte order) of nfscookie isn't defined in > - * RFC 1094. This implementation assumes that it's an XDR uint32. > - */ > - p = xdr_inline_decode(xdr, 4); > - if (!p) > - goto out_overflow; > - > - ndir->cookie = be32_to_cpup(p); > + p = xdr_inline_decode(xdr, 8); > + if (!p) { > + printf("%s: premature end of packet\n", __func__); > + return NULL; > + } > + ndir->cookie = ntohll(net_read_uint64(p)); > > return &ndir->ent; > - > -out_overflow: > - > - printf("nfs: overflow error\n"); > - > - return NULL; > - > } > > static int nfs_closedir(struct device_d *dev, DIR *dir) > @@ -990,7 +1347,7 @@ static int nfs_probe(struct device_d *dev) > } > npriv->mount_port = ret; > > - ret = rpc_lookup_req(npriv, PROG_NFS, 2); > + ret = rpc_lookup_req(npriv, PROG_NFS, 3); so we loose nfs2? > if (ret < 0) { > printf("lookup nfs port failed with %d\n", ret); > goto err2; > -- > 1.8.5.2 > > > _______________________________________________ > barebox mailing list > barebox@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/barebox _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 8/9] nfs: switch to nfs3 2014-02-07 6:48 ` Jean-Christophe PLAGNIOL-VILLARD @ 2014-02-07 8:52 ` Uwe Kleine-König 2014-02-07 9:50 ` Jean-Christophe PLAGNIOL-VILLARD 0 siblings, 1 reply; 20+ messages in thread From: Uwe Kleine-König @ 2014-02-07 8:52 UTC (permalink / raw) To: Jean-Christophe PLAGNIOL-VILLARD; +Cc: barebox Hello Jean-Christophe, On Fri, Feb 07, 2014 at 07:48:57AM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote: > On 17:40 Thu 06 Feb , Uwe Kleine-K??nig wrote: > > +#define ntohll(val) __be64_to_cpu(val) > > +#define htonll(val) __cpu_to_be64(val) > > use the cpu_to and to_cpu directly > as if we have the standard define in any header later this will cause issues htonll isn't that standard. I doesn't exist neither in Linux userspace nor in Linux kernel space. I would prefer to put the macro into a global place already now. Or still better, define {ntoh,hton}{16,32,64} which have a more intuitive naming scheme. > > - printk("NFS: returned filename too long: %u\n", count); > > + printf("%s: returned a too long filename: %u\n", __func__, count); > can we use dev_xx for message I will check where I can get my hands on a good struct device_d*. > > +static uint32_t *nfs_add_fh3(uint32_t *p, unsigned fh_len, const char *fh) > > +{ > > + *p++ = htonl(fh_len); > > + > > + /* zero padding */ > > + if (fh_len & 3) > > + p[fh_len / 4] = 0; > > + > > + memcpy(p, fh, fh_len); > > + p += DIV_ROUND_UP(fh_len, 4); > > + return p; > > +} > > + > > +static uint32_t *nfs_add_filename(uint32_t *p, > > + uint32_t filename_len, const char *filename) > > +{ > > + *p++ = htonl(filename_len); > > + > > + /* zero padding */ > > + if (filename_len & 3) > > + p[filename_len / 4] = 0; > > + > > + memcpy(p, filename, filename_len); > > + p += DIV_ROUND_UP(filename_len, 4); > > + return p; > > +} > > + > what is the difference with the function upper? The function and parameter names and the type of the 2nd argument. (OK, I guess that wasn't the answer you wanted to read. Yes, you're right, they could use the same function. Something like nfs_add_string. (Technically fh3 isn't a string<> but an opaque<NFS3_FHSIZE>, but that doesn't really matter here. I will think a bit about proper naming.)) > > + npriv->rootfh_len = ntohl(net_read_uint32(p++)); > > + if (npriv->rootfh_len > NFS3_FHSIZE) { > > + printf("%s: file handle too big: %lu\n", __func__, > > + (unsigned long)npriv->rootfh_len); > > + return -EIO; > really EIO? That's a protocol error and -EIO is what is returned in other places for protocol errors, too. Still if you have a better suggestion ... > > - ret = rpc_lookup_req(npriv, PROG_NFS, 2); > > + ret = rpc_lookup_req(npriv, PROG_NFS, 3); > > so we loose nfs2? Right. Do you consider it a loss? I don't think it worth to implement both side by side. Best regards Uwe -- Pengutronix e.K. | Uwe Kleine-König | Industrial Linux Solutions | http://www.pengutronix.de/ | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 8/9] nfs: switch to nfs3 2014-02-07 8:52 ` Uwe Kleine-König @ 2014-02-07 9:50 ` Jean-Christophe PLAGNIOL-VILLARD 2014-02-07 10:23 ` Uwe Kleine-König 0 siblings, 1 reply; 20+ messages in thread From: Jean-Christophe PLAGNIOL-VILLARD @ 2014-02-07 9:50 UTC (permalink / raw) To: Uwe Kleine-K??nig; +Cc: barebox On 09:52 Fri 07 Feb , Uwe Kleine-K??nig wrote: > Hello Jean-Christophe, > > On Fri, Feb 07, 2014 at 07:48:57AM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote: > > On 17:40 Thu 06 Feb , Uwe Kleine-K??nig wrote: > > > +#define ntohll(val) __be64_to_cpu(val) > > > +#define htonll(val) __cpu_to_be64(val) > > > > use the cpu_to and to_cpu directly > > as if we have the standard define in any header later this will cause issues > htonll isn't that standard. I doesn't exist neither in Linux userspace > nor in Linux kernel space. I would prefer to put the macro into a global > place already now. Or still better, define {ntoh,hton}{16,32,64} which > have a more intuitive naming scheme. yeah agreed > > > > - printk("NFS: returned filename too long: %u\n", count); > > > + printf("%s: returned a too long filename: %u\n", __func__, count); > > can we use dev_xx for message > I will check where I can get my hands on a good struct device_d*. > > > > +static uint32_t *nfs_add_fh3(uint32_t *p, unsigned fh_len, const char *fh) > > > +{ > > > + *p++ = htonl(fh_len); > > > + > > > + /* zero padding */ > > > + if (fh_len & 3) > > > + p[fh_len / 4] = 0; > > > + > > > + memcpy(p, fh, fh_len); > > > + p += DIV_ROUND_UP(fh_len, 4); > > > + return p; > > > +} > > > + > > > +static uint32_t *nfs_add_filename(uint32_t *p, > > > + uint32_t filename_len, const char *filename) > > > +{ > > > + *p++ = htonl(filename_len); > > > + > > > + /* zero padding */ > > > + if (filename_len & 3) > > > + p[filename_len / 4] = 0; > > > + > > > + memcpy(p, filename, filename_len); > > > + p += DIV_ROUND_UP(filename_len, 4); > > > + return p; > > > +} > > > + > > what is the difference with the function upper? > The function and parameter names and the type of the 2nd argument. ;) > (OK, I guess that wasn't the answer you wanted to read. Yes, you're > right, they could use the same function. Something like nfs_add_string. > (Technically fh3 isn't a string<> but an opaque<NFS3_FHSIZE>, but that > doesn't really matter here. I will think a bit about proper naming.)) > > > > + npriv->rootfh_len = ntohl(net_read_uint32(p++)); > > > + if (npriv->rootfh_len > NFS3_FHSIZE) { > > > + printf("%s: file handle too big: %lu\n", __func__, > > > + (unsigned long)npriv->rootfh_len); > > > + return -EIO; > > really EIO? > That's a protocol error and -EIO is what is returned in other places for > protocol errors, too. Still if you have a better suggestion ... -EPROTO no? > > > > - ret = rpc_lookup_req(npriv, PROG_NFS, 2); > > > + ret = rpc_lookup_req(npriv, PROG_NFS, 3); > > > > so we loose nfs2? > Right. Do you consider it a loss? I don't think it worth to implement > both side by side. I see this as a compatibility issue > > Best regards > Uwe > > -- > Pengutronix e.K. | Uwe Kleine-König | > Industrial Linux Solutions | http://www.pengutronix.de/ | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 8/9] nfs: switch to nfs3 2014-02-07 9:50 ` Jean-Christophe PLAGNIOL-VILLARD @ 2014-02-07 10:23 ` Uwe Kleine-König 0 siblings, 0 replies; 20+ messages in thread From: Uwe Kleine-König @ 2014-02-07 10:23 UTC (permalink / raw) To: Jean-Christophe PLAGNIOL-VILLARD; +Cc: barebox On Fri, Feb 07, 2014 at 10:50:56AM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote: > On 09:52 Fri 07 Feb , Uwe Kleine-K??nig wrote: > > > > + npriv->rootfh_len = ntohl(net_read_uint32(p++)); > > > > + if (npriv->rootfh_len > NFS3_FHSIZE) { > > > > + printf("%s: file handle too big: %lu\n", __func__, > > > > + (unsigned long)npriv->rootfh_len); > > > > + return -EIO; > > > really EIO? > > That's a protocol error and -EIO is what is returned in other places for > > protocol errors, too. Still if you have a better suggestion ... > > -EPROTO no? For the nfs-side EPROTO looks good, but for the caller of the fs functions EIO seems more sensible because the caller didn't violate any protocol. For that it's just a "failed to read" thing. (BTW, I like my bike sheds being blue. :-) > > > > - ret = rpc_lookup_req(npriv, PROG_NFS, 2); > > > > + ret = rpc_lookup_req(npriv, PROG_NFS, 3); > > > > > > so we loose nfs2? > > Right. Do you consider it a loss? I don't think it worth to implement > > both side by side. > > I see this as a compatibility issue Sure it's a compatibility issue. But I guess it won't bite anyone. nfs3 exists since 1995 (the rfc that is). nfsd-v3 support is in Linux 2.4.0 (from 2003) and I bet that any distro-Kernel that has nfsd enabled also knows about nfs3. So I think it's sane to drop nfs2 support from barebox which will only bitrot otherwise. Best regards Uwe -- Pengutronix e.K. | Uwe Kleine-König | Industrial Linux Solutions | http://www.pengutronix.de/ | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 9/9] nfs: parse nfsport and mount port from file system options 2014-02-06 16:40 [PATCH 0/9] nfs3 support Uwe Kleine-König ` (7 preceding siblings ...) 2014-02-06 16:40 ` [PATCH 8/9] nfs: switch to nfs3 Uwe Kleine-König @ 2014-02-06 16:40 ` Uwe Kleine-König 2014-02-07 6:50 ` Jean-Christophe PLAGNIOL-VILLARD 8 siblings, 1 reply; 20+ messages in thread From: Uwe Kleine-König @ 2014-02-06 16:40 UTC (permalink / raw) To: barebox This allows to use unfs3 on the server side which doesn't integrate into portmap/rpcbind which results in the port not being impossible to lookup via rpc calls to the portmap program. Use it like: mount -t nfs -o port=2703,mountport=2703 192.168.77.157:/root /mnt/nfs Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> --- fs/nfs.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/fs/nfs.c b/fs/nfs.c index 8eec63078dd3..50b3744b4551 100644 --- a/fs/nfs.c +++ b/fs/nfs.c @@ -1305,6 +1305,38 @@ static int nfs_stat(struct device_d *dev, const char *filename, struct stat *s) } } +static void parseopt_hu(const char *options, const char *opt, + unsigned short *val) +{ + const char *start; + size_t optlen = strlen(opt); + ulong v; + char *endp; + +again: + start = strstr(options, opt); + + if (!start) + return; + + if (start > options && start[-1] != ',') { + options = start; + goto again; + } + + if (start[optlen] != '=') { + options = start; + goto again; + } + + v = simple_strtoul(start + optlen + 1, &endp, 0); + if (v > USHORT_MAX) + return; + + if (*endp == ',' || *endp == '\0') + *val = v; +} + static int nfs_probe(struct device_d *dev) { struct fs_device_d *fsdev = dev_to_fs_device(dev); @@ -1340,19 +1372,27 @@ static int nfs_probe(struct device_d *dev) /* Need a priviliged source port */ net_udp_bind(npriv->con, 1000); - ret = rpc_lookup_req(npriv, PROG_MOUNT, 1); - if (ret < 0) { - printf("lookup mount port failed with %d\n", ret); - goto err2; + parseopt_hu(fsdev->options, "mountport", &npriv->mount_port); + if (!npriv->mount_port) { + ret = rpc_lookup_req(npriv, PROG_MOUNT, 1); + if (ret < 0) { + printf("lookup mount port failed with %d\n", ret); + goto err2; + } + npriv->mount_port = ret; } - npriv->mount_port = ret; - - ret = rpc_lookup_req(npriv, PROG_NFS, 3); - if (ret < 0) { - printf("lookup nfs port failed with %d\n", ret); - goto err2; + debug("mount port: %hu\n", npriv->mount_port); + + parseopt_hu(fsdev->options, "port", &npriv->nfs_port); + if (!npriv->nfs_port) { + ret = rpc_lookup_req(npriv, PROG_NFS, 3); + if (ret < 0) { + printf("lookup nfs port failed with %d\n", ret); + goto err2; + } + npriv->nfs_port = ret; } - npriv->nfs_port = ret; + debug("nfs port: %d\n", npriv->nfs_port); ret = nfs_mount_req(npriv); if (ret) { -- 1.8.5.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 9/9] nfs: parse nfsport and mount port from file system options 2014-02-06 16:40 ` [PATCH 9/9] nfs: parse nfsport and mount port from file system options Uwe Kleine-König @ 2014-02-07 6:50 ` Jean-Christophe PLAGNIOL-VILLARD 2014-02-07 8:22 ` Uwe Kleine-König 0 siblings, 1 reply; 20+ messages in thread From: Jean-Christophe PLAGNIOL-VILLARD @ 2014-02-07 6:50 UTC (permalink / raw) To: Uwe Kleine-K??nig; +Cc: barebox On 17:40 Thu 06 Feb , Uwe Kleine-K??nig wrote: > This allows to use unfs3 on the server side which doesn't integrate into > portmap/rpcbind which results in the port not being impossible to lookup > via rpc calls to the portmap program. > > Use it like: > > mount -t nfs -o port=2703,mountport=2703 192.168.77.157:/root /mnt/nfs > > Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> > --- > fs/nfs.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++----------- > 1 file changed, 51 insertions(+), 11 deletions(-) > > diff --git a/fs/nfs.c b/fs/nfs.c > index 8eec63078dd3..50b3744b4551 100644 > --- a/fs/nfs.c > +++ b/fs/nfs.c > @@ -1305,6 +1305,38 @@ static int nfs_stat(struct device_d *dev, const char *filename, struct stat *s) > } > } > > +static void parseopt_hu(const char *options, const char *opt, > + unsigned short *val) > +{ > + const char *start; > + size_t optlen = strlen(opt); > + ulong v; > + char *endp; > + > +again: > + start = strstr(options, opt); > + > + if (!start) > + return; > + > + if (start > options && start[-1] != ',') { > + options = start; > + goto again; > + } > + > + if (start[optlen] != '=') { > + options = start; > + goto again; > + } > + > + v = simple_strtoul(start + optlen + 1, &endp, 0); > + if (v > USHORT_MAX) > + return; > + > + if (*endp == ',' || *endp == '\0') > + *val = v; > +} this should be global > + > static int nfs_probe(struct device_d *dev) > { > struct fs_device_d *fsdev = dev_to_fs_device(dev); > @@ -1340,19 +1372,27 @@ static int nfs_probe(struct device_d *dev) > /* Need a priviliged source port */ > net_udp_bind(npriv->con, 1000); > > - ret = rpc_lookup_req(npriv, PROG_MOUNT, 1); > - if (ret < 0) { > - printf("lookup mount port failed with %d\n", ret); > - goto err2; > + parseopt_hu(fsdev->options, "mountport", &npriv->mount_port); > + if (!npriv->mount_port) { > + ret = rpc_lookup_req(npriv, PROG_MOUNT, 1); > + if (ret < 0) { > + printf("lookup mount port failed with %d\n", ret); > + goto err2; > + } > + npriv->mount_port = ret; > } > - npriv->mount_port = ret; > - > - ret = rpc_lookup_req(npriv, PROG_NFS, 3); > - if (ret < 0) { > - printf("lookup nfs port failed with %d\n", ret); > - goto err2; > + debug("mount port: %hu\n", npriv->mount_port); > + > + parseopt_hu(fsdev->options, "port", &npriv->nfs_port); > + if (!npriv->nfs_port) { > + ret = rpc_lookup_req(npriv, PROG_NFS, 3); > + if (ret < 0) { > + printf("lookup nfs port failed with %d\n", ret); > + goto err2; > + } > + npriv->nfs_port = ret; > } > - npriv->nfs_port = ret; > + debug("nfs port: %d\n", npriv->nfs_port); > > ret = nfs_mount_req(npriv); > if (ret) { > -- > 1.8.5.2 > > > _______________________________________________ > barebox mailing list > barebox@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/barebox _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 9/9] nfs: parse nfsport and mount port from file system options 2014-02-07 6:50 ` Jean-Christophe PLAGNIOL-VILLARD @ 2014-02-07 8:22 ` Uwe Kleine-König 2014-02-07 8:45 ` Jean-Christophe PLAGNIOL-VILLARD 0 siblings, 1 reply; 20+ messages in thread From: Uwe Kleine-König @ 2014-02-07 8:22 UTC (permalink / raw) To: Jean-Christophe PLAGNIOL-VILLARD; +Cc: barebox Hello Jean-Christophe, On Fri, Feb 07, 2014 at 07:50:32AM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote: > > +static void parseopt_hu(const char *options, const char *opt, > > + unsigned short *val) > > +{ > > + const char *start; > > + size_t optlen = strlen(opt); > > + ulong v; > > + char *endp; > > + > > +again: > > + start = strstr(options, opt); > > + > > + if (!start) > > + return; > > + > > + if (start > options && start[-1] != ',') { > > + options = start; > > + goto again; > > + } > > + > > + if (start[optlen] != '=') { > > + options = start; > > + goto again; > > + } > > + > > + v = simple_strtoul(start + optlen + 1, &endp, 0); > > + if (v > USHORT_MAX) > > + return; > > + > > + if (*endp == ',' || *endp == '\0') > > + *val = v; > > +} > > this should be global Yeah, do you have a suggestion where to put it? fs/parseopt.c? Uwe -- Pengutronix e.K. | Uwe Kleine-König | Industrial Linux Solutions | http://www.pengutronix.de/ | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 9/9] nfs: parse nfsport and mount port from file system options 2014-02-07 8:22 ` Uwe Kleine-König @ 2014-02-07 8:45 ` Jean-Christophe PLAGNIOL-VILLARD 2014-02-07 10:06 ` Uwe Kleine-König 0 siblings, 1 reply; 20+ messages in thread From: Jean-Christophe PLAGNIOL-VILLARD @ 2014-02-07 8:45 UTC (permalink / raw) To: Uwe Kleine-K??nig; +Cc: barebox On 09:22 Fri 07 Feb , Uwe Kleine-K??nig wrote: > Hello Jean-Christophe, > > On Fri, Feb 07, 2014 at 07:50:32AM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote: > > > +static void parseopt_hu(const char *options, const char *opt, > > > + unsigned short *val) > > > +{ > > > + const char *start; > > > + size_t optlen = strlen(opt); > > > + ulong v; > > > + char *endp; > > > + > > > +again: > > > + start = strstr(options, opt); > > > + > > > + if (!start) > > > + return; > > > + > > > + if (start > options && start[-1] != ',') { > > > + options = start; > > > + goto again; > > > + } > > > + > > > + if (start[optlen] != '=') { > > > + options = start; > > > + goto again; > > > + } > > > + > > > + v = simple_strtoul(start + optlen + 1, &endp, 0); > > > + if (v > USHORT_MAX) > > > + return; > > > + > > > + if (*endp == ',' || *endp == '\0') > > > + *val = v; > > > +} > > > > this should be global > Yeah, do you have a suggestion where to put it? fs/parseopt.c? why not but IIRC the cmdline parser should be the same too Best Regards, J. > > Uwe > > -- > Pengutronix e.K. | Uwe Kleine-König | > Industrial Linux Solutions | http://www.pengutronix.de/ | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 9/9] nfs: parse nfsport and mount port from file system options 2014-02-07 8:45 ` Jean-Christophe PLAGNIOL-VILLARD @ 2014-02-07 10:06 ` Uwe Kleine-König 0 siblings, 0 replies; 20+ messages in thread From: Uwe Kleine-König @ 2014-02-07 10:06 UTC (permalink / raw) To: Jean-Christophe PLAGNIOL-VILLARD; +Cc: barebox Hello Jean-Christophe, On Fri, Feb 07, 2014 at 09:45:10AM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote: > On 09:22 Fri 07 Feb , Uwe Kleine-K??nig wrote: > > On Fri, Feb 07, 2014 at 07:50:32AM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote: > > > > +static void parseopt_hu(const char *options, const char *opt, > > > > + unsigned short *val) > > > > +{ > > > > + const char *start; > > > > + size_t optlen = strlen(opt); > > > > + ulong v; > > > > + char *endp; > > > > + > > > > +again: > > > > + start = strstr(options, opt); > > > > + > > > > + if (!start) > > > > + return; > > > > + > > > > + if (start > options && start[-1] != ',') { > > > > + options = start; > > > > + goto again; > > > > + } > > > > + > > > > + if (start[optlen] != '=') { > > > > + options = start; > > > > + goto again; > > > > + } > > > > + > > > > + v = simple_strtoul(start + optlen + 1, &endp, 0); > > > > + if (v > USHORT_MAX) > > > > + return; > > > > + > > > > + if (*endp == ',' || *endp == '\0') > > > > + *val = v; > > > > +} > > > > > > this should be global > > Yeah, do you have a suggestion where to put it? fs/parseopt.c? > > why not > > but IIRC the cmdline parser should be the same too "the cmdline parser"? AFAIK there is no cmdline parser for the kernel command line(?) in barebox. And if it were, the latter is ' '-separated while the mount options are ','-separated. This could be abstracted, but I think for now and until we need a linux kernel commandline parser it's fine to hardcode ',' and let it live in fs/. Best regards Uwe -- Pengutronix e.K. | Uwe Kleine-König | Industrial Linux Solutions | http://www.pengutronix.de/ | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2014-02-07 10:23 UTC | newest] Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2014-02-06 16:40 [PATCH 0/9] nfs3 support Uwe Kleine-König 2014-02-06 16:40 ` [PATCH 1/9] net: net_read_uint32: assert that only 32 bit are read Uwe Kleine-König 2014-02-06 16:40 ` [PATCH 2/9] nfs: skip over stale rpc packets Uwe Kleine-König 2014-02-07 8:20 ` Uwe Kleine-König 2014-02-06 16:40 ` [PATCH 3/9] nfs: shorten and simplify rpc_add_credentials a bit Uwe Kleine-König 2014-02-06 16:40 ` [PATCH 4/9] nfs: simplify rpc_lookup_req Uwe Kleine-König 2014-02-06 16:40 ` [PATCH 5/9] nfs: drop an unneeded variable from nfs_do_open() Uwe Kleine-König 2014-02-06 16:40 ` [PATCH 6/9] net: new function net_read_uint64 Uwe Kleine-König 2014-02-07 8:17 ` Uwe Kleine-König 2014-02-06 16:40 ` [PATCH 7/9] mount: support filesystem options passed via -o Uwe Kleine-König 2014-02-06 16:40 ` [PATCH 8/9] nfs: switch to nfs3 Uwe Kleine-König 2014-02-07 6:48 ` Jean-Christophe PLAGNIOL-VILLARD 2014-02-07 8:52 ` Uwe Kleine-König 2014-02-07 9:50 ` Jean-Christophe PLAGNIOL-VILLARD 2014-02-07 10:23 ` Uwe Kleine-König 2014-02-06 16:40 ` [PATCH 9/9] nfs: parse nfsport and mount port from file system options Uwe Kleine-König 2014-02-07 6:50 ` Jean-Christophe PLAGNIOL-VILLARD 2014-02-07 8:22 ` Uwe Kleine-König 2014-02-07 8:45 ` Jean-Christophe PLAGNIOL-VILLARD 2014-02-07 10:06 ` Uwe Kleine-König
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox