we now pass all byte range locking tests
authorAndrew Tridgell <tridge@samba.org>
Fri, 14 Jan 2000 04:32:57 +0000 (04:32 +0000)
committerAndrew Tridgell <tridge@samba.org>
Fri, 14 Jan 2000 04:32:57 +0000 (04:32 +0000)
the last piece was to use a smb timeout slightly larger than the
locking timeout in bloking locks to prevent a race

source/include/proto.h
source/libsmb/clientgen.c
source/locking/brlock.c
source/locking/locking.c
source/smbd/close.c
source/utils/torture.c

index c3bbb505a2e5c3379ecc9d943f9021a62bfcaa32..8618c1cd69be69e40900447141c727a4ef599084 100644 (file)
@@ -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);
index 06a5e5427fb4c82dfe5af31e5da93ec57061c6eb..1c9a2123cce1b3e270404b65bb7f33fab1efc096 100644 (file)
@@ -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);
 
index 5d928daa58012985ad4afe464b44d661b6dbe9f1..653a40728bd00d7db86fcc749a21bc62ee538402 100644 (file)
@@ -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);
+}
index e95ec08c58b47404bc34681011e0401fcb54afc3..350057d1a78498690fd2a86db5461498e8419265 100644 (file)
@@ -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);
        }
index bfef7c52354599ee2ca9a9bab123e009a1ffd3a5..7f5769b36828e48875760c0a266bc44d0959460b 100644 (file)
@@ -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;
 
index ba510c0b585012cf7b5b8adef5aa2d697b692a40..4539f11a6aea11a3549e0dd3c40de5339a29d1a4 100644 (file)
@@ -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);