~ubuntu-branches/ubuntu/intrepid/raidutils/intrepid

« back to all changes in this revision

Viewing changes to raidutil/deletrad.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Barak Pearlmutter
  • Date: 2004-05-18 11:33:42 UTC
  • Revision ID: james.westby@ubuntu.com-20040518113342-tyqavmso5q351xi2
Tags: upstream-0.0.4
ImportĀ upstreamĀ versionĀ 0.0.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 1996-2004, Adaptec Corporation
 
2
 * All rights reserved.
 
3
 *
 
4
 * Redistribution and use in source and binary forms, with or without
 
5
 * modification, are permitted provided that the following conditions are met:
 
6
 *
 
7
 * - Redistributions of source code must retain the above copyright notice, this
 
8
 *   list of conditions and the following disclaimer.
 
9
 * - Redistributions in binary form must reproduce the above copyright notice,
 
10
 *   this list of conditions and the following disclaimer in the documentation
 
11
 *   and/or other materials provided with the distribution.
 
12
 * - Neither the name of the Adaptec Corporation nor the names of its
 
13
 *   contributors may be used to endorse or promote products derived from this
 
14
 *   software without specific prior written permission.
 
15
 *
 
16
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
17
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
19
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 
20
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 
21
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 
22
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 
23
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 
24
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
25
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
26
 * POSSIBILITY OF SUCH DAMAGE.
 
27
 */
 
28
 
 
29
/****************************************************************************
 
30
*
 
31
* Created:  7/30/98
 
32
*
 
33
*****************************************************************************
 
34
*
 
35
* File Name:            DeletRad.cpp
 
36
* Module:
 
37
* Contributors:         Lee Page
 
38
* Description:
 
39
* Version Control:
 
40
*
 
41
* $Revision: 22 $
 
42
* $NoKeywords: $
 
43
* $Log: $
 
44
*****************************************************************************/
 
45
 
 
46
/*** INCLUDES ***/
 
47
#include "deletrad.hpp"
 
48
#include "rustring.h"
 
49
#include "ctlr_map.hpp"
 
50
#include "intlist.hpp"
 
51
 
 
52
#include <stdio.h>
 
53
/*** CONSTANTS ***/
 
54
/*** TYPES ***/
 
55
/*** STATIC DATA ***/
 
56
/*** EXTERNAL DATA ***/
 
57
extern int FID_RESET_OUTBUFF;
 
58
extern uSHORT LOG_LIST_SIZE;
 
59
/*** MACROS ***/
 
60
/*** PROTOTYPES ***/
 
61
/*** FUNCTIONS ***/
 
62
 
 
63
/****************************************************************************
 
64
*
 
65
* Function Name:        Delete_Raid(),  Created:7/30/98
 
66
*
 
67
* Description:          This deletes the logicals listed.  If null is passed in, then
 
68
                                        ALL logicals will be deleted.
 
69
*
 
70
* Return:                       Delete_Raid
 
71
*
 
72
* Notes:                        ALL LOGICALS WILL BE DELETED IF NULL IS PASSED IN!
 
73
*
 
74
*****************************************************************************/
 
75
 
 
76
Delete_Raid::Delete_Raid(
 
77
                                SCSI_Addr_List  *which_Raids,
 
78
                                bool                    del_Hiddens )
 
79
                                                        : raids_to_Del( which_Raids ),
 
80
                                                        delete_Hiddens( del_Hiddens )
 
81
        {
 
82
        ENTER( "Delete_Raid::Delete_Raid(" );
 
83
 
 
84
        EXIT();
 
85
        }
 
86
 
 
87
Delete_Raid::Delete_Raid( const Delete_Raid &del_Raid ): delete_Hiddens( del_Raid.delete_Hiddens )
 
88
        {
 
89
        ENTER( "Delete_Raid::Delete_Raid( const Delete_Raid &del_Raid ): delete_Hiddens( del_Raid.delete_Hiddens )" );
 
90
        if( del_Raid.raids_to_Del )
 
91
                {
 
92
                raids_to_Del = new SCSI_Addr_List( *del_Raid.raids_to_Del );
 
93
                }
 
94
                else
 
95
                {
 
96
                raids_to_Del = 0;
 
97
                }
 
98
        EXIT();
 
99
        }
 
100
 
 
101
Delete_Raid::~Delete_Raid()
 
102
        {
 
103
        ENTER( "Delete_Raid::~Delete_Raid()" );
 
104
        delete  raids_to_Del;
 
105
        EXIT();
 
106
        }
 
107
 
 
108
Command::Dpt_Error      Delete_Raid::execute( String_List **output )
 
109
        {
 
110
        ENTER( "Command::Dpt_Error      Delete_Raid::execute( String_List **output )" );
 
111
        String_List             *out;
 
112
        Dpt_Error err = Dpt_Error::DPT_CMD_ERR_NO_ERROR;
 
113
    extern void add_Unique_Item( Int_List *component_List, DPT_TAG_T component_Tag );
 
114
        Int_List raid_List;
 
115
        Int_List raid_List_dual;
 
116
 
 
117
        *output = out = new String_List();
 
118
 
 
119
   Init_Engine();
 
120
 
 
121
        if( !raids_to_Del )
 
122
                {
 
123
                Make_Address_List_of_All_Logicals( &raids_to_Del );
 
124
                }
 
125
 
 
126
        while( raids_to_Del->num_Left() )
 
127
                {
 
128
                bool more_Devs_Left = true;
 
129
                bool tag_Valid; //kds
 
130
                SCSI_Address trash_addr; //kds
 
131
                SCSI_Address raid_Address = raids_to_Del->get_Next_Item();
 
132
                // get this raid's tag
 
133
                for (int dev_Index = 0; more_Devs_Left; dev_Index++)
 
134
                        {
 
135
                        get_Devs_Type devs_Type;
 
136
 
 
137
                        DPT_TAG_T raid_Tag = Get_Address_by_Index( raid_Address,
 
138
                          dev_Index, &more_Devs_Left, &devs_Type );
 
139
                        if ( !more_Devs_Left )
 
140
                                {
 
141
                                break;
 
142
                                }
 
143
                        switch ( devs_Type )
 
144
                                {
 
145
                                case GET_RAID:
 
146
                                case GET_RAID_HOT_SPARE:
 
147
                                case GET_RAID_REDIRECT:
 
148
                    break;
 
149
                default:
 
150
                    continue;
 
151
                }
 
152
            if ((devs_Type == GET_RAID_HOT_SPARE) ^ (delete_Hiddens == 0))
 
153
                {
 
154
                                        trash_addr = DPT_Tag_to_Address (raid_Tag, &tag_Valid);
 
155
                                        // if dual level array, put in one list
 
156
                                        if (trash_addr.level >= 2)
 
157
                                                add_Unique_Item ( &raid_List_dual, raid_Tag);
 
158
                                        // otherwise put in other
 
159
                                        else
 
160
                                                add_Unique_Item( &raid_List, raid_Tag );
 
161
                                }
 
162
                        }
 
163
                }
 
164
 
 
165
        raid_List_dual.reset_Next_Index();
 
166
        raid_List.reset_Next_Index();
 
167
 
 
168
        // invalid if target not found -kds
 
169
        if ((raid_List_dual.num_Left() == 0) &&
 
170
                (raid_List.num_Left() == 0))
 
171
                {
 
172
                err = Dpt_Error::DPT_CMD_ERR_CANT_FIND_COMPONENT;
 
173
                out->add_Item( (char *) err );
 
174
                }
 
175
 
 
176
        if (!err.Is_Error())
 
177
        {
 
178
        // get rid of parents and their children first
 
179
                if (raid_List_dual.num_Left())
 
180
                {
 
181
                        while( raid_List_dual.num_Left() )
 
182
                        {
 
183
                                Dpt_Error this_err = Delete_Raid_and_Children(
 
184
                                        raid_List_dual.get_Next_Item(), out );
 
185
                                if( this_err.Is_Error() )
 
186
                                {
 
187
                                        err |= this_err;
 
188
                                        // output intermediate errors, but don't stop
 
189
                                        // deleting others
 
190
                                        out->add_Item( (char *) this_err );
 
191
                                }
 
192
                        }
 
193
                }                       
 
194
                // now get rid of orphans
 
195
                if (raid_List.num_Left())
 
196
                {
 
197
                        while( raid_List.num_Left() )
 
198
                        {
 
199
                                Dpt_Error this_err = Delete_Raid_and_Children(
 
200
                                                raid_List.get_Next_Item(), out );
 
201
                                // this was already deleted in if (dual) above
 
202
                                if (this_err == Dpt_Error::DPT_ERR_INVALID_TGT_TAG)
 
203
                                        this_err = Dpt_Error::DPT_CMD_ERR_NO_ERROR;
 
204
                                // other errors are really errors
 
205
                                if( this_err.Is_Error() )
 
206
                                {
 
207
                                        err |= this_err;
 
208
                                        // output intermediate errors, but don't stop
 
209
                                        // deleting others
 
210
                                        out->add_Item( (char *) this_err );
 
211
                                }
 
212
                        }
 
213
                }
 
214
 
 
215
        Commit();
 
216
        } // !err.Is_Error
 
217
 
 
218
        EXIT();
 
219
        return( err );
 
220
}
 
221
 
 
222
 
 
223
/****************************************************************************
 
224
*
 
225
* Function Name:        Make_Address_List_of_All_Logicals(),    Created:7/30/98
 
226
*
 
227
* Description:          This fetches a list of all logicals, whether they be parent
 
228
*                                       or child logicals.
 
229
*
 
230
* Return:                       SCSI_Addr_List
 
231
*
 
232
* Notes:                        The caller must deallocate the object returned.
 
233
*
 
234
*****************************************************************************/
 
235
 
 
236
void    Delete_Raid::Make_Address_List_of_All_Logicals( SCSI_Addr_List **ret_List )
 
237
        {
 
238
        ENTER( "void    Delete_Raid::Make_Address_List_of_All_Logicals( SCSI_Addr_List **ret_List )" );
 
239
        SCSI_Addr_List  *addr_List;
 
240
        int                             dev_Index;
 
241
        bool                    index_Found     = true; // force it to succeed the first time through
 
242
 
 
243
        *ret_List       = 0;
 
244
        addr_List       = new SCSI_Addr_List();
 
245
        
 
246
        for( dev_Index = 0; index_Found; dev_Index++ )
 
247
                {
 
248
                SCSI_Address    this_Logicals_Address;
 
249
                DPT_TAG_T               this_Logicals_Tag;
 
250
        
 
251
                this_Logicals_Tag       = Get_Log_Dev_by_Index( dev_Index, (bool)false, &index_Found );
 
252
                if( index_Found )
 
253
                        {
 
254
                        this_Logicals_Address   = DPT_Tag_to_Address( this_Logicals_Tag, &index_Found );
 
255
        
 
256
                        if( index_Found )
 
257
                                {
 
258
                                addr_List->add_Item( this_Logicals_Address );
 
259
                                }
 
260
                        }
 
261
                }
 
262
        
 
263
        *ret_List = addr_List;
 
264
        EXIT();
 
265
}
 
266
 
 
267
Command::Dpt_Error      Delete_Raid::Delete_Raid_and_Children(
 
268
        DPT_TAG_T raid_Tag,
 
269
        String_List     *out)
 
270
{
 
271
        ENTER( "Command::Dpt_Error      Delete_Raid::Delete_Raid_and_Children(" );
 
272
        Dpt_Error       err, busy_err;
 
273
 
 
274
        int                     component_Index;
 
275
        Int_List        component_List;
 
276
        bool            raid_Component_Found = TRUE;
 
277
 
 
278
        // collect all the children
 
279
        for( component_Index = 0; raid_Component_Found; component_Index++ )
 
280
                {
 
281
                DPT_TAG_T               component_Tag;
 
282
                get_Devs_Type   comp_Type;
 
283
 
 
284
                // find the nth *logical* (not physical) owned by this logical
 
285
                component_Tag   = Get_Component( raid_Tag,
 
286
                                                                                 component_Index,
 
287
                                                                                 &raid_Component_Found,
 
288
                                                                                 &comp_Type );
 
289
 
 
290
                if( raid_Component_Found && ( comp_Type != GET_SCSI_DASD ))
 
291
                        {
 
292
                        component_List.add_Item( component_Tag );
 
293
                        }
 
294
                }
 
295
 
 
296
        // delete this top-level raid
 
297
        engine->Reset();
 
298
        err     = engine->Send( MSG_GET_INFO, raid_Tag );
 
299
 
 
300
        // Checks to see if there are any reserved devices that are trying to be deleted
 
301
        if ((engine->devInfo_P->flags3 & FLG_DEV_RES_CONFLICT) && (!(engine->devInfo_P->raidType == RAID_HOT_SPARE)) ){
 
302
                out->add_Item( EventStrings[STR_RESCONFLICT] );
 
303
        }
 
304
 
 
305
 
 
306
        else if( !err.Is_Error() )
 
307
                {
 
308
                bool tag_Valid;
 
309
                SCSI_Address raid_Address;
 
310
                switch( engine->devInfo_P->raidType )
 
311
                        {
 
312
                        case RAID_0 :
 
313
                        case RAID_1 :
 
314
                        case RAID_5 :
 
315
                        case RAID_HOT_SPARE :
 
316
                        case RAID_REDIRECT :
 
317
 
 
318
                /*******start of device busy section**********/
 
319
                        uLONG devStatus;
 
320
                busy_err |= engine->Send(MSG_CHECK_BUSY, raid_Tag);
 
321
 
 
322
                        // If busy_err = MSG_RTN_IGNORED, then the engine does not
 
323
                        // support this command.  Simply treat as not busy.
 
324
                        if ((busy_err.Is_Error()) &&
 
325
                                (busy_err != Dpt_Error::DPT_MSG_RTN_IGNORED))
 
326
                                    err |= busy_err;
 
327
                        if (!err.Is_Error())
 
328
                        {
 
329
                                engine->Extract(&devStatus, sizeof(uLONG));
 
330
                
 
331
                                // If 1, then this device is busy, otherwise
 
332
                                    // the device is considered NOT busy.
 
333
                                if (devStatus == 1)
 
334
                                {
 
335
                                        err = Dpt_Error::DPT_CMD_ERR_COMPONENT_BUSY;
 
336
                                }
 
337
                        }
 
338
                /*******end of device busy section**********/
 
339
 
 
340
                                // delete all logicals (not physicals) owned by this logical
 
341
                if (!err.Is_Error())
 
342
                {
 
343
                                raid_Address = DPT_Tag_to_Address(raid_Tag, &tag_Valid);
 
344
               // get the tag for the corresponding physical device
 
345
               DPT_TAG_T newComponent;
 
346
               bool compFound = false;
 
347
               get_Devs_Type comp_Type;
 
348
               for (int cmpIdx = 0; !compFound; ++cmpIdx)
 
349
               {
 
350
                  newComponent = Get_Component(raid_Tag, cmpIdx,
 
351
                     &compFound, &comp_Type);
 
352
               }
 
353
//      err = engine->Send(MSG_GET_INFO, newComponent);
 
354
//      if (compFound && (comp_Type == GET_SCSI_DASD))
 
355
 
 
356
                          
 
357
 
 
358
                                engine->Reset();
 
359
                                err = engine->Send(MSG_DELETE, raid_Tag);
 
360
               // check to see if this made it unintentionally suppressed
 
361
               CheckForSuppressed(newComponent);
 
362
                }
 
363
                                if( !err.Is_Error())
 
364
                                        {
 
365
                                        DPTControllerMap * map = new DPTControllerMap;
 
366
                                        char * String = map->getTargetString(
 
367
                                          raid_Address.hba, raid_Address.bus, raid_Address.id, raid_Address.lun );
 
368
                                        out->add_Item( String );
 
369
                                        delete [] String;
 
370
                                        delete map;
 
371
                                        out->add_Item( "\n" );
 
372
 
 
373
                                        }
 
374
                                break;
 
375
                        }
 
376
 
 
377
                component_List.reset_Next_Index();
 
378
                while ( component_List.num_Left() )
 
379
                        {
 
380
                        // delete all logicals (not physicals) owned by this logical
 
381
                        err     |= (Dpt_Error)Delete_Raid_and_Children( component_List.get_Next_Item(), out );
 
382
                        }
 
383
                }
 
384
 
 
385
        EXIT();
 
386
        return( err );
 
387
}
 
388
 
 
389
// check to see if this made it unintentionally suppressed
 
390
// if so, the new id will be the lowest chan/id available
 
391
Command::Dpt_Error Delete_Raid::CheckForSuppressed (DPT_TAG_T tag)
 
392
{
 
393
        Dpt_Error err = Dpt_Error::DPT_CMD_ERR_NO_ERROR;
 
394
   const int MAX_CHANNELS = 4;
 
395
   const int NUMBER_OF_IDS = 16;
 
396
   const int NOT_IN_USE = 0;
 
397
   const int IN_USE = 1;
 
398
 
 
399
        err = engine->Send(MSG_GET_INFO, tag);
 
400
   if ((engine->devInfo_P->flags & FLG_DEV_SUPPRESSED) &&
 
401
       (!(engine->devInfo_P->flags & FLG_DEV_SUP_DESIRED)))
 
402
   {
 
403
      dptID_S *loglist = new dptID_S[LOG_LIST_SIZE];
 
404
        int devChannel; // channel number of this device
 
405
           int availIDs [MAX_CHANNELS];
 
406
        char ids [MAX_CHANNELS][NUMBER_OF_IDS];         // array of IDs
 
407
 
 
408
           // Get the information about this device
 
409
        DPT_TAG_T newIDhba = engine->devInfo_P->hbaTag;
 
410
           devChannel = engine->devInfo_P->addr.chan;
 
411
 
 
412
        ///////////////////////////////////////////
 
413
           // We need to find out which IDs are legal
 
414
        ///////////////////////////////////////////
 
415
 
 
416
           // first mark all IDs as NOT-IN-USE
 
417
        for(int i = 0; i < MAX_CHANNELS; i++)
 
418
                for(int j = 0; j < NUMBER_OF_IDS; j++)
 
419
                        ids[i][j] = NOT_IN_USE;
 
420
 
 
421
        // mark the HBAs ID as IN-USE on all channels
 
422
           if(engine->devInfo_P->level != 0)
 
423
        {
 
424
        err = engine->Send(MSG_GET_INFO, newIDhba);
 
425
                   // assume that it is an HBA for now
 
426
                for(int j = 0; j < MAX_CHANNELS; j++)
 
427
                        ids[j][engine->hbaInfo_P->addr.id] = IN_USE;
 
428
           }
 
429
 
 
430
        // mark off the IDs that are out-of-range for the HBA as IN-USE
 
431
           for(int k = 0; k < MAX_CHANNELS; k++)
 
432
        {
 
433
                for(int l = 0; l < NUMBER_OF_IDS; l++)
 
434
                   {
 
435
                           if((l > engine->hbaInfo_P->maxAddr.id) || 
 
436
               (k > engine->hbaInfo_P->maxAddr.chan))
 
437
                                   ids[k][l] = IN_USE;
 
438
                }
 
439
           }
 
440
 
 
441
        // loop through the logicals of this guy's manager and
 
442
           // mark off the ids that are in use
 
443
        int numLogs = EngineFindIDs(FID_RESET_OUTBUFF,MSG_ID_LOGICALS,newIDhba,loglist, LOG_LIST_SIZE);
 
444
           for(int m = 0; m < numLogs; m++)
 
445
        {
 
446
        err = engine->Send(MSG_GET_INFO, loglist[m].tag);
 
447
                   ids[engine->devInfo_P->addr.chan][engine->devInfo_P->addr.id] = IN_USE;
 
448
        }
 
449
 
 
450
        // Figure out the maximum number of IDs available on any bus
 
451
           // and how many buses have IDs available
 
452
        for(int n = 0; n < MAX_CHANNELS; n++)
 
453
         availIDs[n] = 0;
 
454
 
 
455
        int newID = -1;
 
456
      int newChan;
 
457
           for(int p = 0; p < MAX_CHANNELS; p++)
 
458
        {
 
459
                for(int q = 0; q < NUMBER_OF_IDS; q++)
 
460
                   {
 
461
                        if(ids[p][q] == NOT_IN_USE)
 
462
                        {
 
463
                                availIDs[p]++;
 
464
                                // remember the lowest available ID
 
465
                                   if(newID == -1)
 
466
                                {
 
467
                                        newChan = p;
 
468
                                        newID = q;
 
469
                                }
 
470
                           }
 
471
                }
 
472
           }
 
473
        int maxAvail = 0;               // max. number of IDs available on any channel
 
474
           int chansWithAvail = 0;      // number of channels with available IDs
 
475
        for(int r = 0; r < MAX_CHANNELS; r++)
 
476
           {
 
477
                   if(availIDs[r] > maxAvail) maxAvail = availIDs[r];
 
478
                if(availIDs[r]) chansWithAvail++;
 
479
           }
 
480
 
 
481
        // Make sure there are IDs available to redirect this drive to
 
482
           if(!chansWithAvail)
 
483
        {
 
484
         err = Dpt_Error::DPT_ERR_ABS_NO_MORE_IDS;
 
485
        }
 
486
 
 
487
      if (!err.Is_Error())
 
488
      {
 
489
         // set new id
 
490
         engine->Reset();
 
491
                   raidHeader_S rh;
 
492
                memset(&rh, 0, sizeof(raidHeader_S));
 
493
                rh.refNum = RAID_REDIRECT;
 
494
                   rh.addr.id = newID;
 
495
                rh.addr.chan = newChan;
 
496
                rh.control = FLG_RCTL_ADDR;
 
497
 
 
498
                   raidCompList_S component;
 
499
                component.tag = tag;
 
500
                engine->Insert (&rh, sizeof(raidHeader_S));
 
501
                   engine->Insert (&component, sizeof(raidCompList_S));
 
502
                engine->Send (MSG_RAID_NEW, newIDhba);
 
503
      }
 
504
   }
 
505
   return (err);
 
506
}
 
507
 
 
508
Command &Delete_Raid::Clone() const
 
509
{
 
510
        ENTER( "Command         &Delete_Raid::Clone() const" );
 
511
        EXIT();
 
512
        return( *new Delete_Raid( *this ) );
 
513
}
 
514
 
 
515
/*** END OF FILE ***/