@ -161,17 +161,19 @@ static struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = {
& xor_funcs
} ;
static loff_t get_loop_size ( struct loop_device * lo , struct file * file )
static loff_t get_size ( loff_t offset , loff_t sizelimit , struct file * file )
{
loff_t size , offset , loopsize ;
loff_t size , loopsize ;
/* Compute loopsize in bytes */
size = i_size_read ( file - > f_mapping - > host ) ;
offset = lo - > lo_offset ;
loopsize = size - offset ;
if ( lo - > lo_sizelimit > 0 & & lo - > lo_sizelimit < loopsize )
loopsize = lo - > lo_sizelimit ;
/* offset is beyond i_size, wierd but possible */
if ( loopsize < 0 )
return 0 ;
if ( sizelimit > 0 & & sizelimit < loopsize )
loopsize = sizelimit ;
/*
* Unfortunately , if we want to do I / O on the device ,
* the number of 512 - byte sectors has to fit into a sector_t .
@ -179,17 +181,25 @@ static loff_t get_loop_size(struct loop_device *lo, struct file *file)
return loopsize > > 9 ;
}
static loff_t get_loop_size ( struct loop_device * lo , struct file * file )
{
return get_size ( lo - > lo_offset , lo - > lo_sizelimit , file ) ;
}
static int
figure_loop_size ( struct loop_device * lo )
figure_loop_size ( struct loop_device * lo , loff_t offset , loff_t sizelimit )
{
loff_t size = get_loop_size ( lo , lo - > lo_backing_file ) ;
loff_t size = get_size ( offset , sizelimit , lo - > lo_backing_file ) ;
sector_t x = ( sector_t ) size ;
if ( unlikely ( ( loff_t ) x ! = size ) )
return - EFBIG ;
if ( lo - > lo_offset ! = offset )
lo - > lo_offset = offset ;
if ( lo - > lo_sizelimit ! = sizelimit )
lo - > lo_sizelimit = sizelimit ;
set_capacity ( lo - > lo_disk , x ) ;
return 0 ;
return 0 ;
}
static inline int
@ -372,7 +382,8 @@ do_lo_receive(struct loop_device *lo,
if ( retval < 0 )
return retval ;
if ( retval ! = bvec - > bv_len )
return - EIO ;
return 0 ;
}
@ -1058,9 +1069,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
if ( lo - > lo_offset ! = info - > lo_offset | |
lo - > lo_sizelimit ! = info - > lo_sizelimit ) {
lo - > lo_offset = info - > lo_offset ;
lo - > lo_sizelimit = info - > lo_sizelimit ;
if ( figure_loop_size ( lo ) )
if ( figure_loop_size ( lo , info - > lo_offset , info - > lo_sizelimit ) )
return - EFBIG ;
}
loop_config_discard ( lo ) ;
@ -1246,7 +1255,7 @@ static int loop_set_capacity(struct loop_device *lo, struct block_device *bdev)
err = - ENXIO ;
if ( unlikely ( lo - > lo_state ! = Lo_bound ) )
goto out ;
err = figure_loop_size ( lo ) ;
err = figure_loop_size ( lo , lo - > lo_offset , lo - > lo_sizelimit ) ;
if ( unlikely ( err ) )
goto out ;
sec = get_capacity ( lo - > lo_disk ) ;
@ -1284,13 +1293,19 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode,
goto out_unlocked ;
break ;
case LOOP_SET_STATUS :
err = loop_set_status_old ( lo , ( struct loop_info __user * ) arg ) ;
err = - EPERM ;
if ( ( mode & FMODE_WRITE ) | | capable ( CAP_SYS_ADMIN ) )
err = loop_set_status_old ( lo ,
( struct loop_info __user * ) arg ) ;
break ;
case LOOP_GET_STATUS :
err = loop_get_status_old ( lo , ( struct loop_info __user * ) arg ) ;
break ;
case LOOP_SET_STATUS64 :
err = loop_set_status64 ( lo , ( struct loop_info64 __user * ) arg ) ;
err = - EPERM ;
if ( ( mode & FMODE_WRITE ) | | capable ( CAP_SYS_ADMIN ) )
err = loop_set_status64 ( lo ,
( struct loop_info64 __user * ) arg ) ;
break ;
case LOOP_GET_STATUS64 :
err = loop_get_status64 ( lo , ( struct loop_info64 __user * ) arg ) ;