scummvm random work
[patches.git] / cryptsetup-1.0.6-svn-udev.patch
CommitLineData
5e993f12 1Index: lib/setup.c
2===================================================================
3--- lib/setup.c (revision 29)
4+++ lib/setup.c (revision 32)
5@@ -396,7 +396,7 @@ static int __crypt_remove_device(int arg
6 return -EBUSY;
7 }
8
9- return backend->remove(options);
10+ return backend->remove(0, options);
11 }
12
13 static int __crypt_luks_format(int arg, struct setup_backend *backend, struct crypt_options *options)
14@@ -705,7 +705,10 @@ static int crypt_job(int (*job)(int arg,
15
16 backend = get_setup_backend(default_backend);
17
18- setup_enter(backend,options->icb->log);
19+ if (setup_enter(backend,options->icb->log) < 0) {
20+ r = -ENOSYS;
21+ goto out;
22+ }
23
24 if (!backend) {
25 set_error("No setup backend available");
26Index: lib/internal.h
27===================================================================
28--- lib/internal.h (revision 29)
29+++ lib/internal.h (revision 32)
30@@ -40,7 +40,7 @@ struct setup_backend {
31 const char *key);
32 int (*status)(int details, struct crypt_options *options,
33 char **key);
34- int (*remove)(struct crypt_options *options);
35+ int (*remove)(int force, struct crypt_options *options);
36
37 const char * (*dir)(void);
38 };
39Index: lib/libdevmapper.c
40===================================================================
41--- lib/libdevmapper.c (revision 29)
42+++ lib/libdevmapper.c (revision 32)
43@@ -17,13 +17,7 @@
44 #define DEVICE_DIR "/dev"
45
46 #define CRYPT_TARGET "crypt"
47-
48-#define UDEVSETTLE "/sbin/udevsettle"
49-
50-static void run_udevsettle(void)
51-{
52- system(UDEVSETTLE);
53-}
54+#define RETRY_COUNT 5
55
56 static void set_dm_error(int level, const char *file, int line,
57 const char *f, ...)
58@@ -38,9 +32,16 @@ static void set_dm_error(int level, cons
59 va_end(va);
60 }
61
62+static int _dm_simple(int task, const char *name);
63+
64 static int dm_init(void)
65 {
66 dm_log_init(set_dm_error);
67+ if (!_dm_simple(DM_DEVICE_LIST_VERSIONS, "test")) {
68+ set_error("Cannot communicate with device-mapper. Is the dm_mod module loaded?");
69+ return -1;
70+ }
71+
72 return 1; /* unsafe memory */
73 }
74
75@@ -50,16 +51,6 @@ static void dm_exit(void)
76 dm_lib_release();
77 }
78
79-static void flush_dm_workqueue(void)
80-{
81- /*
82- * Unfortunately this is the only way to trigger libdevmapper's
83- * update_nodes function
84- */
85- dm_exit();
86- dm_init();
87-}
88-
89 static char *__lookup_dev(char *path, dev_t dev)
90 {
91 struct dirent *entry;
92@@ -152,6 +143,89 @@ out:
93 return params;
94 }
95
96+/* DM helpers */
97+static int _dm_simple(int task, const char *name)
98+{
99+ int r = 0;
100+ struct dm_task *dmt;
101+
102+ if (!(dmt = dm_task_create(task)))
103+ return 0;
104+
105+ if (!dm_task_set_name(dmt, name))
106+ goto out;
107+
108+ r = dm_task_run(dmt);
109+
110+ out:
111+ dm_task_destroy(dmt);
112+ return r;
113+}
114+
115+static int _error_device(struct crypt_options *options)
116+{
117+ struct dm_task *dmt;
118+ int r = 0;
119+
120+ if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
121+ return 0;
122+
123+ if (!dm_task_set_name(dmt, options->name))
124+ goto error;
125+
126+ if (!dm_task_add_target(dmt, UINT64_C(0), options->size, "error", ""))
127+ goto error;
128+
129+ if (!dm_task_set_ro(dmt))
130+ goto error;
131+
132+ if (!dm_task_no_open_count(dmt))
133+ goto error;
134+
135+ if (!dm_task_run(dmt))
136+ goto error;
137+
138+ if (!_dm_simple(DM_DEVICE_RESUME, options->name)) {
139+ _dm_simple(DM_DEVICE_CLEAR, options->name);
140+ goto error;
141+ }
142+
143+ r = 1;
144+
145+error:
146+ dm_task_destroy(dmt);
147+ return r;
148+}
149+
150+static int _dm_remove(struct crypt_options *options, int force)
151+{
152+ int r = -EINVAL;
153+ int retries = force ? RETRY_COUNT : 1;
154+
155+ /* If force flag is set, replace device with error, read-only target.
156+ * it should stop processes from reading it and also removed underlying
157+ * device from mapping, so it is usable again.
158+ * Force flag should be used only for temporary devices, which are
159+ * intended to work inside cryptsetup only!
160+ * Anyway, if some process try to read temporary cryptsetup device,
161+ * it is bug - no other process should try touch it (e.g. udev).
162+ */
163+ if (force) {
164+ _error_device(options);
165+ retries = RETRY_COUNT;
166+ }
167+
168+ do {
169+ r = _dm_simple(DM_DEVICE_REMOVE, options->name) ? 0 : -EINVAL;
170+ if (--retries)
171+ sleep(1);
172+ } while (r == -EINVAL && retries);
173+
174+ dm_task_update_nodes();
175+
176+ return r;
177+}
178+
179 static int dm_create_device(int reload, struct crypt_options *options,
180 const char *key)
181 {
182@@ -191,24 +265,14 @@ static int dm_create_device(int reload,
183 if (dmi.read_only)
184 options->flags |= CRYPT_FLAG_READONLY;
185
186- /* run udevsettle to avoid a race in libdevmapper causing busy dm devices */
187- run_udevsettle();
188-
189 r = 0;
190-
191 out:
192 if (r < 0 && !reload) {
193 char *error = (char *)get_error();
194 if (error)
195 error = strdup(error);
196- if (dmt)
197- dm_task_destroy(dmt);
198
199- if (!(dmt = dm_task_create(DM_DEVICE_REMOVE)))
200- goto out_restore_error;
201- if (!dm_task_set_name(dmt, options->name))
202- goto out_restore_error;
203- if (!dm_task_run(dmt))
204+ if (!_dm_remove(options, 0))
205 goto out_restore_error;
206
207 out_restore_error:
208@@ -224,7 +288,7 @@ out_no_removal:
209 dm_task_destroy(dmt);
210 if(dmt_query)
211 dm_task_destroy(dmt_query);
212- flush_dm_workqueue();
213+ dm_task_update_nodes();
214 return r;
215 }
216
217@@ -352,25 +416,12 @@ out:
218 return r;
219 }
220
221-static int dm_remove_device(struct crypt_options *options)
222+static int dm_remove_device(int force, struct crypt_options *options)
223 {
224- struct dm_task *dmt;
225- int r = -EINVAL;
226-
227- if (!(dmt = dm_task_create(DM_DEVICE_REMOVE)))
228- goto out;
229- if (!dm_task_set_name(dmt, options->name))
230- goto out;
231- if (!dm_task_run(dmt))
232- goto out;
233-
234- r = 0;
235+ if (!options || !options->name)
236+ return -EINVAL;
237
238-out:
239- if (dmt)
240- dm_task_destroy(dmt);
241- flush_dm_workqueue();
242- return r;
243+ return _dm_remove(options, force);;
244 }
245
246
247Index: luks/keyencryption.c
248===================================================================
249--- luks/keyencryption.c (revision 29)
250+++ luks/keyencryption.c (revision 32)
251@@ -45,6 +45,11 @@ static inline int round_up_modulo(int x,
252 return div_round_up(x, m) * m;
253 }
254
255+static struct setup_backend *cleaner_backend=NULL;
256+static const char *cleaner_name=NULL;
257+static uint64_t cleaner_size = 0;
258+static int devfd=-1;
259+
260 static int setup_mapping(const char *cipher, const char *name,
261 const char *device, unsigned int payloadOffset,
262 const char *key, size_t keyLength,
263@@ -52,7 +57,7 @@ static int setup_mapping(const char *cip
264 struct setup_backend *backend,
265 int mode)
266 {
267- struct crypt_options k;
268+ struct crypt_options k = {0};
269 struct crypt_options *options = &k;
270 int device_sector_size = sector_size_for_device(device);
271 int r;
272@@ -66,6 +71,7 @@ static int setup_mapping(const char *cip
273 return -EINVAL;
274 }
275 options->size = round_up_modulo(srcLength,device_sector_size)/SECTOR_SIZE;
276+ cleaner_size = options->size;
277
278 options->offset = sector;
279 options->cipher = cipher;
280@@ -87,24 +93,21 @@ static int setup_mapping(const char *cip
281 return r;
282 }
283
284-static int clear_mapping(const char *name, struct setup_backend *backend)
285+static int clear_mapping(const char *name, uint64_t size, struct setup_backend *backend)
286 {
287- struct crypt_options options;
288+ struct crypt_options options = {0};
289 options.name=name;
290- return backend->remove(&options);
291+ options.size = size;
292+ return backend->remove(1, &options);
293 }
294
295-/* I miss closures in C! */
296-static struct setup_backend *cleaner_backend=NULL;
297-static const char *cleaner_name=NULL;
298-static int devfd=0;
299-
300 static void sigint_handler(int sig)
301 {
302- if(devfd)
303+ if(devfd >= 0)
304 close(devfd);
305+ devfd = -1;
306 if(cleaner_backend && cleaner_name)
307- clear_mapping(cleaner_name, cleaner_backend);
308+ clear_mapping(cleaner_name, cleaner_size, cleaner_backend);
309 signal(SIGINT, SIG_DFL);
310 kill(getpid(), SIGINT);
311 }
312@@ -160,13 +163,14 @@ static int LUKS_endec_template(char *src
313 r = 0;
314 out3:
315 close(devfd);
316- devfd = 0;
317+ devfd = -1;
318 out2:
319- clear_mapping(name,backend);
320+ clear_mapping(cleaner_name, cleaner_size, cleaner_backend);
321 out1:
322 signal(SIGINT, SIG_DFL);
323 cleaner_name = NULL;
324 cleaner_backend = NULL;
325+ cleaner_size = 0;
326 free(dmCipherSpec);
327 free(fullpath);
328 free(name);