From owner-svn-src-projects@FreeBSD.ORG Sat Mar 17 03:02:11 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 525D7106564A; Sat, 17 Mar 2012 03:02:11 +0000 (UTC) (envelope-from gber@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 408058FC0A; Sat, 17 Mar 2012 03:02:11 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q2H32BgE047237; Sat, 17 Mar 2012 03:02:11 GMT (envelope-from gber@svn.freebsd.org) Received: (from gber@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q2H32BJ1047232; Sat, 17 Mar 2012 03:02:11 GMT (envelope-from gber@svn.freebsd.org) Message-Id: <201203170302.q2H32BJ1047232@svn.freebsd.org> From: Grzegorz Bernacki Date: Sat, 17 Mar 2012 03:02:10 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r233071 - in projects/nand/lib: . libnandfs X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 17 Mar 2012 03:02:11 -0000 Author: gber Date: Sat Mar 17 03:02:10 2012 New Revision: 233071 URL: http://svn.freebsd.org/changeset/base/233071 Log: Add NANDFS library. Obtained from: Semihalf Supported by: FreeBSD Foundation, Juniper Networks Added: projects/nand/lib/libnandfs/ projects/nand/lib/libnandfs/Makefile projects/nand/lib/libnandfs/libnandfs.h projects/nand/lib/libnandfs/nandfs.c Modified: projects/nand/lib/Makefile Modified: projects/nand/lib/Makefile ============================================================================== --- projects/nand/lib/Makefile Sat Mar 17 03:00:51 2012 (r233070) +++ projects/nand/lib/Makefile Sat Mar 17 03:02:10 2012 (r233071) @@ -85,6 +85,7 @@ SUBDIR= ${SUBDIR_ORDERED} \ libmemstat \ ${_libmilter} \ ${_libmp} \ + ${_libnandfs} \ ${_libncp} \ ${_libngatm} \ libopie \ @@ -171,6 +172,10 @@ _libipx= libipx _libthr= libthr .endif +.if ${MK_NAND} != "no" +_libnandfs= libnandfs +.endif + .if ${MK_NETGRAPH} != "no" _libnetgraph= libnetgraph .endif Added: projects/nand/lib/libnandfs/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/nand/lib/libnandfs/Makefile Sat Mar 17 03:02:10 2012 (r233071) @@ -0,0 +1,7 @@ +LIB= nandfs +SRCS+= nandfs.c +INCS= libnandfs.h + +CFLAGS += -I${.CURDIR} + +.include Added: projects/nand/lib/libnandfs/libnandfs.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/nand/lib/libnandfs/libnandfs.h Sat Mar 17 03:02:10 2012 (r233071) @@ -0,0 +1,72 @@ +/*- + * 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 *); + +int nandfs_cleanerd_set(struct nandfs *); +int nandfs_cleanerd_unset(struct nandfs *); + +const char *nandfs_dev(struct nandfs *); + +int nandfs_open(struct nandfs *); +int nandfs_open_rw(struct nandfs *); +int nandfs_open_dev(struct nandfs *); +void nandfs_close(struct nandfs *); +void nandfs_close_dev(struct nandfs *); + +int nandfs_lock(struct nandfs *, int write); +int nandfs_unlock(struct nandfs *); + +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: projects/nand/lib/libnandfs/nandfs.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/nand/lib/libnandfs/nandfs.c Sat Mar 17 03:02:10 2012 (r233071) @@ -0,0 +1,379 @@ +/*- + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define NANDFS_IS_VALID 0x1 +#define NANDFS_IS_OPENED 0x2 +#define NANDFS_IS_OPENED_DEV 0x4 +#define NANDFS_IS_ERROR 0x8 +#define NANDFS_IS_LOCKED 0x10 +#define NANDFS_IS_READONLY 0x20 + +#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)) +#define NANDFS_ASSERT_RDWR(fs) \ + assert(!((fs)->n_flags & NANDFS_IS_READONLY)) +#define NANDFS_ASSERT_LOCKED(fs) \ + assert((fs)->n_flags & NANDFS_IS_LOCKED) +#define NANDFS_ASSERT_UNLOCKED(fs) \ + assert(!((fs)->n_flags & NANDFS_IS_LOCKED)) + +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; +} + +int +nandfs_cleanerd_set(struct nandfs *fs) +{ + + NANDFS_ASSERT_VALID_DEV(fs); + + if (ioctl(fs->n_iocfd, NANDFS_IOCTL_CLEANERD_SET) == -1) { + nandfs_seterr(fs, "%s", strerror(errno)); + return (-1); + } + + return (0); +} + +int +nandfs_cleanerd_unset(struct nandfs *fs) +{ + + NANDFS_ASSERT_VALID_DEV(fs); + + if (ioctl(fs->n_iocfd, NANDFS_IOCTL_CLEANERD_UNSET) == -1) { + nandfs_seterr(fs, "%s", strerror(errno)); + return (-1); + } + + return (0); +} + +int +nandfs_lock(struct nandfs *fs, int rdwr) +{ + struct flock lck; + int error; + + NANDFS_ASSERT_VALID(fs); + NANDFS_ASSERT_RDWR(fs); + NANDFS_ASSERT_UNLOCKED(fs); + + lck.l_type = (rdwr ? F_WRLCK : F_RDLCK); + lck.l_start = 0; + lck.l_whence = SEEK_SET; + lck.l_len = 1; + + error = fcntl(fs->n_iocfd, F_SETLKW, &lck); + if (error == -1) { + nandfs_seterr(fs, "couldn't lock %s: %s", fs->n_ioc, + strerror(errno)); + return (-1); + } + + fs->n_flags |= NANDFS_IS_LOCKED; + + return (0); +} + +int +nandfs_unlock(struct nandfs *fs) +{ + struct flock lck; + int error; + + NANDFS_ASSERT_VALID(fs); + NANDFS_ASSERT_RDWR(fs); + NANDFS_ASSERT_LOCKED(fs); + + lck.l_type = F_UNLCK; + lck.l_start = 0; + lck.l_whence = SEEK_SET; + lck.l_len = 1; + + error = fcntl(fs->n_iocfd, F_SETLK, &lck); + if (error == -1) { + nandfs_seterr(fs, "couldn't unlock %s: %s", fs->n_ioc, + strerror(errno)); + return (-1); + } + + fs->n_flags &= ~NANDFS_IS_LOCKED; + + return (0); +} + +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, ".nandfs"); + 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 | NANDFS_IS_READONLY); + assert(fs->n_flags == 0); +} + +static int +_nandfs_open(struct nandfs *fs, int rdwr) +{ + struct nandfs_fsinfo fsinfo; + int flags; + + fs->n_flags |= NANDFS_IS_OPENED; + + if (rdwr) + flags = O_RDWR; + else { + fs->n_flags |= NANDFS_IS_READONLY; + flags = O_RDONLY; + } + + fs->n_iocfd = open(fs->n_ioc, flags, 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), fsinfo.fs_dev); + + return (0); +} + +int +nandfs_open(struct nandfs *fs) +{ + + return (_nandfs_open(fs, 0)); +} + +int +nandfs_open_rw(struct nandfs *fs) +{ + + return (_nandfs_open(fs, 1)); +} + +int +nandfs_open_dev(struct nandfs *fs) +{ + + fs->n_flags |= NANDFS_IS_OPENED_DEV; + + if (nandfs_open_rw(fs) == -1) + return (-1); + + fs->n_devfd = open(fs->n_dev, O_RDONLY); + if (fs->n_devfd == -1) { + nandfs_seterr(fs, "couldn't open %s: %s", fs->n_dev, + strerror(errno)); + return (-1); + } + + 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; +} + +void +nandfs_close_dev(struct nandfs *fs) +{ + + assert(fs->n_flags & NANDFS_IS_OPENED_DEV); + + close(fs->n_devfd); + fs->n_devfd = -1; + fs->n_flags &= ~NANDFS_IS_OPENED_DEV; + nandfs_close(fs); +} + +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); + NANDFS_ASSERT_RDWR(fs); + NANDFS_ASSERT_LOCKED(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); + NANDFS_ASSERT_RDWR(fs); + NANDFS_ASSERT_LOCKED(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); +}