diff options
author | Andrew Tridgell <tridge@samba.org> | 2000-01-14 04:32:57 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2000-01-14 04:32:57 +0000 |
commit | 82af221e4a7e456f580f16bc5d2fd904fc018c96 (patch) | |
tree | 1b0818867ea76a25e578345364186566c4f167c4 | |
parent | 7cd74b07ef283a4ce2e6f6c98cc7096189a74f20 (diff) | |
download | samba-82af221e4a7e456f580f16bc5d2fd904fc018c96.tar.gz samba-82af221e4a7e456f580f16bc5d2fd904fc018c96.tar.bz2 samba-82af221e4a7e456f580f16bc5d2fd904fc018c96.zip |
we now pass all byte range locking tests
the last piece was to use a smb timeout slightly larger than the
locking timeout in bloking locks to prevent a race
(This used to be commit 1b54cb4a33a65e62c2e3189b78ef073869a60c75)
-rw-r--r-- | source3/include/proto.h | 8 | ||||
-rw-r--r-- | source3/libsmb/clientgen.c | 7 | ||||
-rw-r--r-- | source3/locking/brlock.c | 59 | ||||
-rw-r--r-- | source3/locking/locking.c | 17 | ||||
-rw-r--r-- | source3/smbd/close.c | 2 | ||||
-rw-r--r-- | source3/utils/torture.c | 26 |
6 files changed, 94 insertions, 25 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index c3bbb505a2..8618c1cd69 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -591,7 +591,7 @@ BOOL cli_close(struct cli_state *cli, int fnum); BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout, enum lock_type lock_type); BOOL cli_unlock(struct cli_state *cli, int fnum, - uint32 offset, uint32 len, int timeout); + uint32 offset, uint32 len); size_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size); ssize_t cli_write(struct cli_state *cli, int fnum, uint16 write_mode, @@ -755,20 +755,22 @@ struct packet_struct *receive_unexpected(enum packet_type packet_type, int id, /*The following definitions come from locking/brlock.c */ void brl_init(void); -BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, +BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, uint16 smbpid, pid_t pid, uint16 tid, br_off start, br_off size, enum lock_type lock_type); -BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, +BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, uint16 smbpid, pid_t pid, uint16 tid, br_off start, br_off size); BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, uint16 smbpid, pid_t pid, uint16 tid, br_off start, br_off size, enum lock_type lock_type); +void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum); /*The following definitions come from locking/locking.c */ +void locking_close_file(files_struct *fsp); BOOL is_locked(files_struct *fsp,connection_struct *conn, SMB_OFF_T count,SMB_OFF_T offset, enum lock_type lock_type); diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 06a5e5427f..1c9a2123cc 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -1372,7 +1372,7 @@ BOOL cli_lock(struct cli_state *cli, int fnum, SIVAL(p, 6, len); cli_send_smb(cli); - cli->timeout = (timeout == -1) ? 0x7FFFFFFF : timeout; + cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 2*1000); if (!cli_receive_smb(cli)) { cli->timeout = saved_timeout; @@ -1391,8 +1391,7 @@ BOOL cli_lock(struct cli_state *cli, int fnum, /**************************************************************************** unlock a file ****************************************************************************/ -BOOL cli_unlock(struct cli_state *cli, int fnum, - uint32 offset, uint32 len, int timeout) +BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len) { char *p; @@ -1408,7 +1407,7 @@ BOOL cli_unlock(struct cli_state *cli, int fnum, CVAL(cli->outbuf,smb_vwv0) = 0xFF; SSVAL(cli->outbuf,smb_vwv2,fnum); CVAL(cli->outbuf,smb_vwv3) = 0; - SIVALS(cli->outbuf, smb_vwv4, timeout); + SIVALS(cli->outbuf, smb_vwv4, 0); SSVAL(cli->outbuf,smb_vwv6,1); SSVAL(cli->outbuf,smb_vwv7,0); diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 5d928daa58..653a40728b 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -43,6 +43,7 @@ struct lock_struct { struct lock_context context; br_off start; br_off size; + int fnum; enum lock_type lock_type; }; @@ -102,7 +103,7 @@ void brl_init(void) /**************************************************************************** lock a range of bytes ****************************************************************************/ -BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, +BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, uint16 smbpid, pid_t pid, uint16 tid, br_off start, br_off size, enum lock_type lock_type) @@ -127,6 +128,7 @@ BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, lock.context.tid = tid; lock.start = start; lock.size = size; + lock.fnum = fnum; lock.lock_type = lock_type; if (dbuf.dptr) { @@ -161,7 +163,7 @@ BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, /**************************************************************************** unlock a range of bytes ****************************************************************************/ -BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, +BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, uint16 smbpid, pid_t pid, uint16 tid, br_off start, br_off size) { @@ -192,6 +194,7 @@ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, count = dbuf.dsize / sizeof(*locks); for (i=0; i<count; i++) { if (brl_same_context(&locks[i].context, &context) && + locks[i].fnum == fnum && locks[i].start == start && locks[i].size == size) { /* found it - delete it */ @@ -273,3 +276,55 @@ BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, tdb_unlockchain(tdb, kbuf); return False; } + + +/**************************************************************************** +remove any locks associated with a open file +****************************************************************************/ +void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum) +{ + struct lock_key key; + TDB_DATA kbuf, dbuf; + int count, i; + struct lock_struct *locks; + + key.device = dev; + key.inode = ino; + kbuf.dptr = (char *)&key; + kbuf.dsize = sizeof(key); + + dbuf.dptr = NULL; + + tdb_lockchain(tdb, kbuf); + dbuf = tdb_fetch(tdb, kbuf); + + if (!dbuf.dptr) goto fail; + + /* there are existing locks - remove any for this fnum */ + locks = (struct lock_struct *)dbuf.dptr; + count = dbuf.dsize / sizeof(*locks); + for (i=0; i<count; i++) { + if (locks[i].context.tid == tid && + locks[i].context.pid == pid && + locks[i].fnum == fnum) { + /* found it - delete it */ + if (count > 1 && i < count-1) { + memmove(&locks[i], &locks[i+1], + sizeof(*locks)*((count-1) - i)); + } + count--; + i--; + } + } + + if (count == 0) { + tdb_delete(tdb, kbuf); + } else if (count < (dbuf.dsize / sizeof(*locks))) { + tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); + } + + /* we didn't find it */ + fail: + if (dbuf.dptr) free(dbuf.dptr); + tdb_unlockchain(tdb, kbuf); +} diff --git a/source3/locking/locking.c b/source3/locking/locking.c index e95ec08c58..350057d1a7 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -40,6 +40,19 @@ static TDB_CONTEXT *tdb; int global_smbpid; + +/**************************************************************************** +remove any locks on this fd +****************************************************************************/ +void locking_close_file(files_struct *fsp) +{ + if (!lp_locking(SNUM(fsp->conn))) return; + + brl_close(fsp->fd_ptr->dev, fsp->fd_ptr->inode, + getpid(), fsp->conn->cnum, fsp->fnum); +} + + /**************************************************************************** Utility function called to see if a file region is locked. ****************************************************************************/ @@ -83,7 +96,7 @@ BOOL do_lock(files_struct *fsp,connection_struct *conn, lock_type, (double)offset, (double)count, fsp->fsp_name )); if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) { - ok = brl_lock(fsp->fd_ptr->dev, fsp->fd_ptr->inode, + ok = brl_lock(fsp->fd_ptr->dev, fsp->fd_ptr->inode, fsp->fnum, global_smbpid, getpid(), conn->cnum, offset, count, lock_type); @@ -114,7 +127,7 @@ BOOL do_unlock(files_struct *fsp,connection_struct *conn, (double)offset, (double)count, fsp->fsp_name )); if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) { - ok = brl_unlock(fsp->fd_ptr->dev, fsp->fd_ptr->inode, + ok = brl_unlock(fsp->fd_ptr->dev, fsp->fd_ptr->inode, fsp->fnum, global_smbpid, getpid(), conn->cnum, offset, count); } diff --git a/source3/smbd/close.c b/source3/smbd/close.c index bfef7c5235..7f5769b368 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -115,6 +115,8 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) release_file_oplock(fsp); + locking_close_file(fsp); + if(fd_attempt_close(fsp->fd_ptr,&err) == 0) last_reference = True; diff --git a/source3/utils/torture.c b/source3/utils/torture.c index ba510c0b58..4539f11a6a 100644 --- a/source3/utils/torture.c +++ b/source3/utils/torture.c @@ -242,7 +242,7 @@ static BOOL rw_torture(struct cli_state *c) printf("unlink failed (%s)\n", cli_errstr(c)); } - if (!cli_unlock(c, fnum2, n*sizeof(int), sizeof(int), -1)) { + if (!cli_unlock(c, fnum2, n*sizeof(int), sizeof(int))) { printf("unlock failed (%s)\n", cli_errstr(c)); } } @@ -550,8 +550,6 @@ static void run_locktest2(int dummy) cli_setpid(&cli, 1); - sleep(10); - if (!cli_lock(&cli, fnum1, 0, 4, 0, WRITE_LOCK)) { printf("lock1 failed (%s)\n", cli_errstr(&cli)); return; @@ -565,7 +563,7 @@ static void run_locktest2(int dummy) cli_setpid(&cli, 2); - if (cli_unlock(&cli, fnum1, 0, 4, 0)) { + if (cli_unlock(&cli, fnum1, 0, 8)) { printf("unlock1 succeeded! This is a locking bug\n"); } @@ -677,14 +675,14 @@ static void run_locktest3(int dummy) for (offset=i=0;i<numops;i++) { NEXT_OFFSET; - if (!cli_unlock(&cli1, fnum1, offset-1, 1, 0)) { + if (!cli_unlock(&cli1, fnum1, offset-1, 1)) { printf("unlock1 %d failed (%s)\n", i, cli_errstr(&cli1)); return; } - if (!cli_unlock(&cli2, fnum2, offset-2, 1, 0)) { + if (!cli_unlock(&cli2, fnum2, offset-2, 1)) { printf("unlock2 %d failed (%s)\n", i, cli_errstr(&cli1)); @@ -802,7 +800,7 @@ static void run_locktest4(int dummy) ret = cli_lock(&cli1, fnum1, 110, 4, 0, READ_LOCK) && cli_lock(&cli1, fnum1, 112, 4, 0, READ_LOCK) && - cli_unlock(&cli1, fnum1, 110, 6, 0); + cli_unlock(&cli1, fnum1, 110, 6); EXPECTED(ret, False); printf("the same process %s coalesce read locks\n", ret?"can":"cannot"); @@ -820,30 +818,30 @@ static void run_locktest4(int dummy) ret = cli_lock(&cli1, fnum1, 140, 4, 0, READ_LOCK) && cli_lock(&cli1, fnum1, 140, 4, 0, READ_LOCK) && - cli_unlock(&cli1, fnum1, 140, 4, 0) && - cli_unlock(&cli1, fnum1, 140, 4, 0); + cli_unlock(&cli1, fnum1, 140, 4) && + cli_unlock(&cli1, fnum1, 140, 4); EXPECTED(ret, True); printf("this server %s do recursive read locking\n", ret?"does":"doesn't"); ret = cli_lock(&cli1, fnum1, 150, 4, 0, WRITE_LOCK) && cli_lock(&cli1, fnum1, 150, 4, 0, READ_LOCK) && - cli_unlock(&cli1, fnum1, 150, 4, 0) && + cli_unlock(&cli1, fnum1, 150, 4) && (cli_read(&cli2, fnum2, buf, 150, 4) == 4) && !(cli_write(&cli2, fnum2, 0, buf, 150, 4) == 4) && - cli_unlock(&cli1, fnum1, 150, 4, 0); + cli_unlock(&cli1, fnum1, 150, 4); EXPECTED(ret, True); printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't"); ret = cli_lock(&cli1, fnum1, 160, 4, 0, READ_LOCK) && - cli_unlock(&cli1, fnum1, 160, 4, 0) && + cli_unlock(&cli1, fnum1, 160, 4) && (cli_write(&cli2, fnum2, 0, buf, 160, 4) == 4) && (cli_read(&cli2, fnum2, buf, 160, 4) == 4); EXPECTED(ret, True); printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot"); ret = cli_lock(&cli1, fnum1, 170, 4, 0, WRITE_LOCK) && - cli_unlock(&cli1, fnum1, 170, 4, 0) && + cli_unlock(&cli1, fnum1, 170, 4) && (cli_write(&cli2, fnum2, 0, buf, 170, 4) == 4) && (cli_read(&cli2, fnum2, buf, 170, 4) == 4); EXPECTED(ret, True); @@ -851,7 +849,7 @@ static void run_locktest4(int dummy) ret = cli_lock(&cli1, fnum1, 190, 4, 0, WRITE_LOCK) && cli_lock(&cli1, fnum1, 190, 4, 0, READ_LOCK) && - cli_unlock(&cli1, fnum1, 190, 4, 0) && + cli_unlock(&cli1, fnum1, 190, 4) && !(cli_write(&cli2, fnum2, 0, buf, 190, 4) == 4) && (cli_read(&cli2, fnum2, buf, 190, 4) == 4); EXPECTED(ret, True); |