import netbsd ext2fs fsck and newfs
This commit is contained in:
parent
4d4057d8a2
commit
94715d8e54
61 changed files with 14958 additions and 5 deletions
|
@ -23,6 +23,10 @@ TOTALMB="`expr 3 + $USRKB / 1024 + $ROOTMB`"
|
|||
ROOTFILES="`cat /.rootfiles`"
|
||||
USRFILES="`cat /.usrfiles`"
|
||||
|
||||
if [ -z "$FSTYPE" ]
|
||||
then FSTYPE=mfs
|
||||
fi
|
||||
|
||||
if [ "$TOTALMB" -lt 1 ]
|
||||
then
|
||||
echo "Are you really running from CD?"
|
||||
|
@ -459,17 +463,17 @@ if [ "$nohome" = 0 ]
|
|||
then
|
||||
if [ ! "$auto" = r ]
|
||||
then echo "Creating /dev/$home for /home .."
|
||||
mkfs.mfs -B $blocksizebytes /dev/$home || exit
|
||||
mkfs.$FSTYPE -B $blocksizebytes /dev/$home || exit
|
||||
fi
|
||||
else echo "Skipping /home"
|
||||
fi
|
||||
|
||||
echo "Creating /dev/$usr for /usr .."
|
||||
mkfs.mfs -B $blocksizebytes /dev/$usr || exit
|
||||
mkfs.$FSTYPE -B $blocksizebytes /dev/$usr || exit
|
||||
|
||||
if [ "$nohome" = 0 ]
|
||||
then
|
||||
fshome="/dev/$home /home mfs rw 0 2"
|
||||
fshome="/dev/$home /home $FSTYPE rw 0 2"
|
||||
else fshome=""
|
||||
fi
|
||||
|
||||
|
@ -504,7 +508,7 @@ ln -s /usr/log /mnt/var/log
|
|||
# CD remnants that aren't for the installed system
|
||||
rm /mnt/etc/issue /mnt/CD /mnt/.* 2>/dev/null
|
||||
echo >/mnt/etc/fstab "/dev/$root / mfs rw 0 1
|
||||
/dev/$usr /usr mfs rw 0 2
|
||||
/dev/$usr /usr $FSTYPE rw 0 2
|
||||
$fshome"
|
||||
|
||||
# National keyboard map.
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
#include <minix/types.h>
|
||||
#endif
|
||||
|
||||
#include <minix/u64.h>
|
||||
|
||||
int minix_sizeup(char *name, u64_t *bytes);
|
||||
|
||||
struct partition {
|
||||
u64_t base; /* byte offset to the partition start */
|
||||
u64_t size; /* number of bytes in the partition */
|
||||
|
|
|
@ -180,6 +180,7 @@ struct disklabel {
|
|||
uint16_t d_npartitions; /* number of partitions in following */
|
||||
uint32_t d_bbsize; /* size of boot area at sn0, bytes */
|
||||
uint32_t d_sbsize; /* max size of fs superblock, bytes */
|
||||
#ifndef __minix
|
||||
struct partition { /* the partition table */
|
||||
uint32_t p_size; /* number of sectors in partition */
|
||||
uint32_t p_offset; /* starting sector */
|
||||
|
@ -199,6 +200,7 @@ struct disklabel {
|
|||
#define p_cpg __partition_u1.cpg
|
||||
#define p_sgs __partition_u1.sgs
|
||||
} d_partitions[MAXPARTITIONS]; /* actually may be more */
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined(__HAVE_OLD_DISKLABEL) && !HAVE_NBTOOL_CONFIG_H
|
||||
|
|
|
@ -38,6 +38,31 @@ __RCSID("$NetBSD: uuid_create.c,v 1.1 2004/09/13 21:44:54 thorpej Exp $");
|
|||
|
||||
#include <uuid.h>
|
||||
|
||||
#ifdef __minix
|
||||
#include <paths.h>
|
||||
#include <fcntl.h>
|
||||
/* Fake a uuidgen() syscall */
|
||||
int uuidgen(struct uuid *store, int count)
|
||||
{
|
||||
int rfd;
|
||||
|
||||
if((rfd = open(_PATH_RANDOM, O_RDONLY)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
while(count--) {
|
||||
if(read(rfd, store++, sizeof(*store)) < sizeof(*store)) {
|
||||
close(rfd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
close(rfd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* uuid_create() - create an UUID.
|
||||
* See also:
|
||||
|
|
|
@ -24,6 +24,20 @@ INCS= a.out.h aio.h ar.h assert.h atomic.h \
|
|||
strings.h stringlist.h struct.h sysexits.h tar.h time.h \
|
||||
ttyent.h tzfile.h ucontext.h ulimit.h unistd.h util.h utime.h utmp.h \
|
||||
utmpx.h uuid.h varargs.h vis.h wchar.h wctype.h wordexp.h
|
||||
|
||||
INCS += ufs/chfs/chfs.h ufs/chfs/chfs_args.h ufs/chfs/chfs_inode.h \
|
||||
ufs/chfs/chfs_pool.h ufs/chfs/debug.h ufs/chfs/ebh.h \
|
||||
ufs/chfs/ebh_media.h ufs/chfs/ebh_misc.h ufs/chfs/media.h \
|
||||
ufs/ext2fs/ext2fs.h ufs/ext2fs/ext2fs_dinode.h \
|
||||
ufs/ext2fs/ext2fs_dir.h ufs/ext2fs/ext2fs_extern.h \
|
||||
ufs/ffs/ffs_extern.h ufs/ffs/fs.h ufs/lfs/lfs.h \
|
||||
ufs/lfs/lfs_extern.h ufs/mfs/mfs_extern.h ufs/mfs/mfsnode.h \
|
||||
ufs/ufs/dinode.h ufs/ufs/dir.h ufs/ufs/dirhash.h \
|
||||
ufs/ufs/extattr.h ufs/ufs/inode.h ufs/ufs/quota.h \
|
||||
ufs/ufs/quota1.h ufs/ufs/quota2.h ufs/ufs/ufs_bswap.h \
|
||||
ufs/ufs/ufs_extern.h ufs/ufs/ufs_quota.h ufs/ufs/ufs_wapbl.h \
|
||||
ufs/ufs/ufsmount.h \
|
||||
|
||||
.else
|
||||
INCS= a.out.h aio.h ar.h assert.h atomic.h \
|
||||
bitstring.h bm.h cdbr.h cdbw.h complex.h cpio.h ctype.h \
|
||||
|
|
768
nbsd_include/ufs/chfs/chfs.h
Normal file
768
nbsd_include/ufs/chfs/chfs.h
Normal file
|
@ -0,0 +1,768 @@
|
|||
/* $NetBSD: chfs.h,v 1.4 2011/11/28 12:50:07 ahoka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Department of Software Engineering,
|
||||
* University of Szeged, Hungary
|
||||
* Copyright (C) 2009 Ferenc Havasi <havasi@inf.u-szeged.hu>
|
||||
* Copyright (C) 2009 Zoltan Sogor <weth@inf.u-szeged.hu>
|
||||
* Copyright (C) 2009 David Tengeri <dtengeri@inf.u-szeged.hu>
|
||||
* Copyright (C) 2009 Tamas Toth <ttoth@inf.u-szeged.hu>
|
||||
* Copyright (C) 2010 Adam Hoka <ahoka@NetBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by the Department of Software Engineering, University of Szeged, Hungary
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __CHFS_H__
|
||||
#define __CHFS_H__
|
||||
|
||||
#if 0
|
||||
#define DBG_MSG
|
||||
#define DBG_MSG_GC
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/tree.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/kmem.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/rwlock.h>
|
||||
#include <sys/condvar.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/kthread.h>
|
||||
#include <sys/rbtree.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/hash.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/dirent.h>
|
||||
|
||||
#include <ufs/ufs/quota.h>
|
||||
#include <ufs/ufs/ufsmount.h>
|
||||
#include <ufs/ufs/dir.h>
|
||||
|
||||
/* XXX shouldnt be defined here, but needed by chfs_inode.h */
|
||||
TAILQ_HEAD(chfs_dirent_list, chfs_dirent);
|
||||
|
||||
#include "chfs_pool.h"
|
||||
#include "ebh.h"
|
||||
#include "media.h"
|
||||
#include "chfs_inode.h"
|
||||
|
||||
#ifndef MOUNT_CHFS
|
||||
#define MOUNT_CHFS "chfs"
|
||||
#endif
|
||||
|
||||
#define CHFS_ROOTINO ROOTINO /* ROOTINO == 2 */
|
||||
|
||||
enum {
|
||||
VNO_STATE_UNCHECKED, /* CRC checks not yet done */
|
||||
VNO_STATE_CHECKING, /* CRC checks in progress */
|
||||
VNO_STATE_PRESENT, /* In core */
|
||||
VNO_STATE_CHECKEDABSENT,/* Checked, cleared again */
|
||||
VNO_STATE_GC, /* GCing a 'pristine' node */
|
||||
VNO_STATE_READING, /* In read_inode() */
|
||||
VNO_STATE_CLEARING /* In clear_inode() */
|
||||
};
|
||||
|
||||
#define VNODECACHE_SIZE 128
|
||||
|
||||
#define MAX_READ_FREE(chmp) (((chmp)->chm_ebh)->eb_size / 8)
|
||||
/* an eraseblock will be clean if its dirty size is smaller than this */
|
||||
#define MAX_DIRTY_TO_CLEAN 255
|
||||
#define VERY_DIRTY(chmp, size) ((size) >= (((chmp)->chm_ebh)->eb_size / 2))
|
||||
|
||||
#define CHFS_PAD(x) (((x)+3)&~3)
|
||||
|
||||
enum {
|
||||
CHFS_NODE_OK = 0,
|
||||
CHFS_NODE_BADMAGIC,
|
||||
CHFS_NODE_BADCRC,
|
||||
CHFS_NODE_BADNAMECRC
|
||||
};
|
||||
|
||||
enum {
|
||||
CHFS_BLK_STATE_FREE = 100,
|
||||
CHFS_BLK_STATE_CLEAN,
|
||||
CHFS_BLK_STATE_PARTDIRTY,
|
||||
CHFS_BLK_STATE_ALLDIRTY
|
||||
};
|
||||
|
||||
extern struct pool chfs_inode_pool;
|
||||
extern const struct genfs_ops chfs_genfsops;
|
||||
|
||||
/**
|
||||
* struct chfs_node_ref - a reference to a node
|
||||
* @lnr: logical identifier of the eraseblock where the node is
|
||||
* @offset: offset int hte eraseblock where the node starts
|
||||
* @next: used at data and dirent nodes, it points to the next data node which
|
||||
* belongs to the same vnode
|
||||
*/
|
||||
struct chfs_node_ref
|
||||
{
|
||||
struct chfs_node_ref *nref_next;
|
||||
uint32_t nref_lnr;
|
||||
uint32_t nref_offset;
|
||||
};
|
||||
|
||||
/* Constants for allocating node refs */
|
||||
#define REFS_BLOCK_LEN (255/sizeof(struct chfs_node_ref))
|
||||
#define REF_EMPTY_NODE (UINT_MAX)
|
||||
#define REF_LINK_TO_NEXT (UINT_MAX - 1)
|
||||
|
||||
enum {
|
||||
CHFS_NORMAL_NODE_MASK,
|
||||
CHFS_UNCHECKED_NODE_MASK,
|
||||
CHFS_OBSOLETE_NODE_MASK,
|
||||
CHFS_PRISTINE_NODE_MASK
|
||||
};
|
||||
|
||||
#define CHFS_REF_FLAGS(ref) ((ref)->nref_offset & 3)
|
||||
#define CHFS_REF_OBSOLETE(ref) (((ref)->nref_offset & 3) == CHFS_OBSOLETE_NODE_MASK)
|
||||
#define CHFS_MARK_REF_NORMAL(ref) \
|
||||
do { \
|
||||
(ref)->nref_offset = CHFS_GET_OFS((ref)->nref_offset) | CHFS_NORMAL_NODE_MASK; \
|
||||
} while(0)
|
||||
|
||||
#define CHFS_GET_OFS(ofs) (ofs & ~ 3)
|
||||
|
||||
static inline struct chfs_node_ref *
|
||||
node_next(struct chfs_node_ref *nref)
|
||||
{
|
||||
//dbg("node next: %u : %u\n", nref->nref_lnr, nref->nref_offset);
|
||||
nref++;
|
||||
//dbg("nref++: %u : %u\n", nref->nref_lnr, nref->nref_offset);
|
||||
|
||||
if (nref->nref_lnr == REF_LINK_TO_NEXT) {
|
||||
//dbg("link to next\n");
|
||||
nref = nref->nref_next;
|
||||
if (!nref)
|
||||
return nref;
|
||||
}
|
||||
|
||||
if (nref->nref_lnr == REF_EMPTY_NODE) {
|
||||
//dbg("empty\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return nref;
|
||||
}
|
||||
|
||||
/**
|
||||
* struct chfs_dirent - full representation of a directory entry
|
||||
*/
|
||||
struct chfs_dirent
|
||||
{
|
||||
struct chfs_node_ref *nref;
|
||||
// struct chfs_dirent *next;
|
||||
TAILQ_ENTRY(chfs_dirent) fds;
|
||||
uint64_t version;
|
||||
ino_t vno;
|
||||
uint32_t nhash;
|
||||
enum vtype type;
|
||||
uint8_t nsize;
|
||||
uint8_t name[0];
|
||||
|
||||
/* used by chfs_alloc_dirent and free counterpart */
|
||||
// size_t alloc_size;
|
||||
};
|
||||
|
||||
struct chfs_tmp_dnode {
|
||||
struct chfs_full_dnode *node;
|
||||
uint64_t version;
|
||||
uint32_t data_crc;
|
||||
//uint32_t partial_crc;
|
||||
//uint16_t csize;
|
||||
uint16_t overlapped;
|
||||
struct chfs_tmp_dnode *next;
|
||||
};
|
||||
|
||||
struct chfs_tmp_dnode_info {
|
||||
struct rb_node rb_node;
|
||||
struct chfs_tmp_dnode *tmpnode;
|
||||
};
|
||||
|
||||
struct chfs_readinode_info {
|
||||
struct rb_tree tdi_root;
|
||||
struct chfs_tmp_dnode_info *mdata_tn;
|
||||
uint64_t highest_version;
|
||||
struct chfs_node_ref *latest_ref;
|
||||
};
|
||||
|
||||
struct chfs_full_dnode {
|
||||
struct chfs_node_ref *nref;
|
||||
uint64_t ofs;
|
||||
uint32_t size;
|
||||
uint32_t frags;
|
||||
};
|
||||
|
||||
struct chfs_node_frag {
|
||||
struct rb_node rb_node;
|
||||
struct chfs_full_dnode *node;
|
||||
uint32_t size;
|
||||
uint64_t ofs;
|
||||
};
|
||||
|
||||
static inline struct chfs_node_frag *
|
||||
frag_first(struct rb_tree *tree)
|
||||
{
|
||||
struct chfs_node_frag *frag;
|
||||
|
||||
frag = (struct chfs_node_frag *)RB_TREE_MIN(tree);
|
||||
|
||||
return frag;
|
||||
}
|
||||
|
||||
static inline struct chfs_node_frag *
|
||||
frag_last(struct rb_tree *tree)
|
||||
{
|
||||
struct chfs_node_frag *frag;
|
||||
|
||||
frag = (struct chfs_node_frag *)RB_TREE_MAX(tree);
|
||||
|
||||
return frag;
|
||||
}
|
||||
|
||||
#define frag_next(tree, frag) (struct chfs_node_frag *)rb_tree_iterate(tree, frag, RB_DIR_RIGHT)
|
||||
#define frag_prev(tree, frag) (struct chfs_node_frag *)rb_tree_iterate(tree, frag, RB_DIR_LEFT)
|
||||
|
||||
|
||||
/* XXX hack
|
||||
#ifndef CHFS_FRAG_TREE
|
||||
#define CHFS_FRAG_TREE
|
||||
RB_HEAD(chfs_frag_tree, chfs_node_frag);
|
||||
#endif
|
||||
*/
|
||||
|
||||
/* for prototypes, properly defined in chfs_inode.h */
|
||||
//struct chfs_inode_ext;
|
||||
|
||||
/**
|
||||
* struct chfs_vnode_cache - in memory representation of a vnode
|
||||
* @v: pointer to the vnode info node
|
||||
* @dnode: pointer to the list of data nodes
|
||||
* @dirents: pointer to the list of directory entries
|
||||
* @vno_version: used only during scan, holds the current version number of
|
||||
* chfs_flash_vnode
|
||||
* @scan_dirents: used only during scan, holds the full representation of
|
||||
* directory entries of this vnode
|
||||
* @pvno: parent vnode number
|
||||
* @nlink: number of links to this vnode
|
||||
*/
|
||||
struct chfs_vnode_cache {
|
||||
// struct chfs_dirent *scan_dirents;
|
||||
void *p;
|
||||
struct chfs_dirent_list scan_dirents;
|
||||
|
||||
struct chfs_node_ref *v;
|
||||
struct chfs_node_ref *dnode;
|
||||
struct chfs_node_ref *dirents;
|
||||
|
||||
uint64_t *vno_version;
|
||||
uint64_t highest_version;
|
||||
|
||||
uint8_t flags;
|
||||
uint16_t state;
|
||||
ino_t vno;
|
||||
ino_t pvno;
|
||||
struct chfs_vnode_cache* next;
|
||||
uint32_t nlink;
|
||||
};
|
||||
|
||||
struct chfs_eraseblock
|
||||
{
|
||||
uint32_t lnr;
|
||||
|
||||
TAILQ_ENTRY(chfs_eraseblock) queue;
|
||||
//uint32_t bad_count;
|
||||
uint32_t unchecked_size;
|
||||
uint32_t used_size;
|
||||
uint32_t dirty_size;
|
||||
uint32_t free_size;
|
||||
uint32_t wasted_size;
|
||||
|
||||
struct chfs_node_ref *first_node;
|
||||
struct chfs_node_ref *last_node;
|
||||
|
||||
/* Next block to be garbage collected */
|
||||
struct chfs_node_ref *gc_node;
|
||||
};
|
||||
|
||||
TAILQ_HEAD(chfs_eraseblock_queue, chfs_eraseblock);
|
||||
|
||||
#define ALLOC_NORMAL 0
|
||||
#define ALLOC_DELETION 1
|
||||
#define ALLOC_GC 2
|
||||
|
||||
struct garbage_collector_thread {
|
||||
lwp_t *gcth_thread;
|
||||
kcondvar_t gcth_wakeup;
|
||||
bool gcth_running;
|
||||
};
|
||||
|
||||
#define CHFS_MP_FLAG_SCANNING 2
|
||||
#define CHFS_MP_FLAG_BUILDING 4
|
||||
|
||||
/**
|
||||
* struct chfs_mount - CHFS main descriptor structure
|
||||
* @ebh: eraseblock handler
|
||||
* @fl_index: index of flash device in the flash layer
|
||||
* @fs_version: filesystem version descriptor
|
||||
* @gbl_version: global version number
|
||||
* @max_vno: max vnode id
|
||||
* @chm_lock_mountfields:
|
||||
* @vnocache_hash: hash table of vnode caches
|
||||
* @vnocache_lock:
|
||||
* @blocks: array of eraseblocks on flash
|
||||
* @chm_root: used to protect all fields
|
||||
* @free_size: free size on the flash
|
||||
* @dirty_size: dirtied size on flash
|
||||
* @unchecked_size: size of unchecked data on flash
|
||||
* @free_queue: queue of free eraseblocks
|
||||
* @clean_queue: queue of clean eraseblocks
|
||||
* @dirty_queue: queue of dirty eraseblocks
|
||||
* @very_dirty_queue: queue of very dirty eraseblocks
|
||||
* @erase_pending_queue: queue of eraseblocks waiting for erasing
|
||||
* @erasable_pending_wbuf_queue: queue of eraseblocks waiting for erasing and
|
||||
* have data to write to them
|
||||
* @nextblock: next eraseblock to write to
|
||||
* @nr_free_blocks: number of free blocks on the free_queue
|
||||
* @nr_erasable_blocks: number of blocks that can be erased and are on the
|
||||
* erasable_queue
|
||||
*/
|
||||
struct chfs_mount {
|
||||
struct mount *chm_fsmp;
|
||||
struct chfs_ebh *chm_ebh;
|
||||
int chm_fs_version;
|
||||
uint64_t chm_gbl_version;
|
||||
ino_t chm_max_vno;
|
||||
ino_t chm_checked_vno;
|
||||
unsigned int chm_flags;
|
||||
|
||||
/* chm_lock_mountfields:
|
||||
* Used to protect all the following fields. */
|
||||
kmutex_t chm_lock_mountfields;
|
||||
|
||||
struct chfs_vnode_cache **chm_vnocache_hash;
|
||||
/* chm_lock_vnocache:
|
||||
* Used to protect the vnode cache.
|
||||
* If you have to lock chm_lock_mountfields and also chm_lock_vnocache,
|
||||
* you must lock chm_lock_mountfields first. */
|
||||
kmutex_t chm_lock_vnocache;
|
||||
|
||||
struct chfs_eraseblock *chm_blocks;
|
||||
|
||||
struct chfs_node *chm_root;
|
||||
|
||||
uint32_t chm_free_size;
|
||||
uint32_t chm_dirty_size;
|
||||
uint32_t chm_unchecked_size;
|
||||
uint32_t chm_used_size;
|
||||
uint32_t chm_wasted_size;
|
||||
/* chm_lock_sizes:
|
||||
* Used to protect the (free, used, etc.) sizes of the FS
|
||||
* (and also the sizes of each eraseblock).
|
||||
* If you have to lock chm_lock_mountfields and also chm_lock_sizes,
|
||||
* you must lock chm_lock_mountfields first. */
|
||||
kmutex_t chm_lock_sizes;
|
||||
|
||||
struct chfs_eraseblock_queue chm_free_queue;
|
||||
struct chfs_eraseblock_queue chm_clean_queue;
|
||||
struct chfs_eraseblock_queue chm_dirty_queue;
|
||||
struct chfs_eraseblock_queue chm_very_dirty_queue;
|
||||
struct chfs_eraseblock_queue chm_erasable_pending_wbuf_queue;
|
||||
struct chfs_eraseblock_queue chm_erase_pending_queue;
|
||||
|
||||
uint8_t chm_resv_blocks_deletion;
|
||||
uint8_t chm_resv_blocks_write;
|
||||
uint8_t chm_resv_blocks_gctrigger;
|
||||
uint8_t chm_resv_blocks_gcmerge;
|
||||
uint8_t chm_nospc_dirty;
|
||||
|
||||
uint8_t chm_vdirty_blocks_gctrigger;
|
||||
|
||||
struct chfs_eraseblock *chm_nextblock;
|
||||
|
||||
struct garbage_collector_thread chm_gc_thread;
|
||||
struct chfs_eraseblock *chm_gcblock;
|
||||
|
||||
int chm_nr_free_blocks;
|
||||
int chm_nr_erasable_blocks;
|
||||
|
||||
int32_t chm_fs_bmask;
|
||||
int32_t chm_fs_bsize;
|
||||
int32_t chm_fs_qbmask;
|
||||
int32_t chm_fs_bshift;
|
||||
int32_t chm_fs_fmask;
|
||||
int64_t chm_fs_qfmask;
|
||||
|
||||
/* TODO will we use these? */
|
||||
unsigned int chm_pages_max;
|
||||
unsigned int chm_pages_used;
|
||||
unsigned int chm_nodes_max;
|
||||
unsigned int chm_nodes_cnt;
|
||||
struct chfs_pool chm_dirent_pool;
|
||||
struct chfs_pool chm_node_pool;
|
||||
struct chfs_str_pool chm_str_pool;
|
||||
/**/
|
||||
|
||||
size_t chm_wbuf_pagesize;
|
||||
unsigned char* chm_wbuf;
|
||||
size_t chm_wbuf_ofs;
|
||||
size_t chm_wbuf_len;
|
||||
/* chm_lock_wbuf:
|
||||
* Used to protect the write buffer.
|
||||
* If you have to lock chm_lock_mountfields and also chm_lock_wbuf,
|
||||
* you must lock chm_lock_mountfields first. */
|
||||
krwlock_t chm_lock_wbuf;
|
||||
};
|
||||
|
||||
/*
|
||||
* TODO we should move here all of these from the bottom of the file
|
||||
* Macros/functions to convert from generic data structures to chfs
|
||||
* specific ones.
|
||||
*/
|
||||
|
||||
#define CHFS_OFFSET_DOT 0
|
||||
#define CHFS_OFFSET_DOTDOT 1
|
||||
#define CHFS_OFFSET_EOF 2
|
||||
#define CHFS_OFFSET_FIRST 3
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/* chfs_build.c */
|
||||
void chfs_calc_trigger_levels(struct chfs_mount *);
|
||||
int chfs_build_filesystem(struct chfs_mount *);
|
||||
void chfs_build_set_vnodecache_nlink(struct chfs_mount *,
|
||||
struct chfs_vnode_cache *);
|
||||
void chfs_build_remove_unlinked_vnode(struct chfs_mount *,
|
||||
struct chfs_vnode_cache *, struct chfs_dirent_list *);
|
||||
|
||||
/* chfs_scan.c */
|
||||
int chfs_scan_eraseblock(struct chfs_mount *, struct chfs_eraseblock *);
|
||||
struct chfs_vnode_cache *chfs_scan_make_vnode_cache(struct chfs_mount *,
|
||||
ino_t);
|
||||
int chfs_scan_check_node_hdr(struct chfs_flash_node_hdr *);
|
||||
int chfs_scan_check_vnode(struct chfs_mount *,
|
||||
struct chfs_eraseblock *, void *, off_t);
|
||||
int chfs_scan_mark_dirent_obsolete(struct chfs_mount *,
|
||||
struct chfs_vnode_cache *, struct chfs_dirent *);
|
||||
void chfs_add_fd_to_list(struct chfs_mount *,
|
||||
struct chfs_dirent *, struct chfs_vnode_cache *);
|
||||
int chfs_scan_check_dirent_node(struct chfs_mount *,
|
||||
struct chfs_eraseblock *, void *, off_t);
|
||||
int chfs_scan_check_data_node(struct chfs_mount *,
|
||||
struct chfs_eraseblock *, void *, off_t);
|
||||
int chfs_scan_classify_cheb(struct chfs_mount *,
|
||||
struct chfs_eraseblock *);
|
||||
|
||||
/* chfs_nodeops.c */
|
||||
int chfs_update_eb_dirty(struct chfs_mount *,
|
||||
struct chfs_eraseblock *, uint32_t);
|
||||
void chfs_add_node_to_list(struct chfs_mount *, struct chfs_vnode_cache *,
|
||||
struct chfs_node_ref *, struct chfs_node_ref **);
|
||||
void chfs_add_fd_to_inode(struct chfs_mount *,
|
||||
struct chfs_inode *, struct chfs_dirent *);
|
||||
void chfs_add_vnode_ref_to_vc(struct chfs_mount *, struct chfs_vnode_cache *,
|
||||
struct chfs_node_ref *);
|
||||
struct chfs_node_ref* chfs_nref_next(struct chfs_node_ref *);
|
||||
int chfs_nref_len(struct chfs_mount *,
|
||||
struct chfs_eraseblock *, struct chfs_node_ref *);
|
||||
int chfs_close_eraseblock(struct chfs_mount *,
|
||||
struct chfs_eraseblock *);
|
||||
int chfs_reserve_space_normal(struct chfs_mount *, uint32_t, int);
|
||||
int chfs_reserve_space_gc(struct chfs_mount *, uint32_t);
|
||||
int chfs_reserve_space(struct chfs_mount *, uint32_t);
|
||||
void chfs_mark_node_obsolete(struct chfs_mount *, struct chfs_node_ref *);
|
||||
|
||||
static inline struct chfs_vnode_cache *
|
||||
chfs_nref_to_vc(struct chfs_node_ref *nref)
|
||||
{
|
||||
while (nref->nref_next) {
|
||||
nref = nref->nref_next;
|
||||
//dbg("lnr: %u, ofs: %u\n", nref->nref_lnr, nref->nref_offset);
|
||||
//dbg("vno: %llu\n", ((struct chfs_vnode_cache *)(nref))->vno);
|
||||
//dbg("scan_dirents: %p\n", ((struct chfs_vnode_cache *)(nref))->scan_dirents);
|
||||
if (nref->nref_lnr == REF_LINK_TO_NEXT) {
|
||||
dbg("Link to next!\n");
|
||||
} else if (nref->nref_lnr == REF_EMPTY_NODE) {
|
||||
dbg("Empty!\n");
|
||||
}
|
||||
}
|
||||
//dbg("vno: %llu\n", ((struct chfs_vnode_cache *)(nref))->vno);
|
||||
|
||||
//dbg("NREF_TO_VC: GET IT\n");
|
||||
//dbg("nref_next: %p, lnr: %u, ofs: %u\n", nref->nref_next, nref->nref_lnr, nref->nref_offset);
|
||||
struct chfs_vnode_cache *vc = (struct chfs_vnode_cache *) nref;
|
||||
dbg("vno: %ju, pvno: %ju, hv: %ju, nlink: %u\n", (intmax_t )vc->vno,
|
||||
(intmax_t )vc->pvno, (intmax_t )vc->highest_version, vc->nlink);
|
||||
//return ((struct chfs_vnode_cache *)nref);
|
||||
return vc;
|
||||
}
|
||||
|
||||
|
||||
/* chfs_malloc.c */
|
||||
int chfs_alloc_pool_caches(void);
|
||||
void chfs_destroy_pool_caches(void);
|
||||
struct chfs_vnode_cache* chfs_vnode_cache_alloc(ino_t);
|
||||
void chfs_vnode_cache_free(struct chfs_vnode_cache *);
|
||||
struct chfs_node_ref* chfs_alloc_node_ref(
|
||||
struct chfs_eraseblock *);
|
||||
void chfs_free_node_refs(struct chfs_eraseblock *);
|
||||
struct chfs_dirent* chfs_alloc_dirent(int);
|
||||
void chfs_free_dirent(struct chfs_dirent *);
|
||||
struct chfs_flash_vnode* chfs_alloc_flash_vnode(void);
|
||||
void chfs_free_flash_vnode(struct chfs_flash_vnode *);
|
||||
struct chfs_flash_dirent_node* chfs_alloc_flash_dirent(void);
|
||||
void chfs_free_flash_dirent(struct chfs_flash_dirent_node *);
|
||||
struct chfs_flash_data_node* chfs_alloc_flash_dnode(void);
|
||||
void chfs_free_flash_dnode(struct chfs_flash_data_node *);
|
||||
struct chfs_node_frag* chfs_alloc_node_frag(void);
|
||||
void chfs_free_node_frag(struct chfs_node_frag *);
|
||||
struct chfs_node_ref* chfs_alloc_refblock(void);
|
||||
void chfs_free_refblock(struct chfs_node_ref *);
|
||||
struct chfs_full_dnode* chfs_alloc_full_dnode(void);
|
||||
void chfs_free_full_dnode(struct chfs_full_dnode *);
|
||||
struct chfs_tmp_dnode * chfs_alloc_tmp_dnode(void);
|
||||
void chfs_free_tmp_dnode(struct chfs_tmp_dnode *);
|
||||
struct chfs_tmp_dnode_info * chfs_alloc_tmp_dnode_info(void);
|
||||
void chfs_free_tmp_dnode_info(struct chfs_tmp_dnode_info *);
|
||||
|
||||
/* chfs_readinode.c */
|
||||
int chfs_read_inode(struct chfs_mount *, struct chfs_inode *);
|
||||
int chfs_read_inode_internal(struct chfs_mount *, struct chfs_inode *);
|
||||
void chfs_kill_fragtree(struct rb_tree *);
|
||||
uint32_t chfs_truncate_fragtree(struct chfs_mount *,
|
||||
struct rb_tree *, uint32_t);
|
||||
int chfs_add_full_dnode_to_inode(struct chfs_mount *,
|
||||
struct chfs_inode *,
|
||||
struct chfs_full_dnode *);
|
||||
int chfs_read_data(struct chfs_mount*, struct vnode *,
|
||||
struct buf *);
|
||||
|
||||
/* chfs_erase.c */
|
||||
int chfs_remap_leb(struct chfs_mount *);
|
||||
|
||||
/* chfs_ihash.c */
|
||||
void chfs_ihashinit(void);
|
||||
void chfs_ihashreinit(void);
|
||||
void chfs_ihashdone(void);
|
||||
struct vnode *chfs_ihashlookup(dev_t, ino_t);
|
||||
struct vnode *chfs_ihashget(dev_t, ino_t, int);
|
||||
void chfs_ihashins(struct chfs_inode *);
|
||||
void chfs_ihashrem(struct chfs_inode *);
|
||||
|
||||
extern kmutex_t chfs_ihash_lock;
|
||||
extern kmutex_t chfs_hashlock;
|
||||
|
||||
/* chfs_gc.c */
|
||||
void chfs_gc_trigger(struct chfs_mount *);
|
||||
int chfs_gc_thread_should_wake(struct chfs_mount *);
|
||||
void chfs_gc_thread(void *);
|
||||
void chfs_gc_thread_start(struct chfs_mount *);
|
||||
void chfs_gc_thread_stop(struct chfs_mount *);
|
||||
int chfs_gcollect_pass(struct chfs_mount *);
|
||||
|
||||
/* chfs_vfsops.c*/
|
||||
int chfs_gop_alloc(struct vnode *, off_t, off_t, int, kauth_cred_t);
|
||||
int chfs_mountfs(struct vnode *, struct mount *);
|
||||
|
||||
/* chfs_vnops.c */
|
||||
extern int (**chfs_vnodeop_p)(void *);
|
||||
extern int (**chfs_specop_p)(void *);
|
||||
extern int (**chfs_fifoop_p)(void *);
|
||||
int chfs_lookup(void *);
|
||||
int chfs_create(void *);
|
||||
int chfs_mknod(void *);
|
||||
int chfs_open(void *);
|
||||
int chfs_close(void *);
|
||||
int chfs_access(void *);
|
||||
int chfs_getattr(void *);
|
||||
int chfs_setattr(void *);
|
||||
int chfs_chown(struct vnode *, uid_t, gid_t, kauth_cred_t);
|
||||
int chfs_chmod(struct vnode *, int, kauth_cred_t);
|
||||
int chfs_read(void *);
|
||||
int chfs_write(void *);
|
||||
int chfs_fsync(void *);
|
||||
int chfs_remove(void *);
|
||||
int chfs_link(void *);
|
||||
int chfs_rename(void *);
|
||||
int chfs_mkdir(void *);
|
||||
int chfs_rmdir(void *);
|
||||
int chfs_symlink(void *);
|
||||
int chfs_readdir(void *);
|
||||
int chfs_readlink(void *);
|
||||
int chfs_inactive(void *);
|
||||
int chfs_reclaim(void *);
|
||||
int chfs_advlock(void *);
|
||||
int chfs_strategy(void *);
|
||||
int chfs_bmap(void *);
|
||||
|
||||
/* chfs_vnode.c */
|
||||
struct vnode *chfs_vnode_lookup(struct chfs_mount *, ino_t);
|
||||
int chfs_readvnode(struct mount *, ino_t, struct vnode **);
|
||||
int chfs_readdirent(struct mount *, struct chfs_node_ref *,
|
||||
struct chfs_inode *);
|
||||
int chfs_makeinode(int, struct vnode *, struct vnode **,
|
||||
struct componentname *, int );
|
||||
void chfs_set_vnode_size(struct vnode *, size_t);
|
||||
void chfs_change_size_free(struct chfs_mount *,
|
||||
struct chfs_eraseblock *, int);
|
||||
void chfs_change_size_dirty(struct chfs_mount *,
|
||||
struct chfs_eraseblock *, int);
|
||||
void chfs_change_size_unchecked(struct chfs_mount *,
|
||||
struct chfs_eraseblock *, int);
|
||||
void chfs_change_size_used(struct chfs_mount *,
|
||||
struct chfs_eraseblock *, int);
|
||||
void chfs_change_size_wasted(struct chfs_mount *,
|
||||
struct chfs_eraseblock *, int);
|
||||
|
||||
/* chfs_vnode_cache.c */
|
||||
struct chfs_vnode_cache **chfs_vnocache_hash_init(void);
|
||||
void chfs_vnocache_hash_destroy(struct chfs_vnode_cache **);
|
||||
void chfs_vnode_cache_set_state(struct chfs_mount *,
|
||||
struct chfs_vnode_cache *, int);
|
||||
struct chfs_vnode_cache* chfs_vnode_cache_get(struct chfs_mount *, ino_t);
|
||||
void chfs_vnode_cache_add(struct chfs_mount *, struct chfs_vnode_cache *);
|
||||
void chfs_vnode_cache_remove(struct chfs_mount *, struct chfs_vnode_cache *);
|
||||
|
||||
/* chfs_wbuf.c */
|
||||
int chfs_write_wbuf(struct chfs_mount*,
|
||||
const struct iovec *, long, off_t, size_t *);
|
||||
int chfs_flush_pending_wbuf(struct chfs_mount *);
|
||||
|
||||
/* chfs_write.c */
|
||||
int chfs_write_flash_vnode(struct chfs_mount *, struct chfs_inode *, int);
|
||||
int chfs_write_flash_dirent(struct chfs_mount *, struct chfs_inode *,
|
||||
struct chfs_inode *, struct chfs_dirent *, ino_t, int);
|
||||
int chfs_write_flash_dnode(struct chfs_mount *, struct vnode *,
|
||||
struct buf *, struct chfs_full_dnode *);
|
||||
int chfs_do_link(struct chfs_inode *,
|
||||
struct chfs_inode *, const char *, int, enum vtype);
|
||||
int chfs_do_unlink(struct chfs_inode *,
|
||||
struct chfs_inode *, const char *, int);
|
||||
|
||||
/* chfs_subr.c */
|
||||
size_t chfs_mem_info(bool);
|
||||
struct chfs_dirent * chfs_dir_lookup(struct chfs_inode *,
|
||||
struct componentname *);
|
||||
int chfs_filldir (struct uio *, ino_t, const char *, int, enum vtype);
|
||||
int chfs_chsize(struct vnode *, u_quad_t, kauth_cred_t);
|
||||
int chfs_chflags(struct vnode *, int, kauth_cred_t);
|
||||
void chfs_itimes(struct chfs_inode *, const struct timespec *,
|
||||
const struct timespec *, const struct timespec *);
|
||||
int chfs_update(struct vnode *, const struct timespec *,
|
||||
const struct timespec *, int);
|
||||
//int chfs_truncate(struct vnode *, off_t);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Some inline functions temporarily placed here */
|
||||
static inline int
|
||||
chfs_map_leb(struct chfs_mount *chmp, int lnr)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = ebh_map_leb(chmp->chm_ebh, lnr);
|
||||
if (err)
|
||||
chfs_err("unmap leb %d failed, error: %d\n",lnr, err);
|
||||
|
||||
return err;
|
||||
|
||||
}
|
||||
|
||||
static inline int
|
||||
chfs_unmap_leb(struct chfs_mount *chmp, int lnr)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = ebh_unmap_leb(chmp->chm_ebh, lnr);
|
||||
if (err)
|
||||
chfs_err("unmap leb %d failed, error: %d\n",lnr, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline int
|
||||
chfs_read_leb(struct chfs_mount *chmp, int lnr, char *buf,
|
||||
int offset, int len, size_t *retlen)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = ebh_read_leb(chmp->chm_ebh, lnr, buf, offset, len, retlen);
|
||||
if (err)
|
||||
chfs_err("read leb %d:%d failed, error: %d\n",
|
||||
lnr, offset, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline int chfs_write_leb(struct chfs_mount *chmp, int lnr, char *buf,
|
||||
int offset, int len, size_t *retlen)
|
||||
{
|
||||
int err;
|
||||
err = ebh_write_leb(chmp->chm_ebh, lnr, buf, offset, len, retlen);
|
||||
if (err)
|
||||
chfs_err("write leb %d:%d failed, error: %d\n",
|
||||
lnr, offset, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Code from dummyfs.h */
|
||||
/******************************************************************************/
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
#define CHFS_PAGES_RESERVED (4 * 1024 * 1024 / PAGE_SIZE)
|
||||
|
||||
static __inline size_t
|
||||
CHFS_PAGES_MAX(struct chfs_mount *chmp)
|
||||
{
|
||||
size_t freepages;
|
||||
|
||||
freepages = chfs_mem_info(false);
|
||||
if (freepages < CHFS_PAGES_RESERVED)
|
||||
freepages = 0;
|
||||
else
|
||||
freepages -= CHFS_PAGES_RESERVED;
|
||||
|
||||
return MIN(chmp->chm_pages_max, freepages + chmp->chm_pages_used);
|
||||
}
|
||||
|
||||
#define CHFS_ITIMES(ip, acc, mod, cre) \
|
||||
while ((ip)->iflag & (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY)) \
|
||||
chfs_itimes(ip, acc, mod, cre)
|
||||
|
||||
/* used for KASSERTs */
|
||||
#define IMPLIES(a, b) (!(a) || (b))
|
||||
#define IFF(a, b) (IMPLIES(a, b) && IMPLIES(b, a))
|
||||
|
||||
#endif /* __CHFS_H__ */
|
53
nbsd_include/ufs/chfs/chfs_args.h
Normal file
53
nbsd_include/ufs/chfs/chfs_args.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/* $NetBSD: chfs_args.h,v 1.1 2011/11/24 15:51:31 ahoka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Department of Software Engineering,
|
||||
* University of Szeged, Hungary
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by the Department of Software Engineering, University of Szeged, Hungary
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _FS_CHFS_CHFS_ARGS_H_
|
||||
#define _FS_CHFS_CHFS_ARGS_H_
|
||||
|
||||
#define CHFS_ARGS_VERSION 1
|
||||
|
||||
/**
|
||||
* struct chfs_args - arguments needed when mounting filesystem
|
||||
* @fl_index: index of the flash device in the flash layer
|
||||
*/
|
||||
struct chfs_args {
|
||||
//int ca_version;
|
||||
char *fspec;
|
||||
int fl_index;
|
||||
|
||||
/* Root node attributes. */
|
||||
/*uid_t ca_root_uid;
|
||||
gid_t ca_root_gid;
|
||||
mode_t ca_root_mode;*/
|
||||
};
|
||||
|
||||
#endif /* _FS_CHFS_CHFS_ARGS_H_ */
|
136
nbsd_include/ufs/chfs/chfs_inode.h
Normal file
136
nbsd_include/ufs/chfs/chfs_inode.h
Normal file
|
@ -0,0 +1,136 @@
|
|||
/* $NetBSD: chfs_inode.h,v 1.1 2011/11/24 15:51:31 ahoka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Department of Software Engineering,
|
||||
* University of Szeged, Hungary
|
||||
* Copyright (C) 2010 Tamas Toth <ttoth@inf.u-szeged.hu>
|
||||
* Copyright (C) 2010 Adam Hoka <ahoka@NetBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by the Department of Software Engineering, University of Szeged, Hungary
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __CHFS_INODE_H__
|
||||
#define __CHFS_INODE_H__
|
||||
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/stat.h>
|
||||
#include <ufs/ufs/ufsmount.h>
|
||||
#include <miscfs/genfs/genfs_node.h>
|
||||
|
||||
struct chfs_inode
|
||||
{
|
||||
kmutex_t inode_lock; /* lock the fields of chfs_inode */
|
||||
|
||||
LIST_ENTRY(chfs_inode) hash_entry; /* Hash chain. */
|
||||
|
||||
struct ufsmount *ump; /* ufs mount - TODO we should remove it */
|
||||
struct chfs_mount *chmp; /* chfs mount point - TODO we should remove it */
|
||||
|
||||
struct vnode *vp; /* vnode associated with this inode */
|
||||
ino_t ino; /* vnode identifier number */
|
||||
|
||||
struct vnode *devvp; /* vnode for block I/O */
|
||||
dev_t dev; /* device associated with the inode */
|
||||
|
||||
struct chfs_vnode_cache *chvc; /* vnode cache of this node */
|
||||
|
||||
struct chfs_dirent *fd; /* full dirent of this node */
|
||||
// struct chfs_dirent *dents; /* directory entries */
|
||||
struct chfs_dirent_list dents;
|
||||
|
||||
struct rb_tree fragtree; /* fragtree of inode */
|
||||
|
||||
uint64_t version; /* version number */
|
||||
//uint64_t highest_version; /* highest vers. num. (used at data nodes) */
|
||||
|
||||
uint32_t mode; /* mode */
|
||||
//int16_t nlink; /* link count */
|
||||
uint64_t size; /* file byte count */
|
||||
uint64_t write_size; /* increasing while write the file out to the flash */
|
||||
uint32_t uid; /* file owner */
|
||||
uint32_t gid; /* file group */
|
||||
uint32_t atime; /* access time */
|
||||
uint32_t mtime; /* modify time */
|
||||
uint32_t ctime; /* creation time */
|
||||
|
||||
uint32_t iflag; /* flags, see below */
|
||||
uint32_t flags; /* status flags (chflags) */
|
||||
|
||||
dev_t rdev; /* used if type is VCHR or VBLK or VFIFO*/
|
||||
char *target; /* used if type is VLNK */
|
||||
};
|
||||
|
||||
/* These flags are kept in chfs_inode->iflag. */
|
||||
#define IN_ACCESS 0x0001 /* Access time update request. */
|
||||
#define IN_CHANGE 0x0002 /* Inode change time update request. */
|
||||
#define IN_UPDATE 0x0004 /* Inode was written to; update mtime. */
|
||||
#define IN_MODIFY 0x2000 /* Modification time update request. */
|
||||
#define IN_MODIFIED 0x0008 /* Inode has been modified. */
|
||||
#define IN_ACCESSED 0x0010 /* Inode has been accessed. */
|
||||
#define IN_RENAME 0x0020 /* Inode is being renamed. */
|
||||
#define IN_SHLOCK 0x0040 /* File has shared lock. */
|
||||
#define IN_EXLOCK 0x0080 /* File has exclusive lock. */
|
||||
#define IN_CLEANING 0x0100 /* LFS: file is being cleaned */
|
||||
#define IN_ADIROP 0x0200 /* LFS: dirop in progress */
|
||||
#define IN_SPACECOUNTED 0x0400 /* Blocks to be freed in free count. */
|
||||
#define IN_PAGING 0x1000 /* LFS: file is on paging queue */
|
||||
|
||||
|
||||
#ifdef VTOI
|
||||
# undef VTOI
|
||||
#endif
|
||||
#ifdef ITOV
|
||||
# undef ITOV
|
||||
#endif
|
||||
|
||||
#define VTOI(vp) ((struct chfs_inode *)(vp)->v_data)
|
||||
#define ITOV(ip) ((ip)->vp)
|
||||
|
||||
/* copied from ufs_dinode.h */
|
||||
#define NDADDR 12 /* Direct addresses in inode. */
|
||||
|
||||
#define ROOTINO ((ino_t)2)
|
||||
|
||||
/* File permissions. */
|
||||
#define IEXEC 0000100 /* Executable. */
|
||||
#define IWRITE 0000200 /* Writable. */
|
||||
#define IREAD 0000400 /* Readable. */
|
||||
#define ISVTX 0001000 /* Sticky bit. */
|
||||
#define ISGID 0002000 /* Set-gid. */
|
||||
#define ISUID 0004000 /* Set-uid. */
|
||||
|
||||
/* File types. */
|
||||
#define IFMT 0170000 /* Mask of file type. */
|
||||
#define IFIFO 0010000 /* Named pipe (fifo). */
|
||||
#define IFCHR 0020000 /* Character device. */
|
||||
#define IFDIR 0040000 /* Directory file. */
|
||||
#define IFBLK 0060000 /* Block device. */
|
||||
#define IFREG 0100000 /* Regular file. */
|
||||
#define IFLNK 0120000 /* Symbolic link. */
|
||||
#define IFSOCK 0140000 /* UNIX domain socket. */
|
||||
#define IFWHT 0160000 /* Whiteout. */
|
||||
|
||||
#endif /* __CHFS_INODE_H__ */
|
84
nbsd_include/ufs/chfs/chfs_pool.h
Normal file
84
nbsd_include/ufs/chfs/chfs_pool.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
/* $NetBSD: chfs_pool.h,v 1.1 2011/11/24 15:51:31 ahoka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Department of Software Engineering,
|
||||
* University of Szeged, Hungary
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by the Department of Software Engineering, University of Szeged, Hungary
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _FS_CHFS_CHFS_POOL_H_
|
||||
#define _FS_CHFS_CHFS_POOL_H_
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
struct chfs_pool {
|
||||
struct pool chp_pool;
|
||||
struct chfs_mount * chp_mount;
|
||||
char chp_name[64];
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
struct chfs_str_pool {
|
||||
struct chfs_pool chsp_pool_16;
|
||||
struct chfs_pool chsp_pool_32;
|
||||
struct chfs_pool chsp_pool_64;
|
||||
struct chfs_pool chsp_pool_128;
|
||||
struct chfs_pool chsp_pool_256;
|
||||
struct chfs_pool chsp_pool_512;
|
||||
struct chfs_pool chsp_pool_1024;
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
#ifdef _KERNEL
|
||||
|
||||
/*
|
||||
* Convenience functions and macros to manipulate a chfs_pool.
|
||||
*/
|
||||
|
||||
void chfs_pool_init(struct chfs_pool *chpp, size_t size,
|
||||
const char *what, struct chfs_mount *chmp);
|
||||
void chfs_pool_destroy(struct chfs_pool *chpp);
|
||||
|
||||
#define CHFS_POOL_GET(chpp, flags) pool_get((struct pool *)(chpp), flags)
|
||||
#define CHFS_POOL_PUT(chpp, v) pool_put((struct pool *)(chpp), v)
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Functions to manipulate a chfs_str_pool.
|
||||
*/
|
||||
|
||||
void chfs_str_pool_init(struct chfs_str_pool *, struct chfs_mount *);
|
||||
void chfs_str_pool_destroy(struct chfs_str_pool *);
|
||||
char * chfs_str_pool_get(struct chfs_str_pool *, size_t, int);
|
||||
void chfs_str_pool_put(struct chfs_str_pool *, char *, size_t);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _FS_CHFS_CHFS_POOL_H_ */
|
97
nbsd_include/ufs/chfs/debug.h
Normal file
97
nbsd_include/ufs/chfs/debug.h
Normal file
|
@ -0,0 +1,97 @@
|
|||
/* $NetBSD: debug.h,v 1.1 2011/11/24 15:51:32 ahoka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Department of Software Engineering,
|
||||
* University of Szeged, Hungary
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by the Department of Software Engineering, University of Szeged, Hungary
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* XipFFS -- Xip Flash File System
|
||||
*
|
||||
* Copyright (C) 2009 Ferenc Havasi <havasi@inf.u-szeged.hu>,
|
||||
* Zoltan Sogor <weth@inf.u-szeged.hu>,
|
||||
* ...
|
||||
* University of Szeged, Hungary
|
||||
*
|
||||
*
|
||||
* For licensing information, see the file 'LICENCE' in this directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __CHFS_DEBUG_H__
|
||||
#define __CHFS_DEBUG_H__
|
||||
|
||||
#define CHFS_ERROR_PREFIX "[CHFS ERROR]"
|
||||
#define CHFS_WARNING_PREFIX "[CHFS WARNING]"
|
||||
#define CHFS_NOTICE_PREFIX "[CHFS NOTICE]"
|
||||
#define CHFS_DBG_PREFIX "[CHFS DBG]"
|
||||
#define CHFS_DBG2_PREFIX "[CHFS DBG2]"
|
||||
#define CHFS_DBG_EBH_PREFIX "[CHFS DBG EBH]"
|
||||
#define CHFS_DBG_GC_PREFIX "[CHFS_GC DBG]"
|
||||
|
||||
#define unlikely(x) __builtin_expect ((x), 0)
|
||||
|
||||
|
||||
|
||||
#define debug_msg(pref, fmt, ...) \
|
||||
do { \
|
||||
printf(pref \
|
||||
" %s: " fmt, __FUNCTION__ , ##__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
#define chfs_assert(expr) do { \
|
||||
if (unlikely(!(expr))) { \
|
||||
printf("CHFS assert failed in %s at %u\n", \
|
||||
__func__, __LINE__); \
|
||||
/*dump_stack();*/ \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#ifdef DBG_MSG
|
||||
#define chfs_err(fmt, ...) debug_msg(CHFS_ERROR_PREFIX, fmt, ##__VA_ARGS__)
|
||||
#define chfs_warn(fmt, ...) debug_msg(CHFS_WARNING_PREFIX, fmt, ##__VA_ARGS__)
|
||||
#define chfs_noti(fmt, ...) debug_msg(CHFS_NOTICE_PREFIX, fmt, ##__VA_ARGS__)
|
||||
#define dbg(fmt, ...) debug_msg(CHFS_DBG_PREFIX, fmt, ##__VA_ARGS__)
|
||||
#define dbg2(fmt, ...) debug_msg(CHFS_DBG2_PREFIX(fmt, ##__VA_ARGS__)
|
||||
#define dbg_ebh(fmt, ...) debug_msg(CHFS_DBG_EBH_PREFIX, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define chfs_err(fmt, ...) debug_msg(CHFS_ERROR_PREFIX, fmt, ##__VA_ARGS__)
|
||||
#define chfs_warn(fmt, ...) debug_msg(CHFS_WARNING_PREFIX, fmt, ##__VA_ARGS__)
|
||||
#define chfs_noti(fmt, ...) debug_msg(CHFS_NOTICE_PREFIX, fmt, ##__VA_ARGS__)
|
||||
#define dbg(fmt, ...)
|
||||
#define dbg2(fmt, ...)
|
||||
#define dbg_ebh(fmt, ...)
|
||||
#endif
|
||||
|
||||
#ifdef DBG_MSG_GC
|
||||
#define dbg_gc(fmt, ...) debug_msg(CHFS_DBG_GC_PREFIX, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define dbg_gc(fmt, ...)
|
||||
#endif
|
||||
|
||||
#endif /* __CHFS_DEBUG_H__ */
|
318
nbsd_include/ufs/chfs/ebh.h
Normal file
318
nbsd_include/ufs/chfs/ebh.h
Normal file
|
@ -0,0 +1,318 @@
|
|||
/* $NetBSD: ebh.h,v 1.1 2011/11/24 15:51:32 ahoka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Department of Software Engineering,
|
||||
* University of Szeged, Hungary
|
||||
* Copyright (c) 2010 David Tengeri <dtengeri@inf.u-szeged.hu>
|
||||
* Copyright (c) 2010 Adam Hoka <ahoka@NetBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by the Department of Software Engineering, University of Szeged, Hungary
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ebh.h
|
||||
*
|
||||
* Created on: 2009.11.03.
|
||||
* Author: dtengeri
|
||||
*/
|
||||
|
||||
#ifndef EBH_H_
|
||||
#define EBH_H_
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/tree.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/kmem.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/rwlock.h>
|
||||
#include <sys/condvar.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/kthread.h>
|
||||
|
||||
#include <dev/flash/flash.h>
|
||||
#include <ufs/chfs/ebh_media.h>
|
||||
#include <ufs/chfs/debug.h>
|
||||
#include <ufs/chfs/ebh_misc.h>
|
||||
|
||||
/* Maximum retries when getting new PEB before exit with failure */
|
||||
#define CHFS_MAX_GET_PEB_RETRIES 2
|
||||
|
||||
/**
|
||||
* LEB status
|
||||
*
|
||||
*/
|
||||
enum {
|
||||
EBH_LEB_UNMAPPED = -1,
|
||||
EBH_LEB_MAPPED,
|
||||
EBH_LEB_DIRTY,
|
||||
EBH_LEB_INVALID,
|
||||
EBH_LEB_ERASE,
|
||||
EBH_LEB_ERASED,
|
||||
EBH_LEB_FREE,
|
||||
};
|
||||
|
||||
/**
|
||||
* EB header status
|
||||
*/
|
||||
enum {
|
||||
EBHDR_LEB_OK = 0,
|
||||
EBHDR_LEB_DIRTY,
|
||||
EBHDR_LEB_INVALIDATED,
|
||||
EBHDR_LEB_BADMAGIC,
|
||||
EBHDR_LEB_BADCRC,
|
||||
EBHDR_LEB_FREE,
|
||||
EBHDR_LEB_NO_HDR,
|
||||
};
|
||||
|
||||
struct chfs_ebh;
|
||||
|
||||
/**
|
||||
* struct chfs_ltree_entry - an netry in the lock tree
|
||||
* @rb: RB-node of the tree
|
||||
* @lnr: logical eraseblock number
|
||||
* @users: counts the tasks that are using or want to use the eraseblock
|
||||
* @mutex: read/write mutex to lock the eraseblock
|
||||
*/
|
||||
struct chfs_ltree_entry {
|
||||
RB_ENTRY(chfs_ltree_entry) rb;
|
||||
int lnr;
|
||||
int users;
|
||||
krwlock_t mutex;
|
||||
};
|
||||
|
||||
/* Generate structure for Lock tree's red-black tree */
|
||||
RB_HEAD(ltree_rbtree, chfs_ltree_entry);
|
||||
|
||||
|
||||
/**
|
||||
* struct chfs_scan_leb - scanning infomration about a physical eraseblock
|
||||
* @erase_cnt: erase counter
|
||||
* @pebnr: physical eraseblock number
|
||||
* @info: the status of the PEB's eraseblock header when NOR serial when NAND
|
||||
* @u.list: link in one of the eraseblock list
|
||||
* @u.rb: link in the used RB-tree of chfs_scan_info
|
||||
*/
|
||||
struct chfs_scan_leb {
|
||||
int erase_cnt;
|
||||
int pebnr;
|
||||
int lnr;
|
||||
uint64_t info;
|
||||
union {
|
||||
TAILQ_ENTRY(chfs_scan_leb) queue;
|
||||
RB_ENTRY(chfs_scan_leb) rb;
|
||||
} u;
|
||||
};
|
||||
|
||||
TAILQ_HEAD(scan_leb_queue, chfs_scan_leb);
|
||||
RB_HEAD(scan_leb_used_rbtree, chfs_scan_leb);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* struct chfs_scan_info - chfs scanning information
|
||||
* @corrupted: queue of corrupted physical eraseblocks
|
||||
* @free: queue of free physical eraseblocks
|
||||
* @erase: queue of the physical eraseblocks signed to erase
|
||||
* @erased: queue of physical eraseblocks that contain no header
|
||||
* @used: RB-tree of used PEBs describing by chfs_scan_leb
|
||||
* @sum_of_ec: summary of erase counters
|
||||
* @num_of_eb: number of free and used eraseblocks
|
||||
* @bad_peb_cnt: counter of bad eraseblocks
|
||||
*
|
||||
* This structure contains information about the scanning for further
|
||||
* processing.
|
||||
*/
|
||||
struct chfs_scan_info {
|
||||
struct scan_leb_queue corrupted;
|
||||
struct scan_leb_queue free;
|
||||
struct scan_leb_queue erase;
|
||||
struct scan_leb_queue erased;
|
||||
struct scan_leb_used_rbtree used;
|
||||
uint64_t sum_of_ec;
|
||||
int num_of_eb;
|
||||
int bad_peb_cnt;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct chfs_peb - PEB information for erasing and wear leveling
|
||||
* @erase_cnt: erase counter of the physical eraseblock
|
||||
* @pebnr: physical eraseblock number
|
||||
* @u.queue: link to the queue of the PEBs waiting for erase
|
||||
* @u.rb: link to the RB-tree to the free PEBs
|
||||
*/
|
||||
struct chfs_peb {
|
||||
int erase_cnt;
|
||||
int pebnr;
|
||||
union {
|
||||
TAILQ_ENTRY(chfs_peb) queue;
|
||||
RB_ENTRY(chfs_peb) rb;
|
||||
} u;
|
||||
};
|
||||
|
||||
/* Generate queue and rb-tree structures. */
|
||||
TAILQ_HEAD(peb_queue, chfs_peb);
|
||||
RB_HEAD(peb_free_rbtree, chfs_peb);
|
||||
RB_HEAD(peb_in_use_rbtree, chfs_peb);
|
||||
|
||||
/**
|
||||
* struct chfs_eb_hdr - in-memory representation of eraseblock headers
|
||||
* @ec_hdr: erase counter header ob eraseblock
|
||||
* @u.nor_hdr: eraseblock header on NOR flash
|
||||
* @u.nand_hdr: eraseblock header on NAND flash
|
||||
*/
|
||||
struct chfs_eb_hdr {
|
||||
struct chfs_eb_ec_hdr ec_hdr;
|
||||
union {
|
||||
struct chfs_nor_eb_hdr nor_hdr;
|
||||
struct chfs_nand_eb_hdr nand_hdr;
|
||||
} u;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct chfs_ebh_ops - collection of operations which
|
||||
* depends on flash type
|
||||
* *************************************************************************** *
|
||||
* Direct flash operations:
|
||||
*
|
||||
* @read_eb_hdr: read eraseblock header from media
|
||||
* @write_eb_hdr: write eraseblock header to media
|
||||
* @check_eb_hdr: validates eraseblock header
|
||||
* @mark_eb_hdr_dirty_flash: marks eraseblock dirty on flash
|
||||
* @invalidate_eb_hdr: invalidates eraseblock header
|
||||
* @mark_eb_hdr_free: marks eraseblock header free (after erase)
|
||||
* *************************************************************************** *
|
||||
* Scanning operations:
|
||||
*
|
||||
* @process_eb: process an eraseblock information at scan
|
||||
* *************************************************************************** *
|
||||
* Misc operations:
|
||||
*
|
||||
* @create_eb_hdr: creates an eraseblock header based on flash type
|
||||
* @calc_data_offs: calculates where the data starts
|
||||
*/
|
||||
struct chfs_ebh_ops {
|
||||
int (*read_eb_hdr)(struct chfs_ebh *ebh, int pebnr,
|
||||
struct chfs_eb_hdr *ebhdr);
|
||||
int (*write_eb_hdr)(struct chfs_ebh *ebh, int pebnr,
|
||||
struct chfs_eb_hdr *ebhdr);
|
||||
int (*check_eb_hdr)(struct chfs_ebh *ebh, void *buf);
|
||||
int (*mark_eb_hdr_dirty_flash)(struct chfs_ebh *ebh, int pebnr, int lid);
|
||||
int (*invalidate_eb_hdr)(struct chfs_ebh *ebh, int pebnr);
|
||||
int (*mark_eb_hdr_free)(struct chfs_ebh *ebh, int pebnr, int ec);
|
||||
|
||||
int (*process_eb)(struct chfs_ebh *ebh, struct chfs_scan_info *si,
|
||||
int pebnr, struct chfs_eb_hdr *ebhdr);
|
||||
|
||||
int (*create_eb_hdr)(struct chfs_eb_hdr *ebhdr, int lnr);
|
||||
int (*calc_data_offs)(struct chfs_ebh *ebh, int pebnr, int offset);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct erase_thread - background thread for erasing
|
||||
* @thread: pointer to thread structure
|
||||
* @wakeup: conditional variable for sleeping if there isn't any job to do
|
||||
* @running: flag to signal a thread shutdown
|
||||
*/
|
||||
struct erase_thread {
|
||||
lwp_t *eth_thread;
|
||||
kcondvar_t eth_wakeup;
|
||||
bool eth_running;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct chfs_ebh - eraseblock handler descriptor
|
||||
* @mtd: mtd device descriptor
|
||||
* @eb_size: eraseblock size
|
||||
* @peb_nr: number of PEBs
|
||||
* @lmap: LEB to PEB mapping
|
||||
* @layout_map: the LEBs layout (NOT USED YET)
|
||||
* @ltree: the lock tree
|
||||
* @ltree_lock: protects the tree
|
||||
* @alc_mutex: serializes "atomic LEB change" operation
|
||||
* @free: RB-tree of the free easeblocks
|
||||
* @in_use: RB-tree of PEBs are in use
|
||||
* @to_erase: list of the PEBs waiting for erase
|
||||
* @fully_erased: list of PEBs that have been erased but don't have header
|
||||
* @erase_lock: list and tree lock for fully_erased and to_erase lists and
|
||||
* for the free RB-tree
|
||||
* @bg_erase: background thread for eraseing PEBs.
|
||||
* @ops: collection of operations which depends on flash type
|
||||
* @max_serial: max serial number of eraseblocks, only used on NAND
|
||||
*/
|
||||
struct chfs_ebh {
|
||||
struct peb_free_rbtree free;
|
||||
struct peb_in_use_rbtree in_use;
|
||||
struct peb_queue to_erase;
|
||||
struct peb_queue fully_erased;
|
||||
struct erase_thread bg_erase;
|
||||
device_t flash_dev;
|
||||
const struct flash_interface *flash_if;
|
||||
struct chfs_ebh_ops *ops;
|
||||
uint64_t *max_serial;
|
||||
int *lmap;
|
||||
//int *layout_map;
|
||||
struct ltree_rbtree ltree;
|
||||
//struct mutex alc_mutex;
|
||||
kmutex_t ltree_lock;
|
||||
kmutex_t alc_mutex;
|
||||
kmutex_t erase_lock;
|
||||
size_t eb_size;
|
||||
size_t peb_nr;
|
||||
flash_size_t flash_size;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct chfs_erase_info_priv - private information for erase
|
||||
* @ebh: eraseblock handler
|
||||
* @peb: physical eraseblock information
|
||||
*/
|
||||
struct chfs_erase_info_priv {
|
||||
struct chfs_ebh *ebh;
|
||||
struct chfs_peb *peb;
|
||||
};
|
||||
|
||||
/* ebh.c */
|
||||
|
||||
int ebh_open(struct chfs_ebh *ebh, dev_t dev);
|
||||
int ebh_close(struct chfs_ebh *ebh);
|
||||
int ebh_read_leb(struct chfs_ebh *ebh, int lnr, char *buf,
|
||||
uint32_t offset, size_t len, size_t *retlen);
|
||||
int ebh_write_leb(struct chfs_ebh *ebh, int lnr, char *buf,
|
||||
uint32_t offset, size_t len, size_t *retlen);
|
||||
int ebh_erase_leb(struct chfs_ebh *ebh, int lnr);
|
||||
int ebh_map_leb(struct chfs_ebh *ebh, int lnr);
|
||||
int ebh_unmap_leb(struct chfs_ebh *ebh, int lnr);
|
||||
int ebh_is_mapped(struct chfs_ebh *ebh, int lnr);
|
||||
int ebh_change_leb(struct chfs_ebh *ebh, int lnr, char *buf,
|
||||
size_t len, size_t *retlen);
|
||||
|
||||
|
||||
#endif /* EBH_H_ */
|
116
nbsd_include/ufs/chfs/ebh_media.h
Normal file
116
nbsd_include/ufs/chfs/ebh_media.h
Normal file
|
@ -0,0 +1,116 @@
|
|||
/* $NetBSD: ebh_media.h,v 1.1 2011/11/24 15:51:32 ahoka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Department of Software Engineering,
|
||||
* University of Szeged, Hungary
|
||||
* Copyright (C) 2009 Ferenc Havasi <havasi@inf.u-szeged.hu>
|
||||
* Copyright (C) 2009 Zoltan Sogor <weth@inf.u-szeged.hu>
|
||||
* Copyright (C) 2009 David Tengeri <dtengeri@inf.u-szeged.hu>
|
||||
* Copyright (C) 2010 Adam Hoka <ahoka@NetBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by the Department of Software Engineering, University of Szeged, Hungary
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef EBH_MEDIA_H_
|
||||
#define EBH_MEDIA_H_
|
||||
|
||||
#ifndef _LE_TYPES
|
||||
#define _LE_TYPES
|
||||
typedef uint16_t le16;
|
||||
typedef uint32_t le32;
|
||||
typedef uint64_t le64;
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* EBH specific structures */
|
||||
/*****************************************************************************/
|
||||
#define CHFS_MAGIC_BITMASK 0x53454452
|
||||
|
||||
#define CHFS_LID_NOT_DIRTY_BIT 0x80000000
|
||||
#define CHFS_LID_DIRTY_BIT_MASK 0x7fffffff
|
||||
|
||||
/* sizeof(crc) + sizeof(lid) */
|
||||
#define CHFS_INVALIDATE_SIZE 8
|
||||
|
||||
/* Size of magic + crc_ec + erase_cnt */
|
||||
#define CHFS_EB_EC_HDR_SIZE sizeof(struct chfs_eb_ec_hdr)
|
||||
/* Size of NOR eraseblock header */
|
||||
#define CHFS_EB_HDR_NOR_SIZE sizeof(struct chfs_nor_eb_hdr)
|
||||
/* Size of NAND eraseblock header */
|
||||
#define CHFS_EB_HDR_NAND_SIZE sizeof(struct chfs_nand_eb_hdr)
|
||||
|
||||
/*
|
||||
* chfs_eb_ec_hdr - erase counter header of eraseblock
|
||||
* @magic: filesystem magic
|
||||
* @crc_ec: CRC32 sum of erase counter
|
||||
* @erase_cnt: erase counter
|
||||
*
|
||||
* This structure holds the erasablock description information.
|
||||
* This will be written to the beginning of the eraseblock.
|
||||
*
|
||||
*/
|
||||
struct chfs_eb_ec_hdr {
|
||||
le32 magic;
|
||||
le32 crc_ec;
|
||||
le32 erase_cnt;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct chfs_nor_eb_hdr - eraseblock header on NOR flash
|
||||
* @crc: CRC32 sum
|
||||
* @lid: logical identifier
|
||||
*
|
||||
* @lid contains the logical block reference but only the first 31 bit (0-30) is
|
||||
* used. The 32th bit is for marking a lid dirty (marked for recovery purposes).
|
||||
* If a new eraseblock is succesfully assigned with the same lid then the lid of
|
||||
* the old one is zeroed. If power failure happened during this operation then
|
||||
* the recovery detects that there is two eraseblock with the same lid, but one
|
||||
* of them is marked (the old one).
|
||||
*
|
||||
* Invalidated eraseblock header means that the @crc and @lid is set to 0.
|
||||
*/
|
||||
struct chfs_nor_eb_hdr {
|
||||
le32 crc;
|
||||
le32 lid;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct chfs_nand_eb_hdr - eraseblock header on NAND flash
|
||||
* @crc: CRC32 sum
|
||||
* @lid: logical identifier
|
||||
* @serial: layout of the lid
|
||||
*
|
||||
* @serial is an unique number. Every eraseblock header on NAND flash has its
|
||||
* own serial. If there are two eraseblock on the flash referencing to the same
|
||||
* logical eraseblock, the one with bigger serial is the newer.
|
||||
*/
|
||||
struct chfs_nand_eb_hdr {
|
||||
le32 crc;
|
||||
le32 lid;
|
||||
le64 serial;
|
||||
} __packed;
|
||||
|
||||
#endif /* EBH_MEDIA_H_ */
|
88
nbsd_include/ufs/chfs/ebh_misc.h
Normal file
88
nbsd_include/ufs/chfs/ebh_misc.h
Normal file
|
@ -0,0 +1,88 @@
|
|||
/* $NetBSD: ebh_misc.h,v 1.1 2011/11/24 15:51:32 ahoka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Department of Software Engineering,
|
||||
* University of Szeged, Hungary
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by the Department of Software Engineering, University of Szeged, Hungary
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef EBH_MISC_H_
|
||||
#define EBH_MISC_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/* EBH specific functions */
|
||||
/******************************************************************************/
|
||||
|
||||
#define CHFS_GET_MEMBER_POS(type, member) \
|
||||
((unsigned long)(&((type *)0)->member))
|
||||
|
||||
#define CHFS_GET_LID(lid) (le32toh(lid) & CHFS_LID_DIRTY_BIT_MASK)
|
||||
|
||||
/**
|
||||
* EBH_TREE_DESTROY - destroys an RB-tree and frees the memory of its elements.
|
||||
* @name - the RB-tree structure's name
|
||||
* @head - pointer to the RB-tree's head
|
||||
* @type - type of the elements
|
||||
*/
|
||||
#define EBH_TREE_DESTROY(name, head, type) \
|
||||
{ \
|
||||
type *var, *nxt; \
|
||||
for (var = RB_MIN(name, head); var != NULL; var = nxt) { \
|
||||
nxt = RB_NEXT(name, head, var); \
|
||||
RB_REMOVE(name, head, var); \
|
||||
kmem_free(var, sizeof(type)); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* XXX HACK! we need a clean solution for destroying mutexes in trees */
|
||||
#define EBH_TREE_DESTROY_MUTEX(name, head, type) \
|
||||
{ \
|
||||
type *var, *nxt; \
|
||||
for (var = RB_MIN(name, head); var != NULL; var = nxt) { \
|
||||
nxt = RB_NEXT(name, head, var); \
|
||||
RB_REMOVE(name, head, var); \
|
||||
rw_destroy(&var->mutex); \
|
||||
kmem_free(var, sizeof(type)); \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* EBH_QUEUE_DESTROY - destroys a TAILQ and frees the memory of its elements.
|
||||
* @head: pointer to the head of the queue
|
||||
* @type: type of the elements
|
||||
* @entry: name of TAILQ_ENTRY
|
||||
*/
|
||||
#define EBH_QUEUE_DESTROY(head, type, entry) \
|
||||
{ \
|
||||
type *var; \
|
||||
while ((var = TAILQ_FIRST(head))) { \
|
||||
TAILQ_REMOVE(head, var, entry); \
|
||||
kmem_free(var, sizeof(type)); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif /* EBH_MISC_H_ */
|
200
nbsd_include/ufs/chfs/media.h
Normal file
200
nbsd_include/ufs/chfs/media.h
Normal file
|
@ -0,0 +1,200 @@
|
|||
/*-
|
||||
* Copyright (c) 2010 Department of Software Engineering,
|
||||
* University of Szeged, Hungary
|
||||
* Copyright (C) 2009 Ferenc Havasi <havasi@inf.u-szeged.hu>
|
||||
* Copyright (C) 2009 Zoltan Sogor <weth@inf.u-szeged.hu>
|
||||
* Copyright (C) 2009 David Tengeri <dtengeri@inf.u-szeged.hu>
|
||||
* Copyright (C) 2010 Adam Hoka <ahoka@NetBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by the Department of Software Engineering, University of Szeged, Hungary
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __CHFS_MEDIA_H__
|
||||
#define __CHFS_MEDIA_H__
|
||||
|
||||
#ifndef _LE_TYPES
|
||||
#define _LE_TYPES
|
||||
typedef uint16_t le16;
|
||||
typedef uint32_t le32;
|
||||
typedef uint64_t le64;
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* File system specific structures */
|
||||
/*****************************************************************************/
|
||||
|
||||
enum {
|
||||
CHFS_NODETYPE_VNODE = 1,
|
||||
CHFS_NODETYPE_DATA,
|
||||
CHFS_NODETYPE_DIRENT,
|
||||
CHFS_NODETYPE_PADDING,
|
||||
};
|
||||
|
||||
//#define CHFS_NODE_HDR_SIZE 12 /* magic + type + length + hdr_crc */
|
||||
#define CHFS_NODE_HDR_SIZE sizeof(struct chfs_flash_node_hdr)
|
||||
|
||||
/* Max size we have to read to get all info.
|
||||
* It is max size of chfs_flash_dirent_node with max name length.
|
||||
*/
|
||||
#define CHFS_MAX_NODE_SIZE 299
|
||||
|
||||
/* This will identify CHfs nodes */
|
||||
#define CHFS_FS_MAGIC_BITMASK 0x4AF1
|
||||
|
||||
/**
|
||||
* struct chfs_flash_node_hdr - node header, its members are same for
|
||||
* all nodes, used at scan
|
||||
* @magic: filesystem magic
|
||||
* @type: node type
|
||||
* @length: length of node
|
||||
* @hdr_crc: crc of the first 3 members
|
||||
*/
|
||||
struct chfs_flash_node_hdr
|
||||
{
|
||||
le16 magic;
|
||||
le16 type;
|
||||
le32 length;
|
||||
le32 hdr_crc;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct chfs_flash_vnode - vnode informations stored on flash
|
||||
* @magic: filesystem magic
|
||||
* @type: node type (CHFS_NODETYPE_VNODE)
|
||||
* @length: length of node
|
||||
* @hdr_crc: crc of the first 3 members
|
||||
* @vno: vnode identifier id
|
||||
* @version: vnode's version number
|
||||
* @uid: owner of the file
|
||||
* @gid: group of file
|
||||
* @mode: permissions for vnode
|
||||
* @dn_size: size of written out data nodes
|
||||
* @atime: last access times
|
||||
* @mtime: last modification time
|
||||
* @ctime: change time
|
||||
* @dsize: size of the node's data
|
||||
* @node_crc: crc of full node
|
||||
*/
|
||||
struct chfs_flash_vnode
|
||||
{
|
||||
le16 magic; /*0 */
|
||||
le16 type; /*2 */
|
||||
le32 length; /*4 */
|
||||
le32 hdr_crc; /*8 */
|
||||
le64 vno; /*12*/
|
||||
le64 version; /*20*/
|
||||
le32 uid; /*28*/
|
||||
le32 gid; /*32*/
|
||||
le32 mode; /*36*/
|
||||
le32 dn_size; /*40*/
|
||||
le32 atime; /*44*/
|
||||
le32 mtime; /*48*/
|
||||
le32 ctime; /*52*/
|
||||
le32 dsize; /*56*/
|
||||
le32 node_crc; /*60*/
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct chfs_flash_data_node - node informations of data stored on flash
|
||||
* @magic: filesystem magic
|
||||
* @type: node type (CHFS_NODETYPE_DATA)
|
||||
* @length: length of node with data
|
||||
* @hdr_crc: crc of the first 3 members
|
||||
* @vno: vnode identifier id
|
||||
* @version: vnode's version number
|
||||
* @offset: offset in the file where write begins
|
||||
* @data_length: length of data
|
||||
* @data_crc: crc of data
|
||||
* @node_crc: crc of full node
|
||||
* @data: array of data
|
||||
*/
|
||||
struct chfs_flash_data_node
|
||||
{
|
||||
le16 magic;
|
||||
le16 type;
|
||||
le32 length;
|
||||
le32 hdr_crc;
|
||||
le64 vno;
|
||||
le64 version;
|
||||
le64 offset;
|
||||
le32 data_length;
|
||||
le32 data_crc;
|
||||
le32 node_crc;
|
||||
uint8_t data[0];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct chfs_flash_dirent_node - vnode informations stored on flash
|
||||
* @magic: filesystem magic
|
||||
* @type: node type (CHFS_NODETYPE_DIRENT)
|
||||
* @length: length of node
|
||||
* @hdr_crc: crc of the first 3 members
|
||||
* @vno: vnode identifier id
|
||||
* @pvno: vnode identifier id of parent vnode
|
||||
* @version: vnode's version number
|
||||
* @mctime:
|
||||
* @nsize: length of name
|
||||
* @dtype: file type
|
||||
* @unused: just for padding
|
||||
* @name_crc: crc of name
|
||||
* @node_crc: crc of full node
|
||||
* @name: name of the directory entry
|
||||
*/
|
||||
struct chfs_flash_dirent_node
|
||||
{
|
||||
le16 magic;
|
||||
le16 type;
|
||||
le32 length;
|
||||
le32 hdr_crc;
|
||||
le64 vno;
|
||||
le64 pvno;
|
||||
le64 version;
|
||||
le32 mctime;
|
||||
uint8_t nsize;
|
||||
uint8_t dtype;
|
||||
uint8_t unused[2];
|
||||
le32 name_crc;
|
||||
le32 node_crc;
|
||||
uint8_t name[0];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct chfs_flash_padding_node - node informations of data stored on
|
||||
* flash
|
||||
* @magic: filesystem magic
|
||||
* @type: node type (CHFS_NODETYPE_PADDING)
|
||||
* @length: length of node
|
||||
* @hdr_crc: crc of the first 3 members
|
||||
*/
|
||||
struct chfs_flash_padding_node
|
||||
{
|
||||
le16 magic;
|
||||
le16 type;
|
||||
le32 length;
|
||||
le32 hdr_crc;
|
||||
} __packed;
|
||||
|
||||
#endif /* __CHFS_MEDIA_H__ */
|
372
nbsd_include/ufs/ext2fs/ext2fs.h
Normal file
372
nbsd_include/ufs/ext2fs/ext2fs.h
Normal file
|
@ -0,0 +1,372 @@
|
|||
/* $NetBSD: ext2fs.h,v 1.29 2009/11/27 11:16:54 tsutsui Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)fs.h 8.10 (Berkeley) 10/27/94
|
||||
* Modified for ext2fs by Manuel Bouyer.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Manuel Bouyer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @(#)fs.h 8.10 (Berkeley) 10/27/94
|
||||
* Modified for ext2fs by Manuel Bouyer.
|
||||
*/
|
||||
|
||||
#ifndef _UFS_EXT2FS_EXT2FS_H_
|
||||
#define _UFS_EXT2FS_EXT2FS_H_
|
||||
|
||||
#include <sys/bswap.h>
|
||||
|
||||
/*
|
||||
* Each disk drive contains some number of file systems.
|
||||
* A file system consists of a number of cylinder groups.
|
||||
* Each cylinder group has inodes and data.
|
||||
*
|
||||
* A file system is described by its super-block, which in turn
|
||||
* describes the cylinder groups. The super-block is critical
|
||||
* data and is replicated in each cylinder group to protect against
|
||||
* catastrophic loss. This is done at `newfs' time and the critical
|
||||
* super-block data does not change, so the copies need not be
|
||||
* referenced further unless disaster strikes.
|
||||
*
|
||||
* The first boot and super blocks are given in absolute disk addresses.
|
||||
* The byte-offset forms are preferred, as they don't imply a sector size.
|
||||
*/
|
||||
#define BBSIZE 1024
|
||||
#define SBSIZE 1024
|
||||
#define BBOFF ((off_t)(0))
|
||||
#define SBOFF ((off_t)(BBOFF + BBSIZE))
|
||||
#define BBLOCK ((daddr_t)(0))
|
||||
#define SBLOCK ((daddr_t)(BBLOCK + BBSIZE / DEV_BSIZE))
|
||||
|
||||
/*
|
||||
* Addresses stored in inodes are capable of addressing blocks
|
||||
* XXX
|
||||
*/
|
||||
|
||||
/*
|
||||
* MINBSIZE is the smallest allowable block size.
|
||||
* MINBSIZE must be big enough to hold a cylinder group block,
|
||||
* thus changes to (struct cg) must keep its size within MINBSIZE.
|
||||
* Note that super blocks are always of size SBSIZE,
|
||||
* and that both SBSIZE and MAXBSIZE must be >= MINBSIZE.
|
||||
*/
|
||||
#define LOG_MINBSIZE 10
|
||||
#define MINBSIZE (1 << LOG_MINBSIZE)
|
||||
|
||||
/*
|
||||
* The path name on which the file system is mounted is maintained
|
||||
* in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in
|
||||
* the super block for this name.
|
||||
*/
|
||||
#define MAXMNTLEN 512
|
||||
|
||||
/*
|
||||
* MINFREE gives the minimum acceptable percentage of file system
|
||||
* blocks which may be free. If the freelist drops below this level
|
||||
* only the superuser may continue to allocate blocks. This may
|
||||
* be set to 0 if no reserve of free blocks is deemed necessary,
|
||||
* however throughput drops by fifty percent if the file system
|
||||
* is run at between 95% and 100% full; thus the minimum default
|
||||
* value of fs_minfree is 5%. However, to get good clustering
|
||||
* performance, 10% is a better choice. hence we use 10% as our
|
||||
* default value. With 10% free space, fragmentation is not a
|
||||
* problem, so we choose to optimize for time.
|
||||
*/
|
||||
#define MINFREE 5
|
||||
|
||||
/*
|
||||
* Super block for an ext2fs file system.
|
||||
*/
|
||||
struct ext2fs {
|
||||
uint32_t e2fs_icount; /* Inode count */
|
||||
uint32_t e2fs_bcount; /* blocks count */
|
||||
uint32_t e2fs_rbcount; /* reserved blocks count */
|
||||
uint32_t e2fs_fbcount; /* free blocks count */
|
||||
uint32_t e2fs_ficount; /* free inodes count */
|
||||
uint32_t e2fs_first_dblock; /* first data block */
|
||||
uint32_t e2fs_log_bsize; /* block size = 1024*(2^e2fs_log_bsize) */
|
||||
uint32_t e2fs_fsize; /* fragment size */
|
||||
uint32_t e2fs_bpg; /* blocks per group */
|
||||
uint32_t e2fs_fpg; /* frags per group */
|
||||
uint32_t e2fs_ipg; /* inodes per group */
|
||||
uint32_t e2fs_mtime; /* mount time */
|
||||
uint32_t e2fs_wtime; /* write time */
|
||||
uint16_t e2fs_mnt_count; /* mount count */
|
||||
uint16_t e2fs_max_mnt_count; /* max mount count */
|
||||
uint16_t e2fs_magic; /* magic number */
|
||||
uint16_t e2fs_state; /* file system state */
|
||||
uint16_t e2fs_beh; /* behavior on errors */
|
||||
uint16_t e2fs_minrev; /* minor revision level */
|
||||
uint32_t e2fs_lastfsck; /* time of last fsck */
|
||||
uint32_t e2fs_fsckintv; /* max time between fscks */
|
||||
uint32_t e2fs_creator; /* creator OS */
|
||||
uint32_t e2fs_rev; /* revision level */
|
||||
uint16_t e2fs_ruid; /* default uid for reserved blocks */
|
||||
uint16_t e2fs_rgid; /* default gid for reserved blocks */
|
||||
/* EXT2_DYNAMIC_REV superblocks */
|
||||
uint32_t e2fs_first_ino; /* first non-reserved inode */
|
||||
uint16_t e2fs_inode_size; /* size of inode structure */
|
||||
uint16_t e2fs_block_group_nr; /* block grp number of this sblk*/
|
||||
uint32_t e2fs_features_compat; /* compatible feature set */
|
||||
uint32_t e2fs_features_incompat; /* incompatible feature set */
|
||||
uint32_t e2fs_features_rocompat; /* RO-compatible feature set */
|
||||
uint8_t e2fs_uuid[16]; /* 128-bit uuid for volume */
|
||||
char e2fs_vname[16]; /* volume name */
|
||||
char e2fs_fsmnt[64]; /* name mounted on */
|
||||
uint32_t e2fs_algo; /* For compression */
|
||||
uint8_t e2fs_prealloc; /* # of blocks to preallocate */
|
||||
uint8_t e2fs_dir_prealloc; /* # of blocks to preallocate for dir */
|
||||
uint16_t e2fs_reserved_ngdb; /* # of reserved gd blocks for resize */
|
||||
uint32_t reserved2[204];
|
||||
};
|
||||
|
||||
|
||||
/* in-memory data for ext2fs */
|
||||
struct m_ext2fs {
|
||||
struct ext2fs e2fs;
|
||||
u_char e2fs_fsmnt[MAXMNTLEN]; /* name mounted on */
|
||||
int8_t e2fs_ronly; /* mounted read-only flag */
|
||||
int8_t e2fs_fmod; /* super block modified flag */
|
||||
int32_t e2fs_bsize; /* block size */
|
||||
int32_t e2fs_bshift; /* ``lblkno'' calc of logical blkno */
|
||||
int32_t e2fs_bmask; /* ``blkoff'' calc of blk offsets */
|
||||
int64_t e2fs_qbmask; /* ~fs_bmask - for use with quad size */
|
||||
int32_t e2fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */
|
||||
int32_t e2fs_ncg; /* number of cylinder groups */
|
||||
int32_t e2fs_ngdb; /* number of group descriptor block */
|
||||
int32_t e2fs_ipb; /* number of inodes per block */
|
||||
int32_t e2fs_itpg; /* number of inode table per group */
|
||||
struct ext2_gd *e2fs_gd; /* group descripors */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Filesystem identification
|
||||
*/
|
||||
#define E2FS_MAGIC 0xef53 /* the ext2fs magic number */
|
||||
#define E2FS_REV0 0 /* GOOD_OLD revision */
|
||||
#define E2FS_REV1 1 /* Support compat/incompat features */
|
||||
|
||||
/* compatible/incompatible features */
|
||||
#define EXT2F_COMPAT_PREALLOC 0x0001
|
||||
#define EXT2F_COMPAT_HASJOURNAL 0x0004
|
||||
#define EXT2F_COMPAT_RESIZE 0x0010
|
||||
|
||||
#define EXT2F_ROCOMPAT_SPARSESUPER 0x0001
|
||||
#define EXT2F_ROCOMPAT_LARGEFILE 0x0002
|
||||
#define EXT2F_ROCOMPAT_BTREE_DIR 0x0004
|
||||
|
||||
#define EXT2F_INCOMPAT_COMP 0x0001
|
||||
#define EXT2F_INCOMPAT_FTYPE 0x0002
|
||||
|
||||
/*
|
||||
* Features supported in this implementation
|
||||
*
|
||||
* We support the following REV1 features:
|
||||
* - EXT2F_ROCOMPAT_SPARSESUPER
|
||||
* superblock backups stored only in cg_has_sb(bno) groups
|
||||
* - EXT2F_ROCOMPAT_LARGEFILE
|
||||
* use e2di_dacl in struct ext2fs_dinode to store
|
||||
* upper 32bit of size for >2GB files
|
||||
* - EXT2F_INCOMPAT_FTYPE
|
||||
* store file type to e2d_type in struct ext2fs_direct
|
||||
* (on REV0 e2d_namlen is uint16_t and no e2d_type, like ffs)
|
||||
*/
|
||||
#define EXT2F_COMPAT_SUPP 0x0000
|
||||
#define EXT2F_ROCOMPAT_SUPP (EXT2F_ROCOMPAT_SPARSESUPER \
|
||||
| EXT2F_ROCOMPAT_LARGEFILE)
|
||||
#define EXT2F_INCOMPAT_SUPP EXT2F_INCOMPAT_FTYPE
|
||||
|
||||
/*
|
||||
* Definitions of behavior on errors
|
||||
*/
|
||||
#define E2FS_BEH_CONTINUE 1 /* continue operation */
|
||||
#define E2FS_BEH_READONLY 2 /* remount fs read only */
|
||||
#define E2FS_BEH_PANIC 3 /* cause panic */
|
||||
#define E2FS_BEH_DEFAULT E2FS_BEH_CONTINUE
|
||||
|
||||
/*
|
||||
* OS identification
|
||||
*/
|
||||
#define E2FS_OS_LINUX 0
|
||||
#define E2FS_OS_HURD 1
|
||||
#define E2FS_OS_MASIX 2
|
||||
#define E2FS_OS_FREEBSD 3
|
||||
#define E2FS_OS_LITES 4
|
||||
|
||||
/*
|
||||
* Filesystem clean flags
|
||||
*/
|
||||
#define E2FS_ISCLEAN 0x01
|
||||
#define E2FS_ERRORS 0x02
|
||||
|
||||
/* ext2 file system block group descriptor */
|
||||
|
||||
struct ext2_gd {
|
||||
uint32_t ext2bgd_b_bitmap; /* blocks bitmap block */
|
||||
uint32_t ext2bgd_i_bitmap; /* inodes bitmap block */
|
||||
uint32_t ext2bgd_i_tables; /* inodes table block */
|
||||
uint16_t ext2bgd_nbfree; /* number of free blocks */
|
||||
uint16_t ext2bgd_nifree; /* number of free inodes */
|
||||
uint16_t ext2bgd_ndirs; /* number of directories */
|
||||
uint16_t reserved;
|
||||
uint32_t reserved2[3];
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* If the EXT2F_ROCOMPAT_SPARSESUPER flag is set, the cylinder group has a
|
||||
* copy of the super and cylinder group descriptors blocks only if it's
|
||||
* 1, a power of 3, 5 or 7
|
||||
*/
|
||||
|
||||
static __inline int cg_has_sb(int) __unused;
|
||||
static __inline int
|
||||
cg_has_sb(int i)
|
||||
{
|
||||
int a3, a5, a7;
|
||||
|
||||
if (i == 0 || i == 1)
|
||||
return 1;
|
||||
for (a3 = 3, a5 = 5, a7 = 7;
|
||||
a3 <= i || a5 <= i || a7 <= i;
|
||||
a3 *= 3, a5 *= 5, a7 *= 7)
|
||||
if (i == a3 || i == a5 || i == a7)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* EXT2FS metadatas are stored in little-endian byte order. These macros
|
||||
* helps reading theses metadatas
|
||||
*/
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
# define h2fs16(x) (x)
|
||||
# define h2fs32(x) (x)
|
||||
# define h2fs64(x) (x)
|
||||
# define fs2h16(x) (x)
|
||||
# define fs2h32(x) (x)
|
||||
# define fs2h64(x) (x)
|
||||
# define e2fs_sbload(old, new) memcpy((new), (old), SBSIZE);
|
||||
# define e2fs_cgload(old, new, size) memcpy((new), (old), (size));
|
||||
# define e2fs_sbsave(old, new) memcpy((new), (old), SBSIZE);
|
||||
# define e2fs_cgsave(old, new, size) memcpy((new), (old), (size));
|
||||
#else
|
||||
void e2fs_sb_bswap(struct ext2fs *, struct ext2fs *);
|
||||
void e2fs_cg_bswap(struct ext2_gd *, struct ext2_gd *, int);
|
||||
# define h2fs16(x) bswap16(x)
|
||||
# define h2fs32(x) bswap32(x)
|
||||
# define h2fs64(x) bswap64(x)
|
||||
# define fs2h16(x) bswap16(x)
|
||||
# define fs2h32(x) bswap32(x)
|
||||
# define fs2h64(x) bswap64(x)
|
||||
# define e2fs_sbload(old, new) e2fs_sb_bswap((old), (new))
|
||||
# define e2fs_cgload(old, new, size) e2fs_cg_bswap((old), (new), (size));
|
||||
# define e2fs_sbsave(old, new) e2fs_sb_bswap((old), (new))
|
||||
# define e2fs_cgsave(old, new, size) e2fs_cg_bswap((old), (new), (size));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Turn file system block numbers into disk block addresses.
|
||||
* This maps file system blocks to device size blocks.
|
||||
*/
|
||||
#define fsbtodb(fs, b) ((b) << (fs)->e2fs_fsbtodb)
|
||||
#define dbtofsb(fs, b) ((b) >> (fs)->e2fs_fsbtodb)
|
||||
|
||||
/*
|
||||
* Macros for handling inode numbers:
|
||||
* inode number to file system block offset.
|
||||
* inode number to cylinder group number.
|
||||
* inode number to file system block address.
|
||||
*/
|
||||
#define ino_to_cg(fs, x) (((x) - 1) / (fs)->e2fs.e2fs_ipg)
|
||||
#define ino_to_fsba(fs, x) \
|
||||
((fs)->e2fs_gd[ino_to_cg((fs), (x))].ext2bgd_i_tables + \
|
||||
(((x) - 1) % (fs)->e2fs.e2fs_ipg) / (fs)->e2fs_ipb)
|
||||
#define ino_to_fsbo(fs, x) (((x) - 1) % (fs)->e2fs_ipb)
|
||||
|
||||
/*
|
||||
* Give cylinder group number for a file system block.
|
||||
* Give cylinder group block number for a file system block.
|
||||
*/
|
||||
#define dtog(fs, d) (((d) - (fs)->e2fs.e2fs_first_dblock) / (fs)->e2fs.e2fs_fpg)
|
||||
#define dtogd(fs, d) \
|
||||
(((d) - (fs)->e2fs.e2fs_first_dblock) % (fs)->e2fs.e2fs_fpg)
|
||||
|
||||
/*
|
||||
* The following macros optimize certain frequently calculated
|
||||
* quantities by using shifts and masks in place of divisions
|
||||
* modulos and multiplications.
|
||||
*/
|
||||
#define blkoff(fs, loc) /* calculates (loc % fs->e2fs_bsize) */ \
|
||||
((loc) & (fs)->e2fs_qbmask)
|
||||
#define lblktosize(fs, blk) /* calculates (blk * fs->e2fs_bsize) */ \
|
||||
((blk) << (fs)->e2fs_bshift)
|
||||
#define lblkno(fs, loc) /* calculates (loc / fs->e2fs_bsize) */ \
|
||||
((loc) >> (fs)->e2fs_bshift)
|
||||
#define blkroundup(fs, size) /* calculates roundup(size, fs->e2fs_bsize) */ \
|
||||
(((size) + (fs)->e2fs_qbmask) & (fs)->e2fs_bmask)
|
||||
#define fragroundup(fs, size) /* calculates roundup(size, fs->e2fs_bsize) */ \
|
||||
(((size) + (fs)->e2fs_qbmask) & (fs)->e2fs_bmask)
|
||||
/*
|
||||
* Determine the number of available frags given a
|
||||
* percentage to hold in reserve.
|
||||
*/
|
||||
#define freespace(fs) \
|
||||
((fs)->e2fs.e2fs_fbcount - (fs)->e2fs.e2fs_rbcount)
|
||||
|
||||
/*
|
||||
* Number of indirects in a file system block.
|
||||
*/
|
||||
#define NINDIR(fs) ((fs)->e2fs_bsize / sizeof(uint32_t))
|
||||
|
||||
#endif /* !_UFS_EXT2FS_EXT2FS_H_ */
|
186
nbsd_include/ufs/ext2fs/ext2fs_dinode.h
Normal file
186
nbsd_include/ufs/ext2fs/ext2fs_dinode.h
Normal file
|
@ -0,0 +1,186 @@
|
|||
/* $NetBSD: ext2fs_dinode.h,v 1.22 2009/11/27 11:16:54 tsutsui Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* (c) UNIX System Laboratories, Inc.
|
||||
* All or some portions of this file are derived from material licensed
|
||||
* to the University of California by American Telephone and Telegraph
|
||||
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
|
||||
* the permission of UNIX System Laboratories, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)dinode.h 8.6 (Berkeley) 9/13/94
|
||||
* Modified for ext2fs by Manuel Bouyer.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Manuel Bouyer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @(#)dinode.h 8.6 (Berkeley) 9/13/94
|
||||
* Modified for ext2fs by Manuel Bouyer.
|
||||
*/
|
||||
|
||||
#ifndef _UFS_EXT2FS_EXT2FS_DINODE_H_
|
||||
#define _UFS_EXT2FS_EXT2FS_DINODE_H_
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
/*
|
||||
* The root inode is the root of the file system. Inode 0 can't be used for
|
||||
* normal purposes and bad blocks are normally linked to inode 1, thus
|
||||
* the root inode is 2.
|
||||
* Inode 3 to 10 are reserved in ext2fs.
|
||||
*/
|
||||
#define EXT2_BADBLKINO ((ino_t)1)
|
||||
#define EXT2_ROOTINO ((ino_t)2)
|
||||
#define EXT2_ACLIDXINO ((ino_t)3)
|
||||
#define EXT2_ACLDATAINO ((ino_t)4)
|
||||
#define EXT2_BOOTLOADERINO ((ino_t)5)
|
||||
#define EXT2_UNDELDIRINO ((ino_t)6)
|
||||
#define EXT2_RESIZEINO ((ino_t)7)
|
||||
#define EXT2_JOURNALINO ((ino_t)8)
|
||||
#define EXT2_FIRSTINO ((ino_t)11)
|
||||
|
||||
/*
|
||||
* A dinode contains all the meta-data associated with a UFS file.
|
||||
* This structure defines the on-disk format of a dinode. Since
|
||||
* this structure describes an on-disk structure, all its fields
|
||||
* are defined by types with precise widths.
|
||||
*/
|
||||
|
||||
#define NDADDR 12 /* Direct addresses in inode. */
|
||||
#define NIADDR 3 /* Indirect addresses in inode. */
|
||||
|
||||
#define EXT2_MAXSYMLINKLEN ((NDADDR+NIADDR) * sizeof (uint32_t))
|
||||
|
||||
struct ext2fs_dinode {
|
||||
uint16_t e2di_mode; /* 0: IFMT, permissions; see below. */
|
||||
uint16_t e2di_uid; /* 2: Owner UID */
|
||||
uint32_t e2di_size; /* 4: Size (in bytes) */
|
||||
uint32_t e2di_atime; /* 8: Acces time */
|
||||
uint32_t e2di_ctime; /* 12: Create time */
|
||||
uint32_t e2di_mtime; /* 16: Modification time */
|
||||
uint32_t e2di_dtime; /* 20: Deletion time */
|
||||
uint16_t e2di_gid; /* 24: Owner GID */
|
||||
uint16_t e2di_nlink; /* 26: File link count */
|
||||
uint32_t e2di_nblock; /* 28: Blocks count */
|
||||
uint32_t e2di_flags; /* 32: Status flags (chflags) */
|
||||
uint32_t e2di_linux_reserved1; /* 36 */
|
||||
uint32_t e2di_blocks[NDADDR+NIADDR]; /* 40: disk blocks */
|
||||
uint32_t e2di_gen; /* 100: generation number */
|
||||
uint32_t e2di_facl; /* 104: file ACL (not implemented) */
|
||||
uint32_t e2di_dacl; /* 108: dir ACL (not implemented) */
|
||||
uint32_t e2di_faddr; /* 112: fragment address */
|
||||
uint8_t e2di_nfrag; /* 116: fragment number */
|
||||
uint8_t e2di_fsize; /* 117: fragment size */
|
||||
uint16_t e2di_linux_reserved2; /* 118 */
|
||||
uint16_t e2di_uid_high; /* 120: Owner UID top 16 bits */
|
||||
uint16_t e2di_gid_high; /* 122: Owner GID top 16 bits */
|
||||
uint32_t e2di_linux_reserved3; /* 124 */
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define E2MAXSYMLINKLEN ((NDADDR + NIADDR) * sizeof(uint32_t))
|
||||
|
||||
/* File permissions. */
|
||||
#define EXT2_IEXEC 0000100 /* Executable. */
|
||||
#define EXT2_IWRITE 0000200 /* Writable. */
|
||||
#define EXT2_IREAD 0000400 /* Readable. */
|
||||
#define EXT2_ISVTX 0001000 /* Sticky bit. */
|
||||
#define EXT2_ISGID 0002000 /* Set-gid. */
|
||||
#define EXT2_ISUID 0004000 /* Set-uid. */
|
||||
|
||||
/* File types. */
|
||||
#define EXT2_IFMT 0170000 /* Mask of file type. */
|
||||
#define EXT2_IFIFO 0010000 /* Named pipe (fifo). */
|
||||
#define EXT2_IFCHR 0020000 /* Character device. */
|
||||
#define EXT2_IFDIR 0040000 /* Directory file. */
|
||||
#define EXT2_IFBLK 0060000 /* Block device. */
|
||||
#define EXT2_IFREG 0100000 /* Regular file. */
|
||||
#define EXT2_IFLNK 0120000 /* Symbolic link. */
|
||||
#define EXT2_IFSOCK 0140000 /* UNIX domain socket. */
|
||||
|
||||
/* file flags */
|
||||
#define EXT2_SECRM 0x00000001 /* Secure deletion */
|
||||
#define EXT2_UNRM 0x00000002 /* Undelete */
|
||||
#define EXT2_COMPR 0x00000004 /* Compress file */
|
||||
#define EXT2_SYNC 0x00000008 /* Synchronous updates */
|
||||
#define EXT2_IMMUTABLE 0x00000010 /* Immutable file */
|
||||
#define EXT2_APPEND 0x00000020 /* writes to file may only append */
|
||||
#define EXT2_NODUMP 0x00000040 /* do not dump file */
|
||||
|
||||
/* Size of on-disk inode. */
|
||||
#define EXT2_REV0_DINODE_SIZE sizeof(struct ext2fs_dinode)
|
||||
#define EXT2_DINODE_SIZE(fs) ((fs)->e2fs.e2fs_rev > E2FS_REV0 ? \
|
||||
(fs)->e2fs.e2fs_inode_size : \
|
||||
EXT2_REV0_DINODE_SIZE)
|
||||
|
||||
/*
|
||||
* The e2di_blocks fields may be overlaid with other information for
|
||||
* file types that do not have associated disk storage. Block
|
||||
* and character devices overlay the first data block with their
|
||||
* dev_t value. Short symbolic links place their path in the
|
||||
* di_db area.
|
||||
*/
|
||||
|
||||
#define e2di_rdev e2di_blocks[0]
|
||||
#define e2di_shortlink e2di_blocks
|
||||
|
||||
/* e2fs needs byte swapping on big-endian systems */
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
# define e2fs_iload(old, new) \
|
||||
memcpy((new),(old),sizeof(struct ext2fs_dinode))
|
||||
# define e2fs_isave(old, new) \
|
||||
memcpy((new),(old),sizeof(struct ext2fs_dinode))
|
||||
#else
|
||||
void e2fs_i_bswap(struct ext2fs_dinode *, struct ext2fs_dinode *);
|
||||
# define e2fs_iload(old, new) e2fs_i_bswap((old), (new))
|
||||
# define e2fs_isave(old, new) e2fs_i_bswap((old), (new))
|
||||
#endif
|
||||
|
||||
#endif /* !_UFS_EXT2FS_EXT2FS_DINODE_H_ */
|
180
nbsd_include/ufs/ext2fs/ext2fs_dir.h
Normal file
180
nbsd_include/ufs/ext2fs/ext2fs_dir.h
Normal file
|
@ -0,0 +1,180 @@
|
|||
/* $NetBSD: ext2fs_dir.h,v 1.18 2009/10/19 18:41:17 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* (c) UNIX System Laboratories, Inc.
|
||||
* All or some portions of this file are derived from material licensed
|
||||
* to the University of California by American Telephone and Telegraph
|
||||
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
|
||||
* the permission of UNIX System Laboratories, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)dir.h 8.4 (Berkeley) 8/10/94
|
||||
* Modified for ext2fs by Manuel Bouyer.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Manuel Bouyer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @(#)dir.h 8.4 (Berkeley) 8/10/94
|
||||
* Modified for ext2fs by Manuel Bouyer.
|
||||
*/
|
||||
|
||||
#ifndef _UFS_EXT2FS_EXT2FS_DIR_H_
|
||||
#define _UFS_EXT2FS_EXT2FS_DIR_H_
|
||||
|
||||
/*
|
||||
* Theoretically, directories can be more than 2Gb in length, however, in
|
||||
* practice this seems unlikely. So, we define the type doff_t as a 32-bit
|
||||
* quantity to keep down the cost of doing lookup on a 32-bit machine.
|
||||
*/
|
||||
#define doff_t int32_t
|
||||
#define EXT2FS_MAXDIRSIZE INT32_MAX
|
||||
|
||||
/*
|
||||
* A directory consists of some number of blocks of e2fs_bsize bytes.
|
||||
*
|
||||
* Each block contains some number of directory entry
|
||||
* structures, which are of variable length. Each directory entry has
|
||||
* a struct direct at the front of it, containing its inode number,
|
||||
* the length of the entry, and the length of the name contained in
|
||||
* the entry. These are followed by the name padded to a 4 byte boundary
|
||||
* with null bytes. All names are guaranteed null terminated.
|
||||
* The maximum length of a name in a directory is EXT2FS_MAXNAMLEN.
|
||||
*
|
||||
* The macro EXT2FS_DIRSIZ(fmt, dp) gives the amount of space required to
|
||||
* represent a directory entry. Free space in a directory is represented by
|
||||
* entries which have dp->e2d_reclen > DIRSIZ(fmt, dp). All d2fs_bsize bytes
|
||||
* in a directory block are claimed by the directory entries. This
|
||||
* usually results in the last entry in a directory having a large
|
||||
* dp->e2d_reclen. When entries are deleted from a directory, the
|
||||
* space is returned to the previous entry in the same directory
|
||||
* block by increasing its dp->e2d_reclen. If the first entry of
|
||||
* a directory block is free, then its dp->e2d_ino is set to 0.
|
||||
* Entries other than the first in a directory do not normally have
|
||||
* dp->e2d_ino set to 0.
|
||||
* Ext2 rev 0 has a 16 bits e2d_namlen. For Ext2 vev 1 this has been split
|
||||
* into a 8 bits e2d_namlen and 8 bits e2d_type (looks like ffs, isnt't it ? :)
|
||||
* It's safe to use this for rev 0 as well because all ext2 are little-endian.
|
||||
*/
|
||||
|
||||
#define EXT2FS_MAXNAMLEN 255
|
||||
|
||||
struct ext2fs_direct {
|
||||
uint32_t e2d_ino; /* inode number of entry */
|
||||
uint16_t e2d_reclen; /* length of this record */
|
||||
uint8_t e2d_namlen; /* length of string in d_name */
|
||||
uint8_t e2d_type; /* file type */
|
||||
char e2d_name[EXT2FS_MAXNAMLEN];/* name with length<=EXT2FS_MAXNAMLEN */
|
||||
};
|
||||
|
||||
/* Ext2 directory file types (not the same as FFS. Sigh.) */
|
||||
#define EXT2_FT_UNKNOWN 0
|
||||
#define EXT2_FT_REG_FILE 1
|
||||
#define EXT2_FT_DIR 2
|
||||
#define EXT2_FT_CHRDEV 3
|
||||
#define EXT2_FT_BLKDEV 4
|
||||
#define EXT2_FT_FIFO 5
|
||||
#define EXT2_FT_SOCK 6
|
||||
#define EXT2_FT_SYMLINK 7
|
||||
|
||||
#define EXT2_FT_MAX 8
|
||||
|
||||
#define E2IFTODT(mode) (((mode) & 0170000) >> 12)
|
||||
|
||||
static __inline uint8_t inot2ext2dt(uint16_t) __unused;
|
||||
static __inline uint8_t
|
||||
inot2ext2dt(uint16_t type)
|
||||
{
|
||||
|
||||
switch (type) {
|
||||
case E2IFTODT(EXT2_IFIFO):
|
||||
return EXT2_FT_FIFO;
|
||||
case E2IFTODT(EXT2_IFCHR):
|
||||
return EXT2_FT_CHRDEV;
|
||||
case E2IFTODT(EXT2_IFDIR):
|
||||
return EXT2_FT_DIR;
|
||||
case E2IFTODT(EXT2_IFBLK):
|
||||
return EXT2_FT_BLKDEV;
|
||||
case E2IFTODT(EXT2_IFREG):
|
||||
return EXT2_FT_REG_FILE;
|
||||
case E2IFTODT(EXT2_IFLNK):
|
||||
return EXT2_FT_SYMLINK;
|
||||
case E2IFTODT(EXT2_IFSOCK):
|
||||
return EXT2_FT_SOCK;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The EXT2FS_DIRSIZ macro gives the minimum record length which will hold
|
||||
* the directory entryfor a name len "len" (without the terminating null byte).
|
||||
* This requires the amount of space in struct direct
|
||||
* without the d_name field, plus enough space for the name without a
|
||||
* terminating null byte, rounded up to a 4 byte boundary.
|
||||
*/
|
||||
#define EXT2FS_DIRSIZ(len) roundup2(8 + len, 4)
|
||||
|
||||
/*
|
||||
* Template for manipulating directories. Should use struct direct's,
|
||||
* but the name field is EXT2FS_MAXNAMLEN - 1, and this just won't do.
|
||||
*/
|
||||
struct ext2fs_dirtemplate {
|
||||
uint32_t dot_ino;
|
||||
int16_t dot_reclen;
|
||||
uint8_t dot_namlen;
|
||||
uint8_t dot_type;
|
||||
char dot_name[4]; /* must be multiple of 4 */
|
||||
uint32_t dotdot_ino;
|
||||
int16_t dotdot_reclen;
|
||||
uint8_t dotdot_namlen;
|
||||
uint8_t dotdot_type;
|
||||
char dotdot_name[4]; /* ditto */
|
||||
};
|
||||
|
||||
#endif /* !_UFS_EXT2FS_EXT2FS_DIR_H_ */
|
179
nbsd_include/ufs/ext2fs/ext2fs_extern.h
Normal file
179
nbsd_include/ufs/ext2fs/ext2fs_extern.h
Normal file
|
@ -0,0 +1,179 @@
|
|||
/* $NetBSD: ext2fs_extern.h,v 1.43 2011/07/12 16:59:48 dholland Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ffs_extern.h 8.3 (Berkeley) 4/16/94
|
||||
* Modified for ext2fs by Manuel Bouyer.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997 Manuel Bouyer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ffs_extern.h 8.3 (Berkeley) 4/16/94
|
||||
* Modified for ext2fs by Manuel Bouyer.
|
||||
*/
|
||||
|
||||
#ifndef _UFS_EXT2FS_EXT2FS_EXTERN_H_
|
||||
#define _UFS_EXT2FS_EXT2FS_EXTERN_H_
|
||||
|
||||
struct buf;
|
||||
struct fid;
|
||||
struct m_ext2fs;
|
||||
struct inode;
|
||||
struct mount;
|
||||
struct nameidata;
|
||||
struct lwp;
|
||||
struct proc;
|
||||
struct statvfs;
|
||||
struct timeval;
|
||||
struct ufsmount;
|
||||
struct uio;
|
||||
struct vnode;
|
||||
struct mbuf;
|
||||
struct componentname;
|
||||
|
||||
extern struct pool ext2fs_inode_pool; /* memory pool for inodes */
|
||||
extern struct pool ext2fs_dinode_pool; /* memory pool for dinodes */
|
||||
|
||||
#define EXT2FS_ITIMES(ip, acc, mod, cre) \
|
||||
while ((ip)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY)) \
|
||||
ext2fs_itimes(ip, acc, mod, cre)
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/* ext2fs_alloc.c */
|
||||
int ext2fs_alloc(struct inode *, daddr_t, daddr_t , kauth_cred_t,
|
||||
daddr_t *);
|
||||
int ext2fs_realloccg(struct inode *, daddr_t, daddr_t, int, int ,
|
||||
kauth_cred_t, struct buf **);
|
||||
int ext2fs_valloc(struct vnode *, int, kauth_cred_t, struct vnode **);
|
||||
/* XXX ondisk32 */
|
||||
daddr_t ext2fs_blkpref(struct inode *, daddr_t, int, int32_t *);
|
||||
void ext2fs_blkfree(struct inode *, daddr_t);
|
||||
int ext2fs_vfree(struct vnode *, ino_t, int);
|
||||
|
||||
/* ext2fs_balloc.c */
|
||||
int ext2fs_balloc(struct inode *, daddr_t, int, kauth_cred_t,
|
||||
struct buf **, int);
|
||||
int ext2fs_gop_alloc(struct vnode *, off_t, off_t, int, kauth_cred_t);
|
||||
|
||||
/* ext2fs_bmap.c */
|
||||
int ext2fs_bmap(void *);
|
||||
|
||||
/* ext2fs_inode.c */
|
||||
u_int64_t ext2fs_size(struct inode *);
|
||||
int ext2fs_setsize(struct inode *, u_int64_t);
|
||||
int ext2fs_update(struct vnode *, const struct timespec *,
|
||||
const struct timespec *, int);
|
||||
int ext2fs_truncate(struct vnode *, off_t, int, kauth_cred_t);
|
||||
int ext2fs_inactive(void *);
|
||||
|
||||
/* ext2fs_lookup.c */
|
||||
int ext2fs_readdir(void *);
|
||||
int ext2fs_lookup(void *);
|
||||
int ext2fs_direnter(struct inode *, struct vnode *,
|
||||
const struct ufs_lookup_results *,
|
||||
struct componentname *);
|
||||
int ext2fs_dirremove(struct vnode *, const struct ufs_lookup_results *,
|
||||
struct componentname *);
|
||||
int ext2fs_dirrewrite(struct inode *, const struct ufs_lookup_results *,
|
||||
struct inode *, struct componentname *);
|
||||
int ext2fs_dirempty(struct inode *, ino_t, kauth_cred_t);
|
||||
int ext2fs_checkpath(struct inode *, struct inode *, kauth_cred_t);
|
||||
|
||||
/* ext2fs_subr.c */
|
||||
int ext2fs_blkatoff(struct vnode *, off_t, char **, struct buf **);
|
||||
void ext2fs_fragacct(struct m_ext2fs *, int, int32_t[], int);
|
||||
void ext2fs_itimes(struct inode *, const struct timespec *,
|
||||
const struct timespec *, const struct timespec *);
|
||||
|
||||
/* ext2fs_vfsops.c */
|
||||
VFS_PROTOS(ext2fs);
|
||||
int ext2fs_reload(struct mount *, kauth_cred_t, struct lwp *);
|
||||
int ext2fs_mountfs(struct vnode *, struct mount *);
|
||||
int ext2fs_flushfiles(struct mount *, int);
|
||||
int ext2fs_sbupdate(struct ufsmount *, int);
|
||||
int ext2fs_cgupdate(struct ufsmount *, int);
|
||||
void ext2fs_set_inode_guid(struct inode *);
|
||||
|
||||
/* ext2fs_readwrite.c */
|
||||
int ext2fs_read(void *);
|
||||
int ext2fs_write(void *);
|
||||
|
||||
/* ext2fs_vnops.c */
|
||||
int ext2fs_create(void *);
|
||||
int ext2fs_mknod(void *);
|
||||
int ext2fs_open(void *);
|
||||
int ext2fs_access(void *);
|
||||
int ext2fs_getattr(void *);
|
||||
int ext2fs_setattr(void *);
|
||||
int ext2fs_remove(void *);
|
||||
int ext2fs_link(void *);
|
||||
int ext2fs_rename(void *);
|
||||
int ext2fs_mkdir(void *);
|
||||
int ext2fs_rmdir(void *);
|
||||
int ext2fs_symlink(void *);
|
||||
int ext2fs_readlink(void *);
|
||||
int ext2fs_advlock(void *);
|
||||
int ext2fs_fsync(void *);
|
||||
int ext2fs_vinit(struct mount *, int (**specops)(void *),
|
||||
int (**fifoops)(void *), struct vnode **);
|
||||
int ext2fs_makeinode(int, struct vnode *, struct vnode **,
|
||||
struct componentname *cnp);
|
||||
int ext2fs_reclaim(void *);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#define IS_EXT2_VNODE(vp) (vp->v_tag == VT_EXT2FS)
|
||||
|
||||
extern int (**ext2fs_vnodeop_p)(void *);
|
||||
extern int (**ext2fs_specop_p)(void *);
|
||||
extern int (**ext2fs_fifoop_p)(void *);
|
||||
|
||||
#endif /* !_UFS_EXT2FS_EXT2FS_EXTERN_H_ */
|
211
nbsd_include/ufs/ffs/ffs_extern.h
Normal file
211
nbsd_include/ufs/ffs/ffs_extern.h
Normal file
|
@ -0,0 +1,211 @@
|
|||
/* $NetBSD: ffs_extern.h,v 1.78 2011/06/17 14:23:52 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ffs_extern.h 8.6 (Berkeley) 3/30/95
|
||||
*/
|
||||
|
||||
#ifndef _UFS_FFS_FFS_EXTERN_H_
|
||||
#define _UFS_FFS_FFS_EXTERN_H_
|
||||
|
||||
/*
|
||||
* Sysctl values for the fast filesystem.
|
||||
*/
|
||||
#define FFS_CLUSTERREAD 1 /* cluster reading enabled */
|
||||
#define FFS_CLUSTERWRITE 2 /* cluster writing enabled */
|
||||
#define FFS_REALLOCBLKS 3 /* block reallocation enabled */
|
||||
#define FFS_ASYNCFREE 4 /* asynchronous block freeing enabled */
|
||||
#define FFS_LOG_CHANGEOPT 5 /* log optimalization strategy change */
|
||||
#define FFS_EXTATTR_AUTOCREATE 6 /* size for backing file autocreation */
|
||||
#define FFS_MAXID 7 /* number of valid ffs ids */
|
||||
|
||||
struct buf;
|
||||
struct fid;
|
||||
struct fs;
|
||||
struct inode;
|
||||
struct ufs1_dinode;
|
||||
struct ufs2_dinode;
|
||||
struct mount;
|
||||
struct nameidata;
|
||||
struct lwp;
|
||||
struct statvfs;
|
||||
struct timeval;
|
||||
struct timespec;
|
||||
struct ufsmount;
|
||||
struct uio;
|
||||
struct vnode;
|
||||
struct mbuf;
|
||||
struct cg;
|
||||
|
||||
#if defined(_KERNEL)
|
||||
|
||||
#include <sys/pool.h>
|
||||
|
||||
#define FFS_NOBLK ((daddr_t)-1)
|
||||
|
||||
#define FFS_ITIMES(ip, acc, mod, cre) \
|
||||
while ((ip)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE | IN_MODIFY)) \
|
||||
ffs_itimes(ip, acc, mod, cre)
|
||||
|
||||
extern pool_cache_t ffs_inode_cache; /* memory pool for inodes */
|
||||
extern pool_cache_t ffs_dinode1_cache; /* memory pool for UFS1 dinodes */
|
||||
extern pool_cache_t ffs_dinode2_cache; /* memory pool for UFS2 dinodes */
|
||||
|
||||
#endif /* defined(_KERNEL) */
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#if defined(_KERNEL)
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/wapbl.h>
|
||||
|
||||
/* ffs_alloc.c */
|
||||
int ffs_alloc(struct inode *, daddr_t, daddr_t , int, int, kauth_cred_t,
|
||||
daddr_t *);
|
||||
int ffs_realloccg(struct inode *, daddr_t, daddr_t, int, int ,
|
||||
kauth_cred_t, struct buf **, daddr_t *);
|
||||
int ffs_valloc(struct vnode *, int, kauth_cred_t, struct vnode **);
|
||||
daddr_t ffs_blkpref_ufs1(struct inode *, daddr_t, int, int, int32_t *);
|
||||
daddr_t ffs_blkpref_ufs2(struct inode *, daddr_t, int, int, int64_t *);
|
||||
int ffs_blkalloc(struct inode *, daddr_t, long);
|
||||
int ffs_blkalloc_ump(struct ufsmount *, daddr_t, long);
|
||||
void ffs_blkfree(struct fs *, struct vnode *, daddr_t, long, ino_t);
|
||||
void ffs_blkfree_snap(struct fs *, struct vnode *, daddr_t, long, ino_t);
|
||||
int ffs_vfree(struct vnode *, ino_t, int);
|
||||
int ffs_checkfreefile(struct fs *, struct vnode *, ino_t);
|
||||
int ffs_freefile(struct mount *, ino_t, int);
|
||||
int ffs_freefile_snap(struct fs *, struct vnode *, ino_t, int);
|
||||
|
||||
/* ffs_balloc.c */
|
||||
int ffs_balloc(struct vnode *, off_t, int, kauth_cred_t, int,
|
||||
struct buf **);
|
||||
|
||||
/* ffs_inode.c */
|
||||
int ffs_update(struct vnode *, const struct timespec *,
|
||||
const struct timespec *, int);
|
||||
int ffs_truncate(struct vnode *, off_t, int, kauth_cred_t);
|
||||
|
||||
/* ffs_vfsops.c */
|
||||
VFS_PROTOS(ffs);
|
||||
|
||||
int ffs_reload(struct mount *, kauth_cred_t, struct lwp *);
|
||||
int ffs_mountfs(struct vnode *, struct mount *, struct lwp *);
|
||||
int ffs_flushfiles(struct mount *, int, struct lwp *);
|
||||
int ffs_sbupdate(struct ufsmount *, int);
|
||||
int ffs_cgupdate(struct ufsmount *, int);
|
||||
|
||||
/* ffs_vnops.c */
|
||||
int ffs_read(void *);
|
||||
int ffs_write(void *);
|
||||
int ffs_fsync(void *);
|
||||
int ffs_spec_fsync(void *);
|
||||
int ffs_reclaim(void *);
|
||||
int ffs_getpages(void *);
|
||||
void ffs_gop_size(struct vnode *, off_t, off_t *, int);
|
||||
int ffs_openextattr(void *);
|
||||
int ffs_closeextattr(void *);
|
||||
int ffs_getextattr(void *);
|
||||
int ffs_setextattr(void *);
|
||||
int ffs_listextattr(void *);
|
||||
int ffs_deleteextattr(void *);
|
||||
int ffs_lock(void *);
|
||||
int ffs_unlock(void *);
|
||||
int ffs_islocked(void *);
|
||||
int ffs_full_fsync(struct vnode *, int);
|
||||
|
||||
/*
|
||||
* Snapshot function prototypes.
|
||||
*/
|
||||
int ffs_snapshot_init(struct ufsmount *);
|
||||
void ffs_snapshot_fini(struct ufsmount *);
|
||||
int ffs_snapblkfree(struct fs *, struct vnode *, daddr_t, long, ino_t);
|
||||
void ffs_snapremove(struct vnode *);
|
||||
int ffs_snapshot(struct mount *, struct vnode *, struct timespec *);
|
||||
void ffs_snapshot_mount(struct mount *);
|
||||
void ffs_snapshot_unmount(struct mount *);
|
||||
void ffs_snapgone(struct inode *);
|
||||
int ffs_snapshot_read(struct vnode *, struct uio *, int);
|
||||
|
||||
/* Write Ahead Physical Block Logging */
|
||||
void ffs_wapbl_verify_inodes(struct mount *, const char *);
|
||||
void ffs_wapbl_replay_finish(struct mount *);
|
||||
int ffs_wapbl_start(struct mount *);
|
||||
int ffs_wapbl_stop(struct mount *, int);
|
||||
int ffs_wapbl_replay_start(struct mount *, struct fs *, struct vnode *);
|
||||
void ffs_wapbl_blkalloc(struct fs *, struct vnode *, daddr_t, int);
|
||||
|
||||
void ffs_wapbl_sync_metadata(struct mount *, daddr_t *, int *, int);
|
||||
void ffs_wapbl_abort_sync_metadata(struct mount *, daddr_t *, int *, int);
|
||||
|
||||
extern int (**ffs_vnodeop_p)(void *);
|
||||
extern int (**ffs_specop_p)(void *);
|
||||
extern int (**ffs_fifoop_p)(void *);
|
||||
|
||||
#endif /* defined(_KERNEL) */
|
||||
|
||||
/* ffs_appleufs.c */
|
||||
struct appleufslabel;
|
||||
u_int16_t ffs_appleufs_cksum(const struct appleufslabel *);
|
||||
int ffs_appleufs_validate(const char*, const struct appleufslabel *,
|
||||
struct appleufslabel *);
|
||||
void ffs_appleufs_set(struct appleufslabel *, const char *, time_t,
|
||||
uint64_t);
|
||||
|
||||
/* ffs_bswap.c */
|
||||
void ffs_sb_swap(struct fs*, struct fs *);
|
||||
void ffs_dinode1_swap(struct ufs1_dinode *, struct ufs1_dinode *);
|
||||
void ffs_dinode2_swap(struct ufs2_dinode *, struct ufs2_dinode *);
|
||||
struct csum;
|
||||
void ffs_csum_swap(struct csum *, struct csum *, int);
|
||||
struct csum_total;
|
||||
void ffs_csumtotal_swap(struct csum_total *, struct csum_total *);
|
||||
void ffs_cg_swap(struct cg *, struct cg *, struct fs *);
|
||||
|
||||
/* ffs_subr.c */
|
||||
#if defined(_KERNEL)
|
||||
void ffs_load_inode(struct buf *, struct inode *, struct fs *, ino_t);
|
||||
int ffs_getblk(struct vnode *, daddr_t, daddr_t, int, bool, buf_t **);
|
||||
#endif /* defined(_KERNEL) */
|
||||
void ffs_fragacct(struct fs *, int, int32_t[], int, int);
|
||||
int ffs_isblock(struct fs *, u_char *, int32_t);
|
||||
int ffs_isfreeblock(struct fs *, u_char *, int32_t);
|
||||
void ffs_clrblock(struct fs *, u_char *, int32_t);
|
||||
void ffs_setblock(struct fs *, u_char *, int32_t);
|
||||
void ffs_itimes(struct inode *, const struct timespec *,
|
||||
const struct timespec *, const struct timespec *);
|
||||
void ffs_clusteracct(struct fs *, struct cg *, int32_t, int);
|
||||
|
||||
/* ffs_quota2.c */
|
||||
int ffs_quota2_mount(struct mount *);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* !_UFS_FFS_FFS_EXTERN_H_ */
|
752
nbsd_include/ufs/ffs/fs.h
Normal file
752
nbsd_include/ufs/ffs/fs.h
Normal file
|
@ -0,0 +1,752 @@
|
|||
/* $NetBSD: fs.h,v 1.56 2011/03/06 17:08:38 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)fs.h 8.13 (Berkeley) 3/21/95
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTE: COORDINATE ON-DISK FORMAT CHANGES WITH THE FREEBSD PROJECT.
|
||||
*/
|
||||
|
||||
#ifndef _UFS_FFS_FS_H_
|
||||
#define _UFS_FFS_FS_H_
|
||||
|
||||
/*
|
||||
* Each disk drive contains some number of file systems.
|
||||
* A file system consists of a number of cylinder groups.
|
||||
* Each cylinder group has inodes and data.
|
||||
*
|
||||
* A file system is described by its super-block, which in turn
|
||||
* describes the cylinder groups. The super-block is critical
|
||||
* data and is replicated in each cylinder group to protect against
|
||||
* catastrophic loss. This is done at `newfs' time and the critical
|
||||
* super-block data does not change, so the copies need not be
|
||||
* referenced further unless disaster strikes.
|
||||
*
|
||||
* For file system fs, the offsets of the various blocks of interest
|
||||
* are given in the super block as:
|
||||
* [fs->fs_sblkno] Super-block
|
||||
* [fs->fs_cblkno] Cylinder group block
|
||||
* [fs->fs_iblkno] Inode blocks
|
||||
* [fs->fs_dblkno] Data blocks
|
||||
* The beginning of cylinder group cg in fs, is given by
|
||||
* the ``cgbase(fs, cg)'' macro.
|
||||
*
|
||||
* Depending on the architecture and the media, the superblock may
|
||||
* reside in any one of four places. For tiny media where every block
|
||||
* counts, it is placed at the very front of the partition. Historically,
|
||||
* UFS1 placed it 8K from the front to leave room for the disk label and
|
||||
* a small bootstrap. For UFS2 it got moved to 64K from the front to leave
|
||||
* room for the disk label and a bigger bootstrap, and for really piggy
|
||||
* systems we check at 256K from the front if the first three fail. In
|
||||
* all cases the size of the superblock will be SBLOCKSIZE. All values are
|
||||
* given in byte-offset form, so they do not imply a sector size. The
|
||||
* SBLOCKSEARCH specifies the order in which the locations should be searched.
|
||||
*
|
||||
* Unfortunately the UFS2/FFSv2 change was done without adequate consideration
|
||||
* of backward compatibility. In particular 'newfs' for a FFSv2 partition
|
||||
* must overwrite any old FFSv1 superblock at 8k, and preferrably as many
|
||||
* of the alternates as it can find - otherwise attempting to mount on a
|
||||
* system that only supports FFSv1 is likely to succeed!.
|
||||
* For a small FFSv1 filesystem, an old FFSv2 superblock can be left on
|
||||
* the disk, and a system that tries to find an FFSv2 filesystem in preference
|
||||
* to and FFSv1 one (as NetBSD does) can mount the old FFSv2 filesystem.
|
||||
* As a added bonus, the 'first alternate' superblock of a FFSv1 filesystem
|
||||
* with 64k blocks is at 64k - just where the code looks first when playing
|
||||
* 'hunt the superblock'.
|
||||
*
|
||||
* The ffsv2 superblock layout (which might contain an ffsv1 filesystem)
|
||||
* can be detected by checking for sb->fs_old_flags & FS_FLAGS_UPDATED.
|
||||
* This is the default superblock type for NetBSD since ffsv2 support was added.
|
||||
*/
|
||||
#define BBSIZE 8192
|
||||
#define BBOFF ((off_t)(0))
|
||||
#define BBLOCK ((daddr_t)(0))
|
||||
|
||||
#define SBLOCK_FLOPPY 0
|
||||
#define SBLOCK_UFS1 8192
|
||||
#define SBLOCK_UFS2 65536
|
||||
#define SBLOCK_PIGGY 262144
|
||||
#define SBLOCKSIZE 8192
|
||||
/*
|
||||
* NB: Do not, under any circumstances, look for an ffsv1 filesystem at
|
||||
* SBLOCK_UFS2. Doing so will find the wrong superblock for filesystems
|
||||
* with a 64k block size.
|
||||
*/
|
||||
#define SBLOCKSEARCH \
|
||||
{ SBLOCK_UFS2, SBLOCK_UFS1, SBLOCK_FLOPPY, SBLOCK_PIGGY, -1 }
|
||||
|
||||
/*
|
||||
* Max number of fragments per block. This value is NOT tweakable.
|
||||
*/
|
||||
#define MAXFRAG 8
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Addresses stored in inodes are capable of addressing fragments
|
||||
* of `blocks'. File system blocks of at most size MAXBSIZE can
|
||||
* be optionally broken into 2, 4, or 8 pieces, each of which is
|
||||
* addressable; these pieces may be DEV_BSIZE, or some multiple of
|
||||
* a DEV_BSIZE unit.
|
||||
*
|
||||
* Large files consist of exclusively large data blocks. To avoid
|
||||
* undue wasted disk space, the last data block of a small file may be
|
||||
* allocated as only as many fragments of a large block as are
|
||||
* necessary. The file system format retains only a single pointer
|
||||
* to such a fragment, which is a piece of a single large block that
|
||||
* has been divided. The size of such a fragment is determinable from
|
||||
* information in the inode, using the ``blksize(fs, ip, lbn)'' macro.
|
||||
*
|
||||
* The file system records space availability at the fragment level;
|
||||
* to determine block availability, aligned fragments are examined.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MINBSIZE is the smallest allowable block size.
|
||||
* In order to insure that it is possible to create files of size
|
||||
* 2^32 with only two levels of indirection, MINBSIZE is set to 4096.
|
||||
* MINBSIZE must be big enough to hold a cylinder group block,
|
||||
* thus changes to (struct cg) must keep its size within MINBSIZE.
|
||||
* Note that super blocks are always of size SBSIZE,
|
||||
* and that both SBSIZE and MAXBSIZE must be >= MINBSIZE.
|
||||
*/
|
||||
#define MINBSIZE 4096
|
||||
|
||||
/*
|
||||
* The path name on which the file system is mounted is maintained
|
||||
* in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in
|
||||
* the super block for this name.
|
||||
*/
|
||||
#define MAXMNTLEN 468
|
||||
|
||||
/*
|
||||
* The volume name for this filesystem is maintained in fs_volname.
|
||||
* MAXVOLLEN defines the length of the buffer allocated.
|
||||
* This space used to be part of of fs_fsmnt.
|
||||
*/
|
||||
#define MAXVOLLEN 32
|
||||
|
||||
/*
|
||||
* There is a 128-byte region in the superblock reserved for in-core
|
||||
* pointers to summary information. Originally this included an array
|
||||
* of pointers to blocks of struct csum; now there are just four
|
||||
* pointers and the remaining space is padded with fs_ocsp[].
|
||||
* NOCSPTRS determines the size of this padding. One pointer (fs_csp)
|
||||
* is taken away to point to a contiguous array of struct csum for
|
||||
* all cylinder groups; a second (fs_maxcluster) points to an array
|
||||
* of cluster sizes that is computed as cylinder groups are inspected;
|
||||
* the third (fs_contigdirs) points to an array that tracks the
|
||||
* creation of new directories; and the fourth (fs_active) is used
|
||||
* by snapshots.
|
||||
*/
|
||||
#define NOCSPTRS ((128 / sizeof(void *)) - 4)
|
||||
|
||||
/*
|
||||
* A summary of contiguous blocks of various sizes is maintained
|
||||
* in each cylinder group. Normally this is set by the initial
|
||||
* value of fs_maxcontig. To conserve space, a maximum summary size
|
||||
* is set by FS_MAXCONTIG.
|
||||
*/
|
||||
#define FS_MAXCONTIG 16
|
||||
|
||||
/*
|
||||
* The maximum number of snapshot nodes that can be associated
|
||||
* with each filesystem. This limit affects only the number of
|
||||
* snapshot files that can be recorded within the superblock so
|
||||
* that they can be found when the filesystem is mounted. However,
|
||||
* maintaining too many will slow the filesystem performance, so
|
||||
* having this limit is a good idea.
|
||||
*/
|
||||
#define FSMAXSNAP 20
|
||||
|
||||
/*
|
||||
* Used to identify special blocks in snapshots:
|
||||
*
|
||||
* BLK_NOCOPY - A block that was unallocated at the time the snapshot
|
||||
* was taken, hence does not need to be copied when written.
|
||||
* BLK_SNAP - A block held by another snapshot that is not needed by this
|
||||
* snapshot. When the other snapshot is freed, the BLK_SNAP entries
|
||||
* are converted to BLK_NOCOPY. These are needed to allow fsck to
|
||||
* identify blocks that are in use by other snapshots (which are
|
||||
* expunged from this snapshot).
|
||||
*/
|
||||
#define BLK_NOCOPY ((daddr_t)(1))
|
||||
#define BLK_SNAP ((daddr_t)(2))
|
||||
|
||||
/*
|
||||
* MINFREE gives the minimum acceptable percentage of file system
|
||||
* blocks which may be free. If the freelist drops below this level
|
||||
* only the superuser may continue to allocate blocks. This may
|
||||
* be set to 0 if no reserve of free blocks is deemed necessary,
|
||||
* however throughput drops by fifty percent if the file system
|
||||
* is run at between 95% and 100% full; thus the minimum default
|
||||
* value of fs_minfree is 5%. However, to get good clustering
|
||||
* performance, 10% is a better choice. This value is used only
|
||||
* when creating a file system and can be overriden from the
|
||||
* command line. By default we choose to optimize for time.
|
||||
*/
|
||||
#define MINFREE 5
|
||||
#define DEFAULTOPT FS_OPTTIME
|
||||
|
||||
/*
|
||||
* Grigoriy Orlov <gluk@ptci.ru> has done some extensive work to fine
|
||||
* tune the layout preferences for directories within a filesystem.
|
||||
* His algorithm can be tuned by adjusting the following parameters
|
||||
* which tell the system the average file size and the average number
|
||||
* of files per directory. These defaults are well selected for typical
|
||||
* filesystems, but may need to be tuned for odd cases like filesystems
|
||||
* being used for squid caches or news spools.
|
||||
*/
|
||||
#define AVFILESIZ 16384 /* expected average file size */
|
||||
#define AFPDIR 64 /* expected number of files per directory */
|
||||
|
||||
/*
|
||||
* Per cylinder group information; summarized in blocks allocated
|
||||
* from first cylinder group data blocks. These blocks have to be
|
||||
* read in from fs_csaddr (size fs_cssize) in addition to the
|
||||
* super block.
|
||||
*/
|
||||
struct csum {
|
||||
int32_t cs_ndir; /* number of directories */
|
||||
int32_t cs_nbfree; /* number of free blocks */
|
||||
int32_t cs_nifree; /* number of free inodes */
|
||||
int32_t cs_nffree; /* number of free frags */
|
||||
};
|
||||
|
||||
struct csum_total {
|
||||
int64_t cs_ndir; /* number of directories */
|
||||
int64_t cs_nbfree; /* number of free blocks */
|
||||
int64_t cs_nifree; /* number of free inodes */
|
||||
int64_t cs_nffree; /* number of free frags */
|
||||
int64_t cs_spare[4]; /* future expansion */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Super block for an FFS file system in memory.
|
||||
*/
|
||||
struct fs {
|
||||
int32_t fs_firstfield; /* historic file system linked list, */
|
||||
int32_t fs_unused_1; /* used for incore super blocks */
|
||||
int32_t fs_sblkno; /* addr of super-block in filesys */
|
||||
int32_t fs_cblkno; /* offset of cyl-block in filesys */
|
||||
int32_t fs_iblkno; /* offset of inode-blocks in filesys */
|
||||
int32_t fs_dblkno; /* offset of first data after cg */
|
||||
int32_t fs_old_cgoffset; /* cylinder group offset in cylinder */
|
||||
int32_t fs_old_cgmask; /* used to calc mod fs_ntrak */
|
||||
int32_t fs_old_time; /* last time written */
|
||||
int32_t fs_old_size; /* number of blocks in fs */
|
||||
int32_t fs_old_dsize; /* number of data blocks in fs */
|
||||
int32_t fs_ncg; /* number of cylinder groups */
|
||||
int32_t fs_bsize; /* size of basic blocks in fs */
|
||||
int32_t fs_fsize; /* size of frag blocks in fs */
|
||||
int32_t fs_frag; /* number of frags in a block in fs */
|
||||
/* these are configuration parameters */
|
||||
int32_t fs_minfree; /* minimum percentage of free blocks */
|
||||
int32_t fs_old_rotdelay; /* num of ms for optimal next block */
|
||||
int32_t fs_old_rps; /* disk revolutions per second */
|
||||
/* these fields can be computed from the others */
|
||||
int32_t fs_bmask; /* ``blkoff'' calc of blk offsets */
|
||||
int32_t fs_fmask; /* ``fragoff'' calc of frag offsets */
|
||||
int32_t fs_bshift; /* ``lblkno'' calc of logical blkno */
|
||||
int32_t fs_fshift; /* ``numfrags'' calc number of frags */
|
||||
/* these are configuration parameters */
|
||||
int32_t fs_maxcontig; /* max number of contiguous blks */
|
||||
int32_t fs_maxbpg; /* max number of blks per cyl group */
|
||||
/* these fields can be computed from the others */
|
||||
int32_t fs_fragshift; /* block to frag shift */
|
||||
int32_t fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */
|
||||
int32_t fs_sbsize; /* actual size of super block */
|
||||
int32_t fs_spare1[2]; /* old fs_csmask */
|
||||
/* old fs_csshift */
|
||||
int32_t fs_nindir; /* value of NINDIR */
|
||||
int32_t fs_inopb; /* value of INOPB */
|
||||
int32_t fs_old_nspf; /* value of NSPF */
|
||||
/* yet another configuration parameter */
|
||||
int32_t fs_optim; /* optimization preference, see below */
|
||||
/* these fields are derived from the hardware */
|
||||
int32_t fs_old_npsect; /* # sectors/track including spares */
|
||||
int32_t fs_old_interleave; /* hardware sector interleave */
|
||||
int32_t fs_old_trackskew; /* sector 0 skew, per track */
|
||||
/* fs_id takes the space of the unused fs_headswitch and fs_trkseek fields */
|
||||
int32_t fs_id[2]; /* unique file system id */
|
||||
/* sizes determined by number of cylinder groups and their sizes */
|
||||
int32_t fs_old_csaddr; /* blk addr of cyl grp summary area */
|
||||
int32_t fs_cssize; /* size of cyl grp summary area */
|
||||
int32_t fs_cgsize; /* cylinder group size */
|
||||
/* these fields are derived from the hardware */
|
||||
int32_t fs_spare2; /* old fs_ntrak */
|
||||
int32_t fs_old_nsect; /* sectors per track */
|
||||
int32_t fs_old_spc; /* sectors per cylinder */
|
||||
int32_t fs_old_ncyl; /* cylinders in file system */
|
||||
int32_t fs_old_cpg; /* cylinders per group */
|
||||
int32_t fs_ipg; /* inodes per group */
|
||||
int32_t fs_fpg; /* blocks per group * fs_frag */
|
||||
/* this data must be re-computed after crashes */
|
||||
struct csum fs_old_cstotal; /* cylinder summary information */
|
||||
/* these fields are cleared at mount time */
|
||||
int8_t fs_fmod; /* super block modified flag */
|
||||
uint8_t fs_clean; /* file system is clean flag */
|
||||
int8_t fs_ronly; /* mounted read-only flag */
|
||||
uint8_t fs_old_flags; /* see FS_ flags below */
|
||||
u_char fs_fsmnt[MAXMNTLEN]; /* name mounted on */
|
||||
u_char fs_volname[MAXVOLLEN]; /* volume name */
|
||||
uint64_t fs_swuid; /* system-wide uid */
|
||||
int32_t fs_pad;
|
||||
/* these fields retain the current block allocation info */
|
||||
int32_t fs_cgrotor; /* last cg searched (UNUSED) */
|
||||
void *fs_ocsp[NOCSPTRS]; /* padding; was list of fs_cs buffers */
|
||||
u_int8_t *fs_contigdirs; /* # of contiguously allocated dirs */
|
||||
struct csum *fs_csp; /* cg summary info buffer for fs_cs */
|
||||
int32_t *fs_maxcluster; /* max cluster in each cyl group */
|
||||
u_char *fs_active; /* used by snapshots to track fs */
|
||||
int32_t fs_old_cpc; /* cyl per cycle in postbl */
|
||||
/* this area is otherwise allocated unless fs_old_flags & FS_FLAGS_UPDATED */
|
||||
int32_t fs_maxbsize; /* maximum blocking factor permitted */
|
||||
uint8_t fs_journal_version; /* journal format version */
|
||||
uint8_t fs_journal_location; /* journal location type */
|
||||
uint8_t fs_journal_reserved[2];/* reserved for future use */
|
||||
uint32_t fs_journal_flags; /* journal flags */
|
||||
uint64_t fs_journallocs[4]; /* location info for journal */
|
||||
uint32_t fs_quota_magic; /* see quota2.h */
|
||||
uint8_t fs_quota_flags; /* see quota2.h */
|
||||
uint8_t fs_quota_reserved[3];
|
||||
uint64_t fs_quotafile[2]; /* pointer to quota inodes */
|
||||
int64_t fs_sparecon64[9]; /* reserved for future use */
|
||||
int64_t fs_sblockloc; /* byte offset of standard superblock */
|
||||
struct csum_total fs_cstotal; /* cylinder summary information */
|
||||
int64_t fs_time; /* last time written */
|
||||
int64_t fs_size; /* number of blocks in fs */
|
||||
int64_t fs_dsize; /* number of data blocks in fs */
|
||||
int64_t fs_csaddr; /* blk addr of cyl grp summary area */
|
||||
int64_t fs_pendingblocks; /* blocks in process of being freed */
|
||||
int32_t fs_pendinginodes; /* inodes in process of being freed */
|
||||
int32_t fs_snapinum[FSMAXSNAP];/* list of snapshot inode numbers */
|
||||
/* back to stuff that has been around a while */
|
||||
int32_t fs_avgfilesize; /* expected average file size */
|
||||
int32_t fs_avgfpdir; /* expected # of files per directory */
|
||||
int32_t fs_save_cgsize; /* save real cg size to use fs_bsize */
|
||||
int32_t fs_sparecon32[26]; /* reserved for future constants */
|
||||
uint32_t fs_flags; /* see FS_ flags below */
|
||||
/* back to stuff that has been around a while (again) */
|
||||
int32_t fs_contigsumsize; /* size of cluster summary array */
|
||||
int32_t fs_maxsymlinklen; /* max length of an internal symlink */
|
||||
int32_t fs_old_inodefmt; /* format of on-disk inodes */
|
||||
u_int64_t fs_maxfilesize; /* maximum representable file size */
|
||||
int64_t fs_qbmask; /* ~fs_bmask for use with 64-bit size */
|
||||
int64_t fs_qfmask; /* ~fs_fmask for use with 64-bit size */
|
||||
int32_t fs_state; /* validate fs_clean field (UNUSED) */
|
||||
int32_t fs_old_postblformat; /* format of positional layout tables */
|
||||
int32_t fs_old_nrpos; /* number of rotational positions */
|
||||
int32_t fs_spare5[2]; /* old fs_postbloff */
|
||||
/* old fs_rotbloff */
|
||||
int32_t fs_magic; /* magic number */
|
||||
};
|
||||
|
||||
#define fs_old_postbloff fs_spare5[0]
|
||||
#define fs_old_rotbloff fs_spare5[1]
|
||||
#define fs_old_postbl_start fs_maxbsize
|
||||
#define fs_old_headswitch fs_id[0]
|
||||
#define fs_old_trkseek fs_id[1]
|
||||
#define fs_old_csmask fs_spare1[0]
|
||||
#define fs_old_csshift fs_spare1[1]
|
||||
|
||||
#define FS_42POSTBLFMT -1 /* 4.2BSD rotational table format */
|
||||
#define FS_DYNAMICPOSTBLFMT 1 /* dynamic rotational table format */
|
||||
|
||||
#define old_fs_postbl(fs_, cylno, opostblsave) \
|
||||
((((fs_)->fs_old_postblformat == FS_42POSTBLFMT) || \
|
||||
((fs_)->fs_old_postbloff == offsetof(struct fs, fs_old_postbl_start))) \
|
||||
? ((int16_t *)(opostblsave) + (cylno) * (fs_)->fs_old_nrpos) \
|
||||
: ((int16_t *)((uint8_t *)(fs_) + \
|
||||
(fs_)->fs_old_postbloff) + (cylno) * (fs_)->fs_old_nrpos))
|
||||
#define old_fs_rotbl(fs) \
|
||||
(((fs)->fs_old_postblformat == FS_42POSTBLFMT) \
|
||||
? ((uint8_t *)(&(fs)->fs_magic+1)) \
|
||||
: ((uint8_t *)((uint8_t *)(fs) + (fs)->fs_old_rotbloff)))
|
||||
|
||||
/*
|
||||
* File system identification
|
||||
*/
|
||||
#define FS_UFS1_MAGIC 0x011954 /* UFS1 fast file system magic number */
|
||||
#define FS_UFS2_MAGIC 0x19540119 /* UFS2 fast file system magic number */
|
||||
#define FS_UFS1_MAGIC_SWAPPED 0x54190100
|
||||
#define FS_UFS2_MAGIC_SWAPPED 0x19015419
|
||||
#define FS_OKAY 0x7c269d38 /* superblock checksum */
|
||||
#define FS_42INODEFMT -1 /* 4.2BSD inode format */
|
||||
#define FS_44INODEFMT 2 /* 4.4BSD inode format */
|
||||
|
||||
/*
|
||||
* File system clean flags
|
||||
*/
|
||||
#define FS_ISCLEAN 0x01
|
||||
#define FS_WASCLEAN 0x02
|
||||
|
||||
/*
|
||||
* Preference for optimization.
|
||||
*/
|
||||
#define FS_OPTTIME 0 /* minimize allocation time */
|
||||
#define FS_OPTSPACE 1 /* minimize disk fragmentation */
|
||||
|
||||
/*
|
||||
* File system flags
|
||||
*/
|
||||
#define FS_UNCLEAN 0x001 /* file system not clean at mount (unused) */
|
||||
#define FS_DOSOFTDEP 0x002 /* file system using soft dependencies */
|
||||
#define FS_NEEDSFSCK 0x004 /* needs sync fsck (FreeBSD compat, unused) */
|
||||
#define FS_INDEXDIRS 0x008 /* kernel supports indexed directories */
|
||||
#define FS_ACLS 0x010 /* file system has ACLs enabled */
|
||||
#define FS_MULTILABEL 0x020 /* file system is MAC multi-label */
|
||||
#define FS_GJOURNAL 0x40 /* gjournaled file system */
|
||||
#define FS_FLAGS_UPDATED 0x80 /* flags have been moved to new location */
|
||||
#define FS_DOWAPBL 0x100 /* Write ahead physical block logging */
|
||||
#define FS_DOQUOTA2 0x200 /* in-filesystem quotas */
|
||||
|
||||
/* File system flags that are ok for NetBSD if set in fs_flags */
|
||||
#define FS_KNOWN_FLAGS (FS_DOSOFTDEP | FS_DOWAPBL | FS_DOQUOTA2)
|
||||
|
||||
/*
|
||||
* File system internal flags, also in fs_flags.
|
||||
* (Pick highest number to avoid conflicts with others)
|
||||
*/
|
||||
#define FS_SWAPPED 0x80000000 /* file system is endian swapped */
|
||||
#define FS_INTERNAL 0x80000000 /* mask for internal flags */
|
||||
|
||||
/*
|
||||
* Macros to access bits in the fs_active array.
|
||||
*/
|
||||
#define ACTIVECG_SET(fs, cg) \
|
||||
do { \
|
||||
if ((fs)->fs_active != NULL) \
|
||||
setbit((fs)->fs_active, (cg)); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
#define ACTIVECG_CLR(fs, cg) \
|
||||
do { \
|
||||
if ((fs)->fs_active != NULL) \
|
||||
clrbit((fs)->fs_active, (cg)); \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
#define ACTIVECG_ISSET(fs, cg) \
|
||||
((fs)->fs_active != NULL && isset((fs)->fs_active, (cg)))
|
||||
|
||||
/*
|
||||
* The size of a cylinder group is calculated by CGSIZE. The maximum size
|
||||
* is limited by the fact that cylinder groups are at most one block.
|
||||
* Its size is derived from the size of the maps maintained in the
|
||||
* cylinder group and the (struct cg) size.
|
||||
*/
|
||||
#define CGSIZE_IF(fs, ipg, fpg) \
|
||||
/* base cg */ (sizeof(struct cg) + sizeof(int32_t) + \
|
||||
/* old btotoff */ (fs)->fs_old_cpg * sizeof(int32_t) + \
|
||||
/* old boff */ (fs)->fs_old_cpg * sizeof(u_int16_t) + \
|
||||
/* inode map */ howmany((ipg), NBBY) + \
|
||||
/* block map */ howmany((fpg), NBBY) +\
|
||||
/* if present */ ((fs)->fs_contigsumsize <= 0 ? 0 : \
|
||||
/* cluster sum */ (fs)->fs_contigsumsize * sizeof(int32_t) + \
|
||||
/* cluster map */ howmany(fragstoblks(fs, (fpg)), NBBY)))
|
||||
|
||||
#define CGSIZE(fs) CGSIZE_IF((fs), (fs)->fs_ipg, (fs)->fs_fpg)
|
||||
|
||||
/*
|
||||
* The minimal number of cylinder groups that should be created.
|
||||
*/
|
||||
#define MINCYLGRPS 4
|
||||
|
||||
|
||||
/*
|
||||
* Convert cylinder group to base address of its global summary info.
|
||||
*/
|
||||
#define fs_cs(fs, indx) fs_csp[indx]
|
||||
|
||||
/*
|
||||
* Cylinder group block for a file system.
|
||||
*/
|
||||
#define CG_MAGIC 0x090255
|
||||
struct cg {
|
||||
int32_t cg_firstfield; /* historic cyl groups linked list */
|
||||
int32_t cg_magic; /* magic number */
|
||||
int32_t cg_old_time; /* time last written */
|
||||
int32_t cg_cgx; /* we are the cgx'th cylinder group */
|
||||
int16_t cg_old_ncyl; /* number of cyl's this cg */
|
||||
int16_t cg_old_niblk; /* number of inode blocks this cg */
|
||||
int32_t cg_ndblk; /* number of data blocks this cg */
|
||||
struct csum cg_cs; /* cylinder summary information */
|
||||
int32_t cg_rotor; /* position of last used block */
|
||||
int32_t cg_frotor; /* position of last used frag */
|
||||
int32_t cg_irotor; /* position of last used inode */
|
||||
int32_t cg_frsum[MAXFRAG]; /* counts of available frags */
|
||||
int32_t cg_old_btotoff; /* (int32) block totals per cylinder */
|
||||
int32_t cg_old_boff; /* (u_int16) free block positions */
|
||||
int32_t cg_iusedoff; /* (u_int8) used inode map */
|
||||
int32_t cg_freeoff; /* (u_int8) free block map */
|
||||
int32_t cg_nextfreeoff; /* (u_int8) next available space */
|
||||
int32_t cg_clustersumoff; /* (u_int32) counts of avail clusters */
|
||||
int32_t cg_clusteroff; /* (u_int8) free cluster map */
|
||||
int32_t cg_nclusterblks; /* number of clusters this cg */
|
||||
int32_t cg_niblk; /* number of inode blocks this cg */
|
||||
int32_t cg_initediblk; /* last initialized inode */
|
||||
int32_t cg_sparecon32[3]; /* reserved for future use */
|
||||
int64_t cg_time; /* time last written */
|
||||
int64_t cg_sparecon64[3]; /* reserved for future use */
|
||||
u_int8_t cg_space[1]; /* space for cylinder group maps */
|
||||
/* actually longer */
|
||||
};
|
||||
|
||||
/*
|
||||
* The following structure is defined
|
||||
* for compatibility with old file systems.
|
||||
*/
|
||||
struct ocg {
|
||||
int32_t cg_firstfield; /* historic linked list of cyl groups */
|
||||
int32_t cg_unused_1; /* used for incore cyl groups */
|
||||
int32_t cg_time; /* time last written */
|
||||
int32_t cg_cgx; /* we are the cgx'th cylinder group */
|
||||
int16_t cg_ncyl; /* number of cyl's this cg */
|
||||
int16_t cg_niblk; /* number of inode blocks this cg */
|
||||
int32_t cg_ndblk; /* number of data blocks this cg */
|
||||
struct csum cg_cs; /* cylinder summary information */
|
||||
int32_t cg_rotor; /* position of last used block */
|
||||
int32_t cg_frotor; /* position of last used frag */
|
||||
int32_t cg_irotor; /* position of last used inode */
|
||||
int32_t cg_frsum[8]; /* counts of available frags */
|
||||
int32_t cg_btot[32]; /* block totals per cylinder */
|
||||
int16_t cg_b[32][8]; /* positions of free blocks */
|
||||
u_int8_t cg_iused[256]; /* used inode map */
|
||||
int32_t cg_magic; /* magic number */
|
||||
u_int8_t cg_free[1]; /* free block map */
|
||||
/* actually longer */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Macros for access to cylinder group array structures.
|
||||
*/
|
||||
#define old_cg_blktot_old(cgp, ns) \
|
||||
(((struct ocg *)(cgp))->cg_btot)
|
||||
#define old_cg_blks_old(fs, cgp, cylno, ns) \
|
||||
(((struct ocg *)(cgp))->cg_b[cylno])
|
||||
|
||||
#define old_cg_blktot_new(cgp, ns) \
|
||||
((int32_t *)((u_int8_t *)(cgp) + \
|
||||
ufs_rw32((cgp)->cg_old_btotoff, (ns))))
|
||||
#define old_cg_blks_new(fs, cgp, cylno, ns) \
|
||||
((int16_t *)((u_int8_t *)(cgp) + \
|
||||
ufs_rw32((cgp)->cg_old_boff, (ns))) + (cylno) * (fs)->fs_old_nrpos)
|
||||
|
||||
#define old_cg_blktot(cgp, ns) \
|
||||
((ufs_rw32((cgp)->cg_magic, (ns)) != CG_MAGIC) ? \
|
||||
old_cg_blktot_old(cgp, ns) : old_cg_blktot_new(cgp, ns))
|
||||
#define old_cg_blks(fs, cgp, cylno, ns) \
|
||||
((ufs_rw32((cgp)->cg_magic, (ns)) != CG_MAGIC) ? \
|
||||
old_cg_blks_old(fs, cgp, cylno, ns) : old_cg_blks_new(fs, cgp, cylno, ns))
|
||||
|
||||
#define cg_inosused_new(cgp, ns) \
|
||||
((u_int8_t *)((u_int8_t *)(cgp) + \
|
||||
ufs_rw32((cgp)->cg_iusedoff, (ns))))
|
||||
#define cg_blksfree_new(cgp, ns) \
|
||||
((u_int8_t *)((u_int8_t *)(cgp) + \
|
||||
ufs_rw32((cgp)->cg_freeoff, (ns))))
|
||||
#define cg_chkmagic_new(cgp, ns) \
|
||||
(ufs_rw32((cgp)->cg_magic, (ns)) == CG_MAGIC)
|
||||
|
||||
#define cg_inosused_old(cgp, ns) \
|
||||
(((struct ocg *)(cgp))->cg_iused)
|
||||
#define cg_blksfree_old(cgp, ns) \
|
||||
(((struct ocg *)(cgp))->cg_free)
|
||||
#define cg_chkmagic_old(cgp, ns) \
|
||||
(ufs_rw32(((struct ocg *)(cgp))->cg_magic, (ns)) == CG_MAGIC)
|
||||
|
||||
#define cg_inosused(cgp, ns) \
|
||||
((ufs_rw32((cgp)->cg_magic, (ns)) != CG_MAGIC) ? \
|
||||
cg_inosused_old(cgp, ns) : cg_inosused_new(cgp, ns))
|
||||
#define cg_blksfree(cgp, ns) \
|
||||
((ufs_rw32((cgp)->cg_magic, (ns)) != CG_MAGIC) ? \
|
||||
cg_blksfree_old(cgp, ns) : cg_blksfree_new(cgp, ns))
|
||||
#define cg_chkmagic(cgp, ns) \
|
||||
(cg_chkmagic_new(cgp, ns) || cg_chkmagic_old(cgp, ns))
|
||||
|
||||
#define cg_clustersfree(cgp, ns) \
|
||||
((u_int8_t *)((u_int8_t *)(cgp) + \
|
||||
ufs_rw32((cgp)->cg_clusteroff, (ns))))
|
||||
#define cg_clustersum(cgp, ns) \
|
||||
((int32_t *)((u_int8_t *)(cgp) + \
|
||||
ufs_rw32((cgp)->cg_clustersumoff, (ns))))
|
||||
|
||||
|
||||
/*
|
||||
* Turn file system block numbers into disk block addresses.
|
||||
* This maps file system blocks to device size blocks.
|
||||
*/
|
||||
#if defined (_KERNEL)
|
||||
#define fsbtodb(fs, b) ((b) << ((fs)->fs_fshift - DEV_BSHIFT))
|
||||
#define dbtofsb(fs, b) ((b) >> ((fs)->fs_fshift - DEV_BSHIFT))
|
||||
#else
|
||||
#define fsbtodb(fs, b) ((b) << (fs)->fs_fsbtodb)
|
||||
#define dbtofsb(fs, b) ((b) >> (fs)->fs_fsbtodb)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Cylinder group macros to locate things in cylinder groups.
|
||||
* They calc file system addresses of cylinder group data structures.
|
||||
*/
|
||||
#define cgbase(fs, c) (((daddr_t)(fs)->fs_fpg) * (c))
|
||||
#define cgstart_ufs1(fs, c) \
|
||||
(cgbase(fs, c) + (fs)->fs_old_cgoffset * ((c) & ~((fs)->fs_old_cgmask)))
|
||||
#define cgstart_ufs2(fs, c) cgbase((fs), (c))
|
||||
#define cgstart(fs, c) ((fs)->fs_magic == FS_UFS2_MAGIC \
|
||||
? cgstart_ufs2((fs), (c)) : cgstart_ufs1((fs), (c)))
|
||||
#define cgdmin(fs, c) (cgstart(fs, c) + (fs)->fs_dblkno) /* 1st data */
|
||||
#define cgimin(fs, c) (cgstart(fs, c) + (fs)->fs_iblkno) /* inode blk */
|
||||
#define cgsblock(fs, c) (cgstart(fs, c) + (fs)->fs_sblkno) /* super blk */
|
||||
#define cgtod(fs, c) (cgstart(fs, c) + (fs)->fs_cblkno) /* cg block */
|
||||
|
||||
/*
|
||||
* Macros for handling inode numbers:
|
||||
* inode number to file system block offset.
|
||||
* inode number to cylinder group number.
|
||||
* inode number to file system block address.
|
||||
*/
|
||||
#define ino_to_cg(fs, x) ((x) / (fs)->fs_ipg)
|
||||
#define ino_to_fsba(fs, x) \
|
||||
((daddr_t)(cgimin(fs, ino_to_cg(fs, x)) + \
|
||||
(blkstofrags((fs), (((x) % (fs)->fs_ipg) / INOPB(fs))))))
|
||||
#define ino_to_fsbo(fs, x) ((x) % INOPB(fs))
|
||||
|
||||
/*
|
||||
* Give cylinder group number for a file system block.
|
||||
* Give cylinder group block number for a file system block.
|
||||
*/
|
||||
#define dtog(fs, d) ((d) / (fs)->fs_fpg)
|
||||
#define dtogd(fs, d) ((d) % (fs)->fs_fpg)
|
||||
|
||||
/*
|
||||
* Extract the bits for a block from a map.
|
||||
* Compute the cylinder and rotational position of a cyl block addr.
|
||||
*/
|
||||
#define blkmap(fs, map, loc) \
|
||||
(((map)[(loc) / NBBY] >> ((loc) % NBBY)) & (0xff >> (NBBY - (fs)->fs_frag)))
|
||||
#define old_cbtocylno(fs, bno) \
|
||||
(fsbtodb(fs, bno) / (fs)->fs_old_spc)
|
||||
#define old_cbtorpos(fs, bno) \
|
||||
((fs)->fs_old_nrpos <= 1 ? 0 : \
|
||||
(fsbtodb(fs, bno) % (fs)->fs_old_spc / (fs)->fs_old_nsect * (fs)->fs_old_trackskew + \
|
||||
fsbtodb(fs, bno) % (fs)->fs_old_spc % (fs)->fs_old_nsect * (fs)->fs_old_interleave) % \
|
||||
(fs)->fs_old_nsect * (fs)->fs_old_nrpos / (fs)->fs_old_npsect)
|
||||
|
||||
/*
|
||||
* The following macros optimize certain frequently calculated
|
||||
* quantities by using shifts and masks in place of divisions
|
||||
* modulos and multiplications.
|
||||
*/
|
||||
#define blkoff(fs, loc) /* calculates (loc % fs->fs_bsize) */ \
|
||||
((loc) & (fs)->fs_qbmask)
|
||||
#define fragoff(fs, loc) /* calculates (loc % fs->fs_fsize) */ \
|
||||
((loc) & (fs)->fs_qfmask)
|
||||
#define lfragtosize(fs, frag) /* calculates ((off_t)frag * fs->fs_fsize) */ \
|
||||
(((off_t)(frag)) << (fs)->fs_fshift)
|
||||
#define lblktosize(fs, blk) /* calculates ((off_t)blk * fs->fs_bsize) */ \
|
||||
(((off_t)(blk)) << (fs)->fs_bshift)
|
||||
#define lblkno(fs, loc) /* calculates (loc / fs->fs_bsize) */ \
|
||||
((loc) >> (fs)->fs_bshift)
|
||||
#define numfrags(fs, loc) /* calculates (loc / fs->fs_fsize) */ \
|
||||
((loc) >> (fs)->fs_fshift)
|
||||
#define blkroundup(fs, size) /* calculates roundup(size, fs->fs_bsize) */ \
|
||||
(((size) + (fs)->fs_qbmask) & (fs)->fs_bmask)
|
||||
#define fragroundup(fs, size) /* calculates roundup(size, fs->fs_fsize) */ \
|
||||
(((size) + (fs)->fs_qfmask) & (fs)->fs_fmask)
|
||||
#define fragstoblks(fs, frags) /* calculates (frags / fs->fs_frag) */ \
|
||||
((frags) >> (fs)->fs_fragshift)
|
||||
#define blkstofrags(fs, blks) /* calculates (blks * fs->fs_frag) */ \
|
||||
((blks) << (fs)->fs_fragshift)
|
||||
#define fragnum(fs, fsb) /* calculates (fsb % fs->fs_frag) */ \
|
||||
((fsb) & ((fs)->fs_frag - 1))
|
||||
#define blknum(fs, fsb) /* calculates rounddown(fsb, fs->fs_frag) */ \
|
||||
((fsb) &~ ((fs)->fs_frag - 1))
|
||||
|
||||
/*
|
||||
* Determine the number of available frags given a
|
||||
* percentage to hold in reserve.
|
||||
*/
|
||||
#define freespace(fs, percentreserved) \
|
||||
(blkstofrags((fs), (fs)->fs_cstotal.cs_nbfree) + \
|
||||
(fs)->fs_cstotal.cs_nffree - \
|
||||
(((off_t)((fs)->fs_dsize)) * (percentreserved) / 100))
|
||||
|
||||
/*
|
||||
* Determining the size of a file block in the file system.
|
||||
*/
|
||||
#define blksize(fs, ip, lbn) \
|
||||
(((lbn) >= NDADDR || (ip)->i_size >= lblktosize(fs, (lbn) + 1)) \
|
||||
? (fs)->fs_bsize \
|
||||
: (fragroundup(fs, blkoff(fs, (ip)->i_size))))
|
||||
|
||||
#define sblksize(fs, size, lbn) \
|
||||
(((lbn) >= NDADDR || (size) >= ((lbn) + 1) << (fs)->fs_bshift) \
|
||||
? (fs)->fs_bsize \
|
||||
: (fragroundup(fs, blkoff(fs, (size)))))
|
||||
|
||||
|
||||
/*
|
||||
* Number of inodes in a secondary storage block/fragment.
|
||||
*/
|
||||
#define INOPB(fs) ((fs)->fs_inopb)
|
||||
#define INOPF(fs) ((fs)->fs_inopb >> (fs)->fs_fragshift)
|
||||
|
||||
/*
|
||||
* Number of indirects in a file system block.
|
||||
*/
|
||||
#define NINDIR(fs) ((fs)->fs_nindir)
|
||||
|
||||
/*
|
||||
* Apple UFS Label:
|
||||
* We check for this to decide to use APPLEUFS_DIRBLKSIZ
|
||||
*/
|
||||
#define APPLEUFS_LABEL_MAGIC 0x4c41424c /* LABL */
|
||||
#define APPLEUFS_LABEL_SIZE 1024
|
||||
#define APPLEUFS_LABEL_OFFSET (BBSIZE - APPLEUFS_LABEL_SIZE) /* located at 7k */
|
||||
#define APPLEUFS_LABEL_VERSION 1
|
||||
#define APPLEUFS_MAX_LABEL_NAME 512
|
||||
|
||||
struct appleufslabel {
|
||||
u_int32_t ul_magic;
|
||||
u_int16_t ul_checksum;
|
||||
u_int16_t ul_unused0;
|
||||
u_int32_t ul_version;
|
||||
u_int32_t ul_time;
|
||||
u_int16_t ul_namelen;
|
||||
u_char ul_name[APPLEUFS_MAX_LABEL_NAME]; /* Warning: may not be null terminated */
|
||||
u_int16_t ul_unused1;
|
||||
u_int64_t ul_uuid; /* Note this is only 4 byte aligned */
|
||||
u_char ul_reserved[24];
|
||||
u_char ul_unused[460];
|
||||
} __packed;
|
||||
|
||||
|
||||
#endif /* !_UFS_FFS_FS_H_ */
|
1156
nbsd_include/ufs/lfs/lfs.h
Normal file
1156
nbsd_include/ufs/lfs/lfs.h
Normal file
File diff suppressed because it is too large
Load diff
287
nbsd_include/ufs/lfs/lfs_extern.h
Normal file
287
nbsd_include/ufs/lfs/lfs_extern.h
Normal file
|
@ -0,0 +1,287 @@
|
|||
/* $NetBSD: lfs_extern.h,v 1.96 2008/06/28 01:34:05 rumble Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Konrad E. Schroder <perseant@hhhh.org>.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)lfs_extern.h 8.6 (Berkeley) 5/8/95
|
||||
*/
|
||||
|
||||
#ifndef _UFS_LFS_LFS_EXTERN_H_
|
||||
#define _UFS_LFS_LFS_EXTERN_H_
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <sys/mallocvar.h>
|
||||
|
||||
MALLOC_DECLARE(M_SEGMENT);
|
||||
#endif
|
||||
|
||||
/* Copied from ext2fs for ITIMES. XXX This is a bogus use of v_tag. */
|
||||
#define IS_LFS_VNODE(vp) (vp->v_tag == VT_LFS)
|
||||
|
||||
/*
|
||||
* Sysctl values for LFS.
|
||||
*/
|
||||
#define LFS_WRITEINDIR 1 /* flush indirect blocks on non-checkpoint writes */
|
||||
#define LFS_CLEAN_VNHEAD 2 /* put prev unrefed cleaned vnodes on head of free list */
|
||||
#define LFS_DOSTATS 3
|
||||
#define LFS_MAXPAGES 4
|
||||
#define LFS_FS_PAGETRIP 5
|
||||
#define LFS_STATS 6
|
||||
#define LFS_DO_RFW 7
|
||||
#define LFS_DEBUGLOG 8
|
||||
#define LFS_IGNORE_LAZY_SYNC 9
|
||||
#define LFS_MAXID 10
|
||||
|
||||
struct fid;
|
||||
struct mount;
|
||||
struct nameidata;
|
||||
struct proc;
|
||||
struct statvfs;
|
||||
struct timeval;
|
||||
struct inode;
|
||||
struct uio;
|
||||
struct mbuf;
|
||||
struct ufs1_dinode;
|
||||
struct buf;
|
||||
struct vnode;
|
||||
struct dlfs;
|
||||
struct lfs;
|
||||
struct segment;
|
||||
struct block_info;
|
||||
|
||||
#if defined(_KERNEL)
|
||||
|
||||
extern int lfs_allclean_wakeup;
|
||||
extern struct pool lfs_inode_pool; /* memory pool for inodes */
|
||||
extern struct pool lfs_dinode_pool; /* memory pool for dinodes */
|
||||
extern struct pool lfs_inoext_pool; /* memory pool for inode extension */
|
||||
extern struct pool lfs_lbnentry_pool; /* memory pool for balloc accounting */
|
||||
|
||||
extern int locked_queue_count;
|
||||
extern long locked_queue_bytes;
|
||||
extern int lfs_subsys_pages;
|
||||
extern int lfs_dirvcount;
|
||||
extern kmutex_t lfs_lock;
|
||||
extern int lfs_debug_log_subsys[];
|
||||
extern kcondvar_t lfs_writing_cv;
|
||||
extern kcondvar_t locked_queue_cv;
|
||||
|
||||
__BEGIN_DECLS
|
||||
/* lfs_alloc.c */
|
||||
void lfs_vcreate(struct mount *, ino_t, struct vnode *);
|
||||
int lfs_valloc(struct vnode *, int, kauth_cred_t, struct vnode **);
|
||||
int lfs_vfree(struct vnode *, ino_t, int);
|
||||
void lfs_order_freelist(struct lfs *);
|
||||
int lfs_extend_ifile(struct lfs *, kauth_cred_t);
|
||||
int lfs_ialloc(struct lfs *, struct vnode *, ino_t, int, struct vnode **);
|
||||
void lfs_orphan(struct lfs *, ino_t);
|
||||
|
||||
/* lfs_balloc.c */
|
||||
int lfs_balloc(struct vnode *, off_t, int, kauth_cred_t, int, struct buf **);
|
||||
void lfs_register_block(struct vnode *, daddr_t);
|
||||
void lfs_deregister_block(struct vnode *, daddr_t);
|
||||
void lfs_deregister_all(struct vnode *);
|
||||
|
||||
/* lfs_bio.c */
|
||||
int lfs_availwait(struct lfs *, int);
|
||||
int lfs_bwrite_ext(struct buf *, int);
|
||||
int lfs_fits(struct lfs *, int);
|
||||
void lfs_flush_fs(struct lfs *, int);
|
||||
void lfs_flush(struct lfs *, int, int);
|
||||
int lfs_check(struct vnode *, daddr_t, int);
|
||||
void lfs_freebuf(struct lfs *, struct buf *);
|
||||
struct buf *lfs_newbuf(struct lfs *, struct vnode *, daddr_t, size_t, int);
|
||||
void lfs_countlocked(int *, long *, const char *);
|
||||
int lfs_reserve(struct lfs *, struct vnode *, struct vnode *, int);
|
||||
|
||||
/* lfs_debug.c */
|
||||
#ifdef DEBUG
|
||||
int lfs_bwrite_log(struct buf *, const char *, int);
|
||||
void lfs_dumplog(void);
|
||||
void lfs_dump_super(struct lfs *);
|
||||
void lfs_dump_dinode(struct ufs1_dinode *);
|
||||
void lfs_check_bpp(struct lfs *, struct segment *, char *, int);
|
||||
void lfs_check_segsum(struct lfs *, struct segment *, char *, int);
|
||||
void lfs_debug_log(int, const char *, ...);
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* lfs_inode.c */
|
||||
int lfs_update(struct vnode *, const struct timespec *, const struct timespec *,
|
||||
int);
|
||||
int lfs_truncate(struct vnode *, off_t, int, kauth_cred_t);
|
||||
struct ufs1_dinode *lfs_ifind(struct lfs *, ino_t, struct buf *);
|
||||
void lfs_finalize_ino_seguse(struct lfs *, struct inode *);
|
||||
void lfs_finalize_fs_seguse(struct lfs *);
|
||||
|
||||
/* lfs_rfw.c */
|
||||
int lfs_rf_valloc(struct lfs *, ino_t, int, struct lwp *, struct vnode **);
|
||||
void lfs_roll_forward(struct lfs *, struct mount *, struct lwp *);
|
||||
|
||||
/* lfs_segment.c */
|
||||
void lfs_imtime(struct lfs *);
|
||||
int lfs_vflush(struct vnode *);
|
||||
int lfs_segwrite(struct mount *, int);
|
||||
int lfs_writefile(struct lfs *, struct segment *, struct vnode *);
|
||||
int lfs_writeinode(struct lfs *, struct segment *, struct inode *);
|
||||
int lfs_gatherblock(struct segment *, struct buf *, kmutex_t *);
|
||||
int lfs_gather(struct lfs *, struct segment *, struct vnode *, int (*match )(struct lfs *, struct buf *));
|
||||
void lfs_update_single(struct lfs *, struct segment *, struct vnode *,
|
||||
daddr_t, int32_t, int);
|
||||
void lfs_updatemeta(struct segment *);
|
||||
int lfs_rewind(struct lfs *, int);
|
||||
void lfs_unset_inval_all(struct lfs *);
|
||||
int lfs_initseg(struct lfs *);
|
||||
int lfs_writeseg(struct lfs *, struct segment *);
|
||||
void lfs_writesuper(struct lfs *, daddr_t);
|
||||
int lfs_match_data(struct lfs *, struct buf *);
|
||||
int lfs_match_indir(struct lfs *, struct buf *);
|
||||
int lfs_match_dindir(struct lfs *, struct buf *);
|
||||
int lfs_match_tindir(struct lfs *, struct buf *);
|
||||
void lfs_callback(struct buf *);
|
||||
int lfs_vref(struct vnode *);
|
||||
void lfs_vunref(struct vnode *);
|
||||
void lfs_vunref_head(struct vnode *);
|
||||
void lfs_acquire_finfo(struct lfs *fs, ino_t, int);
|
||||
void lfs_release_finfo(struct lfs *fs);
|
||||
|
||||
/* lfs_subr.c */
|
||||
void lfs_setup_resblks(struct lfs *);
|
||||
void lfs_pad_check(unsigned char *, int, char *, int);
|
||||
void lfs_free_resblks(struct lfs *);
|
||||
void *lfs_malloc(struct lfs *, size_t, int);
|
||||
void lfs_free(struct lfs *, void *, int);
|
||||
int lfs_seglock(struct lfs *, unsigned long);
|
||||
void lfs_segunlock(struct lfs *);
|
||||
void lfs_segunlock_relock(struct lfs *);
|
||||
int lfs_writer_enter(struct lfs *, const char *);
|
||||
void lfs_writer_leave(struct lfs *);
|
||||
void lfs_wakeup_cleaner(struct lfs *);
|
||||
|
||||
/* lfs_syscalls.c */
|
||||
int lfs_fastvget(struct mount *, ino_t, daddr_t, struct vnode **, struct ufs1_dinode *);
|
||||
struct buf *lfs_fakebuf(struct lfs *, struct vnode *, int, size_t, void *);
|
||||
int lfs_do_segclean(struct lfs *, unsigned long);
|
||||
int lfs_segwait(fsid_t *, struct timeval *);
|
||||
int lfs_bmapv(struct proc *, fsid_t *, struct block_info *, int);
|
||||
int lfs_markv(struct proc *, fsid_t *, struct block_info *, int);
|
||||
|
||||
/* lfs_vfsops.c */
|
||||
void lfs_init(void);
|
||||
void lfs_reinit(void);
|
||||
void lfs_done(void);
|
||||
int lfs_mountroot(void);
|
||||
int lfs_mount(struct mount *, const char *, void *, size_t *);
|
||||
int lfs_unmount(struct mount *, int);
|
||||
int lfs_statvfs(struct mount *, struct statvfs *);
|
||||
int lfs_sync(struct mount *, int, kauth_cred_t);
|
||||
int lfs_vget(struct mount *, ino_t, struct vnode **);
|
||||
int lfs_fhtovp(struct mount *, struct fid *, struct vnode **);
|
||||
int lfs_vptofh(struct vnode *, struct fid *, size_t *);
|
||||
void lfs_vinit(struct mount *, struct vnode **);
|
||||
int lfs_resize_fs(struct lfs *, int);
|
||||
|
||||
/* lfs_vnops.c */
|
||||
void lfs_mark_vnode(struct vnode *);
|
||||
void lfs_unmark_vnode(struct vnode *);
|
||||
int lfs_gop_alloc(struct vnode *, off_t, off_t, int, kauth_cred_t);
|
||||
void lfs_gop_size(struct vnode *, off_t, off_t *, int);
|
||||
int lfs_putpages_ext(void *, int);
|
||||
int lfs_gatherpages(struct vnode *);
|
||||
void lfs_flush_dirops(struct lfs *);
|
||||
void lfs_flush_pchain(struct lfs *);
|
||||
|
||||
int lfs_bwrite (void *);
|
||||
int lfs_fsync (void *);
|
||||
int lfs_symlink (void *);
|
||||
int lfs_mknod (void *);
|
||||
int lfs_create (void *);
|
||||
int lfs_mkdir (void *);
|
||||
int lfs_read (void *);
|
||||
int lfs_remove (void *);
|
||||
int lfs_rmdir (void *);
|
||||
int lfs_link (void *);
|
||||
int lfs_mmap (void *);
|
||||
int lfs_rename (void *);
|
||||
int lfs_getattr (void *);
|
||||
int lfs_setattr (void *);
|
||||
int lfs_close (void *);
|
||||
int lfsspec_close(void *);
|
||||
int lfsfifo_close(void *);
|
||||
int lfs_fcntl (void *);
|
||||
int lfs_inactive (void *);
|
||||
int lfs_reclaim (void *);
|
||||
int lfs_strategy (void *);
|
||||
int lfs_write (void *);
|
||||
int lfs_getpages (void *);
|
||||
int lfs_putpages (void *);
|
||||
|
||||
extern int lfs_mount_type;
|
||||
extern int (**lfs_vnodeop_p)(void *);
|
||||
extern int (**lfs_specop_p)(void *);
|
||||
extern int (**lfs_fifoop_p)(void *);
|
||||
extern const struct genfs_ops lfs_genfsops;
|
||||
|
||||
#endif /* defined(_KERNEL) */
|
||||
|
||||
/* lfs_cksum.c */
|
||||
u_int32_t cksum(void *, size_t);
|
||||
u_int32_t lfs_cksum_part(void *, size_t, u_int32_t);
|
||||
#define lfs_cksum_fold(sum) (sum)
|
||||
u_int32_t lfs_sb_cksum(struct dlfs *);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* !_UFS_LFS_LFS_EXTERN_H_ */
|
79
nbsd_include/ufs/mfs/mfs_extern.h
Normal file
79
nbsd_include/ufs/mfs/mfs_extern.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
/* $NetBSD: mfs_extern.h,v 1.31 2010/03/02 17:20:02 pooka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)mfs_extern.h 8.4 (Berkeley) 3/30/95
|
||||
*/
|
||||
|
||||
#ifndef _UFS_MFS_MFS_EXTERN_H_
|
||||
#define _UFS_MFS_MFS_EXTERN_H_
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/mallocvar.h>
|
||||
|
||||
struct buf;
|
||||
struct mount;
|
||||
struct nameidata;
|
||||
struct proc;
|
||||
struct statvfs;
|
||||
struct vnode;
|
||||
|
||||
__BEGIN_DECLS
|
||||
#define mfs_ioctl genfs_enoioctl
|
||||
|
||||
/* mfs_vfsops.c */
|
||||
VFS_PROTOS(mfs);
|
||||
|
||||
int mfs_initminiroot(void *);
|
||||
|
||||
/* mfs_vnops.c */
|
||||
int mfs_open(void *);
|
||||
int mfs_strategy(void *);
|
||||
void mfs_doio(struct buf *, void *);
|
||||
int mfs_bmap(void *);
|
||||
int mfs_close(void *);
|
||||
int mfs_inactive(void *);
|
||||
int mfs_reclaim(void *);
|
||||
int mfs_print(void *);
|
||||
int mfs_fsync(void *);
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#include <sys/mutex.h>
|
||||
|
||||
extern kmutex_t mfs_lock;
|
||||
extern void *mfs_rootbase;
|
||||
extern u_long mfs_rootsize;
|
||||
|
||||
#endif
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* !_UFS_MFS_MFS_EXTERN_H_ */
|
91
nbsd_include/ufs/mfs/mfsnode.h
Normal file
91
nbsd_include/ufs/mfs/mfsnode.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
/* $NetBSD: mfsnode.h,v 1.21 2008/03/26 14:19:43 ad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)mfsnode.h 8.3 (Berkeley) 5/19/95
|
||||
*/
|
||||
|
||||
#ifndef _UFS_MFS_MFSNODE_H_
|
||||
#define _UFS_MFS_MFSNODE_H_
|
||||
|
||||
/*
|
||||
* This structure defines the control data for the memory based file system.
|
||||
*/
|
||||
|
||||
struct mfsnode {
|
||||
struct vnode *mfs_vnode; /* vnode associated with this mfsnode */
|
||||
void *mfs_baseoff; /* base of file system in memory */
|
||||
long mfs_size; /* size of memory file system */
|
||||
struct proc *mfs_proc; /* supporting process */
|
||||
int mfs_shutdown; /* shutdown this mfsnode */
|
||||
#if defined(_KERNEL)
|
||||
kcondvar_t mfs_cv; /* notifier */
|
||||
int mfs_refcnt; /* number of references */
|
||||
struct bufq_state *mfs_buflist;/* list of I/O requests */
|
||||
#endif /* defined(_KERNEL) */
|
||||
};
|
||||
|
||||
#if defined(_KERNEL)
|
||||
/*
|
||||
* Convert between mfsnode pointers and vnode pointers
|
||||
*/
|
||||
#define VTOMFS(vp) ((struct mfsnode *)(vp)->v_data)
|
||||
#define MFSTOV(mfsp) ((mfsp)->mfs_vnode)
|
||||
|
||||
/* Prototypes for MFS operations on vnodes. */
|
||||
#define mfs_lookup genfs_badop
|
||||
#define mfs_create genfs_badop
|
||||
#define mfs_mknod genfs_badop
|
||||
#define mfs_access genfs_badop
|
||||
#define mfs_getattr genfs_badop
|
||||
#define mfs_setattr genfs_badop
|
||||
#define mfs_read genfs_badop
|
||||
#define mfs_write genfs_badop
|
||||
#define mfs_poll genfs_badop
|
||||
#define mfs_mmap genfs_badop
|
||||
#define mfs_seek genfs_badop
|
||||
#define mfs_remove genfs_badop
|
||||
#define mfs_link genfs_badop
|
||||
#define mfs_rename genfs_badop
|
||||
#define mfs_mkdir genfs_badop
|
||||
#define mfs_rmdir genfs_badop
|
||||
#define mfs_symlink genfs_badop
|
||||
#define mfs_readdir genfs_badop
|
||||
#define mfs_readlink genfs_badop
|
||||
#define mfs_abortop genfs_badop
|
||||
#define mfs_islocked genfs_noislocked
|
||||
#define mfs_pathconf genfs_badop
|
||||
#define mfs_advlock genfs_badop
|
||||
#define mfs_bwrite vn_bwrite
|
||||
#define mfs_revoke genfs_revoke
|
||||
#define mfs_putpages genfs_null_putpages
|
||||
|
||||
#endif /* defined(_KERNEL) */
|
||||
|
||||
#endif /* !_UFS_MFS_MFSNODE_H_ */
|
180
nbsd_include/ufs/ufs/dinode.h
Normal file
180
nbsd_include/ufs/ufs/dinode.h
Normal file
|
@ -0,0 +1,180 @@
|
|||
/* $NetBSD: dinode.h,v 1.21 2009/06/28 09:26:18 ad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed for the FreeBSD Project by Marshall
|
||||
* Kirk McKusick and Network Associates Laboratories, the Security
|
||||
* Research Division of Network Associates, Inc. under DARPA/SPAWAR
|
||||
* contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
|
||||
* research program
|
||||
*
|
||||
* Copyright (c) 1982, 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* (c) UNIX System Laboratories, Inc.
|
||||
* All or some portions of this file are derived from material licensed
|
||||
* to the University of California by American Telephone and Telegraph
|
||||
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
|
||||
* the permission of UNIX System Laboratories, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)dinode.h 8.9 (Berkeley) 3/29/95
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTE: COORDINATE ON-DISK FORMAT CHANGES WITH THE FREEBSD PROJECT.
|
||||
*/
|
||||
|
||||
#ifndef _UFS_UFS_DINODE_H_
|
||||
#define _UFS_UFS_DINODE_H_
|
||||
|
||||
/*
|
||||
* The root inode is the root of the file system. Inode 0 can't be used for
|
||||
* normal purposes and historically bad blocks were linked to inode 1, thus
|
||||
* the root inode is 2. (Inode 1 is no longer used for this purpose, however
|
||||
* numerous dump tapes make this assumption, so we are stuck with it).
|
||||
*/
|
||||
#define ROOTINO ((ino_t)2)
|
||||
|
||||
/*
|
||||
* The Whiteout inode# is a dummy non-zero inode number which will
|
||||
* never be allocated to a real file. It is used as a place holder
|
||||
* in the directory entry which has been tagged as a DT_W entry.
|
||||
* See the comments about ROOTINO above.
|
||||
*/
|
||||
#define WINO ((ino_t)1)
|
||||
|
||||
/*
|
||||
* A dinode contains all the meta-data associated with a UFS file.
|
||||
* This structure defines the on-disk format of a dinode. Since
|
||||
* this structure describes an on-disk structure, all its fields
|
||||
* are defined by types with precise widths.
|
||||
*/
|
||||
|
||||
#define NXADDR 2
|
||||
#define NDADDR 12 /* Direct addresses in inode. */
|
||||
#define NIADDR 3 /* Indirect addresses in inode. */
|
||||
|
||||
struct ufs1_dinode {
|
||||
u_int16_t di_mode; /* 0: IFMT, permissions; see below. */
|
||||
int16_t di_nlink; /* 2: File link count. */
|
||||
union {
|
||||
u_int16_t oldids[2]; /* 4: Ffs: old user and group ids. */
|
||||
u_int32_t inumber; /* 4: Lfs: inode number. */
|
||||
} di_u;
|
||||
u_int64_t di_size; /* 8: File byte count. */
|
||||
int32_t di_atime; /* 16: Last access time. */
|
||||
int32_t di_atimensec; /* 20: Last access time. */
|
||||
int32_t di_mtime; /* 24: Last modified time. */
|
||||
int32_t di_mtimensec; /* 28: Last modified time. */
|
||||
int32_t di_ctime; /* 32: Last inode change time. */
|
||||
int32_t di_ctimensec; /* 36: Last inode change time. */
|
||||
int32_t di_db[NDADDR]; /* 40: Direct disk blocks. */
|
||||
int32_t di_ib[NIADDR]; /* 88: Indirect disk blocks. */
|
||||
u_int32_t di_flags; /* 100: Status flags (chflags). */
|
||||
u_int32_t di_blocks; /* 104: Blocks actually held. */
|
||||
int32_t di_gen; /* 108: Generation number. */
|
||||
u_int32_t di_uid; /* 112: File owner. */
|
||||
u_int32_t di_gid; /* 116: File group. */
|
||||
u_int64_t di_modrev; /* 120: i_modrev for NFSv4 */
|
||||
};
|
||||
|
||||
struct ufs2_dinode {
|
||||
u_int16_t di_mode; /* 0: IFMT, permissions; see below. */
|
||||
int16_t di_nlink; /* 2: File link count. */
|
||||
u_int32_t di_uid; /* 4: File owner. */
|
||||
u_int32_t di_gid; /* 8: File group. */
|
||||
u_int32_t di_blksize; /* 12: Inode blocksize. */
|
||||
u_int64_t di_size; /* 16: File byte count. */
|
||||
u_int64_t di_blocks; /* 24: Bytes actually held. */
|
||||
int64_t di_atime; /* 32: Last access time. */
|
||||
int64_t di_mtime; /* 40: Last modified time. */
|
||||
int64_t di_ctime; /* 48: Last inode change time. */
|
||||
int64_t di_birthtime; /* 56: Inode creation time. */
|
||||
int32_t di_mtimensec; /* 64: Last modified time. */
|
||||
int32_t di_atimensec; /* 68: Last access time. */
|
||||
int32_t di_ctimensec; /* 72: Last inode change time. */
|
||||
int32_t di_birthnsec; /* 76: Inode creation time. */
|
||||
int32_t di_gen; /* 80: Generation number. */
|
||||
u_int32_t di_kernflags; /* 84: Kernel flags. */
|
||||
u_int32_t di_flags; /* 88: Status flags (chflags). */
|
||||
int32_t di_extsize; /* 92: External attributes block. */
|
||||
int64_t di_extb[NXADDR];/* 96: External attributes block. */
|
||||
int64_t di_db[NDADDR]; /* 112: Direct disk blocks. */
|
||||
int64_t di_ib[NIADDR]; /* 208: Indirect disk blocks. */
|
||||
u_int64_t di_modrev; /* 232: i_modrev for NFSv4 */
|
||||
int64_t di_spare[2]; /* 240: Reserved; currently unused */
|
||||
};
|
||||
|
||||
/*
|
||||
* The di_db fields may be overlaid with other information for
|
||||
* file types that do not have associated disk storage. Block
|
||||
* and character devices overlay the first data block with their
|
||||
* dev_t value. Short symbolic links place their path in the
|
||||
* di_db area.
|
||||
*/
|
||||
#define di_inumber di_u.inumber
|
||||
#define di_ogid di_u.oldids[1]
|
||||
#define di_ouid di_u.oldids[0]
|
||||
#define di_rdev di_db[0]
|
||||
#define MAXSYMLINKLEN_UFS1 ((NDADDR + NIADDR) * sizeof(int32_t))
|
||||
#define MAXSYMLINKLEN_UFS2 ((NDADDR + NIADDR) * sizeof(int64_t))
|
||||
|
||||
#define MAXSYMLINKLEN(ip) \
|
||||
((ip)->i_ump->um_fstype == UFS1) ? \
|
||||
MAXSYMLINKLEN_UFS1 : MAXSYMLINKLEN_UFS2
|
||||
|
||||
/* NeXT used to keep short symlinks in the inode even when using
|
||||
* FS_42INODEFMT. In that case fs->fs_maxsymlinklen is probably -1,
|
||||
* but short symlinks were stored in inodes shorter than this:
|
||||
*/
|
||||
#define APPLEUFS_MAXSYMLINKLEN 60
|
||||
|
||||
/* File permissions. */
|
||||
#define IEXEC 0000100 /* Executable. */
|
||||
#define IWRITE 0000200 /* Writable. */
|
||||
#define IREAD 0000400 /* Readable. */
|
||||
#define ISVTX 0001000 /* Sticky bit. */
|
||||
#define ISGID 0002000 /* Set-gid. */
|
||||
#define ISUID 0004000 /* Set-uid. */
|
||||
|
||||
/* File types. */
|
||||
#define IFMT 0170000 /* Mask of file type. */
|
||||
#define IFIFO 0010000 /* Named pipe (fifo). */
|
||||
#define IFCHR 0020000 /* Character device. */
|
||||
#define IFDIR 0040000 /* Directory file. */
|
||||
#define IFBLK 0060000 /* Block device. */
|
||||
#define IFREG 0100000 /* Regular file. */
|
||||
#define IFLNK 0120000 /* Symbolic link. */
|
||||
#define IFSOCK 0140000 /* UNIX domain socket. */
|
||||
#define IFWHT 0160000 /* Whiteout. */
|
||||
|
||||
/* Size of the on-disk inode. */
|
||||
#define DINODE1_SIZE (sizeof(struct ufs1_dinode)) /* 128 */
|
||||
#define DINODE2_SIZE (sizeof(struct ufs2_dinode))
|
||||
|
||||
#endif /* !_UFS_UFS_DINODE_H_ */
|
160
nbsd_include/ufs/ufs/dir.h
Normal file
160
nbsd_include/ufs/ufs/dir.h
Normal file
|
@ -0,0 +1,160 @@
|
|||
/* $NetBSD: dir.h,v 1.21 2009/07/22 04:49:19 dholland Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* (c) UNIX System Laboratories, Inc.
|
||||
* All or some portions of this file are derived from material licensed
|
||||
* to the University of California by American Telephone and Telegraph
|
||||
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
|
||||
* the permission of UNIX System Laboratories, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)dir.h 8.5 (Berkeley) 4/27/95
|
||||
*/
|
||||
|
||||
#ifndef _UFS_UFS_DIR_H_
|
||||
#define _UFS_UFS_DIR_H_
|
||||
|
||||
/*
|
||||
* Theoretically, directories can be more than 2Gb in length; however, in
|
||||
* practice this seems unlikely. So, we define the type doff_t as a 32-bit
|
||||
* quantity to keep down the cost of doing lookup on a 32-bit machine.
|
||||
*/
|
||||
#define doff_t int32_t
|
||||
#define MAXDIRSIZE (0x7fffffff)
|
||||
|
||||
/*
|
||||
* A directory consists of some number of blocks of DIRBLKSIZ
|
||||
* bytes, where DIRBLKSIZ is chosen such that it can be transferred
|
||||
* to disk in a single atomic operation (e.g. 512 bytes on most machines).
|
||||
*
|
||||
* Each DIRBLKSIZ byte block contains some number of directory entry
|
||||
* structures, which are of variable length. Each directory entry has
|
||||
* a struct direct at the front of it, containing its inode number,
|
||||
* the length of the entry, and the length of the name contained in
|
||||
* the entry. These are followed by the name padded to a 4 byte boundary.
|
||||
* All names are guaranteed null terminated.
|
||||
* The maximum length of a name in a directory is FFS_MAXNAMLEN.
|
||||
*
|
||||
* The macro DIRSIZ(fmt, dp) gives the amount of space required to represent
|
||||
* a directory entry. Free space in a directory is represented by
|
||||
* entries which have dp->d_reclen > DIRSIZ(fmt, dp). All DIRBLKSIZ bytes
|
||||
* in a directory block are claimed by the directory entries. This
|
||||
* usually results in the last entry in a directory having a large
|
||||
* dp->d_reclen. When entries are deleted from a directory, the
|
||||
* space is returned to the previous entry in the same directory
|
||||
* block by increasing its dp->d_reclen. If the first entry of
|
||||
* a directory block is free, then its dp->d_ino is set to 0.
|
||||
* Entries other than the first in a directory do not normally have
|
||||
* dp->d_ino set to 0.
|
||||
*/
|
||||
#undef DIRBLKSIZ
|
||||
#define DIRBLKSIZ DEV_BSIZE
|
||||
#define FFS_MAXNAMLEN 255
|
||||
#define APPLEUFS_DIRBLKSIZ 1024
|
||||
|
||||
#define d_ino d_fileno
|
||||
struct direct {
|
||||
u_int32_t d_fileno; /* inode number of entry */
|
||||
u_int16_t d_reclen; /* length of this record */
|
||||
u_int8_t d_type; /* file type, see below */
|
||||
u_int8_t d_namlen; /* length of string in d_name */
|
||||
char d_name[FFS_MAXNAMLEN + 1];/* name with length <= FFS_MAXNAMLEN */
|
||||
};
|
||||
|
||||
/*
|
||||
* File types
|
||||
*/
|
||||
#define DT_UNKNOWN 0
|
||||
#define DT_FIFO 1
|
||||
#define DT_CHR 2
|
||||
#define DT_DIR 4
|
||||
#define DT_BLK 6
|
||||
#define DT_REG 8
|
||||
#define DT_LNK 10
|
||||
#define DT_SOCK 12
|
||||
#define DT_WHT 14
|
||||
|
||||
/*
|
||||
* Convert between stat structure types and directory types.
|
||||
*/
|
||||
#define IFTODT(mode) (((mode) & 0170000) >> 12)
|
||||
#define DTTOIF(dirtype) ((dirtype) << 12)
|
||||
|
||||
/*
|
||||
* The DIRSIZ macro gives the minimum record length which will hold
|
||||
* the directory entry. This requires the amount of space in struct direct
|
||||
* without the d_name field, plus enough space for the name with a terminating
|
||||
* null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
|
||||
*/
|
||||
#define DIRECTSIZ(namlen) \
|
||||
((sizeof(struct direct) - (FFS_MAXNAMLEN+1)) + (((namlen)+1 + 3) &~ 3))
|
||||
|
||||
#if (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
#define DIRSIZ(oldfmt, dp, needswap) \
|
||||
(((oldfmt) && !(needswap)) ? \
|
||||
DIRECTSIZ((dp)->d_type) : DIRECTSIZ((dp)->d_namlen))
|
||||
#else
|
||||
#define DIRSIZ(oldfmt, dp, needswap) \
|
||||
(((oldfmt) && (needswap)) ? \
|
||||
DIRECTSIZ((dp)->d_type) : DIRECTSIZ((dp)->d_namlen))
|
||||
#endif
|
||||
|
||||
#define OLDDIRFMT 1
|
||||
#define NEWDIRFMT 0
|
||||
|
||||
/*
|
||||
* Template for manipulating directories. Should use struct direct's,
|
||||
* but the name field is FFS_MAXNAMLEN - 1, and this just won't do.
|
||||
*/
|
||||
struct dirtemplate {
|
||||
u_int32_t dot_ino;
|
||||
int16_t dot_reclen;
|
||||
u_int8_t dot_type;
|
||||
u_int8_t dot_namlen;
|
||||
char dot_name[4]; /* must be multiple of 4 */
|
||||
u_int32_t dotdot_ino;
|
||||
int16_t dotdot_reclen;
|
||||
u_int8_t dotdot_type;
|
||||
u_int8_t dotdot_namlen;
|
||||
char dotdot_name[4]; /* ditto */
|
||||
};
|
||||
|
||||
/*
|
||||
* This is the old format of directories, sanz type element.
|
||||
*/
|
||||
struct odirtemplate {
|
||||
u_int32_t dot_ino;
|
||||
int16_t dot_reclen;
|
||||
u_int16_t dot_namlen;
|
||||
char dot_name[4]; /* must be multiple of 4 */
|
||||
u_int32_t dotdot_ino;
|
||||
int16_t dotdot_reclen;
|
||||
u_int16_t dotdot_namlen;
|
||||
char dotdot_name[4]; /* ditto */
|
||||
};
|
||||
#endif /* !_UFS_UFS_DIR_H_ */
|
129
nbsd_include/ufs/ufs/dirhash.h
Normal file
129
nbsd_include/ufs/ufs/dirhash.h
Normal file
|
@ -0,0 +1,129 @@
|
|||
/* $NetBSD: dirhash.h,v 1.6 2008/06/04 11:33:19 ad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Ian Dowse. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: src/sys/ufs/ufs/dirhash.h,v 1.2.2.2 2004/12/08 11:54:13 dwmalone Exp $
|
||||
*/
|
||||
|
||||
#ifndef _UFS_UFS_DIRHASH_H_
|
||||
#define _UFS_UFS_DIRHASH_H_
|
||||
|
||||
/*
|
||||
* For fast operations on large directories, we maintain a hash
|
||||
* that maps the file name to the offset of the directory entry within
|
||||
* the directory file.
|
||||
*
|
||||
* The hashing uses a dumb spillover to the next free slot on
|
||||
* collisions, so we must keep the utilisation low to avoid
|
||||
* long linear searches. Deleted entries that are not the last
|
||||
* in a chain must be marked DIRHASH_DEL.
|
||||
*
|
||||
* We also maintain information about free space in each block
|
||||
* to speed up creations.
|
||||
*/
|
||||
#define DIRHASH_EMPTY (-1) /* entry unused */
|
||||
#define DIRHASH_DEL (-2) /* deleted entry; may be part of chain */
|
||||
|
||||
#define DIRALIGN 4
|
||||
#define DH_NFSTATS (DIRECTSIZ(FFS_MAXNAMLEN + 1) / DIRALIGN)
|
||||
/* max DIRALIGN words in a directory entry */
|
||||
|
||||
/*
|
||||
* Dirhash uses a score mechanism to achieve a hybrid between a
|
||||
* least-recently-used and a least-often-used algorithm for entry
|
||||
* recycling. The score is incremented when a directory is used, and
|
||||
* decremented when the directory is a candidate for recycling. When
|
||||
* the score reaches zero, the hash is recycled. Hashes are linked
|
||||
* together on a TAILQ list, and hashes with higher scores filter
|
||||
* towards the tail (most recently used) end of the list.
|
||||
*
|
||||
* New hash entries are given an inital score of DH_SCOREINIT and are
|
||||
* placed at the most-recently-used end of the list. This helps a lot
|
||||
* in the worst-case case scenario where every directory access is
|
||||
* to a directory that is not hashed (i.e. the working set of hash
|
||||
* candidates is much larger than the configured memry limit). In this
|
||||
* case it limits the number of hash builds to 1/DH_SCOREINIT of the
|
||||
* number of accesses.
|
||||
*/
|
||||
#define DH_SCOREINIT 8 /* initial dh_score when dirhash built */
|
||||
#define DH_SCOREMAX 64 /* max dh_score value */
|
||||
|
||||
/*
|
||||
* The main hash table has 2 levels. It is an array of pointers to
|
||||
* blocks of DH_NBLKOFF offsets.
|
||||
*/
|
||||
#define DH_BLKOFFSHIFT 8
|
||||
#define DH_NBLKOFF (1 << DH_BLKOFFSHIFT)
|
||||
#define DH_BLKOFFMASK (DH_NBLKOFF - 1)
|
||||
|
||||
#define DH_ENTRY(dh, slot) \
|
||||
((dh)->dh_hash[(slot) >> DH_BLKOFFSHIFT][(slot) & DH_BLKOFFMASK])
|
||||
|
||||
struct dirhash {
|
||||
kmutex_t dh_lock; /* protects all fields except dh_list */
|
||||
|
||||
doff_t **dh_hash; /* the hash array (2-level) */
|
||||
size_t dh_hashsz;
|
||||
int dh_narrays; /* number of entries in dh_hash */
|
||||
int dh_hlen; /* total slots in the 2-level hash array */
|
||||
int dh_hused; /* entries in use */
|
||||
|
||||
u_int8_t *dh_blkfree; /* free DIRALIGN words in each dir block */
|
||||
size_t dh_blkfreesz;
|
||||
int dh_nblk; /* size of dh_blkfree array */
|
||||
int dh_dirblks; /* number of DIRBLKSIZ blocks in dir */
|
||||
int dh_firstfree[DH_NFSTATS + 1]; /* first blk with N words free */
|
||||
|
||||
int dh_seqopt; /* sequential access optimisation enabled */
|
||||
doff_t dh_seqoff; /* sequential access optimisation offset */
|
||||
|
||||
int dh_score; /* access count for this dirhash */
|
||||
|
||||
int dh_onlist; /* true if on the ufsdirhash_list chain */
|
||||
|
||||
/* Protected by ufsdirhash_lock. */
|
||||
TAILQ_ENTRY(dirhash) dh_list; /* chain of all dirhashes */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Dirhash functions.
|
||||
*/
|
||||
int ufsdirhash_build(struct inode *);
|
||||
doff_t ufsdirhash_findfree(struct inode *, int, int *);
|
||||
doff_t ufsdirhash_enduseful(struct inode *);
|
||||
int ufsdirhash_lookup(struct inode *, const char *, int, doff_t *,
|
||||
struct buf **, doff_t *);
|
||||
void ufsdirhash_newblk(struct inode *, doff_t);
|
||||
void ufsdirhash_add(struct inode *, struct direct *, doff_t);
|
||||
void ufsdirhash_remove(struct inode *, struct direct *, doff_t);
|
||||
void ufsdirhash_move(struct inode *, struct direct *, doff_t, doff_t);
|
||||
void ufsdirhash_dirtrunc(struct inode *, doff_t);
|
||||
void ufsdirhash_free(struct inode *);
|
||||
void ufsdirhash_checkblock(struct inode *, char *, doff_t);
|
||||
void ufsdirhash_init(void);
|
||||
void ufsdirhash_done(void);
|
||||
|
||||
#endif /* !_UFS_UFS_DIRHASH_H_ */
|
128
nbsd_include/ufs/ufs/extattr.h
Normal file
128
nbsd_include/ufs/ufs/extattr.h
Normal file
|
@ -0,0 +1,128 @@
|
|||
/* $NetBSD: extattr.h,v 1.10 2011/10/09 21:15:34 chs Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999-2001 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by Robert Watson for the TrustedBSD Project.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: src/sys/ufs/ufs/extattr.h,v 1.20 2005/01/31 08:16:45 imp Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* Support for file system extended attributes on the UFS1 file system.
|
||||
* Developed by the TrustedBSD Project.
|
||||
*/
|
||||
|
||||
#ifndef _UFS_UFS_EXTATTR_H_
|
||||
#define _UFS_UFS_EXTATTR_H_
|
||||
|
||||
#define UFS_EXTATTR_MAGIC 0x00b5d5ec
|
||||
#define UFS_EXTATTR_VERSION 0x00000003
|
||||
#define UFS_EXTATTR_FSROOTSUBDIR ".attribute"
|
||||
#define UFS_EXTATTR_SUBDIR_SYSTEM "system"
|
||||
#define UFS_EXTATTR_SUBDIR_USER "user"
|
||||
#define UFS_EXTATTR_MAXEXTATTRNAME 65 /* including null */
|
||||
|
||||
#define UFS_EXTATTR_ATTR_FLAG_INUSE 0x00000001 /* attr has been set */
|
||||
#define UFS_EXTATTR_PERM_KERNEL 0x00000000
|
||||
#define UFS_EXTATTR_PERM_ROOT 0x00000001
|
||||
#define UFS_EXTATTR_PERM_OWNER 0x00000002
|
||||
#define UFS_EXTATTR_PERM_ANYONE 0x00000003
|
||||
|
||||
#define UFS_EXTATTR_UEPM_INITIALIZED 0x00000001
|
||||
#define UFS_EXTATTR_UEPM_STARTED 0x00000002
|
||||
|
||||
#define UFS_EXTATTR_CMD_START EXTATTR_CMD_START
|
||||
#define UFS_EXTATTR_CMD_STOP EXTATTR_CMD_STOP
|
||||
#define UFS_EXTATTR_CMD_ENABLE 0x00000003
|
||||
#define UFS_EXTATTR_CMD_DISABLE 0x00000004
|
||||
|
||||
struct ufs_extattr_fileheader {
|
||||
uint32_t uef_magic; /* magic number for sanity checking */
|
||||
uint32_t uef_version; /* version of attribute file */
|
||||
uint32_t uef_size; /* size of attributes, w/o header */
|
||||
};
|
||||
|
||||
struct ufs_extattr_header {
|
||||
uint32_t ueh_flags; /* flags for attribute */
|
||||
uint32_t ueh_len; /* local defined length; <= uef_size */
|
||||
uint32_t ueh_i_gen; /* generation number for sanity */
|
||||
/* data follows the header */
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#ifdef MALLOC_DECLARE
|
||||
MALLOC_DECLARE(M_EXTATTR);
|
||||
#endif
|
||||
|
||||
struct vnode;
|
||||
LIST_HEAD(ufs_extattr_list_head, ufs_extattr_list_entry);
|
||||
struct ufs_extattr_list_entry {
|
||||
LIST_ENTRY(ufs_extattr_list_entry) uele_entries;
|
||||
struct ufs_extattr_fileheader uele_fileheader;
|
||||
int uele_attrnamespace;
|
||||
char uele_attrname[UFS_EXTATTR_MAXEXTATTRNAME];
|
||||
struct vnode *uele_backing_vnode;
|
||||
int uele_flags;
|
||||
};
|
||||
|
||||
/* uele_flags */
|
||||
#define UELE_F_NEEDSWAP 0x01 /* needs byte swap */
|
||||
|
||||
#define UELE_NEEDSWAP(uele) ((uele)->uele_flags & UELE_F_NEEDSWAP)
|
||||
|
||||
struct lock;
|
||||
struct ufs_extattr_per_mount {
|
||||
kmutex_t uepm_lock;
|
||||
struct ufs_extattr_list_head uepm_list;
|
||||
kauth_cred_t uepm_ucred;
|
||||
int uepm_lockcnt;
|
||||
int uepm_flags;
|
||||
};
|
||||
|
||||
void ufs_extattr_uepm_init(struct ufs_extattr_per_mount *uepm);
|
||||
void ufs_extattr_uepm_destroy(struct ufs_extattr_per_mount *uepm);
|
||||
int ufs_extattr_start(struct mount *mp, struct lwp *l);
|
||||
int ufs_extattr_autostart(struct mount *mp, struct lwp *l);
|
||||
void ufs_extattr_stop(struct mount *mp, struct lwp *l);
|
||||
int ufs_extattrctl(struct mount *mp, int cmd, struct vnode *filename,
|
||||
int attrnamespace, const char *attrname);
|
||||
struct vop_getextattr_args;
|
||||
int ufs_getextattr(struct vop_getextattr_args *ap);
|
||||
struct vop_deleteextattr_args;
|
||||
int ufs_deleteextattr(struct vop_deleteextattr_args *ap);
|
||||
struct vop_setextattr_args;
|
||||
int ufs_setextattr(struct vop_setextattr_args *ap);
|
||||
struct vop_listextattr_args;
|
||||
int ufs_listextattr(struct vop_listextattr_args *ap);
|
||||
void ufs_extattr_vnode_inactive(struct vnode *vp, struct lwp *l);
|
||||
|
||||
void ufs_extattr_init(void);
|
||||
void ufs_extattr_done(void);
|
||||
|
||||
#endif /* !_KERNEL */
|
||||
|
||||
#endif /* !_UFS_UFS_EXTATTR_H_ */
|
300
nbsd_include/ufs/ufs/inode.h
Normal file
300
nbsd_include/ufs/ufs/inode.h
Normal file
|
@ -0,0 +1,300 @@
|
|||
/* $NetBSD: inode.h,v 1.58 2011/07/12 02:22:13 dholland Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* (c) UNIX System Laboratories, Inc.
|
||||
* All or some portions of this file are derived from material licensed
|
||||
* to the University of California by American Telephone and Telegraph
|
||||
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
|
||||
* the permission of UNIX System Laboratories, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)inode.h 8.9 (Berkeley) 5/14/95
|
||||
*/
|
||||
|
||||
#ifndef _UFS_UFS_INODE_H_
|
||||
#define _UFS_UFS_INODE_H_
|
||||
|
||||
#include <sys/vnode.h>
|
||||
#include <ufs/ufs/dinode.h>
|
||||
#include <ufs/ufs/dir.h>
|
||||
#include <ufs/ufs/quota.h>
|
||||
#include <ufs/ext2fs/ext2fs_dinode.h>
|
||||
#include <miscfs/genfs/genfs_node.h>
|
||||
|
||||
/*
|
||||
* Lookup result state (other than the result inode). This is
|
||||
* currently stashed in the vnode between VOP_LOOKUP and directory
|
||||
* operation VOPs, which is gross.
|
||||
*/
|
||||
struct ufs_lookup_results {
|
||||
int32_t ulr_count; /* Size of free slot in directory. */
|
||||
doff_t ulr_endoff; /* End of useful stuff in directory. */
|
||||
doff_t ulr_diroff; /* Offset in dir, where we found last entry. */
|
||||
doff_t ulr_offset; /* Offset of free space in directory. */
|
||||
u_int32_t ulr_reclen; /* Size of found directory entry. */
|
||||
};
|
||||
|
||||
/* notyet XXX */
|
||||
#define UFS_CHECK_CRAPCOUNTER(dp) ((void)(dp)->i_crapcounter)
|
||||
|
||||
/*
|
||||
* Per-filesystem inode extensions.
|
||||
*/
|
||||
struct ffs_inode_ext {
|
||||
daddr_t *ffs_snapblklist; /* Collect expunged snapshot blocks. */
|
||||
/* follow two fields are used by contiguous allocation code only. */
|
||||
daddr_t ffs_first_data_blk; /* first data block on disk. */
|
||||
daddr_t ffs_first_indir_blk; /* first indirect block on disk. */
|
||||
};
|
||||
|
||||
struct ext2fs_inode_ext {
|
||||
daddr_t ext2fs_last_lblk; /* last logical block allocated */
|
||||
daddr_t ext2fs_last_blk; /* last block allocated on disk */
|
||||
};
|
||||
|
||||
struct lfs_inode_ext;
|
||||
|
||||
/*
|
||||
* The inode is used to describe each active (or recently active) file in the
|
||||
* UFS filesystem. It is composed of two types of information. The first part
|
||||
* is the information that is needed only while the file is active (such as
|
||||
* the identity of the file and linkage to speed its lookup). The second part
|
||||
* is the permanent meta-data associated with the file which is read in
|
||||
* from the permanent dinode from long term storage when the file becomes
|
||||
* active, and is put back when the file is no longer being used.
|
||||
*/
|
||||
struct inode {
|
||||
struct genfs_node i_gnode;
|
||||
LIST_ENTRY(inode) i_hash;/* Hash chain. */
|
||||
TAILQ_ENTRY(inode) i_nextsnap; /* snapshot file list. */
|
||||
struct vnode *i_vnode; /* Vnode associated with this inode. */
|
||||
struct ufsmount *i_ump; /* Mount point associated with this inode. */
|
||||
struct vnode *i_devvp; /* Vnode for block I/O. */
|
||||
u_int32_t i_flag; /* flags, see below */
|
||||
dev_t i_dev; /* Device associated with the inode. */
|
||||
ino_t i_number; /* The identity of the inode. */
|
||||
|
||||
union { /* Associated filesystem. */
|
||||
struct fs *fs; /* FFS */
|
||||
struct lfs *lfs; /* LFS */
|
||||
struct m_ext2fs *e2fs; /* EXT2FS */
|
||||
} inode_u;
|
||||
#define i_fs inode_u.fs
|
||||
#define i_lfs inode_u.lfs
|
||||
#define i_e2fs inode_u.e2fs
|
||||
|
||||
void *i_unused1; /* Unused. */
|
||||
struct dquot *i_dquot[MAXQUOTAS]; /* Dquot structures. */
|
||||
u_quad_t i_modrev; /* Revision level for NFS lease. */
|
||||
struct lockf *i_lockf;/* Head of byte-level lock list. */
|
||||
|
||||
/*
|
||||
* Side effects; used during (and after) directory lookup.
|
||||
* XXX should not be here.
|
||||
*/
|
||||
struct ufs_lookup_results i_crap;
|
||||
unsigned i_crapcounter; /* serial number for i_crap */
|
||||
|
||||
/*
|
||||
* Inode extensions
|
||||
*/
|
||||
union {
|
||||
/* Other extensions could go here... */
|
||||
struct ffs_inode_ext ffs;
|
||||
struct ext2fs_inode_ext e2fs;
|
||||
struct lfs_inode_ext *lfs;
|
||||
} inode_ext;
|
||||
#define i_snapblklist inode_ext.ffs.ffs_snapblklist
|
||||
#define i_ffs_first_data_blk inode_ext.ffs.ffs_first_data_blk
|
||||
#define i_ffs_first_indir_blk inode_ext.ffs.ffs_first_indir_blk
|
||||
#define i_e2fs_last_lblk inode_ext.e2fs.ext2fs_last_lblk
|
||||
#define i_e2fs_last_blk inode_ext.e2fs.ext2fs_last_blk
|
||||
/*
|
||||
* Copies from the on-disk dinode itself.
|
||||
*
|
||||
* These fields are currently only used by FFS and LFS,
|
||||
* do NOT use them with ext2fs.
|
||||
*/
|
||||
u_int16_t i_mode; /* IFMT, permissions; see below. */
|
||||
int16_t i_nlink; /* File link count. */
|
||||
u_int64_t i_size; /* File byte count. */
|
||||
u_int32_t i_flags; /* Status flags (chflags). */
|
||||
int32_t i_gen; /* Generation number. */
|
||||
u_int32_t i_uid; /* File owner. */
|
||||
u_int32_t i_gid; /* File group. */
|
||||
u_int16_t i_omode; /* Old mode, for ufs_reclaim. */
|
||||
|
||||
struct dirhash *i_dirhash; /* Hashing for large directories */
|
||||
|
||||
/*
|
||||
* The on-disk dinode itself.
|
||||
*/
|
||||
union {
|
||||
struct ufs1_dinode *ffs1_din; /* 128 bytes of the on-disk dinode. */
|
||||
struct ufs2_dinode *ffs2_din;
|
||||
struct ext2fs_dinode *e2fs_din; /* 128 bytes of the on-disk
|
||||
dinode. */
|
||||
} i_din;
|
||||
};
|
||||
|
||||
#define i_ffs1_atime i_din.ffs1_din->di_atime
|
||||
#define i_ffs1_atimensec i_din.ffs1_din->di_atimensec
|
||||
#define i_ffs1_blocks i_din.ffs1_din->di_blocks
|
||||
#define i_ffs1_ctime i_din.ffs1_din->di_ctime
|
||||
#define i_ffs1_ctimensec i_din.ffs1_din->di_ctimensec
|
||||
#define i_ffs1_db i_din.ffs1_din->di_db
|
||||
#define i_ffs1_flags i_din.ffs1_din->di_flags
|
||||
#define i_ffs1_gen i_din.ffs1_din->di_gen
|
||||
#define i_ffs1_gid i_din.ffs1_din->di_gid
|
||||
#define i_ffs1_ib i_din.ffs1_din->di_ib
|
||||
#define i_ffs1_mode i_din.ffs1_din->di_mode
|
||||
#define i_ffs1_mtime i_din.ffs1_din->di_mtime
|
||||
#define i_ffs1_mtimensec i_din.ffs1_din->di_mtimensec
|
||||
#define i_ffs1_nlink i_din.ffs1_din->di_nlink
|
||||
#define i_ffs1_rdev i_din.ffs1_din->di_rdev
|
||||
#define i_ffs1_size i_din.ffs1_din->di_size
|
||||
#define i_ffs1_uid i_din.ffs1_din->di_uid
|
||||
#define i_ffs1_ouid i_din.ffs1_din->di_u.oldids[0]
|
||||
#define i_ffs1_ogid i_din.ffs1_din->di_u.oldids[1]
|
||||
|
||||
#define i_ffs2_atime i_din.ffs2_din->di_atime
|
||||
#define i_ffs2_atimensec i_din.ffs2_din->di_atimensec
|
||||
#define i_ffs2_birthtime i_din.ffs2_din->di_birthtime
|
||||
#define i_ffs2_birthnsec i_din.ffs2_din->di_birthnsec
|
||||
#define i_ffs2_blocks i_din.ffs2_din->di_blocks
|
||||
#define i_ffs2_blksize i_din.ffs2_din->di_blksize
|
||||
#define i_ffs2_ctime i_din.ffs2_din->di_ctime
|
||||
#define i_ffs2_ctimensec i_din.ffs2_din->di_ctimensec
|
||||
#define i_ffs2_db i_din.ffs2_din->di_db
|
||||
#define i_ffs2_flags i_din.ffs2_din->di_flags
|
||||
#define i_ffs2_gen i_din.ffs2_din->di_gen
|
||||
#define i_ffs2_gid i_din.ffs2_din->di_gid
|
||||
#define i_ffs2_ib i_din.ffs2_din->di_ib
|
||||
#define i_ffs2_mode i_din.ffs2_din->di_mode
|
||||
#define i_ffs2_mtime i_din.ffs2_din->di_mtime
|
||||
#define i_ffs2_mtimensec i_din.ffs2_din->di_mtimensec
|
||||
#define i_ffs2_nlink i_din.ffs2_din->di_nlink
|
||||
#define i_ffs2_rdev i_din.ffs2_din->di_rdev
|
||||
#define i_ffs2_size i_din.ffs2_din->di_size
|
||||
#define i_ffs2_uid i_din.ffs2_din->di_uid
|
||||
#define i_ffs2_kernflags i_din.ffs2_din->di_kernflags
|
||||
#define i_ffs2_extsize i_din.ffs2_din->di_extsize
|
||||
#define i_ffs2_extb i_din.ffs2_din->di_extb
|
||||
|
||||
#define i_e2fs_mode i_din.e2fs_din->e2di_mode
|
||||
#define i_e2fs_uid i_din.e2fs_din->e2di_uid
|
||||
#define i_e2fs_size i_din.e2fs_din->e2di_size
|
||||
#define i_e2fs_atime i_din.e2fs_din->e2di_atime
|
||||
#define i_e2fs_ctime i_din.e2fs_din->e2di_ctime
|
||||
#define i_e2fs_mtime i_din.e2fs_din->e2di_mtime
|
||||
#define i_e2fs_dtime i_din.e2fs_din->e2di_dtime
|
||||
#define i_e2fs_gid i_din.e2fs_din->e2di_gid
|
||||
#define i_e2fs_nlink i_din.e2fs_din->e2di_nlink
|
||||
#define i_e2fs_nblock i_din.e2fs_din->e2di_nblock
|
||||
#define i_e2fs_flags i_din.e2fs_din->e2di_flags
|
||||
#define i_e2fs_blocks i_din.e2fs_din->e2di_blocks
|
||||
#define i_e2fs_gen i_din.e2fs_din->e2di_gen
|
||||
#define i_e2fs_facl i_din.e2fs_din->e2di_facl
|
||||
#define i_e2fs_dacl i_din.e2fs_din->e2di_dacl
|
||||
#define i_e2fs_faddr i_din.e2fs_din->e2di_faddr
|
||||
#define i_e2fs_nfrag i_din.e2fs_din->e2di_nfrag
|
||||
#define i_e2fs_fsize i_din.e2fs_din->e2di_fsize
|
||||
#define i_e2fs_rdev i_din.e2fs_din->e2di_rdev
|
||||
#define i_e2fs_uid_high i_din.e2fs_din->e2di_uid_high
|
||||
#define i_e2fs_gid_high i_din.e2fs_din->e2di_gid_high
|
||||
|
||||
/* These flags are kept in i_flag. */
|
||||
#define IN_ACCESS 0x0001 /* Access time update request. */
|
||||
#define IN_CHANGE 0x0002 /* Inode change time update request. */
|
||||
#define IN_UPDATE 0x0004 /* Inode was written to; update mtime. */
|
||||
#define IN_MODIFY 0x2000 /* Modification time update request. */
|
||||
#define IN_MODIFIED 0x0008 /* Inode has been modified. */
|
||||
#define IN_ACCESSED 0x0010 /* Inode has been accessed. */
|
||||
#define IN_RENAME 0x0020 /* Inode is being renamed. */
|
||||
#define IN_SHLOCK 0x0040 /* File has shared lock. */
|
||||
#define IN_EXLOCK 0x0080 /* File has exclusive lock. */
|
||||
#define IN_CLEANING 0x0100 /* LFS: file is being cleaned */
|
||||
#define IN_ADIROP 0x0200 /* LFS: dirop in progress */
|
||||
#define IN_SPACECOUNTED 0x0400 /* Blocks to be freed in free count. */
|
||||
#define IN_PAGING 0x1000 /* LFS: file is on paging queue */
|
||||
|
||||
#if defined(_KERNEL)
|
||||
|
||||
/*
|
||||
* The DIP macro is used to access fields in the dinode that are
|
||||
* not cached in the inode itself.
|
||||
*/
|
||||
#define DIP(ip, field) \
|
||||
(((ip)->i_ump->um_fstype == UFS1) ? \
|
||||
(ip)->i_ffs1_##field : (ip)->i_ffs2_##field)
|
||||
|
||||
#define DIP_ASSIGN(ip, field, value) \
|
||||
do { \
|
||||
if ((ip)->i_ump->um_fstype == UFS1) \
|
||||
(ip)->i_ffs1_##field = (value); \
|
||||
else \
|
||||
(ip)->i_ffs2_##field = (value); \
|
||||
} while(0)
|
||||
|
||||
#define DIP_ADD(ip, field, value) \
|
||||
do { \
|
||||
if ((ip)->i_ump->um_fstype == UFS1) \
|
||||
(ip)->i_ffs1_##field += (value); \
|
||||
else \
|
||||
(ip)->i_ffs2_##field += (value); \
|
||||
} while(0)
|
||||
|
||||
#define SHORTLINK(ip) \
|
||||
(((ip)->i_ump->um_fstype == UFS1) ? \
|
||||
(void *)(ip)->i_ffs1_db : (void *)(ip)->i_ffs2_db)
|
||||
|
||||
|
||||
/*
|
||||
* Structure used to pass around logical block paths generated by
|
||||
* ufs_getlbns and used by truncate and bmap code.
|
||||
*/
|
||||
struct indir {
|
||||
daddr_t in_lbn; /* Logical block number. */
|
||||
int in_off; /* Offset in buffer. */
|
||||
int in_exists; /* Flag if the block exists. */
|
||||
};
|
||||
|
||||
/* Convert between inode pointers and vnode pointers. */
|
||||
#define VTOI(vp) ((struct inode *)(vp)->v_data)
|
||||
#define ITOV(ip) ((ip)->i_vnode)
|
||||
|
||||
/* This overlays the fid structure (see fstypes.h). */
|
||||
struct ufid {
|
||||
u_int16_t ufid_len; /* Length of structure. */
|
||||
u_int16_t ufid_pad; /* Force 32-bit alignment. */
|
||||
u_int32_t ufid_ino; /* File number (ino). */
|
||||
int32_t ufid_gen; /* Generation number. */
|
||||
};
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* !_UFS_UFS_INODE_H_ */
|
97
nbsd_include/ufs/ufs/quota.h
Normal file
97
nbsd_include/ufs/ufs/quota.h
Normal file
|
@ -0,0 +1,97 @@
|
|||
/* $NetBSD: quota.h,v 1.28 2011/03/25 10:25:17 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Robert Elz at The University of Melbourne.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)quota.h 8.3 (Berkeley) 8/19/94
|
||||
*/
|
||||
|
||||
#ifndef _UFS_UFS_QUOTA_H_
|
||||
#define _UFS_UFS_QUOTA_H_
|
||||
|
||||
/*
|
||||
* These definitions are common to the original disk quota implementation
|
||||
* (quota1) and the newer implementation (quota2)
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following constants define the usage of the quota file array in the
|
||||
* ufsmount structure and dquot array in the inode structure. The semantics
|
||||
* of the elements of these arrays are defined in the routine getinoquota;
|
||||
* the remainder of the quota code treats them generically and need not be
|
||||
* inspected when changing the size of the array.
|
||||
*/
|
||||
#define MAXQUOTAS 2
|
||||
#define USRQUOTA 0 /* element used for user quotas */
|
||||
#define GRPQUOTA 1 /* element used for group quotas */
|
||||
|
||||
|
||||
#if !defined(HAVE_NBTOOL_CONFIG_H)
|
||||
#include <quota/quotaprop.h>
|
||||
__inline static int __unused
|
||||
ufsclass2qtype(int class)
|
||||
{
|
||||
switch(class) {
|
||||
case QUOTA_CLASS_USER:
|
||||
return USRQUOTA;
|
||||
case QUOTA_CLASS_GROUP:
|
||||
return GRPQUOTA;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static __inline int __unused
|
||||
qtype2ufsclass(int type)
|
||||
{
|
||||
switch(type) {
|
||||
case USRQUOTA:
|
||||
return QUOTA_CLASS_USER;
|
||||
case GRPQUOTA:
|
||||
return QUOTA_CLASS_GROUP;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif /* !defined(HAVE_NBTOOL_CONFIG_H) */
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
void dqinit(void);
|
||||
void dqreinit(void);
|
||||
void dqdone(void);
|
||||
__END_DECLS
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* !_UFS_UFS_QUOTA_H_ */
|
111
nbsd_include/ufs/ufs/quota1.h
Normal file
111
nbsd_include/ufs/ufs/quota1.h
Normal file
|
@ -0,0 +1,111 @@
|
|||
/* $NetBSD: quota1.h,v 1.5 2011/11/25 16:55:05 dholland Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Robert Elz at The University of Melbourne.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)quota.h 8.3 (Berkeley) 8/19/94
|
||||
*/
|
||||
|
||||
#ifndef _UFS_UFS_QUOTA1_H_
|
||||
#define _UFS_UFS_QUOTA1_H_
|
||||
|
||||
#include <sys/quota.h>
|
||||
#include <ufs/ufs/quota.h>
|
||||
|
||||
/*
|
||||
* These definitions are for the original disk quota implementation, which
|
||||
* is deprecated. the newer implementation is defined in quota2.h
|
||||
* and friends
|
||||
*/
|
||||
|
||||
/*
|
||||
* Definitions for the default names of the quotas files/quota types.
|
||||
*/
|
||||
#define INITQFNAMES { \
|
||||
"user", /* USRQUOTA */ \
|
||||
"group", /* GRPQUOTA */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Definitions for disk quotas imposed on the average user
|
||||
* (big brother finally hits UNIX).
|
||||
*
|
||||
* The following constants define the amount of time given a user before the
|
||||
* soft limits are treated as hard limits (usually resulting in an allocation
|
||||
* failure). The timer is started when the user crosses their soft limit, it
|
||||
* is reset when they go below their soft limit.
|
||||
*/
|
||||
#define MAX_IQ_TIME (7*24*60*60) /* seconds in 1 week */
|
||||
#define MAX_DQ_TIME (7*24*60*60) /* seconds in 1 week */
|
||||
|
||||
#define QUOTAFILENAME "quota"
|
||||
#define QUOTAGROUP "operator"
|
||||
|
||||
/*
|
||||
* Command definitions for the 'compat_50_quotactl' system call. The commands
|
||||
* are broken into a main command defined below and a subcommand that is used
|
||||
* to convey the type of quota that is being manipulated (see above).
|
||||
*/
|
||||
#define SUBCMDMASK 0x00ff
|
||||
#define SUBCMDSHIFT 8
|
||||
#define QCMD(cmd, type) (((cmd) << SUBCMDSHIFT) | ((type) & SUBCMDMASK))
|
||||
|
||||
#define Q_QUOTAON 0x0100 /* enable quotas */
|
||||
#define Q_QUOTAOFF 0x0200 /* disable quotas */
|
||||
#define Q_GETQUOTA 0x0300 /* get limits and usage */
|
||||
#define Q_SETQUOTA 0x0400 /* set limits and usage */
|
||||
#define Q_SETUSE 0x0500 /* set usage */
|
||||
#define Q_SYNC 0x0600 /* sync disk copy of a filesystems quotas */
|
||||
|
||||
/*
|
||||
* The following structure defines the format of the disk quota file
|
||||
* (as it appears on disk) - the file is an array of these structures
|
||||
* indexed by user or group number. The setquota system call establishes
|
||||
* the vnode for each quota file (a pointer is retained in the ufsmount
|
||||
* structure).
|
||||
*/
|
||||
struct dqblk {
|
||||
u_int32_t dqb_bhardlimit; /* absolute limit on disk blks alloc */
|
||||
u_int32_t dqb_bsoftlimit; /* preferred limit on disk blks */
|
||||
u_int32_t dqb_curblocks; /* current block count */
|
||||
u_int32_t dqb_ihardlimit; /* maximum # allocated inodes + 1 */
|
||||
u_int32_t dqb_isoftlimit; /* preferred inode limit */
|
||||
u_int32_t dqb_curinodes; /* current # allocated inodes */
|
||||
int32_t dqb_btime; /* time limit for excessive disk use */
|
||||
int32_t dqb_itime; /* time limit for excessive files */
|
||||
};
|
||||
|
||||
/* quota1_subr.c */
|
||||
struct quota2_entry;
|
||||
void dqblk_to_quotaval(const struct dqblk *, struct quotaval *);
|
||||
void quotaval_to_dqblk(const struct quotaval *, struct dqblk *);
|
||||
|
||||
#endif /* !_UFS_UFS_QUOTA1_H_ */
|
131
nbsd_include/ufs/ufs/quota2.h
Normal file
131
nbsd_include/ufs/ufs/quota2.h
Normal file
|
@ -0,0 +1,131 @@
|
|||
/* $NetBSD: quota2.h,v 1.5 2011/06/07 14:56:13 bouyer Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 2010 Manuel Bouyer
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _UFS_UFS_QUOTA2_H_
|
||||
#define _UFS_UFS_QUOTA2_H_
|
||||
#include <ufs/ufs/quota.h>
|
||||
#include <quota/quota.h>
|
||||
|
||||
|
||||
/* New disk quota implementation. In this implementation, the quota datas
|
||||
* (default values, user limits and current usage) are part of the filesystem
|
||||
* metadata. On FFS, this will be in a hidden, unlinked inode. fsck_ffs is
|
||||
* responsible for checking quotas with the rest of the filesystem integrity,
|
||||
* and quotas metadata are also covered by the filesystem journal if any.
|
||||
* quota enable/disable is done on a filesystem basis via flags in the
|
||||
* superblock
|
||||
*/
|
||||
|
||||
/*
|
||||
* The quota file is comprised of 2 parts, the header and the entries.
|
||||
* The header contains global informations, and head of list of quota entries.
|
||||
* A quota entry can either be in the free list, or one of the hash lists.
|
||||
*/
|
||||
|
||||
/* description of a block or inode quota */
|
||||
struct quota2_val {
|
||||
uint64_t q2v_hardlimit; /* absolute limit */
|
||||
uint64_t q2v_softlimit; /* overflowable limit */
|
||||
uint64_t q2v_cur; /* current usage */
|
||||
int64_t q2v_time; /* grace expiration date for softlimit overflow */
|
||||
int64_t q2v_grace; /* allowed time for softlimit overflow */
|
||||
};
|
||||
|
||||
/* NAMES for the above in the plist */
|
||||
#define INITQVNAMES_ALL { \
|
||||
QUOTADICT_LIMIT_HARD, \
|
||||
QUOTADICT_LIMIT_SOFT, \
|
||||
QUOTADICT_LIMIT_USAGE, \
|
||||
QUOTADICT_LIMIT_ETIME, \
|
||||
QUOTADICT_LIMIT_GTIME \
|
||||
}
|
||||
#define INITQVNAMES_LIMITSONLY { \
|
||||
QUOTADICT_LIMIT_HARD, \
|
||||
QUOTADICT_LIMIT_SOFT, \
|
||||
NULL, \
|
||||
NULL, \
|
||||
QUOTADICT_LIMIT_GTIME \
|
||||
}
|
||||
|
||||
#define N_QV 5
|
||||
/*
|
||||
* On-disk description of a user or group quota
|
||||
* These entries are keept as linked list, either in one of the hash HEAD,
|
||||
* or in the free list.
|
||||
*/
|
||||
|
||||
#define N_QL 2
|
||||
#define QL_BLOCK 0
|
||||
#define QL_FILE 1
|
||||
#define INITQLNAMES {QUOTADICT_LTYPE_BLOCK, QUOTADICT_LTYPE_FILE}
|
||||
|
||||
struct quota2_entry {
|
||||
/* block & inode limits and status */
|
||||
struct quota2_val q2e_val[N_QL];
|
||||
/* pointer to next entry for this list (offset in the file) */
|
||||
uint64_t q2e_next;
|
||||
/* ownership information */
|
||||
uint32_t q2e_uid;
|
||||
uint32_t q2e_pad;
|
||||
};
|
||||
|
||||
/* header present at the start of the quota file */
|
||||
struct quota2_header {
|
||||
uint32_t q2h_magic_number;
|
||||
uint8_t q2h_type; /* quota type, see below */
|
||||
uint8_t q2h_hash_shift; /* bytes used for hash index */
|
||||
uint16_t q2h_hash_size; /* size of hash table */
|
||||
/* default values applied to new entries */
|
||||
struct quota2_entry q2h_defentry;
|
||||
/* head of free quota2_entry list */
|
||||
uint64_t q2h_free;
|
||||
/* variable-sized hash table */
|
||||
uint64_t q2h_entries[0];
|
||||
};
|
||||
|
||||
#define Q2_HEAD_MAGIC 0xb746915e
|
||||
|
||||
/* superblock flags */
|
||||
#define FS_Q2_DO_TYPE(type) (0x01 << (type))
|
||||
|
||||
#define off2qindex(hsize, off) (((off) - (hsize)) / sizeof(struct quota2_entry))
|
||||
#define qindex2off(hsize, idx) \
|
||||
((daddr_t)(idx) * sizeof(struct quota2_entry) + (hsize))
|
||||
|
||||
/* quota2_subr.c */
|
||||
void quota2_addfreeq2e(struct quota2_header *, void *, uint64_t, uint64_t, int);
|
||||
void quota2_create_blk0(uint64_t, void *bp, int, int, int);
|
||||
void quota2_ufs_rwq2v(const struct quota2_val *, struct quota2_val *, int);
|
||||
void quota2_ufs_rwq2e(const struct quota2_entry *, struct quota2_entry *, int);
|
||||
|
||||
__inline static int __unused
|
||||
quota2_check_limit(struct quota2_val *q2v, uint64_t change, time_t now)
|
||||
{
|
||||
return quota_check_limit(q2v->q2v_cur, change, q2v->q2v_softlimit,
|
||||
q2v->q2v_hardlimit, q2v->q2v_time, now);
|
||||
}
|
||||
#endif /* _UFS_UFS_QUOTA2_H_ */
|
80
nbsd_include/ufs/ufs/ufs_bswap.h
Normal file
80
nbsd_include/ufs/ufs/ufs_bswap.h
Normal file
|
@ -0,0 +1,80 @@
|
|||
/* $NetBSD: ufs_bswap.h,v 1.19 2009/10/19 18:41:17 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Manuel Bouyer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _UFS_UFS_BSWAP_H_
|
||||
#define _UFS_UFS_BSWAP_H_
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_ffs.h"
|
||||
#endif
|
||||
|
||||
#include <sys/bswap.h>
|
||||
|
||||
/* Macros to access UFS flags */
|
||||
#ifdef FFS_EI
|
||||
#define UFS_MPNEEDSWAP(ump) ((ump)->um_flags & UFS_NEEDSWAP)
|
||||
#define UFS_FSNEEDSWAP(fs) ((fs)->fs_flags & FS_SWAPPED)
|
||||
#define UFS_IPNEEDSWAP(ip) UFS_MPNEEDSWAP((ip)->i_ump)
|
||||
#else
|
||||
#define UFS_MPNEEDSWAP(ump) (0)
|
||||
#define UFS_FSNEEDSWAP(fs) (0)
|
||||
#define UFS_IPNEEDSWAP(ip) (0)
|
||||
#endif
|
||||
|
||||
#if !defined(_KERNEL) || defined(FFS_EI)
|
||||
/* inlines for access to swapped data */
|
||||
static inline u_int16_t
|
||||
ufs_rw16(uint16_t a, int ns)
|
||||
{
|
||||
return ((ns) ? bswap16(a) : (a));
|
||||
}
|
||||
|
||||
static inline u_int32_t
|
||||
ufs_rw32(uint32_t a, int ns)
|
||||
{
|
||||
return ((ns) ? bswap32(a) : (a));
|
||||
}
|
||||
|
||||
static inline u_int64_t
|
||||
ufs_rw64(uint64_t a, int ns)
|
||||
{
|
||||
return ((ns) ? bswap64(a) : (a));
|
||||
}
|
||||
#else
|
||||
#define ufs_rw16(a, ns) ((uint16_t)(a))
|
||||
#define ufs_rw32(a, ns) ((uint32_t)(a))
|
||||
#define ufs_rw64(a, ns) ((uint64_t)(a))
|
||||
#endif
|
||||
|
||||
#define ufs_add16(a, b, ns) \
|
||||
(a) = ufs_rw16(ufs_rw16((a), (ns)) + (b), (ns))
|
||||
#define ufs_add32(a, b, ns) \
|
||||
(a) = ufs_rw32(ufs_rw32((a), (ns)) + (b), (ns))
|
||||
#define ufs_add64(a, b, ns) \
|
||||
(a) = ufs_rw64(ufs_rw64((a), (ns)) + (b), (ns))
|
||||
|
||||
#endif /* !_UFS_UFS_BSWAP_H_ */
|
188
nbsd_include/ufs/ufs/ufs_extern.h
Normal file
188
nbsd_include/ufs/ufs/ufs_extern.h
Normal file
|
@ -0,0 +1,188 @@
|
|||
/* $NetBSD: ufs_extern.h,v 1.66 2011/07/17 22:07:59 dholland Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ufs_extern.h 8.10 (Berkeley) 5/14/95
|
||||
*/
|
||||
|
||||
#ifndef _UFS_UFS_EXTERN_H_
|
||||
#define _UFS_UFS_EXTERN_H_
|
||||
|
||||
#include <sys/mutex.h>
|
||||
|
||||
struct buf;
|
||||
struct componentname;
|
||||
struct direct;
|
||||
struct disklabel;
|
||||
struct dquot;
|
||||
struct fid;
|
||||
struct flock;
|
||||
struct indir;
|
||||
struct inode;
|
||||
struct mbuf;
|
||||
struct mount;
|
||||
struct nameidata;
|
||||
struct lwp;
|
||||
struct ufid;
|
||||
struct ufs_args;
|
||||
struct ufs_lookup_results;
|
||||
struct ufsmount;
|
||||
struct uio;
|
||||
struct vattr;
|
||||
struct vnode;
|
||||
|
||||
extern pool_cache_t ufs_direct_cache; /* memory pool for directs */
|
||||
|
||||
__BEGIN_DECLS
|
||||
#define ufs_abortop genfs_abortop
|
||||
int ufs_access(void *);
|
||||
int ufs_advlock(void *);
|
||||
int ufs_bmap(void *);
|
||||
int ufs_close(void *);
|
||||
int ufs_create(void *);
|
||||
int ufs_getattr(void *);
|
||||
int ufs_inactive(void *);
|
||||
#define ufs_fcntl genfs_fcntl
|
||||
#define ufs_ioctl genfs_enoioctl
|
||||
#define ufs_islocked genfs_islocked
|
||||
int ufs_link(void *);
|
||||
#define ufs_lock genfs_lock
|
||||
int ufs_lookup(void *);
|
||||
int ufs_mkdir(void *);
|
||||
int ufs_mknod(void *);
|
||||
#define ufs_mmap genfs_mmap
|
||||
#define ufs_revoke genfs_revoke
|
||||
int ufs_open(void *);
|
||||
int ufs_pathconf(void *);
|
||||
int ufs_print(void *);
|
||||
int ufs_readdir(void *);
|
||||
int ufs_readlink(void *);
|
||||
int ufs_remove(void *);
|
||||
int ufs_rename(void *);
|
||||
int ufs_rmdir(void *);
|
||||
#define ufs_seek genfs_seek
|
||||
#define ufs_poll genfs_poll
|
||||
int ufs_setattr(void *);
|
||||
int ufs_strategy(void *);
|
||||
int ufs_symlink(void *);
|
||||
#define ufs_unlock genfs_unlock
|
||||
int ufs_whiteout(void *);
|
||||
int ufsspec_close(void *);
|
||||
int ufsspec_read(void *);
|
||||
int ufsspec_write(void *);
|
||||
|
||||
int ufsfifo_read(void *);
|
||||
int ufsfifo_write(void *);
|
||||
int ufsfifo_close(void *);
|
||||
|
||||
/* ufs_bmap.c */
|
||||
typedef bool (*ufs_issequential_callback_t)(const struct ufsmount *,
|
||||
daddr_t, daddr_t);
|
||||
int ufs_bmaparray(struct vnode *, daddr_t, daddr_t *, struct indir *,
|
||||
int *, int *, ufs_issequential_callback_t);
|
||||
int ufs_getlbns(struct vnode *, daddr_t, struct indir *, int *);
|
||||
|
||||
/* ufs_ihash.c */
|
||||
void ufs_ihashinit(void);
|
||||
void ufs_ihashreinit(void);
|
||||
void ufs_ihashdone(void);
|
||||
struct vnode *ufs_ihashlookup(dev_t, ino_t);
|
||||
struct vnode *ufs_ihashget(dev_t, ino_t, int);
|
||||
void ufs_ihashins(struct inode *);
|
||||
void ufs_ihashrem(struct inode *);
|
||||
|
||||
/* ufs_inode.c */
|
||||
int ufs_reclaim(struct vnode *);
|
||||
int ufs_balloc_range(struct vnode *, off_t, off_t, kauth_cred_t, int);
|
||||
|
||||
/* ufs_lookup.c */
|
||||
void ufs_dirbad(struct inode *, doff_t, const char *);
|
||||
int ufs_dirbadentry(struct vnode *, struct direct *, int);
|
||||
void ufs_makedirentry(struct inode *, struct componentname *,
|
||||
struct direct *);
|
||||
int ufs_direnter(struct vnode *, const struct ufs_lookup_results *,
|
||||
struct vnode *, struct direct *,
|
||||
struct componentname *, struct buf *);
|
||||
int ufs_dirremove(struct vnode *, const struct ufs_lookup_results *,
|
||||
struct inode *, int, int);
|
||||
int ufs_dirrewrite(struct inode *, off_t,
|
||||
struct inode *, ino_t, int, int, int);
|
||||
int ufs_dirempty(struct inode *, ino_t, kauth_cred_t);
|
||||
int ufs_checkpath(struct inode *, struct inode *, kauth_cred_t);
|
||||
int ufs_parentcheck(struct vnode *, struct vnode *, kauth_cred_t,
|
||||
int *, struct vnode **);
|
||||
int ufs_blkatoff(struct vnode *, off_t, char **, struct buf **, bool);
|
||||
|
||||
/* ufs_quota.c */
|
||||
/*
|
||||
* Flags to chkdq() and chkiq()
|
||||
*/
|
||||
#define FORCE 0x01 /* force usage changes independent of limits */
|
||||
void ufsquota_init(struct inode *);
|
||||
void ufsquota_free(struct inode *);
|
||||
int chkdq(struct inode *, int64_t, kauth_cred_t, int);
|
||||
int chkiq(struct inode *, int32_t, kauth_cred_t, int);
|
||||
int quota_handle_cmd(struct mount *, struct lwp *, prop_dictionary_t);
|
||||
int qsync(struct mount *);
|
||||
|
||||
/* ufs_quota1.c */
|
||||
int quota1_umount(struct mount *, int);
|
||||
|
||||
/* ufs_quota2.c */
|
||||
int quota2_umount(struct mount *, int);
|
||||
|
||||
/* ufs_vfsops.c */
|
||||
void ufs_init(void);
|
||||
void ufs_reinit(void);
|
||||
void ufs_done(void);
|
||||
int ufs_start(struct mount *, int);
|
||||
int ufs_root(struct mount *, struct vnode **);
|
||||
int ufs_quotactl(struct mount *, prop_dictionary_t);
|
||||
int ufs_fhtovp(struct mount *, struct ufid *, struct vnode **);
|
||||
|
||||
/* ufs_vnops.c */
|
||||
void ufs_vinit(struct mount *, int (**)(void *),
|
||||
int (**)(void *), struct vnode **);
|
||||
int ufs_makeinode(int, struct vnode *, const struct ufs_lookup_results *,
|
||||
struct vnode **, struct componentname *);
|
||||
int ufs_gop_alloc(struct vnode *, off_t, off_t, int, kauth_cred_t);
|
||||
void ufs_gop_markupdate(struct vnode *, int);
|
||||
|
||||
/*
|
||||
* Snapshot function prototypes.
|
||||
*/
|
||||
|
||||
void ffs_snapgone(struct inode *);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
extern kmutex_t ufs_ihash_lock;
|
||||
extern kmutex_t ufs_hashlock;
|
||||
|
||||
#endif /* !_UFS_UFS_EXTERN_H_ */
|
130
nbsd_include/ufs/ufs/ufs_quota.h
Normal file
130
nbsd_include/ufs/ufs/ufs_quota.h
Normal file
|
@ -0,0 +1,130 @@
|
|||
/* $NetBSD: ufs_quota.h,v 1.2 2011/03/06 17:08:39 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1990, 1993, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Robert Elz at The University of Melbourne.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95
|
||||
*/
|
||||
#include <ufs/ufs/quota1.h>
|
||||
#include <ufs/ufs/quota2.h>
|
||||
|
||||
/* link to this quota in the quota inode (for QUOTA2) */
|
||||
struct dq2_desc {
|
||||
uint64_t dq2_lblkno; /* logical disk block holding this quota */
|
||||
u_int dq2_blkoff; /* offset in disk block holding this quota */
|
||||
};
|
||||
|
||||
/*
|
||||
* The following structure records disk usage for a user or group on a
|
||||
* filesystem. There is one allocated for each quota that exists on any
|
||||
* filesystem for the current user or group. A cache is kept of recently
|
||||
* used entries.
|
||||
* Field markings and the corresponding locks:
|
||||
* h: dqlock
|
||||
* d: dq_interlock
|
||||
*
|
||||
* Lock order is: dq_interlock -> dqlock
|
||||
* dq_interlock -> dqvp
|
||||
*/
|
||||
struct dquot {
|
||||
LIST_ENTRY(dquot) dq_hash; /* h: hash list */
|
||||
u_int16_t dq_flags; /* d: flags, see below */
|
||||
u_int16_t dq_type; /* d: quota type of this dquot */
|
||||
u_int32_t dq_cnt; /* h: count of active references */
|
||||
u_int32_t dq_id; /* d: identifier this applies to */
|
||||
struct ufsmount *dq_ump; /* d: filesystem this is taken from */
|
||||
kmutex_t dq_interlock; /* d: lock this dquot */
|
||||
union {
|
||||
struct dqblk dq1_dqb; /* d: actual usage & quotas */
|
||||
struct dq2_desc dq2_desc; /* d: pointer to quota data */
|
||||
} dq_un;
|
||||
};
|
||||
|
||||
/*
|
||||
* Flag values.
|
||||
*/
|
||||
#define DQ_MOD 0x04 /* this quota modified since read */
|
||||
#define DQ_FAKE 0x08 /* no limits here, just usage */
|
||||
#define DQ_WARN(ltype) (0x10 << ltype) /* has been warned about "type" limit */
|
||||
/*
|
||||
* Shorthand notation.
|
||||
*/
|
||||
#define dq_bhardlimit dq_un.dq1_dqb.dqb_bhardlimit
|
||||
#define dq_bsoftlimit dq_un.dq1_dqb.dqb_bsoftlimit
|
||||
#define dq_curblocks dq_un.dq1_dqb.dqb_curblocks
|
||||
#define dq_ihardlimit dq_un.dq1_dqb.dqb_ihardlimit
|
||||
#define dq_isoftlimit dq_un.dq1_dqb.dqb_isoftlimit
|
||||
#define dq_curinodes dq_un.dq1_dqb.dqb_curinodes
|
||||
#define dq_btime dq_un.dq1_dqb.dqb_btime
|
||||
#define dq_itime dq_un.dq1_dqb.dqb_itime
|
||||
|
||||
#define dq2_lblkno dq_un.dq2_desc.dq2_lblkno
|
||||
#define dq2_blkoff dq_un.dq2_desc.dq2_blkoff
|
||||
/*
|
||||
* If the system has never checked for a quota for this file, then it is
|
||||
* set to NODQUOT. Once a write attempt is made the inode pointer is set
|
||||
* to reference a dquot structure.
|
||||
*/
|
||||
#define NODQUOT NULL
|
||||
|
||||
extern kmutex_t dqlock;
|
||||
extern kcondvar_t dqcv;
|
||||
/*
|
||||
* Quota name to error message mapping.
|
||||
*/
|
||||
const char *quotatypes[MAXQUOTAS];
|
||||
|
||||
int getinoquota(struct inode *);
|
||||
int dqget(struct vnode *, u_long, struct ufsmount *, int, struct dquot **);
|
||||
void dqref(struct dquot *);
|
||||
void dqrele(struct vnode *, struct dquot *);
|
||||
void dqflush(struct vnode *);
|
||||
|
||||
int chkdq1(struct inode *, int64_t, kauth_cred_t, int);
|
||||
int chkiq1(struct inode *, int32_t, kauth_cred_t, int);
|
||||
int q1sync(struct mount *);
|
||||
int dq1get(struct vnode *, u_long, struct ufsmount *, int, struct dquot *);
|
||||
int dq1sync(struct vnode *, struct dquot *);
|
||||
int quota1_handle_cmd_get(struct ufsmount *, int, int, int, prop_array_t);
|
||||
int quota1_handle_cmd_set(struct ufsmount *, int, int, int, prop_dictionary_t);
|
||||
int quota1_handle_cmd_quotaon(struct lwp *, struct ufsmount *, int,
|
||||
const char *);
|
||||
int quota1_handle_cmd_quotaoff(struct lwp *, struct ufsmount *, int);
|
||||
|
||||
int chkdq2(struct inode *, int64_t, kauth_cred_t, int);
|
||||
int chkiq2(struct inode *, int32_t, kauth_cred_t, int);
|
||||
int quota2_handle_cmd_get(struct ufsmount *, int, int, int, prop_array_t);
|
||||
int quota2_handle_cmd_set(struct ufsmount *, int, int, int, prop_dictionary_t);
|
||||
int quota2_handle_cmd_clear(struct ufsmount *, int, int, int, prop_dictionary_t);
|
||||
int quota2_handle_cmd_getall(struct ufsmount *, int, prop_array_t);
|
||||
int q2sync(struct mount *);
|
||||
int dq2get(struct vnode *, u_long, struct ufsmount *, int, struct dquot *);
|
||||
int dq2sync(struct vnode *, struct dquot *);
|
178
nbsd_include/ufs/ufs/ufs_wapbl.h
Normal file
178
nbsd_include/ufs/ufs/ufs_wapbl.h
Normal file
|
@ -0,0 +1,178 @@
|
|||
/* $NetBSD: ufs_wapbl.h,v 1.7 2011/09/19 11:18:01 gdt Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003,2006,2008 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Wasabi Systems, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _UFS_UFS_UFS_WAPBL_H_
|
||||
#define _UFS_UFS_UFS_WAPBL_H_
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_wapbl.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Information for the journal location stored in the superblock.
|
||||
* We store the journal version, some flags, the journal location
|
||||
* type, and some location specific "locators" that identify where
|
||||
* the log itself is located.
|
||||
*/
|
||||
|
||||
/* fs->fs_journal_version */
|
||||
#define UFS_WAPBL_VERSION 1
|
||||
|
||||
/* fs->fs_journal_location */
|
||||
#define UFS_WAPBL_JOURNALLOC_NONE 0
|
||||
|
||||
#define UFS_WAPBL_JOURNALLOC_END_PARTITION 1
|
||||
#define UFS_WAPBL_EPART_ADDR 0 /* locator slots */
|
||||
#define UFS_WAPBL_EPART_COUNT 1
|
||||
#define UFS_WAPBL_EPART_BLKSZ 2
|
||||
#define UFS_WAPBL_EPART_UNUSED 3
|
||||
|
||||
#define UFS_WAPBL_JOURNALLOC_IN_FILESYSTEM 2
|
||||
#define UFS_WAPBL_INFS_ADDR 0 /* locator slots */
|
||||
#define UFS_WAPBL_INFS_COUNT 1
|
||||
#define UFS_WAPBL_INFS_BLKSZ 2
|
||||
#define UFS_WAPBL_INFS_INO 3
|
||||
|
||||
/* fs->fs_journal_flags */
|
||||
#define UFS_WAPBL_FLAGS_CREATE_LOG 0x1
|
||||
#define UFS_WAPBL_FLAGS_CLEAR_LOG 0x2
|
||||
|
||||
|
||||
/*
|
||||
* The journal size is limited to between 1MB and 64MB.
|
||||
* The default journal size is the filesystem size divided by
|
||||
* the scale factor - this is 1M of journal per 1GB of filesystem
|
||||
* space.
|
||||
*
|
||||
* XXX: Is 64MB too limiting? If user explicitly asks for more, allow it?
|
||||
*/
|
||||
#define UFS_WAPBL_JOURNAL_SCALE 1024
|
||||
#define UFS_WAPBL_MIN_JOURNAL_SIZE (1024 * 1024)
|
||||
#define UFS_WAPBL_MAX_JOURNAL_SIZE (64 * 1024 * 1024)
|
||||
|
||||
|
||||
#if defined(WAPBL)
|
||||
|
||||
#if defined(WAPBL_DEBUG)
|
||||
#define WAPBL_DEBUG_INODES
|
||||
#endif
|
||||
|
||||
#ifdef WAPBL_DEBUG_INODES
|
||||
#error Undefine WAPBL_DEBUG_INODES or update the code. Have a nice day.
|
||||
#endif
|
||||
|
||||
#ifdef WAPBL_DEBUG_INODES
|
||||
void ufs_wapbl_verify_inodes(struct mount *, const char *);
|
||||
#endif
|
||||
|
||||
static __inline int
|
||||
ufs_wapbl_begin2(struct mount *mp, struct vnode *vp1, struct vnode *vp2,
|
||||
const char *file, int line)
|
||||
{
|
||||
if (mp->mnt_wapbl) {
|
||||
int error;
|
||||
|
||||
if (vp1)
|
||||
vref(vp1);
|
||||
if (vp2)
|
||||
vref(vp2);
|
||||
error = wapbl_begin(mp->mnt_wapbl, file, line);
|
||||
if (error)
|
||||
return error;
|
||||
#ifdef WAPBL_DEBUG_INODES
|
||||
if (mp->mnt_wapbl->wl_lock.lk_exclusivecount == 1)
|
||||
ufs_wapbl_verify_inodes(mp, "wapbl_begin");
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
ufs_wapbl_end2(struct mount *mp, struct vnode *vp1, struct vnode *vp2)
|
||||
{
|
||||
if (mp->mnt_wapbl) {
|
||||
#ifdef WAPBL_DEBUG_INODES
|
||||
if (mp->mnt_wapbl->wl_lock.lk_exclusivecount == 1)
|
||||
ufs_wapbl_verify_inodes(mp, "wapbl_end");
|
||||
#endif
|
||||
wapbl_end(mp->mnt_wapbl);
|
||||
if (vp2)
|
||||
vrele(vp2);
|
||||
if (vp1)
|
||||
vrele(vp1);
|
||||
}
|
||||
}
|
||||
|
||||
#define UFS_WAPBL_BEGIN(mp) \
|
||||
ufs_wapbl_begin2(mp, NULL, NULL, __FUNCTION__, __LINE__)
|
||||
#define UFS_WAPBL_BEGIN1(mp, v1) \
|
||||
ufs_wapbl_begin2(mp, v1, NULL, __FUNCTION__, __LINE__)
|
||||
#define UFS_WAPBL_END(mp) ufs_wapbl_end2(mp, NULL, NULL)
|
||||
#define UFS_WAPBL_END1(mp, v1) ufs_wapbl_end2(mp, v1, NULL)
|
||||
|
||||
#define UFS_WAPBL_UPDATE(vp, access, modify, flags) \
|
||||
if ((vp)->v_mount->mnt_wapbl) { \
|
||||
UFS_UPDATE(vp, access, modify, flags); \
|
||||
}
|
||||
|
||||
#ifdef UFS_WAPBL_DEBUG_JLOCK
|
||||
#define UFS_WAPBL_JLOCK_ASSERT(mp) \
|
||||
if (mp->mnt_wapbl) wapbl_jlock_assert(mp->mnt_wapbl)
|
||||
#define UFS_WAPBL_JUNLOCK_ASSERT(mp) \
|
||||
if (mp->mnt_wapbl) wapbl_junlock_assert(mp->mnt_wapbl)
|
||||
#else
|
||||
#define UFS_WAPBL_JLOCK_ASSERT(mp)
|
||||
#define UFS_WAPBL_JUNLOCK_ASSERT(mp)
|
||||
#endif
|
||||
|
||||
#define UFS_WAPBL_REGISTER_INODE(mp, ino, mode) \
|
||||
if (mp->mnt_wapbl) wapbl_register_inode(mp->mnt_wapbl, ino, mode)
|
||||
#define UFS_WAPBL_UNREGISTER_INODE(mp, ino, mode) \
|
||||
if (mp->mnt_wapbl) wapbl_unregister_inode(mp->mnt_wapbl, ino, mode)
|
||||
|
||||
#define UFS_WAPBL_REGISTER_DEALLOCATION(mp, blk, len) \
|
||||
if (mp->mnt_wapbl) wapbl_register_deallocation(mp->mnt_wapbl, blk, len)
|
||||
|
||||
#else /* ! WAPBL */
|
||||
#define UFS_WAPBL_BEGIN(mp) 0
|
||||
#define UFS_WAPBL_BEGIN1(mp, v1) 0
|
||||
#define UFS_WAPBL_END(mp) do { } while (0)
|
||||
#define UFS_WAPBL_END1(mp, v1)
|
||||
#define UFS_WAPBL_UPDATE(vp, access, modify, flags) do { } while (0)
|
||||
#define UFS_WAPBL_JLOCK_ASSERT(mp)
|
||||
#define UFS_WAPBL_JUNLOCK_ASSERT(mp)
|
||||
#define UFS_WAPBL_REGISTER_INODE(mp, ino, mode) do { } while (0)
|
||||
#define UFS_WAPBL_UNREGISTER_INODE(mp, ino, mode) do { } while (0)
|
||||
#define UFS_WAPBL_REGISTER_DEALLOCATION(mp, blk, len)
|
||||
#endif
|
||||
|
||||
#endif /* !_UFS_UFS_UFS_WAPBL_H_ */
|
197
nbsd_include/ufs/ufs/ufsmount.h
Normal file
197
nbsd_include/ufs/ufs/ufsmount.h
Normal file
|
@ -0,0 +1,197 @@
|
|||
/* $NetBSD: ufsmount.h,v 1.37 2011/11/24 15:51:32 ahoka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ufsmount.h 8.6 (Berkeley) 3/30/95
|
||||
*/
|
||||
|
||||
#ifndef _UFS_UFS_UFSMOUNT_H_
|
||||
#define _UFS_UFS_UFSMOUNT_H_
|
||||
|
||||
#include <sys/mount.h> /* struct export_args30 */
|
||||
|
||||
/*
|
||||
* Arguments to mount UFS-based filesystems
|
||||
*/
|
||||
struct ufs_args {
|
||||
char *fspec; /* block special device to mount */
|
||||
};
|
||||
|
||||
#ifndef __minix
|
||||
/*
|
||||
* Arguments to mount MFS
|
||||
*/
|
||||
struct mfs_args {
|
||||
char *fspec; /* name to export for statfs */
|
||||
struct export_args30 _pad1; /* compat with old userland tools */
|
||||
void * base; /* base of file system in memory */
|
||||
u_long size; /* size of file system */
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_ffs.h"
|
||||
#endif
|
||||
|
||||
#include <sys/mutex.h>
|
||||
|
||||
#include <ufs/ufs/extattr.h>
|
||||
#include <ufs/ufs/quota.h>
|
||||
|
||||
struct buf;
|
||||
struct inode;
|
||||
struct nameidata;
|
||||
struct timeval;
|
||||
struct uio;
|
||||
struct vnode;
|
||||
|
||||
/* This structure describes the UFS specific mount structure data. */
|
||||
struct ufsmount {
|
||||
struct mount *um_mountp; /* filesystem vfs structure */
|
||||
dev_t um_dev; /* device mounted */
|
||||
struct vnode *um_devvp; /* block device mounted vnode */
|
||||
u_long um_fstype;
|
||||
u_int32_t um_flags; /* UFS-specific flags - see below */
|
||||
union { /* pointer to superblock */
|
||||
struct fs *fs; /* FFS */
|
||||
struct lfs *lfs; /* LFS */
|
||||
struct m_ext2fs *e2fs; /* EXT2FS */
|
||||
struct chfs_mount *chfs; /* CHFS */
|
||||
} ufsmount_u;
|
||||
#define um_fs ufsmount_u.fs
|
||||
#define um_lfs ufsmount_u.lfs
|
||||
#define um_e2fs ufsmount_u.e2fs
|
||||
#define um_e2fsb ufsmount_u.e2fs->s_es
|
||||
#define um_chfs ufsmount_u.chfs
|
||||
|
||||
/* Extended attribute information. */
|
||||
struct ufs_extattr_per_mount um_extattr;
|
||||
|
||||
struct vnode *um_quotas[MAXQUOTAS]; /* pointer to quota files */
|
||||
kauth_cred_t um_cred[MAXQUOTAS]; /* quota file access cred */
|
||||
u_long um_nindir; /* indirect ptrs per block */
|
||||
u_long um_lognindir; /* log2 of um_nindir */
|
||||
u_long um_bptrtodb; /* indir ptr to disk block */
|
||||
u_long um_seqinc; /* inc between seq blocks */
|
||||
kmutex_t um_lock; /* lock on global data */
|
||||
union {
|
||||
struct um_q1 {
|
||||
time_t q1_btime[MAXQUOTAS]; /* block quota time limit */
|
||||
time_t q1_itime[MAXQUOTAS]; /* inode quota time limit */
|
||||
char q1_qflags[MAXQUOTAS]; /* quota specific flags */
|
||||
} um_q1;
|
||||
struct um_q2 {
|
||||
uint64_t q2_bsize; /* block size of quota file */
|
||||
uint64_t q2_bmask; /* mask for above */
|
||||
} um_q2;
|
||||
} um_q;
|
||||
#define umq1_btime um_q.um_q1.q1_btime
|
||||
#define umq1_itime um_q.um_q1.q1_itime
|
||||
#define umq1_qflags um_q.um_q1.q1_qflags
|
||||
#define umq2_bsize um_q.um_q2.q2_bsize
|
||||
#define umq2_bmask um_q.um_q2.q2_bmask
|
||||
|
||||
void *um_oldfscompat; /* save 4.2 rotbl */
|
||||
int um_maxsymlinklen;
|
||||
int um_dirblksiz;
|
||||
u_int64_t um_maxfilesize;
|
||||
void *um_snapinfo; /* snapshot private data */
|
||||
|
||||
const struct ufs_ops *um_ops;
|
||||
};
|
||||
|
||||
struct ufs_ops {
|
||||
void (*uo_itimes)(struct inode *ip, const struct timespec *,
|
||||
const struct timespec *, const struct timespec *);
|
||||
int (*uo_update)(struct vnode *, const struct timespec *,
|
||||
const struct timespec *, int);
|
||||
int (*uo_truncate)(struct vnode *, off_t, int, kauth_cred_t);
|
||||
int (*uo_valloc)(struct vnode *, int, kauth_cred_t, struct vnode **);
|
||||
int (*uo_vfree)(struct vnode *, ino_t, int);
|
||||
int (*uo_balloc)(struct vnode *, off_t, int, kauth_cred_t, int,
|
||||
struct buf **);
|
||||
void (*uo_unmark_vnode)(struct vnode *);
|
||||
};
|
||||
|
||||
#define UFS_OPS(vp) (VFSTOUFS((vp)->v_mount)->um_ops)
|
||||
|
||||
#define UFS_ITIMES(vp, acc, mod, cre) \
|
||||
(*UFS_OPS(vp)->uo_itimes)(VTOI(vp), (acc), (mod), (cre))
|
||||
#define UFS_UPDATE(vp, acc, mod, flags) \
|
||||
(*UFS_OPS(vp)->uo_update)((vp), (acc), (mod), (flags))
|
||||
#define UFS_TRUNCATE(vp, off, flags, cr) \
|
||||
(*UFS_OPS(vp)->uo_truncate)((vp), (off), (flags), (cr))
|
||||
#define UFS_VALLOC(vp, mode, cr, vpp) \
|
||||
(*UFS_OPS(vp)->uo_valloc)((vp), (mode), (cr), (vpp))
|
||||
#define UFS_VFREE(vp, ino, mode) \
|
||||
(*UFS_OPS(vp)->uo_vfree)((vp), (ino), (mode))
|
||||
#define UFS_BALLOC(vp, off, size, cr, flags, bpp) \
|
||||
(*UFS_OPS(vp)->uo_balloc)((vp), (off), (size), (cr), (flags), (bpp))
|
||||
#define UFS_UNMARK_VNODE(vp) \
|
||||
(*UFS_OPS(vp)->uo_unmark_vnode)((vp))
|
||||
|
||||
/* UFS-specific flags */
|
||||
#define UFS_NEEDSWAP 0x01 /* filesystem metadata need byte-swapping */
|
||||
#define UFS_ISAPPLEUFS 0x02 /* filesystem is Apple UFS */
|
||||
#define UFS_QUOTA 0x04 /* filesystem has QUOTA (v1) */
|
||||
#define UFS_QUOTA2 0x08 /* filesystem has QUOTA2 */
|
||||
|
||||
/*
|
||||
* Filesystem types
|
||||
*/
|
||||
#define UFS1 1
|
||||
#define UFS2 2
|
||||
|
||||
|
||||
/*
|
||||
* Flags describing the state of quotas.
|
||||
*/
|
||||
#define QTF_OPENING 0x01 /* Q_QUOTAON in progress */
|
||||
#define QTF_CLOSING 0x02 /* Q_QUOTAOFF in progress */
|
||||
|
||||
/* Convert mount ptr to ufsmount ptr. */
|
||||
#define VFSTOUFS(mp) ((struct ufsmount *)((mp)->mnt_data))
|
||||
|
||||
#ifdef APPLE_UFS
|
||||
#define UFS_MPISAPPLEUFS(ump) ((ump)->um_flags & UFS_ISAPPLEUFS)
|
||||
#else
|
||||
#define UFS_MPISAPPLEUFS(ump) (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Macros to access file system parameters in the ufsmount structure.
|
||||
* Used by ufs_bmap.
|
||||
*/
|
||||
#define MNINDIR(ump) ((ump)->um_nindir)
|
||||
#define blkptrtodb(ump, b) ((b) << (ump)->um_bptrtodb)
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* !_UFS_UFS_UFSMOUNT_H_ */
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
SUBDIR= fsck
|
||||
SUBDIR= fsck fsck_ext2fs newfs_ext2fs
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
|
|
@ -183,6 +183,11 @@ main(int argc, char *argv[])
|
|||
if (flags & CHECK_PROGRESS)
|
||||
maxrun = 1;
|
||||
|
||||
#ifdef __minix
|
||||
/* parallel checking heuristic doesn't work for minix currently */
|
||||
maxrun = 1;
|
||||
#endif
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
|
@ -552,6 +557,9 @@ mangle(char *opts, int *argcp, const char ** volatile *argvp, int *maxargcp)
|
|||
static const char *
|
||||
getfslab(const char *str)
|
||||
{
|
||||
#ifdef __minix
|
||||
errx(1, "cannot determine vfstype under minix");
|
||||
#else
|
||||
static struct dkwedge_info dkw;
|
||||
struct disklabel dl;
|
||||
int fd;
|
||||
|
@ -589,6 +597,7 @@ getfslab(const char *str)
|
|||
fstypenames[t], str);
|
||||
|
||||
return vfstype;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -92,6 +92,9 @@ dict2geom(struct disk_geom *geo, prop_dictionary_t dict)
|
|||
static void
|
||||
part2wedge(struct dkwedge_info *dkw, const struct disklabel *lp, const char *s)
|
||||
{
|
||||
#ifdef __minix
|
||||
errx(1, "minix doesn't know about wedges");
|
||||
#else
|
||||
struct stat sb;
|
||||
const struct partition *pp;
|
||||
int ptn;
|
||||
|
@ -150,6 +153,7 @@ part2wedge(struct dkwedge_info *dkw, const struct disklabel *lp, const char *s)
|
|||
(void)strcpy(dkw->dkw_ptype, DKW_PTYPE_NTFS);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
|
|
19
sbin/fsck_ext2fs/Makefile
Normal file
19
sbin/fsck_ext2fs/Makefile
Normal file
|
@ -0,0 +1,19 @@
|
|||
# $NetBSD: Makefile,v 1.16 2011/08/06 16:42:41 dholland Exp $
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/5/93
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
PROG= fsck_ext2fs
|
||||
MAN= fsck_ext2fs.8
|
||||
SRCS= dir.c inode.c main.c pass1.c pass1b.c pass2.c pass3.c pass4.c \
|
||||
pass5.c fsutil.c setup.c utilities.c ext2fs_bswap.c
|
||||
FSCK= ${NETBSDSRCDIR}/sbin/fsck
|
||||
CPPFLAGS+= -I${FSCK}
|
||||
.PATH: -I/usr/nbsdsrc/src/sys/ufs/ext2fs ${FSCK}
|
||||
|
||||
SYMLINKS+= $(BINDIR)/$(PROG) $(BINDIR)/fsck.ext2
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
||||
LDADD+=-lutil
|
||||
DPADD+=${LIBUTIL}
|
723
sbin/fsck_ext2fs/dir.c
Normal file
723
sbin/fsck_ext2fs/dir.c
Normal file
|
@ -0,0 +1,723 @@
|
|||
/* $NetBSD: dir.c,v 1.23 2009/10/19 18:41:07 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1980, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Manuel Bouyer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)dir.c 8.5 (Berkeley) 12/8/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: dir.c,v 1.23 2009/10/19 18:41:07 bouyer Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <ufs/ufs/dir.h>
|
||||
#include <ufs/ext2fs/ext2fs_dinode.h>
|
||||
#include <ufs/ext2fs/ext2fs_dir.h>
|
||||
#include <ufs/ext2fs/ext2fs.h>
|
||||
|
||||
#include <ufs/ufs/dinode.h> /* for IFMT & friends */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <err.h>
|
||||
|
||||
#include "fsck.h"
|
||||
#include "fsutil.h"
|
||||
#include "extern.h"
|
||||
|
||||
const char *lfname = "lost+found";
|
||||
int lfmode = 01700;
|
||||
struct ext2fs_dirtemplate emptydir = {
|
||||
.dot_ino = 0,
|
||||
.dot_reclen = DIRBLKSIZ,
|
||||
};
|
||||
struct ext2fs_dirtemplate dirhead = {
|
||||
.dot_ino = 0,
|
||||
.dot_reclen = 12,
|
||||
.dot_namlen = 1,
|
||||
.dot_type = EXT2_FT_DIR,
|
||||
.dot_name = ".",
|
||||
.dotdot_ino = 0,
|
||||
.dotdot_reclen = DIRBLKSIZ - 12,
|
||||
.dotdot_namlen = 2,
|
||||
.dotdot_type = EXT2_FT_DIR,
|
||||
.dotdot_name = "..",
|
||||
};
|
||||
#undef DIRBLKSIZ
|
||||
|
||||
static int expanddir(struct ext2fs_dinode *, char *);
|
||||
static void freedir(ino_t, ino_t);
|
||||
static struct ext2fs_direct *fsck_readdir(struct inodesc *);
|
||||
static struct bufarea *getdirblk(daddr_t, long);
|
||||
static int lftempname(char *, ino_t);
|
||||
static int mkentry(struct inodesc *);
|
||||
static int chgino(struct inodesc *);
|
||||
|
||||
/*
|
||||
* Propagate connected state through the tree.
|
||||
*/
|
||||
void
|
||||
propagate(void)
|
||||
{
|
||||
struct inoinfo **inpp, *inp, *pinp;
|
||||
struct inoinfo **inpend;
|
||||
|
||||
/*
|
||||
* Create a list of children for each directory.
|
||||
*/
|
||||
inpend = &inpsort[inplast];
|
||||
for (inpp = inpsort; inpp < inpend; inpp++) {
|
||||
inp = *inpp;
|
||||
if (inp->i_parent == 0 ||
|
||||
inp->i_number == EXT2_ROOTINO)
|
||||
continue;
|
||||
pinp = getinoinfo(inp->i_parent);
|
||||
inp->i_parentp = pinp;
|
||||
inp->i_sibling = pinp->i_child;
|
||||
pinp->i_child = inp;
|
||||
}
|
||||
inp = getinoinfo(EXT2_ROOTINO);
|
||||
while (inp) {
|
||||
statemap[inp->i_number] = DFOUND;
|
||||
if (inp->i_child &&
|
||||
statemap[inp->i_child->i_number] == DSTATE)
|
||||
inp = inp->i_child;
|
||||
else if (inp->i_sibling)
|
||||
inp = inp->i_sibling;
|
||||
else
|
||||
inp = inp->i_parentp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan each entry in a directory block.
|
||||
*/
|
||||
int
|
||||
dirscan(struct inodesc *idesc)
|
||||
{
|
||||
struct ext2fs_direct *dp;
|
||||
struct bufarea *bp;
|
||||
int dsize, n;
|
||||
long blksiz;
|
||||
char *dbuf = NULL;
|
||||
|
||||
if ((dbuf = malloc(sblock.e2fs_bsize)) == NULL)
|
||||
err(8, "Can't allocate directory block");
|
||||
|
||||
if (idesc->id_type != DATA)
|
||||
errexit("wrong type to dirscan %d", idesc->id_type);
|
||||
if (idesc->id_entryno == 0 &&
|
||||
(idesc->id_filesize & (sblock.e2fs_bsize - 1)) != 0)
|
||||
idesc->id_filesize = roundup(idesc->id_filesize, sblock.e2fs_bsize);
|
||||
blksiz = idesc->id_numfrags * sblock.e2fs_bsize;
|
||||
if (chkrange(idesc->id_blkno, idesc->id_numfrags)) {
|
||||
idesc->id_filesize -= blksiz;
|
||||
free(dbuf);
|
||||
return (SKIP);
|
||||
}
|
||||
idesc->id_loc = 0;
|
||||
for (dp = fsck_readdir(idesc); dp != NULL; dp = fsck_readdir(idesc)) {
|
||||
dsize = fs2h16(dp->e2d_reclen);
|
||||
memcpy(dbuf, dp, (size_t)dsize);
|
||||
idesc->id_dirp = (struct ext2fs_direct *)dbuf;
|
||||
if ((n = (*idesc->id_func)(idesc)) & ALTERED) {
|
||||
bp = getdirblk(idesc->id_blkno, blksiz);
|
||||
memcpy(bp->b_un.b_buf + idesc->id_loc - dsize, dbuf,
|
||||
(size_t)dsize);
|
||||
dirty(bp);
|
||||
sbdirty();
|
||||
}
|
||||
if (n & STOP) {
|
||||
free(dbuf);
|
||||
return (n);
|
||||
}
|
||||
}
|
||||
free(dbuf);
|
||||
return (idesc->id_filesize > 0 ? KEEPON : STOP);
|
||||
}
|
||||
|
||||
/*
|
||||
* get next entry in a directory.
|
||||
*/
|
||||
static struct ext2fs_direct *
|
||||
fsck_readdir(struct inodesc *idesc)
|
||||
{
|
||||
struct ext2fs_direct *dp, *ndp;
|
||||
struct bufarea *bp;
|
||||
long size, blksiz, fix, dploc;
|
||||
|
||||
blksiz = idesc->id_numfrags * sblock.e2fs_bsize;
|
||||
bp = getdirblk(idesc->id_blkno, blksiz);
|
||||
if (idesc->id_loc % sblock.e2fs_bsize == 0 && idesc->id_filesize > 0 &&
|
||||
idesc->id_loc < blksiz) {
|
||||
dp = (struct ext2fs_direct *)(bp->b_un.b_buf + idesc->id_loc);
|
||||
if (dircheck(idesc, dp))
|
||||
goto dpok;
|
||||
if (idesc->id_fix == IGNORE)
|
||||
return (0);
|
||||
fix = dofix(idesc, "DIRECTORY CORRUPTED");
|
||||
bp = getdirblk(idesc->id_blkno, blksiz);
|
||||
dp = (struct ext2fs_direct *)(bp->b_un.b_buf + idesc->id_loc);
|
||||
dp->e2d_reclen = h2fs16(sblock.e2fs_bsize);
|
||||
dp->e2d_ino = 0;
|
||||
dp->e2d_namlen = 0;
|
||||
dp->e2d_type = 0;
|
||||
dp->e2d_name[0] = '\0';
|
||||
if (fix)
|
||||
dirty(bp);
|
||||
idesc->id_loc += sblock.e2fs_bsize;
|
||||
idesc->id_filesize -= sblock.e2fs_bsize;
|
||||
return (dp);
|
||||
}
|
||||
dpok:
|
||||
if (idesc->id_filesize <= 0 || idesc->id_loc >= blksiz)
|
||||
return NULL;
|
||||
dploc = idesc->id_loc;
|
||||
dp = (struct ext2fs_direct *)(bp->b_un.b_buf + dploc);
|
||||
idesc->id_loc += fs2h16(dp->e2d_reclen);
|
||||
idesc->id_filesize -= fs2h16(dp->e2d_reclen);
|
||||
if ((idesc->id_loc % sblock.e2fs_bsize) == 0)
|
||||
return (dp);
|
||||
ndp = (struct ext2fs_direct *)(bp->b_un.b_buf + idesc->id_loc);
|
||||
if (idesc->id_loc < blksiz && idesc->id_filesize > 0 &&
|
||||
dircheck(idesc, ndp) == 0) {
|
||||
size = sblock.e2fs_bsize - (idesc->id_loc % sblock.e2fs_bsize);
|
||||
idesc->id_loc += size;
|
||||
idesc->id_filesize -= size;
|
||||
if (idesc->id_fix == IGNORE)
|
||||
return (0);
|
||||
fix = dofix(idesc, "DIRECTORY CORRUPTED");
|
||||
bp = getdirblk(idesc->id_blkno, blksiz);
|
||||
dp = (struct ext2fs_direct *)(bp->b_un.b_buf + dploc);
|
||||
dp->e2d_reclen = h2fs16(fs2h16(dp->e2d_reclen) + size);
|
||||
if (fix)
|
||||
dirty(bp);
|
||||
}
|
||||
return (dp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that a directory entry is valid.
|
||||
* This is a superset of the checks made in the kernel.
|
||||
*/
|
||||
int
|
||||
dircheck(struct inodesc *idesc, struct ext2fs_direct *dp)
|
||||
{
|
||||
int size;
|
||||
char *cp;
|
||||
int spaceleft;
|
||||
u_int16_t reclen = fs2h16(dp->e2d_reclen);
|
||||
|
||||
spaceleft = sblock.e2fs_bsize - (idesc->id_loc % sblock.e2fs_bsize);
|
||||
if (fs2h32(dp->e2d_ino) > maxino ||
|
||||
reclen == 0 ||
|
||||
reclen > spaceleft ||
|
||||
(reclen & 0x3) != 0)
|
||||
return (0);
|
||||
if (dp->e2d_ino == 0)
|
||||
return (1);
|
||||
if (sblock.e2fs.e2fs_rev < E2FS_REV1 ||
|
||||
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE) == 0)
|
||||
if (dp->e2d_type != 0)
|
||||
return (1);
|
||||
size = EXT2FS_DIRSIZ(dp->e2d_namlen);
|
||||
if (reclen < size ||
|
||||
idesc->id_filesize < size /* ||
|
||||
dp->e2d_namlen > EXT2FS_MAXNAMLEN */)
|
||||
return (0);
|
||||
for (cp = dp->e2d_name, size = 0; size < dp->e2d_namlen; size++)
|
||||
if (*cp == '\0' || (*cp++ == '/'))
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
direrror(ino_t ino, const char *errmesg)
|
||||
{
|
||||
|
||||
fileerror(ino, ino, errmesg);
|
||||
}
|
||||
|
||||
void
|
||||
fileerror(ino_t cwd, ino_t ino, const char *errmesg)
|
||||
{
|
||||
struct ext2fs_dinode *dp;
|
||||
char pathbuf[MAXPATHLEN + 1];
|
||||
|
||||
pwarn("%s ", errmesg);
|
||||
pinode(ino);
|
||||
printf("\n");
|
||||
getpathname(pathbuf, sizeof(pathbuf), cwd, ino);
|
||||
if ((ino < EXT2_FIRSTINO && ino != EXT2_ROOTINO) || ino > maxino) {
|
||||
pfatal("NAME=%s\n", pathbuf);
|
||||
return;
|
||||
}
|
||||
dp = ginode(ino);
|
||||
if (ftypeok(dp))
|
||||
pfatal("%s=%s\n",
|
||||
(fs2h16(dp->e2di_mode) & IFMT) == IFDIR ? "DIR" : "FILE", pathbuf);
|
||||
else
|
||||
pfatal("NAME=%s\n", pathbuf);
|
||||
}
|
||||
|
||||
void
|
||||
adjust(struct inodesc *idesc, short lcnt)
|
||||
{
|
||||
struct ext2fs_dinode *dp;
|
||||
|
||||
dp = ginode(idesc->id_number);
|
||||
if (fs2h16(dp->e2di_nlink) == lcnt) {
|
||||
if (linkup(idesc->id_number, (ino_t)0) == 0)
|
||||
clri(idesc, "UNREF", 0);
|
||||
} else {
|
||||
pwarn("LINK COUNT %s", (lfdir == idesc->id_number) ? lfname :
|
||||
((fs2h16(dp->e2di_mode) & IFMT) == IFDIR ? "DIR" : "FILE"));
|
||||
pinode(idesc->id_number);
|
||||
printf(" COUNT %d SHOULD BE %d",
|
||||
fs2h16(dp->e2di_nlink), fs2h16(dp->e2di_nlink) - lcnt);
|
||||
if (preen) {
|
||||
if (lcnt < 0) {
|
||||
printf("\n");
|
||||
pfatal("LINK COUNT INCREASING");
|
||||
}
|
||||
printf(" (ADJUSTED)\n");
|
||||
}
|
||||
if (preen || reply("ADJUST") == 1) {
|
||||
dp->e2di_nlink = h2fs16(fs2h16(dp->e2di_nlink) - lcnt);
|
||||
inodirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
mkentry(struct inodesc *idesc)
|
||||
{
|
||||
struct ext2fs_direct *dirp = idesc->id_dirp;
|
||||
struct ext2fs_direct newent;
|
||||
int newlen, oldlen;
|
||||
|
||||
newent.e2d_type = 0; /* XXX gcc */
|
||||
newent.e2d_namlen = strlen(idesc->id_name);
|
||||
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
|
||||
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE))
|
||||
newent.e2d_type = inot2ext2dt(typemap[idesc->id_parent]);
|
||||
newlen = EXT2FS_DIRSIZ(newent.e2d_namlen);
|
||||
if (dirp->e2d_ino != 0)
|
||||
oldlen = EXT2FS_DIRSIZ(dirp->e2d_namlen);
|
||||
else
|
||||
oldlen = 0;
|
||||
if (fs2h16(dirp->e2d_reclen) - oldlen < newlen)
|
||||
return (KEEPON);
|
||||
newent.e2d_reclen = h2fs16(fs2h16(dirp->e2d_reclen) - oldlen);
|
||||
dirp->e2d_reclen = h2fs16(oldlen);
|
||||
dirp = (struct ext2fs_direct *)(((char *)dirp) + oldlen);
|
||||
dirp->e2d_ino = h2fs32(idesc->id_parent); /* ino to be entered is in id_parent */
|
||||
dirp->e2d_reclen = newent.e2d_reclen;
|
||||
dirp->e2d_namlen = newent.e2d_namlen;
|
||||
dirp->e2d_type = newent.e2d_type;
|
||||
memcpy(dirp->e2d_name, idesc->id_name, (size_t)(dirp->e2d_namlen));
|
||||
return (ALTERED|STOP);
|
||||
}
|
||||
|
||||
static int
|
||||
chgino(struct inodesc *idesc)
|
||||
{
|
||||
struct ext2fs_direct *dirp = idesc->id_dirp;
|
||||
u_int16_t namlen = dirp->e2d_namlen;
|
||||
|
||||
if (strlen(idesc->id_name) != namlen ||
|
||||
strncmp(dirp->e2d_name, idesc->id_name, (int)namlen))
|
||||
return (KEEPON);
|
||||
dirp->e2d_ino = h2fs32(idesc->id_parent);
|
||||
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
|
||||
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE))
|
||||
dirp->e2d_type = inot2ext2dt(typemap[idesc->id_parent]);
|
||||
else
|
||||
dirp->e2d_type = 0;
|
||||
return (ALTERED|STOP);
|
||||
}
|
||||
|
||||
int
|
||||
linkup(ino_t orphan, ino_t parentdir)
|
||||
{
|
||||
struct ext2fs_dinode *dp;
|
||||
int lostdir;
|
||||
ino_t oldlfdir;
|
||||
struct inodesc idesc;
|
||||
char tempname[BUFSIZ];
|
||||
|
||||
memset(&idesc, 0, sizeof(struct inodesc));
|
||||
dp = ginode(orphan);
|
||||
lostdir = (fs2h16(dp->e2di_mode) & IFMT) == IFDIR;
|
||||
pwarn("UNREF %s ", lostdir ? "DIR" : "FILE");
|
||||
pinode(orphan);
|
||||
if (preen && inosize(dp) == 0)
|
||||
return (0);
|
||||
if (preen)
|
||||
printf(" (RECONNECTED)\n");
|
||||
else
|
||||
if (reply("RECONNECT") == 0)
|
||||
return (0);
|
||||
if (lfdir == 0) {
|
||||
dp = ginode(EXT2_ROOTINO);
|
||||
idesc.id_name = lfname;
|
||||
idesc.id_type = DATA;
|
||||
idesc.id_func = findino;
|
||||
idesc.id_number = EXT2_ROOTINO;
|
||||
if ((ckinode(dp, &idesc) & FOUND) != 0) {
|
||||
lfdir = idesc.id_parent;
|
||||
} else {
|
||||
pwarn("NO lost+found DIRECTORY");
|
||||
if (preen || reply("CREATE")) {
|
||||
lfdir = allocdir(EXT2_ROOTINO, (ino_t)0, lfmode);
|
||||
if (lfdir != 0) {
|
||||
if (makeentry(EXT2_ROOTINO, lfdir, lfname) != 0) {
|
||||
if (preen)
|
||||
printf(" (CREATED)\n");
|
||||
} else {
|
||||
freedir(lfdir, EXT2_ROOTINO);
|
||||
lfdir = 0;
|
||||
if (preen)
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lfdir == 0) {
|
||||
pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY");
|
||||
printf("\n\n");
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
dp = ginode(lfdir);
|
||||
if ((fs2h16(dp->e2di_mode) & IFMT) != IFDIR) {
|
||||
pfatal("lost+found IS NOT A DIRECTORY");
|
||||
if (reply("REALLOCATE") == 0)
|
||||
return (0);
|
||||
oldlfdir = lfdir;
|
||||
if ((lfdir = allocdir(EXT2_ROOTINO, (ino_t)0, lfmode)) == 0) {
|
||||
pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n");
|
||||
return (0);
|
||||
}
|
||||
if ((changeino(EXT2_ROOTINO, lfname, lfdir) & ALTERED) == 0) {
|
||||
pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n");
|
||||
return (0);
|
||||
}
|
||||
inodirty();
|
||||
idesc.id_type = ADDR;
|
||||
idesc.id_func = pass4check;
|
||||
idesc.id_number = oldlfdir;
|
||||
adjust(&idesc, lncntp[oldlfdir] + 1);
|
||||
lncntp[oldlfdir] = 0;
|
||||
dp = ginode(lfdir);
|
||||
}
|
||||
if (statemap[lfdir] != DFOUND) {
|
||||
pfatal("SORRY. NO lost+found DIRECTORY\n\n");
|
||||
return (0);
|
||||
}
|
||||
(void)lftempname(tempname, orphan);
|
||||
if (makeentry(lfdir, orphan, tempname) == 0) {
|
||||
pfatal("SORRY. NO SPACE IN lost+found DIRECTORY");
|
||||
printf("\n\n");
|
||||
return (0);
|
||||
}
|
||||
lncntp[orphan]--;
|
||||
if (lostdir) {
|
||||
if ((changeino(orphan, "..", lfdir) & ALTERED) == 0 &&
|
||||
parentdir != (ino_t)-1)
|
||||
(void)makeentry(orphan, lfdir, "..");
|
||||
dp = ginode(lfdir);
|
||||
dp->e2di_nlink = h2fs16(fs2h16(dp->e2di_nlink) +1);
|
||||
inodirty();
|
||||
lncntp[lfdir]++;
|
||||
pwarn("DIR I=%llu CONNECTED. ", (unsigned long long)orphan);
|
||||
if (parentdir != (ino_t)-1)
|
||||
printf("PARENT WAS I=%llu\n",
|
||||
(unsigned long long)parentdir);
|
||||
if (preen == 0)
|
||||
printf("\n");
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* fix an entry in a directory.
|
||||
*/
|
||||
int
|
||||
changeino(ino_t dir, const char *name, ino_t newnum)
|
||||
{
|
||||
struct inodesc idesc;
|
||||
|
||||
memset(&idesc, 0, sizeof(struct inodesc));
|
||||
idesc.id_type = DATA;
|
||||
idesc.id_func = chgino;
|
||||
idesc.id_number = dir;
|
||||
idesc.id_fix = DONTKNOW;
|
||||
idesc.id_name = name;
|
||||
idesc.id_parent = newnum; /* new value for name */
|
||||
return (ckinode(ginode(dir), &idesc));
|
||||
}
|
||||
|
||||
/*
|
||||
* make an entry in a directory
|
||||
*/
|
||||
int
|
||||
makeentry(ino_t parent, ino_t ino, const char *name)
|
||||
{
|
||||
struct ext2fs_dinode *dp;
|
||||
struct inodesc idesc;
|
||||
char pathbuf[MAXPATHLEN + 1];
|
||||
|
||||
if ((parent < EXT2_FIRSTINO && parent != EXT2_ROOTINO)
|
||||
|| parent >= maxino ||
|
||||
(ino < EXT2_FIRSTINO && ino < EXT2_ROOTINO) || ino >= maxino)
|
||||
return (0);
|
||||
memset(&idesc, 0, sizeof(struct inodesc));
|
||||
idesc.id_type = DATA;
|
||||
idesc.id_func = mkentry;
|
||||
idesc.id_number = parent;
|
||||
idesc.id_parent = ino; /* this is the inode to enter */
|
||||
idesc.id_fix = DONTKNOW;
|
||||
idesc.id_name = name;
|
||||
dp = ginode(parent);
|
||||
if (inosize(dp) % sblock.e2fs_bsize) {
|
||||
inossize(dp, roundup(inosize(dp), sblock.e2fs_bsize));
|
||||
inodirty();
|
||||
}
|
||||
if ((ckinode(dp, &idesc) & ALTERED) != 0)
|
||||
return (1);
|
||||
getpathname(pathbuf, sizeof(pathbuf), parent, parent);
|
||||
dp = ginode(parent);
|
||||
if (expanddir(dp, pathbuf) == 0)
|
||||
return (0);
|
||||
return (ckinode(dp, &idesc) & ALTERED);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to expand the size of a directory
|
||||
*/
|
||||
static int
|
||||
expanddir(struct ext2fs_dinode *dp, char *name)
|
||||
{
|
||||
daddr_t lastbn, newblk;
|
||||
struct bufarea *bp;
|
||||
char *firstblk;
|
||||
|
||||
lastbn = lblkno(&sblock, inosize(dp));
|
||||
if (lastbn >= NDADDR - 1 || fs2h32(dp->e2di_blocks[lastbn]) == 0 ||
|
||||
inosize(dp) == 0) {
|
||||
return (0);
|
||||
}
|
||||
if ((newblk = allocblk()) == 0) {
|
||||
return (0);
|
||||
}
|
||||
dp->e2di_blocks[lastbn + 1] = dp->e2di_blocks[lastbn];
|
||||
dp->e2di_blocks[lastbn] = h2fs32(newblk);
|
||||
inossize(dp, inosize(dp) + sblock.e2fs_bsize);
|
||||
dp->e2di_nblock = h2fs32(fs2h32(dp->e2di_nblock) + 1);
|
||||
bp = getdirblk(fs2h32(dp->e2di_blocks[lastbn + 1]),
|
||||
sblock.e2fs_bsize);
|
||||
if (bp->b_errs)
|
||||
goto bad;
|
||||
if ((firstblk = malloc(sblock.e2fs_bsize)) == NULL)
|
||||
err(8, "cannot allocate first block");
|
||||
memcpy(firstblk, bp->b_un.b_buf, sblock.e2fs_bsize);
|
||||
bp = getdirblk(newblk, sblock.e2fs_bsize);
|
||||
if (bp->b_errs) {
|
||||
free(firstblk);
|
||||
goto bad;
|
||||
}
|
||||
memcpy(bp->b_un.b_buf, firstblk, sblock.e2fs_bsize);
|
||||
free(firstblk);
|
||||
dirty(bp);
|
||||
bp = getdirblk(fs2h32(dp->e2di_blocks[lastbn + 1]),
|
||||
sblock.e2fs_bsize);
|
||||
if (bp->b_errs)
|
||||
goto bad;
|
||||
emptydir.dot_reclen = h2fs16(sblock.e2fs_bsize);
|
||||
memcpy(bp->b_un.b_buf, &emptydir, sizeof emptydir);
|
||||
pwarn("NO SPACE LEFT IN %s", name);
|
||||
if (preen)
|
||||
printf(" (EXPANDED)\n");
|
||||
else if (reply("EXPAND") == 0)
|
||||
goto bad;
|
||||
dirty(bp);
|
||||
inodirty();
|
||||
return (1);
|
||||
bad:
|
||||
dp->e2di_blocks[lastbn] = dp->e2di_blocks[lastbn + 1];
|
||||
dp->e2di_blocks[lastbn + 1] = 0;
|
||||
inossize(dp, inosize(dp) - sblock.e2fs_bsize);
|
||||
dp->e2di_nblock = h2fs32(fs2h32(dp->e2di_nblock) - 1);
|
||||
freeblk(newblk);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate a new directory
|
||||
*/
|
||||
int
|
||||
allocdir(ino_t parent, ino_t request, int mode)
|
||||
{
|
||||
ino_t ino;
|
||||
struct ext2fs_dinode *dp;
|
||||
struct bufarea *bp;
|
||||
struct ext2fs_dirtemplate *dirp;
|
||||
|
||||
ino = allocino(request, IFDIR|mode);
|
||||
dirhead.dot_reclen = h2fs16(12); /* XXX */
|
||||
dirhead.dotdot_reclen = h2fs16(sblock.e2fs_bsize - 12); /* XXX */
|
||||
dirhead.dot_namlen = 1;
|
||||
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
|
||||
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE))
|
||||
dirhead.dot_type = EXT2_FT_DIR;
|
||||
else
|
||||
dirhead.dot_type = 0;
|
||||
dirhead.dotdot_namlen = 2;
|
||||
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
|
||||
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE))
|
||||
dirhead.dotdot_type = EXT2_FT_DIR;
|
||||
else
|
||||
dirhead.dotdot_type = 0;
|
||||
dirp = &dirhead;
|
||||
dirp->dot_ino = h2fs32(ino);
|
||||
dirp->dotdot_ino = h2fs32(parent);
|
||||
dp = ginode(ino);
|
||||
bp = getdirblk(fs2h32(dp->e2di_blocks[0]), sblock.e2fs_bsize);
|
||||
if (bp->b_errs) {
|
||||
freeino(ino);
|
||||
return (0);
|
||||
}
|
||||
memcpy(bp->b_un.b_buf, dirp, sizeof(struct ext2fs_dirtemplate));
|
||||
dirty(bp);
|
||||
dp->e2di_nlink = h2fs16(2);
|
||||
inodirty();
|
||||
if (ino == EXT2_ROOTINO) {
|
||||
lncntp[ino] = fs2h16(dp->e2di_nlink);
|
||||
cacheino(dp, ino);
|
||||
return(ino);
|
||||
}
|
||||
if (statemap[parent] != DSTATE && statemap[parent] != DFOUND) {
|
||||
freeino(ino);
|
||||
return (0);
|
||||
}
|
||||
cacheino(dp, ino);
|
||||
statemap[ino] = statemap[parent];
|
||||
if (statemap[ino] == DSTATE) {
|
||||
lncntp[ino] = fs2h16(dp->e2di_nlink);
|
||||
lncntp[parent]++;
|
||||
}
|
||||
dp = ginode(parent);
|
||||
dp->e2di_nlink = h2fs16(fs2h16(dp->e2di_nlink) + 1);
|
||||
inodirty();
|
||||
return (ino);
|
||||
}
|
||||
|
||||
/*
|
||||
* free a directory inode
|
||||
*/
|
||||
static void
|
||||
freedir(ino_t ino, ino_t parent)
|
||||
{
|
||||
struct ext2fs_dinode *dp;
|
||||
|
||||
if (ino != parent) {
|
||||
dp = ginode(parent);
|
||||
dp->e2di_nlink = h2fs16(fs2h16(dp->e2di_nlink) - 1);
|
||||
inodirty();
|
||||
}
|
||||
freeino(ino);
|
||||
}
|
||||
|
||||
/*
|
||||
* generate a temporary name for the lost+found directory.
|
||||
*/
|
||||
static int
|
||||
lftempname(char *bufp, ino_t ino)
|
||||
{
|
||||
ino_t in;
|
||||
char *cp;
|
||||
int namlen;
|
||||
|
||||
cp = bufp + 2;
|
||||
for (in = maxino; in > 0; in /= 10)
|
||||
cp++;
|
||||
*--cp = 0;
|
||||
namlen = cp - bufp;
|
||||
in = ino;
|
||||
while (cp > bufp) {
|
||||
*--cp = (in % 10) + '0';
|
||||
in /= 10;
|
||||
}
|
||||
*cp = '#';
|
||||
return (namlen);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a directory block.
|
||||
* Insure that it is held until another is requested.
|
||||
*/
|
||||
static struct bufarea *
|
||||
getdirblk(daddr_t blkno, long size)
|
||||
{
|
||||
|
||||
if (pdirbp != 0)
|
||||
pdirbp->b_flags &= ~B_INUSE;
|
||||
pdirbp = getdatablk(blkno, size);
|
||||
return (pdirbp);
|
||||
}
|
121
sbin/fsck_ext2fs/ext2fs_bswap.c
Normal file
121
sbin/fsck_ext2fs/ext2fs_bswap.c
Normal file
|
@ -0,0 +1,121 @@
|
|||
/* $NetBSD: ext2fs_bswap.c,v 1.16 2009/10/19 18:41:17 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Manuel Bouyer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ext2fs_bswap.c,v 1.16 2009/10/19 18:41:17 bouyer Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <ufs/ext2fs/ext2fs.h>
|
||||
#include <ufs/ext2fs/ext2fs_dinode.h>
|
||||
|
||||
#if defined(_KERNEL)
|
||||
#include <sys/systm.h>
|
||||
#else
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
/* These functions are only needed if native byte order is not big endian */
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
void
|
||||
e2fs_sb_bswap(struct ext2fs *old, struct ext2fs *new)
|
||||
{
|
||||
|
||||
/* preserve unused fields */
|
||||
memcpy(new, old, sizeof(struct ext2fs));
|
||||
new->e2fs_icount = bswap32(old->e2fs_icount);
|
||||
new->e2fs_bcount = bswap32(old->e2fs_bcount);
|
||||
new->e2fs_rbcount = bswap32(old->e2fs_rbcount);
|
||||
new->e2fs_fbcount = bswap32(old->e2fs_fbcount);
|
||||
new->e2fs_ficount = bswap32(old->e2fs_ficount);
|
||||
new->e2fs_first_dblock = bswap32(old->e2fs_first_dblock);
|
||||
new->e2fs_log_bsize = bswap32(old->e2fs_log_bsize);
|
||||
new->e2fs_fsize = bswap32(old->e2fs_fsize);
|
||||
new->e2fs_bpg = bswap32(old->e2fs_bpg);
|
||||
new->e2fs_fpg = bswap32(old->e2fs_fpg);
|
||||
new->e2fs_ipg = bswap32(old->e2fs_ipg);
|
||||
new->e2fs_mtime = bswap32(old->e2fs_mtime);
|
||||
new->e2fs_wtime = bswap32(old->e2fs_wtime);
|
||||
new->e2fs_mnt_count = bswap16(old->e2fs_mnt_count);
|
||||
new->e2fs_max_mnt_count = bswap16(old->e2fs_max_mnt_count);
|
||||
new->e2fs_magic = bswap16(old->e2fs_magic);
|
||||
new->e2fs_state = bswap16(old->e2fs_state);
|
||||
new->e2fs_beh = bswap16(old->e2fs_beh);
|
||||
new->e2fs_minrev = bswap16(old->e2fs_minrev);
|
||||
new->e2fs_lastfsck = bswap32(old->e2fs_lastfsck);
|
||||
new->e2fs_fsckintv = bswap32(old->e2fs_fsckintv);
|
||||
new->e2fs_creator = bswap32(old->e2fs_creator);
|
||||
new->e2fs_rev = bswap32(old->e2fs_rev);
|
||||
new->e2fs_ruid = bswap16(old->e2fs_ruid);
|
||||
new->e2fs_rgid = bswap16(old->e2fs_rgid);
|
||||
new->e2fs_first_ino = bswap32(old->e2fs_first_ino);
|
||||
new->e2fs_inode_size = bswap16(old->e2fs_inode_size);
|
||||
new->e2fs_block_group_nr = bswap16(old->e2fs_block_group_nr);
|
||||
new->e2fs_features_compat = bswap32(old->e2fs_features_compat);
|
||||
new->e2fs_features_incompat = bswap32(old->e2fs_features_incompat);
|
||||
new->e2fs_features_rocompat = bswap32(old->e2fs_features_rocompat);
|
||||
new->e2fs_algo = bswap32(old->e2fs_algo);
|
||||
new->e2fs_reserved_ngdb = bswap16(old->e2fs_reserved_ngdb);
|
||||
}
|
||||
|
||||
void e2fs_cg_bswap(struct ext2_gd *old, struct ext2_gd *new, int size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < (size / (int)sizeof(struct ext2_gd)); i++) {
|
||||
new[i].ext2bgd_b_bitmap = bswap32(old[i].ext2bgd_b_bitmap);
|
||||
new[i].ext2bgd_i_bitmap = bswap32(old[i].ext2bgd_i_bitmap);
|
||||
new[i].ext2bgd_i_tables = bswap32(old[i].ext2bgd_i_tables);
|
||||
new[i].ext2bgd_nbfree = bswap16(old[i].ext2bgd_nbfree);
|
||||
new[i].ext2bgd_nifree = bswap16(old[i].ext2bgd_nifree);
|
||||
new[i].ext2bgd_ndirs = bswap16(old[i].ext2bgd_ndirs);
|
||||
}
|
||||
}
|
||||
|
||||
void e2fs_i_bswap(struct ext2fs_dinode *old, struct ext2fs_dinode *new)
|
||||
{
|
||||
|
||||
new->e2di_mode = bswap16(old->e2di_mode);
|
||||
new->e2di_uid = bswap16(old->e2di_uid);
|
||||
new->e2di_gid = bswap16(old->e2di_gid);
|
||||
new->e2di_nlink = bswap16(old->e2di_nlink);
|
||||
new->e2di_size = bswap32(old->e2di_size);
|
||||
new->e2di_atime = bswap32(old->e2di_atime);
|
||||
new->e2di_ctime = bswap32(old->e2di_ctime);
|
||||
new->e2di_mtime = bswap32(old->e2di_mtime);
|
||||
new->e2di_dtime = bswap32(old->e2di_dtime);
|
||||
new->e2di_nblock = bswap32(old->e2di_nblock);
|
||||
new->e2di_flags = bswap32(old->e2di_flags);
|
||||
new->e2di_gen = bswap32(old->e2di_gen);
|
||||
new->e2di_facl = bswap32(old->e2di_facl);
|
||||
new->e2di_dacl = bswap32(old->e2di_dacl);
|
||||
new->e2di_faddr = bswap32(old->e2di_faddr);
|
||||
new->e2di_uid_high = bswap16(old->e2di_uid_high);
|
||||
new->e2di_gid_high = bswap16(old->e2di_gid_high);
|
||||
memcpy(&new->e2di_blocks[0], &old->e2di_blocks[0],
|
||||
(NDADDR + NIADDR) * sizeof(uint32_t));
|
||||
}
|
||||
#endif
|
73
sbin/fsck_ext2fs/extern.h
Normal file
73
sbin/fsck_ext2fs/extern.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
/* $NetBSD: extern.h,v 1.7 2011/06/09 19:57:50 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Manuel Bouyer.
|
||||
* Copyright (c) 1994 James A. Jegers
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
void adjust(struct inodesc *, short);
|
||||
int allocblk(void);
|
||||
int allocdir(ino_t, ino_t, int);
|
||||
void blkerror(ino_t, const char *, daddr_t);
|
||||
int bread(int, char *, daddr_t, long);
|
||||
void bufinit(void);
|
||||
void bwrite(int, char *, daddr_t, long);
|
||||
void cacheino(struct ext2fs_dinode *, ino_t);
|
||||
int changeino(ino_t, const char *, ino_t);
|
||||
int chkrange(daddr_t, int);
|
||||
void ckfini(int);
|
||||
int ckinode(struct ext2fs_dinode *, struct inodesc *);
|
||||
void clri(struct inodesc *, const char *, int);
|
||||
int dircheck(struct inodesc *, struct ext2fs_direct *);
|
||||
void direrror(ino_t, const char *);
|
||||
int dirscan(struct inodesc *);
|
||||
int dofix(struct inodesc *, const char *);
|
||||
void fileerror(ino_t, ino_t, const char *);
|
||||
int findino(struct inodesc *);
|
||||
int findname(struct inodesc *);
|
||||
void flush(int, struct bufarea *);
|
||||
void freeblk(daddr_t);
|
||||
void freeino(ino_t);
|
||||
void freeinodebuf(void);
|
||||
int ftypeok(struct ext2fs_dinode *);
|
||||
void getpathname(char *, size_t, ino_t, ino_t);
|
||||
void inocleanup(void);
|
||||
void inodirty(void);
|
||||
u_int64_t inosize(struct ext2fs_dinode *);
|
||||
void inossize(struct ext2fs_dinode *, u_int64_t);
|
||||
int linkup(ino_t, ino_t);
|
||||
int makeentry(ino_t, ino_t, const char *);
|
||||
void pass1(void);
|
||||
void pass1b(void);
|
||||
void pass2(void);
|
||||
void pass3(void);
|
||||
void pass4(void);
|
||||
int pass1check(struct inodesc *);
|
||||
int pass4check(struct inodesc *);
|
||||
void pass5(void);
|
||||
void pinode(ino_t);
|
||||
void propagate(void);
|
||||
int reply(const char *);
|
||||
void resetinodebuf(void);
|
||||
int setup(const char *);
|
||||
struct ext2fs_dinode * getnextinode(ino_t);
|
238
sbin/fsck_ext2fs/fsck.h
Normal file
238
sbin/fsck_ext2fs/fsck.h
Normal file
|
@ -0,0 +1,238 @@
|
|||
/* $NetBSD: fsck.h,v 1.15 2009/10/19 18:41:08 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1980, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)fsck.h 8.1 (Berkeley) 6/5/93
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Manuel Bouyer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @(#)fsck.h 8.1 (Berkeley) 6/5/93
|
||||
*/
|
||||
|
||||
#define MAXDUP 10 /* limit on dup blks (per inode) */
|
||||
#define MAXBAD 10 /* limit on bad blks (per inode) */
|
||||
#define MAXBUFSPACE 80*1024 /* maximum space to allocate to buffers */
|
||||
#define INOBUFSIZE 128*1024 /* size of buffer to read inodes in pass1 */
|
||||
|
||||
#ifndef BUFSIZ
|
||||
#define BUFSIZ 1024
|
||||
#endif
|
||||
|
||||
#define USTATE 01 /* inode not allocated */
|
||||
#define FSTATE 02 /* inode is file */
|
||||
#define DSTATE 03 /* inode is directory */
|
||||
#define DFOUND 04 /* directory found during descent */
|
||||
#define DCLEAR 05 /* directory is to be cleared */
|
||||
#define FCLEAR 06 /* file is to be cleared */
|
||||
|
||||
/*
|
||||
* buffer cache structure.
|
||||
*/
|
||||
struct bufarea {
|
||||
struct bufarea *b_next; /* free list queue */
|
||||
struct bufarea *b_prev; /* free list queue */
|
||||
daddr_t b_bno;
|
||||
int b_size;
|
||||
int b_errs;
|
||||
int b_flags;
|
||||
union {
|
||||
char *b_buf; /* buffer space */
|
||||
/* XXX ondisk32 */
|
||||
int32_t *b_indir; /* indirect block */
|
||||
struct ext2fs *b_fs; /* super block */
|
||||
struct ext2_gd *b_cgd; /* cylinder group descriptor */
|
||||
struct ext2fs_dinode *b_dinode; /* inode block */
|
||||
} b_un;
|
||||
char b_dirty;
|
||||
};
|
||||
|
||||
#define B_INUSE 1
|
||||
|
||||
#define MINBUFS 5 /* minimum number of buffers required */
|
||||
struct bufarea bufhead; /* head of list of other blks in filesys */
|
||||
struct bufarea sblk; /* file system superblock */
|
||||
struct bufarea asblk; /* first alternate superblock */
|
||||
struct bufarea *pdirbp; /* current directory contents */
|
||||
struct bufarea *pbp; /* current inode block */
|
||||
struct bufarea *getdatablk(daddr_t, long);
|
||||
struct m_ext2fs sblock;
|
||||
|
||||
#define dirty(bp) (bp)->b_dirty = 1
|
||||
#define initbarea(bp) \
|
||||
(bp)->b_dirty = 0; \
|
||||
(bp)->b_bno = (daddr_t)-1; \
|
||||
(bp)->b_flags = 0;
|
||||
|
||||
#define sbdirty() copyback_sb(&sblk); sblk.b_dirty = 1
|
||||
|
||||
enum fixstate {DONTKNOW, NOFIX, FIX, IGNORE};
|
||||
|
||||
struct inodesc {
|
||||
enum fixstate id_fix; /* policy on fixing errors */
|
||||
int (*id_func) /* function to be applied to blocks of inode */
|
||||
(struct inodesc *);
|
||||
ino_t id_number; /* inode number described */
|
||||
ino_t id_parent; /* for DATA nodes, their parent */
|
||||
daddr_t id_blkno; /* current block number being examined */
|
||||
int id_numfrags; /* number of frags contained in block */
|
||||
quad_t id_filesize; /* for DATA nodes, the size of the directory */
|
||||
int id_loc; /* for DATA nodes, current location in dir */
|
||||
int id_entryno; /* for DATA nodes, current entry number */
|
||||
struct ext2fs_direct *id_dirp; /* for DATA nodes, ptr to current entry */
|
||||
const char *id_name; /* for DATA nodes, name to find or enter */
|
||||
char id_type; /* type of descriptor, DATA or ADDR */
|
||||
};
|
||||
/* file types */
|
||||
#define DATA 1
|
||||
#define ADDR 2
|
||||
|
||||
/*
|
||||
* Linked list of duplicate blocks.
|
||||
*
|
||||
* The list is composed of two parts. The first part of the
|
||||
* list (from duplist through the node pointed to by muldup)
|
||||
* contains a single copy of each duplicate block that has been
|
||||
* found. The second part of the list (from muldup to the end)
|
||||
* contains duplicate blocks that have been found more than once.
|
||||
* To check if a block has been found as a duplicate it is only
|
||||
* necessary to search from duplist through muldup. To find the
|
||||
* total number of times that a block has been found as a duplicate
|
||||
* the entire list must be searched for occurrences of the block
|
||||
* in question. The following diagram shows a sample list where
|
||||
* w (found twice), x (found once), y (found three times), and z
|
||||
* (found once) are duplicate block numbers:
|
||||
*
|
||||
* w -> y -> x -> z -> y -> w -> y
|
||||
* ^ ^
|
||||
* | |
|
||||
* duplist muldup
|
||||
*/
|
||||
struct dups {
|
||||
struct dups *next;
|
||||
daddr_t dup;
|
||||
};
|
||||
struct dups *duplist; /* head of dup list */
|
||||
struct dups *muldup; /* end of unique duplicate dup block numbers */
|
||||
|
||||
/*
|
||||
* Linked list of inodes with zero link counts.
|
||||
*/
|
||||
struct zlncnt {
|
||||
struct zlncnt *next;
|
||||
ino_t zlncnt;
|
||||
};
|
||||
struct zlncnt *zlnhead; /* head of zero link count list */
|
||||
|
||||
/*
|
||||
* Inode cache data structures.
|
||||
*/
|
||||
struct inoinfo {
|
||||
struct inoinfo *i_nexthash; /* next entry in hash chain */
|
||||
struct inoinfo *i_child, *i_sibling, *i_parentp;
|
||||
ino_t i_number; /* inode number of this entry */
|
||||
ino_t i_parent; /* inode number of parent */
|
||||
ino_t i_dotdot; /* inode number of `..' */
|
||||
u_int64_t i_isize; /* size of inode */
|
||||
u_int i_numblks; /* size of block array in bytes */
|
||||
/* XXX ondisk32 */
|
||||
int32_t i_blks[1]; /* actually longer */
|
||||
} **inphead, **inpsort;
|
||||
long numdirs, listmax, inplast;
|
||||
|
||||
long dev_bsize; /* computed value of DEV_BSIZE */
|
||||
long secsize; /* actual disk sector size */
|
||||
char nflag; /* assume a no response */
|
||||
char yflag; /* assume a yes response */
|
||||
int bflag; /* location of alternate super block */
|
||||
int Uflag; /* resolve user names */
|
||||
int debug; /* output debugging info */
|
||||
int preen; /* just fix normal inconsistencies */
|
||||
char havesb; /* superblock has been read */
|
||||
char skipclean; /* skip clean file systems if preening */
|
||||
int fsmodified; /* 1 => write done to file system */
|
||||
int fsreadfd; /* file descriptor for reading file system */
|
||||
int fswritefd; /* file descriptor for writing file system */
|
||||
int rerun; /* rerun fsck. Only used in non-preen mode */
|
||||
|
||||
daddr_t maxfsblock; /* number of blocks in the file system */
|
||||
char *blockmap; /* ptr to primary blk allocation map */
|
||||
ino_t maxino; /* number of inodes in file system */
|
||||
ino_t lastino; /* last inode in use */
|
||||
char *statemap; /* ptr to inode state table */
|
||||
u_char *typemap; /* ptr to inode type table */
|
||||
int16_t *lncntp; /* ptr to link count table */
|
||||
|
||||
ino_t lfdir; /* lost & found directory inode number */
|
||||
extern const char *lfname; /* lost & found directory name */
|
||||
extern int lfmode; /* lost & found directory creation mode */
|
||||
|
||||
daddr_t n_blks; /* number of blocks in use */
|
||||
daddr_t n_files; /* number of files in use */
|
||||
|
||||
#define clearinode(dp) (*(dp) = zino)
|
||||
struct ext2fs_dinode zino;
|
||||
|
||||
#define setbmap(blkno) setbit(blockmap, blkno)
|
||||
#define testbmap(blkno) isset(blockmap, blkno)
|
||||
#define clrbmap(blkno) clrbit(blockmap, blkno)
|
||||
|
||||
#define STOP 0x01
|
||||
#define SKIP 0x02
|
||||
#define KEEPON 0x04
|
||||
#define ALTERED 0x08
|
||||
#define FOUND 0x10
|
||||
|
||||
struct ext2fs_dinode *ginode(ino_t);
|
||||
struct inoinfo *getinoinfo(ino_t);
|
||||
void getblk(struct bufarea *, daddr_t, long);
|
||||
ino_t allocino(ino_t, int);
|
||||
void copyback_sb(struct bufarea*);
|
||||
daddr_t cgoverhead(int); /* overhead per cg */
|
253
sbin/fsck_ext2fs/fsck_ext2fs.8
Normal file
253
sbin/fsck_ext2fs/fsck_ext2fs.8
Normal file
|
@ -0,0 +1,253 @@
|
|||
.\" $NetBSD: fsck_ext2fs.8,v 1.19 2010/02/21 13:26:45 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1980, 1989, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" Copyright (c) 1997 Manuel Bouyer.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)fsck.8 8.3 (Berkeley) 11/29/94
|
||||
.\"
|
||||
.Dd October 9, 2008
|
||||
.Dt FSCK_EXT2FS 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm fsck_ext2fs
|
||||
.Nd ext2 File System consistency check and interactive repair
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl dfnpUy
|
||||
.Op Fl b Ar block#
|
||||
.Op Fl c Ar level
|
||||
.Op Fl m Ar mode
|
||||
.Ar filesystem ...
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
performs interactive filesystem consistency checks and repair for each of
|
||||
the filesystems specified on the command line.
|
||||
It is normally invoked from
|
||||
.Xr fsck 8 .
|
||||
.Pp
|
||||
The kernel takes care that only a restricted class of innocuous filesystem
|
||||
inconsistencies can happen unless hardware or software failures intervene.
|
||||
These are limited to the following:
|
||||
.Pp
|
||||
.Bl -item -compact
|
||||
.It
|
||||
Unreferenced inodes
|
||||
.It
|
||||
Link counts in inodes too large
|
||||
.It
|
||||
Missing blocks in the free map
|
||||
.It
|
||||
Blocks in the free map also in files
|
||||
.It
|
||||
Counts in the super-block wrong
|
||||
.El
|
||||
.Pp
|
||||
These are the only inconsistencies that
|
||||
.Nm
|
||||
in
|
||||
.Dq preen
|
||||
mode (with the
|
||||
.Fl p
|
||||
option) will correct; if it encounters other inconsistencies, it exits
|
||||
with an abnormal return status.
|
||||
For each corrected inconsistency one or more lines will be printed
|
||||
identifying the filesystem on which the correction will take place,
|
||||
and the nature of the correction.
|
||||
After successfully correcting a filesystem,
|
||||
.Nm
|
||||
will print the number of files on that filesystem
|
||||
and the number of used and free blocks.
|
||||
.Pp
|
||||
If sent a
|
||||
.Dv QUIT
|
||||
signal,
|
||||
.Nm
|
||||
will finish the filesystem checks, then exit with an abnormal return status.
|
||||
.Pp
|
||||
Without the
|
||||
.Fl p
|
||||
option,
|
||||
.Nm
|
||||
audits and interactively repairs inconsistent conditions for filesystems.
|
||||
If the filesystem is inconsistent the operator is prompted for concurrence
|
||||
before each correction is attempted.
|
||||
It should be noted that some of the corrective actions which are not
|
||||
correctable under the
|
||||
.Fl p
|
||||
option will result in some loss of data.
|
||||
The amount and severity of data lost may be determined from the diagnostic
|
||||
output.
|
||||
The default action for each consistency correction
|
||||
is to wait for the operator to respond
|
||||
.Li yes
|
||||
or
|
||||
.Li no .
|
||||
If the operator does not have write permission on the filesystem
|
||||
.Nm
|
||||
will default to a
|
||||
.Fl n
|
||||
action.
|
||||
.Pp
|
||||
The following flags are interpreted by
|
||||
.Nm .
|
||||
.Bl -tag -width indent
|
||||
.It Fl b
|
||||
Use the block specified immediately after the flag as
|
||||
the super block for the filesystem.
|
||||
Block 8193 is usually an alternate super block.
|
||||
.It Fl d
|
||||
Print debugging output.
|
||||
.It Fl f
|
||||
Force checking of file systems.
|
||||
Normally, if a file system is cleanly unmounted, the kernel will set a
|
||||
.Dq clean flag
|
||||
in the file system superblock, and
|
||||
.Nm
|
||||
will not check the file system.
|
||||
This option forces
|
||||
.Nm
|
||||
to check the file system, regardless of the state of the clean flag.
|
||||
.It Fl m
|
||||
Use the mode specified in octal immediately after the flag as the
|
||||
permission bits to use when creating the
|
||||
.Pa lost+found
|
||||
directory rather than the default 1777.
|
||||
In particular, systems that do not wish to have lost files accessible
|
||||
by all users on the system should use a more restrictive
|
||||
set of permissions such as 700.
|
||||
.It Fl n
|
||||
Assume a no response to all questions asked by
|
||||
.Nm
|
||||
except for
|
||||
.Ql CONTINUE? ,
|
||||
which is assumed to be affirmative;
|
||||
do not open the filesystem for writing.
|
||||
.It Fl p
|
||||
Specify
|
||||
.Dq preen
|
||||
mode, described above.
|
||||
.It Fl U
|
||||
Resolve numeric userids to usernames.
|
||||
.It Fl y
|
||||
Assume a yes response to all questions asked by
|
||||
.Nm ;
|
||||
this should be used with great caution as this is a free license
|
||||
to continue after essentially unlimited trouble has been encountered.
|
||||
.El
|
||||
.Pp
|
||||
Inconsistencies checked are as follows:
|
||||
.Bl -enum -offset indent -compact
|
||||
.It
|
||||
Blocks claimed by more than one inode or the free map.
|
||||
.It
|
||||
Blocks claimed by an inode outside the range of the filesystem.
|
||||
.It
|
||||
Incorrect link counts.
|
||||
.It
|
||||
Size checks:
|
||||
.Bl -item -offset indent -compact
|
||||
.It
|
||||
Directory size not a multiple of filesystem block size.
|
||||
.It
|
||||
Partially truncated file.
|
||||
.El
|
||||
.It
|
||||
Bad inode format.
|
||||
.It
|
||||
Blocks not accounted for anywhere.
|
||||
.It
|
||||
Directory checks:
|
||||
.Bl -item -offset indent -compact
|
||||
.It
|
||||
File pointing to unallocated inode.
|
||||
.It
|
||||
Inode number out of range.
|
||||
.It
|
||||
Dot or dot-dot not the first two entries of a directory
|
||||
or having the wrong inode number.
|
||||
.El
|
||||
.It
|
||||
Super Block checks:
|
||||
.Bl -item -offset indent -compact
|
||||
.It
|
||||
More blocks for inodes than there are in the filesystem.
|
||||
.It
|
||||
Bad free block map format.
|
||||
.It
|
||||
Total free block and/or free inode count incorrect.
|
||||
.El
|
||||
.El
|
||||
.Pp
|
||||
Orphaned files and directories (allocated but unreferenced) are,
|
||||
with the operator's concurrence, reconnected by
|
||||
placing them in the
|
||||
.Pa lost+found
|
||||
directory.
|
||||
The name assigned is the inode number.
|
||||
If the
|
||||
.Pa lost+found
|
||||
directory does not exist, it is created.
|
||||
If there is insufficient space its size is increased.
|
||||
.Pp
|
||||
Because of inconsistencies between the block device and the buffer cache,
|
||||
the raw device should always be used.
|
||||
.Sh DIAGNOSTICS
|
||||
The diagnostics produced by
|
||||
.Nm
|
||||
are fully enumerated and explained in Appendix A of
|
||||
.Rs
|
||||
.%T "Fsck \- The UNIX File System Check Program"
|
||||
.Re
|
||||
.Sh SEE ALSO
|
||||
.Xr fs 5 ,
|
||||
.Xr fstab 5 ,
|
||||
.Xr fsck 8 ,
|
||||
.Xr fsdb 8 ,
|
||||
.Xr newfs 8 ,
|
||||
.Xr reboot 8
|
736
sbin/fsck_ext2fs/inode.c
Normal file
736
sbin/fsck_ext2fs/inode.c
Normal file
|
@ -0,0 +1,736 @@
|
|||
/* $NetBSD: inode.c,v 1.31 2010/02/04 23:55:42 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1980, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Manuel Bouyer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)inode.c 8.5 (Berkeley) 2/8/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: inode.c,v 1.31 2010/02/04 23:55:42 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <ufs/ext2fs/ext2fs_dinode.h>
|
||||
#include <ufs/ext2fs/ext2fs_dir.h>
|
||||
#include <ufs/ext2fs/ext2fs.h>
|
||||
|
||||
#include <ufs/ufs/dinode.h> /* for IFMT & friends */
|
||||
#ifndef SMALL
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "fsck.h"
|
||||
#include "fsutil.h"
|
||||
#include "extern.h"
|
||||
|
||||
/*
|
||||
* CG is stored in fs byte order in memory, so we can't use ino_to_fsba
|
||||
* here.
|
||||
*/
|
||||
|
||||
#define fsck_ino_to_fsba(fs, x) \
|
||||
(fs2h32((fs)->e2fs_gd[ino_to_cg(fs, x)].ext2bgd_i_tables) + \
|
||||
(((x)-1) % (fs)->e2fs.e2fs_ipg)/(fs)->e2fs_ipb)
|
||||
|
||||
|
||||
static ino_t startinum;
|
||||
|
||||
static int iblock(struct inodesc *, long, u_int64_t);
|
||||
|
||||
static int setlarge(void);
|
||||
|
||||
static int
|
||||
setlarge(void)
|
||||
{
|
||||
if (sblock.e2fs.e2fs_rev < E2FS_REV1) {
|
||||
pfatal("LARGE FILES UNSUPPORTED ON REVISION 0 FILESYSTEMS");
|
||||
return 0;
|
||||
}
|
||||
if (!(sblock.e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_LARGEFILE)) {
|
||||
if (preen)
|
||||
pwarn("SETTING LARGE FILE INDICATOR\n");
|
||||
else if (!reply("SET LARGE FILE INDICATOR"))
|
||||
return 0;
|
||||
sblock.e2fs.e2fs_features_rocompat |= EXT2F_ROCOMPAT_LARGEFILE;
|
||||
sbdirty();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
u_int64_t
|
||||
inosize(struct ext2fs_dinode *dp)
|
||||
{
|
||||
u_int64_t size = fs2h32(dp->e2di_size);
|
||||
|
||||
if ((fs2h16(dp->e2di_mode) & IFMT) == IFREG)
|
||||
size |= (u_int64_t)fs2h32(dp->e2di_dacl) << 32;
|
||||
if (size > INT32_MAX)
|
||||
(void)setlarge();
|
||||
return size;
|
||||
}
|
||||
|
||||
void
|
||||
inossize(struct ext2fs_dinode *dp, u_int64_t size)
|
||||
{
|
||||
if ((fs2h16(dp->e2di_mode) & IFMT) == IFREG) {
|
||||
dp->e2di_dacl = h2fs32(size >> 32);
|
||||
if (size > INT32_MAX)
|
||||
if (!setlarge())
|
||||
return;
|
||||
} else if (size > INT32_MAX) {
|
||||
pfatal("TRYING TO SET FILESIZE TO %llu ON MODE %x FILE\n",
|
||||
(unsigned long long)size, fs2h16(dp->e2di_mode) & IFMT);
|
||||
return;
|
||||
}
|
||||
dp->e2di_size = h2fs32(size);
|
||||
}
|
||||
|
||||
int
|
||||
ckinode(struct ext2fs_dinode *dp, struct inodesc *idesc)
|
||||
{
|
||||
u_int32_t *ap;
|
||||
long ret, n, ndb;
|
||||
struct ext2fs_dinode dino;
|
||||
u_int64_t remsize, sizepb;
|
||||
mode_t mode;
|
||||
char pathbuf[MAXPATHLEN + 1];
|
||||
|
||||
if (idesc->id_fix != IGNORE)
|
||||
idesc->id_fix = DONTKNOW;
|
||||
idesc->id_entryno = 0;
|
||||
idesc->id_filesize = inosize(dp);
|
||||
mode = fs2h16(dp->e2di_mode) & IFMT;
|
||||
if (mode == IFBLK || mode == IFCHR || mode == IFIFO ||
|
||||
(mode == IFLNK && (inosize(dp) < EXT2_MAXSYMLINKLEN)))
|
||||
return (KEEPON);
|
||||
dino = *dp;
|
||||
ndb = howmany(inosize(&dino), sblock.e2fs_bsize);
|
||||
for (ap = &dino.e2di_blocks[0]; ap < &dino.e2di_blocks[NDADDR];
|
||||
ap++,ndb--) {
|
||||
idesc->id_numfrags = 1;
|
||||
if (*ap == 0) {
|
||||
if (idesc->id_type == DATA && ndb > 0) {
|
||||
/* An empty block in a directory XXX */
|
||||
getpathname(pathbuf, sizeof(pathbuf),
|
||||
idesc->id_number, idesc->id_number);
|
||||
pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS",
|
||||
pathbuf);
|
||||
if (reply("ADJUST LENGTH") == 1) {
|
||||
dp = ginode(idesc->id_number);
|
||||
inossize(dp,
|
||||
(ap - &dino.e2di_blocks[0]) *
|
||||
sblock.e2fs_bsize);
|
||||
printf(
|
||||
"YOU MUST RERUN FSCK AFTERWARDS\n");
|
||||
rerun = 1;
|
||||
inodirty();
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
idesc->id_blkno = fs2h32(*ap);
|
||||
if (idesc->id_type == ADDR)
|
||||
ret = (*idesc->id_func)(idesc);
|
||||
else
|
||||
ret = dirscan(idesc);
|
||||
if (ret & STOP)
|
||||
return (ret);
|
||||
}
|
||||
idesc->id_numfrags = 1;
|
||||
remsize = inosize(&dino) - sblock.e2fs_bsize * NDADDR;
|
||||
sizepb = sblock.e2fs_bsize;
|
||||
for (ap = &dino.e2di_blocks[NDADDR], n = 1; n <= NIADDR; ap++, n++) {
|
||||
if (*ap) {
|
||||
idesc->id_blkno = fs2h32(*ap);
|
||||
ret = iblock(idesc, n, remsize);
|
||||
if (ret & STOP)
|
||||
return (ret);
|
||||
} else {
|
||||
if (idesc->id_type == DATA && remsize > 0) {
|
||||
/* An empty block in a directory XXX */
|
||||
getpathname(pathbuf, sizeof(pathbuf),
|
||||
idesc->id_number, idesc->id_number);
|
||||
pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS",
|
||||
pathbuf);
|
||||
if (reply("ADJUST LENGTH") == 1) {
|
||||
dp = ginode(idesc->id_number);
|
||||
inossize(dp, inosize(dp) - remsize);
|
||||
remsize = 0;
|
||||
printf(
|
||||
"YOU MUST RERUN FSCK AFTERWARDS\n");
|
||||
rerun = 1;
|
||||
inodirty();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
sizepb *= NINDIR(&sblock);
|
||||
remsize -= sizepb;
|
||||
}
|
||||
return (KEEPON);
|
||||
}
|
||||
|
||||
static int
|
||||
iblock(struct inodesc *idesc, long ilevel, u_int64_t isize)
|
||||
{
|
||||
/* XXX ondisk32 */
|
||||
int32_t *ap;
|
||||
int32_t *aplim;
|
||||
struct bufarea *bp;
|
||||
int i, n, (*func)(struct inodesc *);
|
||||
size_t nif;
|
||||
u_int64_t sizepb;
|
||||
char buf[BUFSIZ];
|
||||
char pathbuf[MAXPATHLEN + 1];
|
||||
struct ext2fs_dinode *dp;
|
||||
|
||||
if (idesc->id_type == ADDR) {
|
||||
func = idesc->id_func;
|
||||
if (((n = (*func)(idesc)) & KEEPON) == 0)
|
||||
return (n);
|
||||
} else
|
||||
func = dirscan;
|
||||
if (chkrange(idesc->id_blkno, idesc->id_numfrags))
|
||||
return (SKIP);
|
||||
bp = getdatablk(idesc->id_blkno, sblock.e2fs_bsize);
|
||||
ilevel--;
|
||||
for (sizepb = sblock.e2fs_bsize, i = 0; i < ilevel; i++)
|
||||
sizepb *= NINDIR(&sblock);
|
||||
if (isize > sizepb * NINDIR(&sblock))
|
||||
nif = NINDIR(&sblock);
|
||||
else
|
||||
nif = howmany(isize, sizepb);
|
||||
if (idesc->id_func == pass1check &&
|
||||
nif < NINDIR(&sblock)) {
|
||||
aplim = &bp->b_un.b_indir[NINDIR(&sblock)];
|
||||
for (ap = &bp->b_un.b_indir[nif]; ap < aplim; ap++) {
|
||||
if (*ap == 0)
|
||||
continue;
|
||||
(void)snprintf(buf, sizeof(buf),
|
||||
"PARTIALLY TRUNCATED INODE I=%llu",
|
||||
(unsigned long long)idesc->id_number);
|
||||
if (dofix(idesc, buf)) {
|
||||
*ap = 0;
|
||||
dirty(bp);
|
||||
}
|
||||
}
|
||||
flush(fswritefd, bp);
|
||||
}
|
||||
aplim = &bp->b_un.b_indir[nif];
|
||||
for (ap = bp->b_un.b_indir; ap < aplim; ap++) {
|
||||
if (*ap) {
|
||||
idesc->id_blkno = fs2h32(*ap);
|
||||
if (ilevel == 0)
|
||||
n = (*func)(idesc);
|
||||
else
|
||||
n = iblock(idesc, ilevel, isize);
|
||||
if (n & STOP) {
|
||||
bp->b_flags &= ~B_INUSE;
|
||||
return (n);
|
||||
}
|
||||
} else {
|
||||
if (idesc->id_type == DATA && isize > 0) {
|
||||
/* An empty block in a directory XXX */
|
||||
getpathname(pathbuf, sizeof(pathbuf),
|
||||
idesc->id_number, idesc->id_number);
|
||||
pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS",
|
||||
pathbuf);
|
||||
if (reply("ADJUST LENGTH") == 1) {
|
||||
dp = ginode(idesc->id_number);
|
||||
inossize(dp, inosize(dp) - isize);
|
||||
isize = 0;
|
||||
printf(
|
||||
"YOU MUST RERUN FSCK AFTERWARDS\n");
|
||||
rerun = 1;
|
||||
inodirty();
|
||||
bp->b_flags &= ~B_INUSE;
|
||||
return(STOP);
|
||||
}
|
||||
}
|
||||
}
|
||||
isize -= sizepb;
|
||||
}
|
||||
bp->b_flags &= ~B_INUSE;
|
||||
return (KEEPON);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that a block in a legal block number.
|
||||
* Return 0 if in range, 1 if out of range.
|
||||
*/
|
||||
int
|
||||
chkrange(daddr_t blk, int cnt)
|
||||
{
|
||||
int c, overh;
|
||||
|
||||
if ((unsigned int)(blk + cnt) > maxfsblock)
|
||||
return (1);
|
||||
c = dtog(&sblock, blk);
|
||||
overh = cgoverhead(c);
|
||||
if (blk < sblock.e2fs.e2fs_bpg * c + overh +
|
||||
sblock.e2fs.e2fs_first_dblock) {
|
||||
if ((blk + cnt) > sblock.e2fs.e2fs_bpg * c + overh +
|
||||
sblock.e2fs.e2fs_first_dblock) {
|
||||
if (debug) {
|
||||
printf("blk %lld < cgdmin %d;",
|
||||
(long long)blk,
|
||||
sblock.e2fs.e2fs_bpg * c + overh +
|
||||
sblock.e2fs.e2fs_first_dblock);
|
||||
printf(" blk + cnt %lld > cgsbase %d\n",
|
||||
(long long)(blk + cnt),
|
||||
sblock.e2fs.e2fs_bpg * c +
|
||||
overh + sblock.e2fs.e2fs_first_dblock);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
} else {
|
||||
if ((blk + cnt) > sblock.e2fs.e2fs_bpg * (c + 1) + overh +
|
||||
sblock.e2fs.e2fs_first_dblock) {
|
||||
if (debug) {
|
||||
printf("blk %lld >= cgdmin %d;",
|
||||
(long long)blk,
|
||||
sblock.e2fs.e2fs_bpg * c + overh +
|
||||
sblock.e2fs.e2fs_first_dblock);
|
||||
printf(" blk + cnt %lld > cgdmax %d\n",
|
||||
(long long)(blk+cnt),
|
||||
sblock.e2fs.e2fs_bpg * (c + 1) +
|
||||
overh + sblock.e2fs.e2fs_first_dblock);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* General purpose interface for reading inodes.
|
||||
*/
|
||||
struct ext2fs_dinode *
|
||||
ginode(ino_t inumber)
|
||||
{
|
||||
daddr_t iblk;
|
||||
struct ext2fs_dinode *dp;
|
||||
|
||||
if ((inumber < EXT2_FIRSTINO &&
|
||||
inumber != EXT2_ROOTINO &&
|
||||
!(inumber == EXT2_RESIZEINO &&
|
||||
(sblock.e2fs.e2fs_features_compat & EXT2F_COMPAT_RESIZE) != 0))
|
||||
|| inumber > maxino)
|
||||
errexit("bad inode number %llu to ginode",
|
||||
(unsigned long long)inumber);
|
||||
if (startinum == 0 ||
|
||||
inumber < startinum || inumber >= startinum + sblock.e2fs_ipb) {
|
||||
iblk = fsck_ino_to_fsba(&sblock, inumber);
|
||||
if (pbp != 0)
|
||||
pbp->b_flags &= ~B_INUSE;
|
||||
pbp = getdatablk(iblk, sblock.e2fs_bsize);
|
||||
startinum =
|
||||
((inumber - 1) / sblock.e2fs_ipb) * sblock.e2fs_ipb + 1;
|
||||
}
|
||||
dp = (struct ext2fs_dinode *)(pbp->b_un.b_buf +
|
||||
EXT2_DINODE_SIZE(&sblock) * ino_to_fsbo(&sblock, inumber));
|
||||
|
||||
return dp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Special purpose version of ginode used to optimize first pass
|
||||
* over all the inodes in numerical order.
|
||||
*/
|
||||
ino_t nextino, lastinum;
|
||||
long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize;
|
||||
char *inodebuf;
|
||||
|
||||
struct ext2fs_dinode *
|
||||
getnextinode(ino_t inumber)
|
||||
{
|
||||
long size;
|
||||
daddr_t dblk;
|
||||
struct ext2fs_dinode *dp;
|
||||
static char *bp;
|
||||
|
||||
if (inumber != nextino++ || inumber > maxino)
|
||||
errexit("bad inode number %llu to nextinode",
|
||||
(unsigned long long)inumber);
|
||||
if (inumber >= lastinum) {
|
||||
readcnt++;
|
||||
dblk = fsbtodb(&sblock, fsck_ino_to_fsba(&sblock, lastinum));
|
||||
if (readcnt % readpercg == 0) {
|
||||
size = partialsize;
|
||||
lastinum += partialcnt;
|
||||
} else {
|
||||
size = inobufsize;
|
||||
lastinum += fullcnt;
|
||||
}
|
||||
(void)bread(fsreadfd, inodebuf, dblk, size);
|
||||
bp = inodebuf;
|
||||
}
|
||||
dp = (struct ext2fs_dinode *)bp;
|
||||
bp += EXT2_DINODE_SIZE(&sblock);
|
||||
|
||||
return dp;
|
||||
}
|
||||
|
||||
void
|
||||
resetinodebuf(void)
|
||||
{
|
||||
|
||||
startinum = 0;
|
||||
nextino = 1;
|
||||
lastinum = 1;
|
||||
readcnt = 0;
|
||||
inobufsize = blkroundup(&sblock, INOBUFSIZE);
|
||||
fullcnt = inobufsize / EXT2_DINODE_SIZE(&sblock);
|
||||
readpercg = sblock.e2fs.e2fs_ipg / fullcnt;
|
||||
partialcnt = sblock.e2fs.e2fs_ipg % fullcnt;
|
||||
partialsize = partialcnt * EXT2_DINODE_SIZE(&sblock);
|
||||
if (partialcnt != 0) {
|
||||
readpercg++;
|
||||
} else {
|
||||
partialcnt = fullcnt;
|
||||
partialsize = inobufsize;
|
||||
}
|
||||
if (inodebuf == NULL &&
|
||||
(inodebuf = malloc((unsigned int)inobufsize)) == NULL)
|
||||
errexit("Cannot allocate space for inode buffer");
|
||||
while (nextino < EXT2_ROOTINO)
|
||||
(void)getnextinode(nextino);
|
||||
}
|
||||
|
||||
void
|
||||
freeinodebuf(void)
|
||||
{
|
||||
|
||||
if (inodebuf != NULL)
|
||||
free(inodebuf);
|
||||
inodebuf = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Routines to maintain information about directory inodes.
|
||||
* This is built during the first pass and used during the
|
||||
* second and third passes.
|
||||
*
|
||||
* Enter inodes into the cache.
|
||||
*/
|
||||
void
|
||||
cacheino(struct ext2fs_dinode *dp, ino_t inumber)
|
||||
{
|
||||
struct inoinfo *inp;
|
||||
struct inoinfo **inpp;
|
||||
unsigned int blks;
|
||||
|
||||
blks = howmany(inosize(dp), sblock.e2fs_bsize);
|
||||
if (blks > NDADDR)
|
||||
blks = NDADDR + NIADDR;
|
||||
/* XXX ondisk32 */
|
||||
inp = malloc(sizeof(*inp) + (blks - 1) * sizeof(int32_t));
|
||||
if (inp == NULL)
|
||||
return;
|
||||
inpp = &inphead[inumber % numdirs];
|
||||
inp->i_nexthash = *inpp;
|
||||
*inpp = inp;
|
||||
inp->i_child = inp->i_sibling = inp->i_parentp = 0;
|
||||
if (inumber == EXT2_ROOTINO)
|
||||
inp->i_parent = EXT2_ROOTINO;
|
||||
else
|
||||
inp->i_parent = (ino_t)0;
|
||||
inp->i_dotdot = (ino_t)0;
|
||||
inp->i_number = inumber;
|
||||
inp->i_isize = inosize(dp);
|
||||
/* XXX ondisk32 */
|
||||
inp->i_numblks = blks * sizeof(int32_t);
|
||||
memcpy(&inp->i_blks[0], &dp->e2di_blocks[0], (size_t)inp->i_numblks);
|
||||
if (inplast == listmax) {
|
||||
listmax += 100;
|
||||
inpsort = (struct inoinfo **)realloc((char *)inpsort,
|
||||
(unsigned int)listmax * sizeof(struct inoinfo *));
|
||||
if (inpsort == NULL)
|
||||
errexit("cannot increase directory list");
|
||||
}
|
||||
inpsort[inplast++] = inp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up an inode cache structure.
|
||||
*/
|
||||
struct inoinfo *
|
||||
getinoinfo(ino_t inumber)
|
||||
{
|
||||
struct inoinfo *inp;
|
||||
|
||||
for (inp = inphead[inumber % numdirs]; inp; inp = inp->i_nexthash) {
|
||||
if (inp->i_number != inumber)
|
||||
continue;
|
||||
return (inp);
|
||||
}
|
||||
errexit("cannot find inode %llu", (unsigned long long)inumber);
|
||||
return ((struct inoinfo *)0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up all the inode cache structure.
|
||||
*/
|
||||
void
|
||||
inocleanup(void)
|
||||
{
|
||||
struct inoinfo **inpp;
|
||||
|
||||
if (inphead == NULL)
|
||||
return;
|
||||
for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--)
|
||||
free(*inpp);
|
||||
free(inphead);
|
||||
free(inpsort);
|
||||
inphead = inpsort = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
inodirty(void)
|
||||
{
|
||||
|
||||
dirty(pbp);
|
||||
}
|
||||
|
||||
void
|
||||
clri(struct inodesc *idesc, const char *type, int flag)
|
||||
{
|
||||
struct ext2fs_dinode *dp;
|
||||
|
||||
dp = ginode(idesc->id_number);
|
||||
if (flag == 1) {
|
||||
pwarn("%s %s", type,
|
||||
(fs2h16(dp->e2di_mode) & IFMT) == IFDIR ? "DIR" : "FILE");
|
||||
pinode(idesc->id_number);
|
||||
}
|
||||
if (preen || reply("CLEAR") == 1) {
|
||||
if (preen)
|
||||
printf(" (CLEARED)\n");
|
||||
n_files--;
|
||||
(void)ckinode(dp, idesc);
|
||||
clearinode(dp);
|
||||
statemap[idesc->id_number] = USTATE;
|
||||
inodirty();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
findname(struct inodesc *idesc)
|
||||
{
|
||||
struct ext2fs_direct *dirp = idesc->id_dirp;
|
||||
u_int16_t namlen = dirp->e2d_namlen;
|
||||
/* from utilities.c namebuf[] variable */
|
||||
char *buf = __UNCONST(idesc->id_name);
|
||||
if (namlen > MAXPATHLEN) {
|
||||
/* XXX: Prevent overflow but don't fix */
|
||||
namlen = MAXPATHLEN;
|
||||
}
|
||||
|
||||
if (fs2h32(dirp->e2d_ino) != idesc->id_parent)
|
||||
return (KEEPON);
|
||||
(void)memcpy(buf, dirp->e2d_name, (size_t)namlen);
|
||||
buf[namlen] = '\0';
|
||||
return (STOP|FOUND);
|
||||
}
|
||||
|
||||
int
|
||||
findino(struct inodesc *idesc)
|
||||
{
|
||||
struct ext2fs_direct *dirp = idesc->id_dirp;
|
||||
u_int32_t ino = fs2h32(dirp->e2d_ino);
|
||||
|
||||
if (ino == 0)
|
||||
return (KEEPON);
|
||||
if (strcmp(dirp->e2d_name, idesc->id_name) == 0 &&
|
||||
(ino == EXT2_ROOTINO || ino >= EXT2_FIRSTINO)
|
||||
&& ino <= maxino) {
|
||||
idesc->id_parent = ino;
|
||||
return (STOP|FOUND);
|
||||
}
|
||||
return (KEEPON);
|
||||
}
|
||||
|
||||
void
|
||||
pinode(ino_t ino)
|
||||
{
|
||||
struct ext2fs_dinode *dp;
|
||||
struct passwd *pw;
|
||||
uid_t uid;
|
||||
|
||||
printf(" I=%llu ", (unsigned long long)ino);
|
||||
if ((ino < EXT2_FIRSTINO && ino != EXT2_ROOTINO) || ino > maxino)
|
||||
return;
|
||||
dp = ginode(ino);
|
||||
uid = fs2h16(dp->e2di_uid);
|
||||
if (sblock.e2fs.e2fs_rev > E2FS_REV0)
|
||||
uid |= fs2h16(dp->e2di_uid_high) << 16;
|
||||
printf(" OWNER=");
|
||||
#ifndef SMALL
|
||||
if (Uflag && (pw = getpwuid(uid)) != 0)
|
||||
printf("%s ", pw->pw_name);
|
||||
else
|
||||
#endif
|
||||
printf("%u ", (unsigned int)uid);
|
||||
printf("MODE=%o\n", fs2h16(dp->e2di_mode));
|
||||
if (preen)
|
||||
printf("%s: ", cdevname());
|
||||
printf("SIZE=%llu ", (long long)inosize(dp));
|
||||
printf("MTIME=%s ", print_mtime(fs2h32(dp->e2di_mtime)));
|
||||
}
|
||||
|
||||
void
|
||||
blkerror(ino_t ino, const char *type, daddr_t blk)
|
||||
{
|
||||
|
||||
pfatal("%lld %s I=%llu", (long long)blk, type, (unsigned long long)ino);
|
||||
printf("\n");
|
||||
switch (statemap[ino]) {
|
||||
|
||||
case FSTATE:
|
||||
statemap[ino] = FCLEAR;
|
||||
return;
|
||||
|
||||
case DSTATE:
|
||||
statemap[ino] = DCLEAR;
|
||||
return;
|
||||
|
||||
case FCLEAR:
|
||||
case DCLEAR:
|
||||
return;
|
||||
|
||||
default:
|
||||
errexit("BAD STATE %d TO BLKERR", statemap[ino]);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate an unused inode
|
||||
*/
|
||||
ino_t
|
||||
allocino(ino_t request, int type)
|
||||
{
|
||||
ino_t ino;
|
||||
struct ext2fs_dinode *dp;
|
||||
time_t t;
|
||||
|
||||
if (request == 0)
|
||||
request = EXT2_ROOTINO;
|
||||
else if (statemap[request] != USTATE)
|
||||
return (0);
|
||||
for (ino = request; ino < maxino; ino++) {
|
||||
if ((ino > EXT2_ROOTINO) && (ino < EXT2_FIRSTINO))
|
||||
continue;
|
||||
if (statemap[ino] == USTATE)
|
||||
break;
|
||||
}
|
||||
if (ino == maxino)
|
||||
return (0);
|
||||
switch (type & IFMT) {
|
||||
case IFDIR:
|
||||
statemap[ino] = DSTATE;
|
||||
break;
|
||||
case IFREG:
|
||||
case IFLNK:
|
||||
statemap[ino] = FSTATE;
|
||||
break;
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
dp = ginode(ino);
|
||||
dp->e2di_blocks[0] = h2fs32(allocblk());
|
||||
if (dp->e2di_blocks[0] == 0) {
|
||||
statemap[ino] = USTATE;
|
||||
return (0);
|
||||
}
|
||||
dp->e2di_mode = h2fs16(type);
|
||||
(void)time(&t);
|
||||
dp->e2di_atime = h2fs32(t);
|
||||
dp->e2di_mtime = dp->e2di_ctime = dp->e2di_atime;
|
||||
dp->e2di_dtime = 0;
|
||||
inossize(dp, sblock.e2fs_bsize);
|
||||
dp->e2di_nblock = h2fs32(btodb(sblock.e2fs_bsize));
|
||||
n_files++;
|
||||
inodirty();
|
||||
typemap[ino] = E2IFTODT(type);
|
||||
return (ino);
|
||||
}
|
||||
|
||||
/*
|
||||
* deallocate an inode
|
||||
*/
|
||||
void
|
||||
freeino(ino_t ino)
|
||||
{
|
||||
struct inodesc idesc;
|
||||
struct ext2fs_dinode *dp;
|
||||
|
||||
memset(&idesc, 0, sizeof(struct inodesc));
|
||||
idesc.id_type = ADDR;
|
||||
idesc.id_func = pass4check;
|
||||
idesc.id_number = ino;
|
||||
dp = ginode(ino);
|
||||
(void)ckinode(dp, &idesc);
|
||||
clearinode(dp);
|
||||
inodirty();
|
||||
statemap[ino] = USTATE;
|
||||
n_files--;
|
||||
}
|
358
sbin/fsck_ext2fs/main.c
Normal file
358
sbin/fsck_ext2fs/main.c
Normal file
|
@ -0,0 +1,358 @@
|
|||
/* $NetBSD: main.c,v 1.37 2011/06/09 19:57:51 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1980, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Manuel Bouyer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__COPYRIGHT("@(#) Copyright (c) 1980, 1986, 1993\
|
||||
The Regents of the University of California. All rights reserved.");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)main.c 8.2 (Berkeley) 1/23/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: main.c,v 1.37 2011/06/09 19:57:51 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/mount.h>
|
||||
#include <ufs/ufs/ufsmount.h>
|
||||
#include <ufs/ext2fs/ext2fs_dinode.h>
|
||||
#include <ufs/ext2fs/ext2fs.h>
|
||||
#include <fstab.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "fsck.h"
|
||||
#include "extern.h"
|
||||
#include "fsutil.h"
|
||||
#include "exitvalues.h"
|
||||
|
||||
volatile sig_atomic_t returntosingle = 0;
|
||||
|
||||
|
||||
static int argtoi(int, const char *, const char *, int);
|
||||
static int checkfilesys(const char *, char *, long, int);
|
||||
static void usage(void) __dead;
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ch;
|
||||
int ret = FSCK_EXIT_OK;
|
||||
|
||||
ckfinish = ckfini;
|
||||
sync();
|
||||
skipclean = 1;
|
||||
while ((ch = getopt(argc, argv, "b:dfm:npPqUy")) != -1) {
|
||||
switch (ch) {
|
||||
case 'b':
|
||||
skipclean = 0;
|
||||
bflag = argtoi('b', "number", optarg, 10);
|
||||
printf("Alternate super block location: %d\n", bflag);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
debug++;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
skipclean = 0;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
lfmode = argtoi('m', "mode", optarg, 8);
|
||||
if (lfmode &~ 07777)
|
||||
errexit("bad mode to -m: %o", lfmode);
|
||||
printf("** lost+found creation mode %o\n", lfmode);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
nflag++;
|
||||
yflag = 0;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
preen++;
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
/* Progress meter not implemented. */
|
||||
break;
|
||||
|
||||
case 'q': /* Quiet not implemented */
|
||||
break;
|
||||
|
||||
#ifndef SMALL
|
||||
case 'U':
|
||||
Uflag++;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 'y':
|
||||
yflag++;
|
||||
nflag = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (!argc)
|
||||
usage();
|
||||
|
||||
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
|
||||
(void)signal(SIGINT, catch);
|
||||
if (preen)
|
||||
(void)signal(SIGQUIT, catchquit);
|
||||
|
||||
while (argc-- > 0) {
|
||||
int nret = checkfilesys(blockcheck(*argv++), 0, 0L, 0);
|
||||
if (ret < nret)
|
||||
ret = nret;
|
||||
}
|
||||
|
||||
return returntosingle ? FSCK_EXIT_UNRESOLVED : ret;
|
||||
}
|
||||
|
||||
static int
|
||||
argtoi(int flag, const char *req, const char *str, int base)
|
||||
{
|
||||
char *cp;
|
||||
int ret;
|
||||
|
||||
ret = (int)strtol(str, &cp, base);
|
||||
if (cp == str || *cp)
|
||||
errexit("-%c flag requires a %s", flag, req);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the specified filesystem.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
checkfilesys(const char *filesys, char *mntpt, long auxdata, int child)
|
||||
{
|
||||
daddr_t n_bfree;
|
||||
struct dups *dp;
|
||||
struct zlncnt *zlnp;
|
||||
int i;
|
||||
|
||||
if (preen && child)
|
||||
(void)signal(SIGQUIT, voidquit);
|
||||
setcdevname(filesys, preen);
|
||||
if (debug && preen)
|
||||
pwarn("starting\n");
|
||||
switch (setup(filesys)) {
|
||||
case 0:
|
||||
if (preen)
|
||||
pfatal("CAN'T CHECK FILE SYSTEM.");
|
||||
case -1:
|
||||
return FSCK_EXIT_OK;
|
||||
}
|
||||
/*
|
||||
* 1: scan inodes tallying blocks used
|
||||
*/
|
||||
if (preen == 0) {
|
||||
if (sblock.e2fs.e2fs_rev > E2FS_REV0) {
|
||||
printf("** Last Mounted on %s\n",
|
||||
sblock.e2fs.e2fs_fsmnt);
|
||||
}
|
||||
if (hotroot())
|
||||
printf("** Root file system\n");
|
||||
printf("** Phase 1 - Check Blocks and Sizes\n");
|
||||
}
|
||||
pass1();
|
||||
|
||||
/*
|
||||
* 1b: locate first references to duplicates, if any
|
||||
*/
|
||||
if (duplist) {
|
||||
if (preen)
|
||||
pfatal("INTERNAL ERROR: dups with -p");
|
||||
printf("** Phase 1b - Rescan For More DUPS\n");
|
||||
pass1b();
|
||||
}
|
||||
|
||||
/*
|
||||
* 2: traverse directories from root to mark all connected directories
|
||||
*/
|
||||
if (preen == 0)
|
||||
printf("** Phase 2 - Check Pathnames\n");
|
||||
pass2();
|
||||
|
||||
/*
|
||||
* 3: scan inodes looking for disconnected directories
|
||||
*/
|
||||
if (preen == 0)
|
||||
printf("** Phase 3 - Check Connectivity\n");
|
||||
pass3();
|
||||
|
||||
/*
|
||||
* 4: scan inodes looking for disconnected files; check reference counts
|
||||
*/
|
||||
if (preen == 0)
|
||||
printf("** Phase 4 - Check Reference Counts\n");
|
||||
pass4();
|
||||
|
||||
/*
|
||||
* 5: check and repair resource counts in cylinder groups
|
||||
*/
|
||||
if (preen == 0)
|
||||
printf("** Phase 5 - Check Cyl groups\n");
|
||||
pass5();
|
||||
|
||||
/*
|
||||
* print out summary statistics
|
||||
*/
|
||||
n_bfree = sblock.e2fs.e2fs_fbcount;
|
||||
|
||||
pwarn("%lld files, %lld used, %lld free\n",
|
||||
(long long)n_files, (long long)n_blks, (long long)n_bfree);
|
||||
if (debug &&
|
||||
/* 9 reserved and unused inodes in FS */
|
||||
(n_files -= maxino - 9 - sblock.e2fs.e2fs_ficount))
|
||||
printf("%lld files missing\n", (long long)n_files);
|
||||
if (debug) {
|
||||
for (i = 0; i < sblock.e2fs_ncg; i++)
|
||||
n_blks += cgoverhead(i);
|
||||
n_blks += sblock.e2fs.e2fs_first_dblock;
|
||||
if (n_blks -= maxfsblock - n_bfree)
|
||||
printf("%lld blocks missing\n", (long long)n_blks);
|
||||
if (duplist != NULL) {
|
||||
printf("The following duplicate blocks remain:");
|
||||
for (dp = duplist; dp; dp = dp->next)
|
||||
printf(" %lld,", (long long)dp->dup);
|
||||
printf("\n");
|
||||
}
|
||||
if (zlnhead != NULL) {
|
||||
printf("The following zero link count inodes remain:");
|
||||
for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
|
||||
printf(" %llu,",
|
||||
(unsigned long long)zlnp->zlncnt);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
zlnhead = (struct zlncnt *)0;
|
||||
duplist = (struct dups *)0;
|
||||
muldup = (struct dups *)0;
|
||||
inocleanup();
|
||||
if (fsmodified) {
|
||||
time_t t;
|
||||
(void)time(&t);
|
||||
sblock.e2fs.e2fs_wtime = t;
|
||||
sblock.e2fs.e2fs_lastfsck = t;
|
||||
sbdirty();
|
||||
}
|
||||
ckfini(1);
|
||||
free(blockmap);
|
||||
free(statemap);
|
||||
free((char *)lncntp);
|
||||
if (!fsmodified)
|
||||
return FSCK_EXIT_OK;
|
||||
if (!preen)
|
||||
printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
|
||||
if (rerun)
|
||||
printf("\n***** PLEASE RERUN FSCK *****\n");
|
||||
#ifndef __minix
|
||||
if (hotroot()) {
|
||||
struct statvfs stfs_buf;
|
||||
/*
|
||||
* We modified the root. Do a mount update on
|
||||
* it, unless it is read-write, so we can continue.
|
||||
*/
|
||||
if (statvfs("/", &stfs_buf) == 0) {
|
||||
long flags = stfs_buf.f_flag;
|
||||
struct ufs_args args;
|
||||
|
||||
if (flags & MNT_RDONLY) {
|
||||
args.fspec = 0;
|
||||
flags |= MNT_UPDATE | MNT_RELOAD;
|
||||
if (mount(MOUNT_EXT2FS, "/", flags,
|
||||
&args, sizeof args) == 0)
|
||||
return FSCK_EXIT_OK;
|
||||
}
|
||||
}
|
||||
if (!preen)
|
||||
printf("\n***** REBOOT NOW *****\n");
|
||||
sync();
|
||||
return FSCK_EXIT_ROOT_CHANGED;
|
||||
}
|
||||
#endif
|
||||
return FSCK_EXIT_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
(void) fprintf(stderr,
|
||||
"usage: %s [-dfnpUy] [-b block] [-c level] [-m mode] filesystem ...\n",
|
||||
getprogname());
|
||||
exit(FSCK_EXIT_USAGE);
|
||||
}
|
||||
|
394
sbin/fsck_ext2fs/pass1.c
Normal file
394
sbin/fsck_ext2fs/pass1.c
Normal file
|
@ -0,0 +1,394 @@
|
|||
/* $NetBSD: pass1.c,v 1.21 2010/02/04 23:55:42 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1980, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Manuel Bouyer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)pass1.c 8.1 (Berkeley) 6/5/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: pass1.c,v 1.21 2010/02/04 23:55:42 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <ufs/ext2fs/ext2fs_dinode.h>
|
||||
#include <ufs/ext2fs/ext2fs_dir.h>
|
||||
#include <ufs/ext2fs/ext2fs.h>
|
||||
|
||||
#include <ufs/ufs/dinode.h> /* for IFMT & friends */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "fsck.h"
|
||||
#include "extern.h"
|
||||
#include "fsutil.h"
|
||||
#include "exitvalues.h"
|
||||
|
||||
static daddr_t badblk;
|
||||
static daddr_t dupblk;
|
||||
static void checkinode(ino_t, struct inodesc *);
|
||||
|
||||
void
|
||||
pass1(void)
|
||||
{
|
||||
ino_t inumber;
|
||||
int c, i;
|
||||
size_t j;
|
||||
daddr_t dbase;
|
||||
struct inodesc idesc;
|
||||
|
||||
/*
|
||||
* Set file system reserved blocks in used block map.
|
||||
*/
|
||||
for (c = 0; c < sblock.e2fs_ncg; c++) {
|
||||
dbase = c * sblock.e2fs.e2fs_bpg +
|
||||
sblock.e2fs.e2fs_first_dblock;
|
||||
/* Mark the blocks used for the inode table */
|
||||
if (fs2h32(sblock.e2fs_gd[c].ext2bgd_i_tables) >= dbase) {
|
||||
for (i = 0; i < sblock.e2fs_itpg; i++)
|
||||
setbmap(
|
||||
fs2h32(sblock.e2fs_gd[c].ext2bgd_i_tables)
|
||||
+ i);
|
||||
}
|
||||
/* Mark the blocks used for the block bitmap */
|
||||
if (fs2h32(sblock.e2fs_gd[c].ext2bgd_b_bitmap) >= dbase)
|
||||
setbmap(fs2h32(sblock.e2fs_gd[c].ext2bgd_b_bitmap));
|
||||
/* Mark the blocks used for the inode bitmap */
|
||||
if (fs2h32(sblock.e2fs_gd[c].ext2bgd_i_bitmap) >= dbase)
|
||||
setbmap(fs2h32(sblock.e2fs_gd[c].ext2bgd_i_bitmap));
|
||||
|
||||
if (sblock.e2fs.e2fs_rev == E2FS_REV0 ||
|
||||
(sblock.e2fs.e2fs_features_rocompat &
|
||||
EXT2F_ROCOMPAT_SPARSESUPER) == 0 ||
|
||||
cg_has_sb(c)) {
|
||||
/* Mark copuy of SB and descriptors */
|
||||
setbmap(dbase);
|
||||
for (i = 1; i <= sblock.e2fs_ngdb; i++)
|
||||
setbmap(dbase+i);
|
||||
}
|
||||
|
||||
|
||||
if (c == 0) {
|
||||
for(i = 0; i < dbase; i++)
|
||||
setbmap(i);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find all allocated blocks.
|
||||
*/
|
||||
memset(&idesc, 0, sizeof(struct inodesc));
|
||||
idesc.id_type = ADDR;
|
||||
idesc.id_func = pass1check;
|
||||
inumber = 1;
|
||||
n_files = n_blks = 0;
|
||||
resetinodebuf();
|
||||
for (c = 0; c < sblock.e2fs_ncg; c++) {
|
||||
for (j = 0;
|
||||
j < sblock.e2fs.e2fs_ipg && inumber <= sblock.e2fs.e2fs_icount;
|
||||
j++, inumber++) {
|
||||
if (inumber < EXT2_ROOTINO) /* XXX */
|
||||
continue;
|
||||
checkinode(inumber, &idesc);
|
||||
}
|
||||
}
|
||||
freeinodebuf();
|
||||
}
|
||||
|
||||
static void
|
||||
checkinode(ino_t inumber, struct inodesc *idesc)
|
||||
{
|
||||
struct ext2fs_dinode *dp;
|
||||
struct zlncnt *zlnp;
|
||||
int ndb, j;
|
||||
mode_t mode;
|
||||
|
||||
dp = getnextinode(inumber);
|
||||
if (inumber < EXT2_FIRSTINO &&
|
||||
inumber != EXT2_ROOTINO &&
|
||||
!(inumber == EXT2_RESIZEINO &&
|
||||
(sblock.e2fs.e2fs_features_compat & EXT2F_COMPAT_RESIZE) != 0))
|
||||
return;
|
||||
|
||||
mode = fs2h16(dp->e2di_mode) & IFMT;
|
||||
if (mode == 0 || (dp->e2di_dtime != 0 && dp->e2di_nlink == 0)) {
|
||||
if (mode == 0 && (
|
||||
memcmp(dp->e2di_blocks, zino.e2di_blocks,
|
||||
(NDADDR + NIADDR) * sizeof(u_int32_t)) ||
|
||||
dp->e2di_mode || inosize(dp))) {
|
||||
pfatal("PARTIALLY ALLOCATED INODE I=%llu",
|
||||
(unsigned long long)inumber);
|
||||
if (reply("CLEAR") == 1) {
|
||||
dp = ginode(inumber);
|
||||
clearinode(dp);
|
||||
inodirty();
|
||||
}
|
||||
}
|
||||
#ifdef notyet /* it seems that dtime == 0 is valid for a unallocated inode */
|
||||
if (dp->e2di_dtime == 0) {
|
||||
pwarn("DELETED INODE I=%llu HAS A NULL DTIME",
|
||||
(unsigned long long)inumber);
|
||||
if (preen) {
|
||||
printf(" (CORRECTED)\n");
|
||||
}
|
||||
if (preen || reply("CORRECT")) {
|
||||
time_t t;
|
||||
time(&t);
|
||||
dp->e2di_dtime = h2fs32(t);
|
||||
dp = ginode(inumber);
|
||||
inodirty();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
statemap[inumber] = USTATE;
|
||||
return;
|
||||
}
|
||||
lastino = inumber;
|
||||
if (dp->e2di_dtime != 0) {
|
||||
pwarn("INODE I=%llu HAS DTIME=%s",
|
||||
(unsigned long long)inumber,
|
||||
print_mtime(fs2h32(dp->e2di_dtime)));
|
||||
if (preen) {
|
||||
printf(" (CORRECTED)\n");
|
||||
}
|
||||
if (preen || reply("CORRECT")) {
|
||||
dp = ginode(inumber);
|
||||
dp->e2di_dtime = 0;
|
||||
inodirty();
|
||||
}
|
||||
}
|
||||
if (inosize(dp) + sblock.e2fs_bsize - 1 < inosize(dp)) {
|
||||
if (debug)
|
||||
printf("bad size %llu:", (unsigned long long)inosize(dp));
|
||||
goto unknown;
|
||||
}
|
||||
if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) {
|
||||
dp = ginode(inumber);
|
||||
dp->e2di_mode = h2fs16(IFREG|0600);
|
||||
inossize(dp, sblock.e2fs_bsize);
|
||||
inodirty();
|
||||
}
|
||||
ndb = howmany(inosize(dp), sblock.e2fs_bsize);
|
||||
if (ndb < 0) {
|
||||
if (debug)
|
||||
printf("bad size %llu ndb %d:",
|
||||
(unsigned long long)inosize(dp), ndb);
|
||||
goto unknown;
|
||||
}
|
||||
if (mode == IFBLK || mode == IFCHR)
|
||||
ndb++;
|
||||
if (mode == IFLNK) {
|
||||
/*
|
||||
* Fake ndb value so direct/indirect block checks below
|
||||
* will detect any garbage after symlink string.
|
||||
*/
|
||||
if (inosize(dp) < EXT2_MAXSYMLINKLEN ||
|
||||
(EXT2_MAXSYMLINKLEN == 0 && dp->e2di_blocks == 0)) {
|
||||
ndb = howmany(inosize(dp), sizeof(u_int32_t));
|
||||
if (ndb > NDADDR) {
|
||||
j = ndb - NDADDR;
|
||||
for (ndb = 1; j > 1; j--)
|
||||
ndb *= NINDIR(&sblock);
|
||||
ndb += NDADDR;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Linux puts things in blocks for FIFO, so skip this check */
|
||||
if (mode != IFIFO) {
|
||||
for (j = ndb; j < NDADDR; j++)
|
||||
if (dp->e2di_blocks[j] != 0) {
|
||||
if (debug)
|
||||
printf("bad direct addr: %d\n",
|
||||
fs2h32(dp->e2di_blocks[j]));
|
||||
goto unknown;
|
||||
}
|
||||
for (j = 0, ndb -= NDADDR; ndb > 0; j++)
|
||||
ndb /= NINDIR(&sblock);
|
||||
for (; j < NIADDR; j++) {
|
||||
if (dp->e2di_blocks[j+NDADDR] != 0) {
|
||||
if (debug)
|
||||
printf("bad indirect addr: %d\n",
|
||||
fs2h32(dp->e2di_blocks[j+NDADDR]));
|
||||
goto unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ftypeok(dp) == 0)
|
||||
goto unknown;
|
||||
if (inumber >= EXT2_FIRSTINO || inumber == EXT2_ROOTINO) {
|
||||
/* Don't count reserved inodes except root */
|
||||
n_files++;
|
||||
}
|
||||
lncntp[inumber] = fs2h16(dp->e2di_nlink);
|
||||
if (dp->e2di_nlink == 0) {
|
||||
zlnp = malloc(sizeof *zlnp);
|
||||
if (zlnp == NULL) {
|
||||
pfatal("LINK COUNT TABLE OVERFLOW");
|
||||
if (reply("CONTINUE") == 0)
|
||||
exit(FSCK_EXIT_CHECK_FAILED);
|
||||
} else {
|
||||
zlnp->zlncnt = inumber;
|
||||
zlnp->next = zlnhead;
|
||||
zlnhead = zlnp;
|
||||
}
|
||||
}
|
||||
if (mode == IFDIR) {
|
||||
if (inosize(dp) == 0)
|
||||
statemap[inumber] = DCLEAR;
|
||||
else
|
||||
statemap[inumber] = DSTATE;
|
||||
cacheino(dp, inumber);
|
||||
} else {
|
||||
statemap[inumber] = FSTATE;
|
||||
}
|
||||
typemap[inumber] = E2IFTODT(mode);
|
||||
badblk = dupblk = 0;
|
||||
idesc->id_number = inumber;
|
||||
(void)ckinode(dp, idesc);
|
||||
idesc->id_entryno *= btodb(sblock.e2fs_bsize);
|
||||
if (fs2h32(dp->e2di_nblock) != (uint32_t)idesc->id_entryno) {
|
||||
pwarn("INCORRECT BLOCK COUNT I=%llu (%d should be %d)",
|
||||
(unsigned long long)inumber, fs2h32(dp->e2di_nblock),
|
||||
idesc->id_entryno);
|
||||
if (preen)
|
||||
printf(" (CORRECTED)\n");
|
||||
else if (reply("CORRECT") == 0)
|
||||
return;
|
||||
dp = ginode(inumber);
|
||||
dp->e2di_nblock = h2fs32(idesc->id_entryno);
|
||||
inodirty();
|
||||
}
|
||||
return;
|
||||
unknown:
|
||||
pfatal("UNKNOWN FILE TYPE I=%llu", (unsigned long long)inumber);
|
||||
statemap[inumber] = FCLEAR;
|
||||
if (reply("CLEAR") == 1) {
|
||||
statemap[inumber] = USTATE;
|
||||
dp = ginode(inumber);
|
||||
clearinode(dp);
|
||||
inodirty();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
pass1check(struct inodesc *idesc)
|
||||
{
|
||||
int res = KEEPON;
|
||||
int anyout, nfrags;
|
||||
daddr_t blkno = idesc->id_blkno;
|
||||
struct dups *dlp;
|
||||
struct dups *new;
|
||||
|
||||
if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) {
|
||||
blkerror(idesc->id_number, "BAD", blkno);
|
||||
if (badblk++ >= MAXBAD) {
|
||||
pwarn("EXCESSIVE BAD BLKS I=%llu",
|
||||
(unsigned long long)idesc->id_number);
|
||||
if (preen)
|
||||
printf(" (SKIPPING)\n");
|
||||
else if (reply("CONTINUE") == 0)
|
||||
exit(FSCK_EXIT_CHECK_FAILED);
|
||||
return (STOP);
|
||||
}
|
||||
}
|
||||
for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
|
||||
if (anyout && chkrange(blkno, 1)) {
|
||||
res = SKIP;
|
||||
} else if (!testbmap(blkno)) {
|
||||
n_blks++;
|
||||
setbmap(blkno);
|
||||
} else {
|
||||
blkerror(idesc->id_number, "DUP", blkno);
|
||||
if (dupblk++ >= MAXDUP) {
|
||||
pwarn("EXCESSIVE DUP BLKS I=%llu",
|
||||
(unsigned long long)idesc->id_number);
|
||||
if (preen)
|
||||
printf(" (SKIPPING)\n");
|
||||
else if (reply("CONTINUE") == 0)
|
||||
exit(FSCK_EXIT_CHECK_FAILED);
|
||||
return (STOP);
|
||||
}
|
||||
new = malloc(sizeof(struct dups));
|
||||
if (new == NULL) {
|
||||
pfatal("DUP TABLE OVERFLOW.");
|
||||
if (reply("CONTINUE") == 0)
|
||||
exit(FSCK_EXIT_CHECK_FAILED);
|
||||
return (STOP);
|
||||
}
|
||||
new->dup = blkno;
|
||||
if (muldup == 0) {
|
||||
duplist = muldup = new;
|
||||
new->next = 0;
|
||||
} else {
|
||||
new->next = muldup->next;
|
||||
muldup->next = new;
|
||||
}
|
||||
for (dlp = duplist; dlp != muldup; dlp = dlp->next)
|
||||
if (dlp->dup == blkno)
|
||||
break;
|
||||
if (dlp == muldup && dlp->dup != blkno)
|
||||
muldup = new;
|
||||
}
|
||||
/*
|
||||
* count the number of blocks found in id_entryno
|
||||
*/
|
||||
idesc->id_entryno++;
|
||||
}
|
||||
return (res);
|
||||
}
|
130
sbin/fsck_ext2fs/pass1b.c
Normal file
130
sbin/fsck_ext2fs/pass1b.c
Normal file
|
@ -0,0 +1,130 @@
|
|||
/* $NetBSD: pass1b.c,v 1.8 2009/10/19 18:41:08 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1980, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Manuel Bouyer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)pass1b.c 8.1 (Berkeley) 6/5/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: pass1b.c,v 1.8 2009/10/19 18:41:08 bouyer Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <ufs/ext2fs/ext2fs_dinode.h>
|
||||
#include <ufs/ext2fs/ext2fs.h>
|
||||
|
||||
#include <string.h>
|
||||
#include "fsck.h"
|
||||
#include "extern.h"
|
||||
|
||||
static int pass1bcheck(struct inodesc *);
|
||||
static struct dups *duphead;
|
||||
|
||||
void
|
||||
pass1b(void)
|
||||
{
|
||||
int c;
|
||||
uint32_t i;
|
||||
struct ext2fs_dinode *dp;
|
||||
struct inodesc idesc;
|
||||
ino_t inumber;
|
||||
|
||||
memset(&idesc, 0, sizeof(struct inodesc));
|
||||
idesc.id_type = ADDR;
|
||||
idesc.id_func = pass1bcheck;
|
||||
duphead = duplist;
|
||||
inumber = 0;
|
||||
for (c = 0; c < sblock.e2fs_ncg; c++) {
|
||||
for (i = 0; i < sblock.e2fs.e2fs_ipg; i++, inumber++) {
|
||||
if ((inumber < EXT2_FIRSTINO) && (inumber != EXT2_ROOTINO))
|
||||
continue;
|
||||
dp = ginode(inumber);
|
||||
if (dp == NULL)
|
||||
continue;
|
||||
idesc.id_number = inumber;
|
||||
if (statemap[inumber] != USTATE &&
|
||||
(ckinode(dp, &idesc) & STOP))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
pass1bcheck(struct inodesc *idesc)
|
||||
{
|
||||
struct dups *dlp;
|
||||
int nfrags, res = KEEPON;
|
||||
daddr_t blkno = idesc->id_blkno;
|
||||
|
||||
for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
|
||||
if (chkrange(blkno, 1))
|
||||
res = SKIP;
|
||||
for (dlp = duphead; dlp; dlp = dlp->next) {
|
||||
if (dlp->dup == blkno) {
|
||||
blkerror(idesc->id_number, "DUP", blkno);
|
||||
dlp->dup = duphead->dup;
|
||||
duphead->dup = blkno;
|
||||
duphead = duphead->next;
|
||||
}
|
||||
if (dlp == muldup)
|
||||
break;
|
||||
}
|
||||
if (muldup == 0 || duphead == muldup->next)
|
||||
return (STOP);
|
||||
}
|
||||
return (res);
|
||||
}
|
470
sbin/fsck_ext2fs/pass2.c
Normal file
470
sbin/fsck_ext2fs/pass2.c
Normal file
|
@ -0,0 +1,470 @@
|
|||
/* $NetBSD: pass2.c,v 1.15 2009/10/19 18:41:08 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1980, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Manuel Bouyer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)pass2.c 8.6 (Berkeley) 10/27/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: pass2.c,v 1.15 2009/10/19 18:41:08 bouyer Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <ufs/ext2fs/ext2fs_dinode.h>
|
||||
#include <ufs/ext2fs/ext2fs_dir.h>
|
||||
#include <ufs/ext2fs/ext2fs.h>
|
||||
|
||||
#include <ufs/ufs/dinode.h> /* for IFMT & friends */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fsck.h"
|
||||
#include "fsutil.h"
|
||||
#include "extern.h"
|
||||
#include "exitvalues.h"
|
||||
|
||||
#define MINDIRSIZE (sizeof (struct ext2fs_dirtemplate))
|
||||
|
||||
static int pass2check(struct inodesc *);
|
||||
static int blksort(const void *, const void *);
|
||||
|
||||
void
|
||||
pass2(void)
|
||||
{
|
||||
struct ext2fs_dinode *dp;
|
||||
struct inoinfo **inpp, *inp;
|
||||
struct inoinfo **inpend;
|
||||
struct inodesc curino;
|
||||
struct ext2fs_dinode dino;
|
||||
char pathbuf[MAXPATHLEN + 1];
|
||||
|
||||
switch (statemap[EXT2_ROOTINO]) {
|
||||
|
||||
case USTATE:
|
||||
pfatal("ROOT INODE UNALLOCATED");
|
||||
if (reply("ALLOCATE") == 0)
|
||||
exit(FSCK_EXIT_CHECK_FAILED);
|
||||
if (allocdir(EXT2_ROOTINO, EXT2_ROOTINO, 0755) != EXT2_ROOTINO)
|
||||
errexit("CANNOT ALLOCATE ROOT INODE");
|
||||
break;
|
||||
|
||||
case DCLEAR:
|
||||
pfatal("DUPS/BAD IN ROOT INODE");
|
||||
if (reply("REALLOCATE")) {
|
||||
freeino(EXT2_ROOTINO);
|
||||
if (allocdir(EXT2_ROOTINO, EXT2_ROOTINO, 0755) != EXT2_ROOTINO)
|
||||
errexit("CANNOT ALLOCATE ROOT INODE");
|
||||
break;
|
||||
}
|
||||
if (reply("CONTINUE") == 0)
|
||||
exit(FSCK_EXIT_CHECK_FAILED);
|
||||
break;
|
||||
|
||||
case FSTATE:
|
||||
case FCLEAR:
|
||||
pfatal("ROOT INODE NOT DIRECTORY");
|
||||
if (reply("REALLOCATE")) {
|
||||
freeino(EXT2_ROOTINO);
|
||||
if (allocdir(EXT2_ROOTINO, EXT2_ROOTINO, 0755) != EXT2_ROOTINO)
|
||||
errexit("CANNOT ALLOCATE ROOT INODE");
|
||||
break;
|
||||
}
|
||||
if (reply("FIX") == 0)
|
||||
exit(FSCK_EXIT_CHECK_FAILED);
|
||||
dp = ginode(EXT2_ROOTINO);
|
||||
dp->e2di_mode = h2fs16((fs2h16(dp->e2di_mode) & ~IFMT) | IFDIR);
|
||||
inodirty();
|
||||
break;
|
||||
|
||||
case DSTATE:
|
||||
break;
|
||||
|
||||
default:
|
||||
errexit("BAD STATE %d FOR ROOT INODE", statemap[EXT2_ROOTINO]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sort the directory list into disk block order.
|
||||
*/
|
||||
qsort((char *)inpsort, (size_t)inplast, sizeof *inpsort, blksort);
|
||||
/*
|
||||
* Check the integrity of each directory.
|
||||
*/
|
||||
memset(&curino, 0, sizeof(struct inodesc));
|
||||
curino.id_type = DATA;
|
||||
curino.id_func = pass2check;
|
||||
inpend = &inpsort[inplast];
|
||||
for (inpp = inpsort; inpp < inpend; inpp++) {
|
||||
inp = *inpp;
|
||||
if (inp->i_isize == 0)
|
||||
continue;
|
||||
if (inp->i_isize < MINDIRSIZE) {
|
||||
direrror(inp->i_number, "DIRECTORY TOO SHORT");
|
||||
inp->i_isize = roundup(MINDIRSIZE, sblock.e2fs_bsize);
|
||||
if (reply("FIX") == 1) {
|
||||
dp = ginode(inp->i_number);
|
||||
inossize(dp, inp->i_isize);
|
||||
inodirty();
|
||||
}
|
||||
} else if ((inp->i_isize & (sblock.e2fs_bsize - 1)) != 0) {
|
||||
getpathname(pathbuf, sizeof(pathbuf), inp->i_number,
|
||||
inp->i_number);
|
||||
pwarn("DIRECTORY %s: LENGTH %lu NOT MULTIPLE OF %d",
|
||||
pathbuf, (u_long)inp->i_isize, sblock.e2fs_bsize);
|
||||
if (preen)
|
||||
printf(" (ADJUSTED)\n");
|
||||
inp->i_isize = roundup(inp->i_isize, sblock.e2fs_bsize);
|
||||
if (preen || reply("ADJUST") == 1) {
|
||||
dp = ginode(inp->i_number);
|
||||
inossize(dp, inp->i_isize);
|
||||
inodirty();
|
||||
}
|
||||
}
|
||||
memset(&dino, 0, sizeof(struct ext2fs_dinode));
|
||||
dino.e2di_mode = h2fs16(IFDIR);
|
||||
inossize(&dino, inp->i_isize);
|
||||
memcpy(&dino.e2di_blocks[0], &inp->i_blks[0], (size_t)inp->i_numblks);
|
||||
curino.id_number = inp->i_number;
|
||||
curino.id_parent = inp->i_parent;
|
||||
(void)ckinode(&dino, &curino);
|
||||
}
|
||||
/*
|
||||
* Now that the parents of all directories have been found,
|
||||
* make another pass to verify the value of `..'
|
||||
*/
|
||||
for (inpp = inpsort; inpp < inpend; inpp++) {
|
||||
inp = *inpp;
|
||||
if (inp->i_parent == 0 || inp->i_isize == 0)
|
||||
continue;
|
||||
if (inp->i_dotdot == inp->i_parent ||
|
||||
inp->i_dotdot == (ino_t)-1)
|
||||
continue;
|
||||
if (inp->i_dotdot == 0) {
|
||||
inp->i_dotdot = inp->i_parent;
|
||||
fileerror(inp->i_parent, inp->i_number, "MISSING '..'");
|
||||
if (reply("FIX") == 0)
|
||||
continue;
|
||||
(void)makeentry(inp->i_number, inp->i_parent, "..");
|
||||
lncntp[inp->i_parent]--;
|
||||
continue;
|
||||
}
|
||||
fileerror(inp->i_parent, inp->i_number,
|
||||
"BAD INODE NUMBER FOR '..'");
|
||||
if (reply("FIX") == 0)
|
||||
continue;
|
||||
lncntp[inp->i_dotdot]++;
|
||||
lncntp[inp->i_parent]--;
|
||||
inp->i_dotdot = inp->i_parent;
|
||||
(void)changeino(inp->i_number, "..", inp->i_parent);
|
||||
}
|
||||
/*
|
||||
* Mark all the directories that can be found from the root.
|
||||
*/
|
||||
propagate();
|
||||
}
|
||||
|
||||
static int
|
||||
pass2check(struct inodesc *idesc)
|
||||
{
|
||||
struct ext2fs_direct *dirp = idesc->id_dirp;
|
||||
struct inoinfo *inp;
|
||||
int n, entrysize, ret = 0;
|
||||
struct ext2fs_dinode *dp;
|
||||
const char *errmsg;
|
||||
struct ext2fs_direct proto;
|
||||
char namebuf[MAXPATHLEN + 1];
|
||||
char pathbuf[MAXPATHLEN + 1];
|
||||
|
||||
/*
|
||||
* check for "."
|
||||
*/
|
||||
if (idesc->id_entryno != 0)
|
||||
goto chk1;
|
||||
if (fs2h32(dirp->e2d_ino) != 0 && dirp->e2d_namlen == 1 &&
|
||||
dirp->e2d_name[0] == '.') {
|
||||
if (fs2h32(dirp->e2d_ino) != idesc->id_number) {
|
||||
direrror(idesc->id_number, "BAD INODE NUMBER FOR '.'");
|
||||
dirp->e2d_ino = h2fs32(idesc->id_number);
|
||||
if (reply("FIX") == 1)
|
||||
ret |= ALTERED;
|
||||
}
|
||||
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
|
||||
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE)
|
||||
&& (dirp->e2d_type != EXT2_FT_DIR)) {
|
||||
direrror(idesc->id_number, "BAD TYPE VALUE FOR '.'");
|
||||
dirp->e2d_type = EXT2_FT_DIR;
|
||||
if (reply("FIX") == 1)
|
||||
ret |= ALTERED;
|
||||
}
|
||||
goto chk1;
|
||||
}
|
||||
direrror(idesc->id_number, "MISSING '.'");
|
||||
proto.e2d_ino = h2fs32(idesc->id_number);
|
||||
proto.e2d_namlen = 1;
|
||||
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
|
||||
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE))
|
||||
proto.e2d_type = EXT2_FT_DIR;
|
||||
else
|
||||
proto.e2d_type = 0;
|
||||
(void)strlcpy(proto.e2d_name, ".", sizeof(proto.e2d_name));
|
||||
entrysize = EXT2FS_DIRSIZ(proto.e2d_namlen);
|
||||
if (fs2h32(dirp->e2d_ino) != 0 && strcmp(dirp->e2d_name, "..") != 0) {
|
||||
pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n",
|
||||
dirp->e2d_name);
|
||||
} else if (fs2h16(dirp->e2d_reclen) < entrysize) {
|
||||
pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n");
|
||||
} else if (fs2h16(dirp->e2d_reclen) < 2 * entrysize) {
|
||||
proto.e2d_reclen = dirp->e2d_reclen;
|
||||
memcpy(dirp, &proto, (size_t)entrysize);
|
||||
if (reply("FIX") == 1)
|
||||
ret |= ALTERED;
|
||||
} else {
|
||||
n = fs2h16(dirp->e2d_reclen) - entrysize;
|
||||
proto.e2d_reclen = h2fs16(entrysize);
|
||||
memcpy(dirp, &proto, (size_t)entrysize);
|
||||
idesc->id_entryno++;
|
||||
lncntp[fs2h32(dirp->e2d_ino)]--;
|
||||
dirp = (struct ext2fs_direct *)((char *)(dirp) + entrysize);
|
||||
memset(dirp, 0, (size_t)n);
|
||||
dirp->e2d_reclen = h2fs16(n);
|
||||
if (reply("FIX") == 1)
|
||||
ret |= ALTERED;
|
||||
}
|
||||
chk1:
|
||||
if (idesc->id_entryno > 1)
|
||||
goto chk2;
|
||||
inp = getinoinfo(idesc->id_number);
|
||||
proto.e2d_ino = h2fs32(inp->i_parent);
|
||||
proto.e2d_namlen = 2;
|
||||
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
|
||||
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE))
|
||||
proto.e2d_type = EXT2_FT_DIR;
|
||||
else
|
||||
proto.e2d_type = 0;
|
||||
(void)strlcpy(proto.e2d_name, "..", sizeof(proto.e2d_name));
|
||||
entrysize = EXT2FS_DIRSIZ(2);
|
||||
if (idesc->id_entryno == 0) {
|
||||
n = EXT2FS_DIRSIZ(dirp->e2d_namlen);
|
||||
if (fs2h16(dirp->e2d_reclen) < n + entrysize)
|
||||
goto chk2;
|
||||
proto.e2d_reclen = h2fs16(fs2h16(dirp->e2d_reclen) - n);
|
||||
dirp->e2d_reclen = h2fs16(n);
|
||||
idesc->id_entryno++;
|
||||
lncntp[fs2h32(dirp->e2d_ino)]--;
|
||||
dirp = (struct ext2fs_direct *)((char *)(dirp) + n);
|
||||
memset(dirp, 0, (size_t)fs2h16(proto.e2d_reclen));
|
||||
dirp->e2d_reclen = proto.e2d_reclen;
|
||||
}
|
||||
if (fs2h32(dirp->e2d_ino) != 0 &&
|
||||
dirp->e2d_namlen == 2 &&
|
||||
strncmp(dirp->e2d_name, "..", 2) == 0) {
|
||||
inp->i_dotdot = fs2h32(dirp->e2d_ino);
|
||||
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
|
||||
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE)
|
||||
&& dirp->e2d_type != EXT2_FT_DIR) {
|
||||
direrror(idesc->id_number, "BAD TYPE VALUE FOR '..'");
|
||||
dirp->e2d_type = EXT2_FT_DIR;
|
||||
if (reply("FIX") == 1)
|
||||
ret |= ALTERED;
|
||||
}
|
||||
goto chk2;
|
||||
}
|
||||
if (fs2h32(dirp->e2d_ino) != 0 &&
|
||||
dirp->e2d_namlen == 1 &&
|
||||
strncmp(dirp->e2d_name, ".", 1) != 0) {
|
||||
fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
|
||||
pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n",
|
||||
dirp->e2d_name);
|
||||
inp->i_dotdot = (ino_t)-1;
|
||||
} else if (fs2h16(dirp->e2d_reclen) < entrysize) {
|
||||
fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
|
||||
pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n");
|
||||
inp->i_dotdot = (ino_t)-1;
|
||||
} else if (inp->i_parent != 0) {
|
||||
/*
|
||||
* We know the parent, so fix now.
|
||||
*/
|
||||
inp->i_dotdot = inp->i_parent;
|
||||
fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
|
||||
proto.e2d_reclen = dirp->e2d_reclen;
|
||||
memcpy(dirp, &proto, (size_t)entrysize);
|
||||
if (reply("FIX") == 1)
|
||||
ret |= ALTERED;
|
||||
}
|
||||
idesc->id_entryno++;
|
||||
if (fs2h32(dirp->e2d_ino) != 0)
|
||||
lncntp[fs2h32(dirp->e2d_ino)]--;
|
||||
return (ret|KEEPON);
|
||||
chk2:
|
||||
if (fs2h32(dirp->e2d_ino) == 0)
|
||||
return (ret|KEEPON);
|
||||
if (dirp->e2d_namlen <= 2 &&
|
||||
dirp->e2d_name[0] == '.' &&
|
||||
idesc->id_entryno >= 2) {
|
||||
if (dirp->e2d_namlen == 1) {
|
||||
direrror(idesc->id_number, "EXTRA '.' ENTRY");
|
||||
dirp->e2d_ino = 0;
|
||||
if (reply("FIX") == 1)
|
||||
ret |= ALTERED;
|
||||
return (KEEPON | ret);
|
||||
}
|
||||
if (dirp->e2d_name[1] == '.') {
|
||||
direrror(idesc->id_number, "EXTRA '..' ENTRY");
|
||||
dirp->e2d_ino = 0;
|
||||
if (reply("FIX") == 1)
|
||||
ret |= ALTERED;
|
||||
return (KEEPON | ret);
|
||||
}
|
||||
}
|
||||
idesc->id_entryno++;
|
||||
n = 0;
|
||||
if (fs2h32(dirp->e2d_ino) > maxino ||
|
||||
(fs2h32(dirp->e2d_ino) < EXT2_FIRSTINO &&
|
||||
fs2h32(dirp->e2d_ino) != EXT2_ROOTINO)) {
|
||||
fileerror(idesc->id_number, fs2h32(dirp->e2d_ino), "I OUT OF RANGE");
|
||||
n = reply("REMOVE");
|
||||
} else {
|
||||
again:
|
||||
switch (statemap[fs2h32(dirp->e2d_ino)]) {
|
||||
case USTATE:
|
||||
if (idesc->id_entryno <= 2)
|
||||
break;
|
||||
fileerror(idesc->id_number, fs2h32(dirp->e2d_ino), "UNALLOCATED");
|
||||
n = reply("REMOVE");
|
||||
break;
|
||||
|
||||
case DCLEAR:
|
||||
case FCLEAR:
|
||||
if (idesc->id_entryno <= 2)
|
||||
break;
|
||||
if (statemap[fs2h32(dirp->e2d_ino)] == FCLEAR)
|
||||
errmsg = "DUP/BAD";
|
||||
else if (!preen)
|
||||
errmsg = "ZERO LENGTH DIRECTORY";
|
||||
else {
|
||||
n = 1;
|
||||
break;
|
||||
}
|
||||
fileerror(idesc->id_number, fs2h32(dirp->e2d_ino), errmsg);
|
||||
if ((n = reply("REMOVE")) == 1)
|
||||
break;
|
||||
dp = ginode(fs2h32(dirp->e2d_ino));
|
||||
statemap[fs2h32(dirp->e2d_ino)] =
|
||||
(fs2h16(dp->e2di_mode) & IFMT) == IFDIR ? DSTATE : FSTATE;
|
||||
lncntp[fs2h32(dirp->e2d_ino)] = fs2h16(dp->e2di_nlink);
|
||||
goto again;
|
||||
|
||||
case DSTATE:
|
||||
case DFOUND:
|
||||
inp = getinoinfo(fs2h32(dirp->e2d_ino));
|
||||
if (inp->i_parent != 0 && idesc->id_entryno > 2) {
|
||||
getpathname(pathbuf, sizeof(pathbuf),
|
||||
idesc->id_number, idesc->id_number);
|
||||
getpathname(namebuf, sizeof(namebuf),
|
||||
fs2h32(dirp->e2d_ino),
|
||||
fs2h32(dirp->e2d_ino));
|
||||
pwarn("%s %s %s\n", pathbuf,
|
||||
"IS AN EXTRANEOUS HARD LINK TO DIRECTORY",
|
||||
namebuf);
|
||||
if (preen)
|
||||
printf(" (IGNORED)\n");
|
||||
else if ((n = reply("REMOVE")) == 1)
|
||||
break;
|
||||
}
|
||||
if (idesc->id_entryno > 2)
|
||||
inp->i_parent = idesc->id_number;
|
||||
/* fall through */
|
||||
|
||||
case FSTATE:
|
||||
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
|
||||
(sblock.e2fs.e2fs_features_incompat &
|
||||
EXT2F_INCOMPAT_FTYPE) &&
|
||||
dirp->e2d_type !=
|
||||
inot2ext2dt(typemap[fs2h32(dirp->e2d_ino)])) {
|
||||
dirp->e2d_type =
|
||||
inot2ext2dt(typemap[fs2h32(dirp->e2d_ino)]);
|
||||
fileerror(idesc->id_number,
|
||||
fs2h32(dirp->e2d_ino),
|
||||
"BAD TYPE VALUE");
|
||||
if (reply("FIX") == 1)
|
||||
ret |= ALTERED;
|
||||
}
|
||||
lncntp[fs2h32(dirp->e2d_ino)]--;
|
||||
break;
|
||||
|
||||
default:
|
||||
errexit("BAD STATE %d FOR INODE I=%d",
|
||||
statemap[fs2h32(dirp->e2d_ino)], fs2h32(dirp->e2d_ino));
|
||||
}
|
||||
}
|
||||
if (n == 0)
|
||||
return (ret|KEEPON);
|
||||
dirp->e2d_ino = 0;
|
||||
return (ret|KEEPON|ALTERED);
|
||||
}
|
||||
|
||||
/*
|
||||
* Routine to sort disk blocks.
|
||||
*/
|
||||
static int
|
||||
blksort(const void *inpp1, const void *inpp2)
|
||||
{
|
||||
return ((* (const struct inoinfo * const*) inpp1)->i_blks[0] -
|
||||
(* (const struct inoinfo * const*) inpp2)->i_blks[0]);
|
||||
}
|
100
sbin/fsck_ext2fs/pass3.c
Normal file
100
sbin/fsck_ext2fs/pass3.c
Normal file
|
@ -0,0 +1,100 @@
|
|||
/* $NetBSD: pass3.c,v 1.7 2009/10/19 18:41:08 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1980, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Manuel Bouyer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)pass3.c 8.1 (Berkeley) 6/5/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: pass3.c,v 1.7 2009/10/19 18:41:08 bouyer Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <ufs/ext2fs/ext2fs_dinode.h>
|
||||
#include <ufs/ext2fs/ext2fs.h>
|
||||
#include "fsck.h"
|
||||
#include "extern.h"
|
||||
|
||||
void
|
||||
pass3(void)
|
||||
{
|
||||
struct inoinfo **inpp, *inp;
|
||||
ino_t orphan;
|
||||
int loopcnt;
|
||||
|
||||
for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) {
|
||||
inp = *inpp;
|
||||
if (inp->i_number == EXT2_ROOTINO ||
|
||||
!(inp->i_parent == 0 || statemap[inp->i_number] == DSTATE))
|
||||
continue;
|
||||
if (statemap[inp->i_number] == DCLEAR)
|
||||
continue;
|
||||
for (loopcnt = 0; ; loopcnt++) {
|
||||
orphan = inp->i_number;
|
||||
if (inp->i_parent == 0 ||
|
||||
statemap[inp->i_parent] != DSTATE ||
|
||||
loopcnt > numdirs)
|
||||
break;
|
||||
inp = getinoinfo(inp->i_parent);
|
||||
}
|
||||
(void)linkup(orphan, inp->i_dotdot);
|
||||
inp->i_parent = inp->i_dotdot = lfdir;
|
||||
lncntp[lfdir]--;
|
||||
statemap[orphan] = DFOUND;
|
||||
propagate();
|
||||
}
|
||||
}
|
164
sbin/fsck_ext2fs/pass4.c
Normal file
164
sbin/fsck_ext2fs/pass4.c
Normal file
|
@ -0,0 +1,164 @@
|
|||
/* $NetBSD: pass4.c,v 1.10 2009/10/19 18:41:08 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1980, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Manuel Bouyer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)pass4.c 8.1 (Berkeley) 6/5/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: pass4.c,v 1.10 2009/10/19 18:41:08 bouyer Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <ufs/ext2fs/ext2fs_dinode.h>
|
||||
#include <ufs/ext2fs/ext2fs.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fsutil.h"
|
||||
#include "fsck.h"
|
||||
#include "extern.h"
|
||||
|
||||
void
|
||||
pass4(void)
|
||||
{
|
||||
ino_t inumber;
|
||||
struct zlncnt *zlnp;
|
||||
struct ext2fs_dinode *dp;
|
||||
struct inodesc idesc;
|
||||
int n;
|
||||
|
||||
memset(&idesc, 0, sizeof(struct inodesc));
|
||||
idesc.id_type = ADDR;
|
||||
idesc.id_func = pass4check;
|
||||
for (inumber = EXT2_ROOTINO; inumber <= lastino; inumber++) {
|
||||
if (inumber < EXT2_FIRSTINO && inumber > EXT2_ROOTINO)
|
||||
continue;
|
||||
idesc.id_number = inumber;
|
||||
switch (statemap[inumber]) {
|
||||
|
||||
case FSTATE:
|
||||
case DFOUND:
|
||||
n = lncntp[inumber];
|
||||
if (n)
|
||||
adjust(&idesc, (short)n);
|
||||
else {
|
||||
for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
|
||||
if (zlnp->zlncnt == inumber) {
|
||||
zlnp->zlncnt = zlnhead->zlncnt;
|
||||
zlnp = zlnhead;
|
||||
zlnhead = zlnhead->next;
|
||||
free((char *)zlnp);
|
||||
clri(&idesc, "UNREF", 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DSTATE:
|
||||
clri(&idesc, "UNREF", 1);
|
||||
break;
|
||||
|
||||
case DCLEAR:
|
||||
dp = ginode(inumber);
|
||||
if (inosize(dp) == 0) {
|
||||
clri(&idesc, "ZERO LENGTH", 1);
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
case FCLEAR:
|
||||
clri(&idesc, "BAD/DUP", 1);
|
||||
break;
|
||||
|
||||
case USTATE:
|
||||
break;
|
||||
|
||||
default:
|
||||
errexit("BAD STATE %d FOR INODE I=%llu",
|
||||
statemap[inumber], (unsigned long long)inumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
pass4check(struct inodesc *idesc)
|
||||
{
|
||||
struct dups *dlp;
|
||||
int nfrags, res = KEEPON;
|
||||
daddr_t blkno = idesc->id_blkno;
|
||||
|
||||
for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
|
||||
if (chkrange(blkno, 1)) {
|
||||
res = SKIP;
|
||||
} else if (testbmap(blkno)) {
|
||||
for (dlp = duplist; dlp; dlp = dlp->next) {
|
||||
if (dlp->dup != blkno)
|
||||
continue;
|
||||
dlp->dup = duplist->dup;
|
||||
dlp = duplist;
|
||||
duplist = duplist->next;
|
||||
free((char *)dlp);
|
||||
break;
|
||||
}
|
||||
if (dlp == 0) {
|
||||
clrbmap(blkno);
|
||||
n_blks--;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (res);
|
||||
}
|
277
sbin/fsck_ext2fs/pass5.c
Normal file
277
sbin/fsck_ext2fs/pass5.c
Normal file
|
@ -0,0 +1,277 @@
|
|||
/* $NetBSD: pass5.c,v 1.19 2011/08/06 16:42:41 dholland Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1980, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Manuel Bouyer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)pass5.c 8.6 (Berkeley) 11/30/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: pass5.c,v 1.19 2011/08/06 16:42:41 dholland Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <ufs/ufs/dinode.h>
|
||||
#include <ufs/ext2fs/ext2fs_dinode.h>
|
||||
#include <ufs/ext2fs/ext2fs.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "fsutil.h"
|
||||
#include "fsck.h"
|
||||
#include "extern.h"
|
||||
|
||||
|
||||
static void print_bmap(char *, uint32_t);
|
||||
|
||||
void
|
||||
pass5(void)
|
||||
{
|
||||
int c;
|
||||
struct m_ext2fs *fs = &sblock;
|
||||
daddr_t dbase, dmax;
|
||||
daddr_t d;
|
||||
uint32_t i, j;
|
||||
struct inodesc idesc[3];
|
||||
struct bufarea *ino_bitmap = NULL, *blk_bitmap = NULL;
|
||||
char *ibmap, *bbmap;
|
||||
u_int32_t cs_ndir, cs_nbfree, cs_nifree;
|
||||
char msg[255];
|
||||
|
||||
cs_ndir = 0;
|
||||
cs_nbfree = 0;
|
||||
cs_nifree = 0;
|
||||
|
||||
ibmap = malloc(fs->e2fs_bsize);
|
||||
bbmap = malloc(fs->e2fs_bsize);
|
||||
if (ibmap == NULL || bbmap == NULL) {
|
||||
errexit("out of memory");
|
||||
}
|
||||
|
||||
for (c = 0; c < fs->e2fs_ncg; c++) {
|
||||
u_int32_t nbfree = 0;
|
||||
u_int32_t nifree = 0;
|
||||
u_int32_t ndirs = 0;
|
||||
|
||||
nbfree = 0;
|
||||
nifree = fs->e2fs.e2fs_ipg;
|
||||
ndirs = 0;
|
||||
|
||||
if (blk_bitmap == NULL) {
|
||||
blk_bitmap = getdatablk(fs2h32(fs->e2fs_gd[c].ext2bgd_b_bitmap),
|
||||
fs->e2fs_bsize);
|
||||
} else {
|
||||
getblk(blk_bitmap, fs2h32(fs->e2fs_gd[c].ext2bgd_b_bitmap),
|
||||
fs->e2fs_bsize);
|
||||
}
|
||||
if (ino_bitmap == NULL) {
|
||||
ino_bitmap = getdatablk(fs2h32(fs->e2fs_gd[c].ext2bgd_i_bitmap),
|
||||
fs->e2fs_bsize);
|
||||
} else {
|
||||
getblk(ino_bitmap, fs2h32(fs->e2fs_gd[c].ext2bgd_i_bitmap),
|
||||
fs->e2fs_bsize);
|
||||
}
|
||||
memset(bbmap, 0, fs->e2fs_bsize);
|
||||
memset(ibmap, 0, fs->e2fs_bsize);
|
||||
memset(&idesc[0], 0, sizeof idesc);
|
||||
for (i = 0; i < 3; i++) {
|
||||
idesc[i].id_type = ADDR;
|
||||
}
|
||||
|
||||
j = fs->e2fs.e2fs_ipg * c + 1;
|
||||
|
||||
for (i = 0; i < fs->e2fs.e2fs_ipg; j++, i++) {
|
||||
if ((j < EXT2_FIRSTINO) && (j != EXT2_ROOTINO)) {
|
||||
setbit(ibmap, i);
|
||||
nifree--;
|
||||
continue;
|
||||
}
|
||||
if (j > fs->e2fs.e2fs_icount) {
|
||||
setbit(ibmap, i);
|
||||
continue;
|
||||
}
|
||||
switch (statemap[j]) {
|
||||
|
||||
case USTATE:
|
||||
break;
|
||||
|
||||
case DSTATE:
|
||||
case DCLEAR:
|
||||
case DFOUND:
|
||||
ndirs++;
|
||||
/* fall through */
|
||||
|
||||
case FSTATE:
|
||||
case FCLEAR:
|
||||
nifree--;
|
||||
setbit(ibmap, i);
|
||||
break;
|
||||
|
||||
default:
|
||||
errexit("BAD STATE %d FOR INODE I=%"PRIu32,
|
||||
statemap[j], j);
|
||||
}
|
||||
}
|
||||
|
||||
/* fill in unused par of the inode map */
|
||||
for (i = fs->e2fs.e2fs_ipg / NBBY; i < (uint32_t)fs->e2fs_bsize; i++)
|
||||
ibmap[i] = 0xff;
|
||||
|
||||
dbase = c * sblock.e2fs.e2fs_bpg +
|
||||
sblock.e2fs.e2fs_first_dblock;
|
||||
dmax = (c+1) * sblock.e2fs.e2fs_bpg +
|
||||
sblock.e2fs.e2fs_first_dblock;
|
||||
|
||||
for (i = 0, d = dbase;
|
||||
d < dmax;
|
||||
d ++, i ++) {
|
||||
if (testbmap(d) || d >= sblock.e2fs.e2fs_bcount) {
|
||||
setbit(bbmap, i);
|
||||
continue;
|
||||
} else {
|
||||
nbfree++;
|
||||
}
|
||||
|
||||
}
|
||||
cs_nbfree += nbfree;
|
||||
cs_nifree += nifree;
|
||||
cs_ndir += ndirs;
|
||||
|
||||
if (debug && (fs2h16(fs->e2fs_gd[c].ext2bgd_nbfree) != nbfree ||
|
||||
fs2h16(fs->e2fs_gd[c].ext2bgd_nifree) != nifree ||
|
||||
fs2h16(fs->e2fs_gd[c].ext2bgd_ndirs) != ndirs)) {
|
||||
printf("summary info for cg %d is %d, %d, %d,"
|
||||
"should be %d, %d, %d\n", c,
|
||||
fs2h16(fs->e2fs_gd[c].ext2bgd_nbfree),
|
||||
fs2h16(fs->e2fs_gd[c].ext2bgd_nifree),
|
||||
fs2h16(fs->e2fs_gd[c].ext2bgd_ndirs),
|
||||
nbfree,
|
||||
nifree,
|
||||
ndirs);
|
||||
}
|
||||
(void)snprintf(msg, sizeof(msg),
|
||||
"SUMMARY INFORMATIONS WRONG FOR CG #%d", c);
|
||||
if ((fs2h16(fs->e2fs_gd[c].ext2bgd_nbfree) != nbfree ||
|
||||
fs2h16(fs->e2fs_gd[c].ext2bgd_nifree) != nifree ||
|
||||
fs2h16(fs->e2fs_gd[c].ext2bgd_ndirs) != ndirs) &&
|
||||
dofix(&idesc[0], msg)) {
|
||||
fs->e2fs_gd[c].ext2bgd_nbfree = h2fs16(nbfree);
|
||||
fs->e2fs_gd[c].ext2bgd_nifree = h2fs16(nifree);
|
||||
fs->e2fs_gd[c].ext2bgd_ndirs = h2fs16(ndirs);
|
||||
sbdirty();
|
||||
}
|
||||
|
||||
if (debug && memcmp(blk_bitmap->b_un.b_buf, bbmap, fs->e2fs_bsize)) {
|
||||
printf("blk_bitmap:\n");
|
||||
print_bmap(blk_bitmap->b_un.b_buf, fs->e2fs_bsize);
|
||||
printf("bbmap:\n");
|
||||
print_bmap(bbmap, fs->e2fs_bsize);
|
||||
}
|
||||
|
||||
(void)snprintf(msg, sizeof(msg),
|
||||
"BLK(S) MISSING IN BIT MAPS #%d", c);
|
||||
if (memcmp(blk_bitmap->b_un.b_buf, bbmap, fs->e2fs_bsize) &&
|
||||
dofix(&idesc[1], msg)) {
|
||||
memcpy(blk_bitmap->b_un.b_buf, bbmap, fs->e2fs_bsize);
|
||||
dirty(blk_bitmap);
|
||||
}
|
||||
if (debug && memcmp(ino_bitmap->b_un.b_buf, ibmap, fs->e2fs_bsize)) {
|
||||
printf("ino_bitmap:\n");
|
||||
print_bmap(ino_bitmap->b_un.b_buf, fs->e2fs_bsize);
|
||||
printf("ibmap:\n");
|
||||
print_bmap(ibmap, fs->e2fs_bsize);
|
||||
}
|
||||
(void)snprintf(msg, sizeof(msg),
|
||||
"INODE(S) MISSING IN BIT MAPS #%d", c);
|
||||
if (memcmp(ino_bitmap->b_un.b_buf, ibmap, fs->e2fs_bsize) &&
|
||||
dofix(&idesc[1], msg)) {
|
||||
memcpy(ino_bitmap->b_un.b_buf, ibmap, fs->e2fs_bsize);
|
||||
dirty(ino_bitmap);
|
||||
}
|
||||
|
||||
}
|
||||
if (debug && (fs->e2fs.e2fs_fbcount != cs_nbfree ||
|
||||
fs->e2fs.e2fs_ficount != cs_nifree)) {
|
||||
printf("summary info bad in superblock: %d, %d should be %d, %d\n",
|
||||
fs->e2fs.e2fs_fbcount, fs->e2fs.e2fs_ficount,
|
||||
cs_nbfree, cs_nifree);
|
||||
}
|
||||
if ((fs->e2fs.e2fs_fbcount != cs_nbfree ||
|
||||
fs->e2fs.e2fs_ficount != cs_nifree)
|
||||
&& dofix(&idesc[0], "SUPERBLK SUMMARY INFORMATION BAD")) {
|
||||
fs->e2fs.e2fs_fbcount = cs_nbfree;
|
||||
fs->e2fs.e2fs_ficount = cs_nifree;
|
||||
sbdirty();
|
||||
}
|
||||
free(ibmap);
|
||||
free(bbmap);
|
||||
}
|
||||
|
||||
static void
|
||||
print_bmap(char *map, uint32_t size)
|
||||
{
|
||||
uint32_t i, j;
|
||||
|
||||
i = 0;
|
||||
while (i < size) {
|
||||
printf("%04x: ",i);
|
||||
for (j = 0; j < 16; j++, i++)
|
||||
printf("%02x ", (unsigned char)map[i] & 0xff);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
559
sbin/fsck_ext2fs/setup.c
Normal file
559
sbin/fsck_ext2fs/setup.c
Normal file
|
@ -0,0 +1,559 @@
|
|||
/* $NetBSD: setup.c,v 1.28 2011/09/16 16:13:18 plunky Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1980, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Manuel Bouyer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)setup.c 8.5 (Berkeley) 11/23/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: setup.c,v 1.28 2011/09/16 16:13:18 plunky Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#define FSTYPENAMES
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <ufs/ext2fs/ext2fs_dinode.h>
|
||||
#include <ufs/ext2fs/ext2fs.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "fsck.h"
|
||||
#include "extern.h"
|
||||
#include "fsutil.h"
|
||||
#include "exitvalues.h"
|
||||
|
||||
void badsb(int, const char *);
|
||||
int calcsb(const char *, int, struct m_ext2fs *);
|
||||
static struct disklabel *getdisklabel(const char *, int);
|
||||
static int readsb(int);
|
||||
|
||||
int
|
||||
setup(const char *dev)
|
||||
{
|
||||
long cg, asked, i;
|
||||
long bmapsize;
|
||||
struct disklabel *lp;
|
||||
#ifndef __minix
|
||||
off_t sizepb;
|
||||
#else
|
||||
u64_t sizepb;
|
||||
#endif
|
||||
struct stat statb;
|
||||
struct m_ext2fs proto;
|
||||
int doskipclean;
|
||||
u_int64_t maxfilesize;
|
||||
|
||||
havesb = 0;
|
||||
fswritefd = -1;
|
||||
doskipclean = skipclean;
|
||||
if (stat(dev, &statb) < 0) {
|
||||
printf("Can't stat %s: %s\n", dev, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef __minix
|
||||
if (!S_ISCHR(statb.st_mode)) {
|
||||
pfatal("%s is not a character device", dev);
|
||||
if (reply("CONTINUE") == 0)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((fsreadfd = open(dev, O_RDONLY)) < 0) {
|
||||
printf("Can't open %s: %s\n", dev, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if (preen == 0)
|
||||
printf("** %s", dev);
|
||||
if (nflag || (fswritefd = open(dev, O_WRONLY)) < 0) {
|
||||
fswritefd = -1;
|
||||
if (preen)
|
||||
pfatal("NO WRITE ACCESS");
|
||||
printf(" (NO WRITE)");
|
||||
}
|
||||
if (preen == 0)
|
||||
printf("\n");
|
||||
fsmodified = 0;
|
||||
lfdir = 0;
|
||||
initbarea(&sblk);
|
||||
initbarea(&asblk);
|
||||
sblk.b_un.b_buf = malloc(SBSIZE);
|
||||
asblk.b_un.b_buf = malloc(SBSIZE);
|
||||
if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL)
|
||||
errexit("cannot allocate space for superblock");
|
||||
if ((lp = getdisklabel(NULL, fsreadfd)) != NULL)
|
||||
dev_bsize = secsize = lp->d_secsize;
|
||||
else
|
||||
dev_bsize = secsize = DEV_BSIZE;
|
||||
/*
|
||||
* Read in the superblock, looking for alternates if necessary
|
||||
*/
|
||||
if (readsb(1) == 0) {
|
||||
if (bflag || preen || calcsb(dev, fsreadfd, &proto) == 0)
|
||||
return 0;
|
||||
if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0)
|
||||
return 0;
|
||||
for (cg = 1; cg < proto.e2fs_ncg; cg++) {
|
||||
bflag = fsbtodb(&proto,
|
||||
cg * proto.e2fs.e2fs_bpg +
|
||||
proto.e2fs.e2fs_first_dblock);
|
||||
if (readsb(0) != 0)
|
||||
break;
|
||||
}
|
||||
if (cg >= proto.e2fs_ncg) {
|
||||
printf("%s %s\n%s %s\n%s %s\n",
|
||||
"SEARCH FOR ALTERNATE SUPER-BLOCK",
|
||||
"FAILED. YOU MUST USE THE",
|
||||
"-b OPTION TO FSCK_FFS TO SPECIFY THE",
|
||||
"LOCATION OF AN ALTERNATE",
|
||||
"SUPER-BLOCK TO SUPPLY NEEDED",
|
||||
"INFORMATION; SEE fsck_ext2fs(8).");
|
||||
return 0;
|
||||
}
|
||||
doskipclean = 0;
|
||||
pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag);
|
||||
}
|
||||
if (debug)
|
||||
printf("state = %d\n", sblock.e2fs.e2fs_state);
|
||||
if (sblock.e2fs.e2fs_state == E2FS_ISCLEAN) {
|
||||
if (doskipclean) {
|
||||
pwarn("%sile system is clean; not checking\n",
|
||||
preen ? "f" : "** F");
|
||||
return -1;
|
||||
}
|
||||
if (!preen)
|
||||
pwarn("** File system is already clean\n");
|
||||
}
|
||||
maxfsblock = sblock.e2fs.e2fs_bcount;
|
||||
maxino = sblock.e2fs_ncg * sblock.e2fs.e2fs_ipg;
|
||||
sizepb = sblock.e2fs_bsize;
|
||||
maxfilesize = sblock.e2fs_bsize * NDADDR - 1;
|
||||
for (i = 0; i < NIADDR; i++) {
|
||||
sizepb *= NINDIR(&sblock);
|
||||
maxfilesize += sizepb;
|
||||
}
|
||||
/*
|
||||
* Check and potentially fix certain fields in the super block.
|
||||
*/
|
||||
if (/* (sblock.e2fs.e2fs_rbcount < 0) || */
|
||||
(sblock.e2fs.e2fs_rbcount > sblock.e2fs.e2fs_bcount)) {
|
||||
pfatal("IMPOSSIBLE RESERVED BLOCK COUNT=%d IN SUPERBLOCK",
|
||||
sblock.e2fs.e2fs_rbcount);
|
||||
if (reply("SET TO DEFAULT") == 1) {
|
||||
sblock.e2fs.e2fs_rbcount =
|
||||
sblock.e2fs.e2fs_bcount * MINFREE / 100;
|
||||
sbdirty();
|
||||
dirty(&asblk);
|
||||
}
|
||||
}
|
||||
if (sblock.e2fs.e2fs_bpg != sblock.e2fs.e2fs_fpg) {
|
||||
pfatal("WRONG FPG=%d (BPG=%d) IN SUPERBLOCK",
|
||||
sblock.e2fs.e2fs_fpg, sblock.e2fs.e2fs_bpg);
|
||||
return 0;
|
||||
}
|
||||
if (asblk.b_dirty && !bflag) {
|
||||
copyback_sb(&asblk);
|
||||
flush(fswritefd, &asblk);
|
||||
}
|
||||
/*
|
||||
* read in the summary info.
|
||||
*/
|
||||
|
||||
sblock.e2fs_gd = malloc(sblock.e2fs_ngdb * sblock.e2fs_bsize);
|
||||
if (sblock.e2fs_gd == NULL)
|
||||
errexit("out of memory");
|
||||
asked = 0;
|
||||
for (i = 0; i < sblock.e2fs_ngdb; i++) {
|
||||
if (bread(fsreadfd,
|
||||
(char *)&sblock.e2fs_gd[i * sblock.e2fs_bsize /
|
||||
sizeof(struct ext2_gd)],
|
||||
fsbtodb(&sblock, ((sblock.e2fs_bsize > 1024) ? 0 : 1) +
|
||||
i + 1),
|
||||
sblock.e2fs_bsize) != 0 && !asked) {
|
||||
pfatal("BAD SUMMARY INFORMATION");
|
||||
if (reply("CONTINUE") == 0)
|
||||
exit(FSCK_EXIT_CHECK_FAILED);
|
||||
asked++;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* allocate and initialize the necessary maps
|
||||
*/
|
||||
bmapsize = roundup(howmany(maxfsblock, NBBY), sizeof(int16_t));
|
||||
blockmap = calloc((unsigned int)bmapsize, sizeof(char));
|
||||
if (blockmap == NULL) {
|
||||
printf("cannot alloc %u bytes for blockmap\n",
|
||||
(unsigned int)bmapsize);
|
||||
goto badsblabel;
|
||||
}
|
||||
statemap = calloc((unsigned int)(maxino + 2), sizeof(char));
|
||||
if (statemap == NULL) {
|
||||
printf("cannot alloc %u bytes for statemap\n",
|
||||
(unsigned int)(maxino + 1));
|
||||
goto badsblabel;
|
||||
}
|
||||
typemap = calloc((unsigned int)(maxino + 1), sizeof(char));
|
||||
if (typemap == NULL) {
|
||||
printf("cannot alloc %u bytes for typemap\n",
|
||||
(unsigned int)(maxino + 1));
|
||||
goto badsblabel;
|
||||
}
|
||||
lncntp = calloc((unsigned)(maxino + 1), sizeof(int16_t));
|
||||
if (lncntp == NULL) {
|
||||
printf("cannot alloc %u bytes for lncntp\n",
|
||||
(unsigned int)((maxino + 1) * sizeof(int16_t)));
|
||||
goto badsblabel;
|
||||
}
|
||||
for (numdirs = 0, cg = 0; cg < sblock.e2fs_ncg; cg++) {
|
||||
numdirs += fs2h16(sblock.e2fs_gd[cg].ext2bgd_ndirs);
|
||||
}
|
||||
inplast = 0;
|
||||
listmax = numdirs + 10;
|
||||
inpsort = calloc((unsigned int)listmax, sizeof(struct inoinfo *));
|
||||
inphead = calloc((unsigned int)numdirs, sizeof(struct inoinfo *));
|
||||
if (inpsort == NULL || inphead == NULL) {
|
||||
printf("cannot alloc %u bytes for inphead\n",
|
||||
(unsigned int)(numdirs * sizeof(struct inoinfo *)));
|
||||
goto badsblabel;
|
||||
}
|
||||
bufinit();
|
||||
return 1;
|
||||
|
||||
badsblabel:
|
||||
ckfini(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read in the super block and its summary info, convert to host byte order.
|
||||
*/
|
||||
static int
|
||||
readsb(int listerr)
|
||||
{
|
||||
daddr_t super = bflag ? bflag : SBOFF / dev_bsize;
|
||||
|
||||
if (bread(fsreadfd, (char *)sblk.b_un.b_fs, super, (long)SBSIZE) != 0)
|
||||
return 0;
|
||||
sblk.b_bno = super;
|
||||
sblk.b_size = SBSIZE;
|
||||
|
||||
/* Copy the superblock in memory */
|
||||
e2fs_sbload(sblk.b_un.b_fs, &sblock.e2fs);
|
||||
|
||||
/*
|
||||
* run a few consistency checks of the super block
|
||||
*/
|
||||
if (sblock.e2fs.e2fs_magic != E2FS_MAGIC) {
|
||||
badsb(listerr, "MAGIC NUMBER WRONG");
|
||||
return 0;
|
||||
}
|
||||
if (sblock.e2fs.e2fs_log_bsize > 2) {
|
||||
badsb(listerr, "BAD LOG_BSIZE");
|
||||
return 0;
|
||||
}
|
||||
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
|
||||
(!powerof2(sblock.e2fs.e2fs_inode_size) ||
|
||||
sblock.e2fs.e2fs_inode_size < sizeof(struct ext2fs_dinode) ||
|
||||
sblock.e2fs.e2fs_inode_size >
|
||||
(1024 << sblock.e2fs.e2fs_log_bsize))) {
|
||||
badsb(listerr, "BAD INODE_SIZE");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* compute the dynamic fields of the in-memory sb */
|
||||
/* compute dynamic sb infos */
|
||||
sblock.e2fs_ncg =
|
||||
howmany(sblock.e2fs.e2fs_bcount - sblock.e2fs.e2fs_first_dblock,
|
||||
sblock.e2fs.e2fs_bpg);
|
||||
/* XXX assume hw bsize = 512 */
|
||||
sblock.e2fs_fsbtodb = sblock.e2fs.e2fs_log_bsize + 1;
|
||||
sblock.e2fs_bsize = 1024 << sblock.e2fs.e2fs_log_bsize;
|
||||
sblock.e2fs_bshift = LOG_MINBSIZE + sblock.e2fs.e2fs_log_bsize;
|
||||
sblock.e2fs_qbmask = sblock.e2fs_bsize - 1;
|
||||
sblock.e2fs_bmask = ~sblock.e2fs_qbmask;
|
||||
sblock.e2fs_ngdb = howmany(sblock.e2fs_ncg,
|
||||
sblock.e2fs_bsize / sizeof(struct ext2_gd));
|
||||
sblock.e2fs_ipb = sblock.e2fs_bsize / EXT2_DINODE_SIZE(&sblock);
|
||||
sblock.e2fs_itpg = howmany(sblock.e2fs.e2fs_ipg, sblock.e2fs_ipb);
|
||||
|
||||
/*
|
||||
* Compute block size that the filesystem is based on,
|
||||
* according to fsbtodb, and adjust superblock block number
|
||||
* so we can tell if this is an alternate later.
|
||||
*/
|
||||
super *= dev_bsize;
|
||||
dev_bsize = sblock.e2fs_bsize / fsbtodb(&sblock, 1);
|
||||
sblk.b_bno = super / dev_bsize;
|
||||
|
||||
if (sblock.e2fs_ncg == 1) {
|
||||
/* no alternate superblock; assume it's okay */
|
||||
havesb = 1;
|
||||
return 1;
|
||||
}
|
||||
getblk(&asblk, 1 * sblock.e2fs.e2fs_bpg + sblock.e2fs.e2fs_first_dblock,
|
||||
(long)SBSIZE);
|
||||
if (asblk.b_errs)
|
||||
return 0;
|
||||
if (bflag) {
|
||||
havesb = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set all possible fields that could differ, then do check
|
||||
* of whole super block against an alternate super block.
|
||||
* When an alternate super-block is specified this check is skipped.
|
||||
*/
|
||||
asblk.b_un.b_fs->e2fs_rbcount = sblk.b_un.b_fs->e2fs_rbcount;
|
||||
asblk.b_un.b_fs->e2fs_fbcount = sblk.b_un.b_fs->e2fs_fbcount;
|
||||
asblk.b_un.b_fs->e2fs_ficount = sblk.b_un.b_fs->e2fs_ficount;
|
||||
asblk.b_un.b_fs->e2fs_mtime = sblk.b_un.b_fs->e2fs_mtime;
|
||||
asblk.b_un.b_fs->e2fs_wtime = sblk.b_un.b_fs->e2fs_wtime;
|
||||
asblk.b_un.b_fs->e2fs_mnt_count = sblk.b_un.b_fs->e2fs_mnt_count;
|
||||
asblk.b_un.b_fs->e2fs_max_mnt_count =
|
||||
sblk.b_un.b_fs->e2fs_max_mnt_count;
|
||||
asblk.b_un.b_fs->e2fs_state = sblk.b_un.b_fs->e2fs_state;
|
||||
asblk.b_un.b_fs->e2fs_beh = sblk.b_un.b_fs->e2fs_beh;
|
||||
asblk.b_un.b_fs->e2fs_lastfsck = sblk.b_un.b_fs->e2fs_lastfsck;
|
||||
asblk.b_un.b_fs->e2fs_fsckintv = sblk.b_un.b_fs->e2fs_fsckintv;
|
||||
asblk.b_un.b_fs->e2fs_ruid = sblk.b_un.b_fs->e2fs_ruid;
|
||||
asblk.b_un.b_fs->e2fs_rgid = sblk.b_un.b_fs->e2fs_rgid;
|
||||
asblk.b_un.b_fs->e2fs_block_group_nr =
|
||||
sblk.b_un.b_fs->e2fs_block_group_nr;
|
||||
asblk.b_un.b_fs->e2fs_features_rocompat &= ~EXT2F_ROCOMPAT_LARGEFILE;
|
||||
asblk.b_un.b_fs->e2fs_features_rocompat |=
|
||||
sblk.b_un.b_fs->e2fs_features_rocompat & EXT2F_ROCOMPAT_LARGEFILE;
|
||||
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
|
||||
((sblock.e2fs.e2fs_features_incompat & ~EXT2F_INCOMPAT_SUPP) ||
|
||||
(sblock.e2fs.e2fs_features_rocompat & ~EXT2F_ROCOMPAT_SUPP))) {
|
||||
if (debug) {
|
||||
printf("compat 0x%08x, incompat 0x%08x, compat_ro "
|
||||
"0x%08x\n",
|
||||
sblock.e2fs.e2fs_features_compat,
|
||||
sblock.e2fs.e2fs_features_incompat,
|
||||
sblock.e2fs.e2fs_features_rocompat);
|
||||
}
|
||||
badsb(listerr, "INCOMPATIBLE FEATURE BITS IN SUPER BLOCK");
|
||||
return 0;
|
||||
}
|
||||
if (memcmp(sblk.b_un.b_fs, asblk.b_un.b_fs, SBSIZE)) {
|
||||
if (debug) {
|
||||
u_int32_t *nlp, *olp, *endlp;
|
||||
|
||||
printf("superblock mismatches\n");
|
||||
nlp = (u_int32_t *)asblk.b_un.b_fs;
|
||||
olp = (u_int32_t *)sblk.b_un.b_fs;
|
||||
endlp = olp + (SBSIZE / sizeof(*olp));
|
||||
for ( ; olp < endlp; olp++, nlp++) {
|
||||
if (*olp == *nlp)
|
||||
continue;
|
||||
printf("offset %ld, original %ld, "
|
||||
"alternate %ld\n",
|
||||
(long)(olp - (u_int32_t *)sblk.b_un.b_fs),
|
||||
(long)fs2h32(*olp),
|
||||
(long)fs2h32(*nlp));
|
||||
}
|
||||
}
|
||||
badsb(listerr,
|
||||
"VALUES IN SUPER BLOCK DISAGREE WITH "
|
||||
"THOSE IN FIRST ALTERNATE");
|
||||
return 0;
|
||||
}
|
||||
havesb = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
copyback_sb(struct bufarea *bp)
|
||||
{
|
||||
/* Copy the in-memory superblock back to buffer */
|
||||
bp->b_un.b_fs->e2fs_icount = h2fs32(sblock.e2fs.e2fs_icount);
|
||||
bp->b_un.b_fs->e2fs_bcount = h2fs32(sblock.e2fs.e2fs_bcount);
|
||||
bp->b_un.b_fs->e2fs_rbcount = h2fs32(sblock.e2fs.e2fs_rbcount);
|
||||
bp->b_un.b_fs->e2fs_fbcount = h2fs32(sblock.e2fs.e2fs_fbcount);
|
||||
bp->b_un.b_fs->e2fs_ficount = h2fs32(sblock.e2fs.e2fs_ficount);
|
||||
bp->b_un.b_fs->e2fs_first_dblock =
|
||||
h2fs32(sblock.e2fs.e2fs_first_dblock);
|
||||
bp->b_un.b_fs->e2fs_log_bsize = h2fs32(sblock.e2fs.e2fs_log_bsize);
|
||||
bp->b_un.b_fs->e2fs_fsize = h2fs32(sblock.e2fs.e2fs_fsize);
|
||||
bp->b_un.b_fs->e2fs_bpg = h2fs32(sblock.e2fs.e2fs_bpg);
|
||||
bp->b_un.b_fs->e2fs_fpg = h2fs32(sblock.e2fs.e2fs_fpg);
|
||||
bp->b_un.b_fs->e2fs_ipg = h2fs32(sblock.e2fs.e2fs_ipg);
|
||||
bp->b_un.b_fs->e2fs_mtime = h2fs32(sblock.e2fs.e2fs_mtime);
|
||||
bp->b_un.b_fs->e2fs_wtime = h2fs32(sblock.e2fs.e2fs_wtime);
|
||||
bp->b_un.b_fs->e2fs_lastfsck = h2fs32(sblock.e2fs.e2fs_lastfsck);
|
||||
bp->b_un.b_fs->e2fs_fsckintv = h2fs32(sblock.e2fs.e2fs_fsckintv);
|
||||
bp->b_un.b_fs->e2fs_creator = h2fs32(sblock.e2fs.e2fs_creator);
|
||||
bp->b_un.b_fs->e2fs_rev = h2fs32(sblock.e2fs.e2fs_rev);
|
||||
bp->b_un.b_fs->e2fs_mnt_count = h2fs16(sblock.e2fs.e2fs_mnt_count);
|
||||
bp->b_un.b_fs->e2fs_max_mnt_count =
|
||||
h2fs16(sblock.e2fs.e2fs_max_mnt_count);
|
||||
bp->b_un.b_fs->e2fs_magic = h2fs16(sblock.e2fs.e2fs_magic);
|
||||
bp->b_un.b_fs->e2fs_state = h2fs16(sblock.e2fs.e2fs_state);
|
||||
bp->b_un.b_fs->e2fs_beh = h2fs16(sblock.e2fs.e2fs_beh);
|
||||
bp->b_un.b_fs->e2fs_ruid = h2fs16(sblock.e2fs.e2fs_ruid);
|
||||
bp->b_un.b_fs->e2fs_rgid = h2fs16(sblock.e2fs.e2fs_rgid);
|
||||
}
|
||||
|
||||
void
|
||||
badsb(int listerr, const char *s)
|
||||
{
|
||||
|
||||
if (!listerr)
|
||||
return;
|
||||
if (preen)
|
||||
printf("%s: ", cdevname());
|
||||
pfatal("BAD SUPER BLOCK: %s\n", s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate a prototype superblock based on information in the disk label.
|
||||
* When done the cgsblock macro can be calculated and the fs_ncg field
|
||||
* can be used. Do NOT attempt to use other macros without verifying that
|
||||
* their needed information is available!
|
||||
*/
|
||||
|
||||
int
|
||||
calcsb(const char *dev, int devfd, struct m_ext2fs *fs)
|
||||
{
|
||||
#ifdef __minix
|
||||
errexit("%s: calcsb: can't read disk label under minix", dev);
|
||||
#else
|
||||
struct disklabel *lp;
|
||||
struct partition *pp;
|
||||
char *cp;
|
||||
|
||||
cp = strchr(dev, '\0');
|
||||
if (cp-- == dev ||
|
||||
((*cp < 'a' || *cp > 'h') && !isdigit((unsigned char)*cp))) {
|
||||
pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev);
|
||||
return 0;
|
||||
}
|
||||
lp = getdisklabel(dev, devfd);
|
||||
if (isdigit((unsigned char)*cp))
|
||||
pp = &lp->d_partitions[0];
|
||||
else
|
||||
pp = &lp->d_partitions[*cp - 'a'];
|
||||
if (pp->p_fstype != FS_EX2FS) {
|
||||
pfatal("%s: NOT LABELED AS A EXT2 FILE SYSTEM (%s)\n",
|
||||
dev, pp->p_fstype < FSMAXTYPES ?
|
||||
fstypenames[pp->p_fstype] : "unknown");
|
||||
return 0;
|
||||
}
|
||||
memset(fs, 0, sizeof(struct m_ext2fs));
|
||||
fs->e2fs_bsize = pp->p_fsize;
|
||||
fs->e2fs.e2fs_log_bsize = pp->p_fsize / 1024;
|
||||
fs->e2fs.e2fs_bcount = (pp->p_size * DEV_BSIZE) / fs->e2fs_bsize;
|
||||
fs->e2fs.e2fs_first_dblock = (fs->e2fs.e2fs_log_bsize == 0) ? 1 : 0;
|
||||
fs->e2fs.e2fs_bpg = fs->e2fs_bsize * NBBY;
|
||||
fs->e2fs_bshift = LOG_MINBSIZE + fs->e2fs.e2fs_log_bsize;
|
||||
fs->e2fs_qbmask = fs->e2fs_bsize - 1;
|
||||
fs->e2fs_bmask = ~fs->e2fs_qbmask;
|
||||
fs->e2fs_ncg =
|
||||
howmany(fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock,
|
||||
fs->e2fs.e2fs_bpg);
|
||||
fs->e2fs_fsbtodb = fs->e2fs.e2fs_log_bsize + 1;
|
||||
fs->e2fs_ngdb = howmany(fs->e2fs_ncg,
|
||||
fs->e2fs_bsize / sizeof(struct ext2_gd));
|
||||
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct disklabel *
|
||||
getdisklabel(const char *s, int fd)
|
||||
{
|
||||
static struct disklabel lab;
|
||||
|
||||
#ifdef __minix
|
||||
if (s == NULL)
|
||||
return NULL;
|
||||
errexit("%s: can't read disk label under minix", s);
|
||||
#else
|
||||
if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) {
|
||||
if (s == NULL)
|
||||
return NULL;
|
||||
pwarn("ioctl (GCINFO): %s\n", strerror(errno));
|
||||
errexit("%s: can't read disk label", s);
|
||||
}
|
||||
#endif
|
||||
return &lab;
|
||||
}
|
||||
|
||||
daddr_t
|
||||
cgoverhead(int c)
|
||||
{
|
||||
int overh;
|
||||
overh =
|
||||
1 /* block bitmap */ +
|
||||
1 /* inode bitmap */ +
|
||||
sblock.e2fs_itpg;
|
||||
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
|
||||
sblock.e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_SPARSESUPER) {
|
||||
if (cg_has_sb(c) == 0)
|
||||
return overh;
|
||||
}
|
||||
overh += 1 /* superblock */ + sblock.e2fs_ngdb;
|
||||
return overh;
|
||||
}
|
527
sbin/fsck_ext2fs/utilities.c
Normal file
527
sbin/fsck_ext2fs/utilities.c
Normal file
|
@ -0,0 +1,527 @@
|
|||
/* $NetBSD: utilities.c,v 1.22 2011/06/09 19:57:51 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1980, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Manuel Bouyer.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)utilities.c 8.1 (Berkeley) 6/5/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: utilities.c,v 1.22 2011/06/09 19:57:51 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <ufs/ext2fs/ext2fs_dinode.h>
|
||||
#include <ufs/ext2fs/ext2fs_dir.h>
|
||||
#include <ufs/ext2fs/ext2fs.h>
|
||||
#include <ufs/ufs/dinode.h> /* for IFMT & friends */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "fsutil.h"
|
||||
#include "fsck.h"
|
||||
#include "extern.h"
|
||||
#include "exitvalues.h"
|
||||
|
||||
long diskreads, totalreads; /* Disk cache statistics */
|
||||
|
||||
static void rwerror(const char *, daddr_t);
|
||||
|
||||
int
|
||||
ftypeok(struct ext2fs_dinode *dp)
|
||||
{
|
||||
switch (fs2h16(dp->e2di_mode) & IFMT) {
|
||||
|
||||
case IFDIR:
|
||||
case IFREG:
|
||||
case IFBLK:
|
||||
case IFCHR:
|
||||
case IFLNK:
|
||||
case IFSOCK:
|
||||
case IFIFO:
|
||||
return (1);
|
||||
|
||||
default:
|
||||
if (debug)
|
||||
printf("bad file type 0%o\n", fs2h16(dp->e2di_mode));
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
reply(const char *question)
|
||||
{
|
||||
int persevere;
|
||||
char c;
|
||||
|
||||
if (preen)
|
||||
pfatal("INTERNAL ERROR: GOT TO reply()");
|
||||
persevere = !strcmp(question, "CONTINUE");
|
||||
printf("\n");
|
||||
if (!persevere && (nflag || fswritefd < 0)) {
|
||||
printf("%s? no\n\n", question);
|
||||
return (0);
|
||||
}
|
||||
if (yflag || (persevere && nflag)) {
|
||||
printf("%s? yes\n\n", question);
|
||||
return (1);
|
||||
}
|
||||
do {
|
||||
printf("%s? [yn] ", question);
|
||||
(void) fflush(stdout);
|
||||
c = getc(stdin);
|
||||
while (c != '\n' && getc(stdin) != '\n')
|
||||
if (feof(stdin))
|
||||
return (0);
|
||||
} while (c != 'y' && c != 'Y' && c != 'n' && c != 'N');
|
||||
printf("\n");
|
||||
if (c == 'y' || c == 'Y')
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Malloc buffers and set up cache.
|
||||
*/
|
||||
void
|
||||
bufinit(void)
|
||||
{
|
||||
struct bufarea *bp;
|
||||
long bufcnt, i;
|
||||
char *bufp;
|
||||
|
||||
diskreads = totalreads = 0;
|
||||
pbp = pdirbp = (struct bufarea *)0;
|
||||
bufhead.b_next = bufhead.b_prev = &bufhead;
|
||||
bufcnt = MAXBUFSPACE / sblock.e2fs_bsize;
|
||||
if (bufcnt < MINBUFS)
|
||||
bufcnt = MINBUFS;
|
||||
for (i = 0; i < bufcnt; i++) {
|
||||
bp = malloc(sizeof(struct bufarea));
|
||||
bufp = malloc((size_t)sblock.e2fs_bsize);
|
||||
if (bp == NULL || bufp == NULL) {
|
||||
free(bp);
|
||||
free(bufp);
|
||||
if (i >= MINBUFS)
|
||||
break;
|
||||
errexit("cannot allocate buffer pool");
|
||||
}
|
||||
bp->b_un.b_buf = bufp;
|
||||
bp->b_prev = &bufhead;
|
||||
bp->b_next = bufhead.b_next;
|
||||
bufhead.b_next->b_prev = bp;
|
||||
bufhead.b_next = bp;
|
||||
initbarea(bp);
|
||||
}
|
||||
bufhead.b_size = i; /* save number of buffers */
|
||||
}
|
||||
|
||||
/*
|
||||
* Manage a cache of directory blocks.
|
||||
*/
|
||||
struct bufarea *
|
||||
getdatablk(daddr_t blkno, long size)
|
||||
{
|
||||
struct bufarea *bp;
|
||||
|
||||
for (bp = bufhead.b_next; bp != &bufhead; bp = bp->b_next)
|
||||
if (bp->b_bno == fsbtodb(&sblock, blkno))
|
||||
goto foundit;
|
||||
for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev)
|
||||
if ((bp->b_flags & B_INUSE) == 0)
|
||||
break;
|
||||
if (bp == &bufhead)
|
||||
errexit("deadlocked buffer pool");
|
||||
getblk(bp, blkno, size);
|
||||
diskreads++;
|
||||
/* fall through */
|
||||
foundit:
|
||||
totalreads++;
|
||||
bp->b_prev->b_next = bp->b_next;
|
||||
bp->b_next->b_prev = bp->b_prev;
|
||||
bp->b_prev = &bufhead;
|
||||
bp->b_next = bufhead.b_next;
|
||||
bufhead.b_next->b_prev = bp;
|
||||
bufhead.b_next = bp;
|
||||
bp->b_flags |= B_INUSE;
|
||||
return (bp);
|
||||
}
|
||||
|
||||
void
|
||||
getblk(struct bufarea *bp, daddr_t blk, long size)
|
||||
{
|
||||
daddr_t dblk;
|
||||
|
||||
dblk = fsbtodb(&sblock, blk);
|
||||
if (bp->b_bno != dblk) {
|
||||
flush(fswritefd, bp);
|
||||
bp->b_errs = bread(fsreadfd, bp->b_un.b_buf, dblk, size);
|
||||
bp->b_bno = dblk;
|
||||
bp->b_size = size;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
flush(int fd, struct bufarea *bp)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!bp->b_dirty)
|
||||
return;
|
||||
if (bp->b_errs != 0)
|
||||
pfatal("WRITING %sZERO'ED BLOCK %lld TO DISK\n",
|
||||
(bp->b_errs == bp->b_size / dev_bsize) ? "" : "PARTIALLY ",
|
||||
(long long)bp->b_bno);
|
||||
bp->b_dirty = 0;
|
||||
bp->b_errs = 0;
|
||||
bwrite(fd, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size);
|
||||
if (bp != &sblk)
|
||||
return;
|
||||
for (i = 0; i < sblock.e2fs_ngdb; i++) {
|
||||
bwrite(fswritefd, (char *)
|
||||
&sblock.e2fs_gd[i* sblock.e2fs_bsize / sizeof(struct ext2_gd)],
|
||||
fsbtodb(&sblock, ((sblock.e2fs_bsize>1024)?0:1)+i+1),
|
||||
sblock.e2fs_bsize);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rwerror(const char *mesg, daddr_t blk)
|
||||
{
|
||||
|
||||
if (preen == 0)
|
||||
printf("\n");
|
||||
pfatal("CANNOT %s: BLK %lld", mesg, (long long)blk);
|
||||
if (reply("CONTINUE") == 0)
|
||||
errexit("Program terminated");
|
||||
}
|
||||
|
||||
void
|
||||
ckfini(int markclean)
|
||||
{
|
||||
struct bufarea *bp, *nbp;
|
||||
int cnt = 0;
|
||||
|
||||
if (fswritefd < 0) {
|
||||
(void)close(fsreadfd);
|
||||
return;
|
||||
}
|
||||
flush(fswritefd, &sblk);
|
||||
if (havesb && sblk.b_bno != SBOFF / dev_bsize &&
|
||||
!preen && reply("UPDATE STANDARD SUPERBLOCKS")) {
|
||||
sblk.b_bno = SBOFF / dev_bsize;
|
||||
sbdirty();
|
||||
flush(fswritefd, &sblk);
|
||||
copyback_sb(&asblk);
|
||||
asblk.b_dirty = 1;
|
||||
flush(fswritefd, &asblk);
|
||||
}
|
||||
for (bp = bufhead.b_prev; bp && bp != &bufhead; bp = nbp) {
|
||||
cnt++;
|
||||
flush(fswritefd, bp);
|
||||
nbp = bp->b_prev;
|
||||
free(bp->b_un.b_buf);
|
||||
free(bp);
|
||||
}
|
||||
if (bufhead.b_size != cnt)
|
||||
errexit("Panic: lost %d buffers", bufhead.b_size - cnt);
|
||||
pbp = pdirbp = (struct bufarea *)0;
|
||||
if (markclean && (sblock.e2fs.e2fs_state & E2FS_ISCLEAN) == 0) {
|
||||
/*
|
||||
* Mark the file system as clean, and sync the superblock.
|
||||
*/
|
||||
if (preen)
|
||||
pwarn("MARKING FILE SYSTEM CLEAN\n");
|
||||
else if (!reply("MARK FILE SYSTEM CLEAN"))
|
||||
markclean = 0;
|
||||
if (markclean) {
|
||||
sblock.e2fs.e2fs_state = E2FS_ISCLEAN;
|
||||
sbdirty();
|
||||
flush(fswritefd, &sblk);
|
||||
}
|
||||
}
|
||||
if (debug)
|
||||
printf("cache missed %ld of %ld (%d%%)\n", diskreads,
|
||||
totalreads, (int)(diskreads * 100 / totalreads));
|
||||
(void)close(fsreadfd);
|
||||
(void)close(fswritefd);
|
||||
}
|
||||
|
||||
int
|
||||
bread(int fd, char *buf, daddr_t blk, long size)
|
||||
{
|
||||
char *cp;
|
||||
int i, errs;
|
||||
#ifndef __minix
|
||||
off_t offset;
|
||||
#else
|
||||
u64_t offset;
|
||||
#endif
|
||||
|
||||
offset = blk;
|
||||
offset *= dev_bsize;
|
||||
#ifndef __minix
|
||||
if (lseek(fd, offset, 0) < 0)
|
||||
rwerror("SEEK", blk);
|
||||
#else
|
||||
if (lseek64(fd, offset, 0, NULL) < 0)
|
||||
rwerror("SEEK", blk);
|
||||
#endif
|
||||
else if (read(fd, buf, (int)size) == size)
|
||||
return (0);
|
||||
rwerror("READ", blk);
|
||||
#ifndef __minix
|
||||
if (lseek(fd, offset, 0) < 0)
|
||||
rwerror("SEEK", blk);
|
||||
#else
|
||||
if (lseek64(fd, offset, 0, NULL) < 0)
|
||||
rwerror("SEEK", blk);
|
||||
#endif
|
||||
errs = 0;
|
||||
memset(buf, 0, (size_t)size);
|
||||
printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:");
|
||||
for (cp = buf, i = 0; i < size; i += secsize, cp += secsize) {
|
||||
if (read(fd, cp, (int)secsize) != secsize) {
|
||||
(void)lseek(fd, offset + i + secsize, 0);
|
||||
if (secsize != dev_bsize && dev_bsize != 1)
|
||||
printf(" %lld (%lld),",
|
||||
(long long)((blk*dev_bsize + i) / secsize),
|
||||
(long long)(blk + i / dev_bsize));
|
||||
else
|
||||
printf(" %lld,", (long long)(blk +
|
||||
i / dev_bsize));
|
||||
errs++;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
return (errs);
|
||||
}
|
||||
|
||||
void
|
||||
bwrite(int fd, char *buf, daddr_t blk, long size)
|
||||
{
|
||||
int i;
|
||||
char *cp;
|
||||
#ifndef __minix
|
||||
off_t offset;
|
||||
#else
|
||||
u64_t offset;
|
||||
#endif
|
||||
|
||||
if (fd < 0)
|
||||
return;
|
||||
offset = blk;
|
||||
offset *= dev_bsize;
|
||||
#ifndef __minix
|
||||
if (lseek(fd, offset, 0) < 0)
|
||||
rwerror("SEEK", blk);
|
||||
#else
|
||||
if (lseek64(fd, offset, 0, NULL) < 0)
|
||||
rwerror("SEEK", blk);
|
||||
#endif
|
||||
else if (write(fd, buf, (int)size) == size) {
|
||||
fsmodified = 1;
|
||||
return;
|
||||
}
|
||||
rwerror("WRITE", blk);
|
||||
#ifndef __minix
|
||||
if (lseek(fd, offset, 0) < 0)
|
||||
rwerror("SEEK", blk);
|
||||
#else
|
||||
if (lseek64(fd, offset, 0, NULL) < 0)
|
||||
rwerror("SEEK", blk);
|
||||
#endif
|
||||
printf("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:");
|
||||
for (cp = buf, i = 0; i < size; i += dev_bsize, cp += dev_bsize)
|
||||
if (write(fd, cp, (int)dev_bsize) != dev_bsize) {
|
||||
(void)lseek(fd, offset + i + dev_bsize, 0);
|
||||
printf(" %lld,", (long long)(blk + i / dev_bsize));
|
||||
}
|
||||
printf("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate a data block
|
||||
*/
|
||||
int
|
||||
allocblk(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < maxfsblock - 1; i++) {
|
||||
if (testbmap(i))
|
||||
continue;
|
||||
setbmap(i);
|
||||
n_blks++;
|
||||
return (i);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free a previously allocated block
|
||||
*/
|
||||
void
|
||||
freeblk(daddr_t blkno)
|
||||
{
|
||||
struct inodesc idesc;
|
||||
|
||||
idesc.id_blkno = blkno;
|
||||
idesc.id_numfrags = 1;
|
||||
(void)pass4check(&idesc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a pathname
|
||||
*/
|
||||
void
|
||||
getpathname(char *namebuf, size_t namebuflen, ino_t curdir, ino_t ino)
|
||||
{
|
||||
int len;
|
||||
char *cp;
|
||||
struct inodesc idesc;
|
||||
static int busy = 0;
|
||||
|
||||
if (curdir == ino && ino == EXT2_ROOTINO) {
|
||||
(void)strlcpy(namebuf, "/", namebuflen);
|
||||
return;
|
||||
}
|
||||
if (busy ||
|
||||
(statemap[curdir] != DSTATE && statemap[curdir] != DFOUND)) {
|
||||
(void)strlcpy(namebuf, "?", namebuflen);
|
||||
return;
|
||||
}
|
||||
busy = 1;
|
||||
memset(&idesc, 0, sizeof(struct inodesc));
|
||||
idesc.id_type = DATA;
|
||||
idesc.id_fix = IGNORE;
|
||||
cp = &namebuf[MAXPATHLEN - 1];
|
||||
*cp = '\0';
|
||||
if (curdir != ino) {
|
||||
idesc.id_parent = curdir;
|
||||
goto namelookup;
|
||||
}
|
||||
while (ino != EXT2_ROOTINO) {
|
||||
idesc.id_number = ino;
|
||||
idesc.id_func = findino;
|
||||
idesc.id_name = "..";
|
||||
if ((ckinode(ginode(ino), &idesc) & FOUND) == 0)
|
||||
break;
|
||||
namelookup:
|
||||
idesc.id_number = idesc.id_parent;
|
||||
idesc.id_parent = ino;
|
||||
idesc.id_func = findname;
|
||||
idesc.id_name = namebuf;
|
||||
if ((ckinode(ginode(idesc.id_number), &idesc)&FOUND) == 0)
|
||||
break;
|
||||
len = strlen(namebuf);
|
||||
cp -= len;
|
||||
memcpy(cp, namebuf, (size_t)len);
|
||||
*--cp = '/';
|
||||
if (cp < &namebuf[EXT2FS_MAXNAMLEN])
|
||||
break;
|
||||
ino = idesc.id_number;
|
||||
}
|
||||
busy = 0;
|
||||
if (ino != EXT2_ROOTINO)
|
||||
*--cp = '?';
|
||||
memcpy(namebuf, cp, (size_t)(&namebuf[MAXPATHLEN] - cp));
|
||||
}
|
||||
|
||||
/*
|
||||
* determine whether an inode should be fixed.
|
||||
*/
|
||||
int
|
||||
dofix(struct inodesc *idesc, const char *msg)
|
||||
{
|
||||
|
||||
switch (idesc->id_fix) {
|
||||
|
||||
case DONTKNOW:
|
||||
if (idesc->id_type == DATA)
|
||||
direrror(idesc->id_number, msg);
|
||||
else
|
||||
pwarn("%s", msg);
|
||||
if (preen) {
|
||||
printf(" (SALVAGED)\n");
|
||||
idesc->id_fix = FIX;
|
||||
return (ALTERED);
|
||||
}
|
||||
if (reply("SALVAGE") == 0) {
|
||||
idesc->id_fix = NOFIX;
|
||||
return (0);
|
||||
}
|
||||
idesc->id_fix = FIX;
|
||||
return (ALTERED);
|
||||
|
||||
case FIX:
|
||||
return (ALTERED);
|
||||
|
||||
case NOFIX:
|
||||
case IGNORE:
|
||||
return (0);
|
||||
|
||||
default:
|
||||
errexit("UNKNOWN INODESC FIX MODE %d", idesc->id_fix);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
27
sbin/newfs_ext2fs/Makefile
Normal file
27
sbin/newfs_ext2fs/Makefile
Normal file
|
@ -0,0 +1,27 @@
|
|||
# $NetBSD: Makefile,v 1.3 2009/06/05 21:52:31 haad Exp $
|
||||
# @(#)Makefile 8.2 (Berkeley) 3/27/94
|
||||
|
||||
WARNS?= 3 # XXX: sign-compare issues
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
PROG= newfs_ext2fs
|
||||
SRCS= newfs_ext2fs.c mke2fs.c ext2fs_bswap.c partutil.c
|
||||
MAN= newfs_ext2fs.8
|
||||
|
||||
FSCK=${NETBSDSRCDIR}/sbin/fsck
|
||||
MYFSCK=${NETBSDSRCDIR}/sbin/fsck_ext2fs
|
||||
CPPFLAGS+=-I${.CURDIR} -I${FSCK}
|
||||
|
||||
DPADD+= ${LIBUTIL}
|
||||
LDADD+= -lutil
|
||||
|
||||
LDADD+=-lprop
|
||||
DPADD+=${LIBPROP}
|
||||
|
||||
SYMLINKS+= $(BINDIR)/$(PROG) $(BINDIR)/newfs_ext2 \
|
||||
$(BINDIR)/$(PROG) $(BINDIR)/mkfs.ext2
|
||||
|
||||
.PATH: ${FSCK} ${MYFSCK} #${NETBSDSRCDIR}/sys/ufs/ext2fs
|
||||
|
||||
.include <bsd.prog.mk>
|
45
sbin/newfs_ext2fs/extern.h
Normal file
45
sbin/newfs_ext2fs/extern.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/* $NetBSD: extern.h,v 1.4 2009/10/21 01:07:46 snj Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Christos Zoulas. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* XXX should be in <sys/ufs/ext2fs.h> */
|
||||
#define EXT2_LOG_MAXBSIZE 12
|
||||
#define EXT2_MAXBSIZE (1 << EXT2_LOG_MAXBSIZE)
|
||||
|
||||
/* prototypes */
|
||||
void mke2fs(const char *, int, int);
|
||||
|
||||
/* variables set up by front end. */
|
||||
extern int Nflag; /* run mkfs without writing file system */
|
||||
extern int Oflag; /* format as an 4.3BSD file system */
|
||||
extern int verbosity; /* amount of printf() output */
|
||||
extern int64_t fssize; /* file system size */
|
||||
extern uint16_t inodesize; /* bytes per inode */
|
||||
extern uint sectorsize; /* sector size */
|
||||
extern uint fsize; /* fragment size */
|
||||
extern uint bsize; /* block size */
|
||||
extern uint minfree; /* free space threshold */
|
||||
extern uint num_inodes; /* number of inodes (overrides density) */
|
||||
extern char *volname; /* volume name */
|
1459
sbin/newfs_ext2fs/mke2fs.c
Normal file
1459
sbin/newfs_ext2fs/mke2fs.c
Normal file
File diff suppressed because it is too large
Load diff
326
sbin/newfs_ext2fs/newfs_ext2fs.8
Normal file
326
sbin/newfs_ext2fs/newfs_ext2fs.8
Normal file
|
@ -0,0 +1,326 @@
|
|||
.\" $NetBSD: newfs_ext2fs.8,v 1.11 2010/02/25 13:09:17 tsutsui Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1983, 1987, 1991, 1993, 1994
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)newfs.8 8.6 (Berkeley) 5/3/95
|
||||
.\"
|
||||
.Dd March 1, 2009
|
||||
.Dt NEWFS_EXT2FS 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm newfs_ext2fs
|
||||
.Nd construct a new ext2 file system
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl FINZ
|
||||
.Op Fl b Ar block-size
|
||||
.Op Fl D Ar inodesize
|
||||
.Op Fl f Ar frag-size
|
||||
.Op Fl i Ar bytes-per-inode
|
||||
.Op Fl m Ar free-space
|
||||
.Op Fl n Ar inodes
|
||||
.Op Fl O Ar filesystem-format
|
||||
.Op Fl S Ar sector-size
|
||||
.Op Fl s Ar size
|
||||
.Op Fl V Ar verbose
|
||||
.Op Fl v Ar volname
|
||||
.Ar special
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is used to initialize and clear ext2 file systems before first use.
|
||||
Before running
|
||||
.Nm
|
||||
the disk must be labeled using
|
||||
.Xr disklabel 8 .
|
||||
.Nm
|
||||
builds a file system on the specified special device
|
||||
basing its defaults on the information in the disk label.
|
||||
Typically the defaults are reasonable, however
|
||||
.Nm
|
||||
has numerous options to allow the defaults to be selectively overridden.
|
||||
.Pp
|
||||
Options with numeric arguments may contain an optional (case-insensitive)
|
||||
suffix:
|
||||
.Bl -tag -width 3n -offset indent -compact
|
||||
.It b
|
||||
Bytes; causes no modification.
|
||||
(Default)
|
||||
.It k
|
||||
Kilo; multiply the argument by 1024.
|
||||
.It m
|
||||
Mega; multiply the argument by 1048576.
|
||||
.It g
|
||||
Giga; multiply the argument by 1073741824.
|
||||
.El
|
||||
.Pp
|
||||
The following options define the general layout policies.
|
||||
.Bl -tag -width Fl
|
||||
.It Fl b Ar block-size
|
||||
The block size of the file system, in bytes.
|
||||
It must be a power of two.
|
||||
The smallest allowable size is 1024 bytes.
|
||||
The default size depends upon the size of the file system:
|
||||
.Pp
|
||||
.Bl -tag -width "file system size" -compact -offset indent
|
||||
.It Sy "file system size"
|
||||
.Ar block-size
|
||||
.It \*[Lt]= 512 MB
|
||||
1 KB
|
||||
.It \*[Gt] 512 MB
|
||||
4 KB
|
||||
.El
|
||||
.It Fl D Ar inodesize
|
||||
Set the inode size.
|
||||
Defaults to 128, and can also be set to 256 for
|
||||
compatibility with ext4.
|
||||
.It Fl F
|
||||
Create a file system image in
|
||||
.Ar special .
|
||||
The file system size needs to be specified with
|
||||
.Dq Fl s Ar size .
|
||||
No attempts to use or update the disk label will be made.
|
||||
.It Fl f Ar frag-size
|
||||
The fragment size of the file system in bytes.
|
||||
It must be the same with blocksize because the current ext2fs
|
||||
implementation doesn't support fragmentation.
|
||||
.It Fl I
|
||||
Do not require that the file system type listed in the disk label is
|
||||
.Ql Linux\ Ext2 .
|
||||
.It Fl i Ar bytes-per-inode
|
||||
This specifies the density of inodes in the file system.
|
||||
If fewer inodes are desired, a larger number should be used;
|
||||
to create more inodes a smaller number should be given.
|
||||
.It Fl m Ar free-space
|
||||
The percentage of space reserved from normal users; the minimum free
|
||||
space threshold.
|
||||
The default value used is 5%.
|
||||
.It Fl N
|
||||
Causes the file system parameters to be printed out
|
||||
without really creating the file system.
|
||||
.It Fl n Ar inodes
|
||||
This specifies the number of inodes for the file system.
|
||||
If both
|
||||
.Fl i
|
||||
and
|
||||
.Fl n
|
||||
are specified then
|
||||
.Fl n
|
||||
takes precedence.
|
||||
The default number of inodes is calculated from a number of blocks in
|
||||
the file system.
|
||||
.It Fl O Ar filesystem-format
|
||||
Select the filesystem-format.
|
||||
.Bl -tag -width 3n -offset indent -compact
|
||||
.It 0
|
||||
.Ql GOOD_OLD_REV ;
|
||||
this option is primarily used to build root file systems that can be
|
||||
understood by old or dumb firmwares for bootstrap.
|
||||
(default)
|
||||
.It 1
|
||||
.Ql DYNAMIC_REV ;
|
||||
various extended (and sometimes incompatible) features are enabled
|
||||
(though not all features are supported on
|
||||
.Nx ) .
|
||||
Currently only the following features are supported:
|
||||
.Bl -tag -width "SPARSESUPER" -offset indent -compact
|
||||
.It RESIZE
|
||||
Prepare some reserved structures which enable future file system resizing.
|
||||
.It FTYPE
|
||||
Store file types in directory entries to improve performance.
|
||||
.It SPARSESUPER
|
||||
Prepare superblock backups for the
|
||||
.Xr fsck_ext2fs 8
|
||||
utility on not all but sparse block groups.
|
||||
.It LARGEFILE
|
||||
Enable files larger than 2G bytes.
|
||||
.El
|
||||
.El
|
||||
.It Fl s Ar size
|
||||
The size of the file system in sectors.
|
||||
An
|
||||
.Sq s
|
||||
suffix will be interpreted as the number of sectors (the default).
|
||||
All other suffixes are interpreted as per other numeric arguments,
|
||||
except that the number is converted into sectors by dividing by the
|
||||
sector size (as specified by
|
||||
.Fl S Ar secsize )
|
||||
after suffix interpretation.
|
||||
.Pp
|
||||
If no
|
||||
.Fl s Ar size
|
||||
is specified then the filesystem size defaults to that of the partition, or,
|
||||
if
|
||||
.Fl F
|
||||
is specified, the existing file.
|
||||
.Pp
|
||||
If
|
||||
.Ar size
|
||||
is negative the specified size is subtracted from the default size
|
||||
(reserving space at the end of the partition).
|
||||
.It Fl V Ar verbose
|
||||
This controls the amount of information written to stdout:
|
||||
.Bl -tag -width 3n -offset indent -compact
|
||||
.It 0
|
||||
No output.
|
||||
.It 1
|
||||
Overall size and cylinder group details.
|
||||
.It 2
|
||||
A progress bar (dots ending at right hand margin).
|
||||
.It 3
|
||||
The first few super-block backup sector numbers are displayed before the
|
||||
progress bar.
|
||||
.It 4
|
||||
All the super-block backup sector numbers are displayed (no progress bar).
|
||||
.El
|
||||
The default is 3.
|
||||
If
|
||||
.Fl N
|
||||
is specified
|
||||
.Nm
|
||||
stops before outputting the progress bar.
|
||||
.It Fl v Ar volname
|
||||
This specifies a volume name for the file system.
|
||||
.It Fl Z
|
||||
Pre-zeros the file system image created with
|
||||
.Fl F .
|
||||
This is necessary if the image is to be used by
|
||||
.Xr vnd 4
|
||||
(which doesn't support file systems with
|
||||
.Sq holes ) .
|
||||
.El
|
||||
.Pp
|
||||
The following option overrides the standard sizes for the disk geometry.
|
||||
The default value is taken from the disk label.
|
||||
Changing this default is useful only when using
|
||||
.Nm
|
||||
to build a file system whose raw image will eventually be used on a
|
||||
different type of disk than the one on which it is initially created
|
||||
(for example on a write-once disk).
|
||||
Note that changing this value from its default will make it impossible for
|
||||
.Xr fsck_ext2fs 8
|
||||
to find the alternative superblocks if the standard superblock is lost.
|
||||
.Bl -tag -width Fl
|
||||
.It Fl S Ar sector-size
|
||||
The size of a sector in bytes (almost never anything but 512).
|
||||
Defaults to 512.
|
||||
.El
|
||||
.Sh NOTES
|
||||
There is no option to specify the metadata byte order on the file system
|
||||
to be created because the native ext2 file system is always little endian
|
||||
even on big endian hosts.
|
||||
.Pp
|
||||
The file system is created with
|
||||
.Sq random
|
||||
inode generation numbers to improve NFS security.
|
||||
.Pp
|
||||
The owner and group IDs of the root node and reserved blocks of the new
|
||||
file system are set to the effective UID and GID of the user initializing
|
||||
the file system.
|
||||
.Pp
|
||||
For the
|
||||
.Nm
|
||||
command to succeed,
|
||||
the disk label should first be updated such that the fstype field for the
|
||||
partition is set to
|
||||
.Ql Linux\ Ext2 ,
|
||||
unless
|
||||
.Fl F
|
||||
or
|
||||
.Fl I
|
||||
is used.
|
||||
.Pp
|
||||
.\" To create and populate a filesystem image within a file use the
|
||||
.\" .Xr makefs 8
|
||||
.\" utility.
|
||||
.\" .Pp
|
||||
The partition size is found using
|
||||
.Xr fstat 2 ,
|
||||
not by inspecting the disk label.
|
||||
The block size and fragment size will be written back to the disk label
|
||||
only if the last character of
|
||||
.Ar special
|
||||
references the same partition as the minor device number.
|
||||
.Sh SEE ALSO
|
||||
.Xr fstat 2 ,
|
||||
.Xr disklabel 5 ,
|
||||
.Xr disktab 5 ,
|
||||
.Xr fs 5 ,
|
||||
.Xr disklabel 8 ,
|
||||
.Xr diskpart 8 ,
|
||||
.\" .Xr dumpfs 8 ,
|
||||
.\" .Xr format 8 ,
|
||||
.Xr fsck_ext2fs 8 ,
|
||||
.\" .Xr makefs 8 ,
|
||||
.Xr mount 8 ,
|
||||
.Xr mount_ext2fs 8 ,
|
||||
.Xr newfs 8
|
||||
.Rs
|
||||
.%A Remy Card
|
||||
.%A Theodore Ts'o
|
||||
.%A Stephen Tweedie
|
||||
.%T "Design and Implementation of the Second Extended Filesystem"
|
||||
.%J "The Proceedings of the First Dutch International Symposium on Linux"
|
||||
.%U http://e2fsprogs.sourceforge.net/ext2intro.html
|
||||
.Re
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command first appeared in
|
||||
.Nx 5.0 .
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
command was written by
|
||||
.An Izumi Tsutsui
|
||||
.Aq tsutsui@NetBSD.org .
|
||||
.Sh BUGS
|
||||
The
|
||||
.Nm
|
||||
command is still experimental and there are few sanity checks.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
command doesn't have options to specify each REV1 file system feature
|
||||
independently.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
command doesn't support the bad block list accounted by the bad blocks inode.
|
||||
.Pp
|
||||
Many newer ext2 file system features (especially journaling) are
|
||||
not supported yet.
|
||||
.Pp
|
||||
Some features in file systems created by the
|
||||
.Nm
|
||||
command might not be recognized properly by the
|
||||
.Xr fsck_ext2fs 8
|
||||
utility.
|
||||
.Pp
|
||||
There is no native tool in the
|
||||
.Nx
|
||||
distribution for resizing ext2 file systems yet.
|
530
sbin/newfs_ext2fs/newfs_ext2fs.c
Normal file
530
sbin/newfs_ext2fs/newfs_ext2fs.c
Normal file
|
@ -0,0 +1,530 @@
|
|||
/* $NetBSD: newfs_ext2fs.c,v 1.8 2009/03/02 10:38:13 tsutsui Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1989, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__COPYRIGHT("@(#) Copyright (c) 1983, 1989, 1993, 1994\
|
||||
The Regents of the University of California. All rights reserved.");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)newfs.c 8.13 (Berkeley) 5/1/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: newfs_ext2fs.c,v 1.8 2009/03/02 10:38:13 tsutsui Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* newfs: friendly front end to mke2fs
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/disk.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#include <ufs/ext2fs/ext2fs.h>
|
||||
#include <ufs/ext2fs/ext2fs_dinode.h>
|
||||
|
||||
#include <disktab.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <paths.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <util.h>
|
||||
#include <mntopts.h>
|
||||
|
||||
#include <minix/partition.h>
|
||||
|
||||
#include "extern.h"
|
||||
#include "partutil.h"
|
||||
|
||||
static int64_t strsuftoi64(const char *, const char *, int64_t, int64_t, int *);
|
||||
static void usage(void) __dead;
|
||||
|
||||
/*
|
||||
* For file systems smaller than SMALL_FSSIZE we use the S_DFL_* defaults,
|
||||
* otherwise if less than MEDIUM_FSSIZE use M_DFL_*, otherwise use
|
||||
* L_DFL_*.
|
||||
*/
|
||||
#define SMALL_FSSIZE ((4 * 1024 * 1024) / sectorsize) /* 4MB */
|
||||
#define S_DFL_BSIZE 1024
|
||||
#define MEDIUM_FSSIZE ((512 * 1024 * 1024) / sectorsize) /* 512MB */
|
||||
#define M_DFL_BSIZE 1024
|
||||
#define L_DFL_BSIZE 4096
|
||||
|
||||
/*
|
||||
* Each file system has a number of inodes statically allocated.
|
||||
* We allocate one inode slot per 2, 4, or 8 blocks, expecting this
|
||||
* to be far more than we will ever need.
|
||||
*/
|
||||
#define S_DFL_NINODE(blocks) ((blocks) / 8)
|
||||
#define M_DFL_NINODE(blocks) ((blocks) / 4)
|
||||
#define L_DFL_NINODE(blocks) ((blocks) / 2)
|
||||
|
||||
/*
|
||||
* Default sector size.
|
||||
*/
|
||||
#define DFL_SECSIZE 512
|
||||
|
||||
int Nflag; /* run without writing file system */
|
||||
int Oflag = 0; /* format as conservative REV0 by default */
|
||||
int verbosity; /* amount of printf() output */
|
||||
#define DEFAULT_VERBOSITY 3 /* 4 is traditional behavior of newfs(8) */
|
||||
int64_t fssize; /* file system size */
|
||||
uint sectorsize; /* bytes/sector */
|
||||
uint16_t inodesize = EXT2_REV0_DINODE_SIZE; /* inode size */
|
||||
uint fsize = 0; /* fragment size */
|
||||
uint bsize = 0; /* block size */
|
||||
uint minfree = MINFREE; /* free space threshold */
|
||||
uint density; /* number of bytes per inode */
|
||||
uint num_inodes; /* number of inodes (overrides density) */
|
||||
char *volname = NULL; /* volume name */
|
||||
|
||||
#ifndef __minix
|
||||
static char *disktype = NULL;
|
||||
#endif
|
||||
static char device[MAXPATHLEN];
|
||||
|
||||
static const char lmsg[] = "%s: can't read disk label";
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
#ifndef __minix
|
||||
struct disk_geom geo;
|
||||
struct dkwedge_info dkw;
|
||||
struct statvfs *mp;
|
||||
char *s2;
|
||||
int len, n;
|
||||
#else
|
||||
u64_t minix_fssize;
|
||||
#endif
|
||||
struct stat sb;
|
||||
int ch, fsi, fso, Fflag, Iflag, Zflag;
|
||||
char *cp, *s1, *special;
|
||||
const char *opstring;
|
||||
int byte_sized;
|
||||
uint blocks; /* number of blocks */
|
||||
|
||||
cp = NULL;
|
||||
fso = -1;
|
||||
Fflag = Iflag = Zflag = 0;
|
||||
verbosity = -1;
|
||||
opstring = "D:FINO:S:V:Zb:f:i:l:m:n:s:v:B:";
|
||||
byte_sized = 0;
|
||||
while ((ch = getopt(argc, argv, opstring)) != -1)
|
||||
switch (ch) {
|
||||
case 'D':
|
||||
inodesize = (uint16_t)strtol(optarg, &s1, 0);
|
||||
if (*s1 || (inodesize != 128 && inodesize != 256))
|
||||
errx(1, "Bad inode size %d "
|
||||
"(only 128 and 256 supported)", inodesize);
|
||||
break;
|
||||
case 'F':
|
||||
Fflag = 1;
|
||||
break;
|
||||
#ifndef __minix
|
||||
case 'I':
|
||||
Iflag = 1;
|
||||
break;
|
||||
#endif
|
||||
case 'N':
|
||||
Nflag = 1;
|
||||
if (verbosity == -1)
|
||||
verbosity = DEFAULT_VERBOSITY;
|
||||
break;
|
||||
case 'O':
|
||||
Oflag = strsuftoi64("format", optarg, 0, 1, NULL);
|
||||
break;
|
||||
case 'S':
|
||||
/*
|
||||
* XXX:
|
||||
* non-512 byte sectors almost certainly don't work.
|
||||
*/
|
||||
sectorsize = strsuftoi64("sector size",
|
||||
optarg, 512, 65536, NULL);
|
||||
if (!powerof2(sectorsize))
|
||||
errx(EXIT_FAILURE,
|
||||
"sector size `%s' is not a power of 2.",
|
||||
optarg);
|
||||
break;
|
||||
case 'V':
|
||||
verbosity = strsuftoi64("verbose", optarg, 0, 4, NULL);
|
||||
break;
|
||||
#ifndef __minix
|
||||
case 'Z':
|
||||
Zflag = 1;
|
||||
break;
|
||||
#endif
|
||||
case 'B':
|
||||
case 'b':
|
||||
bsize = strsuftoi64("block size",
|
||||
optarg, MINBSIZE, EXT2_MAXBSIZE, NULL);
|
||||
break;
|
||||
case 'f':
|
||||
fsize = strsuftoi64("fragment size",
|
||||
optarg, MINBSIZE, EXT2_MAXBSIZE, NULL);
|
||||
break;
|
||||
case 'i':
|
||||
density = strsuftoi64("bytes per inode",
|
||||
optarg, 1, INT_MAX, NULL);
|
||||
break;
|
||||
case 'm':
|
||||
minfree = strsuftoi64("free space %",
|
||||
optarg, 0, 99, NULL);
|
||||
break;
|
||||
case 'n':
|
||||
num_inodes = strsuftoi64("number of inodes",
|
||||
optarg, 1, INT_MAX, NULL);
|
||||
break;
|
||||
case 's':
|
||||
fssize = strsuftoi64("file system size",
|
||||
optarg, INT64_MIN, INT64_MAX, &byte_sized);
|
||||
break;
|
||||
case 'v':
|
||||
volname = optarg;
|
||||
if (volname[0] == '\0')
|
||||
errx(EXIT_FAILURE,
|
||||
"Volume name cannot be zero length");
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (verbosity == -1)
|
||||
/* Default to showing cg info */
|
||||
verbosity = DEFAULT_VERBOSITY;
|
||||
|
||||
if (argc != 1)
|
||||
usage();
|
||||
|
||||
memset(&sb, 0, sizeof(sb));
|
||||
#ifndef __minix
|
||||
memset(&dkw, 0, sizeof(dkw));
|
||||
#endif
|
||||
special = argv[0];
|
||||
if (Fflag) {
|
||||
int fl;
|
||||
/*
|
||||
* It's a file system image
|
||||
* no label, use fixed default for sectorsize.
|
||||
*/
|
||||
if (sectorsize == 0)
|
||||
sectorsize = DFL_SECSIZE;
|
||||
|
||||
/* creating image in a regular file */
|
||||
if (Nflag)
|
||||
fl = O_RDONLY;
|
||||
else {
|
||||
if (fssize > 0)
|
||||
fl = O_RDWR | O_CREAT;
|
||||
else
|
||||
fl = O_RDWR;
|
||||
}
|
||||
fsi = open(special, fl, 0777);
|
||||
if (fsi == -1)
|
||||
err(EXIT_FAILURE, "can't open file %s", special);
|
||||
if (fstat(fsi, &sb) == -1)
|
||||
err(EXIT_FAILURE, "can't fstat opened %s", special);
|
||||
if (!Nflag)
|
||||
fso = fsi;
|
||||
} else { /* !Fflag */
|
||||
fsi = opendisk(special, O_RDONLY, device, sizeof(device), 0);
|
||||
special = device;
|
||||
if (fsi < 0 || fstat(fsi, &sb) == -1)
|
||||
err(EXIT_FAILURE, "%s: open for read", special);
|
||||
|
||||
#ifndef __minix
|
||||
if (!Nflag) {
|
||||
fso = open(special, O_WRONLY, 0);
|
||||
if (fso < 0)
|
||||
err(EXIT_FAILURE,
|
||||
"%s: open for write", special);
|
||||
|
||||
/* Bail if target special is mounted */
|
||||
n = getmntinfo(&mp, MNT_NOWAIT);
|
||||
if (n == 0)
|
||||
err(EXIT_FAILURE, "%s: getmntinfo", special);
|
||||
|
||||
len = sizeof(_PATH_DEV) - 1;
|
||||
s1 = special;
|
||||
if (strncmp(_PATH_DEV, s1, len) == 0)
|
||||
s1 += len;
|
||||
|
||||
while (--n >= 0) {
|
||||
s2 = mp->f_mntfromname;
|
||||
if (strncmp(_PATH_DEV, s2, len) == 0) {
|
||||
s2 += len - 1;
|
||||
*s2 = 'r';
|
||||
}
|
||||
if (strcmp(s1, s2) == 0 ||
|
||||
strcmp(s1, &s2[1]) == 0)
|
||||
errx(EXIT_FAILURE,
|
||||
"%s is mounted on %s",
|
||||
special, mp->f_mntonname);
|
||||
++mp;
|
||||
}
|
||||
}
|
||||
|
||||
if (getdiskinfo(special, fsi, disktype, &geo, &dkw) == -1)
|
||||
errx(EXIT_FAILURE, lmsg, special);
|
||||
|
||||
if (sectorsize == 0) {
|
||||
sectorsize = geo.dg_secsize;
|
||||
if (sectorsize <= 0)
|
||||
errx(EXIT_FAILURE, "no default sector size");
|
||||
}
|
||||
|
||||
if (dkw.dkw_parent[0]) {
|
||||
if (dkw.dkw_size == 0)
|
||||
errx(EXIT_FAILURE,
|
||||
"%s partition is unavailable", special);
|
||||
|
||||
if (!Iflag) {
|
||||
static const char m[] =
|
||||
"%s partition type is not `%s' (or use -I)";
|
||||
if (strcmp(dkw.dkw_ptype, DKW_PTYPE_EXT2FS))
|
||||
errx(EXIT_FAILURE, m,
|
||||
special, "Linux Ext2");
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
fso = open(special, O_WRONLY, 0);
|
||||
if (fso < 0)
|
||||
err(EXIT_FAILURE,
|
||||
"%s: open for write", special);
|
||||
|
||||
if(minix_sizeup(special, &minix_fssize) < 0)
|
||||
errx(EXIT_FAILURE, "minix_sizeup failed");
|
||||
|
||||
fssize = minix_fssize;
|
||||
byte_sized = 1;
|
||||
|
||||
if (sectorsize == 0)
|
||||
sectorsize = 512;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (byte_sized)
|
||||
fssize /= sectorsize;
|
||||
#ifndef __minix
|
||||
if (fssize <= 0) {
|
||||
if (sb.st_size != 0)
|
||||
fssize += sb.st_size / sectorsize;
|
||||
else
|
||||
fssize += dkw.dkw_size;
|
||||
if (fssize <= 0)
|
||||
errx(EXIT_FAILURE,
|
||||
"Unable to determine file system size");
|
||||
}
|
||||
|
||||
if (dkw.dkw_parent[0] && fssize > dkw.dkw_size)
|
||||
errx(EXIT_FAILURE,
|
||||
"size %" PRIu64 " exceeds maximum file system size on "
|
||||
"`%s' of %" PRIu64 " sectors",
|
||||
fssize, special, dkw.dkw_size);
|
||||
#endif
|
||||
|
||||
printf("fssize = %lld %d-byte sectors\n", fssize, sectorsize);
|
||||
|
||||
/* XXXLUKEM: only ftruncate() regular files ? (dsl: or at all?) */
|
||||
if (Fflag && fso != -1
|
||||
&& ftruncate(fso, (off_t)fssize * sectorsize) == -1)
|
||||
err(1, "can't ftruncate %s to %" PRId64, special, fssize);
|
||||
|
||||
#ifndef __minix
|
||||
if (Zflag && fso != -1) { /* pre-zero (and de-sparce) the file */
|
||||
char *buf;
|
||||
int bufsize, i;
|
||||
off_t bufrem;
|
||||
|
||||
struct statvfs sfs;
|
||||
if (fstatvfs(fso, &sfs) == -1) {
|
||||
warn("can't fstatvfs `%s'", special);
|
||||
bufsize = 8192;
|
||||
} else
|
||||
bufsize = sfs.f_iosize;
|
||||
|
||||
if ((buf = calloc(1, bufsize)) == NULL)
|
||||
err(1, "can't malloc buffer of %d",
|
||||
bufsize);
|
||||
bufrem = fssize * sectorsize;
|
||||
if (verbosity > 0)
|
||||
printf("Creating file system image in `%s', "
|
||||
"size %" PRId64 " bytes, in %d byte chunks.\n",
|
||||
special, (signed long long) bufrem, bufsize);
|
||||
while (bufrem > 0) {
|
||||
i = write(fso, buf, MIN(bufsize, bufrem));
|
||||
if (i == -1)
|
||||
err(1, "writing image");
|
||||
bufrem -= i;
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Sort out fragment and block sizes */
|
||||
if (bsize == 0) {
|
||||
bsize = fsize;
|
||||
if (bsize == 0) {
|
||||
if (fssize < SMALL_FSSIZE)
|
||||
bsize = S_DFL_BSIZE;
|
||||
else if (fssize < MEDIUM_FSSIZE)
|
||||
bsize = M_DFL_BSIZE;
|
||||
else
|
||||
bsize = L_DFL_BSIZE;
|
||||
}
|
||||
}
|
||||
|
||||
if (fsize == 0)
|
||||
fsize = bsize;
|
||||
|
||||
blocks = fssize * sectorsize / bsize;
|
||||
|
||||
fssize = (u64_t) blocks * bsize / sectorsize;
|
||||
|
||||
if (num_inodes == 0) {
|
||||
if (density != 0)
|
||||
num_inodes = fssize / density;
|
||||
else {
|
||||
if (fssize < SMALL_FSSIZE)
|
||||
num_inodes = S_DFL_NINODE(blocks);
|
||||
else if (fssize < MEDIUM_FSSIZE)
|
||||
num_inodes = M_DFL_NINODE(blocks);
|
||||
else
|
||||
num_inodes = L_DFL_NINODE(blocks);
|
||||
}
|
||||
}
|
||||
mke2fs(special, fsi, fso);
|
||||
|
||||
if (fsi != -1)
|
||||
close(fsi);
|
||||
if (fso != -1 && fso != fsi)
|
||||
close(fso);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static int64_t
|
||||
strsuftoi64(const char *desc, const char *arg, int64_t min, int64_t max,
|
||||
int *num_suffix)
|
||||
{
|
||||
int64_t result, r1;
|
||||
int shift = 0;
|
||||
char *ep;
|
||||
|
||||
errno = 0;
|
||||
r1 = strtoll(arg, &ep, 10);
|
||||
if (ep[0] != '\0' && ep[1] != '\0')
|
||||
errx(EXIT_FAILURE,
|
||||
"%s `%s' is not a valid number.", desc, arg);
|
||||
switch (ep[0]) {
|
||||
case '\0':
|
||||
case 's':
|
||||
case 'S':
|
||||
if (num_suffix != NULL)
|
||||
*num_suffix = 0;
|
||||
break;
|
||||
case 'g':
|
||||
case 'G':
|
||||
shift += 10;
|
||||
/* FALLTHROUGH */
|
||||
case 'm':
|
||||
case 'M':
|
||||
shift += 10;
|
||||
/* FALLTHROUGH */
|
||||
case 'k':
|
||||
case 'K':
|
||||
shift += 10;
|
||||
/* FALLTHROUGH */
|
||||
case 'b':
|
||||
case 'B':
|
||||
if (num_suffix != NULL)
|
||||
*num_suffix = 1;
|
||||
break;
|
||||
default:
|
||||
errx(EXIT_FAILURE,
|
||||
"`%s' is not a valid suffix for %s.", ep, desc);
|
||||
}
|
||||
result = r1 << shift;
|
||||
if (errno == ERANGE || result >> shift != r1)
|
||||
errx(EXIT_FAILURE,
|
||||
"%s `%s' is too large to convert.", desc, arg);
|
||||
if (result < min)
|
||||
errx(EXIT_FAILURE,
|
||||
"%s `%s' (%" PRId64 ") is less than the minimum (%"
|
||||
PRId64 ").", desc, arg, result, min);
|
||||
if (result > max)
|
||||
errx(EXIT_FAILURE,
|
||||
"%s `%s' (%" PRId64 ") is greater than the maximum (%"
|
||||
PRId64 ").", desc, arg, result, max);
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char help_strings[] =
|
||||
"\t-b bsize\tblock size\n"
|
||||
"\t-D inodesize\tsize of an inode in bytes (128 or 256)\n"
|
||||
"\t-F \t\tcreate file system image in regular file\n"
|
||||
"\t-f fsize\tfragment size\n"
|
||||
"\t-I \t\tdo not check that the file system type is `Linux Ext2'\n"
|
||||
"\t-i density\tnumber of bytes per inode\n"
|
||||
"\t-m minfree\tminimum free space %\n"
|
||||
"\t-N \t\tdo not create file system, just print out parameters\n"
|
||||
"\t-n inodes\tnumber of inodes (overrides -i density)\n"
|
||||
"\t-O N\t\tfilesystem revision: 0 ==> REV0, 1 ==> REV1 (default 0)\n"
|
||||
"\t-S secsize\tsector size\n"
|
||||
"\t-s fssize\tfile system size (sectors)\n"
|
||||
"\t-V verbose\toutput verbosity: 0 ==> none, 4 ==> max\n"
|
||||
"\t-v volname\text2fs volume name\n"
|
||||
"\t-Z \t\tpre-zero the image file\n";
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
fprintf(stderr,
|
||||
"usage: %s [ fsoptions ] special-device\n", getprogname());
|
||||
fprintf(stderr, "where fsoptions are:\n");
|
||||
fprintf(stderr, "%s", help_strings);
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
Loading…
Reference in a new issue