199767f8919635c4928607450d9e0abb932109ceToomas Soome/*-
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Copyright (c) 2010-2012 Semihalf.
199767f8919635c4928607450d9e0abb932109ceToomas Soome * All rights reserved.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Redistribution and use in source and binary forms, with or without
199767f8919635c4928607450d9e0abb932109ceToomas Soome * modification, are permitted provided that the following conditions
199767f8919635c4928607450d9e0abb932109ceToomas Soome * are met:
199767f8919635c4928607450d9e0abb932109ceToomas Soome * 1. Redistributions of source code must retain the above copyright
199767f8919635c4928607450d9e0abb932109ceToomas Soome * notice, this list of conditions and the following disclaimer.
199767f8919635c4928607450d9e0abb932109ceToomas Soome * 2. Redistributions in binary form must reproduce the above copyright
199767f8919635c4928607450d9e0abb932109ceToomas Soome * notice, this list of conditions and the following disclaimer in the
199767f8919635c4928607450d9e0abb932109ceToomas Soome * documentation and/or other materials provided with the distribution.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
199767f8919635c4928607450d9e0abb932109ceToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
199767f8919635c4928607450d9e0abb932109ceToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
199767f8919635c4928607450d9e0abb932109ceToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
199767f8919635c4928607450d9e0abb932109ceToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
199767f8919635c4928607450d9e0abb932109ceToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
199767f8919635c4928607450d9e0abb932109ceToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
199767f8919635c4928607450d9e0abb932109ceToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
199767f8919635c4928607450d9e0abb932109ceToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
199767f8919635c4928607450d9e0abb932109ceToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
199767f8919635c4928607450d9e0abb932109ceToomas Soome * SUCH DAMAGE.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <sys/cdefs.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome__FBSDID("$FreeBSD$");
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <sys/param.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <sys/queue.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <sys/stdint.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <ufs/ufs/dinode.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <fs/nandfs/nandfs_fs.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include "stand.h"
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include "string.h"
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include "zlib.h"
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#define DEBUG
199767f8919635c4928607450d9e0abb932109ceToomas Soome#undef DEBUG
199767f8919635c4928607450d9e0abb932109ceToomas Soome#ifdef DEBUG
199767f8919635c4928607450d9e0abb932109ceToomas Soome#define NANDFS_DEBUG(fmt, args...) do { \
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("NANDFS_DEBUG:" fmt "\n", ##args); } while (0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome#else
199767f8919635c4928607450d9e0abb932109ceToomas Soome#define NANDFS_DEBUG(fmt, args...)
199767f8919635c4928607450d9e0abb932109ceToomas Soome#endif
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestruct nandfs_mdt {
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint32_t entries_per_block;
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint32_t entries_per_group;
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint32_t blocks_per_group;
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint32_t groups_per_desc_block; /* desc is super group */
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint32_t blocks_per_desc_block; /* desc is super group */
199767f8919635c4928607450d9e0abb932109ceToomas Soome};
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestruct bmap_buf {
199767f8919635c4928607450d9e0abb932109ceToomas Soome LIST_ENTRY(bmap_buf) list;
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_daddr_t blknr;
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint64_t *map;
199767f8919635c4928607450d9e0abb932109ceToomas Soome};
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestruct nandfs_node {
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_inode *inode;
199767f8919635c4928607450d9e0abb932109ceToomas Soome LIST_HEAD(, bmap_buf) bmap_bufs;
199767f8919635c4928607450d9e0abb932109ceToomas Soome};
199767f8919635c4928607450d9e0abb932109ceToomas Soomestruct nandfs {
199767f8919635c4928607450d9e0abb932109ceToomas Soome int nf_blocksize;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int nf_sectorsize;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int nf_cpno;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct open_file *nf_file;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_node *nf_opened_node;
199767f8919635c4928607450d9e0abb932109ceToomas Soome u_int nf_offset;
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint8_t *nf_buf;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int64_t nf_buf_blknr;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_fsdata *nf_fsdata;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_super_block *nf_sb;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_segment_summary nf_segsum;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_checkpoint nf_checkpoint;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_super_root nf_sroot;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_node nf_ifile;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_node nf_datfile;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_node nf_cpfile;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_mdt nf_datfile_mdt;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_mdt nf_ifile_mdt;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome int nf_nindir[NIADDR];
199767f8919635c4928607450d9e0abb932109ceToomas Soome};
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int nandfs_open(const char *, struct open_file *);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int nandfs_close(struct open_file *);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int nandfs_read(struct open_file *, void *, size_t, size_t *);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic off_t nandfs_seek(struct open_file *, off_t, int);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int nandfs_stat(struct open_file *, struct stat *);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int nandfs_readdir(struct open_file *, struct dirent *);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int nandfs_buf_read(struct nandfs *, void **, size_t *);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic struct nandfs_node *nandfs_lookup_path(struct nandfs *, const char *);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int nandfs_read_inode(struct nandfs *, struct nandfs_node *,
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_lbn_t, u_int, void *, int);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int nandfs_read_blk(struct nandfs *, nandfs_daddr_t, void *, int);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int nandfs_bmap_lookup(struct nandfs *, struct nandfs_node *,
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_lbn_t, nandfs_daddr_t *, int);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int nandfs_get_checkpoint(struct nandfs *, uint64_t,
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_checkpoint *);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic nandfs_daddr_t nandfs_vtop(struct nandfs *, nandfs_daddr_t);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic void nandfs_calc_mdt_consts(int, struct nandfs_mdt *, int);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic void nandfs_mdt_trans(struct nandfs_mdt *, uint64_t,
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_daddr_t *, uint32_t *);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int ioread(struct open_file *, off_t, void *, u_int);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int nandfs_probe_sectorsize(struct open_file *);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestruct fs_ops nandfs_fsops = {
199767f8919635c4928607450d9e0abb932109ceToomas Soome "nandfs",
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_open,
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_close,
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_read,
199767f8919635c4928607450d9e0abb932109ceToomas Soome null_write,
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_seek,
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_stat,
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_readdir
199767f8919635c4928607450d9e0abb932109ceToomas Soome};
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#define NINDIR(fs) ((fs)->nf_blocksize / sizeof(nandfs_daddr_t))
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* from NetBSD's src/sys/net/if_ethersubr.c */
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic uint32_t
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_crc32(uint32_t crc, const uint8_t *buf, size_t len)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome static const uint32_t crctab[] = {
199767f8919635c4928607450d9e0abb932109ceToomas Soome 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
199767f8919635c4928607450d9e0abb932109ceToomas Soome 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
199767f8919635c4928607450d9e0abb932109ceToomas Soome 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
199767f8919635c4928607450d9e0abb932109ceToomas Soome 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
199767f8919635c4928607450d9e0abb932109ceToomas Soome };
199767f8919635c4928607450d9e0abb932109ceToomas Soome size_t i;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome crc = crc ^ ~0U;
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (i = 0; i < len; i++) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome crc ^= buf[i];
199767f8919635c4928607450d9e0abb932109ceToomas Soome crc = (crc >> 4) ^ crctab[crc & 0xf];
199767f8919635c4928607450d9e0abb932109ceToomas Soome crc = (crc >> 4) ^ crctab[crc & 0xf];
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (crc ^ ~0U);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_check_fsdata_crc(struct nandfs_fsdata *fsdata)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint32_t fsdata_crc, comp_crc;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (fsdata->f_magic != NANDFS_FSDATA_MAGIC)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Preserve crc */
199767f8919635c4928607450d9e0abb932109ceToomas Soome fsdata_crc = fsdata->f_sum;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Calculate */
199767f8919635c4928607450d9e0abb932109ceToomas Soome fsdata->f_sum = (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome comp_crc = nandfs_crc32(0, (uint8_t *)fsdata, fsdata->f_bytes);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Restore */
199767f8919635c4928607450d9e0abb932109ceToomas Soome fsdata->f_sum = fsdata_crc;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Check CRC */
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (fsdata_crc == comp_crc);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_check_superblock_crc(struct nandfs_fsdata *fsdata,
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_super_block *super)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint32_t super_crc, comp_crc;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Check super block magic */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (super->s_magic != NANDFS_SUPER_MAGIC)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Preserve CRC */
199767f8919635c4928607450d9e0abb932109ceToomas Soome super_crc = super->s_sum;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Calculate */
199767f8919635c4928607450d9e0abb932109ceToomas Soome super->s_sum = (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome comp_crc = nandfs_crc32(0, (uint8_t *)super, fsdata->f_sbbytes);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Restore */
199767f8919635c4928607450d9e0abb932109ceToomas Soome super->s_sum = super_crc;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Check CRC */
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (super_crc == comp_crc);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_find_super_block(struct nandfs *fs, struct open_file *f)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_super_block *sb;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int i, j, n, s;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int sectors_to_read, error;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome sb = malloc(fs->nf_sectorsize);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (sb == NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (ENOMEM);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome memset(fs->nf_sb, 0, sizeof(*fs->nf_sb));
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome sectors_to_read = (NANDFS_NFSAREAS * fs->nf_fsdata->f_erasesize) /
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_sectorsize;
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (i = 0; i < sectors_to_read; i++) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("reading i %d offset %d\n", i,
199767f8919635c4928607450d9e0abb932109ceToomas Soome i * fs->nf_sectorsize);
199767f8919635c4928607450d9e0abb932109ceToomas Soome error = ioread(f, i * fs->nf_sectorsize, (char *)sb,
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_sectorsize);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (error) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("error %d\n", error);
199767f8919635c4928607450d9e0abb932109ceToomas Soome continue;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome n = fs->nf_sectorsize / sizeof(struct nandfs_super_block);
199767f8919635c4928607450d9e0abb932109ceToomas Soome s = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((i * fs->nf_sectorsize) % fs->nf_fsdata->f_erasesize == 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (fs->nf_sectorsize == sizeof(struct nandfs_fsdata))
199767f8919635c4928607450d9e0abb932109ceToomas Soome continue;
199767f8919635c4928607450d9e0abb932109ceToomas Soome else {
199767f8919635c4928607450d9e0abb932109ceToomas Soome s += (sizeof(struct nandfs_fsdata) /
199767f8919635c4928607450d9e0abb932109ceToomas Soome sizeof(struct nandfs_super_block));
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (j = s; j < n; j++) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (!nandfs_check_superblock_crc(fs->nf_fsdata, &sb[j]))
199767f8919635c4928607450d9e0abb932109ceToomas Soome continue;
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("magic %x wtime %jd, lastcp 0x%jx\n",
199767f8919635c4928607450d9e0abb932109ceToomas Soome sb[j].s_magic, sb[j].s_wtime, sb[j].s_last_cno);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (sb[j].s_last_cno > fs->nf_sb->s_last_cno)
199767f8919635c4928607450d9e0abb932109ceToomas Soome memcpy(fs->nf_sb, &sb[j], sizeof(*fs->nf_sb));
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(sb);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (fs->nf_sb->s_magic != 0 ? 0 : EINVAL);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_find_fsdata(struct nandfs *fs, struct open_file *f)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome int offset, error, i;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("starting\n");
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome offset = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (i = 0; i < 64 * NANDFS_NFSAREAS; i++) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome error = ioread(f, offset, (char *)fs->nf_fsdata,
199767f8919635c4928607450d9e0abb932109ceToomas Soome sizeof(struct nandfs_fsdata));
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (error)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (error);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (fs->nf_fsdata->f_magic == NANDFS_FSDATA_MAGIC) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("found at %x, volume %s\n", offset,
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_fsdata->f_volume_name);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (nandfs_check_fsdata_crc(fs->nf_fsdata))
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome offset += fs->nf_sectorsize;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (error);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_read_structures(struct nandfs *fs, struct open_file *f)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome int error;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome error = nandfs_find_fsdata(fs, f);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (error)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (error);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome error = nandfs_find_super_block(fs, f);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (error == 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("selected sb with w_time %jd last_pseg %jx\n",
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_sb->s_wtime, fs->nf_sb->s_last_pseg);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (error);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_mount(struct nandfs *fs, struct open_file *f)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome int err = 0, level;
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint64_t last_pseg;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_fsdata = malloc(sizeof(struct nandfs_fsdata));
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_sb = malloc(sizeof(struct nandfs_super_block));
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome err = nandfs_read_structures(fs, f);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (err) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(fs->nf_fsdata);
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(fs->nf_sb);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (err);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_blocksize = 1 << (fs->nf_fsdata->f_log_block_size + 10);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("using superblock with wtime %jd\n", fs->nf_sb->s_wtime);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_cpno = fs->nf_sb->s_last_cno;
199767f8919635c4928607450d9e0abb932109ceToomas Soome last_pseg = fs->nf_sb->s_last_pseg;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Calculate indirect block levels.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_daddr_t mult;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome mult = 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (level = 0; level < NIADDR; level++) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome mult *= NINDIR(fs);
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_nindir[level] = mult;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_calc_mdt_consts(fs->nf_blocksize, &fs->nf_datfile_mdt,
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_fsdata->f_dat_entry_size);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_calc_mdt_consts(fs->nf_blocksize, &fs->nf_ifile_mdt,
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_fsdata->f_inode_size);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome err = ioread(f, last_pseg * fs->nf_blocksize, &fs->nf_segsum,
199767f8919635c4928607450d9e0abb932109ceToomas Soome sizeof(struct nandfs_segment_summary));
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (err) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(fs->nf_sb);
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(fs->nf_fsdata);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (err);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome err = ioread(f, (last_pseg + fs->nf_segsum.ss_nblocks - 1) *
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_blocksize, &fs->nf_sroot, sizeof(struct nandfs_super_root));
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (err) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(fs->nf_sb);
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(fs->nf_fsdata);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (err);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_datfile.inode = &fs->nf_sroot.sr_dat;
199767f8919635c4928607450d9e0abb932109ceToomas Soome LIST_INIT(&fs->nf_datfile.bmap_bufs);
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_cpfile.inode = &fs->nf_sroot.sr_cpfile;
199767f8919635c4928607450d9e0abb932109ceToomas Soome LIST_INIT(&fs->nf_cpfile.bmap_bufs);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome err = nandfs_get_checkpoint(fs, fs->nf_cpno, &fs->nf_checkpoint);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (err) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(fs->nf_sb);
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(fs->nf_fsdata);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (err);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("checkpoint cp_cno=%lld\n", fs->nf_checkpoint.cp_cno);
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("checkpoint cp_inodes_count=%lld\n",
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_checkpoint.cp_inodes_count);
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("checkpoint cp_ifile_inode.i_blocks=%lld\n",
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_checkpoint.cp_ifile_inode.i_blocks);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_ifile.inode = &fs->nf_checkpoint.cp_ifile_inode;
199767f8919635c4928607450d9e0abb932109ceToomas Soome LIST_INIT(&fs->nf_ifile.bmap_bufs);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#define NINDIR(fs) ((fs)->nf_blocksize / sizeof(nandfs_daddr_t))
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_open(const char *path, struct open_file *f)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs *fs;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_node *node;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int err, bsize, level;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("nandfs_open('%s', %p)\n", path, f);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs = malloc(sizeof(struct nandfs));
199767f8919635c4928607450d9e0abb932109ceToomas Soome f->f_fsdata = fs;
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_file = f;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome bsize = nandfs_probe_sectorsize(f);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (bsize < 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("Cannot probe medium sector size\n");
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EINVAL);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_sectorsize = bsize;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Calculate indirect block levels.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_daddr_t mult;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome mult = 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (level = 0; level < NIADDR; level++) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome mult *= NINDIR(fs);
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_nindir[level] = mult;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("fs %p nf_sectorsize=%x\n", fs, fs->nf_sectorsize);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome err = nandfs_mount(fs, f);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (err) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("Cannot mount nandfs: %s\n", strerror(err));
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (err);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome node = nandfs_lookup_path(fs, path);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (node == NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EINVAL);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_offset = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_buf = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_buf_blknr = -1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_opened_node = node;
199767f8919635c4928607450d9e0abb932109ceToomas Soome LIST_INIT(&fs->nf_opened_node->bmap_bufs);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic void
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_free_node(struct nandfs_node *node)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct bmap_buf *bmap, *tmp;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(node->inode);
199767f8919635c4928607450d9e0abb932109ceToomas Soome LIST_FOREACH_SAFE(bmap, &node->bmap_bufs, list, tmp) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome LIST_REMOVE(bmap, list);
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(bmap->map);
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(bmap);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(node);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_close(struct open_file *f)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs *fs = f->f_fsdata;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("nandfs_close(%p)\n", f);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (fs->nf_buf != NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(fs->nf_buf);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_free_node(fs->nf_opened_node);
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(fs->nf_sb);
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(fs);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_read(struct open_file *f, void *addr, size_t size, size_t *resid)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs *fs = (struct nandfs *)f->f_fsdata;
199767f8919635c4928607450d9e0abb932109ceToomas Soome size_t csize, buf_size;
199767f8919635c4928607450d9e0abb932109ceToomas Soome void *buf;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int error = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("nandfs_read(file=%p, addr=%p, size=%d)\n", f, addr, size);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome while (size != 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (fs->nf_offset >= fs->nf_opened_node->inode->i_size)
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome error = nandfs_buf_read(fs, &buf, &buf_size);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (error)
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome csize = size;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (csize > buf_size)
199767f8919635c4928607450d9e0abb932109ceToomas Soome csize = buf_size;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome bcopy(buf, addr, csize);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_offset += csize;
199767f8919635c4928607450d9e0abb932109ceToomas Soome addr = (char *)addr + csize;
199767f8919635c4928607450d9e0abb932109ceToomas Soome size -= csize;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (resid)
199767f8919635c4928607450d9e0abb932109ceToomas Soome *resid = size;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (error);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic off_t
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_seek(struct open_file *f, off_t offset, int where)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs *fs = f->f_fsdata;
199767f8919635c4928607450d9e0abb932109ceToomas Soome off_t off;
199767f8919635c4928607450d9e0abb932109ceToomas Soome u_int size;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("nandfs_seek(file=%p, offset=%lld, where=%d)\n", f,
199767f8919635c4928607450d9e0abb932109ceToomas Soome offset, where);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome size = fs->nf_opened_node->inode->i_size;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome switch (where) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome case SEEK_SET:
199767f8919635c4928607450d9e0abb932109ceToomas Soome off = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome case SEEK_CUR:
199767f8919635c4928607450d9e0abb932109ceToomas Soome off = fs->nf_offset;
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome case SEEK_END:
199767f8919635c4928607450d9e0abb932109ceToomas Soome off = size;
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome default:
199767f8919635c4928607450d9e0abb932109ceToomas Soome errno = EINVAL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (-1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome off += offset;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (off < 0 || off > size) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome errno = EINVAL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(-1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_offset = (u_int)off;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (off);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_stat(struct open_file *f, struct stat *sb)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs *fs = f->f_fsdata;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("nandfs_stat(file=%p, stat=%p)\n", f, sb);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome sb->st_size = fs->nf_opened_node->inode->i_size;
199767f8919635c4928607450d9e0abb932109ceToomas Soome sb->st_mode = fs->nf_opened_node->inode->i_mode;
199767f8919635c4928607450d9e0abb932109ceToomas Soome sb->st_uid = fs->nf_opened_node->inode->i_uid;
199767f8919635c4928607450d9e0abb932109ceToomas Soome sb->st_gid = fs->nf_opened_node->inode->i_gid;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_readdir(struct open_file *f, struct dirent *d)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs *fs = f->f_fsdata;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_dir_entry *dirent;
199767f8919635c4928607450d9e0abb932109ceToomas Soome void *buf;
199767f8919635c4928607450d9e0abb932109ceToomas Soome size_t buf_size;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("nandfs_readdir(file=%p, dirent=%p)\n", f, d);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (fs->nf_offset >= fs->nf_opened_node->inode->i_size) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("nandfs_readdir(file=%p, dirent=%p) ENOENT\n",
199767f8919635c4928607450d9e0abb932109ceToomas Soome f, d);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (ENOENT);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (nandfs_buf_read(fs, &buf, &buf_size)) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("nandfs_readdir(file=%p, dirent=%p)"
199767f8919635c4928607450d9e0abb932109ceToomas Soome "buf_read failed\n", f, d);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EIO);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("nandfs_readdir(file=%p, dirent=%p) moving forward\n",
199767f8919635c4928607450d9e0abb932109ceToomas Soome f, d);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome dirent = (struct nandfs_dir_entry *)buf;
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_offset += dirent->rec_len;
199767f8919635c4928607450d9e0abb932109ceToomas Soome strncpy(d->d_name, dirent->name, dirent->name_len);
199767f8919635c4928607450d9e0abb932109ceToomas Soome d->d_name[dirent->name_len] = '\0';
199767f8919635c4928607450d9e0abb932109ceToomas Soome d->d_type = dirent->file_type;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_buf_read(struct nandfs *fs, void **buf_p, size_t *size_p)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_daddr_t blknr, blkoff;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome blknr = fs->nf_offset / fs->nf_blocksize;
199767f8919635c4928607450d9e0abb932109ceToomas Soome blkoff = fs->nf_offset % fs->nf_blocksize;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (blknr != fs->nf_buf_blknr) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (fs->nf_buf == NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_buf = malloc(fs->nf_blocksize);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (nandfs_read_inode(fs, fs->nf_opened_node, blknr, 1,
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_buf, 0))
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EIO);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_buf_blknr = blknr;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome *buf_p = fs->nf_buf + blkoff;
199767f8919635c4928607450d9e0abb932109ceToomas Soome *size_p = fs->nf_blocksize - blkoff;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("nandfs_buf_read buf_p=%p size_p=%d\n", *buf_p, *size_p);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (*size_p > fs->nf_opened_node->inode->i_size - fs->nf_offset)
199767f8919635c4928607450d9e0abb932109ceToomas Soome *size_p = fs->nf_opened_node->inode->i_size - fs->nf_offset;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic struct nandfs_node *
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_lookup_node(struct nandfs *fs, uint64_t ino)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint64_t blocknr;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int entrynr;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_inode *buffer;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_node *node;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_inode *inode;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("nandfs_lookup_node ino=%lld\n", ino);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (ino == 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("nandfs_lookup_node: invalid inode requested\n");
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (NULL);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome buffer = malloc(fs->nf_blocksize);
199767f8919635c4928607450d9e0abb932109ceToomas Soome inode = malloc(sizeof(struct nandfs_inode));
199767f8919635c4928607450d9e0abb932109ceToomas Soome node = malloc(sizeof(struct nandfs_node));
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_mdt_trans(&fs->nf_ifile_mdt, ino, &blocknr, &entrynr);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (nandfs_read_inode(fs, &fs->nf_ifile, blocknr, 1, buffer, 0))
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (NULL);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome memcpy(inode, &buffer[entrynr], sizeof(struct nandfs_inode));
199767f8919635c4928607450d9e0abb932109ceToomas Soome node->inode = inode;
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(buffer);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (node);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic struct nandfs_node *
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_lookup_path(struct nandfs *fs, const char *path)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_node *node;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_dir_entry *dirent;
199767f8919635c4928607450d9e0abb932109ceToomas Soome char *namebuf;
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint64_t i, done, pinode, inode;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int nlinks = 0, counter, len, link_len, nameidx;
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint8_t *buffer, *orig;
199767f8919635c4928607450d9e0abb932109ceToomas Soome char *strp, *lpath;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome buffer = malloc(fs->nf_blocksize);
199767f8919635c4928607450d9e0abb932109ceToomas Soome orig = buffer;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome namebuf = malloc(2 * MAXPATHLEN + 2);
199767f8919635c4928607450d9e0abb932109ceToomas Soome strncpy(namebuf, path, MAXPATHLEN);
199767f8919635c4928607450d9e0abb932109ceToomas Soome namebuf[MAXPATHLEN] = '\0';
199767f8919635c4928607450d9e0abb932109ceToomas Soome done = nameidx = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome lpath = namebuf;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Get the root inode */
199767f8919635c4928607450d9e0abb932109ceToomas Soome node = nandfs_lookup_node(fs, NANDFS_ROOT_INO);
199767f8919635c4928607450d9e0abb932109ceToomas Soome inode = NANDFS_ROOT_INO;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome while ((strp = strsep(&lpath, "/")) != NULL) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (*strp == '\0')
199767f8919635c4928607450d9e0abb932109ceToomas Soome continue;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((node->inode->i_mode & IFMT) != IFDIR) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_free_node(node);
199767f8919635c4928607450d9e0abb932109ceToomas Soome node = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome goto out;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome len = strlen(strp);
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("%s: looking for %s\n", __func__, strp);
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (i = 0; i < node->inode->i_blocks; i++) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (nandfs_read_inode(fs, node, i, 1, orig, 0)) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome node = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome goto out;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome buffer = orig;
199767f8919635c4928607450d9e0abb932109ceToomas Soome done = counter = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome while (1) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome dirent =
199767f8919635c4928607450d9e0abb932109ceToomas Soome (struct nandfs_dir_entry *)(void *)buffer;
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("%s: dirent.name = %s\n",
199767f8919635c4928607450d9e0abb932109ceToomas Soome __func__, dirent->name);
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("%s: dirent.rec_len = %d\n",
199767f8919635c4928607450d9e0abb932109ceToomas Soome __func__, dirent->rec_len);
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("%s: dirent.inode = %lld\n",
199767f8919635c4928607450d9e0abb932109ceToomas Soome __func__, dirent->inode);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (len == dirent->name_len &&
199767f8919635c4928607450d9e0abb932109ceToomas Soome (strncmp(strp, dirent->name, len) == 0) &&
199767f8919635c4928607450d9e0abb932109ceToomas Soome dirent->inode != 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_free_node(node);
199767f8919635c4928607450d9e0abb932109ceToomas Soome node = nandfs_lookup_node(fs,
199767f8919635c4928607450d9e0abb932109ceToomas Soome dirent->inode);
199767f8919635c4928607450d9e0abb932109ceToomas Soome pinode = inode;
199767f8919635c4928607450d9e0abb932109ceToomas Soome inode = dirent->inode;
199767f8919635c4928607450d9e0abb932109ceToomas Soome done = 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome counter += dirent->rec_len;
199767f8919635c4928607450d9e0abb932109ceToomas Soome buffer += dirent->rec_len;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (counter == fs->nf_blocksize)
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (done)
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (!done) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome node = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome goto out;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("%s: %.*s has mode %o\n", __func__,
199767f8919635c4928607450d9e0abb932109ceToomas Soome dirent->name_len, dirent->name, node->inode->i_mode);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((node->inode->i_mode & IFMT) == IFLNK) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("%s: %.*s is symlink\n",
199767f8919635c4928607450d9e0abb932109ceToomas Soome __func__, dirent->name_len, dirent->name);
199767f8919635c4928607450d9e0abb932109ceToomas Soome link_len = node->inode->i_size;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (++nlinks > MAXSYMLINKS) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_free_node(node);
199767f8919635c4928607450d9e0abb932109ceToomas Soome node = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome goto out;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (nandfs_read_inode(fs, node, 0, 1, orig, 0)) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_free_node(node);
199767f8919635c4928607450d9e0abb932109ceToomas Soome node = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome goto out;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("%s: symlink is %.*s\n",
199767f8919635c4928607450d9e0abb932109ceToomas Soome __func__, link_len, (char *)orig);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome nameidx = (nameidx == 0) ? MAXPATHLEN + 1 : 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome bcopy((char *)orig, namebuf + nameidx,
199767f8919635c4928607450d9e0abb932109ceToomas Soome (unsigned)link_len);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (lpath != NULL) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome namebuf[nameidx + link_len++] = '/';
199767f8919635c4928607450d9e0abb932109ceToomas Soome strncpy(namebuf + nameidx + link_len, lpath,
199767f8919635c4928607450d9e0abb932109ceToomas Soome MAXPATHLEN - link_len);
199767f8919635c4928607450d9e0abb932109ceToomas Soome namebuf[nameidx + MAXPATHLEN] = '\0';
199767f8919635c4928607450d9e0abb932109ceToomas Soome } else
199767f8919635c4928607450d9e0abb932109ceToomas Soome namebuf[nameidx + link_len] = '\0';
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("%s: strp=%s, lpath=%s, namebuf0=%s, "
199767f8919635c4928607450d9e0abb932109ceToomas Soome "namebuf1=%s, idx=%d\n", __func__, strp, lpath,
199767f8919635c4928607450d9e0abb932109ceToomas Soome namebuf + 0, namebuf + MAXPATHLEN + 1, nameidx);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome lpath = namebuf + nameidx;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_free_node(node);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * If absolute pathname, restart at root. Otherwise
199767f8919635c4928607450d9e0abb932109ceToomas Soome * continue with out parent inode.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome inode = (orig[0] == '/') ? NANDFS_ROOT_INO : pinode;
199767f8919635c4928607450d9e0abb932109ceToomas Soome node = nandfs_lookup_node(fs, inode);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomeout:
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(namebuf);
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(orig);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (node);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_read_inode(struct nandfs *fs, struct nandfs_node *node,
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_daddr_t blknr, u_int nblks, void *buf, int raw)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint64_t *pblks;
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint64_t *vblks;
199767f8919635c4928607450d9e0abb932109ceToomas Soome u_int i;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int error;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome pblks = malloc(nblks * sizeof(uint64_t));
199767f8919635c4928607450d9e0abb932109ceToomas Soome vblks = malloc(nblks * sizeof(uint64_t));
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("nandfs_read_inode fs=%p node=%p blknr=%lld nblks=%d\n",
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs, node, blknr, nblks);
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (i = 0; i < nblks; i++) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome error = nandfs_bmap_lookup(fs, node, blknr + i, &vblks[i], raw);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (error) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(pblks);
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(vblks);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (error);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (raw == 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome pblks[i] = nandfs_vtop(fs, vblks[i]);
199767f8919635c4928607450d9e0abb932109ceToomas Soome else
199767f8919635c4928607450d9e0abb932109ceToomas Soome pblks[i] = vblks[i];
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (i = 0; i < nblks; i++) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (ioread(fs->nf_file, pblks[i] * fs->nf_blocksize, buf,
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_blocksize)) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(pblks);
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(vblks);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EIO);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome buf = (void *)((uintptr_t)buf + fs->nf_blocksize);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(pblks);
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(vblks);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_read_blk(struct nandfs *fs, nandfs_daddr_t blknr, void *buf, int phys)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint64_t pblknr;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome pblknr = (phys ? blknr : nandfs_vtop(fs, blknr));
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (ioread(fs->nf_file, pblknr * fs->nf_blocksize, buf,
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs->nf_blocksize));
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_get_checkpoint(struct nandfs *fs, uint64_t cpno,
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_checkpoint *cp)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint64_t blocknr;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int blockoff, cp_per_block, dlen;
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint8_t *buf;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("nandfs_get_checkpoint(fs=%p cpno=%lld)\n", fs, cpno);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome buf = malloc(fs->nf_blocksize);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome cpno += NANDFS_CPFILE_FIRST_CHECKPOINT_OFFSET - 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome dlen = fs->nf_fsdata->f_checkpoint_size;
199767f8919635c4928607450d9e0abb932109ceToomas Soome cp_per_block = fs->nf_blocksize / dlen;
199767f8919635c4928607450d9e0abb932109ceToomas Soome blocknr = cpno / cp_per_block;
199767f8919635c4928607450d9e0abb932109ceToomas Soome blockoff = (cpno % cp_per_block) * dlen;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (nandfs_read_inode(fs, &fs->nf_cpfile, blocknr, 1, buf, 0)) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(buf);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EINVAL);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome memcpy(cp, buf + blockoff, sizeof(struct nandfs_checkpoint));
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(buf);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic uint64_t *
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_get_map(struct nandfs *fs, struct nandfs_node *node, nandfs_daddr_t blknr,
199767f8919635c4928607450d9e0abb932109ceToomas Soome int phys)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct bmap_buf *bmap;
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint64_t *map;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome LIST_FOREACH(bmap, &node->bmap_bufs, list) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (bmap->blknr == blknr)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (bmap->map);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome map = malloc(fs->nf_blocksize);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (nandfs_read_blk(fs, blknr, map, phys)) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(map);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (NULL);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome bmap = malloc(sizeof(struct bmap_buf));
199767f8919635c4928607450d9e0abb932109ceToomas Soome bmap->blknr = blknr;
199767f8919635c4928607450d9e0abb932109ceToomas Soome bmap->map = map;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome LIST_INSERT_HEAD(&node->bmap_bufs, bmap, list);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("%s:(node=%p, map=%p)\n", __func__, node, map);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (map);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_bmap_lookup(struct nandfs *fs, struct nandfs_node *node,
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_lbn_t lblknr, nandfs_daddr_t *vblknr, int phys)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_inode *ino;
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_daddr_t ind_block_num;
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint64_t *map;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int idx;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int level;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome ino = node->inode;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (lblknr < NDADDR) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome *vblknr = ino->i_db[lblknr];
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome lblknr -= NDADDR;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * nindir[0] = NINDIR
199767f8919635c4928607450d9e0abb932109ceToomas Soome * nindir[1] = NINDIR**2
199767f8919635c4928607450d9e0abb932109ceToomas Soome * nindir[2] = NINDIR**3
199767f8919635c4928607450d9e0abb932109ceToomas Soome * etc
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (level = 0; level < NIADDR; level++) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("lblknr=%jx fs->nf_nindir[%d]=%d\n", lblknr, level, fs->nf_nindir[level]);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (lblknr < fs->nf_nindir[level])
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome lblknr -= fs->nf_nindir[level];
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (level == NIADDR) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Block number too high */
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("lblknr %jx too high\n", lblknr);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EFBIG);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome ind_block_num = ino->i_ib[level];
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (; level >= 0; level--) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (ind_block_num == 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome *vblknr = 0; /* missing */
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome twiddle(1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("calling get_map with %jx\n", ind_block_num);
199767f8919635c4928607450d9e0abb932109ceToomas Soome map = nandfs_get_map(fs, node, ind_block_num, phys);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (map == NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (EIO);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (level > 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome idx = lblknr / fs->nf_nindir[level - 1];
199767f8919635c4928607450d9e0abb932109ceToomas Soome lblknr %= fs->nf_nindir[level - 1];
199767f8919635c4928607450d9e0abb932109ceToomas Soome } else
199767f8919635c4928607450d9e0abb932109ceToomas Soome idx = lblknr;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome ind_block_num = ((nandfs_daddr_t *)map)[idx];
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome *vblknr = ind_block_num;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic nandfs_daddr_t
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_vtop(struct nandfs *fs, nandfs_daddr_t vblocknr)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_lbn_t blocknr;
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_daddr_t pblocknr;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int entrynr;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct nandfs_dat_entry *dat;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome dat = malloc(fs->nf_blocksize);
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_mdt_trans(&fs->nf_datfile_mdt, vblocknr, &blocknr, &entrynr);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (nandfs_read_inode(fs, &fs->nf_datfile, blocknr, 1, dat, 1)) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(dat);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("nandfs_vtop entrynr=%d vblocknr=%lld pblocknr=%lld\n",
199767f8919635c4928607450d9e0abb932109ceToomas Soome entrynr, vblocknr, dat[entrynr].de_blocknr);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome pblocknr = dat[entrynr].de_blocknr;
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(dat);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (pblocknr);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic void
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_calc_mdt_consts(int blocksize, struct nandfs_mdt *mdt, int entry_size)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome mdt->entries_per_group = blocksize * 8; /* bits in sector */
199767f8919635c4928607450d9e0abb932109ceToomas Soome mdt->entries_per_block = blocksize / entry_size;
199767f8919635c4928607450d9e0abb932109ceToomas Soome mdt->blocks_per_group =
199767f8919635c4928607450d9e0abb932109ceToomas Soome (mdt->entries_per_group -1) / mdt->entries_per_block + 1 + 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome mdt->groups_per_desc_block =
199767f8919635c4928607450d9e0abb932109ceToomas Soome blocksize / sizeof(struct nandfs_block_group_desc);
199767f8919635c4928607450d9e0abb932109ceToomas Soome mdt->blocks_per_desc_block =
199767f8919635c4928607450d9e0abb932109ceToomas Soome mdt->groups_per_desc_block * mdt->blocks_per_group + 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic void
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_mdt_trans(struct nandfs_mdt *mdt, uint64_t index,
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_daddr_t *blocknr, uint32_t *entry_in_block)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome nandfs_daddr_t blknr;
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint64_t group, group_offset, blocknr_in_group;
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint64_t desc_block, desc_offset;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Calculate our offset in the file */
199767f8919635c4928607450d9e0abb932109ceToomas Soome group = index / mdt->entries_per_group;
199767f8919635c4928607450d9e0abb932109ceToomas Soome group_offset = index % mdt->entries_per_group;
199767f8919635c4928607450d9e0abb932109ceToomas Soome desc_block = group / mdt->groups_per_desc_block;
199767f8919635c4928607450d9e0abb932109ceToomas Soome desc_offset = group % mdt->groups_per_desc_block;
199767f8919635c4928607450d9e0abb932109ceToomas Soome blocknr_in_group = group_offset / mdt->entries_per_block;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* To descgroup offset */
199767f8919635c4928607450d9e0abb932109ceToomas Soome blknr = 1 + desc_block * mdt->blocks_per_desc_block;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* To group offset */
199767f8919635c4928607450d9e0abb932109ceToomas Soome blknr += desc_offset * mdt->blocks_per_group;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* To actual file block */
199767f8919635c4928607450d9e0abb932109ceToomas Soome blknr += 1 + blocknr_in_group;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome *blocknr = blknr;
199767f8919635c4928607450d9e0abb932109ceToomas Soome *entry_in_block = group_offset % mdt->entries_per_block;
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomeioread(struct open_file *f, off_t pos, void *buf, u_int length)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome void *buffer;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int err;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int bsize = ((struct nandfs *)f->f_fsdata)->nf_sectorsize;
199767f8919635c4928607450d9e0abb932109ceToomas Soome u_int off, nsec;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome off = pos % bsize;
199767f8919635c4928607450d9e0abb932109ceToomas Soome pos /= bsize;
199767f8919635c4928607450d9e0abb932109ceToomas Soome nsec = (length + (bsize - 1)) / bsize;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("pos=%lld length=%d off=%d nsec=%d\n", pos, length,
199767f8919635c4928607450d9e0abb932109ceToomas Soome off, nsec);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome buffer = malloc(nsec * bsize);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome err = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, pos,
199767f8919635c4928607450d9e0abb932109ceToomas Soome nsec * bsize, buffer, NULL);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome memcpy(buf, (void *)((uintptr_t)buffer + off), length);
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(buffer);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (err);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomenandfs_probe_sectorsize(struct open_file *f)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome void *buffer;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int i, err;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome buffer = malloc(16 * 1024);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("probing for sector size: ");
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (i = 512; i < (16 * 1024); i <<= 1) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("%d ", i);
199767f8919635c4928607450d9e0abb932109ceToomas Soome err = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 0, i,
199767f8919635c4928607450d9e0abb932109ceToomas Soome buffer, NULL);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (err == 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("found");
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(buffer);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (i);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(buffer);
199767f8919635c4928607450d9e0abb932109ceToomas Soome NANDFS_DEBUG("not found\n");
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (-1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}