/*
* linux/fs/file_dev.c
*
* (C) 1991 Linus Torvalds
*/

#include <errno.h>		// ͷļϵͳиֳš(Linus minix )
#include <fcntl.h>		// ļͷļļĲƳŵĶ塣

#include <linux/sched.h>	// ȳͷļṹtask_structʼ0 ݣ
// һЩйúͻȡǶʽຯ䡣
#include <linux/kernel.h>	// ںͷļһЩں˳úԭζ塣
#include <asm/segment.h>	// βͷļйضμĴǶʽຯ

#define MIN(a,b) (((a)<(b))?(a):(b))	// ȡa,b еСֵ
#define MAX(a,b) (((a)>(b))?(a):(b))	// ȡa,b еֵ

//// ļ - i ڵļṹ豸ݡ
// i ڵ֪豸ţfilp ṹ֪ļеǰдָλábuf ָû̬
// λãcount ΪҪȡֵֽʵʶȡֽ(С0)
int
file_read (struct m_inode *inode, struct file *filp, char *buf, int count)
{
  int left, chars, nr;
  struct buffer_head *bh;

// ҪȡֽڼֵСڵ㣬򷵻ء
  if ((left = count) <= 0)
    return 0;
// Ҫȡֽ0ѭִ²ֱȫ
  while (left)
    {
// i ڵļṹϢȡݿļǰдλ豸϶Ӧ߼nrnr 
// Ϊ0i ڵָ豸϶ȡ߼飬ʧ˳ѭnr Ϊ0ʾָ
// ݿ鲻ڣûָΪNULL
      if (nr = bmap (inode, (filp->f_pos) / BLOCK_SIZE))
	{
	  if (!(bh = bread (inode->i_dev, nr)))
	    break;
	}
      else
	bh = NULL;
// ļдָݿеƫֵnrÿпɶֽΪ(BLOCK_SIZE-nr)Ȼ뻹
// ȡֽleft ȽϣСֵΪֽchars(BLOCK_SIZE-nr)˵
// ÿҪȡһݣ֮Ҫȡһݡ
      nr = filp->f_pos % BLOCK_SIZE;
      chars = MIN (BLOCK_SIZE - nr, left);
// дļָ롣ָǰƴ˴νȡֽcharsʣֽڼӦȥchars
      filp->f_pos += chars;
      left -= chars;
// 豸϶ݣp ָݿ黺пʼȡλãҸchars ֽ
// ûbuf Сûchars 0 ֵֽڡ
      if (bh)
	{
	  char *p = nr + bh->b_data;
	  while (chars-- > 0)
	    put_fs_byte (*(p++), buf++);
	  brelse (bh);
	}
      else
	{
	  while (chars-- > 0)
	    put_fs_byte (0, buf++);
	}
    }
// ޸ĸi ڵķʱΪǰʱ䡣ضȡֽȡֽΪ0򷵻سš
  inode->i_atime = CURRENT_TIME;
  return (count - left) ? (count - left) : -ERROR;
}

//// ļд - i ڵļṹϢûдָ豸
// i ڵ֪豸ţfilp ṹ֪ļеǰдָλábuf ָû̬
// λãcount ΪҪдֵֽʵдֽ(С0)
int
file_write (struct m_inode *inode, struct file *filp, char *buf, int count)
{
  off_t pos;
  int block, c;
  struct buffer_head *bh;
  char *p;
  int i = 0;

/*
* ok, append may not work when many processes are writing at the same time
* but so what. That way leads to madness anyway.
*/
/*
* okͬʱдʱappend ܲУ
* »һš
*/
// ҪļݣļдָƵļβͽļдָ봦д롣
  if (filp->f_flags & O_APPEND)
    pos = inode->i_size;
  else
    pos = filp->f_pos;
// дֽi СҪдֽcountѭִ²
  while (i < count)
    {
// ݿ(pos/BLOCK_SIZE)豸϶Ӧ߼飬豸ϵ߼š߼
// =0ʾʧܣ˳ѭ
      if (!(block = create_block (inode, pos / BLOCK_SIZE)))
	break;
// ݸ߼Ŷȡ豸ϵӦݿ飬˳ѭ
      if (!(bh = bread (inode->i_dev, block)))
	break;
// ļдָݿеƫֵcp ָݿ黺пʼȡλáø
// ޸ı־
      c = pos % BLOCK_SIZE;
      p = c + bh->b_data;
      bh->b_dirt = 1;
// ӿʼдλõĩдc=(BLOCK_SIZE-c)ֽڡc ʣ໹дֽ
// (count-i)˴ֻдc=(count-i)ɡ
      c = BLOCK_SIZE - c;
      if (c > count - i)
	c = count - i;
// ļдָǰƴ˴дֽǰļдָλֵļĴС
// ޸i ڵļСֶΣi ڵ޸ı־
      pos += c;
      if (pos > inode->i_size)
	{
	  inode->i_size = pos;
	  inode->i_dirt = 1;
	}
// дֽڼۼӴ˴дֽcûbuf иc ֽڵٻp
// ָʼλôȻͷŸû
      i += c;
      while (c-- > 0)
	*(p++) = get_fs_byte (buf++);
      brelse (bh);
    }
// ļ޸ʱΪǰʱ䡣
  inode->i_mtime = CURRENT_TIME;
// ˴βļβݣļдָǰдλãi ڵ޸
// ʱΪǰʱ䡣
  if (!(filp->f_flags & O_APPEND))
    {
      filp->f_pos = pos;
      inode->i_ctime = CURRENT_TIME;
    }
// дֽдֽΪ0򷵻س-1
  return (i ? i : -1);
}
