svn commit: r235537 - in head: etc/mtree include lib lib/libnandfs lib/libstand sbin sbin/nandfs sbin/newfs_nandfs share/man/man4 share/man/man5 share/mk sys/boot/arm/uboot sys/boot/i386/loader sys...

Grzegorz Bernacki gber at FreeBSD.org
Thu May 17 10:11:19 UTC 2012


Author: gber
Date: Thu May 17 10:11:18 2012
New Revision: 235537
URL: http://svn.freebsd.org/changeset/base/235537

Log:
  Import work done under project/nand (@235533) into head.
  
  The NAND Flash environment consists of several distinct components:
    - NAND framework (drivers harness for NAND controllers and NAND chips)
    - NAND simulator (NANDsim)
    - NAND file system (NAND FS)
    - Companion tools and utilities
    - Documentation (manual pages)
  
  This work is still experimental. Please use with caution.
  
  Obtained from: Semihalf
  Supported by:  FreeBSD Foundation, Juniper Networks

Added:
  head/lib/libnandfs/
  head/lib/libnandfs/Makefile   (contents, props changed)
  head/lib/libnandfs/libnandfs.h   (contents, props changed)
  head/lib/libnandfs/nandfs.c   (contents, props changed)
  head/lib/libstand/nandfs.c   (contents, props changed)
  head/sbin/nandfs/
  head/sbin/nandfs/Makefile   (contents, props changed)
  head/sbin/nandfs/lssnap.c   (contents, props changed)
  head/sbin/nandfs/mksnap.c   (contents, props changed)
  head/sbin/nandfs/nandfs.8   (contents, props changed)
  head/sbin/nandfs/nandfs.c   (contents, props changed)
  head/sbin/nandfs/nandfs.h   (contents, props changed)
  head/sbin/nandfs/rmsnap.c   (contents, props changed)
  head/sbin/newfs_nandfs/
  head/sbin/newfs_nandfs/Makefile   (contents, props changed)
  head/sbin/newfs_nandfs/newfs_nandfs.8   (contents, props changed)
  head/sbin/newfs_nandfs/newfs_nandfs.c   (contents, props changed)
  head/share/man/man4/nand.4   (contents, props changed)
  head/share/man/man4/nandsim.4   (contents, props changed)
  head/share/man/man5/nandfs.5   (contents, props changed)
  head/sys/dev/nand/
  head/sys/dev/nand/nand.c   (contents, props changed)
  head/sys/dev/nand/nand.h   (contents, props changed)
  head/sys/dev/nand/nand_bbt.c   (contents, props changed)
  head/sys/dev/nand/nand_cdev.c   (contents, props changed)
  head/sys/dev/nand/nand_dev.h   (contents, props changed)
  head/sys/dev/nand/nand_ecc_pos.h   (contents, props changed)
  head/sys/dev/nand/nand_generic.c   (contents, props changed)
  head/sys/dev/nand/nand_geom.c   (contents, props changed)
  head/sys/dev/nand/nand_id.c   (contents, props changed)
  head/sys/dev/nand/nand_if.m   (contents, props changed)
  head/sys/dev/nand/nandbus.c   (contents, props changed)
  head/sys/dev/nand/nandbus.h   (contents, props changed)
  head/sys/dev/nand/nandbus_if.m   (contents, props changed)
  head/sys/dev/nand/nandsim.c   (contents, props changed)
  head/sys/dev/nand/nandsim.h   (contents, props changed)
  head/sys/dev/nand/nandsim_chip.c   (contents, props changed)
  head/sys/dev/nand/nandsim_chip.h   (contents, props changed)
  head/sys/dev/nand/nandsim_ctrl.c   (contents, props changed)
  head/sys/dev/nand/nandsim_log.c   (contents, props changed)
  head/sys/dev/nand/nandsim_log.h   (contents, props changed)
  head/sys/dev/nand/nandsim_swap.c   (contents, props changed)
  head/sys/dev/nand/nandsim_swap.h   (contents, props changed)
  head/sys/dev/nand/nfc_if.m   (contents, props changed)
  head/sys/dev/nand/nfc_mv.c   (contents, props changed)
  head/sys/fs/nandfs/
  head/sys/fs/nandfs/bmap.c   (contents, props changed)
  head/sys/fs/nandfs/bmap.h   (contents, props changed)
  head/sys/fs/nandfs/nandfs.h   (contents, props changed)
  head/sys/fs/nandfs/nandfs_alloc.c   (contents, props changed)
  head/sys/fs/nandfs/nandfs_bmap.c   (contents, props changed)
  head/sys/fs/nandfs/nandfs_buffer.c   (contents, props changed)
  head/sys/fs/nandfs/nandfs_cleaner.c   (contents, props changed)
  head/sys/fs/nandfs/nandfs_cpfile.c   (contents, props changed)
  head/sys/fs/nandfs/nandfs_dat.c   (contents, props changed)
  head/sys/fs/nandfs/nandfs_dir.c   (contents, props changed)
  head/sys/fs/nandfs/nandfs_fs.h   (contents, props changed)
  head/sys/fs/nandfs/nandfs_ifile.c   (contents, props changed)
  head/sys/fs/nandfs/nandfs_mount.h   (contents, props changed)
  head/sys/fs/nandfs/nandfs_segment.c   (contents, props changed)
  head/sys/fs/nandfs/nandfs_subr.c   (contents, props changed)
  head/sys/fs/nandfs/nandfs_subr.h   (contents, props changed)
  head/sys/fs/nandfs/nandfs_sufile.c   (contents, props changed)
  head/sys/fs/nandfs/nandfs_vfsops.c   (contents, props changed)
  head/sys/fs/nandfs/nandfs_vnops.c   (contents, props changed)
  head/sys/modules/nandfs/
  head/sys/modules/nandfs/Makefile   (contents, props changed)
  head/sys/modules/nandsim/
  head/sys/modules/nandsim/Makefile   (contents, props changed)
  head/tools/build/options/WITHOUT_NAND   (contents, props changed)
  head/tools/build/options/WITH_NAND   (contents, props changed)
  head/usr.sbin/nandsim/
  head/usr.sbin/nandsim/Makefile   (contents, props changed)
  head/usr.sbin/nandsim/nandsim.8   (contents, props changed)
  head/usr.sbin/nandsim/nandsim.c   (contents, props changed)
  head/usr.sbin/nandsim/nandsim_cfgparse.c   (contents, props changed)
  head/usr.sbin/nandsim/nandsim_cfgparse.h   (contents, props changed)
  head/usr.sbin/nandsim/nandsim_rcfile.c   (contents, props changed)
  head/usr.sbin/nandsim/nandsim_rcfile.h   (contents, props changed)
  head/usr.sbin/nandsim/sample.conf   (contents, props changed)
  head/usr.sbin/nandtool/
  head/usr.sbin/nandtool/Makefile   (contents, props changed)
  head/usr.sbin/nandtool/nand_erase.c   (contents, props changed)
  head/usr.sbin/nandtool/nand_info.c   (contents, props changed)
  head/usr.sbin/nandtool/nand_read.c   (contents, props changed)
  head/usr.sbin/nandtool/nand_readoob.c   (contents, props changed)
  head/usr.sbin/nandtool/nand_write.c   (contents, props changed)
  head/usr.sbin/nandtool/nand_writeoob.c   (contents, props changed)
  head/usr.sbin/nandtool/nandtool.8   (contents, props changed)
  head/usr.sbin/nandtool/nandtool.c   (contents, props changed)
  head/usr.sbin/nandtool/nandtool.h   (contents, props changed)
  head/usr.sbin/nandtool/usage.h   (contents, props changed)
Modified:
  head/etc/mtree/BSD.include.dist
  head/include/Makefile
  head/lib/Makefile
  head/lib/libstand/Makefile
  head/lib/libstand/stand.h
  head/sbin/Makefile
  head/share/man/man4/Makefile
  head/share/man/man5/Makefile
  head/share/mk/bsd.own.mk
  head/sys/boot/arm/uboot/Makefile
  head/sys/boot/arm/uboot/conf.c
  head/sys/boot/arm/uboot/version
  head/sys/boot/i386/loader/Makefile
  head/sys/boot/i386/loader/conf.c
  head/sys/conf/files
  head/sys/conf/options
  head/sys/modules/Makefile
  head/usr.sbin/Makefile

Modified: head/etc/mtree/BSD.include.dist
==============================================================================
--- head/etc/mtree/BSD.include.dist	Thu May 17 08:14:10 2012	(r235536)
+++ head/etc/mtree/BSD.include.dist	Thu May 17 10:11:18 2012	(r235537)
@@ -122,6 +122,8 @@
             mpilib
             ..
         ..
+        nand
+        ..
         ofw
         ..
         pbio
@@ -154,6 +156,8 @@
         ..
         msdosfs
         ..
+        nandfs
+        ..
         nfs
         ..
         ntfs

Modified: head/include/Makefile
==============================================================================
--- head/include/Makefile	Thu May 17 08:14:10 2012	(r235536)
+++ head/include/Makefile	Thu May 17 10:11:18 2012	(r235537)
@@ -43,7 +43,7 @@ LSUBDIRS=	cam/ata cam/scsi \
 	dev/ic dev/iicbus ${_dev_ieee488} dev/io dev/lmc dev/mfi dev/ofw \
 	dev/pbio ${_dev_powermac_nvram} dev/ppbus dev/smbus \
 	dev/speaker dev/usb dev/utopia dev/vkbd dev/wi \
-	fs/devfs fs/fdescfs fs/msdosfs fs/nfs fs/ntfs fs/nullfs \
+	fs/devfs fs/fdescfs fs/msdosfs fs/nandfs fs/nfs fs/ntfs fs/nullfs \
 	${_fs_nwfs} fs/portalfs fs/procfs fs/smbfs fs/udf fs/unionfs \
 	geom/cache geom/concat geom/eli geom/gate geom/journal geom/label \
 	geom/mirror geom/mountver geom/multipath geom/nop \
@@ -157,7 +157,7 @@ copies:
 	done
 .endif
 .endfor
-.for i in ${LDIRS} ${LSUBDIRS:Ndev/acpica:Ndev/bktr} ${LSUBSUBDIRS}
+.for i in ${LDIRS} ${LSUBDIRS:Ndev/acpica:Ndev/bktr:Ndev/nand} ${LSUBSUBDIRS}
 	cd ${.CURDIR}/../sys; \
 	${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 $i/*.h \
 	    ${DESTDIR}${INCLUDEDIR}/$i
@@ -168,6 +168,13 @@ copies:
 	cd ${.CURDIR}/../sys/dev/bktr; \
 	${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ioctl_*.h \
 	    ${DESTDIR}${INCLUDEDIR}/dev/bktr
+.if ${MK_NAND} != "no"
+	cd ${.CURDIR}/../sys/dev/nand; \
+	${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 nandsim.h \
+	    ${DESTDIR}${INCLUDEDIR}/dev/nand; \
+	${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 nand_dev.h \
+	    ${DESTDIR}${INCLUDEDIR}/dev/nand
+.endif
 	cd ${.CURDIR}/../sys/contrib/altq/altq; \
 	${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 *.h \
 	    ${DESTDIR}${INCLUDEDIR}/altq
@@ -224,7 +231,7 @@ symlinks:
 		ln -fs ../../../sys/$i/$$h ${DESTDIR}${INCLUDEDIR}/$i; \
 	done
 .endfor
-.for i in ${LSUBDIRS:Ndev/acpica:Ndev/bktr}
+.for i in ${LSUBDIRS:Ndev/acpica:Ndev/bktr:Ndev/nand}
 	cd ${.CURDIR}/../sys/$i; \
 	for h in *.h; do \
 		ln -fs ../../../../sys/$i/$$h ${DESTDIR}${INCLUDEDIR}/$i; \
@@ -240,6 +247,13 @@ symlinks:
 		ln -fs ../../../../sys/dev/bktr/$$h \
 		    ${DESTDIR}${INCLUDEDIR}/dev/bktr; \
 	done
+.if ${MK_NAND} != "no"
+	cd ${.CURDIR}/../sys/dev/nand; \
+	for h in nandsim.h nand_dev.h; do \
+		ln -fs ../../../../sys/dev/nand/$$h \
+		    ${DESTDIR}${INCLUDEDIR}/dev/nand; \
+	done
+.endif
 .for i in ${LSUBSUBDIRS}
 	cd ${.CURDIR}/../sys/$i; \
 	for h in *.h; do \

Modified: head/lib/Makefile
==============================================================================
--- head/lib/Makefile	Thu May 17 08:14:10 2012	(r235536)
+++ head/lib/Makefile	Thu May 17 10:11:18 2012	(r235537)
@@ -88,6 +88,7 @@ SUBDIR=	${SUBDIR_ORDERED} \
 	libmemstat \
 	${_libmilter} \
 	${_libmp} \
+	${_libnandfs} \
 	${_libncp} \
 	${_libngatm} \
 	libopie \
@@ -175,6 +176,10 @@ _libipx=	libipx
 _libthr=	libthr
 .endif
 
+.if ${MK_NAND} != "no"
+_libnandfs=	libnandfs
+.endif
+
 .if ${MK_NETGRAPH} != "no"
 _libnetgraph=	libnetgraph
 .endif

Added: head/lib/libnandfs/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libnandfs/Makefile	Thu May 17 10:11:18 2012	(r235537)
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+LIB=	nandfs
+SRCS+=	nandfs.c
+INCS=	libnandfs.h
+
+CFLAGS += -I${.CURDIR}
+
+.include <bsd.lib.mk>

Added: head/lib/libnandfs/libnandfs.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libnandfs/libnandfs.h	Thu May 17 10:11:18 2012	(r235537)
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 2010-2012 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef	_LIBNANDFS_NANDFS_H
+#define	_LIBNANDFS_NANDFS_H
+
+struct nandfs {
+	struct nandfs_fsdata		n_fsdata;
+	struct nandfs_super_block	n_sb;
+	char				n_ioc[MNAMELEN];
+	char				n_dev[MNAMELEN];
+	int				n_iocfd;
+	int				n_devfd;
+	int				n_flags;
+	char				n_errmsg[120];
+};
+
+int nandfs_iserror(struct nandfs *);
+const char *nandfs_errmsg(struct nandfs *);
+
+void nandfs_init(struct nandfs *, const char *);
+void nandfs_destroy(struct nandfs *);
+
+const char *nandfs_dev(struct nandfs *);
+
+int nandfs_open(struct nandfs *);
+void nandfs_close(struct nandfs *);
+
+int nandfs_get_cpstat(struct nandfs *, struct nandfs_cpstat *);
+
+ssize_t nandfs_get_cp(struct nandfs *, uint64_t,
+    struct nandfs_cpinfo *, size_t);
+
+ssize_t nandfs_get_snap(struct nandfs *, uint64_t,
+    struct nandfs_cpinfo *, size_t);
+
+int nandfs_make_snap(struct nandfs *, uint64_t *);
+int nandfs_delete_snap(struct nandfs *, uint64_t);
+
+#endif	/* _LIBNANDFS_NANDFS_H */

Added: head/lib/libnandfs/nandfs.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libnandfs/nandfs.c	Thu May 17 10:11:18 2012	(r235537)
@@ -0,0 +1,247 @@
+/*-
+ * Copyright (c) 2010-2012 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/stdint.h>
+#include <sys/ucred.h>
+#include <sys/disk.h>
+#include <sys/mount.h>
+
+#include <fs/nandfs/nandfs_fs.h>
+#include <libnandfs.h>
+
+#define	NANDFS_IS_VALID		0x1
+#define	NANDFS_IS_OPENED	0x2
+#define	NANDFS_IS_OPENED_DEV	0x4
+#define	NANDFS_IS_ERROR		0x8
+
+#define DEBUG
+#undef DEBUG
+#ifdef DEBUG
+#define NANDFS_DEBUG(fmt, args...) do { \
+    printf("libnandfs:" fmt "\n", ##args); } while (0)
+#else
+#define NANDFS_DEBUG(fmt, args...)
+#endif
+
+#define	NANDFS_ASSERT_VALID(fs)		assert((fs)->n_flags & NANDFS_IS_VALID)
+#define	NANDFS_ASSERT_VALID_DEV(fs)	\
+	assert(((fs)->n_flags & (NANDFS_IS_VALID | NANDFS_IS_OPENED_DEV)) == \
+	    (NANDFS_IS_VALID | NANDFS_IS_OPENED_DEV))
+
+int
+nandfs_iserror(struct nandfs *fs)
+{
+
+	NANDFS_ASSERT_VALID(fs);
+
+	return (fs->n_flags & NANDFS_IS_ERROR);
+}
+
+const char *
+nandfs_errmsg(struct nandfs *fs)
+{
+
+	NANDFS_ASSERT_VALID(fs);
+
+	assert(nandfs_iserror(fs));
+	assert(fs->n_errmsg);
+	return (fs->n_errmsg);
+}
+
+static void
+nandfs_seterr(struct nandfs *fs, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	vsnprintf(fs->n_errmsg, sizeof(fs->n_errmsg), fmt, ap);
+	va_end(ap);
+	fs->n_flags |= NANDFS_IS_ERROR;
+}
+
+const char *
+nandfs_dev(struct nandfs *fs)
+{
+
+	NANDFS_ASSERT_VALID(fs);
+	return (fs->n_dev);
+}
+
+void
+nandfs_init(struct nandfs *fs, const char *dir)
+{
+
+	snprintf(fs->n_ioc, sizeof(fs->n_ioc), "%s/%s", dir, ".");
+	fs->n_iocfd = -1;
+	fs->n_flags = NANDFS_IS_VALID;
+}
+
+void
+nandfs_destroy(struct nandfs *fs)
+{
+
+	assert(fs->n_iocfd == -1);
+	fs->n_flags &=
+	    ~(NANDFS_IS_ERROR | NANDFS_IS_VALID);
+	assert(fs->n_flags == 0);
+}
+
+int
+nandfs_open(struct nandfs *fs)
+{
+	struct nandfs_fsinfo fsinfo;
+
+	fs->n_flags |= NANDFS_IS_OPENED;
+
+	fs->n_iocfd = open(fs->n_ioc, O_RDONLY, S_IRUSR | S_IWUSR | S_IRGRP |
+	    S_IWGRP | S_IROTH | S_IWOTH);
+	if (fs->n_iocfd == -1) {
+		nandfs_seterr(fs, "couldn't open %s: %s", fs->n_ioc,
+		    strerror(errno));
+		return (-1);
+	}
+
+	if (ioctl(fs->n_iocfd, NANDFS_IOCTL_GET_FSINFO, &fsinfo) == -1) {
+		nandfs_seterr(fs, "couldn't fetch fsinfo: %s",
+		    strerror(errno));
+		return (-1);
+	}
+
+	memcpy(&fs->n_fsdata, &fsinfo.fs_fsdata, sizeof(fs->n_fsdata));
+	memcpy(&fs->n_sb, &fsinfo.fs_super, sizeof(fs->n_sb));
+	snprintf(fs->n_dev, sizeof(fs->n_dev), "%s", fsinfo.fs_dev);
+
+	return (0);
+}
+
+void
+nandfs_close(struct nandfs *fs)
+{
+
+	NANDFS_ASSERT_VALID(fs);
+	assert(fs->n_flags & NANDFS_IS_OPENED);
+
+	close(fs->n_iocfd);
+	fs->n_iocfd = -1;
+	fs->n_flags &= ~NANDFS_IS_OPENED;
+}
+
+int
+nandfs_get_cpstat(struct nandfs *fs, struct nandfs_cpstat *cpstat)
+{
+
+	NANDFS_ASSERT_VALID(fs);
+
+	if (ioctl(fs->n_iocfd, NANDFS_IOCTL_GET_CPSTAT, cpstat) == -1) {
+		nandfs_seterr(fs, "ioctl NANDFS_IOCTL_GET_CPSTAT: %s",
+		    strerror(errno));
+		return (-1);
+	}
+
+	return (0);
+}
+
+static ssize_t
+nandfs_get_cpinfo(struct nandfs *fs, uint64_t cno, int mode,
+    struct nandfs_cpinfo *cpinfo, size_t nci)
+{
+	struct nandfs_argv args;
+
+	NANDFS_ASSERT_VALID(fs);
+
+	args.nv_base = (u_long)cpinfo;
+	args.nv_nmembs = nci;
+	args.nv_index = cno;
+	args.nv_flags = mode;
+
+	if (ioctl(fs->n_iocfd, NANDFS_IOCTL_GET_CPINFO, &args) == -1) {
+		nandfs_seterr(fs, "ioctl NANDFS_IOCTL_GET_CPINFO: %s",
+		    strerror(errno));
+		return (-1);
+	}
+
+	return (args.nv_nmembs);
+}
+
+ssize_t
+nandfs_get_cp(struct nandfs *fs, uint64_t cno, struct nandfs_cpinfo *cpinfo,
+    size_t nci)
+{
+
+	return (nandfs_get_cpinfo(fs, cno, NANDFS_CHECKPOINT, cpinfo, nci));
+}
+
+ssize_t
+nandfs_get_snap(struct nandfs *fs, uint64_t cno, struct nandfs_cpinfo *cpinfo,
+    size_t nci)
+{
+
+	return (nandfs_get_cpinfo(fs, cno, NANDFS_SNAPSHOT, cpinfo, nci));
+}
+
+int
+nandfs_make_snap(struct nandfs *fs, uint64_t *cno)
+{
+
+	NANDFS_ASSERT_VALID(fs);
+
+	if (ioctl(fs->n_iocfd, NANDFS_IOCTL_MAKE_SNAP, cno) == -1) {
+		nandfs_seterr(fs, "ioctl NANDFS_IOCTL_MAKE_SNAP: %s",
+		    strerror(errno));
+		return (-1);
+	}
+
+	return (0);
+}
+
+int
+nandfs_delete_snap(struct nandfs *fs, uint64_t cno)
+{
+
+	NANDFS_ASSERT_VALID(fs);
+
+	if (ioctl(fs->n_iocfd, NANDFS_IOCTL_DELETE_SNAP, &cno) == -1) {
+		nandfs_seterr(fs, "ioctl NANDFS_IOCTL_DELETE_SNAP: %s",
+		    strerror(errno));
+		return (-1);
+	}
+
+	return (0);
+}

Modified: head/lib/libstand/Makefile
==============================================================================
--- head/lib/libstand/Makefile	Thu May 17 08:14:10 2012	(r235536)
+++ head/lib/libstand/Makefile	Thu May 17 10:11:18 2012	(r235537)
@@ -150,6 +150,9 @@ SRCS+=	bootp.c rarp.c bootparam.c
 SRCS+=	ufs.c nfs.c cd9660.c tftp.c gzipfs.c bzipfs.c
 SRCS+=	dosfs.c ext2fs.c
 SRCS+=	splitfs.c
+.if ${MK_NAND} != "no"
+SRCS+=	nandfs.c
+.endif
 
 .include <bsd.lib.mk>
 

Added: head/lib/libstand/nandfs.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libstand/nandfs.c	Thu May 17 10:11:18 2012	(r235537)
@@ -0,0 +1,1041 @@
+/*-
+ * Copyright (c) 2010-2012 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/stdint.h>
+#include <ufs/ufs/dinode.h>
+#include <fs/nandfs/nandfs_fs.h>
+#include "stand.h"
+#include "string.h"
+#include "zlib.h"
+
+#define DEBUG
+#undef DEBUG
+#ifdef DEBUG
+#define NANDFS_DEBUG(fmt, args...) do { \
+    printf("NANDFS_DEBUG:" fmt "\n", ##args); } while (0)
+#else
+#define NANDFS_DEBUG(fmt, args...)
+#endif
+
+struct nandfs_mdt {
+	uint32_t	entries_per_block;
+	uint32_t	entries_per_group;
+	uint32_t	blocks_per_group;
+	uint32_t	groups_per_desc_block;	/* desc is super group */
+	uint32_t	blocks_per_desc_block;	/* desc is super group */
+};
+
+struct bmap_buf {
+	LIST_ENTRY(bmap_buf)	list;
+	nandfs_daddr_t		blknr;
+	uint64_t		*map;
+};
+
+struct nandfs_node {
+	struct nandfs_inode	*inode;
+	LIST_HEAD(, bmap_buf)	bmap_bufs;
+};
+struct nandfs {
+	int	nf_blocksize;
+	int	nf_sectorsize;
+	int	nf_cpno;
+
+	struct open_file	*nf_file;
+	struct nandfs_node	*nf_opened_node;
+	u_int			nf_offset;
+	uint8_t			*nf_buf;
+	int64_t			nf_buf_blknr;
+
+	struct nandfs_fsdata		*nf_fsdata;
+	struct nandfs_super_block	*nf_sb;
+	struct nandfs_segment_summary	nf_segsum;
+	struct nandfs_checkpoint	nf_checkpoint;
+	struct nandfs_super_root	nf_sroot;
+	struct nandfs_node		nf_ifile;
+	struct nandfs_node		nf_datfile;
+	struct nandfs_node		nf_cpfile;
+	struct nandfs_mdt		nf_datfile_mdt;
+	struct nandfs_mdt		nf_ifile_mdt;
+
+	int nf_nindir[NIADDR];
+};
+
+static int nandfs_open(const char *, struct open_file *);
+static int nandfs_close(struct open_file *);
+static int nandfs_read(struct open_file *, void *, size_t, size_t *);
+static off_t nandfs_seek(struct open_file *, off_t, int);
+static int nandfs_stat(struct open_file *, struct stat *);
+static int nandfs_readdir(struct open_file *, struct dirent *);
+
+static int nandfs_buf_read(struct nandfs *, char **, size_t *);
+static struct nandfs_node *nandfs_lookup_inode(struct nandfs *, nandfs_daddr_t);
+static struct nandfs_node *nandfs_lookup_path(struct nandfs *, const char *);
+static int nandfs_read_inode(struct nandfs *, struct nandfs_node *,
+    nandfs_lbn_t, u_int, void *, int);
+static int nandfs_read_blk(struct nandfs *, nandfs_daddr_t, void *, int);
+static int nandfs_bmap_lookup(struct nandfs *, struct nandfs_node *,
+    nandfs_lbn_t, nandfs_daddr_t *, int);
+static int nandfs_get_checkpoint(struct nandfs *, uint64_t,
+    struct nandfs_checkpoint *);
+static nandfs_daddr_t nandfs_vtop(struct nandfs *, nandfs_daddr_t);
+static void nandfs_calc_mdt_consts(int, struct nandfs_mdt *, int);
+static void nandfs_mdt_trans(struct nandfs_mdt *, uint64_t,
+    nandfs_daddr_t *, uint32_t *);
+static int ioread(struct open_file *, off_t, void *, u_int);
+static int nandfs_probe_sectorsize(struct open_file *);
+
+struct fs_ops nandfs_fsops = {
+	"nandfs",
+	nandfs_open,
+	nandfs_close,
+	nandfs_read,
+	null_write,
+	nandfs_seek,
+	nandfs_stat,
+	nandfs_readdir
+};
+
+#define	NINDIR(fs)	((fs)->nf_blocksize / sizeof(nandfs_daddr_t))
+
+static int
+nandfs_check_fsdata_crc(struct nandfs_fsdata *fsdata)
+{
+	uint32_t fsdata_crc, comp_crc;
+
+	if (fsdata->f_magic != NANDFS_FSDATA_MAGIC)
+		return (0);
+
+	/* Preserve crc */
+	fsdata_crc = fsdata->f_sum;
+
+	/* Calculate */
+	fsdata->f_sum = (0);
+	comp_crc = crc32(0, (uint8_t *)fsdata, fsdata->f_bytes);
+
+	/* Restore */
+	fsdata->f_sum = fsdata_crc;
+
+	/* Check CRC */
+	return (fsdata_crc == comp_crc);
+}
+
+static int
+nandfs_check_superblock_crc(struct nandfs_fsdata *fsdata,
+    struct nandfs_super_block *super)
+{
+	uint32_t super_crc, comp_crc;
+
+	/* Check super block magic */
+	if (super->s_magic != NANDFS_SUPER_MAGIC)
+		return (0);
+
+	/* Preserve CRC */
+	super_crc = super->s_sum;
+
+	/* Calculate */
+	super->s_sum = (0);
+	comp_crc = crc32(0, (uint8_t *)super, fsdata->f_sbbytes);
+
+	/* Restore */
+	super->s_sum = super_crc;
+
+	/* Check CRC */
+	return (super_crc == comp_crc);
+}
+
+static int
+nandfs_find_super_block(struct nandfs *fs, struct open_file *f)
+{
+	struct nandfs_super_block *sb;
+	int i, j, n;
+	int sectors_to_read, error;
+
+	sb = malloc(fs->nf_sectorsize);
+	if (sb == NULL)
+		return (ENOMEM);
+
+	memset(fs->nf_sb, 0, sizeof(*fs->nf_sb));
+
+	sectors_to_read = (NANDFS_NFSAREAS * fs->nf_fsdata->f_erasesize) /
+	    fs->nf_sectorsize;
+	for (i = 0; i < sectors_to_read; i++) {
+		NANDFS_DEBUG("reading i %d offset %d\n", i,
+		    i * fs->nf_sectorsize);
+		error = ioread(f, i * fs->nf_sectorsize, (char *)sb,
+		    fs->nf_sectorsize);
+		if (error) {
+			NANDFS_DEBUG("error %d\n", error);
+			continue;
+		}
+		n = fs->nf_sectorsize / sizeof(struct nandfs_super_block);
+		if ((i * fs->nf_sectorsize) % fs->nf_fsdata->f_erasesize == 0) {
+			if (fs->nf_sectorsize == sizeof(struct nandfs_fsdata))
+				continue;
+			else {
+				sb += (sizeof(struct nandfs_fsdata) /
+				    sizeof(struct nandfs_super_block));
+				n -= (sizeof(struct nandfs_fsdata) /
+				    sizeof(struct nandfs_super_block));
+			}
+		}
+
+		for (j = 0; j < n; j++) {
+			if (!nandfs_check_superblock_crc(fs->nf_fsdata, &sb[j]))
+				continue;
+			NANDFS_DEBUG("magic %x wtime %jd\n", sb->s_magic,
+			    sb->s_wtime);
+			if (sb[j].s_wtime > fs->nf_sb->s_wtime)
+				memcpy(fs->nf_sb, &sb[j], sizeof(*fs->nf_sb));
+		}
+	}
+
+	free(sb);
+
+	return (fs->nf_sb->s_magic != 0 ? 0 : EINVAL);
+}
+
+static int
+nandfs_find_fsdata(struct nandfs *fs, struct open_file *f)
+{
+	int offset, error, i;
+
+	NANDFS_DEBUG("starting\n");
+
+	offset = 0;
+	for (i = 0; i < 64 * NANDFS_NFSAREAS; i++) {
+		error = ioread(f, offset, (char *)fs->nf_fsdata,
+		    sizeof(struct nandfs_fsdata));
+		if (error)
+			return (error);
+		if (fs->nf_fsdata->f_magic == NANDFS_FSDATA_MAGIC) {
+			NANDFS_DEBUG("found at %x, volume %s\n", offset,
+			    fs->nf_fsdata->f_volume_name);
+			if (nandfs_check_fsdata_crc(fs->nf_fsdata))
+				break;
+		}
+		offset += fs->nf_sectorsize;
+	}
+
+	return (error);
+}
+
+static int
+nandfs_read_structures(struct nandfs *fs, struct open_file *f)
+{
+	int error;
+
+	error = nandfs_find_fsdata(fs, f);
+	if (error)
+		return (error);
+
+	error = nandfs_find_super_block(fs, f);
+
+	if (error == 0)
+		NANDFS_DEBUG("selected sb with w_time %jd last_pseg %jx\n",
+		    fs->nf_sb->s_wtime, fs->nf_sb->s_last_pseg);
+
+	return (error);
+}
+
+static int
+nandfs_mount(struct nandfs *fs, struct open_file *f)
+{
+	int err = 0, level;
+	uint64_t last_pseg;
+
+	fs->nf_fsdata = malloc(sizeof(struct nandfs_fsdata));
+	fs->nf_sb = malloc(sizeof(struct nandfs_super_block));
+
+	err = nandfs_read_structures(fs, f);
+	if (err) {
+		free(fs->nf_fsdata);
+		free(fs->nf_sb);
+		return (err);
+	}
+
+	fs->nf_blocksize = 1 << (fs->nf_fsdata->f_log_block_size + 10);
+
+	NANDFS_DEBUG("using superblock with wtime %jd\n", fs->nf_sb->s_wtime);
+
+	fs->nf_cpno = fs->nf_sb->s_last_cno;
+	last_pseg = fs->nf_sb->s_last_pseg;
+
+	/*
+	 * Calculate indirect block levels.
+	 */
+	nandfs_daddr_t mult;
+
+	mult = 1;
+	for (level = 0; level < NIADDR; level++) {
+		mult *= NINDIR(fs);
+		fs->nf_nindir[level] = mult;
+	}
+
+	nandfs_calc_mdt_consts(fs->nf_blocksize, &fs->nf_datfile_mdt,
+	    fs->nf_fsdata->f_dat_entry_size);
+
+	nandfs_calc_mdt_consts(fs->nf_blocksize, &fs->nf_ifile_mdt,
+	    fs->nf_fsdata->f_inode_size);
+
+	err = ioread(f, last_pseg * fs->nf_blocksize, &fs->nf_segsum,
+	    sizeof(struct nandfs_segment_summary));
+	if (err) {
+		free(fs->nf_sb);
+		free(fs->nf_fsdata);
+		return (err);
+	}
+
+	err = ioread(f, (last_pseg + fs->nf_segsum.ss_nblocks - 1) *
+	    fs->nf_blocksize, &fs->nf_sroot, sizeof(struct nandfs_super_root));
+	if (err) {
+		free(fs->nf_sb);
+		free(fs->nf_fsdata);
+		return (err);
+	}
+
+	fs->nf_datfile.inode = &fs->nf_sroot.sr_dat;
+	LIST_INIT(&fs->nf_datfile.bmap_bufs);
+	fs->nf_cpfile.inode = &fs->nf_sroot.sr_cpfile;
+	LIST_INIT(&fs->nf_cpfile.bmap_bufs);
+
+	err = nandfs_get_checkpoint(fs, fs->nf_cpno, &fs->nf_checkpoint);
+	if (err) {
+		free(fs->nf_sb);
+		free(fs->nf_fsdata);
+		return (err);
+	}
+
+	NANDFS_DEBUG("checkpoint cp_cno=%lld\n", fs->nf_checkpoint.cp_cno);
+	NANDFS_DEBUG("checkpoint cp_inodes_count=%lld\n",
+	    fs->nf_checkpoint.cp_inodes_count);
+	NANDFS_DEBUG("checkpoint cp_ifile_inode.i_blocks=%lld\n",
+	    fs->nf_checkpoint.cp_ifile_inode.i_blocks);
+
+	fs->nf_ifile.inode = &fs->nf_checkpoint.cp_ifile_inode;
+	LIST_INIT(&fs->nf_ifile.bmap_bufs);
+	return (0);
+}
+
+#define NINDIR(fs)	((fs)->nf_blocksize / sizeof(nandfs_daddr_t))
+
+static int
+nandfs_open(const char *path, struct open_file *f)
+{
+	struct nandfs *fs;
+	struct nandfs_node *node;
+	int err, bsize, level;
+
+	NANDFS_DEBUG("nandfs_open('%s', %p)\n", path, f);
+
+	fs = malloc(sizeof(struct nandfs));
+	f->f_fsdata = fs;
+	fs->nf_file = f;
+
+	bsize = nandfs_probe_sectorsize(f);
+	if (bsize < 0) {
+		printf("Cannot probe medium sector size\n");
+		return (EINVAL);
+	}
+
+	fs->nf_sectorsize = bsize;
+
+	/*
+	 * Calculate indirect block levels.
+	 */
+	nandfs_daddr_t mult;
+
+	mult = 1;
+	for (level = 0; level < NIADDR; level++) {
+		mult *= NINDIR(fs);
+		fs->nf_nindir[level] = mult;
+	}
+
+	NANDFS_DEBUG("fs %p nf_sectorsize=%x\n", fs, fs->nf_sectorsize);
+
+	err = nandfs_mount(fs, f);
+	if (err) {
+		NANDFS_DEBUG("Cannot mount nandfs: %s\n", strerror(err));
+		return (err);
+	}
+
+	node = nandfs_lookup_path(fs, path);
+	if (node == NULL)
+		return (EINVAL);
+
+	fs->nf_offset = 0;
+	fs->nf_buf = NULL;
+	fs->nf_buf_blknr = -1;
+	fs->nf_opened_node = node;
+	LIST_INIT(&fs->nf_opened_node->bmap_bufs);
+	return (0);
+}
+
+static int
+nandfs_free_node(struct nandfs_node *node)
+{
+	struct bmap_buf *bmap, *tmp;
+
+	free(node->inode);
+	LIST_FOREACH_SAFE(bmap, &node->bmap_bufs, list, tmp) {
+		LIST_REMOVE(bmap, list);
+		free(bmap->map);
+		free(bmap);
+	}
+	free(node);
+}
+
+static int
+nandfs_close(struct open_file *f)
+{
+	struct nandfs *fs = f->f_fsdata;
+
+	NANDFS_DEBUG("nandfs_close(%p)\n", f);
+
+	if (fs->nf_buf != NULL)
+		free(fs->nf_buf);
+
+	nandfs_free_node(fs->nf_opened_node);
+	free(fs->nf_sb);
+	free(fs);
+}
+
+static int
+nandfs_read(struct open_file *f, void *addr, size_t size, size_t *resid)
+{
+	struct nandfs *fs = (struct nandfs *)f->f_fsdata;
+	size_t csize, buf_size;
+	uint8_t *buf;
+	int error = 0;
+
+	NANDFS_DEBUG("nandfs_read(file=%p, addr=%p, size=%d)\n", f, addr, size);
+
+	while (size != 0) {
+		if (fs->nf_offset >= fs->nf_opened_node->inode->i_size)
+			break;
+
+		error = nandfs_buf_read(fs, (void *)&buf, &buf_size);
+		if (error)
+			break;
+
+		csize = size;
+		if (csize > buf_size)
+			csize = buf_size;
+
+		bcopy(buf, addr, csize);
+
+		fs->nf_offset += csize;
+		addr = (char *)addr + csize;
+		size -= csize;
+	}
+
+	if (resid)
+		*resid = size;
+	return (error);
+}
+
+static off_t
+nandfs_seek(struct open_file *f, off_t offset, int where)
+{
+	struct nandfs *fs = f->f_fsdata;
+	off_t off;
+	u_int size;
+
+	NANDFS_DEBUG("nandfs_seek(file=%p, offset=%lld, where=%d)\n", f,
+	    offset, where);
+
+	size = fs->nf_opened_node->inode->i_size;
+
+	switch (where) {
+	case SEEK_SET:
+		off = 0;
+		break;
+	case SEEK_CUR:
+		off = fs->nf_offset;
+		break;
+	case SEEK_END:
+		off = size;
+		break;
+	default:
+		errno = EINVAL;
+		return (-1);
+	}
+
+	off += offset;
+	if (off < 0 || off > size) {
+		errno = EINVAL;
+		return(-1);
+	}
+
+	fs->nf_offset = (u_int)off;
+
+	return (off);
+}
+
+static int
+nandfs_stat(struct open_file *f, struct stat *sb)
+{
+	struct nandfs *fs = f->f_fsdata;
+
+	NANDFS_DEBUG("nandfs_stat(file=%p, stat=%p)\n", f, sb);
+
+	sb->st_size = fs->nf_opened_node->inode->i_size;
+	sb->st_mode = fs->nf_opened_node->inode->i_mode;
+	sb->st_uid = fs->nf_opened_node->inode->i_uid;
+	sb->st_gid = fs->nf_opened_node->inode->i_gid;
+	return (0);
+}
+
+static int
+nandfs_readdir(struct open_file *f, struct dirent *d)
+{
+	struct nandfs *fs = f->f_fsdata;
+	struct nandfs_dir_entry *dirent;
+	uint8_t *buf;
+	size_t buf_size;
+
+	NANDFS_DEBUG("nandfs_readdir(file=%p, dirent=%p)\n", f, d);
+
+	if (fs->nf_offset >= fs->nf_opened_node->inode->i_size) {
+		NANDFS_DEBUG("nandfs_readdir(file=%p, dirent=%p) ENOENT\n",
+		    f, d);
+		return (ENOENT);
+	}
+
+	if (nandfs_buf_read(fs, (void *)&buf, &buf_size)) {
+		NANDFS_DEBUG("nandfs_readdir(file=%p, dirent=%p)"
+		    "buf_read failed\n", f, d);
+		return (EIO);
+	}
+
+	NANDFS_DEBUG("nandfs_readdir(file=%p, dirent=%p) moving forward\n",
+	    f, d);
+
+	dirent = (struct nandfs_dir_entry *)buf;
+	fs->nf_offset += dirent->rec_len;
+	strncpy(d->d_name, dirent->name, dirent->name_len);
+	d->d_name[dirent->name_len] = '\0';
+	d->d_type = dirent->file_type;
+	return (0);
+}
+
+static int
+nandfs_buf_read(struct nandfs *fs, char **buf_p, size_t *size_p)
+{
+	nandfs_daddr_t blknr, blkoff;
+
+	blknr = fs->nf_offset / fs->nf_blocksize;
+	blkoff = fs->nf_offset % fs->nf_blocksize;
+
+	if (blknr != fs->nf_buf_blknr) {

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list