~ubuntu-branches/ubuntu/vivid/openipmi/vivid

« back to all changes in this revision

Viewing changes to lib/sel.c

  • Committer: Bazaar Package Importer
  • Author(s): Noèl Köthe
  • Date: 2006-09-15 17:56:24 UTC
  • mfrom: (1.1.2 upstream) (2.1.1 etch)
  • Revision ID: james.westby@ubuntu.com-20060915175624-ljk0mg3xtcm65tvm
Tags: 2.0.7-1
* new upstream release from 2006-06-08
  Thanks to John Wright <john.wright hp.com> for initial work
  (closes: Bug#380149)
* updated Standards Version
* new binaries openipmicmd, openipmish, rmcp_ping

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
 */
33
33
 
34
34
#include <string.h>
 
35
#include <stdio.h>
35
36
 
36
37
#include <OpenIPMI/ipmiif.h>
37
38
#include <OpenIPMI/ipmi_msgbits.h>
60
61
/* Holds an event in the list of events. */
61
62
typedef struct sel_event_holder_s
62
63
{
63
 
    int          deleted;
 
64
    unsigned int deleted : 1;
 
65
    unsigned int cancelled : 1;
 
66
    unsigned int refcount;
64
67
    ipmi_event_t *event;
65
68
} sel_event_holder_t;
66
69
 
67
 
#define SEL_NAME_LEN (IPMI_DOMAIN_NAME_LEN + 32)
 
70
static sel_event_holder_t *
 
71
sel_event_holder_alloc(void)
 
72
{
 
73
    sel_event_holder_t *holder = ipmi_mem_alloc(sizeof(*holder));
 
74
 
 
75
    if (!holder)
 
76
        return NULL;
 
77
    holder->deleted = 0;
 
78
    holder->cancelled = 0;
 
79
    holder->refcount = 1;
 
80
    holder->event = NULL;
 
81
    return holder;
 
82
}
 
83
 
 
84
static void
 
85
sel_event_holder_get(sel_event_holder_t *holder)
 
86
{
 
87
    holder->refcount++;
 
88
}
 
89
 
 
90
static void
 
91
sel_event_holder_put(sel_event_holder_t *holder)
 
92
{
 
93
    holder->refcount--;
 
94
    if (holder->refcount == 0) {
 
95
        ipmi_event_free(holder->event);
 
96
        ipmi_mem_free(holder);
 
97
    }
 
98
}
 
99
 
 
100
typedef struct sel_clear_req_s
 
101
{
 
102
    ipmi_event_t *last_event;
 
103
    struct sel_clear_req_s *next;
 
104
} sel_clear_req_t;
 
105
 
 
106
#define SEL_NAME_LEN (IPMI_MC_NAME_LEN + 32)
68
107
 
69
108
struct ipmi_sel_info_s
70
109
{
113
152
 
114
153
    /* When fetching the data in event-driven mode, these are the
115
154
       variables that track what is going on. */
116
 
    int                    curr_rec_id;
117
 
    int                    next_rec_id;
 
155
    unsigned int           curr_rec_id;
 
156
    unsigned int           next_rec_id;
118
157
    unsigned int           reservation;
119
158
    int                    sels_changed;
120
 
    int                    fetch_retry_count;
 
159
    unsigned int           fetch_retry_count;
121
160
    sel_fetch_handler_t    *fetch_handlers;
122
161
 
 
162
    /* When we start a fetch, we start with this id.  This is the last
 
163
       one we successfully fetches (or 0 if it is not valid) so we can
 
164
       find the next valid id to fetch. */
 
165
    unsigned int           start_rec_id;
 
166
    unsigned char          start_rec_id_data[14];
 
167
 
123
168
    /* A lock, primarily for handling race conditions fetching the data. */
124
169
    os_hnd_lock_t *sel_lock;
125
170
 
175
220
free_event(ilist_iter_t *iter, void *item, void *cb_data)
176
221
{
177
222
    sel_event_holder_t *holder = item;
178
 
    ipmi_event_free(holder->event);
179
 
    ipmi_mem_free(holder);
 
223
    sel_event_holder_put(holder);
180
224
}
 
225
 
181
226
static void
182
227
free_events(ilist_t *events)
183
228
{
242
287
    ipmi_sel_info_t *sel = NULL;
243
288
    int             rv = 0;
244
289
    ipmi_domain_t   *domain;
 
290
    int             i;
245
291
 
246
292
    CHECK_MC_LOCK(mc);
247
293
 
257
303
    }
258
304
    memset(sel, 0, sizeof(*sel));
259
305
 
260
 
    strncpy(sel->name, _ipmi_mc_name(mc), sizeof(sel->name));
 
306
    i = ipmi_mc_get_name(mc, sel->name, sizeof(sel->name));
 
307
    snprintf(sel->name+i, sizeof(sel->name)-i, "(sel)");
261
308
 
262
309
    sel->events = alloc_ilist();
263
310
    if (!sel->events) {
351
398
 
352
399
    /* We don't have to have a valid ipmi to destroy an SEL, the are
353
400
       designed to live after the ipmi has been destroyed. */
354
 
    sel_unlock(sel);
355
401
 
356
 
    free_events(sel->events);
357
 
    if (sel->events)
 
402
    if (sel->events) {
 
403
        free_events(sel->events);
358
404
        free_ilist(sel->events);
 
405
    }
 
406
    sel_unlock(sel);
359
407
 
360
408
    if (sel->opq)
361
409
        opq_destroy(sel->opq);
427
475
/* This should be called with the sel locked.  It will unlock the sel
428
476
   before returning. */
429
477
static void
430
 
fetch_complete(ipmi_sel_info_t *sel, int err)
 
478
fetch_complete(ipmi_sel_info_t *sel, int err, int do_opq_done)
431
479
{
432
480
    sel_fetch_handler_t *elem, *next;
433
481
    int                 sels_changed;
465
513
        return;
466
514
    }
467
515
 
468
 
    opq_op_done(sel->opq);
 
516
    if (do_opq_done)
 
517
        opq_op_done(sel->opq);
469
518
    return;
470
519
 
471
520
 out:
476
525
free_deleted_event(ilist_iter_t *iter, void *item, void *cb_data)
477
526
{
478
527
    sel_event_holder_t *holder = item;
 
528
    ipmi_sel_info_t    *sel = cb_data;
479
529
 
480
530
    if (holder->deleted) {
481
531
        ilist_delete(iter);
482
 
        ipmi_event_free(holder->event);
483
 
        ipmi_mem_free(holder);
 
532
        holder->cancelled = 1;
 
533
        sel->del_sels--;
 
534
        sel_event_holder_put(holder);
484
535
    }
485
536
}
 
537
 
486
538
static void
487
 
free_deleted_events(ilist_t *events)
 
539
free_deleted_events(ipmi_sel_info_t *sel)
488
540
{
489
 
    ilist_iter(events, free_deleted_event, NULL);
 
541
    ilist_iter(sel->events, free_deleted_event, sel);
490
542
}
491
543
 
492
544
static void
503
555
                 "%ssel.c(handle_sel_clear): "
504
556
                 "SEL info was destroyed while an operation was in"
505
557
                 " progress(1)", sel->name);
506
 
        fetch_complete(sel, ECANCELED);
 
558
        fetch_complete(sel, ECANCELED, 1);
507
559
        goto out;
508
560
    }
509
561
 
512
564
                 "%ssel.c(handle_sel_clear): "
513
565
                 "MC went away while SEL op was in progress",
514
566
                 sel->name);
515
 
        fetch_complete(sel, ECANCELED);
 
567
        fetch_complete(sel, ECANCELED, 1);
516
568
        goto out;
517
569
    }
518
570
 
521
573
            ipmi_domain_stat_add(sel->sel_good_clears, 1);
522
574
 
523
575
        /* Success!  We can free the data. */
524
 
        free_deleted_events(sel->events);
 
576
        free_deleted_events(sel);
525
577
        sel->del_sels = 0;
526
578
    } else if (rsp->data[0] == IPMI_INVALID_RESERVATION_CC) {
527
579
        if (sel->sel_clear_lost_reservation)
531
583
            ipmi_domain_stat_add(sel->sel_clear_errors, 1);
532
584
    }
533
585
 
534
 
    fetch_complete(sel, 0);
 
586
    fetch_complete(sel, 0, 1);
535
587
 out:
536
588
    return;
537
589
}
557
609
                                handle_sel_clear, elem);
558
610
}
559
611
 
560
 
static void start_fetch(void *cb_data, int shutdown);
 
612
static int start_fetch(void *cb_data, int shutdown);
561
613
 
562
614
static void
563
615
handle_sel_data(ipmi_mc_t  *mc,
582
634
                 "%ssel.c(handle_sel_data): "
583
635
                 "SEL info was destroyed while an operation was in"
584
636
                 " progress(2)", sel->name);
585
 
        fetch_complete(sel, ECANCELED);
 
637
        fetch_complete(sel, ECANCELED, 1);
586
638
        goto out;
587
639
    }
588
640
 
591
643
                 "%ssel.c(handle_sel_data): "
592
644
                 "handle_sel_data: MC went away while SEL op was in progress",
593
645
                 sel->name);
594
 
        fetch_complete(sel, ECANCELED);
 
646
        fetch_complete(sel, ECANCELED, 1);
595
647
        goto out;
596
648
    }
597
649
        
613
665
                     "%ssel.c(handle_sel_data): "
614
666
                     "Too many lost reservations in SEL fetch",
615
667
                     sel->name);
616
 
            fetch_complete(sel, EAGAIN);
 
668
            fetch_complete(sel, EAGAIN, 1);
617
669
            goto out;
618
670
        } else {
 
671
            sel_unlock(sel);
619
672
            start_fetch(elem, 0);
620
 
            goto out_unlock;
 
673
            goto out;
621
674
        }
622
675
    }
623
 
    if (rsp->data[0] != 0) {
624
 
        if (sel->curr_rec_id != 0) {
 
676
    if ((rsp->data[0] == 0) && (rsp->data_len < 19)) {
 
677
        ipmi_log(IPMI_LOG_ERR_INFO,
 
678
                 "%ssel.c(handle_sel_data): "
 
679
                 "Received a short SEL data message",
 
680
                 sel->name);
 
681
        fetch_complete(sel, EINVAL, 1);
 
682
        goto out;
 
683
    }
 
684
 
 
685
    if ((rsp->data[0] != 0)
 
686
        || ((sel->start_rec_id != 0) && (sel->start_rec_id == sel->curr_rec_id)
 
687
            && (memcmp(sel->start_rec_id_data, rsp->data+5, 14) != 0)))
 
688
    {
 
689
        /* We got an error fetching the current id, or the current
 
690
           id's data was for our "start" record and it doesn't match
 
691
           the one we fetched, so it has changed.  We have to start
 
692
           over or handle the error. */
 
693
        if (sel->start_rec_id != 0) {
625
694
            /* If we get a fetch error and it is not a lost
626
695
               reservation, it may be that another system deleted our
627
696
               "current" record.  Start over from the beginning of the
628
697
               SEL. */
 
698
            sel->start_rec_id = 0;
629
699
            sel->curr_rec_id = 0;
630
700
            del_event = NULL;
631
701
            goto start_request_sel_data;
636
706
                 "%ssel.c(handle_sel_data): "
637
707
                 "IPMI error from SEL fetch: %x",
638
708
                 sel->name, rsp->data[0]);
639
 
        fetch_complete(sel, IPMI_IPMI_ERR_VAL(rsp->data[0]));
 
709
        fetch_complete(sel, IPMI_IPMI_ERR_VAL(rsp->data[0]), 1);
640
710
        goto out;
641
711
    }
642
712
 
659
729
                 "%ssel.c(handle_sel_data): "
660
730
                 "Could not allocate event for SEL",
661
731
                 sel->name);
662
 
        fetch_complete(sel, ENOMEM);
 
732
        fetch_complete(sel, ENOMEM, 1);
663
733
        goto out;
664
734
    }
665
735
 
668
738
 
669
739
    holder = find_event(sel->events, record_id);
670
740
    if (!holder) {
671
 
        holder = ipmi_mem_alloc(sizeof(*holder));
 
741
        holder = sel_event_holder_alloc();
672
742
        if (!holder) {
673
743
            ipmi_log(IPMI_LOG_ERR_INFO,
674
744
                     "%ssel.c(handle_sel_data): "
675
745
                     "Could not allocate log information for SEL",
676
746
                     sel->name);
677
 
            fetch_complete(sel, ENOMEM);
 
747
            fetch_complete(sel, ENOMEM, 1);
678
748
            goto out;
679
749
        }
680
750
        if (!ilist_add_tail(sel->events, holder, NULL)) {
683
753
                     "%ssel.c(handle_sel_data): "
684
754
                     "Could not link log onto the log linked list",
685
755
                     sel->name);
686
 
            fetch_complete(sel, ENOMEM);
 
756
            fetch_complete(sel, ENOMEM, 1);
687
757
            goto out;
688
758
        }
689
759
        holder->event = del_event;
719
789
 
720
790
        /* To avoid confusion, deliver the event before we deliver fetch
721
791
           complete. */
722
 
        if (event_is_new && sel->new_event_handler)
723
 
            sel->new_event_handler(sel,
724
 
                                   mc,
725
 
                                   del_event,
726
 
                                   sel->new_event_cb_data);
 
792
        if (event_is_new && sel->new_event_handler) {
 
793
            ipmi_sel_new_event_handler_cb handler = sel->new_event_handler;
 
794
            void                          *cb_data = sel->new_event_cb_data;
 
795
            sel_unlock(sel);
 
796
            handler(sel, mc, del_event, cb_data);
 
797
            sel_lock(sel);
 
798
        }
727
799
 
728
800
        if (sel->sel_good_scans)
729
801
            ipmi_domain_stat_add(sel->sel_good_scans, 1);
739
811
               happen again later if it does. */
740
812
            rv = send_sel_clear(elem, mc);
741
813
            if (rv) {
742
 
                fetch_complete(sel, 0);
 
814
                fetch_complete(sel, 0, 1);
743
815
                goto out;
744
816
            }
745
817
            rv = 0;
746
818
            goto out_unlock;
747
819
        } else {
748
 
            fetch_complete(sel, 0);
 
820
            fetch_complete(sel, 0, 1);
749
821
            goto out;
750
822
        }
751
823
    }
 
824
    sel->start_rec_id = sel->curr_rec_id;
 
825
    memcpy(sel->start_rec_id_data, rsp->data+5, 14);
752
826
    sel->curr_rec_id = sel->next_rec_id;
753
827
 
754
828
 start_request_sel_data:
766
840
        ipmi_log(IPMI_LOG_ERR_INFO,
767
841
                 "%ssel.c(handle_sel_clear): "
768
842
                 "Could not send SEL fetch command: %x", sel->name, rv);
769
 
        fetch_complete(sel, rv);
 
843
        fetch_complete(sel, rv, 1);
770
844
        goto out;
771
845
    }
772
846
 
773
 
    if (event_is_new && sel->new_event_handler)
774
 
        sel->new_event_handler(sel, mc, del_event, sel->new_event_cb_data);
 
847
    if (event_is_new && sel->new_event_handler) {
 
848
        ipmi_sel_new_event_handler_cb handler = sel->new_event_handler;
 
849
        void                          *cb_data = sel->new_event_cb_data;
 
850
        sel_unlock(sel);
 
851
        handler(sel, mc, del_event, cb_data);
 
852
        sel_lock(sel);
 
853
    }
775
854
 out_unlock:
776
855
    sel_unlock(sel);
777
856
 out:
802
881
    unsigned char       cmd_data[MAX_IPMI_DATA_SIZE];
803
882
    ipmi_msg_t          cmd_msg;
804
883
    int                 rv;
805
 
    int32_t             add_timestamp;
806
 
    int32_t             erase_timestamp;
 
884
    uint32_t            add_timestamp;
 
885
    uint32_t            erase_timestamp;
807
886
    int                 fetched_num_sels;
808
887
 
809
888
    sel_lock(sel);
812
891
                 "%ssel.c(handle_sel_info): "
813
892
                 "SEL info was destroyed while an operation was in progress",
814
893
                 sel->name);
815
 
        fetch_complete(sel, ECANCELED);
 
894
        fetch_complete(sel, ECANCELED, 1);
816
895
        goto out;
817
896
    }
818
897
 
821
900
                 "%ssel.c(handle_sel_info): "
822
901
                 "MC went away while SEL op was in progress",
823
902
                 sel->name);
824
 
        fetch_complete(sel, ECANCELED);
 
903
        fetch_complete(sel, ECANCELED, 1);
825
904
        goto out;
826
905
    }
827
906
        
832
911
                 "%ssel.c(handle_sel_info): "
833
912
                 "IPMI error from SEL info fetch: %x",
834
913
                 sel->name, rsp->data[0]);
835
 
        fetch_complete(sel, IPMI_IPMI_ERR_VAL(rsp->data[0]));
 
914
        fetch_complete(sel, IPMI_IPMI_ERR_VAL(rsp->data[0]), 1);
836
915
        goto out;
837
916
    }
838
917
 
841
920
            ipmi_domain_stat_add(sel->sel_fetch_errors, 1);
842
921
        ipmi_log(IPMI_LOG_ERR_INFO,
843
922
                 "%ssel.c(handle_sel_info): SEL info too short", sel->name);
844
 
        fetch_complete(sel, EINVAL);
 
923
        fetch_complete(sel, EINVAL, 1);
845
924
        goto out;
846
925
    }
847
926
 
862
941
 
863
942
    sel_fixups(mc, sel);
864
943
 
865
 
    /* If the timestamps still match, no need to re-fetch the repository */
866
 
    if (sel->fetched
867
 
        && (add_timestamp == sel->last_addition_timestamp)
868
 
        && (erase_timestamp == sel->last_erase_timestamp))
869
 
    {
 
944
    /* If the timestamps still match, no need to re-fetch the
 
945
       repository.  Note that we only check the add timestamp.  We
 
946
       don't care if things were deleted. */
 
947
    if (sel->fetched && (add_timestamp == sel->last_addition_timestamp)) {
870
948
        /* If the operation completed successfully and everything in
871
949
           our SEL is deleted, then clear it with our old reservation.
872
950
           We also do the clear if the overflow flag is set; on some
878
956
               happen again later if it does. */
879
957
            rv = send_sel_clear(elem, mc);
880
958
            if (rv) {
881
 
                fetch_complete(sel, 0);
 
959
                fetch_complete(sel, 0, 1);
882
960
                goto out;
883
961
            }
884
962
            goto out_unlock;
885
963
        } else {
886
 
            fetch_complete(sel, 0);
 
964
            fetch_complete(sel, 0, 1);
887
965
            goto out;
888
966
        }
889
967
    }
890
968
 
891
 
    /* Note that we only re-fetch from the beginning if the SEL is
892
 
       erased.  The SEL is supposed to be ordered and only have new
893
 
       records added onto the end.  So we can re-fetch from the last
894
 
       added one to get the next event properly.  Unless, of course,
895
 
       the SEL was erased. */
896
 
    if (sel->last_erase_timestamp != erase_timestamp) {
897
 
        sel->curr_rec_id = 0;
898
 
    }
899
 
 
900
969
    sel->curr_addition_timestamp = add_timestamp;
901
970
    sel->curr_erase_timestamp = erase_timestamp;
902
971
 
910
979
           there was nothing to do. */
911
980
        sel->last_addition_timestamp = sel->curr_addition_timestamp;
912
981
        sel->last_erase_timestamp = sel->curr_erase_timestamp;
 
982
        sel->start_rec_id = 0;
 
983
        sel->curr_rec_id = 0;
913
984
 
914
 
        fetch_complete(sel, 0);
 
985
        fetch_complete(sel, 0, 1);
915
986
        goto out;
916
987
    }
917
988
 
918
989
    /* Fetch the first SEL entry. */
 
990
    sel->curr_rec_id = sel->start_rec_id;
919
991
    cmd_msg.data = cmd_data;
920
992
    cmd_msg.netfn = IPMI_STORAGE_NETFN;
921
993
    cmd_msg.cmd = IPMI_GET_SEL_ENTRY_CMD;
930
1002
                 "%ssel.c(handle_sel_info): "
931
1003
                 "Could not send first SEL fetch command: %x",
932
1004
                 sel->name, rv);
933
 
        fetch_complete(sel, rv);
 
1005
        fetch_complete(sel, rv, 1);
934
1006
        goto out;
935
1007
    }
936
1008
 out_unlock:
939
1011
    return;
940
1012
}
941
1013
 
 
1014
static int
 
1015
send_get_sel_info(sel_fetch_handler_t *elem, ipmi_mc_t *mc)
 
1016
{
 
1017
    ipmi_sel_info_t *sel = elem->sel;
 
1018
    ipmi_msg_t      cmd_msg;
 
1019
 
 
1020
    /* Fetch the repository info. */
 
1021
    cmd_msg.netfn = IPMI_STORAGE_NETFN;
 
1022
    cmd_msg.cmd = IPMI_GET_SEL_INFO_CMD;
 
1023
    cmd_msg.data = NULL;
 
1024
    cmd_msg.data_len = 0;
 
1025
    return ipmi_mc_send_command(mc, sel->lun, &cmd_msg, handle_sel_info, elem);
 
1026
}
 
1027
 
942
1028
static void
943
1029
sel_handle_reservation(ipmi_mc_t  *mc,
944
1030
                       ipmi_msg_t *rsp,
946
1032
{
947
1033
    sel_fetch_handler_t *elem = rsp_data;
948
1034
    ipmi_sel_info_t     *sel = elem->sel;
949
 
    unsigned char       cmd_data[MAX_IPMI_DATA_SIZE];
950
 
    ipmi_msg_t          cmd_msg;
951
1035
    int                 rv;
952
1036
 
953
1037
    sel_lock(sel);
956
1040
                 "%ssel.c(sel_handle_reservation): "
957
1041
                 "SEL info was destroyed while an operation was in progress",
958
1042
                 sel->name);
959
 
        fetch_complete(sel, ECANCELED);
 
1043
        fetch_complete(sel, ECANCELED, 1);
960
1044
        goto out;
961
1045
    }
962
1046
 
965
1049
                 "%ssel.c(sel_handle_reservation): "
966
1050
                 "MC went away while SEL op was in progress",
967
1051
                 sel->name);
968
 
        fetch_complete(sel, ECANCELED);
 
1052
        fetch_complete(sel, ECANCELED, 1);
969
1053
        goto out;
970
1054
    }
971
1055
        
975
1059
        ipmi_log(IPMI_LOG_ERR_INFO,
976
1060
                 "%ssel.c(sel_handle_reservation): "
977
1061
                 "Failed getting reservation", sel->name);
978
 
        fetch_complete(sel, ENOSYS);
 
1062
        fetch_complete(sel, ENOSYS, 1);
979
1063
        goto out;
980
1064
    } else if (rsp->data_len < 3) {
981
1065
        if (sel->sel_fetch_errors)
983
1067
        ipmi_log(IPMI_LOG_ERR_INFO,
984
1068
                 "%ssel.c(sel_handle_reservation): "
985
1069
                 "got invalid reservation length", sel->name);
986
 
        fetch_complete(sel, EINVAL);
 
1070
        fetch_complete(sel, EINVAL, 1);
987
1071
        goto out;
988
1072
    }
989
1073
 
990
1074
    sel->reservation = ipmi_get_uint16(rsp->data+1);
991
1075
 
992
 
    /* Fetch the repository info. */
993
 
    cmd_msg.data = cmd_data;
994
 
    cmd_msg.netfn = IPMI_STORAGE_NETFN;
995
 
    cmd_msg.cmd = IPMI_GET_SEL_INFO_CMD;
996
 
    cmd_msg.data_len = 0;
997
 
    rv = ipmi_mc_send_command(mc, sel->lun, &cmd_msg, handle_sel_info, elem);
 
1076
    rv = send_get_sel_info(elem, mc);
998
1077
    if (rv) {
999
1078
        ipmi_log(IPMI_LOG_ERR_INFO,
1000
1079
                 "%ssel.c(sel_handle_reservation): "
1001
1080
                 "Could not send SEL info command: %x", sel->name, rv);
1002
 
        fetch_complete(sel, rv);
 
1081
        fetch_complete(sel, rv, 1);
1003
1082
        goto out;
1004
1083
    }
1005
1084
    sel_unlock(sel);
1016
1095
    ipmi_msg_t          cmd_msg;
1017
1096
    int                 rv;
1018
1097
 
1019
 
    sel_lock(sel);
1020
1098
    if (sel->destroyed) {
1021
1099
        ipmi_log(IPMI_LOG_ERR_INFO,
1022
1100
                 "%ssel.c(start_fetch_cb): "
1023
1101
                 "SEL info was destroyed while an operation was in progress",
1024
1102
                 sel->name);
1025
 
        fetch_complete(sel, ECANCELED);
 
1103
        elem->rv = ECANCELED;
1026
1104
        goto out;
1027
1105
    }
1028
1106
 
1051
1129
        ipmi_log(IPMI_LOG_ERR_INFO,
1052
1130
                 "%ssel.c(start_fetch_cb): could not send cmd: %x",
1053
1131
                 sel->name, rv);
1054
 
        fetch_complete(sel, ECANCELED);
 
1132
        elem->rv = rv;
1055
1133
        goto out;
1056
1134
    }
1057
1135
 
1058
 
    sel_unlock(sel);
1059
1136
 out:
1060
1137
    return;
1061
1138
}
1062
1139
 
1063
 
static void
 
1140
static int
1064
1141
start_fetch(void *cb_data, int shutdown)
1065
1142
{
1066
1143
    sel_fetch_handler_t *elem = cb_data;
1067
1144
    int                 rv;
1068
1145
 
 
1146
    sel_lock(elem->sel);
1069
1147
    if (shutdown) {
1070
1148
        ipmi_log(IPMI_LOG_ERR_INFO,
1071
1149
                 "%ssel.c(start_fetch): "
1072
1150
                 "SEL info was destroyed while an operation was in progress",
1073
1151
                 elem->sel->name);
1074
 
        sel_lock(elem->sel);
1075
 
        fetch_complete(elem->sel, ECANCELED);
1076
 
        return;
 
1152
        fetch_complete(elem->sel, ECANCELED, 0);
 
1153
        return OPQ_HANDLER_ABORTED;
1077
1154
    }
1078
1155
 
1079
1156
    /* The read lock must be claimed before the sel lock to avoid
1080
1157
       deadlock. */
1081
1158
    rv = ipmi_mc_pointer_cb(elem->sel->mc, start_fetch_cb, elem);
1082
 
    if (rv) {
 
1159
    if (rv)
1083
1160
        ipmi_log(IPMI_LOG_ERR_INFO,
1084
1161
                 "%ssel.c(start_fetch): MC is not valid", elem->sel->name);
1085
 
        sel_lock(elem->sel);
1086
 
        fetch_complete(elem->sel, rv);
 
1162
    else
 
1163
        rv = elem->rv;
 
1164
 
 
1165
    if (rv) {
 
1166
        fetch_complete(elem->sel, rv, 0);
 
1167
        return OPQ_HANDLER_ABORTED;
1087
1168
    }
 
1169
 
 
1170
    sel_unlock(elem->sel);
 
1171
 
 
1172
    return OPQ_HANDLER_STARTED;
1088
1173
}
1089
1174
 
1090
1175
/* We have to have this because the allocate element can go away (the
1122
1207
        elem->next = NULL;
1123
1208
        sel->fetch_handlers = elem;
1124
1209
        sel_unlock(sel);
1125
 
        if (!opq_new_op(sel->opq, start_fetch, elem, 0)) {
 
1210
        /* Always put a fetch ahead of everything else.  If there are
 
1211
           deletes in progress and a clear gets done, we can complete
 
1212
           all the deletes. */
 
1213
        if (!opq_new_op_prio(sel->opq, start_fetch, elem, 0, OPQ_ADD_HEAD,
 
1214
                            NULL))
 
1215
        {
1126
1216
            sel->fetch_handlers = NULL;
1127
1217
            info->rv = ENOMEM;
1128
1218
        }
1133
1223
        elem->next = sel->fetch_handlers;
1134
1224
        sel->fetch_handlers = elem;
1135
1225
    } else {
 
1226
        /* No handler and fetch was already in progress.  Return an
 
1227
           error so the caller knows what happened. */
1136
1228
        info->rv = EEXIST;
1137
1229
    }
1138
1230
 
1182
1274
/* Don't do this forever. */
1183
1275
#define MAX_DEL_RESERVE_RETRIES         10
1184
1276
 
1185
 
typedef struct sel_cb_handler_data_s
 
1277
typedef struct sel_del_handler_data_s
1186
1278
{
1187
1279
    ipmi_sel_info_t       *sel;
1188
1280
    ipmi_sel_op_done_cb_t handler;
1192
1284
    unsigned int          lun;
1193
1285
    unsigned int          count;
1194
1286
    ipmi_event_t          *event;
1195
 
} sel_cb_handler_data_t;
1196
 
 
1197
 
static int send_reserve_sel_for_delete(sel_cb_handler_data_t *data,
 
1287
    sel_event_holder_t    *holder;
 
1288
 
 
1289
    /* If true, we do a clear operation if the given record is the
 
1290
       last record in the SEL. */
 
1291
    int                   do_clear;
 
1292
} sel_del_handler_data_t;
 
1293
 
 
1294
static int send_reserve_sel_for_delete(sel_del_handler_data_t *data,
1198
1295
                                       ipmi_mc_t *mc);
1199
1296
 
1200
1297
static void
1201
 
sel_op_done(sel_cb_handler_data_t *data,
1202
 
            int                   rv)
 
1298
sel_op_done(sel_del_handler_data_t *data,
 
1299
            int                    rv,
 
1300
            int                    do_op_done)
1203
1301
{
1204
1302
    ipmi_sel_info_t *sel = data->sel;
1205
1303
 
 
1304
    if (data->holder)
 
1305
        sel_event_holder_put(data->holder);
 
1306
 
 
1307
    sel_unlock(sel);
 
1308
 
1206
1309
    if (data->handler)
1207
1310
        data->handler(sel, data->cb_data, rv);
1208
1311
 
 
1312
    sel_lock(sel);
 
1313
 
1209
1314
    if (sel->in_destroy) {
1210
1315
        /* Nothing to do */
1211
1316
        sel_unlock(sel);
1214
1319
        internal_destroy_sel(sel);
1215
1320
    } else {
1216
1321
        sel_unlock(sel);
1217
 
        opq_op_done(sel->opq);
 
1322
        if (do_op_done)
 
1323
            opq_op_done(sel->opq);
1218
1324
    }
1219
1325
    if (data->event)
1220
1326
        ipmi_event_free(data->event);
1222
1328
}
1223
1329
 
1224
1330
static void
 
1331
free_all_event(ilist_iter_t *iter, void *item, void *cb_data)
 
1332
{
 
1333
    sel_event_holder_t *holder = item;
 
1334
    ipmi_sel_info_t    *sel = cb_data;
 
1335
 
 
1336
    if (holder->deleted) {
 
1337
        sel->del_sels--;
 
1338
        holder->cancelled = 1;
 
1339
    }
 
1340
    ilist_delete(iter);
 
1341
    sel_event_holder_put(holder);
 
1342
}
 
1343
 
 
1344
static void
 
1345
free_all_events(ipmi_sel_info_t *sel)
 
1346
{
 
1347
    ilist_iter(sel->events, free_all_event, sel);
 
1348
}
 
1349
 
 
1350
static void
 
1351
handle_del_sel_clear(ipmi_mc_t  *mc,
 
1352
                     ipmi_msg_t *rsp,
 
1353
                     void       *rsp_data)
 
1354
{
 
1355
    sel_del_handler_data_t *data = rsp_data;
 
1356
    ipmi_sel_info_t        *sel = data->sel;
 
1357
 
 
1358
    sel_lock(sel);
 
1359
    if (sel->destroyed) {
 
1360
        ipmi_log(IPMI_LOG_ERR_INFO,
 
1361
                 "%ssel.c(handle_del_sel_clear): "
 
1362
                 "SEL info was destroyed while an operation was in progress",
 
1363
                 sel->name);
 
1364
        sel_op_done(data, ECANCELED, 1);
 
1365
        goto out;
 
1366
    }
 
1367
 
 
1368
    if (!mc) {
 
1369
        ipmi_log(IPMI_LOG_ERR_INFO,
 
1370
                 "%ssel.c(handle_del_sel_clear): "
 
1371
                 "MC went away while SEL fetch was in progress",
 
1372
                 sel->name);
 
1373
        sel_op_done(data, ECANCELED, 1);
 
1374
        goto out;
 
1375
    }
 
1376
 
 
1377
    if (rsp->data[0]) {
 
1378
        ipmi_log(IPMI_LOG_ERR_INFO,
 
1379
                 "%ssel.c(handle_del_sel_clear): "
 
1380
                 "IPMI error clearing SEL: 0x%x",
 
1381
                 sel->name, rsp->data[0]);
 
1382
        sel_op_done(data, IPMI_IPMI_ERR_VAL(rsp->data[0]), 1);
 
1383
        goto out;
 
1384
    }
 
1385
 
 
1386
    free_all_events(sel);
 
1387
    sel->num_sels = 0;
 
1388
 
 
1389
    sel_op_done(data, 0, 1);
 
1390
 
 
1391
 out:
 
1392
    return;
 
1393
}
 
1394
 
 
1395
static int
 
1396
send_del_clear(sel_del_handler_data_t *data, ipmi_mc_t *mc)
 
1397
{
 
1398
    ipmi_sel_info_t *sel = data->sel;
 
1399
    unsigned char   cmd_data[MAX_IPMI_DATA_SIZE];
 
1400
    ipmi_msg_t      cmd_msg;
 
1401
 
 
1402
    cmd_msg.data = cmd_data;
 
1403
    cmd_msg.netfn = IPMI_STORAGE_NETFN;
 
1404
    cmd_msg.cmd = IPMI_CLEAR_SEL_CMD;
 
1405
    cmd_msg.data_len = 6;
 
1406
    ipmi_set_uint16(cmd_msg.data, data->reservation);
 
1407
    cmd_msg.data[2] = 'C';
 
1408
    cmd_msg.data[3] = 'L';
 
1409
    cmd_msg.data[4] = 'R';
 
1410
    cmd_msg.data[5] = 0xaa;
 
1411
 
 
1412
    return ipmi_mc_send_command(mc, sel->lun, &cmd_msg,
 
1413
                                handle_del_sel_clear, data);
 
1414
}
 
1415
 
 
1416
static void
1225
1417
handle_sel_delete(ipmi_mc_t  *mc,
1226
1418
                  ipmi_msg_t *rsp,
1227
1419
                  void       *rsp_data)
1228
1420
{
1229
 
    sel_cb_handler_data_t *data = (sel_cb_handler_data_t *) rsp_data;
1230
 
    ipmi_sel_info_t       *sel = data->sel;
1231
 
    int                   rv = 0;
 
1421
    sel_del_handler_data_t *data = rsp_data;
 
1422
    ipmi_sel_info_t        *sel = data->sel;
 
1423
    int                    rv = 0;
1232
1424
    
1233
1425
    sel_lock(sel);
1234
1426
    if (sel->destroyed) {
1236
1428
                 "%ssel.c(handle_sel_delete): "
1237
1429
                 "SEL info was destroyed while an operation was in progress",
1238
1430
                 sel->name);
1239
 
        sel_op_done(data, ECANCELED);
 
1431
        sel_op_done(data, ECANCELED, 1);
1240
1432
        goto out;
1241
1433
    }
1242
1434
 
1245
1437
                 "%ssel.c(handle_sel_delete): "
1246
1438
                 "MC went away while SEL fetch was in progress",
1247
1439
                 sel->name);
1248
 
        sel_op_done(data, ECANCELED);
 
1440
        sel_op_done(data, ECANCELED, 1);
1249
1441
        goto out;
1250
1442
    }
1251
1443
 
1285
1477
                 "%ssel.c(handle_sel_delete): "
1286
1478
                 "IPMI error from SEL delete: %x", sel->name, rsp->data[0]);
1287
1479
        rv = IPMI_IPMI_ERR_VAL(rsp->data[0]);
1288
 
    } else {
 
1480
    } else {    
1289
1481
        /* We deleted the entry, so remove it from our database. */
1290
1482
        sel_event_holder_t *real_holder;
1291
1483
        ilist_iter_t       iter;
1296
1488
                                        &(data->record_id));
1297
1489
        if (real_holder) {
1298
1490
            ilist_delete(&iter);
1299
 
            ipmi_event_free(real_holder->event);
1300
 
            ipmi_mem_free(real_holder);
 
1491
            sel_event_holder_put(real_holder);
1301
1492
            sel->del_sels--;
1302
1493
        }
1303
1494
    }
1304
1495
 
1305
 
    sel_op_done(data, rv);
 
1496
    sel_op_done(data, rv, 1);
1306
1497
 
1307
1498
 out:
1308
1499
    return;
1312
1503
}
1313
1504
 
1314
1505
static int
1315
 
send_del_sel(sel_cb_handler_data_t *data, ipmi_mc_t *mc)
 
1506
send_del_sel(sel_del_handler_data_t *data, ipmi_mc_t *mc)
1316
1507
{
1317
1508
    unsigned char   cmd_data[MAX_IPMI_DATA_SIZE];
1318
1509
    ipmi_msg_t      cmd_msg;
1335
1526
                 ipmi_msg_t *rsp,
1336
1527
                 void       *rsp_data)
1337
1528
{
1338
 
    sel_cb_handler_data_t *data = (sel_cb_handler_data_t *) rsp_data;
1339
 
    ipmi_sel_info_t       *sel = data->sel;
1340
 
    int                   rv = 0;
 
1529
    sel_del_handler_data_t *data = rsp_data;
 
1530
    ipmi_sel_info_t        *sel = data->sel;
 
1531
    int                    rv = 0;
1341
1532
    
1342
1533
    sel_lock(sel);
1343
1534
    if (sel->destroyed) {
1344
1535
        ipmi_log(IPMI_LOG_ERR_INFO,
1345
1536
                 "%ssel.c(handle_sel_check): "
1346
 
                 "SEL info was destroyed while an operation was in progress",
 
1537
                 "SEL info was destroyed while SEL delete element was in"
 
1538
                 " progress",
1347
1539
                 sel->name);
1348
 
        sel_op_done(data, ECANCELED);
 
1540
        sel_op_done(data, ECANCELED, 1);
1349
1541
        goto out;
1350
1542
    }
1351
1543
 
1352
1544
    if (!mc) {
1353
1545
        ipmi_log(IPMI_LOG_ERR_INFO,
1354
1546
                 "%ssel.c(handle_sel_check): "
1355
 
                 "MC went away while SEL fetch was in progress",
 
1547
                 "MC went away while SEL delete element was in progress",
1356
1548
                 sel->name);
1357
 
        sel_op_done(data, ECANCELED);
 
1549
        sel_op_done(data, ECANCELED, 1);
1358
1550
        goto out;
1359
1551
    }
1360
1552
 
1361
1553
    /* Special return codes. */
1362
1554
    if (rsp->data[0] == IPMI_NOT_PRESENT_CC) {
1363
1555
        /* The entry is already gone, so just return no error. */
1364
 
        sel_op_done(data, 0);
 
1556
        sel_op_done(data, 0, 1);
1365
1557
        goto out;
1366
1558
    } else if (rsp->data[0]) {
1367
1559
        if (sel->sel_delete_errors)
1368
1560
            ipmi_domain_stat_add(sel->sel_delete_errors, 1);
1369
1561
        ipmi_log(IPMI_LOG_ERR_INFO,
1370
 
                 "%ssel.c(handle_sel_check): IPMI error from SEL get: %x",
 
1562
                 "%ssel.c(handle_sel_check): IPMI error from SEL check: %x",
1371
1563
                 sel->name, rsp->data[0]);
1372
 
        sel_op_done(data, IPMI_IPMI_ERR_VAL(rsp->data[0]));
 
1564
        sel_op_done(data, IPMI_IPMI_ERR_VAL(rsp->data[0]), 1);
1373
1565
        goto out;
1374
1566
    } else {
1375
1567
        ipmi_event_t *ch_event;
1389
1581
            ipmi_log(IPMI_LOG_ERR_INFO,
1390
1582
                     "%ssel.c(handle_sel_check): Could not allocate memory",
1391
1583
                     sel->name);
1392
 
            sel_op_done(data, ENOMEM);
 
1584
            sel_op_done(data, ENOMEM, 1);
1393
1585
            goto out;
1394
1586
        }
1395
1587
 
1396
 
        if (event_cmp(ch_event, data->event) != 0) {
 
1588
        if (data->event && (event_cmp(ch_event, data->event) != 0)) {
1397
1589
            /* The event's don't match, so just finish. */
1398
1590
            ipmi_event_free(ch_event);
1399
 
            sel_op_done(data, 0);
 
1591
            sel_op_done(data, 0, 1);
1400
1592
            goto out;
1401
1593
        }
1402
1594
        ipmi_event_free(ch_event);
1403
1595
 
1404
 
        rv = send_del_sel(data, mc);
1405
 
        if (rv) {
1406
 
            ipmi_log(IPMI_LOG_ERR_INFO,
1407
 
                     "%ssel.c(handle_sel_check): "
1408
 
                     "Could not send SEL delete command: %x",
1409
 
                     sel->name, rv);
1410
 
            sel_op_done(data, rv);
1411
 
            goto out;
1412
 
        } else if (data->record_id == sel->curr_rec_id)
1413
 
            /* We are deleting our "current" record (used for finding
1414
 
               the next record), make sure we start again from
1415
 
               scratch on the next fetch. */
1416
 
            sel->curr_rec_id = 0;
 
1596
        if (data->do_clear) {
 
1597
            /* Make sure that there is no next event. */
 
1598
            uint16_t next_ev = ipmi_get_uint16(rsp->data+1);
 
1599
 
 
1600
            if (next_ev != 0xffff) {
 
1601
                /* A new event was added after this one.  Fail the op. */
 
1602
                ipmi_log(IPMI_LOG_ERR_INFO,
 
1603
                         "%ssel.c(handle_sel_check): "
 
1604
                         "Clear SEL failed, new events in SEL",
 
1605
                         sel->name);
 
1606
                sel_op_done(data, EAGAIN, 1);
 
1607
                goto out;
 
1608
            }
 
1609
 
 
1610
            rv = send_del_clear(data, mc);
 
1611
            if (rv) {
 
1612
                ipmi_log(IPMI_LOG_ERR_INFO,
 
1613
                         "%ssel.c(handle_sel_check): "
 
1614
                         "Could not send SEL clear command: %x",
 
1615
                         sel->name, rv);
 
1616
                sel_op_done(data, rv, 1);
 
1617
                goto out;
 
1618
            }
 
1619
        } else {
 
1620
            rv = send_del_sel(data, mc);
 
1621
            if (rv) {
 
1622
                ipmi_log(IPMI_LOG_ERR_INFO,
 
1623
                         "%ssel.c(handle_sel_check): "
 
1624
                         "Could not send SEL delete command: %x",
 
1625
                         sel->name, rv);
 
1626
                sel_op_done(data, rv, 1);
 
1627
                goto out;
 
1628
            } else if (data->record_id == sel->start_rec_id)
 
1629
                /* We are deleting our "current" record (used for finding
 
1630
                   the next record), make sure we start again from
 
1631
                   scratch on the next fetch. */
 
1632
                sel->start_rec_id = 0;
 
1633
        }
1417
1634
    }
1418
1635
        
1419
1636
 
1425
1642
 
1426
1643
/* First get the entry, to make sure we are deleting the right one. */
1427
1644
static int
1428
 
send_check_sel(sel_cb_handler_data_t *data, ipmi_mc_t *mc)
 
1645
send_check_sel(sel_del_handler_data_t *data, ipmi_mc_t *mc)
1429
1646
{
1430
1647
    unsigned char   cmd_data[MAX_IPMI_DATA_SIZE];
1431
1648
    ipmi_msg_t      cmd_msg;
1450
1667
                        ipmi_msg_t *rsp,
1451
1668
                        void       *rsp_data)
1452
1669
{
1453
 
    sel_cb_handler_data_t *data = rsp_data;
1454
 
    ipmi_sel_info_t       *sel = data->sel;
1455
 
    int                   rv;
 
1670
    sel_del_handler_data_t *data = rsp_data;
 
1671
    ipmi_sel_info_t        *sel = data->sel;
 
1672
    int                    rv;
1456
1673
 
1457
1674
    sel_lock(sel);
1458
1675
    if (sel->destroyed) {
1459
1676
        ipmi_log(IPMI_LOG_ERR_INFO,
1460
1677
                 "%ssel.c(sel_reserved_for_delete): "
1461
 
                 "SEL info was destroyed while an operation was in progress",
 
1678
                 "SEL info was destroyed while SEL delete element was in"
 
1679
                 " progress",
1462
1680
                 sel->name);
1463
 
        sel_op_done(data, ECANCELED);
 
1681
        sel_op_done(data, ECANCELED, 1);
1464
1682
        goto out;
1465
1683
    }
1466
1684
    if (!mc) {
1467
1685
        ipmi_log(IPMI_LOG_ERR_INFO,
1468
1686
                 "%ssel.c(sel_reserved_for_delete): "
1469
 
                 "MC went away while SEL fetch was in progress", sel->name);
1470
 
        sel_op_done(data, ECANCELED);
 
1687
                 "MC went away while SEL delete element was in progress",
 
1688
                 sel->name);
 
1689
        sel_op_done(data, ECANCELED, 1);
1471
1690
        goto out;
1472
1691
    }
1473
1692
 
1478
1697
                 "%ssel.c(sel_reserved_for_delete): "
1479
1698
                 "IPMI error from SEL delete reservation: %x",
1480
1699
                 sel->name, rsp->data[0]);
1481
 
        sel_op_done(data, IPMI_IPMI_ERR_VAL(rsp->data[0]));
 
1700
        sel_op_done(data, IPMI_IPMI_ERR_VAL(rsp->data[0]), 1);
1482
1701
        goto out;
1483
1702
    }
1484
1703
 
1485
1704
    data->reservation = ipmi_get_uint16(rsp->data+1);
1486
 
    rv = send_check_sel(data, mc);
1487
 
    if (rv) {
1488
 
        ipmi_log(IPMI_LOG_ERR_INFO,
1489
 
                 "%ssel.c(sel_reserved_for_delete): "
1490
 
                 "Could not send SEL get command: %x", sel->name, rv);
1491
 
        sel_op_done(data, rv);
1492
 
        goto out;
 
1705
    if (!data->do_clear || data->event) {
 
1706
        rv = send_check_sel(data, mc);
 
1707
        if (rv) {
 
1708
            ipmi_log(IPMI_LOG_ERR_INFO,
 
1709
                     "%ssel.c(sel_reserved_for_delete): "
 
1710
                     "Could not send SEL get command: %x", sel->name, rv);
 
1711
            sel_op_done(data, rv, 1);
 
1712
            goto out;
 
1713
        }
 
1714
    } else {
 
1715
        /* We are clearing the SEL and the user didn't supply an
 
1716
           event.  Don't worry about checking anything. */
 
1717
        rv = send_del_clear(data, mc);
 
1718
        if (rv) {
 
1719
            ipmi_log(IPMI_LOG_ERR_INFO,
 
1720
                     "%ssel.c(sel_reserved_for_delete): "
 
1721
                     "Could not send SEL clear command: %x", sel->name, rv);
 
1722
            sel_op_done(data, rv, 1);
 
1723
            goto out;
 
1724
        }
1493
1725
    }
1494
1726
 
1495
1727
    sel_unlock(sel);
1498
1730
}
1499
1731
 
1500
1732
static int
1501
 
send_reserve_sel_for_delete(sel_cb_handler_data_t *data, ipmi_mc_t *mc)
 
1733
send_reserve_sel_for_delete(sel_del_handler_data_t *data, ipmi_mc_t *mc)
1502
1734
{
1503
1735
    unsigned char   cmd_data[MAX_IPMI_DATA_SIZE];
1504
1736
    ipmi_msg_t      cmd_msg;
1517
1749
static void
1518
1750
start_del_sel_cb(ipmi_mc_t *mc, void *cb_data)
1519
1751
{
1520
 
    sel_cb_handler_data_t *data = cb_data;
1521
 
    ipmi_sel_info_t       *sel = data->sel;
1522
 
    int                   rv;
 
1752
    sel_del_handler_data_t *data = cb_data;
 
1753
    ipmi_sel_info_t        *sel = data->sel;
 
1754
    int                    rv;
1523
1755
 
1524
1756
    /* Called with SEL lock held. */
1525
1757
    if (sel->destroyed) {
1527
1759
                 "%ssel.c(start_del_sel_cb): "
1528
1760
                 "SEL info was destroyed while an operation was in progress",
1529
1761
                 sel->name);
1530
 
        sel_op_done(data, ECANCELED);
 
1762
        sel_op_done(data, ECANCELED, 1);
1531
1763
        goto out;
1532
1764
    }
1533
1765
 
1540
1772
        ipmi_log(IPMI_LOG_ERR_INFO,
1541
1773
                 "%ssel.c(start_del_sel_cb): could not send cmd: %x",
1542
1774
                 sel->name, rv);
1543
 
        sel_op_done(data, rv);
 
1775
        sel_op_done(data, rv, 1);
1544
1776
        goto out;
1545
1777
    }
1546
1778
 
1549
1781
    return;
1550
1782
}
1551
1783
 
1552
 
static void
 
1784
static int
1553
1785
start_del_sel(void *cb_data, int shutdown)
1554
1786
{
1555
 
    sel_cb_handler_data_t *data = cb_data;
1556
 
    ipmi_sel_info_t       *sel = data->sel;
1557
 
    int                   rv;
 
1787
    sel_del_handler_data_t *data = cb_data;
 
1788
    ipmi_sel_info_t        *sel = data->sel;
 
1789
    int                    rv;
1558
1790
 
1559
1791
    sel_lock(sel);
1560
1792
    if (shutdown) {
1562
1794
                 "%ssel.c(start_del_sel): "
1563
1795
                 "SEL info was destroyed while an operation was in progress",
1564
1796
                 sel->name);
1565
 
        sel_op_done(data, ECANCELED);
1566
 
        goto out;
 
1797
        sel_op_done(data, ECANCELED, 0);
 
1798
        return OPQ_HANDLER_ABORTED;
 
1799
    }
 
1800
 
 
1801
    if (data->holder && data->holder->cancelled) {
 
1802
        /* Deleted by a clear, everything is ok. */
 
1803
        sel_op_done(data, 0, 0);
 
1804
        return OPQ_HANDLER_ABORTED;
1567
1805
    }
1568
1806
 
1569
1807
    rv = ipmi_mc_pointer_cb(sel->mc, start_del_sel_cb, data);
1571
1809
        ipmi_log(IPMI_LOG_ERR_INFO,
1572
1810
                 "%ssel.c(start_del_sel_cb): MC went away during delete",
1573
1811
                 sel->name);
1574
 
        sel_op_done(data, ECANCELED);
1575
 
        goto out;
 
1812
        sel_op_done(data, ECANCELED, 0);
 
1813
        return OPQ_HANDLER_ABORTED;
1576
1814
    }
1577
1815
 
1578
 
 out:
1579
 
    return;
 
1816
    return OPQ_HANDLER_STARTED;
1580
1817
}
1581
1818
 
1582
1819
typedef struct sel_del_event_info_s
1588
1825
    void                  *cb_data;
1589
1826
    int                   cmp_event;
1590
1827
    int                   rv;
 
1828
    int                   do_clear;
1591
1829
} sel_del_event_info_t;
1592
1830
 
1593
1831
static void
1597
1835
    ipmi_sel_info_t       *sel = info->sel;
1598
1836
    ipmi_event_t          *event = info->event;
1599
1837
    int                   cmp_event = info->cmp_event;
1600
 
    sel_cb_handler_data_t *data;
1601
 
    sel_event_holder_t    *real_holder;
 
1838
    sel_event_holder_t    *real_holder = NULL;
1602
1839
    ilist_iter_t          iter;
1603
 
    int                   lun;
 
1840
    int                   start_fetch = 0;
1604
1841
 
1605
1842
    sel_lock(sel);
1606
1843
    if (sel->destroyed) {
1608
1845
        goto out_unlock;
1609
1846
    }
1610
1847
 
1611
 
    ilist_init_iter(&iter, sel->events);
1612
 
    ilist_unpositioned(&iter);
1613
 
    real_holder = ilist_search_iter(&iter, recid_search_cmp,
 
1848
    if (event) {
 
1849
        ilist_init_iter(&iter, sel->events);
 
1850
        ilist_unpositioned(&iter);
 
1851
        real_holder = ilist_search_iter(&iter, recid_search_cmp,
1614
1852
                                    &info->record_id);
1615
 
    if (!real_holder) {
1616
 
        info->rv = EINVAL;
1617
 
        goto out_unlock;
1618
 
    }
1619
 
 
1620
 
    if (cmp_event && (event_cmp(event, real_holder->event) != 0)) {
1621
 
        info->rv = EINVAL;
1622
 
        goto out_unlock;
1623
 
    }
1624
 
 
1625
 
    if (real_holder->deleted) {
1626
 
        info->rv = EINVAL;
1627
 
        goto out_unlock;
1628
 
    }
1629
 
 
1630
 
    real_holder->deleted = 1;
1631
 
    sel->num_sels--;
1632
 
    sel->del_sels++;
1633
 
 
1634
 
    lun = sel->lun;
1635
 
 
1636
 
    if (sel->supports_delete_sel) {
 
1853
        if (!real_holder) {
 
1854
            info->rv = EINVAL;
 
1855
            goto out_unlock;
 
1856
        }
 
1857
 
 
1858
        if (cmp_event && (event_cmp(event, real_holder->event) != 0)) {
 
1859
            info->rv = EINVAL;
 
1860
            goto out_unlock;
 
1861
        }
 
1862
 
 
1863
        if (! info->do_clear) {
 
1864
            if (real_holder->deleted) {
 
1865
                info->rv = EINVAL;
 
1866
                goto out_unlock;
 
1867
            }
 
1868
 
 
1869
            real_holder->deleted = 1;
 
1870
            sel->num_sels--;
 
1871
            sel->del_sels++;
 
1872
 
 
1873
            start_fetch = (sel->num_sels == 0) && (sel->del_sels > 1);
 
1874
        }
 
1875
    }
 
1876
 
 
1877
    /* Note that at this point we cannot check num_sels to see if it
 
1878
       is zero and do a bulk clear.  A new event might be added to the
 
1879
       SEL after this point, thus failing the bulk clear, and that
 
1880
       would prevent the individual delete from happening.  But we can
 
1881
       start a fetch if the value reaches zero, which is just as
 
1882
       good. */
 
1883
 
 
1884
    if (sel->supports_delete_sel || info->do_clear) {
 
1885
        sel_del_handler_data_t *data;
 
1886
        opq_elem_t             *elem;
 
1887
 
1637
1888
        /* We can delete the entry immediately, just do it. */
1638
1889
        data = ipmi_mem_alloc(sizeof(*data));
1639
 
        if (!data)
1640
 
            /* We will eventually free this anyway, so no need to
1641
 
               worry. */
 
1890
        elem = opq_alloc_elem();
 
1891
        if (!data || !elem) {
 
1892
            if (! info->do_clear) {
 
1893
                real_holder->deleted = 0;
 
1894
                sel->num_sels++;
 
1895
                sel->del_sels--;
 
1896
            }
 
1897
            info->rv = ENOMEM;
 
1898
            if (data)
 
1899
                ipmi_mem_free(data);
 
1900
            if (elem)
 
1901
                opq_free_elem(elem);
1642
1902
            goto out_unlock;
 
1903
        }
1643
1904
 
1644
1905
        data->sel = sel;
1645
1906
        data->handler = info->handler;
1646
1907
        data->cb_data = info->cb_data;
1647
 
        data->lun = lun;
 
1908
        data->lun = sel->lun;
1648
1909
        data->record_id = info->record_id;
1649
1910
        data->count = 0;
1650
1911
        data->event = event;
 
1912
        data->holder = real_holder;
 
1913
        if (real_holder)
 
1914
            sel_event_holder_get(real_holder);
 
1915
        data->do_clear = info->do_clear;
1651
1916
        event = NULL;
1652
1917
 
1653
 
        /* We don't return a return code, because we don't really
1654
 
           care.  If this fails, it will just be handled later. */
1655
1918
        sel_unlock(sel);
1656
 
        if (!opq_new_op(sel->opq, start_del_sel, data, 0))
1657
 
            ipmi_mem_free(data);
 
1919
        opq_new_op_prio(sel->opq, start_del_sel, data, 0, OPQ_ADD_TAIL, elem);
1658
1920
    } else {
1659
1921
        sel_unlock(sel);
1660
1922
        /* Don't really delete the event, but report is as done. */
1661
1923
        info->handler(sel, info->cb_data, 0);
1662
1924
        ipmi_event_free(event);
1663
1925
    }
 
1926
 
 
1927
    if (start_fetch)
 
1928
        ipmi_sel_get(sel, NULL, NULL);
1664
1929
    return;
1665
1930
 
1666
1931
 out_unlock:
1673
1938
              unsigned int          record_id,
1674
1939
              ipmi_sel_op_done_cb_t handler,
1675
1940
              void                  *cb_data,
1676
 
              int                   cmp_event)
 
1941
              int                   cmp_event,
 
1942
              int                   do_clear)
1677
1943
{
1678
1944
    sel_del_event_info_t info;
1679
1945
    int                  rv;
1685
1951
    info.cb_data = cb_data;
1686
1952
    info.cmp_event = cmp_event;
1687
1953
    info.rv = 0;
 
1954
    info.do_clear = do_clear;
1688
1955
    rv = ipmi_mc_pointer_cb(sel->mc, sel_del_event_cb, &info);
1689
1956
    if (!rv)
1690
1957
        rv = info.rv;
1700
1967
                   void                  *cb_data)
1701
1968
{
1702
1969
    return sel_del_event(sel, event, ipmi_event_get_record_id(event),
1703
 
                         handler, cb_data, 1);
 
1970
                         handler, cb_data, 1, 0);
1704
1971
}
1705
1972
 
1706
1973
int
1709
1976
                            ipmi_sel_op_done_cb_t handler,
1710
1977
                            void                  *cb_data)
1711
1978
{
1712
 
    return sel_del_event(sel, NULL, record_id, handler, cb_data, 0);
 
1979
    return sel_del_event(sel, NULL, record_id, handler, cb_data, 0, 0);
 
1980
}
 
1981
 
 
1982
int
 
1983
ipmi_sel_clear(ipmi_sel_info_t       *sel,
 
1984
               ipmi_event_t          *last_event,
 
1985
               ipmi_sel_op_done_cb_t handler,
 
1986
               void                  *cb_data)
 
1987
{
 
1988
    int cmp_event = (last_event != NULL);
 
1989
    unsigned int record_id = 0;
 
1990
    if (last_event)
 
1991
        record_id = ipmi_event_get_record_id(last_event);
 
1992
    return sel_del_event(sel, last_event, record_id, handler, cb_data,
 
1993
                         cmp_event, 1);
1713
1994
}
1714
1995
 
1715
1996
int
1894
2175
                  int             *array_size,
1895
2176
                  ipmi_event_t    **array)
1896
2177
{
1897
 
    int i;
1898
 
    int rv = 0;
 
2178
    unsigned int i;
 
2179
    int          rv = 0;
1899
2180
 
1900
2181
    sel_lock(sel);
1901
2182
    if (sel->destroyed) {
1903
2184
        return EINVAL;
1904
2185
    }
1905
2186
 
1906
 
    if (*array_size < sel->num_sels) {
 
2187
    if (*array_size < (int) sel->num_sels) {
1907
2188
        rv = E2BIG;
1908
2189
    } else if (sel->num_sels == 0) {
1909
2190
        rv = 0;
1922
2203
                array[i] = ipmi_event_dup(holder->event);
1923
2204
            }
1924
2205
            i++;
1925
 
            if (i<sel->num_sels) {
 
2206
            if (i < sel->num_sels) {
1926
2207
                if (! ilist_next(&iter)) {
1927
2208
                    rv = EINVAL;
1928
2209
                    i--;
2098
2379
                               ipmi_sel_new_event_handler_cb handler,
2099
2380
                               void                          *cb_data)
2100
2381
{
 
2382
    sel_lock(sel);
2101
2383
    sel->new_event_handler = handler;
2102
2384
    sel->new_event_cb_data = cb_data;
 
2385
    sel_unlock(sel);
2103
2386
    return 0;
2104
2387
}
2105
2388
 
2120
2403
    record_id = ipmi_event_get_record_id(new_event);
2121
2404
    holder = find_event(sel->events, record_id);
2122
2405
    if (!holder) {
2123
 
        holder = ipmi_mem_alloc(sizeof(*holder));
 
2406
        holder = sel_event_holder_alloc();
2124
2407
        if (!holder) {
2125
2408
            rv = ENOMEM;
2126
2409
            goto out_unlock;
2255
2538
                                    info);
2256
2539
}
2257
2540
 
2258
 
static void
 
2541
static int
2259
2542
sel_add_event_op(void *cb_data, int shutdown)
2260
2543
{
2261
2544
    sel_add_cb_handler_data_t *info = cb_data;
2289
2572
 
2290
2573
    sel_unlock(sel);
2291
2574
 out:
2292
 
    return;
 
2575
    return OPQ_HANDLER_STARTED;
2293
2576
}
2294
2577
 
2295
2578
int