Ignore:
Timestamp:
Nov 27, 2012, 4:43:17 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: updated trunk to 3.6.0

Location:
trunk/server
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/server

  • trunk/server/source3/smbd/smb2_lock.c

    r414 r745  
    44
    55   Copyright (C) Stefan Metzmacher 2009
     6   Copyright (C) Jeremy Allison 2010
    67
    78   This program is free software; you can redistribute it and/or modify
     
    2021
    2122#include "includes.h"
     23#include "smbd/smbd.h"
    2224#include "smbd/globals.h"
    2325#include "../libcli/smb/smb_common.h"
     26#include "../lib/util/tevent_ntstatus.h"
     27#include "messages.h"
    2428
    2529struct smbd_smb2_lock_element {
     
    2832        uint32_t flags;
    2933};
     34
     35struct smbd_smb2_lock_state {
     36        struct smbd_smb2_request *smb2req;
     37        struct smb_request *smb1req;
     38        struct blocking_lock_record *blr;
     39        uint16_t lock_count;
     40        struct smbd_lock_element *locks;
     41};
     42
     43static void remove_pending_lock(struct smbd_smb2_lock_state *state,
     44                                struct blocking_lock_record *blr);
    3045
    3146static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx,
     
    8499        if (req->compat_chain_fsp) {
    85100                /* skip check */
    86         } else if (in_file_id_persistent != 0) {
     101        } else if (in_file_id_persistent != in_file_id_volatile) {
    87102                return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
    88103        }
     
    130145static void smbd_smb2_request_lock_done(struct tevent_req *subreq)
    131146{
    132         struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
     147        struct smbd_smb2_request *smb2req = tevent_req_callback_data(subreq,
    133148                                        struct smbd_smb2_request);
    134149        DATA_BLOB outbody;
     
    136151        NTSTATUS error; /* transport error */
    137152
     153        if (smb2req->cancelled) {
     154                const uint8_t *inhdr = (const uint8_t *)
     155                        smb2req->in.vector[smb2req->current_idx].iov_base;
     156                uint64_t mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
     157                struct smbd_smb2_lock_state *state;
     158
     159                DEBUG(10,("smbd_smb2_request_lock_done: cancelled mid %llu\n",
     160                        (unsigned long long)mid ));
     161
     162                state = tevent_req_data(smb2req->subreq,
     163                                struct smbd_smb2_lock_state);
     164
     165                SMB_ASSERT(state);
     166                SMB_ASSERT(state->blr);
     167
     168                remove_pending_lock(state, state->blr);
     169
     170                error = smbd_smb2_request_error(smb2req, NT_STATUS_CANCELLED);
     171                if (!NT_STATUS_IS_OK(error)) {
     172                        smbd_server_connection_terminate(smb2req->sconn,
     173                                nt_errstr(error));
     174                        return;
     175                }
     176                return;
     177        }
     178
    138179        status = smbd_smb2_lock_recv(subreq);
    139180        TALLOC_FREE(subreq);
    140181        if (!NT_STATUS_IS_OK(status)) {
    141                 error = smbd_smb2_request_error(req, status);
     182                error = smbd_smb2_request_error(smb2req, status);
    142183                if (!NT_STATUS_IS_OK(error)) {
    143                         smbd_server_connection_terminate(req->sconn,
     184                        smbd_server_connection_terminate(smb2req->sconn,
    144185                                                         nt_errstr(error));
    145186                        return;
     
    148189        }
    149190
    150         outbody = data_blob_talloc(req->out.vector, NULL, 0x04);
     191        outbody = data_blob_talloc(smb2req->out.vector, NULL, 0x04);
    151192        if (outbody.data == NULL) {
    152                 error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
     193                error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
    153194                if (!NT_STATUS_IS_OK(error)) {
    154                         smbd_server_connection_terminate(req->sconn,
     195                        smbd_server_connection_terminate(smb2req->sconn,
    155196                                                         nt_errstr(error));
    156197                        return;
     
    162203        SSVAL(outbody.data, 0x02, 0);           /* reserved */
    163204
    164         error = smbd_smb2_request_done(req, outbody, NULL);
     205        error = smbd_smb2_request_done(smb2req, outbody, NULL);
    165206        if (!NT_STATUS_IS_OK(error)) {
    166                 smbd_server_connection_terminate(req->sconn,
     207                smbd_server_connection_terminate(smb2req->sconn,
    167208                                                 nt_errstr(error));
    168209                return;
    169210        }
    170211}
    171 
    172 struct smbd_smb2_lock_state {
    173         struct smbd_smb2_request *smb2req;
    174 };
    175212
    176213static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx,
     
    184221        struct tevent_req *req;
    185222        struct smbd_smb2_lock_state *state;
    186         struct smb_request *smbreq;
     223        struct smb_request *smb1req;
    187224        connection_struct *conn = smb2req->tcon->compat_conn;
    188225        files_struct *fsp;
     
    195232
    196233        req = tevent_req_create(mem_ctx, &state,
    197                                 struct smbd_smb2_lock_state);
     234                        struct smbd_smb2_lock_state);
    198235        if (req == NULL) {
    199236                return NULL;
    200237        }
    201238        state->smb2req = smb2req;
     239        smb2req->subreq = req; /* So we can find this when going async. */
     240
     241        smb1req = smbd_smb2_fake_smb_request(smb2req);
     242        if (tevent_req_nomem(smb1req, req)) {
     243                return tevent_req_post(req, ev);
     244        }
     245        state->smb1req = smb1req;
    202246
    203247        DEBUG(10,("smbd_smb2_lock_send: file_id[0x%016llX]\n",
    204248                  (unsigned long long)in_file_id_volatile));
    205249
    206         smbreq = smbd_smb2_fake_smb_request(smb2req);
    207         if (tevent_req_nomem(smbreq, req)) {
    208                 return tevent_req_post(req, ev);
    209         }
    210 
    211         fsp = file_fsp(smbreq, (uint16_t)in_file_id_volatile);
     250        fsp = file_fsp(smb1req, (uint16_t)in_file_id_volatile);
    212251        if (fsp == NULL) {
    213252                tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
     
    257296
    258297        for (i=0; i<in_lock_count; i++) {
    259                 uint64_t max_count;
    260298                bool invalid = false;
    261299
     
    263301                case SMB2_LOCK_FLAG_SHARED:
    264302                case SMB2_LOCK_FLAG_EXCLUSIVE:
     303                        if (isunlock) {
     304                                invalid = true;
     305                                break;
     306                        }
    265307                        if (i > 0) {
    266308                                tevent_req_nterror(req,
     
    268310                                return tevent_req_post(req, ev);
    269311                        }
    270                         if (isunlock) {
    271                                 tevent_req_nterror(req,
    272                                                    NT_STATUS_INVALID_PARAMETER);
    273                                 return tevent_req_post(req, ev);
    274                         }
    275312                        break;
    276313
     
    278315                case SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY:
    279316                        if (isunlock) {
    280                                 tevent_req_nterror(req,
    281                                                    NT_STATUS_INVALID_PARAMETER);
    282                                 return tevent_req_post(req, ev);
     317                                invalid = true;
    283318                        }
    284319                        break;
     
    307342                }
    308343
    309                 locks[i].smbpid = in_smbpid;
     344                locks[i].smblctx = in_file_id_volatile;
    310345                locks[i].offset = in_locks[i].offset;
    311346                locks[i].count  = in_locks[i].length;
     
    327362                }
    328363
    329                 max_count = UINT64_MAX - locks[i].offset;
    330                 if (locks[i].count > max_count) {
    331                         tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_RANGE);
    332                         return tevent_req_post(req, ev);
    333                 }
    334         }
     364                DEBUG(10,("smbd_smb2_lock_send: index %d offset=%llu, count=%llu, "
     365                        "smblctx = %llu type %d\n",
     366                        i,
     367                        (unsigned long long)locks[i].offset,
     368                        (unsigned long long)locks[i].count,
     369                        (unsigned long long)locks[i].smblctx,
     370                        (int)locks[i].brltype ));
     371        }
     372
     373        state->locks = locks;
     374        state->lock_count = in_lock_count;
    335375
    336376        if (isunlock) {
    337                 status = smbd_do_locking(smbreq, fsp,
     377                status = smbd_do_locking(smb1req, fsp,
    338378                                         0,
    339379                                         timeout,
     
    344384                                         &async);
    345385        } else {
    346                 status = smbd_do_locking(smbreq, fsp,
     386                status = smbd_do_locking(smb1req, fsp,
    347387                                         0,
    348388                                         timeout,
     
    362402
    363403        if (async) {
    364                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
    365                 return tevent_req_post(req, ev);
     404                return req;
    366405        }
    367406
     
    382421        return NT_STATUS_OK;
    383422}
     423
     424/****************************************************************
     425 Cancel an outstanding blocking lock request.
     426*****************************************************************/
     427
     428static bool smbd_smb2_lock_cancel(struct tevent_req *req)
     429{
     430        struct smbd_smb2_request *smb2req = NULL;
     431        struct smbd_smb2_lock_state *state = tevent_req_data(req,
     432                                struct smbd_smb2_lock_state);
     433        if (!state) {
     434                return false;
     435        }
     436
     437        if (!state->smb2req) {
     438                return false;
     439        }
     440
     441        smb2req = state->smb2req;
     442        smb2req->cancelled = true;
     443
     444        tevent_req_done(req);
     445        return true;
     446}
     447
     448/****************************************************************
     449 Got a message saying someone unlocked a file. Re-schedule all
     450 blocking lock requests as we don't know if anything overlapped.
     451*****************************************************************/
     452
     453static void received_unlock_msg(struct messaging_context *msg,
     454                                void *private_data,
     455                                uint32_t msg_type,
     456                                struct server_id server_id,
     457                                DATA_BLOB *data)
     458{
     459        struct smbd_server_connection *sconn;
     460
     461        DEBUG(10,("received_unlock_msg (SMB2)\n"));
     462
     463        sconn = msg_ctx_to_sconn(msg);
     464        if (sconn == NULL) {
     465                DEBUG(1, ("could not find sconn\n"));
     466                return;
     467        }
     468        process_blocking_lock_queue_smb2(sconn, timeval_current());
     469}
     470
     471/****************************************************************
     472 Function to get the blr on a pending record.
     473*****************************************************************/
     474
     475struct blocking_lock_record *get_pending_smb2req_blr(struct smbd_smb2_request *smb2req)
     476{
     477        struct smbd_smb2_lock_state *state = NULL;
     478        const uint8_t *inhdr;
     479
     480        if (!smb2req) {
     481                return NULL;
     482        }
     483        if (smb2req->subreq == NULL) {
     484                return NULL;
     485        }
     486        if (!tevent_req_is_in_progress(smb2req->subreq)) {
     487                return NULL;
     488        }
     489        inhdr = (const uint8_t *)smb2req->in.vector[smb2req->current_idx].iov_base;
     490        if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_LOCK) {
     491                return NULL;
     492        }
     493        state = tevent_req_data(smb2req->subreq,
     494                        struct smbd_smb2_lock_state);
     495        if (!state) {
     496                return NULL;
     497        }
     498        return state->blr;
     499}
     500/****************************************************************
     501 Set up the next brl timeout.
     502*****************************************************************/
     503
     504static bool recalc_smb2_brl_timeout(struct smbd_server_connection *sconn)
     505{
     506        struct smbd_smb2_request *smb2req;
     507        struct timeval next_timeout = timeval_zero();
     508        int max_brl_timeout = lp_parm_int(-1, "brl", "recalctime", 5);
     509
     510        TALLOC_FREE(sconn->smb2.locks.brl_timeout);
     511
     512        for (smb2req = sconn->smb2.requests; smb2req; smb2req = smb2req->next) {
     513                struct blocking_lock_record *blr =
     514                        get_pending_smb2req_blr(smb2req);
     515                if (!blr) {
     516                        continue;
     517                }
     518                if (timeval_is_zero(&blr->expire_time)) {
     519                        /*
     520                         * If we're blocked on pid 0xFFFFFFFFFFFFFFFFLL this is
     521                         * a POSIX lock, so calculate a timeout of
     522                         * 10 seconds into the future.
     523                         */
     524                        if (blr->blocking_smblctx == 0xFFFFFFFFFFFFFFFFLL) {
     525                                struct timeval psx_to = timeval_current_ofs(10, 0);
     526                                next_timeout = timeval_brl_min(&next_timeout, &psx_to);
     527                        }
     528
     529                        continue;
     530                }
     531
     532                next_timeout = timeval_brl_min(&next_timeout, &blr->expire_time);
     533        }
     534
     535        if (timeval_is_zero(&next_timeout)) {
     536                DEBUG(10, ("recalc_smb2_brl_timeout:Next "
     537                        "timeout = Infinite.\n"));
     538                return true;
     539        }
     540
     541        /*
     542         * To account for unclean shutdowns by clients we need a
     543         * maximum timeout that we use for checking pending locks. If
     544         * we have any pending locks at all, then check if the pending
     545         * lock can continue at least every brl:recalctime seconds
     546         * (default 5 seconds).
     547         *
     548         * This saves us needing to do a message_send_all() in the
     549         * SIGCHLD handler in the parent daemon. That
     550         * message_send_all() caused O(n^2) work to be done when IP
     551         * failovers happened in clustered Samba, which could make the
     552         * entire system unusable for many minutes.
     553         */
     554
     555        if (max_brl_timeout > 0) {
     556                struct timeval min_to = timeval_current_ofs(max_brl_timeout, 0);
     557                next_timeout = timeval_brl_min(&next_timeout, &min_to);
     558        }
     559
     560        if (DEBUGLVL(10)) {
     561                struct timeval cur, from_now;
     562
     563                cur = timeval_current();
     564                from_now = timeval_until(&cur, &next_timeout);
     565                DEBUG(10, ("recalc_smb2_brl_timeout: Next "
     566                        "timeout = %d.%d seconds from now.\n",
     567                        (int)from_now.tv_sec, (int)from_now.tv_usec));
     568        }
     569
     570        sconn->smb2.locks.brl_timeout = event_add_timed(
     571                                smbd_event_context(),
     572                                NULL,
     573                                next_timeout,
     574                                brl_timeout_fn,
     575                                NULL);
     576        if (!sconn->smb2.locks.brl_timeout) {
     577                return false;
     578        }
     579        return true;
     580}
     581
     582/****************************************************************
     583 Get an SMB2 lock reqeust to go async. lock_timeout should
     584 always be -1 here.
     585*****************************************************************/
     586
     587bool push_blocking_lock_request_smb2( struct byte_range_lock *br_lck,
     588                                struct smb_request *smb1req,
     589                                files_struct *fsp,
     590                                int lock_timeout,
     591                                int lock_num,
     592                                uint64_t smblctx,
     593                                enum brl_type lock_type,
     594                                enum brl_flavour lock_flav,
     595                                uint64_t offset,
     596                                uint64_t count,
     597                                uint64_t blocking_smblctx)
     598{
     599        struct smbd_server_connection *sconn = smb1req->sconn;
     600        struct smbd_smb2_request *smb2req = smb1req->smb2req;
     601        struct tevent_req *req = NULL;
     602        struct smbd_smb2_lock_state *state = NULL;
     603        struct blocking_lock_record *blr = NULL;
     604        NTSTATUS status = NT_STATUS_OK;
     605
     606        if (!smb2req) {
     607                return false;
     608        }
     609        req = smb2req->subreq;
     610        if (!req) {
     611                return false;
     612        }
     613        if (!tevent_req_is_in_progress(smb2req->subreq)) {
     614                return false;
     615        }
     616        state = tevent_req_data(req, struct smbd_smb2_lock_state);
     617        if (!state) {
     618                return false;
     619        }
     620
     621        blr = talloc_zero(state, struct blocking_lock_record);
     622        if (!blr) {
     623                return false;
     624        }
     625        blr->fsp = fsp;
     626
     627        if (lock_timeout == -1) {
     628                blr->expire_time.tv_sec = 0;
     629                blr->expire_time.tv_usec = 0; /* Never expire. */
     630        } else {
     631                blr->expire_time = timeval_current_ofs(
     632                        lock_timeout/1000,
     633                        (lock_timeout % 1000) * 1000);
     634        }
     635
     636        blr->lock_num = lock_num;
     637        blr->smblctx = smblctx;
     638        blr->blocking_smblctx = blocking_smblctx;
     639        blr->lock_flav = lock_flav;
     640        blr->lock_type = lock_type;
     641        blr->offset = offset;
     642        blr->count = count;
     643
     644        /* Specific brl_lock() implementations can fill this in. */
     645        blr->blr_private = NULL;
     646
     647        /* Add a pending lock record for this. */
     648        status = brl_lock(sconn->msg_ctx,
     649                        br_lck,
     650                        smblctx,
     651                        sconn_server_id(sconn),
     652                        offset,
     653                        count,
     654                        lock_type == READ_LOCK ? PENDING_READ_LOCK : PENDING_WRITE_LOCK,
     655                        blr->lock_flav,
     656                        true,
     657                        NULL,
     658                        blr);
     659
     660        if (!NT_STATUS_IS_OK(status)) {
     661                DEBUG(0,("push_blocking_lock_request_smb2: "
     662                        "failed to add PENDING_LOCK record.\n"));
     663                TALLOC_FREE(blr);
     664                return false;
     665        }
     666        state->blr = blr;
     667
     668        DEBUG(10,("push_blocking_lock_request_smb2: file %s timeout %d\n",
     669                fsp_str_dbg(fsp),
     670                lock_timeout ));
     671
     672        recalc_smb2_brl_timeout(sconn);
     673
     674        /* Ensure we'll receive messages when this is unlocked. */
     675        if (!sconn->smb2.locks.blocking_lock_unlock_state) {
     676                messaging_register(sconn->msg_ctx, NULL,
     677                                MSG_SMB_UNLOCK, received_unlock_msg);
     678                sconn->smb2.locks.blocking_lock_unlock_state = true;
     679        }
     680
     681        /* allow this request to be canceled */
     682        tevent_req_set_cancel_fn(req, smbd_smb2_lock_cancel);
     683
     684        return true;
     685}
     686
     687/****************************************************************
     688 Remove a pending lock record under lock.
     689*****************************************************************/
     690
     691static void remove_pending_lock(struct smbd_smb2_lock_state *state,
     692                        struct blocking_lock_record *blr)
     693{
     694        int i;
     695        struct byte_range_lock *br_lck = brl_get_locks(
     696                                state, blr->fsp);
     697
     698        DEBUG(10, ("remove_pending_lock: BLR = %p\n", blr));
     699
     700        if (br_lck) {
     701                brl_lock_cancel(br_lck,
     702                                blr->smblctx,
     703                                sconn_server_id(blr->fsp->conn->sconn),
     704                                blr->offset,
     705                                blr->count,
     706                                blr->lock_flav,
     707                                blr);
     708                TALLOC_FREE(br_lck);
     709        }
     710
     711        /* Remove the locks we already got. */
     712
     713        for(i = blr->lock_num - 1; i >= 0; i--) {
     714                struct smbd_lock_element *e = &state->locks[i];
     715
     716                do_unlock(blr->fsp->conn->sconn->msg_ctx,
     717                        blr->fsp,
     718                        e->smblctx,
     719                        e->count,
     720                        e->offset,
     721                        WINDOWS_LOCK);
     722        }
     723}
     724
     725/****************************************************************
     726 Re-proccess a blocking lock request.
     727 This is equivalent to process_lockingX() inside smbd/blocking.c
     728*****************************************************************/
     729
     730static void reprocess_blocked_smb2_lock(struct smbd_smb2_request *smb2req,
     731                                struct timeval tv_curr)
     732{
     733        NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
     734        struct blocking_lock_record *blr = NULL;
     735        struct smbd_smb2_lock_state *state = NULL;
     736        files_struct *fsp = NULL;
     737
     738        if (!smb2req->subreq) {
     739                return;
     740        }
     741        state = tevent_req_data(smb2req->subreq, struct smbd_smb2_lock_state);
     742        if (!state) {
     743                return;
     744        }
     745
     746        blr = state->blr;
     747        fsp = blr->fsp;
     748
     749        /* Try and finish off getting all the outstanding locks. */
     750
     751        for (; blr->lock_num < state->lock_count; blr->lock_num++) {
     752                struct byte_range_lock *br_lck = NULL;
     753                struct smbd_lock_element *e = &state->locks[blr->lock_num];
     754
     755                br_lck = do_lock(fsp->conn->sconn->msg_ctx,
     756                                fsp,
     757                                e->smblctx,
     758                                e->count,
     759                                e->offset,
     760                                e->brltype,
     761                                WINDOWS_LOCK,
     762                                true,
     763                                &status,
     764                                &blr->blocking_smblctx,
     765                                blr);
     766
     767                TALLOC_FREE(br_lck);
     768
     769                if (NT_STATUS_IS_ERR(status)) {
     770                        break;
     771                }
     772        }
     773
     774        if(blr->lock_num == state->lock_count) {
     775                /*
     776                 * Success - we got all the locks.
     777                 */
     778
     779                DEBUG(3,("reprocess_blocked_smb2_lock SUCCESS file = %s, "
     780                        "fnum=%d num_locks=%d\n",
     781                        fsp_str_dbg(fsp),
     782                        fsp->fnum,
     783                        (int)state->lock_count));
     784
     785                tevent_req_done(smb2req->subreq);
     786                return;
     787        }
     788
     789        if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
     790                        !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
     791                /*
     792                 * We have other than a "can't get lock"
     793                 * error. Return an error.
     794                 */
     795                remove_pending_lock(state, blr);
     796                tevent_req_nterror(smb2req->subreq, status);
     797                return;
     798        }
     799
     800        /*
     801         * We couldn't get the locks for this record on the list.
     802         * If the time has expired, return a lock error.
     803         */
     804
     805        if (!timeval_is_zero(&blr->expire_time) &&
     806                        timeval_compare(&blr->expire_time, &tv_curr) <= 0) {
     807                remove_pending_lock(state, blr);
     808                tevent_req_nterror(smb2req->subreq, NT_STATUS_LOCK_NOT_GRANTED);
     809                return;
     810        }
     811
     812        /*
     813         * Still can't get all the locks - keep waiting.
     814         */
     815
     816        DEBUG(10,("reprocess_blocked_smb2_lock: only got %d locks of %d needed "
     817                "for file %s, fnum = %d. Still waiting....\n",
     818                (int)blr->lock_num,
     819                (int)state->lock_count,
     820                fsp_str_dbg(fsp),
     821                (int)fsp->fnum));
     822
     823        return;
     824
     825}
     826
     827/****************************************************************
     828 Attempt to proccess all outstanding blocking locks pending on
     829 the request queue.
     830*****************************************************************/
     831
     832void process_blocking_lock_queue_smb2(
     833        struct smbd_server_connection *sconn, struct timeval tv_curr)
     834{
     835        struct smbd_smb2_request *smb2req, *nextreq;
     836
     837        for (smb2req = sconn->smb2.requests; smb2req; smb2req = nextreq) {
     838                const uint8_t *inhdr;
     839
     840                nextreq = smb2req->next;
     841
     842                if (smb2req->subreq == NULL) {
     843                        /* This message has been processed. */
     844                        continue;
     845                }
     846                if (!tevent_req_is_in_progress(smb2req->subreq)) {
     847                        /* This message has been processed. */
     848                        continue;
     849                }
     850
     851                inhdr = (const uint8_t *)smb2req->in.vector[smb2req->current_idx].iov_base;
     852                if (SVAL(inhdr, SMB2_HDR_OPCODE) == SMB2_OP_LOCK) {
     853                        reprocess_blocked_smb2_lock(smb2req, tv_curr);
     854                }
     855        }
     856
     857        recalc_smb2_brl_timeout(sconn);
     858}
     859
     860/****************************************************************************
     861 Remove any locks on this fd. Called from file_close().
     862****************************************************************************/
     863
     864void cancel_pending_lock_requests_by_fid_smb2(files_struct *fsp,
     865                        struct byte_range_lock *br_lck,
     866                        enum file_close_type close_type)
     867{
     868        struct smbd_server_connection *sconn = fsp->conn->sconn;
     869        struct smbd_smb2_request *smb2req, *nextreq;
     870
     871        for (smb2req = sconn->smb2.requests; smb2req; smb2req = nextreq) {
     872                struct smbd_smb2_lock_state *state = NULL;
     873                files_struct *fsp_curr = NULL;
     874                int i = smb2req->current_idx;
     875                uint64_t in_file_id_volatile;
     876                struct blocking_lock_record *blr = NULL;
     877                const uint8_t *inhdr;
     878                const uint8_t *inbody;
     879
     880                nextreq = smb2req->next;
     881
     882                if (smb2req->subreq == NULL) {
     883                        /* This message has been processed. */
     884                        continue;
     885                }
     886                if (!tevent_req_is_in_progress(smb2req->subreq)) {
     887                        /* This message has been processed. */
     888                        continue;
     889                }
     890
     891                inhdr = (const uint8_t *)smb2req->in.vector[i].iov_base;
     892                if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_LOCK) {
     893                        /* Not a lock call. */
     894                        continue;
     895                }
     896
     897                inbody = (const uint8_t *)smb2req->in.vector[i+1].iov_base;
     898                in_file_id_volatile = BVAL(inbody, 0x10);
     899
     900                state = tevent_req_data(smb2req->subreq,
     901                                struct smbd_smb2_lock_state);
     902                if (!state) {
     903                        /* Strange - is this even possible ? */
     904                        continue;
     905                }
     906
     907                fsp_curr = file_fsp(state->smb1req, (uint16_t)in_file_id_volatile);
     908                if (fsp_curr == NULL) {
     909                        /* Strange - is this even possible ? */
     910                        continue;
     911                }
     912
     913                if (fsp_curr != fsp) {
     914                        /* It's not our fid */
     915                        continue;
     916                }
     917
     918                blr = state->blr;
     919
     920                /* Remove the entries from the lock db. */
     921                brl_lock_cancel(br_lck,
     922                                blr->smblctx,
     923                                sconn_server_id(sconn),
     924                                blr->offset,
     925                                blr->count,
     926                                blr->lock_flav,
     927                                blr);
     928
     929                /* Finally end the request. */
     930                if (close_type == SHUTDOWN_CLOSE) {
     931                        tevent_req_done(smb2req->subreq);
     932                } else {
     933                        tevent_req_nterror(smb2req->subreq,
     934                                NT_STATUS_RANGE_NOT_LOCKED);
     935                }
     936        }
     937}
Note: See TracChangeset for help on using the changeset viewer.