~james-page/ubuntu/saucy/openvswitch/1.12-snapshot

« back to all changes in this revision

Viewing changes to lib/lockfile.c

  • Committer: James Page
  • Date: 2013-08-21 10:16:57 UTC
  • mfrom: (1.1.20)
  • Revision ID: james.page@canonical.com-20130821101657-3o0z0qeiv5zkwlzi
New upstream snapshot

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 /* Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
 
1
 /* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
2
2
 *
3
3
 * Licensed under the Apache License, Version 2.0 (the "License");
4
4
 * you may not use this file except in compliance with the License.
27
27
#include "coverage.h"
28
28
#include "hash.h"
29
29
#include "hmap.h"
 
30
#include "ovs-thread.h"
30
31
#include "timeval.h"
31
32
#include "util.h"
32
33
#include "vlog.h"
52
53
 * descriptor for a file on which a process holds a lock drops *all* locks on
53
54
 * that file.  That means that we can't afford to open a lockfile more than
54
55
 * once. */
55
 
static struct hmap lock_table = HMAP_INITIALIZER(&lock_table);
 
56
static struct ovs_mutex lock_table_mutex = OVS_MUTEX_INITIALIZER;
 
57
static struct hmap lock_table__ = HMAP_INITIALIZER(&lock_table__);
 
58
static struct hmap *const lock_table OVS_GUARDED_BY(lock_table_mutex)
 
59
    = &lock_table__;
56
60
 
57
61
static void lockfile_unhash(struct lockfile *);
58
62
static int lockfile_try_lock(const char *name, pid_t *pidp,
106
110
 
107
111
    lock_name = lockfile_name(file);
108
112
 
 
113
    ovs_mutex_lock(&lock_table_mutex);
109
114
    error = lockfile_try_lock(lock_name, &pid, lockfilep);
 
115
    ovs_mutex_unlock(&lock_table_mutex);
110
116
 
111
117
    if (error) {
112
118
        COVERAGE_INC(lockfile_error);
118
124
                      "pid %ld", lock_name, (long int) pid);
119
125
        } else {
120
126
            VLOG_WARN("%s: failed to lock file: %s",
121
 
                      lock_name, strerror(error));
 
127
                      lock_name, ovs_strerror(error));
122
128
        }
123
129
    }
124
130
 
132
138
lockfile_unlock(struct lockfile *lockfile)
133
139
{
134
140
    if (lockfile) {
 
141
        ovs_mutex_lock(&lock_table_mutex);
 
142
        lockfile_unhash(lockfile);
 
143
        ovs_mutex_unlock(&lock_table_mutex);
 
144
 
135
145
        COVERAGE_INC(lockfile_unlock);
136
 
        lockfile_unhash(lockfile);
137
146
        free(lockfile->name);
138
147
        free(lockfile);
139
148
    }
147
156
{
148
157
    struct lockfile *lockfile;
149
158
 
150
 
    HMAP_FOR_EACH (lockfile, hmap_node, &lock_table) {
 
159
    ovs_mutex_lock(&lock_table_mutex);
 
160
    HMAP_FOR_EACH (lockfile, hmap_node, lock_table) {
151
161
        if (lockfile->fd >= 0) {
152
162
            VLOG_WARN("%s: child does not inherit lock", lockfile->name);
153
163
            lockfile_unhash(lockfile);
154
164
        }
155
165
    }
 
166
    ovs_mutex_unlock(&lock_table_mutex);
156
167
}
157
168
 
158
169
static uint32_t
163
174
}
164
175
 
165
176
static struct lockfile *
166
 
lockfile_find(dev_t device, ino_t inode)
 
177
lockfile_find(dev_t device, ino_t inode) OVS_REQUIRES(&lock_table_mutex)
167
178
{
168
179
    struct lockfile *lockfile;
169
180
 
170
181
    HMAP_FOR_EACH_WITH_HASH (lockfile, hmap_node,
171
 
                             lockfile_hash(device, inode), &lock_table) {
 
182
                             lockfile_hash(device, inode), lock_table) {
172
183
        if (lockfile->device == device && lockfile->inode == inode) {
173
184
            return lockfile;
174
185
        }
177
188
}
178
189
 
179
190
static void
180
 
lockfile_unhash(struct lockfile *lockfile)
 
191
lockfile_unhash(struct lockfile *lockfile) OVS_REQUIRES(&lock_table_mutex)
181
192
{
182
193
    if (lockfile->fd >= 0) {
183
194
        close(lockfile->fd);
184
195
        lockfile->fd = -1;
185
 
        hmap_remove(&lock_table, &lockfile->hmap_node);
 
196
        hmap_remove(lock_table, &lockfile->hmap_node);
186
197
    }
187
198
}
188
199
 
189
200
static struct lockfile *
190
201
lockfile_register(const char *name, dev_t device, ino_t inode, int fd)
 
202
    OVS_REQUIRES(&lock_table_mutex)
191
203
{
192
204
    struct lockfile *lockfile;
193
205
 
202
214
    lockfile->device = device;
203
215
    lockfile->inode = inode;
204
216
    lockfile->fd = fd;
205
 
    hmap_insert(&lock_table, &lockfile->hmap_node,
 
217
    hmap_insert(lock_table, &lockfile->hmap_node,
206
218
                lockfile_hash(device, inode));
207
219
    return lockfile;
208
220
}
209
221
 
210
222
static int
211
223
lockfile_try_lock(const char *name, pid_t *pidp, struct lockfile **lockfilep)
 
224
    OVS_REQUIRES(&lock_table_mutex)
212
225
{
213
226
    struct flock l;
214
227
    struct stat s;
225
238
        }
226
239
    } else if (errno != ENOENT) {
227
240
        VLOG_WARN("%s: failed to stat lock file: %s",
228
 
                  name, strerror(errno));
 
241
                  name, ovs_strerror(errno));
229
242
        return errno;
230
243
    }
231
244
 
233
246
    fd = open(name, O_RDWR | O_CREAT, 0600);
234
247
    if (fd < 0) {
235
248
        VLOG_WARN("%s: failed to open lock file: %s",
236
 
                  name, strerror(errno));
 
249
                  name, ovs_strerror(errno));
237
250
        return errno;
238
251
    }
239
252
 
240
253
    /* Get the inode and device number for the lock table. */
241
254
    if (fstat(fd, &s)) {
242
 
        VLOG_ERR("%s: failed to fstat lock file: %s", name, strerror(errno));
 
255
        VLOG_ERR("%s: failed to fstat lock file: %s",
 
256
                 name, ovs_strerror(errno));
243
257
        close(fd);
244
258
        return errno;
245
259
    }
251
265
    l.l_start = 0;
252
266
    l.l_len = 0;
253
267
 
254
 
    time_disable_restart();
255
268
    error = fcntl(fd, F_SETLK, &l) == -1 ? errno : 0;
256
 
    time_enable_restart();
257
269
 
258
270
    if (!error) {
259
271
        *lockfilep = lockfile_register(name, s.st_dev, s.st_ino, fd);