*参照元 [#x40dcf69]
#backlinks

*説明 [#n2fb029f]
-パス: [[linux-2.6.33/fs/direct-io.c]]

-FIXME: これは何?
--説明


**引数 [#qb274b75]
-
-int rw
--
-struct kiocb *iocb
--
--[[linux-2.6.33/kiocb]]
-struct inode *inode
--
--[[linux-2.6.33/inode]]
-struct block_device *bdev
--
--[[linux-2.6.33/block_device]]
-const struct iovec *iov
--
--[[linux-2.6.33/iovec]]
-loff_t offset
--
-unsigned long nr_segs
--
-get_block_t get_block
--
--[[linux-2.6.33/get_block_t]]
-dio_iodone_t end_io
--
--[[linux-2.6.33/dio_iodone_t]]
--int flags
--


**返り値 [#hfff5a72]
-
-ssize_t
--


**参考 [#b6fe5875]


*実装 [#n34ab5cd]
 /*
  * This is a library function for use by filesystem drivers.
  *
  * The locking rules are governed by the flags parameter:
  *  - if the flags value contains DIO_LOCKING we use a fancy locking
  *    scheme for dumb filesystems.
  *    For writes this function is called under i_mutex and returns with
  *    i_mutex held, for reads, i_mutex is not held on entry, but it is
  *    taken and dropped again before returning.
  *    For reads and writes i_alloc_sem is taken in shared mode and released
  *    on I/O completion (which may happen asynchronously after returning to
  *    the caller).
  *
  *  - if the flags value does NOT contain DIO_LOCKING we don't use any
  *    internal locking but rather rely on the filesystem to synchronize
  *    direct I/O reads/writes versus each other and truncate.
  *    For reads and writes both i_mutex and i_alloc_sem are not held on
  *    entry and are never taken.
  */
 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 flags)
 {
 	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;
 
-
--[[linux-2.6.33/dio]]

 	if (rw & WRITE)
 		rw = WRITE_ODIRECT_PLUG;
 
-
--[[linux-2.6.33/WRITE]]
--[[linux-2.6.33/WRITE_ODIRECT_PLUG]]

 	if (bdev)
 		bdev_blkbits = blksize_bits(bdev_logical_block_size(bdev));
 
-
--[[linux-2.6.33/blksize_bits()]]
--[[linux-2.6.33/bdev_logical_block_size()]]

 	if (offset & blocksize_mask) {
 		if (bdev)
 			 blkbits = bdev_blkbits;
 		blocksize_mask = (1 << blkbits) - 1;
 		if (offset & blocksize_mask)
 			goto out;
 	}
 
 	/* Check the memory alignment.  Blocks cannot straddle pages */
 	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;
-
--[[linux-2.6.33/kmalloc()]]

 	/*
 	 * Believe it or not, zeroing out the page array caused a .5%
 	 * performance regression in a database benchmark.  So, we take
 	 * care to only zero out what's needed.
 	 */
 	memset(dio, 0, offsetof(struct dio, pages));
 
-
--[[linux-2.6.33/memset()]]

 	dio->flags = flags;
 	if (dio->flags & DIO_LOCKING) {
-
--[[linux-2.6.33/DIO_LOCKING]]

 		/* watch out for a 0 len io from a tricksy fs */
 		if (rw == READ && end > offset) {
 			struct address_space *mapping =
 					iocb->ki_filp->f_mapping;
 
 			/* will be released by direct_io_worker */
 			mutex_lock(&inode->i_mutex);
 
-
--[[linux-2.6.33/mutex_lock()]]

 			retval = filemap_write_and_wait_range(mapping, offset,
 							      end - 1);
 			if (retval) {
 				mutex_unlock(&inode->i_mutex);
 				kfree(dio);
 				goto out;
 			}
-
--[[linux-2.6.33/filemap_write_and_wait_range()]]
--[[linux-2.6.33/mutex_unlock()]]
--[[linux-2.6.33/kfree()]]

 		}
 
 		/*
 		 * Will be released at I/O completion, possibly in a
 		 * different thread.
 		 */
 		down_read_non_owner(&inode->i_alloc_sem);
-
--[[linux-2.6.33/down_read_non_owner()]]

 	}
 
 	/*
 	 * For file extending writes updating i_size before data
 	 * writeouts complete can expose uninitialized blocks. So
 	 * even for AIO, we need to wait for i/o to complete before
 	 * returning in this case.
 	 */
 	dio->is_async = !is_sync_kiocb(iocb) && !((rw & WRITE) &&
 		(end > i_size_read(inode)));
 
-
--[[linux-2.6.33/is_sync_kiocb()]]
--[[linux-2.6.33/i_size_read()]]

 	retval = direct_io_worker(rw, iocb, inode, iov, offset,
 				nr_segs, blkbits, get_block, end_io, dio);
 
-
--[[linux-2.6.33/direct_io_worker()]]

 	/*
 	 * In case of error extending write may have instantiated a few
 	 * blocks outside i_size. Trim these off again for DIO_LOCKING.
 	 *
 	 * NOTE: filesystems with their own locking have to handle this
 	 * on their own.
 	 */
 	if (flags & DIO_LOCKING) {
 		if (unlikely((rw & WRITE) && retval < 0)) {
 			loff_t isize = i_size_read(inode);
 			if (end > isize)
 				vmtruncate(inode, isize);
 		}
-
--[[linux-2.6.33/vmtruncate()]]

 	}
 
 out:
 	return retval;
 }
 EXPORT_SYMBOL(__blockdev_direct_IO);
-特にライセンスを区別せず関数をエクスポートする。
--[[linux-2.6.33/EXPORT_SYMBOL()]]


*コメント [#t0f61807]

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS