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-head
mailing list