| 
                         函数 generic_file_direct_IO() 代码如下所示: 
- static ssize_t  
 - generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,  
 -  loff_t offset, unsigned long nr_segs)  
 - {  
 -  struct file *file = iocb->ki_filp;  
 -  struct address_space *mapping = file->f_mapping;  
 -  ssize_t retval;  
 -  size_t write_len = 0;  
 -   
 -  if (rw == WRITE) {  
 -  write_len = iov_length(iov, nr_segs);  
 -  if (mapping_mapped(mapping))  
 -  unmap_mapping_range(mapping, offset, write_len, 0);  
 -  }  
 -   
 -  retval = filemap_write_and_wait(mapping);  
 -  if (retval == 0) {  
 -  retval = mapping->a_ops->direct_IO(rw, iocb, iov,  
 -  offset, nr_segs);  
 -  if (rw == WRITE && mapping->nrpages) {  
 -  pgoff_t end = (offset + write_len - 1)  
 -  >> PAGE_CACHE_SHIFT;  
 -  int err = invalidate_inode_pages2_range(mapping,  
 -  offset >> PAGE_CACHE_SHIFT, end);  
 -  if (err)  
 -  retval = err;  
 -  }  
 -  }  
 -  return retval;  
 - } 
 
  
函数 generic_file_direct_IO() 对 WRITE 操作类型进行了一些特殊处理。除此之外,它主要是调用了 direct_IO 方法去执行直接 I/O 的读或者写操作。在进行直接 I/O 读操作之前,先将页缓存中的相关脏数据刷回到磁盘上去,这样做可以确保从磁盘上读到的是最新的数据。这里的 direct_IO 方法最终会对应到 __blockdev_direct_IO() 函数上去。__blockdev_direct_IO() 函数的代码如下所示: 
- ssize_t  
 - __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,  
 -  struct block_device *bdev, const struct iovec *iov, loff_t offset,  
 -  unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io,  
 -  int dio_lock_type)  
 - {  
 -  int seg;  
 -  size_t size;  
 -  unsigned long addr;  
 -  unsigned blkbits = inode->i_blkbits;  
 -  unsigned bdev_blkbits = 0;  
 -  unsigned blocksize_mask = (1 << blkbits) - 1;  
 -  ssize_t retval = -EINVAL;  
 -  loff_t end = offset;  
 -  struct dio *dio;  
 -  int release_i_mutex = 0;  
 -  int acquire_i_mutex = 0;  
 -   
 -  if (rw & WRITE)  
 -  rw = WRITE_SYNC;  
 -   
 -  if (bdev)  
 -  bdev_blkbits = blksize_bits(bdev_hardsect_size(bdev));  
 -   
 -  if (offset & blocksize_mask) {  
 -  if (bdev)  
 -  blkbits = bdev_blkbits;  
 -  blocksize_mask = (1 << blkbits) - 1;  
 -  if (offset & blocksize_mask)  
 -  goto out;  
 -  }  
 -   
 -  for (seg = 0; seg < nr_segs; seg++) {  
 -  addr = (unsigned long)iov[seg].iov_base;  
 -  size = iov[seg].iov_len;  
 -  end += size;  
 -  if ((addr & blocksize_mask) || (size & blocksize_mask)) {  
 -  if (bdev)  
 -  blkbits = bdev_blkbits;  
 -  blocksize_mask = (1 << blkbits) - 1;  
 -  if ((addr & blocksize_mask) || (size & blocksize_mask))  
 -  goto out;  
 -  }  
 -  }  
 -   
 -  dio = kmalloc(sizeof(*dio), GFP_KERNEL);  
 -  retval = -ENOMEM;  
 -  if (!dio)  
 -  goto out;  
 -  dio->lock_type = dio_lock_type;  
 -  if (dio_lock_type != DIO_NO_LOCKING) {  
 -  if (rw == READ && end > offset) {  
 -  struct address_space *mapping;  
 -   
 -  mapping = iocb->ki_filp->f_mapping;  
 -  if (dio_lock_type != DIO_OWN_LOCKING) {  
 -  mutex_lock(&inode->i_mutex);  
 -  release_i_mutex = 1;  
 -  }  
 -   
 -  retval = filemap_write_and_wait_range(mapping, offset,  
 -  end - 1);  
 -  if (retval) {  
 -  kfree(dio);  
 -  goto out;  
 -  }  
 -   
 -  if (dio_lock_type == DIO_OWN_LOCKING) {  
 -  mutex_unlock(&inode->i_mutex);  
 -  acquire_i_mutex = 1;  
 -  }  
 -  }  
 -   
 -  if (dio_lock_type == DIO_LOCKING)  
 -  down_read_non_owner(&inode->i_alloc_sem);  
 -  }  
 -   
 -  dio->is_async = !is_sync_kiocb(iocb) && !((rw & WRITE) &&  
 -  (end > i_size_read(inode)));  
 -   
 -  retval = direct_io_worker(rw, iocb, inode, iov, offset,  
 -  nr_segs, blkbits, get_block, end_io, dio);  
 -   
 -  if (rw == READ && dio_lock_type == DIO_LOCKING)  
 -  release_i_mutex = 0;  
 -   
 - out:  
 -  if (release_i_mutex)  
 -  mutex_unlock(&inode->i_mutex);  
 -  else if (acquire_i_mutex)  
 -  mutex_lock(&inode->i_mutex);  
 -  return retval;  
 - } 
 
                          (编辑:泰州站长网) 
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! 
                     |