| 函数 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;  } 
 (编辑:南平站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |