in drivers/ubd_kern.c [625:702]
static int open_ubd_file(char *file, struct openflags *openflags, int shared,
char **backing_file_out, int *bitmap_offset_out,
unsigned long *bitmap_len_out, int *data_offset_out,
int *create_cow_out)
{
time64_t mtime;
unsigned long long size;
__u32 version, align;
char *backing_file;
int fd, err, sectorsize, asked_switch, mode = 0644;
fd = os_open_file(file, *openflags, mode);
if (fd < 0) {
if ((fd == -ENOENT) && (create_cow_out != NULL))
*create_cow_out = 1;
if (!openflags->w ||
((fd != -EROFS) && (fd != -EACCES)))
return fd;
openflags->w = 0;
fd = os_open_file(file, *openflags, mode);
if (fd < 0)
return fd;
}
if (shared)
printk(KERN_INFO "Not locking \"%s\" on the host\n", file);
else {
err = os_lock_file(fd, openflags->w);
if (err < 0) {
printk(KERN_ERR "Failed to lock '%s', err = %d\n",
file, -err);
goto out_close;
}
}
/* Successful return case! */
if (backing_file_out == NULL)
return fd;
err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime,
&size, §orsize, &align, bitmap_offset_out);
if (err && (*backing_file_out != NULL)) {
printk(KERN_ERR "Failed to read COW header from COW file "
"\"%s\", errno = %d\n", file, -err);
goto out_close;
}
if (err)
return fd;
asked_switch = path_requires_switch(*backing_file_out, backing_file,
file);
/* Allow switching only if no mismatch. */
if (asked_switch && !backing_file_mismatch(*backing_file_out, size,
mtime)) {
printk(KERN_ERR "Switching backing file to '%s'\n",
*backing_file_out);
err = write_cow_header(file, fd, *backing_file_out,
sectorsize, align, &size);
if (err) {
printk(KERN_ERR "Switch failed, errno = %d\n", -err);
goto out_close;
}
} else {
*backing_file_out = backing_file;
err = backing_file_mismatch(*backing_file_out, size, mtime);
if (err)
goto out_close;
}
cow_sizes(version, size, sectorsize, align, *bitmap_offset_out,
bitmap_len_out, data_offset_out);
return fd;
out_close:
os_close_file(fd);
return err;
}