📄 inode.c
字号:
/* * FILE NAME fs/pramfs/inode.c * * BRIEF DESCRIPTION * * Inode methods (allocate/free/read/write). * * Author: Steve Longerbeam <stevel@mvista.com, or source@mvista.com> * * Copyright 2003 Sony Corporation * Copyright 2003 Matsushita Electric Industrial Co., Ltd. * 2003-2004 (c) MontaVista Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */#include <linux/fs.h>#include <linux/pram_fs.h>#include <linux/smp_lock.h>#include <linux/sched.h>#include <linux/highuid.h>#include <linux/quotaops.h>#include <linux/module.h>#include <linux/buffer_head.h>#include <linux/mpage.h>#include <linux/backing-dev.h>static struct backing_dev_info pram_backing_dev_info = { .ra_pages = 0, /* No readahead */ /* Does not contribute to dirty memory */ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,};#if 0static void pram_dump_inode(struct inode * inode){ struct pram_inode * pi = pram_get_inode(inode->i_sb, inode->i_ino); printk("uid 0x%08x\n", pi->i_uid); printk("gid 0x%08x\n", pi->i_gid); printk("mode 0x%08x\n", pi->i_mode); printk("links_count 0x%08x\n", pi->i_links_count); printk("blocks 0x%08x\n", pi->i_blocks); printk("size 0x%08x\n", pi->i_size); printk("atime 0x%08x\n", pi->i_atime); printk("ctime 0x%08x\n", pi->i_ctime); printk("mtime 0x%08x\n", pi->i_mtime); printk("dtime 0x%08x\n", pi->i_dtime); printk("row_block 0x%08lx\n", pi->i_type.reg.row_block); printk("head 0x%08lx\n", pi->i_type.dir.head); printk("tail 0x%08lx\n", pi->i_type.dir.tail); printk("rdev 0x%08x\n", pi->i_type.dev.rdev); printk("d_next 0x%08lx\n", pi->i_d.d_next); printk("d_prev 0x%08lx\n", pi->i_d.d_prev); printk("d_parent 0x%08lx\n", pi->i_d.d_parent); printk("d_name %s\n", pi->i_d.d_name);}#endif/* * allocate a data block for inode and return it's absolute blocknr. * Zeroes out the block if zero set. Increments inode->i_blocks. */static intpram_new_data_block (struct inode * inode, int* blocknr, int zero){ int errval = pram_new_block(inode->i_sb, blocknr, zero); if (!errval) { struct pram_inode * pi = pram_get_inode(inode->i_sb, inode->i_ino); inode->i_blocks++; pram_lock_inode(inode->i_sb, pi); pi->i_blocks = inode->i_blocks; pram_unlock_inode(inode->i_sb, pi); } return errval;}/* * find the offset to the block represented by the given inode's file * relative block number. */pram_off_t pram_find_data_block(struct inode * inode, int file_blocknr){ struct super_block * sb = inode->i_sb; struct pram_inode * pi; pram_off_t * row; /* ptr to row block */ pram_off_t * col; /* ptr to column blocks */ pram_off_t bp = 0; int i_row, i_col; int N = sb->s_blocksize >> 2; // num block ptrs per block int Nbits = sb->s_blocksize_bits - 2; pi = pram_get_inode(sb, inode->i_ino); i_row = file_blocknr >> Nbits; i_col = file_blocknr & (N-1); row = pram_get_block(sb, pi->i_type.reg.row_block); if (row) { col = pram_get_block(sb, row[i_row]); if (col) bp = col[i_col]; } return bp;}/* * Free data blocks from inode starting at first_trunc_block. */static voidpram_truncate_blocks(struct inode * inode, int first_trunc_block){ struct super_block * sb = inode->i_sb; struct pram_inode * pi = pram_get_inode(sb, inode->i_ino); int N = sb->s_blocksize >> 2; // num block ptrs per block int Nbits = sb->s_blocksize_bits - 2; int first_row_index, last_row_index; int i, j, first_blocknr, last_blocknr, blocknr; pram_off_t * row; /* ptr to row block */ pram_off_t * col; /* ptr to column blocks */ if (first_trunc_block >= inode->i_blocks || !inode->i_blocks || !pi->i_type.reg.row_block) { return; } first_blocknr = first_trunc_block; last_blocknr = inode->i_blocks - 1; first_row_index = first_blocknr >> Nbits; last_row_index = last_blocknr >> Nbits; row = pram_get_block(sb, pi->i_type.reg.row_block); for (i=first_row_index; i <= last_row_index; i++) { int first_col_index = (i == first_row_index) ? first_blocknr & (N-1) : 0; int last_col_index = (i == last_row_index) ? last_blocknr & (N-1) : N-1; col = pram_get_block(sb, row[i]); for (j=first_col_index; j <= last_col_index; j++) { blocknr = pram_get_blocknr(sb, col[j]); pram_free_block(sb, blocknr); pram_lock_block(sb, col); col[j] = 0; pram_unlock_block(sb, col); } if (first_col_index == 0) { blocknr = pram_get_blocknr(sb, row[i]); pram_free_block(sb, blocknr); pram_lock_block(sb, row); row[i] = 0; pram_unlock_block(sb, row); } } inode->i_blocks -= (last_blocknr - first_blocknr + 1); if (first_blocknr == 0) { blocknr = pram_get_blocknr(sb, pi->i_type.reg.row_block); pram_free_block(sb, blocknr); pram_lock_inode(sb, pi); pi->i_type.reg.row_block = 0; pram_unlock_inode(sb, pi); } pram_lock_inode(sb, pi); pi->i_blocks = inode->i_blocks; pram_unlock_inode(sb, pi);}/* * Allocate num data blocks for inode, starting at given file-relative * block number. Any unallocated file blocks before file_blocknr * are allocated. All blocks except the last are zeroed out. */int pram_alloc_blocks(struct inode * inode, int file_blocknr, int num){ struct super_block * sb = inode->i_sb; struct pram_inode * pi = pram_get_inode(sb, inode->i_ino); int N = sb->s_blocksize >> 2; // num block ptrs per block int Nbits = sb->s_blocksize_bits - 2; int first_file_blocknr; int last_file_blocknr; int first_row_index, last_row_index; int i, j, blocknr, errval; pram_off_t * row; pram_off_t * col; if (!pi->i_type.reg.row_block) { /* alloc the 2nd order array block */ errval = pram_new_block(sb, &blocknr, 1); if (errval) { pram_err("failed to alloc 2nd order array block\n"); goto fail; } pram_lock_inode(sb, pi); pi->i_type.reg.row_block = pram_get_block_off(sb, blocknr); pram_unlock_inode(sb, pi); } row = pram_get_block(sb, pi->i_type.reg.row_block); first_file_blocknr = (file_blocknr > inode->i_blocks) ? inode->i_blocks : file_blocknr; last_file_blocknr = file_blocknr + num - 1; first_row_index = first_file_blocknr >> Nbits; last_row_index = last_file_blocknr >> Nbits; if (last_row_index >= N || first_row_index >= N) { errval = -ENOSPC; goto fail; } for (i=first_row_index; i<=last_row_index; i++) { int first_col_index, last_col_index; /* * we are starting a new row, so make sure * there is a block allocated for the row. */ if (!row[i]) { /* allocate the row block */ errval = pram_new_block(sb, &blocknr, 1); if (errval) { pram_err("failed to alloc row block\n"); goto fail; } pram_lock_block(sb, row); row[i] = pram_get_block_off(sb, blocknr); pram_unlock_block(sb, row); } col = pram_get_block(sb, row[i]); first_col_index = (i == first_row_index) ? first_file_blocknr & (N-1) : 0; last_col_index = (i == last_row_index) ? last_file_blocknr & (N-1) : N-1; for (j=first_col_index; j<=last_col_index; j++) { int last_block = (i==last_row_index) && (j==last_col_index); if (!col[j]) { errval = pram_new_data_block(inode, &blocknr, !last_block); if (errval) { pram_err("failed to alloc " "data block\n"); goto fail; } pram_lock_block(sb, col); col[j] = pram_get_block_off(sb, blocknr); pram_unlock_block(sb, col); } } } errval = 0; fail: return errval;}static intpram_fill_inode(struct inode * inode, struct pram_inode * pi){ int ret = -EIO; if (pram_calc_checksum((u32*)pi, PRAM_INODE_SIZE>>2)) { pram_err("checksum error in inode %08x\n", (u32)inode->i_ino); goto bad_inode; } inode->i_mode = pi->i_mode; inode->i_uid = pi->i_uid; inode->i_gid = pi->i_gid; inode->i_nlink = pi->i_links_count; inode->i_size = pi->i_size; inode->i_atime.tv_sec = pi->i_atime; inode->i_ctime.tv_sec = pi->i_ctime; inode->i_mtime.tv_sec = pi->i_mtime; inode->i_atime.tv_nsec = inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0; /* check if the inode is active. */ if (inode->i_nlink == 0 && (inode->i_mode == 0 || pi->i_dtime)) { /* this inode is deleted */ ret = -EINVAL; goto bad_inode; } inode->i_blocks = pi->i_blocks; inode->i_ino = pram_get_inodenr(inode->i_sb, pi); inode->i_mapping->a_ops = &pram_aops; inode->i_mapping->backing_dev_info = &pram_backing_dev_info; insert_inode_hash(inode); switch (inode->i_mode & S_IFMT) { case S_IFREG: inode->i_op = &pram_file_inode_operations; inode->i_fop = &pram_file_operations; break; case S_IFDIR: inode->i_op = &pram_dir_inode_operations; inode->i_fop = &pram_dir_operations; break; case S_IFLNK: inode->i_op = &pram_symlink_inode_operations; break; default: inode->i_size = 0; init_special_inode(inode, inode->i_mode, pi->i_type.dev.rdev); break; } return 0; bad_inode: make_bad_inode(inode); return ret;}static int pram_update_inode(struct inode * inode){ struct pram_inode * pi; int retval = 0; pi = pram_get_inode(inode->i_sb, inode->i_ino); if ((inode->i_sb->s_flags & MS_NOTIME) && pi->i_mode == inode->i_mode && pi->i_uid == inode->i_uid && pi->i_gid == inode->i_gid && pi->i_links_count == inode->i_nlink && pi->i_size == inode->i_size && pi->i_blocks == inode->i_blocks && ((!S_ISCHR(inode->i_mode) && !S_ISBLK(inode->i_mode)) || (pi->i_type.dev.rdev == inode->i_rdev))) return retval; pram_lock_inode(inode->i_sb, pi); pi->i_mode = inode->i_mode; pi->i_uid = inode->i_uid; pi->i_gid = inode->i_gid; pi->i_links_count = inode->i_nlink; pi->i_size = inode->i_size; pi->i_blocks = inode->i_blocks; pi->i_atime = inode->i_atime.tv_sec; pi->i_ctime = inode->i_ctime.tv_sec; pi->i_mtime = inode->i_mtime.tv_sec;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -