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 ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to