*参照元 [#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]