~ubuntu-branches/ubuntu/saucy/lvm2/saucy

« back to all changes in this revision

Viewing changes to daemons/clvmd/clvmd-singlenode.c

  • Committer: Package Import Robot
  • Author(s): Dmitrijs Ledkovs
  • Date: 2013-05-30 11:02:10 UTC
  • mfrom: (3.1.28 sid)
  • Revision ID: package-import@ubuntu.com-20130530110210-q8bou4f333ruwhn0
Tags: 2.02.98-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - debian/patches/avoid-dev-block.patch: Prefer any other device name over
    names in /dev/block/ since lvm.conf won't handle this.
  - debian/rules:
    - copy .po file to .pot file for Rosetta (Ubuntu specific).
  - debian/{dmsetup,lvm2}-udeb.install:
    - install initramfs and udev hooks in udebs (Debian bug 504341).
  - auto-start VGs as their PVs are discovered (Ubuntu specific):
    - add debian/tree/lvm2/lib/udev/rules.d/85-lvm2.rules: use watershed plus
      the sledgehammer of vgscan/vgchange to turn on VGs as they come online.
    - debian/tree/lvm2/usr/share/initramfs-tools/scripts/hooks/lvm2:
      - add 85-lvm2.rules to the list of udev rules to copy.
      - depend on udev.
    - debian/control:
      - add versioned Depend on watershed in lvm2 for udev rules.
      - add Depends on watershed-udeb in lvm2-udeb for udev rules.
      - add versioned Depend/Breaks on udev in dmsetup for udev rules.
      - add Depend on initramfs-tools in dmsetup so system is not potentially
        rendered unbootable by out-of-order dpkg configuration.
      - In libdevmapper-event1.02.1 add Breaks: dmeventd
        (<< 2.02.95-4ubuntu1) due to debian symbol rename
    - debian/rules:
      - do not install local-top scripts since Ubuntu mounts root using udev.
      - do not install init scripts for lvm2, since udev starts LVM.
      - continue to build clvm support.
    - debian/lvm2.postinst: handle missing lvm2 init script.
    - debian/tree/dmsetup/lib/udev/rules.d/60-persistent-storage-dm.rules:
      watch dm devices for changes with inotify
  - add mountroot failure hooks to help fix bad boots (Debian bug 468115):
    - debian/tree/lvm2/usr/share/initramfs-tools/scripts/init-premount/lvm2
  - remaining changes to upstream event manager packages (Debian bug 514706):
    - debian/rules:
      - enable dmeventd during configure.
    - debian/dmeventd.{8,manpages}: install dmeventd files.
  - rename debian/clvm.defaults to debian/clvm.default so it is installed
    correctly.
  - debian/control: add dmsetup-udeb to libdevmapper1.02.1-udeb recommends.
  - debian/rules: make sure dmsetup and lvm2 initramfs-tools scripts are
    executable.  When the Ubuntu-specific ones are added with a patch,
    they may lose their executable bit.
  - Add and install clvmd resource agent
  - Add dependency on libudev-dev to libdevmapper-dev so that the .pc file
    works.
  - debian/{clvmd.ra,clvm.init}:
    - create /run/lvm if it doesn't exist.
  - debian/clvm.init:
    - exit 3 if not running on status action.
  - Call dh_installman so that our dmeventd manpage actually gets installed
  - Install the missing fsadm manpage.
  - Complete libdevmapper-dev multiarch:
    - move .so symlinks and pkgconfig files to multiarched locations.
    - mark libdevmapper-dev M-A: same

* Dropped changes, applied upstream:
  - Update Micron PCIe SSD and other device-types to latest available.
  - Cherry pick from upstream, remove unsupported udev_get_dev_path() call.
  - Move thin check to global section.

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
 
29
29
static const char SINGLENODE_CLVMD_SOCKNAME[] = DEFAULT_RUN_DIR "/clvmd_singlenode.sock";
30
30
static int listen_fd = -1;
31
 
static int *_locks = NULL;
32
 
static char **_resources = NULL;
 
31
 
 
32
static struct dm_hash_table *_locks;
 
33
static int _lockid;
 
34
 
 
35
struct lock {
 
36
        int lockid;
 
37
        int mode;
 
38
        int excl;
 
39
};
33
40
 
34
41
static void close_comms(void)
35
42
{
41
48
 
42
49
static int init_comms(void)
43
50
{
44
 
        struct sockaddr_un addr;
45
51
        mode_t old_mask;
 
52
        struct sockaddr_un addr = { .sun_family = AF_UNIX };
 
53
 
 
54
        if (!dm_strncpy(addr.sun_path, SINGLENODE_CLVMD_SOCKNAME,
 
55
                        sizeof(addr.sun_path))) {
 
56
                DEBUGLOG("%s: singlenode socket name too long.",
 
57
                         SINGLENODE_CLVMD_SOCKNAME);
 
58
                return -1;
 
59
        }
46
60
 
47
61
        close_comms();
48
62
 
60
74
                goto error;
61
75
        }
62
76
 
63
 
        memset(&addr, 0, sizeof(addr));
64
 
        memcpy(addr.sun_path, SINGLENODE_CLVMD_SOCKNAME,
65
 
               sizeof(SINGLENODE_CLVMD_SOCKNAME));
66
 
        addr.sun_family = AF_UNIX;
67
 
 
68
77
        if (bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
69
78
                DEBUGLOG("Can't bind local socket: %s\n", strerror(errno));
70
79
                goto error;
88
97
{
89
98
        int r;
90
99
 
 
100
        if (!(_locks = dm_hash_create(128))) {
 
101
                DEBUGLOG("Failed to allocate single-node hash table.\n");
 
102
                return 1;
 
103
        }
 
104
 
91
105
        r = init_comms();
92
 
        if (r)
 
106
        if (r) {
 
107
                dm_hash_destroy(_locks);
93
108
                return r;
 
109
        }
94
110
 
95
111
        DEBUGLOG("Single-node cluster initialised.\n");
96
112
        return 0;
102
118
 
103
119
        DEBUGLOG("cluster_closedown\n");
104
120
        destroy_lvhash();
105
 
        dm_free(_locks);
106
 
        dm_free(_resources);
 
121
        dm_hash_destroy(_locks);
107
122
        _locks = NULL;
108
 
        _resources = NULL;
 
123
        _lockid = 0;
109
124
}
110
125
 
111
126
static void _get_our_csid(char *csid)
145
160
 
146
161
int _lock_file(const char *file, uint32_t flags);
147
162
 
148
 
static int _lock_max = 1;
149
163
static pthread_mutex_t _lock_mutex = PTHREAD_MUTEX_INITIALIZER;
150
164
/* Using one common condition for all locks for simplicity */
151
165
static pthread_cond_t _lock_cond = PTHREAD_COND_INITIALIZER;
153
167
/* Real locking */
154
168
static int _lock_resource(const char *resource, int mode, int flags, int *lockid)
155
169
{
156
 
        int *_locks_1;
157
 
        char **_resources_1;
158
 
        int i, j;
159
 
 
160
 
        if (mode == LCK_READ) { /* only track PREAD, aka PROTECTED READ */
161
 
                DEBUGLOG("Not tracking CONCURRENT READ lock: %s, flags=%d, mode=%d\n",
162
 
                         resource, flags, mode);
163
 
                *lockid = -1;
164
 
                return 0;
165
 
        }
 
170
        struct lock *lck;
166
171
 
167
172
        DEBUGLOG("Locking resource %s, flags=%d, mode=%d\n",
168
173
                 resource, flags, mode);
169
174
 
 
175
        mode &= LCK_TYPE_MASK;
170
176
        pthread_mutex_lock(&_lock_mutex);
171
177
retry:
172
 
 
173
 
        /* look for an existing lock for this resource */
174
 
        for (i = 1; i < _lock_max; ++i) {
175
 
                if (!_resources[i])
176
 
                        break;
177
 
                if (!strcmp(_resources[i], resource)) {
178
 
                        if ((_locks[i] & LCK_TYPE_MASK) == LCK_WRITE ||
179
 
                            (_locks[i] & LCK_TYPE_MASK) == LCK_EXCL) {
180
 
                                DEBUGLOG("Resource %s already write/exclusively locked...\n", resource);
181
 
                                goto maybe_retry;
182
 
                        }
183
 
                        if ((mode & LCK_TYPE_MASK) == LCK_WRITE ||
184
 
                            (mode & LCK_TYPE_MASK) == LCK_EXCL) {
185
 
                                DEBUGLOG("Resource %s already locked and WRITE/EXCL lock requested...\n",
186
 
                                         resource);
187
 
                                goto maybe_retry;
188
 
                        }
189
 
                }
190
 
        }
191
 
 
192
 
        if (i == _lock_max) { /* out of lock slots, extend */
193
 
                if (!(_locks_1 = dm_realloc(_locks, 2 * _lock_max * sizeof(int))))
194
 
                        goto_bad;
195
 
 
196
 
                _locks = _locks_1;
197
 
                if (!(_resources_1 = dm_realloc(_resources, 2 * _lock_max * sizeof(char *))))
198
 
                        /* _locks may get realloc'd twice, but that should be safe */
199
 
                        goto_bad;
200
 
 
201
 
                _resources = _resources_1;
202
 
                /* clear the new resource entries */
203
 
                for (j = _lock_max; j < 2 * _lock_max; ++j)
204
 
                        _resources[j] = NULL;
205
 
                _lock_max = 2 * _lock_max;
206
 
        }
207
 
 
208
 
        /* resource is not currently locked, grab it */
209
 
        if (!(_resources[i] = dm_strdup(resource)))
210
 
                goto_bad;
211
 
 
212
 
        *lockid = i;
213
 
        _locks[i] = mode;
214
 
 
215
 
        DEBUGLOG("Locked resource %s, lockid=%d\n", resource, i);
 
178
        if (!(lck = dm_hash_lookup(_locks, resource))) {
 
179
                /* Add new locked resource */
 
180
                if (!(lck = dm_zalloc(sizeof(struct lock))) ||
 
181
                    !dm_hash_insert(_locks, resource, lck))
 
182
                        goto bad;
 
183
 
 
184
                lck->lockid = ++_lockid;
 
185
                goto out;
 
186
        }
 
187
 
 
188
        /* Update/convert lock */
 
189
        if (flags == LCKF_CONVERT) {
 
190
                if (lck->excl)
 
191
                        mode = LCK_EXCL;
 
192
        } else if ((lck->mode == LCK_WRITE) || (lck->mode == LCK_EXCL)) {
 
193
                DEBUGLOG("Resource %s already %s locked (%d)...\n", resource,
 
194
                         (lck->mode == LCK_WRITE) ? "write" : "exclusively", lck->lockid);
 
195
                goto maybe_retry;
 
196
        } else if (lck->mode > mode) {
 
197
                DEBUGLOG("Resource %s already locked and %s lock requested...\n",
 
198
                         resource,
 
199
                         (mode == LCK_READ) ? "READ" :
 
200
                         (mode == LCK_WRITE) ? "WRITE" : "EXCLUSIVE");
 
201
                goto maybe_retry;
 
202
        }
 
203
 
 
204
out:
 
205
        *lockid = lck->lockid;
 
206
        lck->mode = mode;
 
207
        lck->excl |= (mode == LCK_EXCL);
 
208
        DEBUGLOG("Locked resource %s, lockid=%d, mode=%d\n", resource, lck->lockid, mode);
 
209
        pthread_cond_broadcast(&_lock_cond); /* wakeup waiters */
216
210
        pthread_mutex_unlock(&_lock_mutex);
217
211
 
218
212
        return 0;
220
214
maybe_retry:
221
215
        if (!(flags & LCK_NONBLOCK)) {
222
216
                pthread_cond_wait(&_lock_cond, &_lock_mutex);
 
217
                DEBUGLOG("Resource %s RETRYING lock...\n", resource);
223
218
                goto retry;
224
219
        }
225
220
bad:
231
226
 
232
227
static int _unlock_resource(const char *resource, int lockid)
233
228
{
 
229
        struct lock *lck;
 
230
 
234
231
        if (lockid < 0) {
235
232
                DEBUGLOG("Not tracking unlock of lockid -1: %s, lockid=%d\n",
236
233
                         resource, lockid);
240
237
        DEBUGLOG("Unlocking resource %s, lockid=%d\n", resource, lockid);
241
238
        pthread_mutex_lock(&_lock_mutex);
242
239
 
243
 
        if (!_resources[lockid]) {
244
 
                pthread_mutex_unlock(&_lock_mutex);
245
 
                DEBUGLOG("Resource %s, lockid=%d is not locked\n", resource, lockid);
246
 
                return 1;
247
 
        }
248
 
 
249
 
        if (strcmp(_resources[lockid], resource)) {
250
 
                pthread_mutex_unlock(&_lock_mutex);
251
 
                DEBUGLOG("Resource %d has wrong resource (requested %s, got %s)\n",
252
 
                         lockid, resource, _resources[lockid]);
253
 
                return 1;
254
 
        }
255
 
 
256
 
        dm_free(_resources[lockid]);
257
 
        _resources[lockid] = 0;
 
240
        if (!(lck = dm_hash_lookup(_locks, resource))) {
 
241
                pthread_mutex_unlock(&_lock_mutex);
 
242
                DEBUGLOG("Resource %s, lockid=%d is not locked.\n", resource, lockid);
 
243
                return 1;
 
244
        }
 
245
 
 
246
        if (lck->lockid != lockid) {
 
247
                pthread_mutex_unlock(&_lock_mutex);
 
248
                DEBUGLOG("Resource %s has wrong lockid %d, expected %d.\n",
 
249
                         resource, lck->lockid, lockid);
 
250
                return 1;
 
251
        }
 
252
 
 
253
        dm_hash_remove(_locks, resource);
 
254
        dm_free(lck);
258
255
        pthread_cond_broadcast(&_lock_cond); /* wakeup waiters */
259
256
        pthread_mutex_unlock(&_lock_mutex);
260
257