1 /* libbdev - tracking and reopening of opened minor devices */ 2 3 #include <minix/drivers.h> 4 #include <minix/bdev.h> 5 #include <assert.h> 6 7 #include "const.h" 8 #include "type.h" 9 #include "proto.h" 10 11 static struct { 12 dev_t dev; 13 int count; 14 int access; 15 } open_dev[NR_OPEN_DEVS] = { { NO_DEV, 0, 0 } }; 16 17 int bdev_minor_reopen(dev_t dev) 18 { 19 /* Reopen all minor devices on a major device. This function duplicates some 20 * code from elsewhere, because in this case we must avoid performing recovery. 21 * FIXME: if reopening fails with a non-IPC error, we should attempt to close 22 * all minors that we did manage to reopen so far, or they might stay open 23 * forever. 24 */ 25 endpoint_t endpt; 26 message m; 27 int i, j, r, major; 28 29 major = major(dev); 30 endpt = bdev_driver_get(dev); 31 32 assert(endpt != NONE); 33 34 for (i = 0; i < NR_OPEN_DEVS; i++) { 35 if (major(open_dev[i].dev) != major) 36 continue; 37 38 /* Each minor device may have been opened multiple times. Send an open 39 * request for each time that it was opened before. We could reopen it 40 * just once, but then we'd have to keep a shadow open count as well. 41 */ 42 for (j = 0; j < open_dev[i].count; j++) { 43 memset(&m, 0, sizeof(m)); 44 m.m_type = BDEV_OPEN; 45 m.m_lbdev_lblockdriver_msg.minor = minor(open_dev[i].dev); 46 m.m_lbdev_lblockdriver_msg.access = open_dev[i].access; 47 m.m_lbdev_lblockdriver_msg.id = NO_ID; 48 49 if ((r = ipc_sendrec(endpt, &m)) != OK) { 50 printf("bdev: IPC to driver (%d) failed (%d)\n", 51 endpt, r); 52 return r; 53 } 54 55 if (m.m_type != BDEV_REPLY) { 56 printf("bdev: driver (%d) sent weird response (%d)\n", 57 endpt, m.m_type); 58 return EINVAL; 59 } 60 61 if (m.m_lblockdriver_lbdev_reply.id != NO_ID) { 62 printf("bdev: driver (%d) sent invalid ID (%d)\n", 63 endpt, m.m_lblockdriver_lbdev_reply.id); 64 return EINVAL; 65 } 66 67 if ((r = m.m_lblockdriver_lbdev_reply.status) != OK) { 68 printf("bdev: driver (%d) failed device reopen (%d)\n", 69 endpt, r); 70 return r; 71 } 72 } 73 } 74 75 return OK; 76 } 77 78 void bdev_minor_add(dev_t dev, int bits) 79 { 80 /* Increase the reference count of the given minor device. 81 */ 82 int i, ifree = -1; 83 84 for (i = 0; i < NR_OPEN_DEVS; i++) { 85 if (open_dev[i].dev == dev) { 86 open_dev[i].count++; 87 open_dev[i].access |= bits; 88 89 return; 90 } 91 92 if (ifree < 0 && open_dev[i].dev == NO_DEV) 93 ifree = i; 94 } 95 96 if (ifree < 0) { 97 printf("bdev: too many open devices, increase NR_OPEN_DEVS\n"); 98 return; 99 } 100 101 open_dev[ifree].dev = dev; 102 open_dev[ifree].count = 1; 103 open_dev[ifree].access = bits; 104 } 105 106 void bdev_minor_del(dev_t dev) 107 { 108 /* Decrease the reference count of the given minor device, if present. 109 */ 110 int i; 111 112 for (i = 0; i < NR_OPEN_DEVS; i++) { 113 if (open_dev[i].dev == dev) { 114 if (!--open_dev[i].count) 115 open_dev[i].dev = NO_DEV; 116 117 break; 118 } 119 } 120 } 121 122 int bdev_minor_is_open(dev_t dev) 123 { 124 /* Return whether any minor is open for the major of the given device. 125 */ 126 int i, major; 127 128 major = major(dev); 129 130 for (i = 0; i < NR_OPEN_DEVS; i++) { 131 if (major(open_dev[i].dev) == major) 132 return TRUE; 133 } 134 135 return FALSE; 136 } 137