source: rtems/cpukit/libblock/src/media.c @ 3a95a07d

Last change on this file since 3a95a07d was 3a95a07d, checked in by Christian Mauderer <christian.mauderer@…>, on 07/09/20 at 08:21:29

media-server: Add ability for retry.

This adds the possibility to request a retry in the media-listener if an
operation failed. Usefull for example if you want to automatically
reformat a disk if it wasn't possible to mount it.

  • Property mode set to 100644
File size: 19.6 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup RTEMSMedia
5 *
6 * @brief Media implementation.
7 */
8
9/*
10 * Copyright (c) 2009-2013 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Dornierstr. 4
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
17 *
18 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
20 * http://www.rtems.org/license/LICENSE.
21 */
22
23#include <stdlib.h>
24#include <string.h>
25#include <assert.h>
26#include <unistd.h>
27
28#include <rtems/media.h>
29
30#include <rtems.h>
31#include <rtems/bdbuf.h>
32#include <rtems/blkdev.h>
33#include <rtems/bdpart.h>
34#include <rtems/libio.h>
35#include <rtems/dosfs.h>
36#include <rtems/thread.h>
37
38typedef struct {
39  rtems_bdpart_partition *partitions;
40  size_t *count;
41} partition_table;
42
43typedef struct {
44  size_t index;
45  rtems_blkdev_bnum begin;
46  rtems_blkdev_bnum count;
47} partition;
48
49typedef struct media_item {
50  rtems_chain_node node;
51  struct media_item *parent;
52  char *disk_path;
53  char *mount_path;
54} media_item;
55
56typedef struct listener_item {
57  rtems_chain_node node;
58  rtems_media_listener listener;
59  void *listener_arg;
60} listener_item;
61
62static RTEMS_CHAIN_DEFINE_EMPTY(listener_item_chain);
63
64static RTEMS_CHAIN_DEFINE_EMPTY(media_item_chain);
65
66static rtems_mutex media_mutex = RTEMS_MUTEX_INITIALIZER("Media");
67
68static void lock(void)
69{
70  rtems_mutex_lock(&media_mutex);
71}
72
73static void unlock(void)
74{
75  rtems_mutex_unlock(&media_mutex);
76}
77
78static listener_item *find_listener(
79  rtems_media_listener listener,
80  void *listener_arg
81)
82{
83  rtems_chain_node *node = rtems_chain_first(&listener_item_chain);
84
85  while (!rtems_chain_is_tail(&listener_item_chain, node)) {
86    listener_item *item = (listener_item *) node;
87
88    if (item->listener == listener && item->listener_arg == listener_arg) {
89      return item;
90    }
91
92    node = rtems_chain_next(node);
93  }
94
95  return NULL;
96}
97
98rtems_status_code rtems_media_listener_add(
99  rtems_media_listener listener,
100  void *listener_arg
101)
102{
103  rtems_status_code sc = RTEMS_SUCCESSFUL;
104  listener_item *item;
105
106  lock();
107
108  item = find_listener(listener, listener_arg);
109
110  if (item == NULL) {
111    item = malloc(sizeof(*item));
112    if (item != NULL) {
113      item->listener = listener;
114      item->listener_arg = listener_arg;
115      rtems_chain_initialize_node(&item->node);
116      rtems_chain_append_unprotected(&listener_item_chain, &item->node);
117    } else {
118      sc = RTEMS_NO_MEMORY;
119    }
120  } else {
121    sc = RTEMS_TOO_MANY;
122  }
123
124  unlock();
125
126  return sc;
127}
128
129rtems_status_code rtems_media_listener_remove(
130  rtems_media_listener listener,
131  void *listener_arg
132)
133{
134  rtems_status_code sc = RTEMS_SUCCESSFUL;
135  listener_item *item;
136
137  lock();
138
139  item = find_listener(listener, listener_arg);
140
141  if (item != NULL) {
142    rtems_chain_extract_unprotected(&item->node);
143    free(item);
144  } else {
145    sc = RTEMS_INVALID_ID;
146  }
147
148  unlock();
149
150  return sc;
151}
152
153static rtems_status_code notify(
154  rtems_media_event event,
155  rtems_media_state state,
156  const char *src,
157  const char *dest
158)
159{
160  rtems_status_code sc = RTEMS_SUCCESSFUL;
161  rtems_status_code rsc = RTEMS_SUCCESSFUL;
162  rtems_chain_node *node = rtems_chain_first(&listener_item_chain);
163
164  while (!rtems_chain_is_tail(&listener_item_chain, node)) {
165    listener_item *item = (listener_item *) node;
166
167    sc = (*item->listener)(event, state, src, dest, item->listener_arg);
168    if (sc != RTEMS_SUCCESSFUL) {
169      rsc = sc;
170    }
171
172    node = rtems_chain_next(node);
173  }
174
175  return rsc;
176}
177
178static void error(
179  rtems_media_state state,
180  const char *src,
181  const char *dest
182)
183{
184  notify(RTEMS_MEDIA_EVENT_ERROR, state, src, dest);
185}
186
187static media_item *get_media_item(
188  const char *disk_path,
189  const char *mount_path
190)
191{
192  rtems_chain_node *node = rtems_chain_first(&media_item_chain);
193
194  while (!rtems_chain_is_tail(&media_item_chain, node)) {
195    media_item *item = (media_item *) node;
196
197    if (
198      (disk_path == NULL || strcmp(disk_path, item->disk_path) == 0)
199        && (mount_path == NULL
200          || (item->mount_path != NULL
201            && strcmp(mount_path, item->mount_path) == 0))
202    ) {
203      return item;
204    }
205
206    node = rtems_chain_next(node);
207  }
208
209  return NULL;
210}
211
212static void free_item(media_item *item)
213{
214  rtems_chain_extract_unprotected(&item->node);
215  free(item->mount_path);
216  free(item);
217}
218
219static void create_item(
220  media_item *parent,
221  const char *disk_path,
222  const char *mount_path
223)
224{
225  size_t disk_path_size = strlen(disk_path) + 1;
226  media_item *item = malloc(sizeof(*item) + disk_path_size);
227
228  if (item != NULL) {
229    if (mount_path != NULL) {
230      item->mount_path = strdup(mount_path);
231
232      if (item->mount_path == NULL) {
233        free(item);
234
235        return;
236      }
237    } else {
238      item->mount_path = NULL;
239    }
240
241    item->parent = parent;
242    item->disk_path = (char *) item + sizeof(*item);
243    memcpy(item->disk_path, disk_path, disk_path_size);
244    rtems_chain_initialize_node(&item->node);
245    rtems_chain_append(&media_item_chain, &item->node);
246  }
247}
248
249static void remove_mount_point(const char *mount_path)
250{
251  media_item *item = get_media_item(NULL, mount_path);
252
253  if (item != NULL) {
254    free(item->mount_path);
255    item->mount_path = NULL;
256  } else {
257    error(RTEMS_MEDIA_ERROR_MOUNT_POINT_UNKNOWN, mount_path, NULL);
258  }
259}
260
261static void remove_partition(const char *partition_path)
262{
263  media_item *item = get_media_item(partition_path, NULL);
264
265  if (item != NULL) {
266    if (item->mount_path != NULL) {
267      error(
268        RTEMS_MEDIA_ERROR_PARTITION_DETACH_WITH_MOUNT,
269        partition_path,
270        item->mount_path
271      );
272    }
273    free_item(item);
274  } else {
275    error(RTEMS_MEDIA_ERROR_PARTITION_UNKNOWN, partition_path, NULL);
276  }
277}
278
279static void remove_disk(const char *disk_path)
280{
281  media_item *item = get_media_item(disk_path, NULL);
282
283  if (item != NULL) {
284    rtems_chain_node *node = rtems_chain_first(&media_item_chain);
285
286    while (!rtems_chain_is_tail(&media_item_chain, node)) {
287      media_item *child = (media_item *) node;
288
289      node = rtems_chain_next(node);
290
291      if (child->parent == item) {
292        if (child->mount_path != NULL) {
293          error(
294            RTEMS_MEDIA_ERROR_MOUNT_POINT_ORPHAN,
295            child->mount_path,
296            disk_path
297          );
298        }
299        error(RTEMS_MEDIA_ERROR_PARTITION_ORPHAN, child->disk_path, disk_path);
300        free_item(child);
301      }
302    }
303
304    free_item(item);
305  } else {
306    error(RTEMS_MEDIA_ERROR_DISK_UNKNOWN, disk_path, NULL);
307  }
308}
309
310static void add_disk(const char *disk_path)
311{
312  media_item *item = get_media_item(disk_path, NULL);
313
314  if (item != NULL) {
315    error(RTEMS_MEDIA_ERROR_DISK_EXISTS, disk_path, NULL);
316    remove_disk(disk_path);
317  }
318
319  create_item(NULL, disk_path, NULL);
320}
321
322static void add_partition(const char *disk_path, const char *partition_path)
323{
324  media_item *item = get_media_item(partition_path, NULL);
325  media_item *parent = get_media_item(disk_path, NULL);
326
327  if (item != NULL) {
328    error(RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_EXISTS, partition_path, NULL);
329    remove_disk(partition_path);
330  }
331
332  if (parent != NULL) {
333    create_item(parent, partition_path, NULL);
334  } else {
335    error(
336      RTEMS_MEDIA_ERROR_PARTITION_WITH_UNKNOWN_DISK,
337      partition_path,
338      disk_path
339    );
340  }
341}
342
343static void add_mount_point(const char *disk_path, const char *mount_path)
344{
345  media_item *item = get_media_item(disk_path, NULL);
346
347  if (item != NULL) {
348    if (item->mount_path != NULL) {
349      error(RTEMS_MEDIA_ERROR_MOUNT_POINT_EXISTS, item->mount_path, NULL);
350      free(item->mount_path);
351    }
352    item->mount_path = strdup(mount_path);
353  } else {
354    error(RTEMS_MEDIA_ERROR_DISK_OR_PARTITION_UNKNOWN, disk_path, NULL);
355  }
356}
357
358static bool is_add_state(rtems_media_state state)
359{
360  return state == RTEMS_MEDIA_STATE_SUCCESS;
361}
362
363static bool is_remove_state(rtems_media_state state)
364{
365  return state == RTEMS_MEDIA_STATE_SUCCESS
366    || state == RTEMS_MEDIA_STATE_FAILED;
367}
368
369static rtems_status_code remember_event(
370  rtems_media_event event,
371  rtems_media_state state,
372  const char *src,
373  const char *dest
374)
375{
376  switch (event) {
377    case RTEMS_MEDIA_EVENT_DISK_ATTACH:
378      if (is_add_state(state)) {
379        add_disk(dest);
380      }
381      break;
382    case RTEMS_MEDIA_EVENT_PARTITION_ATTACH:
383      if (is_add_state(state)) {
384        add_partition(src, dest);
385      }
386      break;
387    case RTEMS_MEDIA_EVENT_MOUNT:
388      if (is_add_state(state)) {
389        add_mount_point(src, dest);
390      }
391      break;
392    case RTEMS_MEDIA_EVENT_UNMOUNT:
393      if (is_remove_state(state)) {
394        remove_mount_point(src);
395      }
396      break;
397    case RTEMS_MEDIA_EVENT_PARTITION_DETACH:
398      if (is_remove_state(state)) {
399        remove_partition(src);
400      }
401      break;
402    case RTEMS_MEDIA_EVENT_DISK_DETACH:
403      if (is_remove_state(state)) {
404        remove_disk(src);
405      }
406      break;
407    default:
408      break;
409  }
410
411  return RTEMS_SUCCESSFUL;
412}
413
414static rtems_status_code process_event(
415  rtems_media_event event,
416  const char *src,
417  char **dest_ptr,
418  rtems_media_worker worker,
419  void *worker_arg
420)
421{
422  rtems_status_code sc = RTEMS_SUCCESSFUL;
423  rtems_status_code sc_retry = RTEMS_SUCCESSFUL;
424  rtems_media_state state = RTEMS_MEDIA_STATE_FAILED;
425  char *dest = NULL;
426
427  do {
428    sc = notify(event, RTEMS_MEDIA_STATE_INQUIRY, src, NULL);
429    if (sc == RTEMS_SUCCESSFUL) {
430      state = RTEMS_MEDIA_STATE_READY;
431    } else {
432      state = RTEMS_MEDIA_STATE_ABORTED;
433    }
434
435    sc = (*worker)(state, src, &dest, worker_arg);
436    if (state == RTEMS_MEDIA_STATE_READY) {
437      if (sc == RTEMS_SUCCESSFUL) {
438        state = RTEMS_MEDIA_STATE_SUCCESS;
439      } else {
440        state = RTEMS_MEDIA_STATE_FAILED;
441      }
442    }
443
444    sc_retry = notify(event, state, src, dest);
445  } while (state == RTEMS_MEDIA_STATE_FAILED
446    && sc_retry == RTEMS_INCORRECT_STATE);
447  remember_event(event, state, src, dest);
448
449  if (state == RTEMS_MEDIA_STATE_SUCCESS) {
450    sc = RTEMS_SUCCESSFUL;
451  } else if (state == RTEMS_MEDIA_STATE_ABORTED) {
452    sc = RTEMS_UNSATISFIED;
453  } else {
454    sc = RTEMS_IO_ERROR;
455  }
456
457  if (dest_ptr != NULL && sc == RTEMS_SUCCESSFUL) {
458    *dest_ptr = dest;
459  } else {
460    free(dest);
461  }
462
463  return sc;
464}
465
466static rtems_status_code mount_worker(
467  rtems_media_state state,
468  const char *src,
469  char **dest,
470  void *worker_arg
471)
472{
473  int rv = 0;
474
475  if (state == RTEMS_MEDIA_STATE_READY) {
476    rtems_dosfs_mount_options mount_options;
477    char *mount_path = NULL;
478
479    if (worker_arg == NULL) {
480      mount_path = rtems_media_replace_prefix(RTEMS_MEDIA_MOUNT_BASE, src);
481    } else {
482      mount_path = strdup(worker_arg);
483    }
484
485    if (mount_path == NULL) {
486      return RTEMS_IO_ERROR;
487    }
488
489    rv = rtems_mkdir(mount_path, S_IRWXU | S_IRWXG | S_IRWXO);
490    if (rv != 0) {
491      free(mount_path);
492
493      return RTEMS_IO_ERROR;
494    }
495
496    memset(&mount_options, 0, sizeof(mount_options));
497
498    /* In case this fails, we fall back to use the default converter */
499    mount_options.converter = rtems_dosfs_create_utf8_converter("CP850");
500
501    rv = mount(
502      src,
503      mount_path,
504      RTEMS_FILESYSTEM_TYPE_DOSFS,
505      RTEMS_FILESYSTEM_READ_WRITE,
506      &mount_options
507    );
508    if (rv != 0) {
509      rmdir(mount_path);
510      free(mount_path);
511
512      return RTEMS_IO_ERROR;
513    }
514
515    *dest = mount_path;
516  }
517
518  return RTEMS_SUCCESSFUL;
519}
520
521static rtems_status_code do_mount(
522  const char *src,
523  char **dest_ptr,
524  rtems_media_worker worker,
525  void *worker_arg
526)
527{
528  if (worker == NULL) {
529    worker = mount_worker;
530  }
531
532  return process_event(
533    RTEMS_MEDIA_EVENT_MOUNT,
534    src,
535    dest_ptr,
536    worker,
537    worker_arg
538  );
539}
540
541static rtems_status_code do_partition_attach(
542  const char *src,
543  char **dest_ptr,
544  rtems_media_worker worker,
545  void *worker_arg
546)
547{
548  rtems_status_code sc = RTEMS_SUCCESSFUL;
549  char *part_path = NULL;
550
551  if (worker != NULL) {
552    sc = process_event(
553      RTEMS_MEDIA_EVENT_PARTITION_ATTACH,
554      src,
555      &part_path,
556      worker,
557      worker_arg
558    );
559
560    if (sc == RTEMS_SUCCESSFUL) {
561      sc = do_mount(part_path, NULL, NULL, NULL);
562    }
563  } else {
564    sc = RTEMS_INVALID_ADDRESS;
565  }
566
567  if (dest_ptr != NULL && sc == RTEMS_SUCCESSFUL) {
568    *dest_ptr = part_path;
569  } else {
570    free(part_path);
571  }
572
573  return sc;
574}
575
576static rtems_status_code partition_attach_worker(
577  rtems_media_state state,
578  const char *src,
579  char **dest,
580  void *worker_arg
581)
582{
583  rtems_status_code sc = RTEMS_SUCCESSFUL;
584
585  if (state == RTEMS_MEDIA_STATE_READY) {
586    partition *part = worker_arg;
587    char *part_path = rtems_media_append_minor(src, part->index);
588
589    if (part_path == NULL) {
590      return RTEMS_IO_ERROR;
591    }
592
593    sc = rtems_blkdev_create_partition(
594      part_path,
595      src,
596      part->begin,
597      part->count
598    );
599    if (sc != RTEMS_SUCCESSFUL) {
600      free(part_path);
601
602      return RTEMS_IO_ERROR;
603    }
604
605    *dest = part_path;
606  }
607
608  return RTEMS_SUCCESSFUL;
609}
610
611static rtems_status_code attach_and_mount_partitions(
612  const char *disk_path,
613  const rtems_bdpart_partition *partitions,
614  size_t count
615)
616{
617  rtems_status_code sc = RTEMS_SUCCESSFUL;
618  size_t i = 0;
619
620  for (i = 0; i < count; ++i) {
621    partition part_desc = {
622      .index = i,
623      .begin = partitions [i].begin,
624      .count = partitions [i].end - partitions [i].begin
625    };
626    char *part_path = NULL;
627
628    sc = process_event(
629      RTEMS_MEDIA_EVENT_PARTITION_ATTACH,
630      disk_path,
631      &part_path,
632      partition_attach_worker,
633      &part_desc
634    );
635
636    if (sc == RTEMS_SUCCESSFUL) {
637      sc = do_mount(part_path, NULL, NULL, NULL);
638    }
639
640    free(part_path);
641  }
642
643  return sc;
644}
645
646static rtems_status_code partition_inquiry_worker(
647  rtems_media_state state,
648  const char *src,
649  char **dest RTEMS_UNUSED,
650  void *worker_arg
651)
652{
653  rtems_status_code sc = RTEMS_SUCCESSFUL;
654
655  if (state == RTEMS_MEDIA_STATE_READY) {
656    partition_table *pt = worker_arg;
657    rtems_bdpart_format format;
658
659    sc = rtems_bdpart_read(src, &format, pt->partitions, pt->count);
660    if (sc != RTEMS_SUCCESSFUL || *pt->count == 0) {
661      return RTEMS_IO_ERROR;
662    }
663  }
664
665  return RTEMS_SUCCESSFUL;
666}
667
668static rtems_status_code do_partition_inquiry(
669  const char *src,
670  char **dest_ptr,
671  rtems_media_worker worker,
672  void *worker_arg
673)
674{
675  rtems_status_code sc = RTEMS_SUCCESSFUL;
676
677  if (worker == NULL) {
678    rtems_bdpart_partition partitions [RTEMS_BDPART_PARTITION_NUMBER_HINT];
679    size_t count = RTEMS_BDPART_PARTITION_NUMBER_HINT;
680    partition_table pt = {
681     .partitions = partitions,
682     .count = &count
683    };
684
685    sc = process_event(
686      RTEMS_MEDIA_EVENT_PARTITION_INQUIRY,
687      src,
688      dest_ptr,
689      partition_inquiry_worker,
690      &pt
691    );
692
693    if (sc == RTEMS_SUCCESSFUL) {
694      sc = attach_and_mount_partitions(src, partitions, count);
695    }
696  } else {
697    sc = process_event(
698      RTEMS_MEDIA_EVENT_PARTITION_INQUIRY,
699      src,
700      dest_ptr,
701      worker,
702      worker_arg
703    );
704  }
705
706  return sc;
707}
708
709static rtems_status_code do_disk_attach(
710  const char *src,
711  char **dest_ptr,
712  rtems_media_worker worker,
713  void *worker_arg
714)
715{
716  rtems_status_code sc = RTEMS_SUCCESSFUL;
717  rtems_status_code rsc = RTEMS_SUCCESSFUL;
718  char *disk_path = NULL;
719
720  if (worker != NULL) {
721    rsc = process_event(
722      RTEMS_MEDIA_EVENT_DISK_ATTACH,
723      src,
724      &disk_path,
725      worker,
726      worker_arg
727    );
728   
729    if (rsc == RTEMS_SUCCESSFUL) {
730      sc = do_mount(disk_path, NULL, NULL, NULL);
731
732      if (sc != RTEMS_SUCCESSFUL) {
733        do_partition_inquiry(disk_path, NULL, NULL, NULL);
734      }
735    }
736  } else {
737    rsc = RTEMS_INVALID_ADDRESS;
738  }
739
740  if (dest_ptr != NULL && rsc == RTEMS_SUCCESSFUL) {
741    *dest_ptr = disk_path;
742  } else {
743    free(disk_path);
744  }
745
746  return rsc;
747}
748
749static rtems_status_code unmount_worker(
750  rtems_media_state state,
751  const char *src,
752  char **dest RTEMS_UNUSED,
753  void *worker_arg RTEMS_UNUSED
754)
755{
756  rtems_status_code sc = RTEMS_SUCCESSFUL;
757
758  if (state == RTEMS_MEDIA_STATE_READY) {
759    int rv = unmount(src);
760
761    if (rv == 0) {
762      rv = rmdir(src);
763      if (rv != 0) {
764        sc = RTEMS_IO_ERROR;
765      }
766    } else {
767      sc = RTEMS_IO_ERROR;
768    }
769  }
770
771  return sc;
772}
773
774static rtems_status_code do_unmount(
775  const char *src,
776  char **dest_ptr,
777  rtems_media_worker worker,
778  void *worker_arg
779)
780{
781  if (worker == NULL) {
782    worker = unmount_worker;
783    worker_arg = NULL;
784  }
785
786  return process_event(
787    RTEMS_MEDIA_EVENT_UNMOUNT,
788    src,
789    dest_ptr,
790    worker,
791    worker_arg
792  );
793}
794
795static rtems_status_code disk_detach_worker(
796  rtems_media_state state,
797  const char *src,
798  char **dest RTEMS_UNUSED,
799  void *worker_arg RTEMS_UNUSED
800)
801{
802  rtems_status_code rsc = RTEMS_SUCCESSFUL;
803
804  if (state == RTEMS_MEDIA_STATE_READY) {
805    int rv = unlink(src);
806
807    if (rv != 0) {
808      rsc = RTEMS_IO_ERROR;
809    }
810  }
811
812  return rsc;
813}
814
815static rtems_status_code detach_item(rtems_media_event event, media_item *item)
816{
817  rtems_status_code sc = RTEMS_SUCCESSFUL;
818  rtems_status_code rsc = RTEMS_SUCCESSFUL;
819
820  if (item->mount_path != NULL) {
821    sc = do_unmount(item->mount_path, NULL, NULL, NULL);
822    if (sc != RTEMS_SUCCESSFUL) {
823      rsc = RTEMS_IO_ERROR;
824    }
825  }
826
827  sc = process_event(event, item->disk_path, NULL, disk_detach_worker, NULL);
828  if (sc != RTEMS_SUCCESSFUL) {
829    rsc = RTEMS_IO_ERROR;
830  }
831
832  return rsc;
833}
834
835static rtems_status_code detach_parent_item(media_item *parent)
836{
837  rtems_status_code sc = RTEMS_SUCCESSFUL;
838  rtems_status_code rsc = RTEMS_SUCCESSFUL;
839
840  rtems_chain_node *node = rtems_chain_first(&media_item_chain);
841
842  while (!rtems_chain_is_tail(&media_item_chain, node)) {
843    media_item *child = (media_item *) node;
844
845    node = rtems_chain_next(node);
846
847    if (child->parent == parent) {
848      sc = detach_item(RTEMS_MEDIA_EVENT_PARTITION_DETACH, child);
849      if (sc != RTEMS_SUCCESSFUL) {
850        rsc = RTEMS_IO_ERROR;
851      }
852    }
853  }
854
855  sc = detach_item(RTEMS_MEDIA_EVENT_DISK_DETACH, parent);
856  if (sc != RTEMS_SUCCESSFUL) {
857    rsc = RTEMS_IO_ERROR;
858  }
859
860  return rsc;
861}
862
863static rtems_status_code do_disk_detach(
864  const char *src,
865  char **dest_ptr,
866  rtems_media_worker worker,
867  void *worker_arg
868)
869{
870  if (worker == NULL) {
871    media_item *parent = get_media_item(src, NULL);
872
873    if (parent != NULL) {
874      return detach_parent_item(parent);
875    }
876
877    worker = disk_detach_worker;
878    worker_arg = NULL;
879  }
880
881  return process_event(
882    RTEMS_MEDIA_EVENT_DISK_DETACH,
883    src,
884    dest_ptr,
885    worker,
886    worker_arg
887  );
888}
889
890static rtems_status_code do_partition_detach(
891  const char *src,
892  char **dest_ptr,
893  rtems_media_worker worker,
894  void *worker_arg
895)
896{
897  if (worker == NULL) {
898    media_item *item = get_media_item(src, NULL);
899
900    if (item != NULL) {
901      return detach_item(RTEMS_MEDIA_EVENT_PARTITION_DETACH, item);
902    }
903
904    worker = disk_detach_worker;
905    worker_arg = NULL;
906  }
907
908  return process_event(
909    RTEMS_MEDIA_EVENT_PARTITION_DETACH,
910    src,
911    dest_ptr,
912    worker,
913    worker_arg
914  );
915}
916
917rtems_status_code rtems_media_post_event(
918  rtems_media_event event,
919  const char *src,
920  char **dest_ptr,
921  rtems_media_worker worker,
922  void *worker_arg
923)
924{
925  rtems_status_code sc = RTEMS_SUCCESSFUL;
926
927  lock();
928
929  switch (event) {
930    case RTEMS_MEDIA_EVENT_DISK_ATTACH:
931      sc = do_disk_attach(src, dest_ptr, worker, worker_arg);
932      break;
933    case RTEMS_MEDIA_EVENT_DISK_DETACH:
934      sc = do_disk_detach(src, dest_ptr, worker, worker_arg);
935      break;
936    case RTEMS_MEDIA_EVENT_MOUNT:
937      sc = do_mount(src, dest_ptr, worker, worker_arg);
938      break;
939    case RTEMS_MEDIA_EVENT_UNMOUNT:
940      sc = do_unmount(src, dest_ptr, worker, worker_arg);
941      break;
942    case RTEMS_MEDIA_EVENT_PARTITION_INQUIRY:
943      sc = do_partition_inquiry(src, dest_ptr, worker, worker_arg);
944      break;
945    case RTEMS_MEDIA_EVENT_PARTITION_ATTACH:
946      sc = do_partition_attach(src, dest_ptr, worker, worker_arg);
947      break;
948    case RTEMS_MEDIA_EVENT_PARTITION_DETACH:
949      sc = do_partition_detach(src, dest_ptr, worker, worker_arg);
950      break;
951    default:
952      sc = RTEMS_INVALID_ID;
953      break;
954  }
955
956  unlock();
957
958  return sc;
959}
Note: See TracBrowser for help on using the repository browser.