static void test_rgetlock (void) { Npfcall *fc, *fc2; if (!(fc = np_create_rgetlock (P9_LOCK_TYPE_WRLCK, 2, 3, 4, "xyz"))) msg_exit ("out of memory"); fc2 = _rcv_buf (fc, P9_RGETLOCK, __FUNCTION__); assert (fc->u.rgetlock.type == fc2->u.rgetlock.type); assert (fc->u.rgetlock.start == fc2->u.rgetlock.start); assert (fc->u.rgetlock.length == fc2->u.rgetlock.length); assert (fc->u.rgetlock.proc_id == fc2->u.rgetlock.proc_id); assert (np_str9cmp (&fc->u.rgetlock.client_id, &fc2->u.rgetlock.client_id) == 0); free (fc); free (fc2); }
Npfcall* diod_getlock (Npfid *fid, u8 type, u64 start, u64 length, u32 proc_id, Npstr *client_id) { Fid *f = fid->aux; Npfcall *ret; char *cid = NULL; int ftype; if ((f->flags & DIOD_FID_FLAGS_ROFS)) { np_uerror (EROFS); goto error_quiet; } if (!f->ioctx) { msg ("diod_getlock: fid is not open"); np_uerror (EBADF); goto error; } if (!(cid = np_strdup (client_id))) { np_uerror (ENOMEM); goto error; } if (type != P9_LOCK_TYPE_RDLCK && type != P9_LOCK_TYPE_WRLCK) { np_uerror (EINVAL); goto error; } ftype = (type == P9_LOCK_TYPE_RDLCK) ? LOCK_SH : LOCK_EX; ftype = ioctx_testlock (f->ioctx, ftype); type = (ftype == LOCK_EX) ? P9_LOCK_TYPE_WRLCK : P9_LOCK_TYPE_UNLCK; if (!((ret = np_create_rgetlock(type, start, length, proc_id, cid)))) { np_uerror (ENOMEM); goto error; } free (cid); return ret; error: errn (np_rerror (), "diod_getlock %s@%s:%s", fid->user->uname, np_conn_get_client_id (fid->conn), path_s (f->path)); error_quiet: if (cid) free (cid); return NULL; }
Npfcall* diod_getlock (Npfid *fid, u8 type, u64 start, u64 length, u32 proc_id, Npstr *client_id) { Fid *f = fid->aux; Npfcall *ret; char *cid = NULL; struct stat sb; if ((f->xflags & XFLAGS_RO)) { np_uerror (EROFS); goto error_quiet; } if (!(cid = np_strdup (client_id))) { np_uerror (ENOMEM); goto error; } if (fstat(f->fd, &sb) < 0) { np_uerror (errno); goto error_quiet; } switch (type) { case P9_LOCK_TYPE_RDLCK: switch (f->lock_type) { case LOCK_EX: case LOCK_SH: type = P9_LOCK_TYPE_UNLCK; break; case LOCK_UN: if (flock (f->fd, LOCK_SH | LOCK_NB) >= 0) { (void)flock (f->fd, LOCK_UN); type = P9_LOCK_TYPE_UNLCK; } else type = P9_LOCK_TYPE_WRLCK; break; } break; case P9_LOCK_TYPE_WRLCK: switch (f->lock_type) { case LOCK_EX: type = P9_LOCK_TYPE_UNLCK; break; case LOCK_SH: /* Rather than upgrade the lock to LOCK_EX and risk * not reacquiring the LOCK_SH afterwards, lie about * the lock being available. Getlock is racy anyway. */ type = P9_LOCK_TYPE_UNLCK; break; case LOCK_UN: if (flock (f->fd, LOCK_EX | LOCK_NB) >= 0) { (void)flock (f->fd, LOCK_UN); type = P9_LOCK_TYPE_UNLCK; } else type = P9_LOCK_TYPE_WRLCK; /* could also be LOCK_SH actually */ } break; default: np_uerror (EINVAL); goto error; } if (type != P9_LOCK_TYPE_UNLCK && type != F_UNLCK) { /* FIXME: need to fake up start, length, proc_id, cid? */ } if (!((ret = np_create_rgetlock(type, start, length, proc_id, cid)))) { np_uerror (ENOMEM); goto error; } free (cid); return ret; error: errn (np_rerror (), "diod_getlock %s@%s:%s", fid->user->uname, np_conn_get_client_id (fid->conn), f->path); error_quiet: if (cid) free (cid); return NULL; }