summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/proto.h8
-rw-r--r--source3/libsmb/clientgen.c7
-rw-r--r--source3/locking/brlock.c59
-rw-r--r--source3/locking/locking.c17
-rw-r--r--source3/smbd/close.c2
-rw-r--r--source3/utils/torture.c26
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);