2006-07-04 04:27:12 +04:00
/*
* linux / fs / ocfs2 / ioctl . c
*
* Copyright ( C ) 2006 Herbert Poetzl
* adapted from Remy Card ' s ext2 / ioctl . c
*/
# include <linux/fs.h>
# include <linux/mount.h>
2010-01-27 05:21:52 +03:00
# include <linux/compat.h>
2006-07-04 04:27:12 +04:00
# define MLOG_MASK_PREFIX ML_INODE
# include <cluster/masklog.h>
# include "ocfs2.h"
# include "alloc.h"
# include "dlmglue.h"
2007-03-10 03:53:21 +03:00
# include "file.h"
2006-07-04 04:27:12 +04:00
# include "inode.h"
# include "journal.h"
# include "ocfs2_fs.h"
2006-07-10 03:32:51 +04:00
# include "ioctl.h"
2007-12-18 10:47:03 +03:00
# include "resize.h"
2009-09-21 07:25:14 +04:00
# include "refcounttree.h"
2006-07-10 03:32:51 +04:00
2006-07-04 04:27:12 +04:00
# include <linux/ext2_fs.h>
Ocfs2: Add new OCFS2_IOC_INFO ioctl for ocfs2 v8.
The reason why we need this ioctl is to offer the none-privileged
end-user a possibility to get filesys info gathering.
We use OCFS2_IOC_INFO to manipulate the new ioctl, userspace passes a
structure to kernel containing an array of request pointers and request
count, such as,
* From userspace:
struct ocfs2_info_blocksize oib = {
.ib_req = {
.ir_magic = OCFS2_INFO_MAGIC,
.ir_code = OCFS2_INFO_BLOCKSIZE,
...
}
...
}
struct ocfs2_info_clustersize oic = {
...
}
uint64_t reqs[2] = {(unsigned long)&oib,
(unsigned long)&oic};
struct ocfs2_info info = {
.oi_requests = reqs,
.oi_count = 2,
}
ret = ioctl(fd, OCFS2_IOC_INFO, &info);
* In kernel:
Get the request pointers from *info*, then handle each request one bye one.
Idea here is to make the spearated request small enough to guarantee
a better backward&forward compatibility since a small piece of request
would be less likely to be broken if filesys on raw disk get changed.
Currently, the following 7 requests are supported per the requirement from
userspace tool o2info, and I believe it will grow over time:-)
OCFS2_INFO_CLUSTERSIZE
OCFS2_INFO_BLOCKSIZE
OCFS2_INFO_MAXSLOTS
OCFS2_INFO_LABEL
OCFS2_INFO_UUID
OCFS2_INFO_FS_FEATURES
OCFS2_INFO_JOURNAL_SIZE
This ioctl is only specific to OCFS2.
Signed-off-by: Tristan Ye <tristan.ye@oracle.com>
Signed-off-by: Joel Becker <joel.becker@oracle.com>
2010-05-22 12:26:33 +04:00
# define o2info_from_user(a, b) \
copy_from_user ( & ( a ) , ( b ) , sizeof ( a ) )
# define o2info_to_user(a, b) \
copy_to_user ( ( typeof ( a ) __user * ) b , & ( a ) , sizeof ( a ) )
/*
* This call is void because we are already reporting an error that may
* be - EFAULT . The error will be returned from the ioctl ( 2 ) call . It ' s
* just a best - effort to tell userspace that this request caused the error .
*/
static inline void __o2info_set_request_error ( struct ocfs2_info_request * kreq ,
struct ocfs2_info_request __user * req )
{
kreq - > ir_flags | = OCFS2_INFO_FL_ERROR ;
( void ) put_user ( kreq - > ir_flags , ( __u32 __user * ) & ( req - > ir_flags ) ) ;
}
# define o2info_set_request_error(a, b) \
__o2info_set_request_error ( ( struct ocfs2_info_request * ) & ( a ) , b )
2006-07-04 04:27:12 +04:00
static int ocfs2_get_inode_attr ( struct inode * inode , unsigned * flags )
{
int status ;
2007-10-19 02:30:42 +04:00
status = ocfs2_inode_lock ( inode , NULL , 0 ) ;
2006-07-04 04:27:12 +04:00
if ( status < 0 ) {
mlog_errno ( status ) ;
return status ;
}
2007-04-27 22:08:01 +04:00
ocfs2_get_inode_flags ( OCFS2_I ( inode ) ) ;
2006-07-04 04:27:12 +04:00
* flags = OCFS2_I ( inode ) - > ip_attr ;
2007-10-19 02:30:42 +04:00
ocfs2_inode_unlock ( inode , 0 ) ;
2006-07-04 04:27:12 +04:00
mlog_exit ( status ) ;
return status ;
}
static int ocfs2_set_inode_attr ( struct inode * inode , unsigned flags ,
unsigned mask )
{
struct ocfs2_inode_info * ocfs2_inode = OCFS2_I ( inode ) ;
struct ocfs2_super * osb = OCFS2_SB ( inode - > i_sb ) ;
2006-10-10 05:11:45 +04:00
handle_t * handle = NULL ;
2006-07-04 04:27:12 +04:00
struct buffer_head * bh = NULL ;
unsigned oldflags ;
int status ;
mutex_lock ( & inode - > i_mutex ) ;
2007-10-19 02:30:42 +04:00
status = ocfs2_inode_lock ( inode , & bh , 1 ) ;
2006-07-04 04:27:12 +04:00
if ( status < 0 ) {
mlog_errno ( status ) ;
goto bail ;
}
status = - EACCES ;
2007-07-17 13:30:08 +04:00
if ( ! is_owner_or_cap ( inode ) )
2006-07-04 04:27:12 +04:00
goto bail_unlock ;
if ( ! S_ISDIR ( inode - > i_mode ) )
flags & = ~ OCFS2_DIRSYNC_FL ;
2006-10-10 04:26:22 +04:00
handle = ocfs2_start_trans ( osb , OCFS2_INODE_UPDATE_CREDITS ) ;
2006-07-04 04:27:12 +04:00
if ( IS_ERR ( handle ) ) {
status = PTR_ERR ( handle ) ;
mlog_errno ( status ) ;
goto bail_unlock ;
}
oldflags = ocfs2_inode - > ip_attr ;
flags = flags & mask ;
flags | = oldflags & ~ mask ;
/*
* The IMMUTABLE and APPEND_ONLY flags can only be changed by
* the relevant capability .
*/
status = - EPERM ;
if ( ( oldflags & OCFS2_IMMUTABLE_FL ) | | ( ( flags ^ oldflags ) &
( OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL ) ) ) {
if ( ! capable ( CAP_LINUX_IMMUTABLE ) )
goto bail_unlock ;
}
ocfs2_inode - > ip_attr = flags ;
ocfs2_set_inode_flags ( inode ) ;
status = ocfs2_mark_inode_dirty ( handle , inode , bh ) ;
if ( status < 0 )
mlog_errno ( status ) ;
2006-10-10 03:48:10 +04:00
ocfs2_commit_trans ( osb , handle ) ;
2006-07-04 04:27:12 +04:00
bail_unlock :
2007-10-19 02:30:42 +04:00
ocfs2_inode_unlock ( inode , 1 ) ;
2006-07-04 04:27:12 +04:00
bail :
mutex_unlock ( & inode - > i_mutex ) ;
2008-10-08 01:25:16 +04:00
brelse ( bh ) ;
2006-07-04 04:27:12 +04:00
mlog_exit ( status ) ;
return status ;
}
Ocfs2: Add new OCFS2_IOC_INFO ioctl for ocfs2 v8.
The reason why we need this ioctl is to offer the none-privileged
end-user a possibility to get filesys info gathering.
We use OCFS2_IOC_INFO to manipulate the new ioctl, userspace passes a
structure to kernel containing an array of request pointers and request
count, such as,
* From userspace:
struct ocfs2_info_blocksize oib = {
.ib_req = {
.ir_magic = OCFS2_INFO_MAGIC,
.ir_code = OCFS2_INFO_BLOCKSIZE,
...
}
...
}
struct ocfs2_info_clustersize oic = {
...
}
uint64_t reqs[2] = {(unsigned long)&oib,
(unsigned long)&oic};
struct ocfs2_info info = {
.oi_requests = reqs,
.oi_count = 2,
}
ret = ioctl(fd, OCFS2_IOC_INFO, &info);
* In kernel:
Get the request pointers from *info*, then handle each request one bye one.
Idea here is to make the spearated request small enough to guarantee
a better backward&forward compatibility since a small piece of request
would be less likely to be broken if filesys on raw disk get changed.
Currently, the following 7 requests are supported per the requirement from
userspace tool o2info, and I believe it will grow over time:-)
OCFS2_INFO_CLUSTERSIZE
OCFS2_INFO_BLOCKSIZE
OCFS2_INFO_MAXSLOTS
OCFS2_INFO_LABEL
OCFS2_INFO_UUID
OCFS2_INFO_FS_FEATURES
OCFS2_INFO_JOURNAL_SIZE
This ioctl is only specific to OCFS2.
Signed-off-by: Tristan Ye <tristan.ye@oracle.com>
Signed-off-by: Joel Becker <joel.becker@oracle.com>
2010-05-22 12:26:33 +04:00
int ocfs2_info_handle_blocksize ( struct inode * inode ,
struct ocfs2_info_request __user * req )
{
int status = - EFAULT ;
struct ocfs2_info_blocksize oib ;
if ( o2info_from_user ( oib , req ) )
goto bail ;
oib . ib_blocksize = inode - > i_sb - > s_blocksize ;
oib . ib_req . ir_flags | = OCFS2_INFO_FL_FILLED ;
if ( o2info_to_user ( oib , req ) )
goto bail ;
status = 0 ;
bail :
if ( status )
o2info_set_request_error ( oib , req ) ;
return status ;
}
int ocfs2_info_handle_clustersize ( struct inode * inode ,
struct ocfs2_info_request __user * req )
{
int status = - EFAULT ;
struct ocfs2_info_clustersize oic ;
struct ocfs2_super * osb = OCFS2_SB ( inode - > i_sb ) ;
if ( o2info_from_user ( oic , req ) )
goto bail ;
oic . ic_clustersize = osb - > s_clustersize ;
oic . ic_req . ir_flags | = OCFS2_INFO_FL_FILLED ;
if ( o2info_to_user ( oic , req ) )
goto bail ;
status = 0 ;
bail :
if ( status )
o2info_set_request_error ( oic , req ) ;
return status ;
}
int ocfs2_info_handle_maxslots ( struct inode * inode ,
struct ocfs2_info_request __user * req )
{
int status = - EFAULT ;
struct ocfs2_info_maxslots oim ;
struct ocfs2_super * osb = OCFS2_SB ( inode - > i_sb ) ;
if ( o2info_from_user ( oim , req ) )
goto bail ;
oim . im_max_slots = osb - > max_slots ;
oim . im_req . ir_flags | = OCFS2_INFO_FL_FILLED ;
if ( o2info_to_user ( oim , req ) )
goto bail ;
status = 0 ;
bail :
if ( status )
o2info_set_request_error ( oim , req ) ;
return status ;
}
int ocfs2_info_handle_label ( struct inode * inode ,
struct ocfs2_info_request __user * req )
{
int status = - EFAULT ;
struct ocfs2_info_label oil ;
struct ocfs2_super * osb = OCFS2_SB ( inode - > i_sb ) ;
if ( o2info_from_user ( oil , req ) )
goto bail ;
memcpy ( oil . il_label , osb - > vol_label , OCFS2_MAX_VOL_LABEL_LEN ) ;
oil . il_req . ir_flags | = OCFS2_INFO_FL_FILLED ;
if ( o2info_to_user ( oil , req ) )
goto bail ;
status = 0 ;
bail :
if ( status )
o2info_set_request_error ( oil , req ) ;
return status ;
}
int ocfs2_info_handle_uuid ( struct inode * inode ,
struct ocfs2_info_request __user * req )
{
int status = - EFAULT ;
struct ocfs2_info_uuid oiu ;
struct ocfs2_super * osb = OCFS2_SB ( inode - > i_sb ) ;
if ( o2info_from_user ( oiu , req ) )
goto bail ;
memcpy ( oiu . iu_uuid_str , osb - > uuid_str , OCFS2_TEXT_UUID_LEN + 1 ) ;
oiu . iu_req . ir_flags | = OCFS2_INFO_FL_FILLED ;
if ( o2info_to_user ( oiu , req ) )
goto bail ;
status = 0 ;
bail :
if ( status )
o2info_set_request_error ( oiu , req ) ;
return status ;
}
int ocfs2_info_handle_fs_features ( struct inode * inode ,
struct ocfs2_info_request __user * req )
{
int status = - EFAULT ;
struct ocfs2_info_fs_features oif ;
struct ocfs2_super * osb = OCFS2_SB ( inode - > i_sb ) ;
if ( o2info_from_user ( oif , req ) )
goto bail ;
oif . if_compat_features = osb - > s_feature_compat ;
oif . if_incompat_features = osb - > s_feature_incompat ;
oif . if_ro_compat_features = osb - > s_feature_ro_compat ;
oif . if_req . ir_flags | = OCFS2_INFO_FL_FILLED ;
if ( o2info_to_user ( oif , req ) )
goto bail ;
status = 0 ;
bail :
if ( status )
o2info_set_request_error ( oif , req ) ;
return status ;
}
int ocfs2_info_handle_journal_size ( struct inode * inode ,
struct ocfs2_info_request __user * req )
{
int status = - EFAULT ;
struct ocfs2_info_journal_size oij ;
struct ocfs2_super * osb = OCFS2_SB ( inode - > i_sb ) ;
if ( o2info_from_user ( oij , req ) )
goto bail ;
oij . ij_journal_size = osb - > journal - > j_inode - > i_size ;
oij . ij_req . ir_flags | = OCFS2_INFO_FL_FILLED ;
if ( o2info_to_user ( oij , req ) )
goto bail ;
status = 0 ;
bail :
if ( status )
o2info_set_request_error ( oij , req ) ;
return status ;
}
int ocfs2_info_handle_unknown ( struct inode * inode ,
struct ocfs2_info_request __user * req )
{
int status = - EFAULT ;
struct ocfs2_info_request oir ;
if ( o2info_from_user ( oir , req ) )
goto bail ;
oir . ir_flags & = ~ OCFS2_INFO_FL_FILLED ;
if ( o2info_to_user ( oir , req ) )
goto bail ;
status = 0 ;
bail :
if ( status )
o2info_set_request_error ( oir , req ) ;
return status ;
}
/*
* Validate and distinguish OCFS2_IOC_INFO requests .
*
* - validate the magic number .
* - distinguish different requests .
* - validate size of different requests .
*/
int ocfs2_info_handle_request ( struct inode * inode ,
struct ocfs2_info_request __user * req )
{
int status = - EFAULT ;
struct ocfs2_info_request oir ;
if ( o2info_from_user ( oir , req ) )
goto bail ;
status = - EINVAL ;
if ( oir . ir_magic ! = OCFS2_INFO_MAGIC )
goto bail ;
switch ( oir . ir_code ) {
case OCFS2_INFO_BLOCKSIZE :
if ( oir . ir_size = = sizeof ( struct ocfs2_info_blocksize ) )
status = ocfs2_info_handle_blocksize ( inode , req ) ;
break ;
case OCFS2_INFO_CLUSTERSIZE :
if ( oir . ir_size = = sizeof ( struct ocfs2_info_clustersize ) )
status = ocfs2_info_handle_clustersize ( inode , req ) ;
break ;
case OCFS2_INFO_MAXSLOTS :
if ( oir . ir_size = = sizeof ( struct ocfs2_info_maxslots ) )
status = ocfs2_info_handle_maxslots ( inode , req ) ;
break ;
case OCFS2_INFO_LABEL :
if ( oir . ir_size = = sizeof ( struct ocfs2_info_label ) )
status = ocfs2_info_handle_label ( inode , req ) ;
break ;
case OCFS2_INFO_UUID :
if ( oir . ir_size = = sizeof ( struct ocfs2_info_uuid ) )
status = ocfs2_info_handle_uuid ( inode , req ) ;
break ;
case OCFS2_INFO_FS_FEATURES :
if ( oir . ir_size = = sizeof ( struct ocfs2_info_fs_features ) )
status = ocfs2_info_handle_fs_features ( inode , req ) ;
break ;
case OCFS2_INFO_JOURNAL_SIZE :
if ( oir . ir_size = = sizeof ( struct ocfs2_info_journal_size ) )
status = ocfs2_info_handle_journal_size ( inode , req ) ;
break ;
default :
status = ocfs2_info_handle_unknown ( inode , req ) ;
break ;
}
bail :
return status ;
}
int ocfs2_get_request_ptr ( struct ocfs2_info * info , int idx ,
u64 * req_addr , int compat_flag )
{
int status = - EFAULT ;
u64 __user * bp = NULL ;
if ( compat_flag ) {
# ifdef CONFIG_COMPAT
/*
* pointer bp stores the base address of a pointers array ,
* which collects all addresses of separate request .
*/
bp = ( u64 __user * ) ( unsigned long ) compat_ptr ( info - > oi_requests ) ;
# else
BUG ( ) ;
# endif
} else
bp = ( u64 __user * ) ( unsigned long ) ( info - > oi_requests ) ;
if ( o2info_from_user ( * req_addr , bp + idx ) )
goto bail ;
status = 0 ;
bail :
return status ;
}
/*
* OCFS2_IOC_INFO handles an array of requests passed from userspace .
*
* ocfs2_info_handle ( ) recevies a large info aggregation , grab and
* validate the request count from header , then break it into small
* pieces , later specific handlers can handle them one by one .
*
* Idea here is to make each separate request small enough to ensure
* a better backward & forward compatibility , since a small piece of
* request will be less likely to be broken if disk layout get changed .
*/
int ocfs2_info_handle ( struct inode * inode , struct ocfs2_info * info ,
int compat_flag )
{
int i , status = 0 ;
u64 req_addr ;
struct ocfs2_info_request __user * reqp ;
if ( ( info - > oi_count > OCFS2_INFO_MAX_REQUEST ) | |
( ! info - > oi_requests ) ) {
status = - EINVAL ;
goto bail ;
}
for ( i = 0 ; i < info - > oi_count ; i + + ) {
status = ocfs2_get_request_ptr ( info , i , & req_addr , compat_flag ) ;
if ( status )
break ;
reqp = ( struct ocfs2_info_request * ) ( unsigned long ) req_addr ;
if ( ! reqp ) {
status = - EINVAL ;
goto bail ;
}
status = ocfs2_info_handle_request ( inode , reqp ) ;
if ( status )
break ;
}
bail :
return status ;
}
2008-01-27 05:17:17 +03:00
long ocfs2_ioctl ( struct file * filp , unsigned int cmd , unsigned long arg )
2006-07-04 04:27:12 +04:00
{
2008-01-27 05:17:17 +03:00
struct inode * inode = filp - > f_path . dentry - > d_inode ;
2006-07-04 04:27:12 +04:00
unsigned int flags ;
2007-12-18 10:47:03 +03:00
int new_clusters ;
2006-07-04 04:27:12 +04:00
int status ;
2007-03-10 03:53:21 +03:00
struct ocfs2_space_resv sr ;
2007-12-18 10:47:25 +03:00
struct ocfs2_new_group_input input ;
2009-09-21 07:25:14 +04:00
struct reflink_arguments args ;
const char * old_path , * new_path ;
bool preserve ;
Ocfs2: Add new OCFS2_IOC_INFO ioctl for ocfs2 v8.
The reason why we need this ioctl is to offer the none-privileged
end-user a possibility to get filesys info gathering.
We use OCFS2_IOC_INFO to manipulate the new ioctl, userspace passes a
structure to kernel containing an array of request pointers and request
count, such as,
* From userspace:
struct ocfs2_info_blocksize oib = {
.ib_req = {
.ir_magic = OCFS2_INFO_MAGIC,
.ir_code = OCFS2_INFO_BLOCKSIZE,
...
}
...
}
struct ocfs2_info_clustersize oic = {
...
}
uint64_t reqs[2] = {(unsigned long)&oib,
(unsigned long)&oic};
struct ocfs2_info info = {
.oi_requests = reqs,
.oi_count = 2,
}
ret = ioctl(fd, OCFS2_IOC_INFO, &info);
* In kernel:
Get the request pointers from *info*, then handle each request one bye one.
Idea here is to make the spearated request small enough to guarantee
a better backward&forward compatibility since a small piece of request
would be less likely to be broken if filesys on raw disk get changed.
Currently, the following 7 requests are supported per the requirement from
userspace tool o2info, and I believe it will grow over time:-)
OCFS2_INFO_CLUSTERSIZE
OCFS2_INFO_BLOCKSIZE
OCFS2_INFO_MAXSLOTS
OCFS2_INFO_LABEL
OCFS2_INFO_UUID
OCFS2_INFO_FS_FEATURES
OCFS2_INFO_JOURNAL_SIZE
This ioctl is only specific to OCFS2.
Signed-off-by: Tristan Ye <tristan.ye@oracle.com>
Signed-off-by: Joel Becker <joel.becker@oracle.com>
2010-05-22 12:26:33 +04:00
struct ocfs2_info info ;
2006-07-04 04:27:12 +04:00
switch ( cmd ) {
case OCFS2_IOC_GETFLAGS :
status = ocfs2_get_inode_attr ( inode , & flags ) ;
if ( status < 0 )
return status ;
flags & = OCFS2_FL_VISIBLE ;
return put_user ( flags , ( int __user * ) arg ) ;
case OCFS2_IOC_SETFLAGS :
if ( get_user ( flags , ( int __user * ) arg ) )
return - EFAULT ;
2008-02-16 01:37:46 +03:00
status = mnt_want_write ( filp - > f_path . mnt ) ;
if ( status )
return status ;
status = ocfs2_set_inode_attr ( inode , flags ,
2006-07-04 04:27:12 +04:00
OCFS2_FL_MODIFIABLE ) ;
2008-02-16 01:37:46 +03:00
mnt_drop_write ( filp - > f_path . mnt ) ;
return status ;
2007-03-10 03:53:21 +03:00
case OCFS2_IOC_RESVSP :
case OCFS2_IOC_RESVSP64 :
case OCFS2_IOC_UNRESVSP :
case OCFS2_IOC_UNRESVSP64 :
if ( copy_from_user ( & sr , ( int __user * ) arg , sizeof ( sr ) ) )
return - EFAULT ;
return ocfs2_change_file_space ( filp , cmd , & sr ) ;
2007-12-18 10:47:03 +03:00
case OCFS2_IOC_GROUP_EXTEND :
2007-12-19 05:58:18 +03:00
if ( ! capable ( CAP_SYS_RESOURCE ) )
return - EPERM ;
2007-12-18 10:47:03 +03:00
if ( get_user ( new_clusters , ( int __user * ) arg ) )
return - EFAULT ;
return ocfs2_group_extend ( inode , new_clusters ) ;
2007-12-18 10:47:25 +03:00
case OCFS2_IOC_GROUP_ADD :
case OCFS2_IOC_GROUP_ADD64 :
2007-12-19 05:58:18 +03:00
if ( ! capable ( CAP_SYS_RESOURCE ) )
return - EPERM ;
2007-12-18 10:47:25 +03:00
if ( copy_from_user ( & input , ( int __user * ) arg , sizeof ( input ) ) )
return - EFAULT ;
return ocfs2_group_add ( inode , & input ) ;
2009-09-21 07:25:14 +04:00
case OCFS2_IOC_REFLINK :
if ( copy_from_user ( & args , ( struct reflink_arguments * ) arg ,
sizeof ( args ) ) )
return - EFAULT ;
old_path = ( const char * ) ( unsigned long ) args . old_path ;
new_path = ( const char * ) ( unsigned long ) args . new_path ;
preserve = ( args . preserve ! = 0 ) ;
return ocfs2_reflink_ioctl ( inode , old_path , new_path , preserve ) ;
Ocfs2: Add new OCFS2_IOC_INFO ioctl for ocfs2 v8.
The reason why we need this ioctl is to offer the none-privileged
end-user a possibility to get filesys info gathering.
We use OCFS2_IOC_INFO to manipulate the new ioctl, userspace passes a
structure to kernel containing an array of request pointers and request
count, such as,
* From userspace:
struct ocfs2_info_blocksize oib = {
.ib_req = {
.ir_magic = OCFS2_INFO_MAGIC,
.ir_code = OCFS2_INFO_BLOCKSIZE,
...
}
...
}
struct ocfs2_info_clustersize oic = {
...
}
uint64_t reqs[2] = {(unsigned long)&oib,
(unsigned long)&oic};
struct ocfs2_info info = {
.oi_requests = reqs,
.oi_count = 2,
}
ret = ioctl(fd, OCFS2_IOC_INFO, &info);
* In kernel:
Get the request pointers from *info*, then handle each request one bye one.
Idea here is to make the spearated request small enough to guarantee
a better backward&forward compatibility since a small piece of request
would be less likely to be broken if filesys on raw disk get changed.
Currently, the following 7 requests are supported per the requirement from
userspace tool o2info, and I believe it will grow over time:-)
OCFS2_INFO_CLUSTERSIZE
OCFS2_INFO_BLOCKSIZE
OCFS2_INFO_MAXSLOTS
OCFS2_INFO_LABEL
OCFS2_INFO_UUID
OCFS2_INFO_FS_FEATURES
OCFS2_INFO_JOURNAL_SIZE
This ioctl is only specific to OCFS2.
Signed-off-by: Tristan Ye <tristan.ye@oracle.com>
Signed-off-by: Joel Becker <joel.becker@oracle.com>
2010-05-22 12:26:33 +04:00
case OCFS2_IOC_INFO :
if ( copy_from_user ( & info , ( struct ocfs2_info __user * ) arg ,
sizeof ( struct ocfs2_info ) ) )
return - EFAULT ;
return ocfs2_info_handle ( inode , & info , 0 ) ;
2006-07-04 04:27:12 +04:00
default :
return - ENOTTY ;
}
}
2007-03-10 02:56:28 +03:00
# ifdef CONFIG_COMPAT
long ocfs2_compat_ioctl ( struct file * file , unsigned cmd , unsigned long arg )
{
2010-01-27 05:21:52 +03:00
bool preserve ;
struct reflink_arguments args ;
struct inode * inode = file - > f_path . dentry - > d_inode ;
Ocfs2: Add new OCFS2_IOC_INFO ioctl for ocfs2 v8.
The reason why we need this ioctl is to offer the none-privileged
end-user a possibility to get filesys info gathering.
We use OCFS2_IOC_INFO to manipulate the new ioctl, userspace passes a
structure to kernel containing an array of request pointers and request
count, such as,
* From userspace:
struct ocfs2_info_blocksize oib = {
.ib_req = {
.ir_magic = OCFS2_INFO_MAGIC,
.ir_code = OCFS2_INFO_BLOCKSIZE,
...
}
...
}
struct ocfs2_info_clustersize oic = {
...
}
uint64_t reqs[2] = {(unsigned long)&oib,
(unsigned long)&oic};
struct ocfs2_info info = {
.oi_requests = reqs,
.oi_count = 2,
}
ret = ioctl(fd, OCFS2_IOC_INFO, &info);
* In kernel:
Get the request pointers from *info*, then handle each request one bye one.
Idea here is to make the spearated request small enough to guarantee
a better backward&forward compatibility since a small piece of request
would be less likely to be broken if filesys on raw disk get changed.
Currently, the following 7 requests are supported per the requirement from
userspace tool o2info, and I believe it will grow over time:-)
OCFS2_INFO_CLUSTERSIZE
OCFS2_INFO_BLOCKSIZE
OCFS2_INFO_MAXSLOTS
OCFS2_INFO_LABEL
OCFS2_INFO_UUID
OCFS2_INFO_FS_FEATURES
OCFS2_INFO_JOURNAL_SIZE
This ioctl is only specific to OCFS2.
Signed-off-by: Tristan Ye <tristan.ye@oracle.com>
Signed-off-by: Joel Becker <joel.becker@oracle.com>
2010-05-22 12:26:33 +04:00
struct ocfs2_info info ;
2010-01-27 05:21:52 +03:00
2007-03-10 02:56:28 +03:00
switch ( cmd ) {
case OCFS2_IOC32_GETFLAGS :
cmd = OCFS2_IOC_GETFLAGS ;
break ;
case OCFS2_IOC32_SETFLAGS :
cmd = OCFS2_IOC_SETFLAGS ;
break ;
2007-03-10 03:53:21 +03:00
case OCFS2_IOC_RESVSP :
case OCFS2_IOC_RESVSP64 :
case OCFS2_IOC_UNRESVSP :
case OCFS2_IOC_UNRESVSP64 :
2007-12-18 10:47:03 +03:00
case OCFS2_IOC_GROUP_EXTEND :
2007-12-18 10:47:25 +03:00
case OCFS2_IOC_GROUP_ADD :
case OCFS2_IOC_GROUP_ADD64 :
2007-03-10 03:53:21 +03:00
break ;
2010-01-27 05:21:52 +03:00
case OCFS2_IOC_REFLINK :
if ( copy_from_user ( & args , ( struct reflink_arguments * ) arg ,
sizeof ( args ) ) )
return - EFAULT ;
preserve = ( args . preserve ! = 0 ) ;
return ocfs2_reflink_ioctl ( inode , compat_ptr ( args . old_path ) ,
compat_ptr ( args . new_path ) , preserve ) ;
Ocfs2: Add new OCFS2_IOC_INFO ioctl for ocfs2 v8.
The reason why we need this ioctl is to offer the none-privileged
end-user a possibility to get filesys info gathering.
We use OCFS2_IOC_INFO to manipulate the new ioctl, userspace passes a
structure to kernel containing an array of request pointers and request
count, such as,
* From userspace:
struct ocfs2_info_blocksize oib = {
.ib_req = {
.ir_magic = OCFS2_INFO_MAGIC,
.ir_code = OCFS2_INFO_BLOCKSIZE,
...
}
...
}
struct ocfs2_info_clustersize oic = {
...
}
uint64_t reqs[2] = {(unsigned long)&oib,
(unsigned long)&oic};
struct ocfs2_info info = {
.oi_requests = reqs,
.oi_count = 2,
}
ret = ioctl(fd, OCFS2_IOC_INFO, &info);
* In kernel:
Get the request pointers from *info*, then handle each request one bye one.
Idea here is to make the spearated request small enough to guarantee
a better backward&forward compatibility since a small piece of request
would be less likely to be broken if filesys on raw disk get changed.
Currently, the following 7 requests are supported per the requirement from
userspace tool o2info, and I believe it will grow over time:-)
OCFS2_INFO_CLUSTERSIZE
OCFS2_INFO_BLOCKSIZE
OCFS2_INFO_MAXSLOTS
OCFS2_INFO_LABEL
OCFS2_INFO_UUID
OCFS2_INFO_FS_FEATURES
OCFS2_INFO_JOURNAL_SIZE
This ioctl is only specific to OCFS2.
Signed-off-by: Tristan Ye <tristan.ye@oracle.com>
Signed-off-by: Joel Becker <joel.becker@oracle.com>
2010-05-22 12:26:33 +04:00
case OCFS2_IOC_INFO :
if ( copy_from_user ( & info , ( struct ocfs2_info __user * ) arg ,
sizeof ( struct ocfs2_info ) ) )
return - EFAULT ;
return ocfs2_info_handle ( inode , & info , 1 ) ;
2007-03-10 02:56:28 +03:00
default :
return - ENOIOCTLCMD ;
}
2008-01-27 05:17:17 +03:00
return ocfs2_ioctl ( file , cmd , arg ) ;
2007-03-10 02:56:28 +03:00
}
# endif