Hello everyone.
I find the subject suspicious.
See comments in the function below.
Where am I wrong?
Any ideas?
Thanks,
Edward.
int32_t
oplock_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, struct
iovec *vector,
int32_t count, off_t offset, struct iobref *iobref)
{
server_state_t *state = CALL_STATE(frame);
inode_t *inode = fd->inode;
struct oplock_entry *entry = NULL;
oplock_private_t *priv = this->private;
int op_errno = 0;
entry = fetch_op_lock(&priv->locks,inode,state->conn);
if (entry) {
LIST_REMOVE(entry,links);
if (entry->value != inode->gen) {
gf_log(this->name,GF_LOG_DEBUG,
"would reject write for %d from %p",
inode->ino, state->conn);
op_errno = EBUSY;
goto err;
}
FREE(entry);
}
++(inode->gen);
/* Suppose thread A overwrites a byte at offset 0,
* and thread B overwrites a byte in the same file
* at offset 15 (the same block).
*
* Suppose A sets the counter above (inode->gen) to N.
* At this point global file's data is not yet modified.
* Thread B issues a lock with assigned value N, then
* successfully reads old data from disk.
*/
STACK_WIND (frame, oplock_writev_cbk,
FIRST_CHILD(this), FIRST_CHILD(this)->fops->writev,
fd, vector, count, offset, iobref);
/* At this point global file's data has been modified by A.
* Next, B increases the counter to N+1, and also modifies
* global data. Changes performed by A are lost.
*/
return 0;
err:
STACK_UNWIND_STRICT(writev,frame,-1,op_errno,NULL,NULL);
return 0;
}