文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>linux 1.0 内核注解 linux/fs/ext2/file.c

linux 1.0 内核注解 linux/fs/ext2/file.c

时间:2009-05-24  来源:taozhijiangscu

/********************************************
 *Created By: Prometheus
 *Date        : 2009-5-24   
 ********************************************/
/*
 *  linux/fs/ext2/file.c
 *
 *  Copyright (C) 1992, 1993, 1994  Remy Card ([email protected])
 *                                  Laboratoire MASI - Institut Blaise Pascal
 *                                  Universite Pierre et Marie Curie (Paris VI)
 *
 *  from
 *
 *  linux/fs/minix/file.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *
 *  ext2 fs regular file handling primitives
 */
#include <asm/segment.h>
#include <asm/system.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/ext2_fs.h>
#include <linux/fcntl.h>
#include <linux/sched.h>
#include <linux/stat.h>
#include <linux/locks.h>
#define NBUF 32 #define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#include <linux/fs.h>
#include <linux/ext2_fs.h>
static int ext2_file_read (struct inode *, struct file *, char *, int);
static int ext2_file_write (struct inode *, struct file *, char *, int);
static void ext2_release_file (struct inode *, struct file *);
/*
 * We have mostly NULL's here: the current defaults are ok for
 * the ext2 filesystem.
 */
static struct file_operations ext2_file_operations = {
 NULL,   /* lseek - default */
 ext2_file_read,  /* read */
 ext2_file_write, /* write */
 NULL,   /* readdir - bad */
 NULL,   /* select - default */
 ext2_ioctl,  /* ioctl */
 generic_mmap,    /* mmap */
 NULL,   /* no special open is needed */
 ext2_release_file, /* release */
 ext2_sync_file  /* fsync */
};
struct inode_operations ext2_file_inode_operations = {
 &ext2_file_operations,/* default file operations */
 NULL,   /* create */
 NULL,   /* lookup */
 NULL,   /* link */
 NULL,   /* unlink */
 NULL,   /* symlink */
 NULL,   /* mkdir */
 NULL,   /* rmdir */
 NULL,   /* mknod */
 NULL,   /* rename */
 NULL,   /* readlink */
 NULL,   /* follow_link */
 ext2_bmap,  /* bmap */
 ext2_truncate,  /* truncate */
 ext2_permission  /* permission */
};
static int ext2_file_read (struct inode * inode, struct file * filp,
      char * buf, int count)
{
 int read, left, chars;
 int block, blocks, offset;
 int bhrequest, uptodate;
 struct buffer_head ** bhb, ** bhe;
 struct buffer_head * bhreq[NBUF];
 struct buffer_head * buflist[NBUF];
 struct super_block * sb;
 unsigned int size;
 int err;
 if (!inode) {
  printk ("ext2_file_read: inode = NULL\n");
  return -EINVAL;
 }
 sb = inode->i_sb;
 if (!S_ISREG(inode->i_mode)) {
  ext2_warning (sb, "ext2_file_read", "mode = %07o",
         inode->i_mode);
  return -EINVAL;
 }
 offset = filp->f_pos;
 size = inode->i_size;
 if (offset > size)
  left = 0;
 else
  left = size - offset;  //剩余可读数
 if (left > count)
  left = count;   //left就是最终要读取的数据
 if (left <= 0)
  return 0;
 read = 0;
 block = offset >> EXT2_BLOCK_SIZE_BITS(sb); //算出读取的起始块号以及在快内的偏移
 offset &= (sb->s_blocksize - 1);
 
 //下面的size和blocks是对于整个文件的索引操作担,都使用块计算的
 size = (size + sb->s_blocksize - 1) >> EXT2_BLOCK_SIZE_BITS(sb); //整个文件的块数
 blocks = (left + offset + sb->s_blocksize - 1) >> EXT2_BLOCK_SIZE_BITS(sb); //要读取的块数
 bhb = bhe = buflist;
 
 //进行预读
 if (filp->f_reada) {
 
// 37 /* This specifies how many sectors to read ahead on the disk.  */
// 39 int read_ahead[MAX_BLKDEV] = {0, };
  blocks += read_ahead[MAJOR(inode->i_dev)] >>
   (EXT2_BLOCK_SIZE_BITS(sb) - 9);  //可能都是使用512标示的,这里进行校正
  if (block + blocks > size)
   blocks = size - block;   //校正实际能读取的块数
 }
 /*
  * We do this in a two stage process.  We first try and request
  * as many blocks as we can, then we wait for the first one to
  * complete, and then we try and wrap up as many as are actually
  * done.  This routine is rather generic, in that it can be used
  * in a filesystem by substituting the appropriate function in
  * for getblk
  *
  * This routine is optimized to make maximum use of the various
  * buffers and caches.
  */
 do {
  bhrequest = 0;
  uptodate = 1;
  while (blocks) {
   --blocks;
   *bhb = ext2_getblk (inode, block++, 0, &err);
   if (*bhb && !(*bhb)->b_uptodate) {
    uptodate = 0;
    bhreq[bhrequest++] = *bhb;  //同时bhrequest记录了需要重新读取的块数
   }
   if (++bhb == &buflist[NBUF])   //回卷到头部
    bhb = buflist;
   /*
    * If the block we have on hand is uptodate, go ahead
    * and complete processing
    */
   if (uptodate)  //只要得到了更新块就跳出去处理,否则就记录要读取的块
    break;
   if (bhb == bhe)  //满了,要读取NBUF块
    break;
  }
  /*
   * Now request them all
   */
  if (bhrequest)  //调用底层的读取函数
   ll_rw_block (READ, bhrequest, bhreq);
  do {
   /*
    * Finish off all I/O that has actually completed
    */
   if (*bhe) {
    wait_on_buffer (*bhe);
    if (!(*bhe)->b_uptodate) { /* read error? */
       //这里当做错误处理的,left=0,跳出大循环了
            brelse(*bhe);
     if (++bhe == &buflist[NBUF]) 
       bhe = buflist; //不是跳出去就完了,这里的bhe将来还是有用的
     left = 0;
     break;
    }
   }
   //记录读取了的数目
   if (left < sb->s_blocksize - offset)
    chars = left;
   else
    chars = sb->s_blocksize - offset;
   filp->f_pos += chars;
   left -= chars;
   read += chars;
   if (*bhe) {
    memcpy_tofs (buf, offset + (*bhe)->b_data,
          chars);
    brelse (*bhe);
    buf += chars;
   } else { //*bhe是什么情况?
    while (chars-- > 0)
     put_fs_byte (0, buf++);
   }
   offset = 0;
   if (++bhe == &buflist[NBUF])
    bhe = buflist;
  } while (left > 0 && bhe != bhb && (!*bhe || !(*bhe)->b_lock));
 } while (left > 0);
 /*
  * Release the read-ahead blocks
  */
 while (bhe != bhb) { //预读的块释放掉
  brelse (*bhe);
  if (++bhe == &buflist[NBUF])
   bhe = buflist;
 }
 if (!read)
  return -EIO;
 filp->f_reada = 1; //标志已经预读了
 if (!IS_RDONLY(inode)) {
  inode->i_atime = CURRENT_TIME;
  inode->i_dirt = 1;
 }
 return read;
}
static int ext2_file_write (struct inode * inode, struct file * filp,
       char * buf, int count)
{
 off_t pos;
 int written, c;
 struct buffer_head * bh;
 char * p;
 struct super_block * sb;
 int err;
 if (!inode) {
  printk("ext2_file_write: inode = NULL\n");
  return -EINVAL;
 }
 sb = inode->i_sb;
 if (sb->s_flags & MS_RDONLY)
  /*
   * This fs has been automatically remounted ro because of errors
   */
  return -ENOSPC;
 if (!S_ISREG(inode->i_mode)) {
  ext2_warning (sb, "ext2_file_write", "mode = %07o\n",
         inode->i_mode);
  return -EINVAL;
 }
/*
 * ok, append may not work when many processes are writing at the same time
 * but so what. That way leads to madness anyway.
 */
 if (filp->f_flags & O_APPEND)  //是否追加,更新文件指针
  pos = inode->i_size;
 else
  pos = filp->f_pos;
 written = 0;
 while (written < count) {
  bh = ext2_getblk (inode, pos / sb->s_blocksize, 1, &err);
  if (!bh) {
   if (!written)
    written = err;
   break;
  }
  c = sb->s_blocksize - (pos % sb->s_blocksize); //c记录本次可以读取的字符个数
  if (c > count-written)
   c = count - written;
  if (c != sb->s_blocksize && !bh->b_uptodate) { //整块的写入时很好办的,只要整体为脏就可以了
        //但是对于不能整块写入的,必须写入的块原先是更新的
        //但是想想呢,好像不更新也行啊 :-( ??
   ll_rw_block (READ, 1, &bh);
   wait_on_buffer (bh);
   if (!bh->b_uptodate) {
    brelse (bh);
    if (!written)
     written = -EIO;
    break;
   }
  }
  p = (pos % sb->s_blocksize) + bh->b_data;
  pos += c;
  if (pos > inode->i_size) {
   inode->i_size = pos;
   inode->i_dirt = 1;
  }
  written += c;
  memcpy_fromfs (p, buf, c); //写入到缓冲块中
  buf += c;
  bh->b_uptodate = 1;
  bh->b_dirt = 1;
  brelse (bh);
 }
 inode->i_ctime = inode->i_mtime = CURRENT_TIME;
 filp->f_pos = pos;
 inode->i_dirt = 1;
 return written;
}
/*
 * Called when a inode is released. Note that this is different
 * from ext2_open: open gets called at every open, but release
 * gets called only when /all/ the files are closed.
 */
static void ext2_release_file (struct inode * inode, struct file * filp)
{
 if (filp->f_mode & 2)
  ext2_discard_prealloc (inode);
}
  文档:http://blogimg.chinaunix.net/blog/upfile2/090524221628.pdf
相关阅读 更多 +
排行榜 更多 +
Unity Connect

Unity Connect

学习教育 下载
青橙记录本

青橙记录本

商务办公 下载
脑洞惊魂夜

脑洞惊魂夜

休闲益智 下载