Changeset 905 for trunk/server


Ignore:
Timestamp:
May 19, 2016, 2:25:59 PM (9 years ago)
Author:
dmik
Message:

tdb: Revert open/lock code to vendor.

This effectively reverts r895, r896 and many earlier commits that would
all attempt to solve the issues with file advisory locking provided by
fcntl() and used to serialize access to TDB files in Samba. All these
issues are to be solved by a proper fcntl() lock implementation provided
now by the new libcx library (https://github.com/bitwiseworks/libcx).

With the current version of libcx tdbtorture works flawlessly for
-n > 1 (it may run out of memory returning ENOLCK but that's a separate
issue that will be solved soon).

Location:
trunk/server/lib/tdb/common
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/server/lib/tdb/common/lock.c

    r895 r905  
    3333}
    3434
    35 #ifdef __OS2__
    36 enum os2_fl {
    37     OS2_FL_LOCK = 0x1,
    38     OS2_FL_RW = 0x2,
    39     OS2_FL_WAIT = 0x4,
    40     OS2_FL_UPGRADE = 0x8,
    41 };
    42 
    43 static int os2_set_file_locks(struct tdb_context *tdb, enum os2_fl flags,
    44                               off_t start, off_t offset, off_t len)
    45 {
    46     FILELOCKL locks[2] = {0};
    47     ULONG fl;
    48     BOOL dowait;
    49     APIRET arc;
    50 
    51     if ((!(flags & OS2_FL_UPGRADE) && (start > offset || start < 0)) ||
    52         offset < 0 || offset + len < 0) {
    53         errno = EINVAL;
    54         return -1;
    55     }
    56 
    57     fl = (flags & OS2_FL_RW) ? 0 : 1; /* excluive when rw, shared otherwise */
    58 
    59     if (flags & OS2_FL_UPGRADE) {
    60         locks[0].lOffset = offset;
    61         locks[0].lRange = len == 0 ? OFF_MAX : len;
    62         locks[1] = locks[0];
    63         fl |= 2; /* atomic */
    64     } else {
    65         if (start != offset) {
    66             locks[0].lOffset = start;
    67             locks[0].lRange = offset - start;
    68             fl |= 2; /* atomic */
    69         }
    70         locks[1].lOffset = start;
    71         locks[1].lRange = len == 0 ? OFF_MAX : (locks[0].lRange + len);
    72     }
    73 
    74     dowait = (flags & (OS2_FL_LOCK | OS2_FL_UPGRADE)) && (flags & OS2_FL_WAIT);
    75 
    76     TDB_LOG((tdb, TDB_DEBUG_TRACE, "os2_file_locks: fd=%d lock_fd=%d flags=%x start=%lld offset=%lld len=%lld pid=%d\n",
    77              tdb->fd, tdb->lock_fd, flags, start, offset, len, getpid()));
    78 
    79     arc = DosSetFileLocksL(tdb->lock_fd,
    80                            &locks[(flags & OS2_FL_LOCK) ? 0 : 1],
    81                            &locks[(flags & OS2_FL_LOCK) ? 1 : 0],
    82                            dowait ? SEM_INDEFINITE_WAIT : SEM_IMMEDIATE_RETURN,
    83                            fl);
    84 
    85     TDB_LOG((tdb, TDB_DEBUG_TRACE, "os2_file_locks: arc=%d pid=%d\n", arc, getpid()));
    86 
    87     if (arc) {
    88         switch (arc) {
    89             case ERROR_LOCK_VIOLATION:
    90                 errno = EACCES;
    91                 break;
    92             case ERROR_INTERRUPT:
    93                 errno = EINTR;
    94                 break;
    95             case ERROR_TIMEOUT:
    96                 errno = EDEADLK;
    97                 break;
    98             default:
    99                 TDB_LOG((tdb, TDB_DEBUG_ERROR, "os2_file_locks failed, lock_fd=%d flags=%x start=%d off=%d len=%d (arc=%d)\n",
    100                          tdb->lock_fd, flags, start, offset, len, arc));
    101         }
    102         return -1;
    103     }
    104 
    105     return 0;
    106 }
    107 #else /* __OS2__ */
    10835static int fcntl_lock(struct tdb_context *tdb,
    10936                      int rw, off_t off, off_t len, bool waitflag)
     
    192119        return fcntl(tdb->fd, F_SETLKW, &fl);
    193120}
    194 #endif /* __OS2__ */
    195121
    196122/* list -1 is the alloc list, otherwise a hash chain. */
     
    208134   note that a len of zero means lock to end of file
    209135*/
    210 #ifdef __OS2__
    211 static int tdb_brlock_ex(struct tdb_context *tdb,
    212                          int rw_type, tdb_off_t start,
    213                          tdb_off_t offset, size_t len,
    214                          enum tdb_lock_flags flags)
    215 #else
    216136int tdb_brlock(struct tdb_context *tdb,
    217137               int rw_type, tdb_off_t offset, size_t len,
    218138               enum tdb_lock_flags flags)
    219 #endif
    220139{
    221140        int ret;
     
    234153        }
    235154
    236 #ifdef __OS2__
    237         int os2_flags = OS2_FL_LOCK;
    238         if (rw_type == F_WRLCK) {
    239             os2_flags |= OS2_FL_RW;
    240         }
    241         if (flags & TDB_LOCK_WAIT) {
    242             os2_flags |= OS2_FL_WAIT;
    243         }
    244         if (flags & TDB_LOCK_UPGRADE) {
    245             os2_flags |= OS2_FL_UPGRADE;
    246         }
    247 #endif
    248 
    249155        do {
    250 #ifdef __OS2__
    251                 ret = os2_set_file_locks(tdb, os2_flags, start, offset, len);
    252 #else
    253156                ret = fcntl_lock(tdb, rw_type, offset, len,
    254157                                 flags & TDB_LOCK_WAIT);
    255 #endif
    256158                /* Check for a sigalarm break. */
    257159                if (ret == -1 && errno == EINTR &&
     
    268170                 * locks. */
    269171                if (!(flags & TDB_LOCK_PROBE) && errno != EAGAIN) {
    270                         TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d flags=%d len=%d (errno=%d)\n",
    271                                  tdb->fd, offset, rw_type, flags, (int)len, errno));
     172                        TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d flags=%d len=%d\n",
     173                                 tdb->fd, offset, rw_type, flags, (int)len));
    272174                }
    273175                return -1;
     
    276178}
    277179
    278 #ifdef __OS2__
    279 int tdb_brlock(struct tdb_context *tdb,
    280                int rw_type, tdb_off_t offset, size_t len,
    281                enum tdb_lock_flags flags)
    282 {
    283     return tdb_brlock_ex(tdb, rw_type, offset, offset, len, flags);
    284 }
    285 #endif
    286 
    287 #ifdef __OS2__
    288 static int tdb_brunlock_ex(struct tdb_context *tdb,
    289                            int rw_type, tdb_off_t start,
    290                            tdb_off_t offset, size_t len)
    291 #else
    292180int tdb_brunlock(struct tdb_context *tdb,
    293181                 int rw_type, tdb_off_t offset, size_t len)
    294 #endif
    295182{
    296183        int ret;
     
    301188
    302189        do {
    303 #ifdef __OS2__
    304                 ret = os2_set_file_locks(tdb, rw_type == F_WRLCK ? OS2_FL_RW : 0,
    305                                          start, offset, len);
    306 #else
    307190                ret = fcntl_unlock(tdb, rw_type, offset, len);
    308 #endif
    309191        } while (ret == -1 && errno == EINTR);
    310192
    311193        if (ret == -1) {
    312                 TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brunlock failed (fd=%d) at offset %d rw_type=%d len=%d (errno=%d)\n",
    313                          tdb->fd, offset, rw_type, (int)len, errno));
    314         }
    315         return ret;
    316 }
    317 
    318 #ifdef __OS2__
    319 int tdb_brunlock(struct tdb_context *tdb,
    320                  int rw_type, tdb_off_t offset, size_t len)
    321 {
    322         return tdb_brunlock_ex(tdb, rw_type, offset, offset, len);
    323 }
    324 #endif
     194                TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brunlock failed (fd=%d) at offset %d rw_type=%d len=%d\n",
     195                         tdb->fd, offset, rw_type, (int)len));
     196        }
     197        return ret;
     198}
    325199
    326200/*
     
    350224                struct timeval tv;
    351225                if (tdb_brlock(tdb, F_WRLCK, FREELIST_TOP, 0,
    352                                TDB_LOCK_WAIT|TDB_LOCK_PROBE|TDB_LOCK_UPGRADE) == 0) {
     226                               TDB_LOCK_WAIT|TDB_LOCK_PROBE) == 0) {
    353227                        tdb->allrecord_lock.ltype = F_WRLCK;
    354228                        tdb->allrecord_lock.off = 0;
     
    640514}
    641515
    642 #ifdef __OS2__
    643 #define TDB_ADJLOCK_START_DECL size_t start,
    644 #define TDB_ADJLOCK_START start,
    645 #define TDB_ADJLOCK(tdb, rw_type, start, offset, len, flags) \
    646         tdb_brlock_ex(tdb, rw_type, start, offset, len, flags)
    647 #define TDB_ADJUNLOCK(tdb, rw_type, start, offset, len) \
    648         tdb_brunlock_ex(tdb, rw_type, start, offset, len)
    649 #define TDB_CHAINLOCK_GRADUAL(tdb, ltype, flags, start, offset, len) \
    650         tdb_chainlock_gradual(tdb, ltype, flags, start, offset, len)
    651 #else
    652 #define TDB_ADJLOCK_START_DECL
    653 #define TDB_ADJLOCK_START_REF
    654 #define TDB_ADJLOCK(tdb, rw_type, start, offset, len, flags) \
    655         tdb_brlock(tdb, rw_type, offset, len, flags)
    656 #define TDB_ADJUNLOCK(tdb, rw_type, start, offset, len) \
    657         tdb_brunlock(tdb, rw_type, offset, len)
    658 #define TDB_CHAINLOCK_GRADUAL(tdb, ltype, flags, start, offset, len) \
    659         tdb_chainlock_gradual(tdb, ltype, flags, offset, len)
    660 #endif
    661 
    662516/* We only need to lock individual bytes, but Linux merges consecutive locks
    663517 * so we lock in contiguous ranges. */
    664518static int tdb_chainlock_gradual(struct tdb_context *tdb,
    665519                                 int ltype, enum tdb_lock_flags flags,
    666                                  TDB_ADJLOCK_START_DECL size_t off, size_t len)
     520                                 size_t off, size_t len)
    667521{
    668522        int ret;
     
    671525        if (len <= 4) {
    672526                /* Single record.  Just do blocking lock. */
    673                 return TDB_ADJLOCK(tdb, ltype, start, off, len, flags);
     527                return tdb_brlock(tdb, ltype, off, len, flags);
    674528        }
    675529
    676530        /* First we try non-blocking. */
    677         ret = TDB_ADJLOCK(tdb, ltype, start, off, len, nb_flags);
     531        ret = tdb_brlock(tdb, ltype, off, len, nb_flags);
    678532        if (ret == 0) {
    679533                return 0;
     
    681535
    682536        /* Try locking first half, then second. */
    683         ret = TDB_CHAINLOCK_GRADUAL(tdb, ltype, flags, start, off, len / 2);
     537        ret = tdb_chainlock_gradual(tdb, ltype, flags, off, len / 2);
    684538        if (ret == -1)
    685539                return -1;
    686540
    687         ret = TDB_CHAINLOCK_GRADUAL(tdb, ltype, flags, start,
     541        ret = tdb_chainlock_gradual(tdb, ltype, flags,
    688542                                    off + len / 2, len - len / 2);
    689543        if (ret == -1) {
    690                 TDB_ADJUNLOCK(tdb, ltype, start, off, len / 2);
     544                tdb_brunlock(tdb, ltype, off, len / 2);
    691545                return -1;
    692546        }
     
    714568         * It is (1) which cause the starvation problem, so we're only
    715569         * gradual for that. */
    716         if (TDB_CHAINLOCK_GRADUAL(tdb, ltype, flags, FREELIST_TOP, FREELIST_TOP,
     570        if (tdb_chainlock_gradual(tdb, ltype, flags, FREELIST_TOP,
    717571                                  tdb->header.hash_size * 4) == -1) {
    718572                return -1;
     
    720574
    721575        /* Grab individual record locks. */
    722         if (TDB_ADJLOCK(tdb, ltype, FREELIST_TOP, lock_offset(tdb->header.hash_size), 0,
    723                         flags) == -1) {
     576        if (tdb_brlock(tdb, ltype, lock_offset(tdb->header.hash_size), 0,
     577                       flags) == -1) {
    724578                tdb_brunlock(tdb, ltype, FREELIST_TOP,
    725579                             tdb->header.hash_size * 4);
  • trunk/server/lib/tdb/common/open.c

    r901 r905  
    1  /*
     1 /* 
    22   Unix SMB/CIFS implementation.
    33
     
    120120}
    121121
    122 /* open the database, creating it if necessary
     122/* open the database, creating it if necessary 
    123123
    124124   The open_flags and mode are passed straight to the open call on the
     
    126126   is advisory, use zero for a default value.
    127127
    128    Return is NULL on error, in which case errno is also set.  Don't
     128   Return is NULL on error, in which case errno is also set.  Don't 
    129129   try to call tdb_error or tdb_errname, just do strerror(errno).
    130130
     
    162162        return check_header_hash(tdb, false, m1, m2);
    163163}
    164 
    165 #ifdef __OS2__
    166 static int os2_create_lockfile(struct tdb_context *tdb, const char *name, const char *origin)
    167 {
    168         /* name could be null, so handle it */
    169         if (name == NULL)
    170                 return 0;
    171 
    172         char lock_name[_MAX_PATH + 5];
    173         snprintf(lock_name, sizeof(lock_name), "%s.lock", name);
    174         /*
    175          * First try to O_TRUNC it to make sure the file is empty (this
    176          * will succeed on first open), but ignore the error that will
    177          * happen if some bytes are already locked.
    178          */
    179         tdb->lock_fd = open(lock_name, tdb->open_flags | O_CREAT | O_TRUNC, 0777);
    180         if (tdb->lock_fd == -1 && errno == EACCES)
    181                 tdb->lock_fd = open(lock_name, tdb->open_flags | O_CREAT, 0777);
    182         if (tdb->lock_fd == -1) {
    183                 TDB_LOG((tdb, TDB_DEBUG_ERROR, "os2_create_lockfile: cannot create lock file %s, errno=%d\n",
    184                          lock_name, errno));
    185                 return -1;
    186         }
    187 
    188         return 0;
    189 }
    190 #endif
    191164
    192165_PUBLIC_ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
     
    333306        fcntl(tdb->fd, F_SETFD, v | FD_CLOEXEC);
    334307
    335 #ifdef __OS2__
    336         if (os2_create_lockfile(tdb, name, "tdb_open_ex") != 0)
    337                 goto fail;
    338 #endif
    339 
    340308        /* ensure there is only one process initialising at once */
    341309        if (tdb_nest_lock(tdb, OPEN_LOCK, F_WRLCK, TDB_LOCK_WAIT) == -1) {
     
    505473        { int save_errno = errno;
    506474
    507 #ifdef __OS2__
    508         close(tdb->lock_fd);
    509         tdb->lock_fd = -1;
    510 #endif
    511475        if (!tdb)
    512476                return NULL;
     
    577541        }
    578542
    579 #ifdef __OS2__
    580         close(tdb->lock_fd);
    581         tdb->lock_fd = -1;
    582 #endif
    583 
    584543#ifdef TDB_TRACE
    585544        close(tdb->tracefd);
     
    649608#endif /* fake pread or pwrite */
    650609
    651 #ifdef __OS2__
    652         close(tdb->lock_fd);
    653         tdb->lock_fd = -1;
    654 
    655         if (os2_create_lockfile(tdb, tdb->name, "tdb_reopen") != 0)
    656                 goto fail;
    657 #endif
    658610        /* We may still think we hold the active lock. */
    659611        tdb->num_lockrecs = 0;
  • trunk/server/lib/tdb/common/tdb_private.h

    r895 r905  
    2323   License along with this library; if not, see <http://www.gnu.org/licenses/>.
    2424*/
    25 #ifdef __OS2__
    26 #define INCL_ERRORS
    27 #define INCL_DOS
    28 #include <os2.h>
    29 #endif
    3025
    3126#include "replace.h"
     
    180175        /* If set, don't actually lock at all. */
    181176        TDB_LOCK_MARK_ONLY = 4,
    182         /* If set, upgrade the existiong lock (used only on OS/2). */
    183         TDB_LOCK_UPGRADE = 8,
    184177};
    185178
     
    221214#endif
    222215        volatile sig_atomic_t *interrupt_sig_ptr;
    223 #ifdef __OS2__
    224         int lock_fd;
    225 #endif
    226216};
    227217
Note: See TracChangeset for help on using the changeset viewer.