2 * Copyright (c) 2010-2012 Semihalf.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/param.h>
31 #include <sys/queue.h>
32 #include <sys/stdint.h>
33 #include <ufs/ufs/dinode.h>
34 #include <fs/nandfs/nandfs_fs.h>
42 #define NANDFS_DEBUG(fmt, args...) do { \
43 printf("NANDFS_DEBUG:" fmt "\n", ##args); } while (0)
45 #define NANDFS_DEBUG(fmt, args...)
49 uint32_t entries_per_block;
50 uint32_t entries_per_group;
51 uint32_t blocks_per_group;
52 uint32_t groups_per_desc_block; /* desc is super group */
53 uint32_t blocks_per_desc_block; /* desc is super group */
57 LIST_ENTRY(bmap_buf) list;
63 struct nandfs_inode *inode;
64 LIST_HEAD(, bmap_buf) bmap_bufs;
71 struct open_file *nf_file;
72 struct nandfs_node *nf_opened_node;
77 struct nandfs_fsdata *nf_fsdata;
78 struct nandfs_super_block *nf_sb;
79 struct nandfs_segment_summary nf_segsum;
80 struct nandfs_checkpoint nf_checkpoint;
81 struct nandfs_super_root nf_sroot;
82 struct nandfs_node nf_ifile;
83 struct nandfs_node nf_datfile;
84 struct nandfs_node nf_cpfile;
85 struct nandfs_mdt nf_datfile_mdt;
86 struct nandfs_mdt nf_ifile_mdt;
88 int nf_nindir[NIADDR];
91 static int nandfs_open(const char *, struct open_file *);
92 static int nandfs_close(struct open_file *);
93 static int nandfs_read(struct open_file *, void *, size_t, size_t *);
94 static off_t nandfs_seek(struct open_file *, off_t, int);
95 static int nandfs_stat(struct open_file *, struct stat *);
96 static int nandfs_readdir(struct open_file *, struct dirent *);
98 static int nandfs_buf_read(struct nandfs *, char **, size_t *);
99 static struct nandfs_node *nandfs_lookup_inode(struct nandfs *, nandfs_daddr_t);
100 static struct nandfs_node *nandfs_lookup_path(struct nandfs *, const char *);
101 static int nandfs_read_inode(struct nandfs *, struct nandfs_node *,
102 nandfs_lbn_t, u_int, void *, int);
103 static int nandfs_read_blk(struct nandfs *, nandfs_daddr_t, void *, int);
104 static int nandfs_bmap_lookup(struct nandfs *, struct nandfs_node *,
105 nandfs_lbn_t, nandfs_daddr_t *, int);
106 static int nandfs_get_checkpoint(struct nandfs *, uint64_t,
107 struct nandfs_checkpoint *);
108 static nandfs_daddr_t nandfs_vtop(struct nandfs *, nandfs_daddr_t);
109 static void nandfs_calc_mdt_consts(int, struct nandfs_mdt *, int);
110 static void nandfs_mdt_trans(struct nandfs_mdt *, uint64_t,
111 nandfs_daddr_t *, uint32_t *);
112 static int ioread(struct open_file *, off_t, void *, u_int);
113 static int nandfs_probe_sectorsize(struct open_file *);
115 struct fs_ops nandfs_fsops = {
126 #define NINDIR(fs) ((fs)->nf_blocksize / sizeof(nandfs_daddr_t))
129 nandfs_check_fsdata_crc(struct nandfs_fsdata *fsdata)
131 uint32_t fsdata_crc, comp_crc;
133 if (fsdata->f_magic != NANDFS_FSDATA_MAGIC)
137 fsdata_crc = fsdata->f_sum;
141 comp_crc = crc32(0, (uint8_t *)fsdata, fsdata->f_bytes);
144 fsdata->f_sum = fsdata_crc;
147 return (fsdata_crc == comp_crc);
151 nandfs_check_superblock_crc(struct nandfs_fsdata *fsdata,
152 struct nandfs_super_block *super)
154 uint32_t super_crc, comp_crc;
156 /* Check super block magic */
157 if (super->s_magic != NANDFS_SUPER_MAGIC)
161 super_crc = super->s_sum;
165 comp_crc = crc32(0, (uint8_t *)super, fsdata->f_sbbytes);
168 super->s_sum = super_crc;
171 return (super_crc == comp_crc);
175 nandfs_find_super_block(struct nandfs *fs, struct open_file *f)
177 struct nandfs_super_block *sb;
179 int sectors_to_read, error;
181 sb = malloc(fs->nf_sectorsize);
185 memset(fs->nf_sb, 0, sizeof(*fs->nf_sb));
187 sectors_to_read = (NANDFS_NFSAREAS * fs->nf_fsdata->f_erasesize) /
189 for (i = 0; i < sectors_to_read; i++) {
190 NANDFS_DEBUG("reading i %d offset %d\n", i,
191 i * fs->nf_sectorsize);
192 error = ioread(f, i * fs->nf_sectorsize, (char *)sb,
195 NANDFS_DEBUG("error %d\n", error);
198 n = fs->nf_sectorsize / sizeof(struct nandfs_super_block);
199 if ((i * fs->nf_sectorsize) % fs->nf_fsdata->f_erasesize == 0) {
200 if (fs->nf_sectorsize == sizeof(struct nandfs_fsdata))
203 sb += (sizeof(struct nandfs_fsdata) /
204 sizeof(struct nandfs_super_block));
205 n -= (sizeof(struct nandfs_fsdata) /
206 sizeof(struct nandfs_super_block));
210 for (j = 0; j < n; j++) {
211 if (!nandfs_check_superblock_crc(fs->nf_fsdata, &sb[j]))
213 NANDFS_DEBUG("magic %x wtime %jd\n", sb->s_magic,
215 if (sb[j].s_wtime > fs->nf_sb->s_wtime)
216 memcpy(fs->nf_sb, &sb[j], sizeof(*fs->nf_sb));
222 return (fs->nf_sb->s_magic != 0 ? 0 : EINVAL);
226 nandfs_find_fsdata(struct nandfs *fs, struct open_file *f)
228 int offset, error, i;
230 NANDFS_DEBUG("starting\n");
233 for (i = 0; i < 64 * NANDFS_NFSAREAS; i++) {
234 error = ioread(f, offset, (char *)fs->nf_fsdata,
235 sizeof(struct nandfs_fsdata));
238 if (fs->nf_fsdata->f_magic == NANDFS_FSDATA_MAGIC) {
239 NANDFS_DEBUG("found at %x, volume %s\n", offset,
240 fs->nf_fsdata->f_volume_name);
241 if (nandfs_check_fsdata_crc(fs->nf_fsdata))
244 offset += fs->nf_sectorsize;
251 nandfs_read_structures(struct nandfs *fs, struct open_file *f)
255 error = nandfs_find_fsdata(fs, f);
259 error = nandfs_find_super_block(fs, f);
262 NANDFS_DEBUG("selected sb with w_time %jd last_pseg %jx\n",
263 fs->nf_sb->s_wtime, fs->nf_sb->s_last_pseg);
269 nandfs_mount(struct nandfs *fs, struct open_file *f)
274 fs->nf_fsdata = malloc(sizeof(struct nandfs_fsdata));
275 fs->nf_sb = malloc(sizeof(struct nandfs_super_block));
277 err = nandfs_read_structures(fs, f);
284 fs->nf_blocksize = 1 << (fs->nf_fsdata->f_log_block_size + 10);
286 NANDFS_DEBUG("using superblock with wtime %jd\n", fs->nf_sb->s_wtime);
288 fs->nf_cpno = fs->nf_sb->s_last_cno;
289 last_pseg = fs->nf_sb->s_last_pseg;
292 * Calculate indirect block levels.
297 for (level = 0; level < NIADDR; level++) {
299 fs->nf_nindir[level] = mult;
302 nandfs_calc_mdt_consts(fs->nf_blocksize, &fs->nf_datfile_mdt,
303 fs->nf_fsdata->f_dat_entry_size);
305 nandfs_calc_mdt_consts(fs->nf_blocksize, &fs->nf_ifile_mdt,
306 fs->nf_fsdata->f_inode_size);
308 err = ioread(f, last_pseg * fs->nf_blocksize, &fs->nf_segsum,
309 sizeof(struct nandfs_segment_summary));
316 err = ioread(f, (last_pseg + fs->nf_segsum.ss_nblocks - 1) *
317 fs->nf_blocksize, &fs->nf_sroot, sizeof(struct nandfs_super_root));
324 fs->nf_datfile.inode = &fs->nf_sroot.sr_dat;
325 LIST_INIT(&fs->nf_datfile.bmap_bufs);
326 fs->nf_cpfile.inode = &fs->nf_sroot.sr_cpfile;
327 LIST_INIT(&fs->nf_cpfile.bmap_bufs);
329 err = nandfs_get_checkpoint(fs, fs->nf_cpno, &fs->nf_checkpoint);
336 NANDFS_DEBUG("checkpoint cp_cno=%lld\n", fs->nf_checkpoint.cp_cno);
337 NANDFS_DEBUG("checkpoint cp_inodes_count=%lld\n",
338 fs->nf_checkpoint.cp_inodes_count);
339 NANDFS_DEBUG("checkpoint cp_ifile_inode.i_blocks=%lld\n",
340 fs->nf_checkpoint.cp_ifile_inode.i_blocks);
342 fs->nf_ifile.inode = &fs->nf_checkpoint.cp_ifile_inode;
343 LIST_INIT(&fs->nf_ifile.bmap_bufs);
347 #define NINDIR(fs) ((fs)->nf_blocksize / sizeof(nandfs_daddr_t))
350 nandfs_open(const char *path, struct open_file *f)
353 struct nandfs_node *node;
354 int err, bsize, level;
356 NANDFS_DEBUG("nandfs_open('%s', %p)\n", path, f);
358 fs = malloc(sizeof(struct nandfs));
362 bsize = nandfs_probe_sectorsize(f);
364 printf("Cannot probe medium sector size\n");
368 fs->nf_sectorsize = bsize;
371 * Calculate indirect block levels.
376 for (level = 0; level < NIADDR; level++) {
378 fs->nf_nindir[level] = mult;
381 NANDFS_DEBUG("fs %p nf_sectorsize=%x\n", fs, fs->nf_sectorsize);
383 err = nandfs_mount(fs, f);
385 NANDFS_DEBUG("Cannot mount nandfs: %s\n", strerror(err));
389 node = nandfs_lookup_path(fs, path);
395 fs->nf_buf_blknr = -1;
396 fs->nf_opened_node = node;
397 LIST_INIT(&fs->nf_opened_node->bmap_bufs);
402 nandfs_free_node(struct nandfs_node *node)
404 struct bmap_buf *bmap, *tmp;
407 LIST_FOREACH_SAFE(bmap, &node->bmap_bufs, list, tmp) {
408 LIST_REMOVE(bmap, list);
416 nandfs_close(struct open_file *f)
418 struct nandfs *fs = f->f_fsdata;
420 NANDFS_DEBUG("nandfs_close(%p)\n", f);
422 if (fs->nf_buf != NULL)
425 nandfs_free_node(fs->nf_opened_node);
431 nandfs_read(struct open_file *f, void *addr, size_t size, size_t *resid)
433 struct nandfs *fs = (struct nandfs *)f->f_fsdata;
434 size_t csize, buf_size;
438 NANDFS_DEBUG("nandfs_read(file=%p, addr=%p, size=%d)\n", f, addr, size);
441 if (fs->nf_offset >= fs->nf_opened_node->inode->i_size)
444 error = nandfs_buf_read(fs, (void *)&buf, &buf_size);
449 if (csize > buf_size)
452 bcopy(buf, addr, csize);
454 fs->nf_offset += csize;
455 addr = (char *)addr + csize;
465 nandfs_seek(struct open_file *f, off_t offset, int where)
467 struct nandfs *fs = f->f_fsdata;
471 NANDFS_DEBUG("nandfs_seek(file=%p, offset=%lld, where=%d)\n", f,
474 size = fs->nf_opened_node->inode->i_size;
492 if (off < 0 || off > size) {
497 fs->nf_offset = (u_int)off;
503 nandfs_stat(struct open_file *f, struct stat *sb)
505 struct nandfs *fs = f->f_fsdata;
507 NANDFS_DEBUG("nandfs_stat(file=%p, stat=%p)\n", f, sb);
509 sb->st_size = fs->nf_opened_node->inode->i_size;
510 sb->st_mode = fs->nf_opened_node->inode->i_mode;
511 sb->st_uid = fs->nf_opened_node->inode->i_uid;
512 sb->st_gid = fs->nf_opened_node->inode->i_gid;
517 nandfs_readdir(struct open_file *f, struct dirent *d)
519 struct nandfs *fs = f->f_fsdata;
520 struct nandfs_dir_entry *dirent;
524 NANDFS_DEBUG("nandfs_readdir(file=%p, dirent=%p)\n", f, d);
526 if (fs->nf_offset >= fs->nf_opened_node->inode->i_size) {
527 NANDFS_DEBUG("nandfs_readdir(file=%p, dirent=%p) ENOENT\n",
532 if (nandfs_buf_read(fs, (void *)&buf, &buf_size)) {
533 NANDFS_DEBUG("nandfs_readdir(file=%p, dirent=%p)"
534 "buf_read failed\n", f, d);
538 NANDFS_DEBUG("nandfs_readdir(file=%p, dirent=%p) moving forward\n",
541 dirent = (struct nandfs_dir_entry *)buf;
542 fs->nf_offset += dirent->rec_len;
543 strncpy(d->d_name, dirent->name, dirent->name_len);
544 d->d_name[dirent->name_len] = '\0';
545 d->d_type = dirent->file_type;
550 nandfs_buf_read(struct nandfs *fs, char **buf_p, size_t *size_p)
552 nandfs_daddr_t blknr, blkoff;
554 blknr = fs->nf_offset / fs->nf_blocksize;
555 blkoff = fs->nf_offset % fs->nf_blocksize;
557 if (blknr != fs->nf_buf_blknr) {
558 if (fs->nf_buf == NULL)
559 fs->nf_buf = malloc(fs->nf_blocksize);
561 if (nandfs_read_inode(fs, fs->nf_opened_node, blknr, 1,
565 fs->nf_buf_blknr = blknr;
568 *buf_p = fs->nf_buf + blkoff;
569 *size_p = fs->nf_blocksize - blkoff;
571 NANDFS_DEBUG("nandfs_buf_read buf_p=%p size_p=%d\n", *buf_p, *size_p);
573 if (*size_p > fs->nf_opened_node->inode->i_size - fs->nf_offset)
574 *size_p = fs->nf_opened_node->inode->i_size - fs->nf_offset;
579 static struct nandfs_node *
580 nandfs_lookup_node(struct nandfs *fs, uint64_t ino)
584 struct nandfs_inode *buffer;
585 struct nandfs_node *node;
586 struct nandfs_inode *inode;
588 NANDFS_DEBUG("nandfs_lookup_node ino=%lld\n", ino);
591 printf("nandfs_lookup_node: invalid inode requested\n");
595 buffer = malloc(fs->nf_blocksize);
596 inode = malloc(sizeof(struct nandfs_inode));
597 node = malloc(sizeof(struct nandfs_node));
599 nandfs_mdt_trans(&fs->nf_ifile_mdt, ino, &blocknr, &entrynr);
601 if (nandfs_read_inode(fs, &fs->nf_ifile, blocknr, 1, buffer, 0))
604 memcpy(inode, &buffer[entrynr], sizeof(struct nandfs_inode));
610 static struct nandfs_node *
611 nandfs_lookup_path(struct nandfs *fs, const char *path)
613 struct nandfs_node *node;
614 struct nandfs_dir_entry *dirent;
616 uint64_t i, j, done, counter, pinode, inode;
617 int nlinks = 0, len, link_len, nameidx;
618 uint8_t *buffer, *orig;
621 buffer = malloc(fs->nf_blocksize);
624 namebuf = malloc(2 * MAXPATHLEN + 2);
625 strncpy(namebuf, path, MAXPATHLEN);
626 namebuf[MAXPATHLEN] = '\0';
630 /* Get the root inode */
631 node = nandfs_lookup_node(fs, NANDFS_ROOT_INO);
632 inode = NANDFS_ROOT_INO;
634 while ((strp = strsep(&lpath, "/")) != NULL) {
637 if ((node->inode->i_mode & IFMT) != IFDIR) {
638 nandfs_free_node(node);
644 NANDFS_DEBUG("%s: looking for %s\n", __func__, strp);
645 for (i = 0; i < node->inode->i_blocks; i++) {
646 if (nandfs_read_inode(fs, node, i, 1, orig, 0)) {
654 dirent = (struct nandfs_dir_entry *)buffer;
655 NANDFS_DEBUG("%s: dirent.name = %s\n",
656 __func__, dirent->name);
657 NANDFS_DEBUG("%s: dirent.rec_len = %d\n",
658 __func__, dirent->rec_len);
659 NANDFS_DEBUG("%s: dirent.inode = %lld\n",
660 __func__, dirent->inode);
661 if (len == dirent->name_len &&
662 (strncmp(strp, dirent->name, len) == 0) &&
663 dirent->inode != 0) {
664 nandfs_free_node(node);
665 node = nandfs_lookup_node(fs,
668 inode = dirent->inode;
673 counter += dirent->rec_len;
674 buffer += dirent->rec_len;
676 if (counter == fs->nf_blocksize)
689 NANDFS_DEBUG("%s: %.*s has mode %o\n", __func__,
690 dirent->name_len, dirent->name, node->inode->i_mode);
692 if ((node->inode->i_mode & IFMT) == IFLNK) {
693 NANDFS_DEBUG("%s: %.*s is symlink\n",
694 __func__, dirent->name_len, dirent->name);
695 link_len = node->inode->i_size;
697 if (++nlinks > MAXSYMLINKS) {
698 nandfs_free_node(node);
703 if (nandfs_read_inode(fs, node, 0, 1, orig, 0)) {
704 nandfs_free_node(node);
709 NANDFS_DEBUG("%s: symlink is %.*s\n",
710 __func__, link_len, (char *)orig);
712 nameidx = (nameidx == 0) ? MAXPATHLEN + 1 : 0;
713 bcopy((char *)orig, namebuf + nameidx,
716 namebuf[nameidx + link_len++] = '/';
717 strncpy(namebuf + nameidx + link_len, lpath,
718 MAXPATHLEN - link_len);
719 namebuf[nameidx + MAXPATHLEN] = '\0';
721 namebuf[nameidx + link_len] = '\0';
723 NANDFS_DEBUG("%s: strp=%s, lpath=%s, namebuf0=%s, "
724 "namebuf1=%s, idx=%d\n", __func__, strp, lpath,
725 namebuf + 0, namebuf + MAXPATHLEN + 1, nameidx);
727 lpath = namebuf + nameidx;
729 nandfs_free_node(node);
732 * If absolute pathname, restart at root. Otherwise
733 * continue with out parent inode.
735 inode = (orig[0] == '/') ? NANDFS_ROOT_INO : pinode;
736 node = nandfs_lookup_node(fs, inode);
747 nandfs_read_inode(struct nandfs *fs, struct nandfs_node *node,
748 nandfs_daddr_t blknr, u_int nblks, void *buf, int raw)
755 pblks = malloc(nblks * sizeof(uint64_t));
756 vblks = malloc(nblks * sizeof(uint64_t));
758 NANDFS_DEBUG("nandfs_read_inode fs=%p node=%p blknr=%lld nblks=%d\n",
759 fs, node, blknr, nblks);
760 for (i = 0; i < nblks; i++) {
761 error = nandfs_bmap_lookup(fs, node, blknr + i, &vblks[i], raw);
768 pblks[i] = nandfs_vtop(fs, vblks[i]);
773 for (i = 0; i < nblks; i++) {
774 if (ioread(fs->nf_file, pblks[i] * fs->nf_blocksize, buf,
781 buf += fs->nf_blocksize;
790 nandfs_read_blk(struct nandfs *fs, nandfs_daddr_t blknr, void *buf, int phys)
794 pblknr = (phys ? blknr : nandfs_vtop(fs, blknr));
796 return (ioread(fs->nf_file, pblknr * fs->nf_blocksize, buf,
801 nandfs_get_checkpoint(struct nandfs *fs, uint64_t cpno,
802 struct nandfs_checkpoint *cp)
805 int blockoff, cp_per_block, dlen;
808 NANDFS_DEBUG("nandfs_get_checkpoint(fs=%p cpno=%lld)\n", fs, cpno);
810 buf = malloc(fs->nf_blocksize);
812 cpno += NANDFS_CPFILE_FIRST_CHECKPOINT_OFFSET - 1;
813 dlen = fs->nf_fsdata->f_checkpoint_size;
814 cp_per_block = fs->nf_blocksize / dlen;
815 blocknr = cpno / cp_per_block;
816 blockoff = (cpno % cp_per_block) * dlen;
818 if (nandfs_read_inode(fs, &fs->nf_cpfile, blocknr, 1, buf, 0)) {
823 memcpy(cp, buf + blockoff, sizeof(struct nandfs_checkpoint));
830 nandfs_get_map(struct nandfs *fs, struct nandfs_node *node, nandfs_daddr_t blknr,
833 struct bmap_buf *bmap;
836 LIST_FOREACH(bmap, &node->bmap_bufs, list) {
837 if (bmap->blknr == blknr)
841 map = malloc(fs->nf_blocksize);
842 if (nandfs_read_blk(fs, blknr, map, phys)) {
847 bmap = malloc(sizeof(struct bmap_buf));
851 LIST_INSERT_HEAD(&node->bmap_bufs, bmap, list);
853 NANDFS_DEBUG("%s:(node=%p, map=%p)\n", __func__, node, map);
858 nandfs_bmap_lookup(struct nandfs *fs, struct nandfs_node *node,
859 nandfs_lbn_t lblknr, nandfs_daddr_t *vblknr, int phys)
861 struct nandfs_inode *ino;
862 nandfs_daddr_t ind_block_num;
863 uint64_t *map, *indir;
864 uint64_t idx0, idx1, vblk, tmp;
870 if (lblknr < NDADDR) {
871 *vblknr = ino->i_db[lblknr];
879 * nindir[1] = NINDIR**2
880 * nindir[2] = NINDIR**3
883 for (level = 0; level < NIADDR; level++) {
884 NANDFS_DEBUG("lblknr=%jx fs->nf_nindir[%d]=%d\n", lblknr, level, fs->nf_nindir[level]);
885 if (lblknr < fs->nf_nindir[level])
887 lblknr -= fs->nf_nindir[level];
890 if (level == NIADDR) {
891 /* Block number too high */
892 NANDFS_DEBUG("lblknr %jx too high\n", lblknr);
896 ind_block_num = ino->i_ib[level];
898 for (; level >= 0; level--) {
899 if (ind_block_num == 0) {
900 *vblknr = 0; /* missing */
905 NANDFS_DEBUG("calling get_map with %jx\n", ind_block_num);
906 map = nandfs_get_map(fs, node, ind_block_num, phys);
911 idx = lblknr / fs->nf_nindir[level - 1];
912 lblknr %= fs->nf_nindir[level - 1];
916 ind_block_num = ((nandfs_daddr_t *)map)[idx];
919 *vblknr = ind_block_num;
924 static nandfs_daddr_t
925 nandfs_vtop(struct nandfs *fs, nandfs_daddr_t vblocknr)
927 nandfs_lbn_t blocknr;
928 nandfs_daddr_t pblocknr;
930 struct nandfs_dat_entry *dat;
932 dat = malloc(fs->nf_blocksize);
933 nandfs_mdt_trans(&fs->nf_datfile_mdt, vblocknr, &blocknr, &entrynr);
935 if (nandfs_read_inode(fs, &fs->nf_datfile, blocknr, 1, dat, 1)) {
940 NANDFS_DEBUG("nandfs_vtop entrynr=%d vblocknr=%lld pblocknr=%lld\n",
941 entrynr, vblocknr, dat[entrynr].de_blocknr);
943 pblocknr = dat[entrynr].de_blocknr;
949 nandfs_calc_mdt_consts(int blocksize, struct nandfs_mdt *mdt, int entry_size)
952 mdt->entries_per_group = blocksize * 8; /* bits in sector */
953 mdt->entries_per_block = blocksize / entry_size;
954 mdt->blocks_per_group =
955 (mdt->entries_per_group -1) / mdt->entries_per_block + 1 + 1;
956 mdt->groups_per_desc_block =
957 blocksize / sizeof(struct nandfs_block_group_desc);
958 mdt->blocks_per_desc_block =
959 mdt->groups_per_desc_block * mdt->blocks_per_group + 1;
963 nandfs_mdt_trans(struct nandfs_mdt *mdt, uint64_t index,
964 nandfs_daddr_t *blocknr, uint32_t *entry_in_block)
966 nandfs_daddr_t blknr;
967 uint64_t group, group_offset, blocknr_in_group;
968 uint64_t desc_block, desc_offset;
970 /* Calculate our offset in the file */
971 group = index / mdt->entries_per_group;
972 group_offset = index % mdt->entries_per_group;
973 desc_block = group / mdt->groups_per_desc_block;
974 desc_offset = group % mdt->groups_per_desc_block;
975 blocknr_in_group = group_offset / mdt->entries_per_block;
977 /* To descgroup offset */
978 blknr = 1 + desc_block * mdt->blocks_per_desc_block;
980 /* To group offset */
981 blknr += desc_offset * mdt->blocks_per_group;
983 /* To actual file block */
984 blknr += 1 + blocknr_in_group;
987 *entry_in_block = group_offset % mdt->entries_per_block;
991 ioread(struct open_file *f, off_t pos, void *buf, u_int length)
995 int bsize = ((struct nandfs *)f->f_fsdata)->nf_sectorsize;
1000 nsec = (length + (bsize - 1)) / bsize;
1002 NANDFS_DEBUG("pos=%lld length=%d off=%d nsec=%d\n", pos, length,
1005 buffer = malloc(nsec * bsize);
1007 err = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, pos,
1008 nsec * bsize, buffer, NULL);
1010 memcpy(buf, buffer + off, length);
1017 nandfs_probe_sectorsize(struct open_file *f)
1022 buffer = malloc(16 * 1024);
1024 NANDFS_DEBUG("probing for sector size: ");
1026 for (i = 512; i < (16 * 1024); i <<= 1) {
1027 NANDFS_DEBUG("%d ", i);
1028 err = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 0, i,
1032 NANDFS_DEBUG("found");
1039 NANDFS_DEBUG("not found\n");