VOP_READ(9) FreeBSD 一般コマンドマニュアル

VOP_READ

前のページ 上に戻る 次のページ

VOP_READ


     #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]           ファイルシステムが一杯です。

ABELNET VPSサービス