diff options
author | Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> | 2006-01-18 20:43:00 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-18 22:20:21 -0500 |
commit | 4833aff757b747b51b878a13f3a6e2b1a2abb619 (patch) | |
tree | caec57a746cb04ef62e04fc5cf14a6acc555de46 /arch/um | |
parent | ce2d2aedcc3ca582fed90f44970e8b3e4f006a7d (diff) |
[PATCH] uml: allow again to move backing file and to override saved location
When the user specifies both a COW file and its backing file, if the previous
backing file is not found, currently UML tries again to use it and fails.
This can be corrected by changing same_backing_files() return value in that
case, so that the caller will try to change the COW file to point to the new
location, as already done in other cases.
Additionally, given the change in the meaning of the func, change its name,
invert its return value, so all values are inverted except when
stat(from_cow,&buf2) fails. And add some comments and two minor bugfixes -
remove a fd leak (return err rather than goto out) and a repeated check.
Tested well.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/um')
-rw-r--r-- | arch/um/drivers/ubd_kern.c | 28 |
1 files changed, 15 insertions, 13 deletions
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 7696f8d2d89c..c171d0aa5e9d 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c | |||
@@ -1103,31 +1103,33 @@ static int ubd_ioctl(struct inode * inode, struct file * file, | |||
1103 | return(-EINVAL); | 1103 | return(-EINVAL); |
1104 | } | 1104 | } |
1105 | 1105 | ||
1106 | static int same_backing_files(char *from_cmdline, char *from_cow, char *cow) | 1106 | static int path_requires_switch(char *from_cmdline, char *from_cow, char *cow) |
1107 | { | 1107 | { |
1108 | struct uml_stat buf1, buf2; | 1108 | struct uml_stat buf1, buf2; |
1109 | int err; | 1109 | int err; |
1110 | 1110 | ||
1111 | if(from_cmdline == NULL) return(1); | 1111 | if(from_cmdline == NULL) |
1112 | if(!strcmp(from_cmdline, from_cow)) return(1); | 1112 | return 0; |
1113 | if(!strcmp(from_cmdline, from_cow)) | ||
1114 | return 0; | ||
1113 | 1115 | ||
1114 | err = os_stat_file(from_cmdline, &buf1); | 1116 | err = os_stat_file(from_cmdline, &buf1); |
1115 | if(err < 0){ | 1117 | if(err < 0){ |
1116 | printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err); | 1118 | printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err); |
1117 | return(1); | 1119 | return 0; |
1118 | } | 1120 | } |
1119 | err = os_stat_file(from_cow, &buf2); | 1121 | err = os_stat_file(from_cow, &buf2); |
1120 | if(err < 0){ | 1122 | if(err < 0){ |
1121 | printk("Couldn't stat '%s', err = %d\n", from_cow, -err); | 1123 | printk("Couldn't stat '%s', err = %d\n", from_cow, -err); |
1122 | return(1); | 1124 | return 1; |
1123 | } | 1125 | } |
1124 | if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino)) | 1126 | if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino)) |
1125 | return(1); | 1127 | return 0; |
1126 | 1128 | ||
1127 | printk("Backing file mismatch - \"%s\" requested,\n" | 1129 | printk("Backing file mismatch - \"%s\" requested,\n" |
1128 | "\"%s\" specified in COW header of \"%s\"\n", | 1130 | "\"%s\" specified in COW header of \"%s\"\n", |
1129 | from_cmdline, from_cow, cow); | 1131 | from_cmdline, from_cow, cow); |
1130 | return(0); | 1132 | return 1; |
1131 | } | 1133 | } |
1132 | 1134 | ||
1133 | static int backing_file_mismatch(char *file, __u64 size, time_t mtime) | 1135 | static int backing_file_mismatch(char *file, __u64 size, time_t mtime) |
@@ -1189,7 +1191,7 @@ int open_ubd_file(char *file, struct openflags *openflags, | |||
1189 | unsigned long long size; | 1191 | unsigned long long size; |
1190 | __u32 version, align; | 1192 | __u32 version, align; |
1191 | char *backing_file; | 1193 | char *backing_file; |
1192 | int fd, err, sectorsize, same, mode = 0644; | 1194 | int fd, err, sectorsize, asked_switch, mode = 0644; |
1193 | 1195 | ||
1194 | fd = os_open_file(file, *openflags, mode); | 1196 | fd = os_open_file(file, *openflags, mode); |
1195 | if(fd < 0){ | 1197 | if(fd < 0){ |
@@ -1209,6 +1211,7 @@ int open_ubd_file(char *file, struct openflags *openflags, | |||
1209 | goto out_close; | 1211 | goto out_close; |
1210 | } | 1212 | } |
1211 | 1213 | ||
1214 | /* Succesful return case! */ | ||
1212 | if(backing_file_out == NULL) return(fd); | 1215 | if(backing_file_out == NULL) return(fd); |
1213 | 1216 | ||
1214 | err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime, | 1217 | err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime, |
@@ -1220,17 +1223,16 @@ int open_ubd_file(char *file, struct openflags *openflags, | |||
1220 | } | 1223 | } |
1221 | if(err) return(fd); | 1224 | if(err) return(fd); |
1222 | 1225 | ||
1223 | if(backing_file_out == NULL) return(fd); | 1226 | asked_switch = path_requires_switch(*backing_file_out, backing_file, file); |
1224 | |||
1225 | same = same_backing_files(*backing_file_out, backing_file, file); | ||
1226 | 1227 | ||
1227 | if(!same && !backing_file_mismatch(*backing_file_out, size, mtime)){ | 1228 | /* Allow switching only if no mismatch. */ |
1229 | if (asked_switch && !backing_file_mismatch(*backing_file_out, size, mtime)) { | ||
1228 | printk("Switching backing file to '%s'\n", *backing_file_out); | 1230 | printk("Switching backing file to '%s'\n", *backing_file_out); |
1229 | err = write_cow_header(file, fd, *backing_file_out, | 1231 | err = write_cow_header(file, fd, *backing_file_out, |
1230 | sectorsize, align, &size); | 1232 | sectorsize, align, &size); |
1231 | if(err){ | 1233 | if(err){ |
1232 | printk("Switch failed, errno = %d\n", -err); | 1234 | printk("Switch failed, errno = %d\n", -err); |
1233 | return(err); | 1235 | goto out_close; |
1234 | } | 1236 | } |
1235 | } | 1237 | } |
1236 | else { | 1238 | else { |