[PATCHES] Cleanup dead records in messages.tdb

Christof Schmitt cs at samba.org
Thu Apr 3 16:15:20 MDT 2014


On Thu, Apr 03, 2014 at 03:05:02PM -0700, Christof Schmitt wrote:
> On Thu, Apr 03, 2014 at 02:56:39PM -0700, Jeremy Allison wrote:
> > On Thu, Apr 03, 2014 at 02:32:25PM -0700, Jeremy Allison wrote:
> > > On Thu, Apr 03, 2014 at 02:26:29PM -0700, Christof Schmitt wrote:
> > > > 
> > > > Actually, there is an issue with the locking here: tdb_delete fails,
> > > > because it tries to get a lock for the delete, but the chain is already
> > > > locked. Either we have to live with the race here, or add a call to tdb
> > > > that allows deletion without acquiring the lock.
> > > 
> > > Are you sure here ? That same bug would then exist
> > > in the function :
> > > 
> > > tatic NTSTATUS retrieve_all_messages(TDB_CONTEXT *msg_tdb,
> > >                                       struct server_id id,
> > >                                       TALLOC_CTX *mem_ctx,
> > >                                       struct messaging_array **presult)
> > > {
> > >         struct messaging_array *result;
> > >         TDB_DATA key = message_key_pid(mem_ctx, id);
> > >         NTSTATUS status;
> > > 
> > >         if (tdb_chainlock(msg_tdb, key) != 0) {
> > >                 TALLOC_FREE(key.dptr);
> > >                 return NT_STATUS_LOCK_NOT_GRANTED;
> > >         }
> > > 
> > >         status = messaging_tdb_fetch(msg_tdb, key, mem_ctx, &result);
> > > 
> > >         /*
> > >          * We delete the record here, tdb_set_max_dead keeps it around
> > >          */
> > >         tdb_delete(msg_tdb, key);
> > >         tdb_chainunlock(msg_tdb, key);
> > > 
> > >         if (NT_STATUS_IS_OK(status)) {
> > >                 *presult = result;
> > >         }
> > > 
> > >         TALLOC_FREE(key.dptr);
> > > 
> > >         return status;
> > > }
> > > 
> > > which is called regularly in the messaging
> > > code...
> > 
> > Just wrote a quick standalone test:
> > 
> > +static void jratest(TDB_CONTEXT *db)
> > +{
> > +       TDB_DATA key, data;
> > +
> > +       key.dptr = "keyname";
> > +       key.dsize = 8;
> > +       data.dptr = "data";
> > +       data.dsize = 5;
> > +
> > +       if (tdb_store(db, key, data, 0) != 0) {
> > +               abort();
> > +       }
> > +
> > +       if (tdb_chainlock(db, key) != 0) {
> > +               abort();
> > +       }
> > +
> > +       if (tdb_delete(db, key) != 0) {
> > +               abort();
> > +       }
> > +       if (tdb_chainunlock(db, key) != 0) {
> > +               abort();
> > +       }
> > +}
> > 
> > seems to work fine. So I don't think there's
> > a problem with deleting a record under a chainlock...
> > 
> > (I'm pretty sure those locks are recursive).
> 
> I tried adding a record with tdbtool insert, killing the corresponding
> smbd process and watch the record disappear. So far i only get -1 from
> tdb_delete. Maybe something is wrong with this test, i am still digging
> through it.

The patch works as expected, i just forgot to add the 0 byte terminator
in the key of my fake tdb record. Sorry for the noise.

Christof


More information about the samba-technical mailing list