source: trunk/src/ifd/locks.c @ 677

Revision 677, 2.7 KB checked in by aj, 7 years ago (diff)

add/fix/unify out of memory handling.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * Locking functions - these are somewhat simplified
3 * by the fact that we have one manager process per reader,
4 * so we don't have to worry about different readers here,
5 * just different slots.
6 *
7 * Copyright (C) 2003 Olaf Kirch <okir@suse.de>
8 *
9 * FIXME - prevent denial of service from clients allocating
10 * huge numbers of locks. There should be a maximum of one shared
11 * and one exclusive lock per client.
12 */
13
14#include "internal.h"
15#include <stdlib.h>
16#include "ifdhandler.h"
17
18typedef struct ct_lock {
19        struct ct_lock *next;
20        unsigned int slot;
21        uid_t uid;
22        ct_lock_handle handle;
23        ct_socket_t *owner;
24        int exclusive;
25} ct_lock_t;
26
27static ct_lock_t *locks;
28static unsigned int lock_handle = 0;
29
30/*
31 * Try to establish a lock
32 */
33int ifdhandler_lock(ct_socket_t * sock, int slot, int type,
34                    ct_lock_handle * res)
35{
36        ct_lock_t *l;
37        int rc;
38
39        /* See if we have a locking conflict */
40        if ((rc = ifdhandler_check_lock(sock, slot, type)) < 0)
41                return rc;
42
43        /* No conflict - grant lock and record this fact */
44        l = (ct_lock_t *) calloc(1, sizeof(*l));
45        if (!l) {
46                ct_error("out of memory");
47                return IFD_ERROR_NO_MEMORY;
48        }
49        l->exclusive = (type == IFD_LOCK_EXCLUSIVE);
50        l->uid = sock->client_uid;
51        l->handle = lock_handle++;
52        l->owner = sock;
53        l->slot = slot;
54
55        l->next = locks;
56        locks = l;
57
58        ifd_debug(1, "granted %s lock %u for slot %u by uid=%u",
59                  l->exclusive ? "excl" : "shared", l->handle, l->slot, l->uid);
60
61        *res = l->handle;
62        return 0;
63}
64
65/*
66 * Check if a slot is locked by someone else
67 */
68int ifdhandler_check_lock(ct_socket_t * sock, int slot, int type)
69{
70        ct_lock_t *l;
71
72        for (l = locks; l; l = l->next) {
73                if (l->slot != slot)
74                        continue;
75
76                if (l->owner == sock)
77                        continue;
78
79                if (l->exclusive
80                    || type == IFD_LOCK_EXCLUSIVE || l->uid != sock->client_uid)
81                        return IFD_ERROR_LOCKED;
82        }
83
84        return 0;
85}
86
87/*
88 * Release a lock
89 */
90int ifdhandler_unlock(ct_socket_t * sock, int slot, ct_lock_handle handle)
91{
92        ct_lock_t *l, **lp;
93
94        for (lp = &locks; (l = *lp) != NULL; lp = &l->next) {
95                if (l->owner == sock && l->slot == slot && l->handle == handle) {
96                        ifd_debug(1,
97                                  "released %s lock %u for slot %u by uid=%u",
98                                  l->exclusive ? "excl" : "shared",
99                                  l->handle, l->slot, l->uid);
100
101                        *lp = l->next;
102                        free(l);
103                        return 0;
104                }
105        }
106
107        return IFD_ERROR_NOLOCK;
108}
109
110/*
111 * Release all locks held by a client
112 * (called when the client socket is closed)
113 */
114void ifdhandler_unlock_all(ct_socket_t * sock)
115{
116        ct_lock_t *l, **lp;
117
118        lp = &locks;
119        while ((l = *lp) != NULL) {
120                if (l->owner == sock) {
121                        ifd_debug(1,
122                                  "released %s lock %u for slot %u by uid=%u",
123                                  l->exclusive ? "excl" : "shared",
124                                  l->handle, l->slot, l->uid);
125                        *lp = l->next;
126                        free(l);
127                } else {
128                        lp = &l->next;
129                }
130        }
131}
Note: See TracBrowser for help on using the repository browser.