⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 module.h

📁 可以在不启动LINUX的情况下直接访问EXT2和EXT3格式的磁盘
💻 H
📖 第 1 页 / 共 3 页
字号:

/*
 * test_set_buffer_foo() and test_clear_buffer_foo()
 */
#define TAS_BUFFER_FNS(bit, name)					\
static inline int test_set_buffer_##name(struct buffer_head *bh)	\
{									\
	return test_and_set_bit(BH_##bit, &(bh)->b_state);		\
}									\
static inline int test_clear_buffer_##name(struct buffer_head *bh)	\
{									\
	return test_and_clear_bit(BH_##bit, &(bh)->b_state);		\
}									\

/*
 * Emit the buffer bitops functions.   Note that there are also functions
 * of the form "mark_buffer_foo()".  These are higher-level functions which
 * do something in addition to setting a b_state bit.
 */
BUFFER_FNS(Uptodate, uptodate)
BUFFER_FNS(Dirty, dirty)
TAS_BUFFER_FNS(Dirty, dirty)
BUFFER_FNS(Lock, locked)
TAS_BUFFER_FNS(Lock, locked)
BUFFER_FNS(Req, req)
TAS_BUFFER_FNS(Req, req)
BUFFER_FNS(Mapped, mapped)
BUFFER_FNS(New, new)
BUFFER_FNS(Async_Read, async_read)
BUFFER_FNS(Async_Write, async_write)
BUFFER_FNS(Delay, delay)
BUFFER_FNS(Boundary, boundary)
BUFFER_FNS(Write_EIO, write_io_error)
BUFFER_FNS(Ordered, ordered)
BUFFER_FNS(Eopnotsupp, eopnotsupp)
BUFFER_FNS(Unwritten, unwritten)

#define bh_offset(bh)		((unsigned long)(bh)->b_data & ~PAGE_MASK)
#define touch_buffer(bh)	mark_page_accessed(bh->b_page)

/* If we *know* page->private refers to buffer_heads */

#define page_buffers(page)					\
	(                                       \
		BUG_ON(!PagePrivate(page)),			\
		((struct buffer_head *)page_private(page))	\
	)
#define page_has_buffers(page)	PagePrivate(page)


/*
 * Declarations
 */

void mark_buffer_dirty(struct buffer_head *bh);
void init_buffer(struct buffer_head *, bh_end_io_t *, void *);
void set_bh_page(struct buffer_head *bh,
		struct page *page, unsigned long offset);
int try_to_free_buffers(struct page *);
struct buffer_head *alloc_page_buffers(struct page *page, unsigned long size,
		int retry);
void create_empty_buffers(struct page *, unsigned long,
			unsigned long b_state);
void end_buffer_read_sync(struct buffer_head *bh, int uptodate);
void end_buffer_write_sync(struct buffer_head *bh, int uptodate);

/* Things to do with buffers at mapping->private_list */
void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode);
int inode_has_buffers(struct inode *);
void invalidate_inode_buffers(struct inode *);
int remove_inode_buffers(struct inode *inode);
int sync_mapping_buffers(struct address_space *mapping);
void unmap_underlying_metadata(struct block_device *bdev, sector_t block);

void mark_buffer_async_write(struct buffer_head *bh);
void invalidate_bdev(struct block_device *);
int sync_blockdev(struct block_device *bdev);
void __wait_on_buffer(struct buffer_head *);
wait_queue_head_t *bh_waitq_head(struct buffer_head *bh);
int fsync_bdev(struct block_device *);
struct super_block *freeze_bdev(struct block_device *);
void thaw_bdev(struct block_device *, struct super_block *);
int fsync_super(struct super_block *);
int fsync_no_super(struct block_device *);
struct buffer_head *__find_get_block(struct block_device *bdev, sector_t block,
			unsigned long size);
struct buffer_head *__getblk(struct block_device *bdev, sector_t block,
			unsigned long size);
void __brelse(struct buffer_head *);
void __bforget(struct buffer_head *);
void __breadahead(struct block_device *, sector_t block, unsigned int size);
struct buffer_head *__bread(struct block_device *, sector_t block, unsigned size);
void invalidate_bh_lrus(void);
struct buffer_head *alloc_buffer_head(gfp_t gfp_flags);
void free_buffer_head(struct buffer_head * bh);
void unlock_buffer(struct buffer_head *bh);
void __lock_buffer(struct buffer_head *bh);
void ll_rw_block(int, int, struct buffer_head * bh[]);
int sync_dirty_buffer(struct buffer_head *bh);
int submit_bh(int, struct buffer_head *);
void write_boundary_block(struct block_device *bdev,
			sector_t bblock, unsigned blocksize);
int bh_uptodate_or_lock(struct buffer_head *bh);
int bh_submit_read(struct buffer_head *bh);

extern int buffer_heads_over_limit;

/*
 * Generic address_space_operations implementations for buffer_head-backed
 * address_spaces.
 */

#if 0

int block_write_full_page(struct page *page, get_block_t *get_block,
				struct writeback_control *wbc);
int block_read_full_page(struct page*, get_block_t*);
int block_write_begin(struct file *, struct address_space *,
				loff_t, unsigned, unsigned,
				struct page **, void **, get_block_t*);
int block_write_end(struct file *, struct address_space *,
				loff_t, unsigned, unsigned,
				struct page *, void *);
int generic_write_end(struct file *, struct address_space *,
				loff_t, unsigned, unsigned,
				struct page *, void *);

int block_prepare_write(struct page*, unsigned, unsigned, get_block_t*);
int cont_write_begin(struct file *, struct address_space *, loff_t,
			unsigned, unsigned, struct page **, void **,
			get_block_t *, loff_t *);
int block_page_mkwrite(struct vm_area_struct *vma, struct page *page,
				get_block_t get_block);
sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *);
int generic_commit_write(struct file *, struct page *, unsigned, unsigned);
int block_truncate_page(struct address_space *, loff_t, get_block_t *);
int file_fsync(struct file *, struct dentry *, int);
int nobh_write_begin(struct file *, struct address_space *,
				loff_t, unsigned, unsigned,
				struct page **, void **, get_block_t*);
int nobh_write_end(struct file *, struct address_space *,
				loff_t, unsigned, unsigned,
				struct page *, void *);
int nobh_truncate_page(struct address_space *, loff_t, get_block_t *);
int nobh_writepage(struct page *page, get_block_t *get_block,
                        struct writeback_control *wbc);
int generic_cont_expand_simple(struct inode *inode, loff_t size);
#endif

void block_invalidatepage(struct page *page, unsigned long offset);
void page_zero_new_buffers(struct page *page, unsigned from, unsigned to);
int  block_commit_write(struct page *page, unsigned from, unsigned to);
void block_sync_page(struct page *);

void buffer_init(void);

/*
 * inline definitions
 */
#if 0
static inline void attach_page_buffers(struct page *page,
		struct buffer_head *head)
{
	page_cache_get(page);
	SetPagePrivate(page);
	set_page_private(page, (unsigned long)head);
}
#endif

static inline void get_bh(struct buffer_head *bh)
{
    atomic_inc(&bh->b_count);
}

static inline void put_bh(struct buffer_head *bh)
{
    __brelse(bh);
}

static inline void brelse(struct buffer_head *bh)
{
	if (bh)
		__brelse(bh);
}

static inline void bforget(struct buffer_head *bh)
{
	if (bh)
		__bforget(bh);
}

#if 0
static inline struct buffer_head *
sb_bread(struct super_block *sb, sector_t block)
{
	return __bread(sb->s_bdev, block, sb->s_blocksize);
}

static inline void
sb_breadahead(struct super_block *sb, sector_t block)
{
	__breadahead(sb->s_bdev, block, sb->s_blocksize);
}

static inline struct buffer_head *
sb_getblk(struct super_block *sb, sector_t block)
{
	return __getblk(sb->s_bdev, block, sb->s_blocksize);
}

static inline struct buffer_head *
sb_find_get_block(struct super_block *sb, sector_t block)
{
	return __find_get_block(sb->s_bdev, block, sb->s_blocksize);
}

static inline void
map_bh(struct buffer_head *bh, struct super_block *sb, sector_t block)
{
	set_buffer_mapped(bh);
	bh->b_bdev = sb->s_bdev;
	bh->b_blocknr = block;
	bh->b_size = sb->s_blocksize;
}
#endif

/*
 * Calling wait_on_buffer() for a zero-ref buffer is illegal, so we call into
 * __wait_on_buffer() just to trip a debug check.  Because debug code in inline
 * functions is bloaty.
 */

static inline void wait_on_buffer(struct buffer_head *bh)
{
	might_sleep();
	if (buffer_locked(bh) || atomic_read(&bh->b_count) == 0)
		__wait_on_buffer(bh);
}

static inline void lock_buffer(struct buffer_head *bh)
{
	might_sleep();
	if (test_set_buffer_locked(bh))
		__lock_buffer(bh);
}

extern int __set_page_dirty_buffers(struct page *page);

//
// unicode character
//

struct nls_table {
        char *charset;
        char *alias;
        int (*uni2char) (wchar_t uni, unsigned char *out, int boundlen);
        int (*char2uni) (const unsigned char *rawstring, int boundlen,
                         wchar_t *uni);
        unsigned char *charset2lower;
        unsigned char *charset2upper;
        struct module *owner;
        struct nls_table *next;
};

/* this value hold the maximum octet of charset */
#define NLS_MAX_CHARSET_SIZE 6 /* for UTF-8 */

/* nls.c */
extern int register_nls(struct nls_table *);
extern int unregister_nls(struct nls_table *);
extern struct nls_table *load_nls(char *);
extern void unload_nls(struct nls_table *);
extern struct nls_table *load_nls_default(void);

extern int utf8_mbtowc(wchar_t *, const __u8 *, int);
extern int utf8_mbstowcs(wchar_t *, const __u8 *, int);
extern int utf8_wctomb(__u8 *, wchar_t, int);
extern int utf8_wcstombs(__u8 *, const wchar_t *, int);

//
//  kernel jiffies
//

#define HZ  (100)

static inline __u32 JIFFIES()
{
    LARGE_INTEGER Tick;

    KeQueryTickCount(&Tick);
    Tick.QuadPart *= KeQueryTimeIncrement();
    Tick.QuadPart /= (10000000 / HZ);

    return Tick.LowPart;
}

#define jiffies JIFFIES()

//
// memory routines
//

#ifdef _WIN2K_TARGET_

typedef GUID UUID;
NTKERNELAPI
NTSTATUS
ExUuidCreate(
    OUT UUID *Uuid
    );

NTKERNELAPI
PVOID
NTAPI
ExAllocatePoolWithTag(
    IN POOL_TYPE PoolType,
    IN SIZE_T NumberOfBytes,
    IN ULONG Tag
    );

#define  ExFreePoolWithTag(_P, _T) ExFreePool(_P)
#endif


void *kzalloc(int size, int flags);
#define kmalloc(size, gfp) ExAllocatePoolWithTag(NonPagedPool, size, 'JBDM')
#define kfree(p) ExFreePoolWithTag(p, 'JBDM')


/* memory slab */

#define	SLAB_HWCACHE_ALIGN	0x00002000U	/* align objs on a h/w cache lines */
#define SLAB_KERNEL         0x00000001U
#define SLAB_TEMPORARY      0x00000002U

typedef void (*kmem_cache_cb_t)(void*, kmem_cache_t *, unsigned long);

struct kmem_cache {
    CHAR                    name[32];
    ULONG                   flags;
    ULONG                   size;
    atomic_t                count;
    atomic_t                acount;
    NPAGED_LOOKASIDE_LIST   la;
    kmem_cache_cb_t         constructor;
};


kmem_cache_t *
kmem_cache_create(
    const char *name,
    size_t size,
    size_t offset,
    unsigned long flags,
    kmem_cache_cb_t ctor
    );

void* kmem_cache_alloc(kmem_cache_t *kc, int flags);
void  kmem_cache_free(kmem_cache_t *kc, void *p);
int   kmem_cache_destroy(kmem_cache_t *kc);


//
// block device
//

#define BDEVNAME_SIZE      32      /* Largest string for a blockdev identifier */

//
// ll_rw_block ....
//


#define RW_MASK         1
#define RWA_MASK        2
#define READ 0
#define WRITE 1
#define READA 2         /* read-ahead  - don't block if no resources */
#define SWRITE 3        /* for ll_rw_block() - wait for buffer lock */
#define READ_SYNC       (READ | (1 << BIO_RW_SYNC))
#define READ_META       (READ | (1 << BIO_RW_META))
#define WRITE_SYNC      (WRITE | (1 << BIO_RW_SYNC))
#define WRITE_BARRIER   ((1 << BIO_RW) | (1 << BIO_RW_BARRIER))


//
// file system specific structures
//

/*
 * Kernel pointers have redundant information, so we can use a
 * scheme where we can return either an error code or a dentry
 * pointer with the same return value.
 *
 * This should be a per-architecture thing, to allow different
 * error and pointer decisions.
 */


struct super_block {
	unsigned long		s_blocksize;        /* blocksize */
	unsigned char		s_blocksize_bits;   /* bits of blocksize */
	unsigned char		s_dirt;             /* any thing */
    char                s_id[30];           /* id string */
	kdev_t              s_bdev;             /* block_device */
    void *              s_priv;             /* EXT2_VCB */
};

struct inode {
	unsigned long   i_ino;      /* inode number */
	umode_t			i_mode;     /* mode */
	loff_t			i_size;     /* size */
    atomic_t        i_count;    /* ref count */
	struct super_block	*i_sb;  /* super_block */
    void *          i_priv;     /* EXT2_MCB */
};

unsigned long bmap(struct inode *, unsigned long);
void iput(struct inode *inode);
void iget(struct inode *inode);

//
// timer routines
//

/*
 *      These inlines deal with timer wrapping correctly. You are
 *      strongly encouraged to use them
 *      1. Because people otherwise forget
 *      2. Because if the timer wrap changes in future you won't have to
 *         alter your driver code.
 *
 * time_after(a,b) returns true if the time a is after time b.
 *
 * Do this with "<0" and ">=0" to only test the sign of the result. A
 * good compiler would generate better code (and a really good compiler
 * wouldn't care). Gcc is currently neither.
 */
#define typecheck(x, y) (TRUE)

#define time_after(a,b)         \
        (typecheck(unsigned long, a) && \
         typecheck(unsigned long, b) && \
         ((long)(b) - (long)(a) < 0))
#define time_before(a,b)        time_after(b,a)

#define time_after_eq(a,b)      \
        (typecheck(unsigned long, a) && \
         typecheck(unsigned long, b) && \
         ((long)(a) - (long)(b) >= 0))
#define time_before_eq(a,b)     time_after_eq(b,a)

#define time_in_range(a,b,c) \
        (time_after_eq(a,b) && \
         time_before_eq(a,c))

#endif // _EXT2_MODULE_HEADER_

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -