After some thoughts I decided to fix this bug.
It appears that you need to use O_LARGEFILE flag to filp_open() if the caller can handle 64 bit addressing in the file. And since cloop uses 64bit loff_t addresses it should be able to do it.
Attached is a patch addressing this problem. I also made it gracefully handle inability to open a file - unregister major number and all disks.
As a bonus, I've added some handling of LOOP_GET/SET_STATUS ioctl calls too. This way losetup will be able to show which file keeps a cloop device and as a result the cloop module itself.
Hope you like it, Igor
--- modules/cloop/compressed_loop.c.orig 2005-03-04 21:17:23.000000000 -0500 +++ modules/cloop/compressed_loop.c 2005-03-04 21:04:46.000000000 -0500 @@ -120,6 +120,7 @@ struct file *backing_file; /* associated file */ struct inode *backing_inode; /* for bmap */ + char backing_file_name[LO_NAME_SIZE]; unsigned int underlying_blksize; int refcnt; @@ -448,6 +449,8 @@ } clo->backing_file = file; + memcpy(clo->backing_file_name, filename, LO_NAME_SIZE); + clo->backing_file_name[LO_NAME_SIZE-1] = 0; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) clo->dev = dev; #endif @@ -625,6 +628,7 @@ error_release: if(bbuf) vfree(bbuf); clo->backing_file=NULL; + memset(clo->backing_file_name, 0, LO_NAME_SIZE); return error; } @@ -663,6 +667,7 @@ else { filp_close(initial_file,0); initial_file=NULL; } clo->backing_file = NULL; clo->backing_inode = NULL; + memset(clo->backing_file_name, 0, LO_NAME_SIZE); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) cloop_sizes[cloop_num] = 0; cloop_blksizes[cloop_num] = 0; @@ -678,6 +683,7 @@ { struct cloop_device *clo; int cloop_num, err=0; + struct loop_info info; if (!inode) return -EINVAL; if (MAJOR(inode->i_rdev) != MAJOR_NR) { @@ -700,8 +706,26 @@ err = clo_clr_fd(cloop_num, inode->i_bdev); break; case LOOP_SET_STATUS: + if(copy_from_user(&info,(struct loop_info __user *)arg,sizeof(info))) + err = -EFAULT; + else if (clo->backing_file) { + memcpy(clo->backing_file_name, info.lo_name, LO_NAME_SIZE); + clo->backing_file_name[LO_NAME_SIZE-1] = 0; + } else + err = -ENXIO; + break; case LOOP_GET_STATUS: - err=0; break; + memset(&info, 0, sizeof(info)); + if (clo->backing_file) { + memcpy(info.lo_name, clo->backing_file_name, LO_NAME_SIZE); + info.lo_number = cloop_num; + info.lo_inode = clo->backing_inode->i_ino; + info.lo_device = new_encode_dev(clo->backing_inode->i_rdev); + if(copy_to_user((struct loop_info __user *)arg,&info,sizeof(info))) + err = -EFAULT; + } else + err = -ENXIO; + break; default: err = -EINVAL; } @@ -832,13 +856,16 @@ if(file) /* global file name for first cloop-Device is a module option string. */ { - initial_file=filp_open(file,0x00,0x00); - if(initial_file==NULL||IS_ERR(initial_file)) + initial_file=filp_open(file, O_RDONLY | O_LARGEFILE, 0); + if(initial_file==NULL||IS_ERR(initial_file)) { printk(KERN_ERR - "%s: Unable to get file %s for cloop device\n", - cloop_name, file); - return -EINVAL; + "%s: Unable to get file %s for cloop device (%ld)\n", + cloop_name, file, PTR_ERR(initial_file)); + error = -EINVAL; + initial_file = NULL; + i=max_cloop; + goto out_mem; } error=clo_set_file(0,initial_file,file); if(error) { i=max_cloop; goto out_mem; } @@ -857,6 +884,7 @@ /* error_filp_close: */ if(initial_file) filp_close(initial_file,0); initial_file=NULL; cloop_dev[0].backing_file=NULL; + memset(cloop_dev[0].backing_file_name, 0, LO_NAME_SIZE); return error; }