Esempio n. 1
0
/* Locking note:
 * Implement POSIX locks in terms of BSD flock locks.
 * This at least gets distributed whole-file locking to work.
 * Strategies for distributed record locking will deadlock.
 */
Npfcall*
diod_lock (Npfid *fid, u8 type, u32 flags, u64 start, u64 length, u32 proc_id,
           Npstr *client_id)
{
    Fid *f = fid->aux;
    Npfcall *ret = NULL;
    u8 status = P9_LOCK_ERROR;

    if ((f->xflags & XFLAGS_RO)) {
        np_uerror (EROFS);
        goto error_quiet;
    }
    if (flags & ~P9_LOCK_FLAGS_BLOCK) { /* only one valid flag for now */
        np_uerror (EINVAL);             /*  (which we ignore) */
        goto error;
    }
    if (_fidstat(f) < 0)
        goto error_quiet;
    switch (type) {
        case F_UNLCK:
            if (flock (f->fd, LOCK_UN) >= 0) {
                status = P9_LOCK_SUCCESS;
                f->lock_type = LOCK_UN;
            } else
                status = P9_LOCK_ERROR;
            break;
        case F_RDLCK:
            if (flock (f->fd, LOCK_SH | LOCK_NB) >= 0) {
                status = P9_LOCK_SUCCESS;
                f->lock_type = LOCK_SH;
            } else if (errno == EWOULDBLOCK) {
                status = P9_LOCK_BLOCKED;
            } else
                status = P9_LOCK_ERROR;
            break;
        case F_WRLCK:
            if (flock (f->fd, LOCK_EX | LOCK_NB) >= 0) {
                status = P9_LOCK_SUCCESS;
                f->lock_type = LOCK_EX;
            } else if (errno == EWOULDBLOCK) {
                status  = P9_LOCK_BLOCKED;
            }
            break;
        default:
            np_uerror (EINVAL);
            goto error;
    }
    if (!((ret = np_create_rlock (status)))) {
        np_uerror (ENOMEM);
        goto error;
    }
    return ret;
error:
    errn (np_rerror (), "diod_lock %s@%s:%s",
          fid->user->uname, np_conn_get_client_id (fid->conn), f->path);
error_quiet:
    if (ret)
        free (ret);
    return NULL;
}
Esempio n. 2
0
/* Locking note:
 * Implement POSIX locks in terms of BSD flock locks.
 * This at least gets distributed whole-file locking to work.
 * Strategies for distributed record locking will deadlock.
 */
Npfcall*
diod_lock (Npfid *fid, u8 type, u32 flags, u64 start, u64 length, u32 proc_id,
           Npstr *client_id)
{
    Fid *f = fid->aux;
    Npfcall *ret;
    u8 status = P9_LOCK_ERROR;

    if ((f->flags & DIOD_FID_FLAGS_ROFS)) {
        np_uerror (EROFS);
        goto error_quiet;
    }
    if (flags & ~P9_LOCK_FLAGS_BLOCK) { /* only one valid flag for now */
        np_uerror (EINVAL);             /*  (which we ignore) */
        goto error;
    }
    if (!f->ioctx) {
        msg ("diod_lock: fid is not open");
        np_uerror (EBADF);
        goto error;
    }
    switch (type) {
        case P9_LOCK_TYPE_UNLCK:
            if (ioctx_flock (f->ioctx, LOCK_UN) == 0)
                status = P9_LOCK_SUCCESS;
            break;
        case P9_LOCK_TYPE_RDLCK:
            if (ioctx_flock (f->ioctx, LOCK_SH | LOCK_NB) == 0)
                status = P9_LOCK_SUCCESS;
            else if (errno == EWOULDBLOCK)
                status = P9_LOCK_BLOCKED;
            break;
        case P9_LOCK_TYPE_WRLCK:
            if (ioctx_flock (f->ioctx, LOCK_EX | LOCK_NB) == 0) 
                status = P9_LOCK_SUCCESS;
            else if (errno == EWOULDBLOCK)
                status  = P9_LOCK_BLOCKED;
            break;
        default:
            np_uerror (EINVAL);
            goto error;
    }
    if (!((ret = np_create_rlock (status)))) {
        np_uerror (ENOMEM);
        goto error;
    }
    return ret;
error:
    errn (np_rerror (), "diod_lock %s@%s:%s",
          fid->user->uname, np_conn_get_client_id (fid->conn),
          path_s (f->path));
error_quiet:
    return NULL;
}
Esempio n. 3
0
static void
test_rlock (void)
{
    Npfcall *fc, *fc2;

    if (!(fc = np_create_rlock (1)))
        msg_exit ("out of memory");
    fc2 = _rcv_buf (fc, P9_RLOCK,  __FUNCTION__);

    assert (fc->u.rlock.status == fc2->u.rlock.status);

    free (fc);
    free (fc2);
}