免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 928 | 回复: 0
打印 上一主题 下一主题

linux 1.0 内核注解 linux/fs/ext2/file.c [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-05-24 22:18 |只看该作者 |倒序浏览
/********************************************
*Created By: Prometheus
*Date        : 2009-5-24   
********************************************/
/*
*  linux/fs/ext2/file.c
*
*  Copyright (C) 1992, 1993, 1994  Remy Card (
card@masi.ibp.fr
)
*                                  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
#include
#include
#include
#include
#include
#include
#include
#include
#define NBUF 32
#define MIN(a,b) (((a)(b))?(a):(b))
#include
#include
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 > 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 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 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


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/90306/showart_1943482.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP