VOP_RDWR(9)
|
FreeBSD 一般コマンドマニュアル
|
VOP_RDWR
VOP_RDWR
#include <sys/vnode.h>
#include <sys/uio.h>
int
VOP_READ(struct vnode *vp, struct uio *uio, int ioflag,
struct ucred *cred);
int
VOP_WRITE(struct vnode *vp, struct uio *uio, int ioflag,
struct ucred *cred);
解説
これらのエントリポイントは、ファイルの内容を読み込みまたは書き込みます。
引数は以下の通りです。
vp ファイルの vnode。
uio 読み込みまたは書き込み対象のデータの位置。
ioflag 様々なフラグ。
cnp 呼び出し側の証明。
ioflag 引数は、ファイルシステムに対する命令およびヒントを与えるために使用
されます。読み込みを試みる時には、上位の 16 ビットは、ファイルシステムが
試みるべき先読みのヒントを (ファイルシステムブロック単位で) 提供するため
に使用されます。下位の 16 ビットは、以下のフラグを含むことができるビット
マスクです。
IO_UNIT 不可分に入出力を行ないます。
IO_APPEND 末尾に追加書き込みを行ないます。
IO_SYNC 同期的に入出力を行ないます。
IO_NODELOCKED 下位層のノードは既にロックされています。
IO_NDELAY ファイルテーブルに FNDELAY フラグを設定します。
IO_VMIO 仮想メモリ入出力 (VMIO) 領域にデータが既にあります。
ロック
入る時に、ファイルはロックされているべきで、終了時までロックされ続けま
す。
戻り値
成功時には 0 が返され、そうでない場合にはエラーコードが返されます。
疑似コード
int
vop_read(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
lbn = uio->uio_offset / size;
blkoffset = uio->uio_offset - lbn * size;
xfersize = size - blkoffset;
if (uio->uio_resid < xfersize)
xfersize = uio->uio_resid;
if (bytesinfile < xfersize)
xfersize = bytesinfile;
error = bread(vp, lbn, size, NOCRED, &bp);
if (error) {
brelse(bp);
bp = NULL;
break;
}
/*
* 入出力エラーが起こった時には 0 でない b_resid のみ
* を得ます。これは上で break を引き起こすべきです。
* しかしながら、短い読み込みがエラーを起こさなかった
* 場合には、間違ったまたは初期化されていないデータの
* uiomove を行なわないことを保証したい。
*/
size -= bp->b_resid;
if (size < xfersize) {
if (size == 0)
break;
xfersize = size;
}
error = uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio);
if (error)
break;
bqrelse(bp);
}
if (bp != NULL)
bqrelse(bp);
return error;
}
int
vop_write(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
{
struct buf *bp;
off_t bytesinfile;
daddr_t lbn, nextlbn;
off_t osize;
long size, resid, xfersize, blkoffset;
int flags;
int error;
if (uio->uio_resid < xfersize)
xfersize = uio->uio_resid;
if (uio->uio_offset + xfersize > size of file)
vnode_pager_setsize(vp, uio->uio_offset + xfersize);
if (size > xfersize)
flags |= B_CLRBUF;
else
flags &= ~B_CLRBUF;
error = find_block_in_file(vp, lbn, blkoffset + xfersize,
cred, &bp, flags);
if (error)
break;
if (uio->uio_offset + xfersize > size of file)
set size of file to uio->uio_offset + xfersize;
error = uiomove((char *)bp->b_data + blkoffset, (int) xfersize, uio);
/* XXX ufs はここでエラーチェックをしていません。何故? */
if (ioflag & IO_VMIO)
bp->b_flags |= B_RELBUF; /* ??? */
if (ioflag & IO_SYNC)
bwrite(bp);
else if (xfersize + blkoffset == size)
bawrite(bp);
else
bdwrite(bp);
if (error || xfersize == 0)
break;
}
if (error) {
if (ioflag & IO_UNIT) {
VOP_TRUNCATE(vp, osize, ioflag & IO_SYNC, cred, uio->uio_procp);
uio->uio_offset -= resid - uio->uio_resid;
uio->uio_resid = resid;
}
} else if (resid > uio->uio_resid && (ioflag & IO_SYNC)) {
struct timeval tv;
error = VOP_UPDATE(vp, &tv, &tv, 1); /* XXX これは何をしているの? */
}
return error;
}
エラー
[ENOSPC] ファイルシステムが一杯です。