VOP_LOCK(9)

名称
VOP_LOCK, VOP_UNLOCK, VOP_ISLOCKED, vn_lock - vnode アクセスの直列化

書式
<sys/param.h> <sys/lock.h> <sys/vnode.h> int VOP_LOCK(struct vnode *vp, int flags, struct thread *td) int VOP_UNLOCK(struct vnode *vp, int flags, struct thread *td) int VOP_ISLOCKED(struct vnode *vp, struct thread *td) int vn_lock(struct vnode *vp, int flags, struct thread *td)

解説
これらの呼び出しは、 ファイルシステムへのアクセスを直列化するために使用されます。 例えば、同一ファイルに対する 2 つの書き込みが同時に発生することを 避けるために使用します。

引数は以下の通りです。

vp  ロックまたはロック解除される vnode。

flags
    以下のロック要求タイプのひとつ。
    LK_SHARED | 共有ロック
    LK_EXCLUSIVE | 排他的ロック
    LK_UPGRADE | 共有から排他的へのアップグレード
    LK_EXCLUPGRADE | 最初の共有から排他的へのアップグレード
    LK_DOWNGRADE | 排他的から共有へのダウングレード
    LK_RELEASE | 全てのロックタイプの解除
    LK_DRAIN | ロック状態終了までの待機

    ロックタイプは、以下のロックフラグと OR されているかもしれません。
    LK_NOWAIT | ロックを待つために sleep しない
    LK_SLEEPFAIL | sleep して、失敗を返す
    LK_CANRECURSE | 再帰的排他的ロックを認める
    LK_REENABLE | ロック消失後再有効化されるべき
    LK_NOPAUSE | 空回りしない

    ロックタイプは、以下の制御フラグと OR されているかもしれません。
    LK_INTERLOCK | 呼び出し側が既に簡易ロックを保持している時に指定
    (VOP_LOCK はロックを取得した後で簡易ロックを解除します)
    LK_RETRY | ロックされるまでリトライ
    LK_NOOBJ | オブジェクトを作成しない

td  ロックを使用するためのスレッドコンテキスト。

カーネルコードは vnode をロックするために VOP_LOCK() を直接呼び出さずに、 vn_lock() を使用するべきです。

戻り値
成功時には 0 が返され、そうでない場合にはエラーが返されます。

疑似コード

    struct vopnode {
        int von_flag;
        /*
         * 他のファイルシステム固有データ
         */
        ...;
    };
    #define VON_LOCKED	1
    #define VON_WANTED	2
    #define VTOVON(vp)	((struct vopnode *) (vp)->v_data)
    int
    vop_lock(struct vnode *vp)
    {
        struct vopnode* vop;
    start:
        while (vp->v_flag & VXLOCK) {
    	vp->v_flag |= VXWANT;
    	tsleep((caddr_t)vp, PINOD, "voplk1", 0);
        }
        if (vp->v_tag == VT_NON)
    	return ENOENT;
        vop = VTOVON(vp);
        if (vop->von_flag & VON_LOCKED) {
    	vop->von_flag |= VON_WANTED;
    	tsleep((caddr_t) vop, PINOD, "voplk2", 0);
    	goto start;
        }
        vop->von_flag |= VON_LOCKED;
        return 0;
    }
    int
    vop_unlock(struct vnode *vp)
    {
        struct vopnode *vop = VTOVON(vp);
        if ((vop->von_flag & VON_LOCKED) == 0) {
    	panic("vop_unlock not locked");
        }
        vop->von_flag &= ~VON_LOCKED;
        if (vop->von_flag & VON_WANTED) {
    	vop->von_flag &= ~VON_WANTED;
    	wakeup((caddr_t) vop);
        }
        return 0;
    }
    int
    vop_islocked(struct vnode *vp)
    {
        struct vopnode *vop = VTOVON(vp);
        if (vop->von_flag & VON_LOCKED)
    	return 1;
        else
    	return 0;
    }

関連項目
vnode(9)

作者
このマニュアルページは Doug Rabson が書きました。