~ubuntu-branches/ubuntu/hardy/mdadm/hardy-updates

« back to all changes in this revision

Viewing changes to ,,mdadm--debian--1.12.0--patch-1--pkg-mdadm-devel@lists.alioth.debian.org--2005.1123495738.2396.13/util.c

  • Committer: Package Import Robot
  • Author(s): Scott James Remnant
  • Date: 2006-07-11 17:23:21 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20060711172321-070tz7lox9adujtw
Tags: 2.4.1-6ubuntu1
* Merge from debian unstable, remaining changes:
  - integration with initramfs-tools,
  - autocreate devices when udev is in use,
  - use lstat in mdopen.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * mdadm - manage Linux "md" devices aka RAID arrays.
3
 
 *
4
 
 * Copyright (C) 2001-2002 Neil Brown <neilb@cse.unsw.edu.au>
5
 
 *
6
 
 *
7
 
 *    This program is free software; you can redistribute it and/or modify
8
 
 *    it under the terms of the GNU General Public License as published by
9
 
 *    the Free Software Foundation; either version 2 of the License, or
10
 
 *    (at your option) any later version.
11
 
 *
12
 
 *    This program is distributed in the hope that it will be useful,
13
 
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
 *    GNU General Public License for more details.
16
 
 *
17
 
 *    You should have received a copy of the GNU General Public License
18
 
 *    along with this program; if not, write to the Free Software
19
 
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
 
 *
21
 
 *    Author: Neil Brown
22
 
 *    Email: <neilb@cse.unsw.edu.au>
23
 
 *    Paper: Neil Brown
24
 
 *           School of Computer Science and Engineering
25
 
 *           The University of New South Wales
26
 
 *           Sydney, 2052
27
 
 *           Australia
28
 
 */
29
 
 
30
 
#include        "mdadm.h"
31
 
#include        "md_p.h"
32
 
#include        <sys/utsname.h>
33
 
#include        <ctype.h>
34
 
 
35
 
/*
36
 
 * Parse a 128 bit uuid in 4 integers
37
 
 * format is 32 hexx nibbles with options :.<space> separator
38
 
 * If not exactly 32 hex digits are found, return 0
39
 
 * else return 1
40
 
 */
41
 
int parse_uuid(char *str, int uuid[4])
42
 
{
43
 
    int hit = 0; /* number of Hex digIT */
44
 
    int i;
45
 
    char c;
46
 
    for (i=0; i<4; i++) uuid[i]=0;
47
 
 
48
 
    while ((c= *str++)) {
49
 
        int n;
50
 
        if (c>='0' && c<='9')
51
 
            n = c-'0';
52
 
        else if (c>='a' && c <= 'f')
53
 
            n = 10 + c - 'a';
54
 
        else if (c>='A' && c <= 'F')
55
 
            n = 10 + c - 'A';
56
 
        else if (strchr(":. -", c))
57
 
            continue;
58
 
        else return 0;
59
 
 
60
 
        if (hit<32) {
61
 
            uuid[hit/8] <<= 4;
62
 
            uuid[hit/8] += n;
63
 
        }
64
 
        hit++;
65
 
    }
66
 
    if (hit == 32)
67
 
        return 1;
68
 
    return 0;
69
 
    
70
 
}
71
 
 
72
 
 
73
 
/*
74
 
 * Get the md version number.
75
 
 * We use the RAID_VERSION ioctl if it is supported
76
 
 * If not, but we have a block device with major '9', we assume
77
 
 * 0.36.0
78
 
 *
79
 
 * Return version number as 24 but number - assume version parts
80
 
 * always < 255
81
 
 */
82
 
 
83
 
int md_get_version(int fd)
84
 
{
85
 
    struct stat stb;
86
 
    mdu_version_t vers;
87
 
 
88
 
    if (fstat(fd, &stb)<0)
89
 
        return -1;
90
 
    if ((S_IFMT&stb.st_mode) != S_IFBLK)
91
 
        return -1;
92
 
 
93
 
    if (ioctl(fd, RAID_VERSION, &vers) == 0)
94
 
        return  (vers.major*10000) + (vers.minor*100) + vers.patchlevel;
95
 
    if (errno == EACCES)
96
 
            return -1;
97
 
    if (major(stb.st_rdev) == MD_MAJOR)
98
 
        return (3600);
99
 
    return -1;
100
 
}
101
 
 
102
 
    
103
 
int get_linux_version()
104
 
{
105
 
        struct utsname name;
106
 
        char *cp;
107
 
        int a,b,c;
108
 
        if (uname(&name) <0)
109
 
                return -1;
110
 
 
111
 
        cp = name.release;
112
 
        a = strtoul(cp, &cp, 10);
113
 
        if (*cp != '.') return -1;
114
 
        b = strtoul(cp+1, &cp, 10);
115
 
        if (*cp != '.') return -1;
116
 
        c = strtoul(cp+1, NULL, 10);
117
 
 
118
 
        return (a*1000000)+(b*1000)+c;
119
 
}
120
 
 
121
 
int enough(int level, int raid_disks, int avail_disks)
122
 
{
123
 
        switch (level) {
124
 
        case 10: return 1; /* a lie, but it is hard to tell */
125
 
 
126
 
        case -4:
127
 
                return avail_disks>= 1;
128
 
        case -1:
129
 
        case 0:
130
 
                return avail_disks == raid_disks;
131
 
        case 1:
132
 
                return avail_disks >= 1;
133
 
        case 4:
134
 
        case 5:
135
 
                return avail_disks >= raid_disks-1;
136
 
        case 6:
137
 
                return avail_disks >= raid_disks-2;
138
 
        default:
139
 
                return 0;
140
 
        }
141
 
}
142
 
 
143
 
int same_uuid(int a[4], int b[4])
144
 
{
145
 
    if (a[0]==b[0] &&
146
 
        a[1]==b[1] &&
147
 
        a[2]==b[2] &&
148
 
        a[3]==b[3])
149
 
        return 1;
150
 
    return 0;
151
 
}
152
 
 
153
 
void uuid_from_super(int uuid[4], mdp_super_t *super)
154
 
{
155
 
    uuid[0] = super->set_uuid0;
156
 
    if (super->minor_version >= 90) {
157
 
        uuid[1] = super->set_uuid1;
158
 
        uuid[2] = super->set_uuid2;
159
 
        uuid[3] = super->set_uuid3;
160
 
    } else {
161
 
        uuid[1] = 0;
162
 
        uuid[2] = 0;
163
 
        uuid[3] = 0;
164
 
    }
165
 
}
166
 
 
167
 
int compare_super(mdp_super_t *first, mdp_super_t *second)
168
 
{
169
 
    /*
170
 
     * return:
171
 
     *  0 same, or first was empty, and second was copied
172
 
     *  1 second had wrong number
173
 
     *  2 wrong uuid
174
 
     *  3 wrong other info
175
 
     */
176
 
    int uuid1[4], uuid2[4];
177
 
    if (second->md_magic != MD_SB_MAGIC)
178
 
        return 1;
179
 
    if (first-> md_magic != MD_SB_MAGIC) {
180
 
        memcpy(first, second, sizeof(*first));
181
 
        return 0;
182
 
    }
183
 
 
184
 
    uuid_from_super(uuid1, first);
185
 
    uuid_from_super(uuid2, second);
186
 
    if (!same_uuid(uuid1, uuid2))
187
 
        return 2;
188
 
    if (first->major_version != second->major_version ||
189
 
        first->minor_version != second->minor_version ||
190
 
        first->patch_version != second->patch_version ||
191
 
        first->gvalid_words  != second->gvalid_words  ||
192
 
        first->ctime         != second->ctime         ||
193
 
        first->level         != second->level         ||
194
 
        first->size          != second->size          ||
195
 
        first->raid_disks    != second->raid_disks    )
196
 
        return 3;
197
 
 
198
 
    return 0;
199
 
}
200
 
 
201
 
int load_super(int fd, mdp_super_t *super)
202
 
{
203
 
        /* try to read in the superblock
204
 
         *
205
 
         * return
206
 
         *   0 - success
207
 
         *   1 - no block size
208
 
         *   2 - too small
209
 
         *   3 - no seek
210
 
         *   4 - no read
211
 
         *   5 - no magic
212
 
         *   6 - wrong major version
213
 
         */
214
 
        unsigned long size;
215
 
        unsigned long long dsize;
216
 
        unsigned long long offset;
217
 
    
218
 
#ifdef BLKGETSIZE64
219
 
        if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
220
 
#endif
221
 
        {
222
 
                if (ioctl(fd, BLKGETSIZE, &size))
223
 
                        return 1;
224
 
                else {
225
 
                        dsize = size;
226
 
                        dsize <<= 9;
227
 
                }
228
 
        }
229
 
 
230
 
        if (dsize < MD_RESERVED_SECTORS*2)
231
 
                return 2;
232
 
        
233
 
        offset = MD_NEW_SIZE_SECTORS(dsize>>9);
234
 
 
235
 
        offset *= 512;
236
 
 
237
 
        ioctl(fd, BLKFLSBUF, 0); /* make sure we read current data */
238
 
 
239
 
        if (lseek64(fd, offset, 0)< 0LL)
240
 
                return 3;
241
 
 
242
 
        if (read(fd, super, sizeof(*super)) != sizeof(*super))
243
 
                return 4;
244
 
 
245
 
        if (super->md_magic != MD_SB_MAGIC)
246
 
                return 5;
247
 
 
248
 
        if (super->major_version != 0)
249
 
                return 6;
250
 
        return 0;
251
 
}
252
 
 
253
 
int store_super(int fd, mdp_super_t *super)
254
 
{
255
 
        unsigned long size;
256
 
        unsigned long long dsize;
257
 
        
258
 
        long long offset;
259
 
    
260
 
#ifdef BLKGETSIZE64
261
 
        if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
262
 
#endif
263
 
        {
264
 
                if (ioctl(fd, BLKGETSIZE, &size))
265
 
                        return 1;
266
 
                else
267
 
                        dsize = ((unsigned long long)size) << 9;
268
 
        }
269
 
 
270
 
        if (dsize < MD_RESERVED_SECTORS*2)
271
 
                return 2;
272
 
        
273
 
        offset = MD_NEW_SIZE_SECTORS(dsize>>9);
274
 
 
275
 
        offset *= 512;
276
 
 
277
 
        if (lseek64(fd, offset, 0)< 0LL)
278
 
                return 3;
279
 
 
280
 
        if (write(fd, super, sizeof(*super)) != sizeof(*super))
281
 
                return 4;
282
 
 
283
 
        fsync(fd);
284
 
        return 0;
285
 
}
286
 
    
287
 
 
288
 
 
289
 
int check_ext2(int fd, char *name)
290
 
{
291
 
        /*
292
 
         * Check for an ext2fs file system.
293
 
         * Superblock is always 1K at 1K offset
294
 
         *
295
 
         * s_magic is le16 at 56 == 0xEF53
296
 
         * report mtime - le32 at 44
297
 
         * blocks - le32 at 4
298
 
         * logblksize - le32 at 24
299
 
         */
300
 
        unsigned char sb[1024];
301
 
        time_t mtime;
302
 
        int size, bsize;
303
 
        if (lseek(fd, 1024,0)!= 1024)
304
 
                return 0;
305
 
        if (read(fd, sb, 1024)!= 1024)
306
 
                return 0;
307
 
        if (sb[56] != 0x53 || sb[57] != 0xef)
308
 
                return 0;
309
 
 
310
 
        mtime = sb[44]|(sb[45]|(sb[46]|sb[47]<<8)<<8)<<8;
311
 
        bsize = sb[24]|(sb[25]|(sb[26]|sb[27]<<8)<<8)<<8;
312
 
        size = sb[4]|(sb[5]|(sb[6]|sb[7]<<8)<<8)<<8;
313
 
        fprintf(stderr, Name ": %s appears to contain an ext2fs file system\n",
314
 
                name);
315
 
        fprintf(stderr,"    size=%dK  mtime=%s",
316
 
                size*(1<<bsize), ctime(&mtime));
317
 
        return 1;
318
 
}
319
 
 
320
 
int check_reiser(int fd, char *name)
321
 
{
322
 
        /*
323
 
         * superblock is at 64K
324
 
         * size is 1024;
325
 
         * Magic string "ReIsErFs" or "ReIsEr2Fs" at 52
326
 
         *
327
 
         */
328
 
        unsigned char sb[1024];
329
 
        int size;
330
 
        if (lseek(fd, 64*1024, 0) != 64*1024)
331
 
                return 0;
332
 
        if (read(fd, sb, 1024) != 1024)
333
 
                return 0;
334
 
        if (strncmp((char*)sb+52, "ReIsErFs",8)!=0 &&
335
 
            strncmp((char*)sb+52, "ReIsEr2Fs",9)!=0)
336
 
                return 0;
337
 
        fprintf(stderr, Name ": %s appears to contain a reiserfs file system\n",name);
338
 
        size = sb[0]|(sb[1]|(sb[2]|sb[3]<<8)<<8)<<8;
339
 
        fprintf(stderr, "    size = %dK\n", size*4);
340
 
                
341
 
        return 1;
342
 
}
343
 
 
344
 
int check_raid(int fd, char *name)
345
 
{
346
 
        mdp_super_t super;
347
 
        time_t crtime;
348
 
        if (load_super(fd, &super))
349
 
                return 0;
350
 
        /* Looks like a raid array .. */
351
 
        fprintf(stderr, Name ": %s appears to be part of a raid array:\n",
352
 
                name);
353
 
        crtime = super.ctime;
354
 
        fprintf(stderr, "    level=%d devices=%d ctime=%s",
355
 
                super.level, super.raid_disks, ctime(&crtime));
356
 
        return 1;
357
 
}
358
 
 
359
 
 
360
 
int ask(char *mesg)
361
 
{
362
 
        char *add = "";
363
 
        int i;
364
 
        for (i=0; i<5; i++) {
365
 
                char buf[100];
366
 
                fprintf(stderr, "%s%s", mesg, add);
367
 
                fflush(stderr);
368
 
                if (fgets(buf, 100, stdin)==NULL)
369
 
                        return 0;
370
 
                if (buf[0]=='y' || buf[0]=='Y')
371
 
                        return 1;
372
 
                if (buf[0]=='n' || buf[0]=='N')
373
 
                        return 0;
374
 
                add = "(y/n) ";
375
 
        }
376
 
        fprintf(stderr, Name ": assuming 'no'\n");
377
 
        return 0;
378
 
}
379
 
 
380
 
char *map_num(mapping_t *map, int num)
381
 
{
382
 
        while (map->name) {
383
 
                if (map->num == num)
384
 
                        return map->name;
385
 
                map++;
386
 
        }
387
 
        return NULL;
388
 
}
389
 
 
390
 
int map_name(mapping_t *map, char *name)
391
 
{
392
 
        while (map->name) {
393
 
                if (strcmp(map->name, name)==0)
394
 
                        return map->num;
395
 
                map++;
396
 
        }
397
 
        return UnSet;
398
 
}
399
 
 
400
 
 
401
 
int is_standard(char *dev, int *nump)
402
 
{
403
 
        /* tests if dev is a "standard" md dev name.
404
 
         * i.e if the last component is "/dNN" or "/mdNN",
405
 
         * where NN is a string of digits 
406
 
         */
407
 
        char *d = strrchr(dev, '/');
408
 
        int type=0;
409
 
        int num;
410
 
        if (!d)
411
 
                return 0;
412
 
        if (strncmp(d, "/d",2)==0)
413
 
                d += 2, type=1; /* /dev/md/dN{pM} */
414
 
        else if (strncmp(d, "/md_d", 5)==0)
415
 
                d += 5, type=1; /* /dev/md_dNpM */
416
 
        else if (strncmp(d, "/md", 3)==0)
417
 
                d += 3, type=-1; /* /dev/mdN */
418
 
        else if (d-dev > 3 && strncmp(d-2, "md/", 3)==0)
419
 
                d += 1, type=-1; /* /dev/md/N */
420
 
        else
421
 
                return 0;
422
 
        if (!*d)
423
 
                return 0;
424
 
        num = atoi(d);
425
 
        while (isdigit(*d))
426
 
                d++;
427
 
        if (*d)
428
 
                return 0;
429
 
        if (nump) *nump = num;
430
 
 
431
 
        return type;
432
 
}
433
 
 
434
 
 
435
 
/*
436
 
 * convert a major/minor pair for a block device into a name in /dev, if possible.
437
 
 * On the first call, walk /dev collecting name.
438
 
 * Put them in a simple linked listfor now.
439
 
 */
440
 
struct devmap {
441
 
    int major, minor;
442
 
    char *name;
443
 
    struct devmap *next;
444
 
} *devlist = NULL;
445
 
int devlist_ready = 0;
446
 
 
447
 
#ifdef UCLIBC
448
 
int add_dev(const char *name, const struct stat *stb, int flag, struct FTW *s)
449
 
{
450
 
}
451
 
char *map_dev(int major, int minor)
452
 
{
453
 
#if 0
454
 
        fprintf(stderr, "Warning - fail to map %d,%d to a device name\n",
455
 
                major, minor);
456
 
#endif
457
 
        return NULL;
458
 
}
459
 
#else
460
 
 
461
 
#ifdef __dietlibc__
462
 
int add_dev_1(const char *name, const struct stat *stb, int flag)
463
 
{
464
 
        return add_dev(name, stb, flag, NULL);
465
 
}
466
 
int nftw(const char *path, int (*han)(const char *name, const struct stat *stb, int flag, struct FTW *s), int nopenfd, int flags)
467
 
{
468
 
        ftw(path, add_dev_1, nopenfd);
469
 
}
470
 
#endif
471
 
 
472
 
int add_dev(const char *name, const struct stat *stb, int flag, struct FTW *s)
473
 
{
474
 
    if ((stb->st_mode&S_IFMT)== S_IFBLK) {
475
 
        char *n = strdup(name);
476
 
        struct devmap *dm = malloc(sizeof(*dm));
477
 
        if (dm) {
478
 
            dm->major = major(stb->st_rdev);
479
 
            dm->minor = minor(stb->st_rdev);
480
 
            dm->name = n;
481
 
            dm->next = devlist;
482
 
            devlist = dm;
483
 
        }
484
 
    }
485
 
    return 0;
486
 
}
487
 
 
488
 
/*
489
 
 * Find a block device with the right major/minor number.
490
 
 * If we find multiple names, choose the shortest.
491
 
 * If we find a non-standard name, it is probably there
492
 
 * deliberately so prefer it over a standard name.
493
 
 * This applies only to names for MD devices.
494
 
 */
495
 
char *map_dev(int major, int minor)
496
 
{
497
 
        struct devmap *p;
498
 
        char *std = NULL, *nonstd=NULL;
499
 
        if (!devlist_ready) {
500
 
                nftw("/dev", add_dev, 10, FTW_PHYS);
501
 
                devlist_ready=1;
502
 
        }
503
 
 
504
 
        for (p=devlist; p; p=p->next)
505
 
                if (p->major == major &&
506
 
                    p->minor == minor) {
507
 
                        if (is_standard(p->name, NULL)) {
508
 
                                if (std == NULL ||
509
 
                                    strlen(p->name) < strlen(std))
510
 
                                        std = p->name;
511
 
                        } else {
512
 
                                if (nonstd == NULL ||
513
 
                                    strlen(p->name) < strlen(nonstd))
514
 
                                        nonstd = p->name;
515
 
                        }
516
 
                }
517
 
        return nonstd ? nonstd : std;
518
 
}
519
 
 
520
 
#endif
521
 
 
522
 
unsigned long calc_sb_csum(mdp_super_t *super)
523
 
{
524
 
        unsigned int  oldcsum = super->sb_csum;
525
 
        unsigned long long newcsum = 0;
526
 
        unsigned long csum;
527
 
        int i;
528
 
        unsigned int *superc = (unsigned int*) super;
529
 
        super->sb_csum = 0;
530
 
 
531
 
        for(i=0; i<MD_SB_BYTES/4; i++)
532
 
                newcsum+= superc[i];
533
 
        csum = (newcsum& 0xffffffff) + (newcsum>>32);
534
 
        super->sb_csum = oldcsum;
535
 
        return csum;
536
 
}
537
 
 
538
 
char *human_size(long long bytes)
539
 
{
540
 
        static char buf[30];
541
 
 
542
 
        /* We convert bytes to either centi-M{ega,ibi}bytes or
543
 
         * centi-G{igi,ibi}bytes, with appropriate rounding,
544
 
         * and then print 1/100th of those as a decimal.
545
 
         * We allow upto 2048Megabytes before converting to
546
 
         * gigabytes, as that shows more precision and isn't
547
 
         * too large a number.
548
 
         * Terrabytes are not yet handled.
549
 
         */
550
 
 
551
 
        if (bytes < 1024*1024)
552
 
                buf[0]=0;
553
 
        else if (bytes < 2*1024LL*1024LL*1024LL) {
554
 
                long cMiB = (bytes / ( (1LL<<20) / 200LL ) +1) /2;
555
 
                long cMB  = (bytes / ( 1000000LL / 200LL ) +1) /2;
556
 
                snprintf(buf, sizeof(buf), " (%ld.%02ld MiB %ld.%02ld MB)",
557
 
                        cMiB/100 , cMiB % 100,
558
 
                        cMB/100, cMB % 100);
559
 
        } else {
560
 
                long cGiB = (bytes / ( (1LL<<30) / 200LL ) +1) /2;
561
 
                long cGB  = (bytes / (1000000000LL/200LL ) +1) /2;
562
 
                snprintf(buf, sizeof(buf), " (%ld.%02ld GiB %ld.%02ld GB)",
563
 
                        cGiB/100 , cGiB % 100,
564
 
                        cGB/100, cGB % 100);
565
 
        }
566
 
        return buf;
567
 
}
568
 
 
569
 
char *human_size_brief(long long bytes)
570
 
{
571
 
        static char buf[30];
572
 
        
573
 
 
574
 
        if (bytes < 5000*1024)
575
 
                snprintf(buf, sizeof(buf), "%ld.%02ldKiB",
576
 
                        (long)(bytes>>10), (long)(((bytes&1023)*100+512)/1024)
577
 
                        );
578
 
        else if (bytes < 2*1024LL*1024LL*1024LL)
579
 
                snprintf(buf, sizeof(buf), "%ld.%02ldMiB",
580
 
                        (long)(bytes>>20),
581
 
                        (long)((bytes&0xfffff)+0x100000/200)/(0x100000/100)
582
 
                        );
583
 
        else
584
 
                snprintf(buf, sizeof(buf), "%ld.%02ldGiB",
585
 
                        (long)(bytes>>30),
586
 
                        (long)(((bytes>>10)&0xfffff)+0x100000/200)/(0x100000/100)
587
 
                        );
588
 
        return buf;
589
 
}
590
 
 
591
 
int get_mdp_major(void)
592
 
{
593
 
static int mdp_major = -1;
594
 
        FILE *fl;
595
 
        char *w;
596
 
        int have_block = 0;
597
 
        int have_devices = 0;
598
 
        int last_num = -1;
599
 
 
600
 
        if (mdp_major != -1)
601
 
                return mdp_major;
602
 
        fl = fopen("/proc/devices", "r");
603
 
        if (!fl)
604
 
                return -1;
605
 
        while ((w = conf_word(fl, 1))) {
606
 
                if (have_block && strcmp(w, "devices:")==0)
607
 
                        have_devices = 1;
608
 
                have_block =  (strcmp(w, "Block")==0);
609
 
                if (isdigit(w[0]))
610
 
                        last_num = atoi(w);
611
 
                if (have_devices && strcmp(w, "mdp")==0)
612
 
                        mdp_major = last_num;
613
 
                free(w);
614
 
        }
615
 
        fclose(fl);
616
 
        return mdp_major;
617
 
}
618
 
 
619
 
 
620
 
 
621
 
char *get_md_name(int dev)
622
 
{
623
 
        /* find /dev/md%d or /dev/md/%d or make a device /dev/.tmp.md%d */
624
 
        /* if dev < 0, want /dev/md/d%d or find mdp in /proc/devices ... */
625
 
        static char devname[50];
626
 
        struct stat stb;
627
 
        dev_t rdev;
628
 
        char *dn;
629
 
 
630
 
        if (dev < 0) {
631
 
                int mdp =  get_mdp_major();
632
 
                if (mdp < 0) return NULL;
633
 
                rdev = makedev(mdp, (-1-dev)<<6);
634
 
                snprintf(devname, sizeof(devname), "/dev/md/d%d", -1-dev);
635
 
                if (stat(devname, &stb) == 0
636
 
                    && (S_IFMT&stb.st_mode) == S_IFBLK
637
 
                    && (stb.st_rdev == rdev))
638
 
                        return devname;
639
 
        } else {
640
 
                rdev = makedev(MD_MAJOR, dev);
641
 
                snprintf(devname, sizeof(devname), "/dev/md%d", dev);
642
 
                if (stat(devname, &stb) == 0
643
 
                    && (S_IFMT&stb.st_mode) == S_IFBLK
644
 
                    && (stb.st_rdev == rdev))
645
 
                        return devname;
646
 
 
647
 
                snprintf(devname, sizeof(devname), "/dev/md/%d", dev);
648
 
                if (stat(devname, &stb) == 0
649
 
                    && (S_IFMT&stb.st_mode) == S_IFBLK
650
 
                    && (stb.st_rdev == rdev))
651
 
                        return devname;
652
 
        }
653
 
        dn = map_dev(major(rdev), minor(rdev));
654
 
        if (dn)
655
 
                return dn;
656
 
        snprintf(devname, sizeof(devname), "/dev/.tmp.md%d", dev);
657
 
        if (mknod(devname, S_IFBLK | 0600, rdev) == -1)
658
 
                if (errno != EEXIST)
659
 
                        return NULL;
660
 
 
661
 
        if (stat(devname, &stb) == 0
662
 
            && (S_IFMT&stb.st_mode) == S_IFBLK
663
 
            && (stb.st_rdev == rdev))
664
 
                return devname;
665
 
        unlink(devname);
666
 
        return NULL;
667
 
}
668
 
 
669
 
void put_md_name(char *name)
670
 
{
671
 
        if (strncmp(name, "/dev/.tmp.md", 12)==0)
672
 
                unlink(name);
673
 
}
674
 
 
675
 
#ifdef __TINYC__
676
 
/* tinyc doesn't optimize this check in ioctl.h out ... */
677
 
unsigned int __invalid_size_argument_for_IOC = 0;
678
 
#endif
679