@ -145,22 +145,22 @@ static void fuse_invalidate_entry(struct dentry *entry)
fuse_invalidate_entry_cache ( entry ) ;
}
static void fuse_lookup_init ( struct fuse_conn * fc , struct fuse_req * req ,
static void fuse_lookup_init ( struct fuse_conn * fc , struct fuse_args * args ,
u64 nodeid , struct qstr * name ,
struct fuse_entry_out * outarg )
{
memset ( outarg , 0 , sizeof ( struct fuse_entry_out ) ) ;
req - > in . h . opcode = FUSE_LOOKUP ;
req - > in . h . nodeid = nodeid ;
req - > in . numargs = 1 ;
req - > in . args [ 0 ] . size = name - > len + 1 ;
req - > in . args [ 0 ] . value = name - > name ;
req - > out . numargs = 1 ;
args - > in . h . opcode = FUSE_LOOKUP ;
args - > in . h . nodeid = nodeid ;
args - > in . numargs = 1 ;
args - > in . args [ 0 ] . size = name - > len + 1 ;
args - > in . args [ 0 ] . value = name - > name ;
args - > out . numargs = 1 ;
if ( fc - > minor < 9 )
req - > out . args [ 0 ] . size = FUSE_COMPAT_ENTRY_OUT_SIZE ;
args - > out . args [ 0 ] . size = FUSE_COMPAT_ENTRY_OUT_SIZE ;
else
req - > out . args [ 0 ] . size = sizeof ( struct fuse_entry_out ) ;
req - > out . args [ 0 ] . value = outarg ;
args - > out . args [ 0 ] . size = sizeof ( struct fuse_entry_out ) ;
args - > out . args [ 0 ] . value = outarg ;
}
u64 fuse_get_attr_version ( struct fuse_conn * fc )
@ -200,9 +200,8 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
goto invalid ;
else if ( time_before64 ( fuse_dentry_time ( entry ) , get_jiffies_64 ( ) ) | |
( flags & LOOKUP_REVAL ) ) {
int err ;
struct fuse_entry_out outarg ;
struct fuse_req * req ;
FUSE_ARGS ( args ) ;
struct fuse_forget_link * forget ;
u64 attr_version ;
@ -215,31 +214,23 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
goto out ;
fc = get_fuse_conn ( inode ) ;
req = fuse_get_req_nopages ( fc ) ;
ret = PTR_ERR ( req ) ;
if ( IS_ERR ( req ) )
goto out ;
forget = fuse_alloc_forget ( ) ;
if ( ! forget ) {
fuse_put_request ( fc , req ) ;
ret = - ENOMEM ;
ret = - ENOMEM ;
if ( ! forget )
goto out ;
}
attr_version = fuse_get_attr_version ( fc ) ;
parent = dget_parent ( entry ) ;
fuse_lookup_init ( fc , req , get_node_id ( parent - > d_inode ) ,
fuse_lookup_init ( fc , & args , get_node_id ( parent - > d_inode ) ,
& entry - > d_name , & outarg ) ;
fuse_request_send ( fc , req ) ;
ret = fuse_simple_ request ( fc , & args ) ;
dput ( parent ) ;
err = req - > out . h . error ;
fuse_put_request ( fc , req ) ;
/* Zero nodeid is same as -ENOENT */
if ( ! er r & & ! outarg . nodeid )
er r = - ENOENT ;
if ( ! er r) {
if ( ! ret & & ! outarg . nodeid )
ret = - ENOENT ;
if ( ! ret ) {
fi = get_fuse_inode ( inode ) ;
if ( outarg . nodeid ! = get_node_id ( inode ) ) {
fuse_queue_forget ( fc , forget , outarg . nodeid , 1 ) ;
@ -250,7 +241,9 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
spin_unlock ( & fc - > lock ) ;
}
kfree ( forget ) ;
if ( err | | ( outarg . attr . mode ^ inode - > i_mode ) & S_IFMT )
if ( ret = = - ENOMEM )
goto out ;
if ( ret | | ( outarg . attr . mode ^ inode - > i_mode ) & S_IFMT )
goto invalid ;
fuse_change_attributes ( inode , & outarg . attr ,
@ -296,7 +289,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
struct fuse_entry_out * outarg , struct inode * * inode )
{
struct fuse_conn * fc = get_fuse_conn_super ( sb ) ;
struct fuse_req * req ;
FUSE_ARGS ( args ) ;
struct fuse_forget_link * forget ;
u64 attr_version ;
int err ;
@ -306,24 +299,16 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
if ( name - > len > FUSE_NAME_MAX )
goto out ;
req = fuse_get_req_nopages ( fc ) ;
err = PTR_ERR ( req ) ;
if ( IS_ERR ( req ) )
goto out ;
forget = fuse_alloc_forget ( ) ;
err = - ENOMEM ;
if ( ! forget ) {
fuse_put_request ( fc , req ) ;
if ( ! forget )
goto out ;
}
attr_version = fuse_get_attr_version ( fc ) ;
fuse_lookup_init ( fc , req , nodeid , name , outarg ) ;
fuse_request_send ( fc , req ) ;
err = req - > out . h . error ;
fuse_put_request ( fc , req ) ;
fuse_lookup_init ( fc , & args , nodeid , name , outarg ) ;
err = fuse_simple_request ( fc , & args ) ;
/* Zero nodeid is same as -ENOENT, but with valid timeout */
if ( err | | ! outarg - > nodeid )
goto out_put_forget ;
@ -405,7 +390,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
int err ;
struct inode * inode ;
struct fuse_conn * fc = get_fuse_conn ( dir ) ;
struct fuse_req * req ;
FUSE_ARGS ( args ) ;
struct fuse_forget_link * forget ;
struct fuse_create_in inarg ;
struct fuse_open_out outopen ;
@ -420,15 +405,10 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
if ( ! forget )
goto out_err ;
req = fuse_get_req_nopages ( fc ) ;
err = PTR_ERR ( req ) ;
if ( IS_ERR ( req ) )
goto out_put_forget_req ;
err = - ENOMEM ;
ff = fuse_file_alloc ( fc ) ;
if ( ! ff )
goto out_put_request ;
goto out_put_forget_req ;
if ( ! fc - > dont_mask )
mode & = ~ current_umask ( ) ;
@ -439,24 +419,23 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
inarg . flags = flags ;
inarg . mode = mode ;
inarg . umask = current_umask ( ) ;
req - > in . h . opcode = FUSE_CREATE ;
req - > in . h . nodeid = get_node_id ( dir ) ;
req - > in . numargs = 2 ;
req - > in . args [ 0 ] . size = fc - > minor < 12 ? sizeof ( struct fuse_open_in ) :
args . in . h . opcode = FUSE_CREATE ;
args . in . h . nodeid = get_node_id ( dir ) ;
args . in . numargs = 2 ;
args . in . args [ 0 ] . size = fc - > minor < 12 ? sizeof ( struct fuse_open_in ) :
sizeof ( inarg ) ;
req - > in . args [ 0 ] . value = & inarg ;
req - > in . args [ 1 ] . size = entry - > d_name . len + 1 ;
req - > in . args [ 1 ] . value = entry - > d_name . name ;
req - > out . numargs = 2 ;
args . in . args [ 0 ] . value = & inarg ;
args . in . args [ 1 ] . size = entry - > d_name . len + 1 ;
args . in . args [ 1 ] . value = entry - > d_name . name ;
args . out . numargs = 2 ;
if ( fc - > minor < 9 )
req - > out . args [ 0 ] . size = FUSE_COMPAT_ENTRY_OUT_SIZE ;
args . out . args [ 0 ] . size = FUSE_COMPAT_ENTRY_OUT_SIZE ;
else
req - > out . args [ 0 ] . size = sizeof ( outentry ) ;
req - > out . args [ 0 ] . value = & outentry ;
req - > out . args [ 1 ] . size = sizeof ( outopen ) ;
req - > out . args [ 1 ] . value = & outopen ;
fuse_request_send ( fc , req ) ;
err = req - > out . h . error ;
args . out . args [ 0 ] . size = sizeof ( outentry ) ;
args . out . args [ 0 ] . value = & outentry ;
args . out . args [ 1 ] . size = sizeof ( outopen ) ;
args . out . args [ 1 ] . value = & outopen ;
err = fuse_simple_request ( fc , & args ) ;
if ( err )
goto out_free_ff ;
@ -464,7 +443,6 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
if ( ! S_ISREG ( outentry . attr . mode ) | | invalid_nodeid ( outentry . nodeid ) )
goto out_free_ff ;
fuse_put_request ( fc , req ) ;
ff - > fh = outopen . fh ;
ff - > nodeid = outentry . nodeid ;
ff - > open_flags = outopen . open_flags ;
@ -492,8 +470,6 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
out_free_ff :
fuse_file_free ( ff ) ;
out_put_request :
fuse_put_request ( fc , req ) ;
out_put_forget_req :
kfree ( forget ) ;
out_err :
@ -547,7 +523,7 @@ no_open:
/*
* Code shared between mknod , mkdir , symlink and link
*/
static int create_new_entry ( struct fuse_conn * fc , struct fuse_req * req ,
static int create_new_entry ( struct fuse_conn * fc , struct fuse_args * args ,
struct inode * dir , struct dentry * entry ,
umode_t mode )
{
@ -557,22 +533,18 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
struct fuse_forget_link * forget ;
forget = fuse_alloc_forget ( ) ;
if ( ! forget ) {
fuse_put_request ( fc , req ) ;
if ( ! forget )
return - ENOMEM ;
}
memset ( & outarg , 0 , sizeof ( outarg ) ) ;
req - > in . h . nodeid = get_node_id ( dir ) ;
req - > out . numargs = 1 ;
args - > in . h . nodeid = get_node_id ( dir ) ;
args - > out . numargs = 1 ;
if ( fc - > minor < 9 )
req - > out . args [ 0 ] . size = FUSE_COMPAT_ENTRY_OUT_SIZE ;
args - > out . args [ 0 ] . size = FUSE_COMPAT_ENTRY_OUT_SIZE ;
else
req - > out . args [ 0 ] . size = sizeof ( outarg ) ;
req - > out . args [ 0 ] . value = & outarg ;
fuse_request_send ( fc , req ) ;
err = req - > out . h . error ;
fuse_put_request ( fc , req ) ;
args - > out . args [ 0 ] . size = sizeof ( outarg ) ;
args - > out . args [ 0 ] . value = & outarg ;
err = fuse_simple_request ( fc , args ) ;
if ( err )
goto out_put_forget_req ;
@ -609,9 +581,7 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
{
struct fuse_mknod_in inarg ;
struct fuse_conn * fc = get_fuse_conn ( dir ) ;
struct fuse_req * req = fuse_get_req_nopages ( fc ) ;
if ( IS_ERR ( req ) )
return PTR_ERR ( req ) ;
FUSE_ARGS ( args ) ;
if ( ! fc - > dont_mask )
mode & = ~ current_umask ( ) ;
@ -620,14 +590,14 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
inarg . mode = mode ;
inarg . rdev = new_encode_dev ( rdev ) ;
inarg . umask = current_umask ( ) ;
req - > in . h . opcode = FUSE_MKNOD ;
req - > in . numargs = 2 ;
req - > in . args [ 0 ] . size = fc - > minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE :
args . in . h . opcode = FUSE_MKNOD ;
args . in . numargs = 2 ;
args . in . args [ 0 ] . size = fc - > minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE :
sizeof ( inarg ) ;
req - > in . args [ 0 ] . value = & inarg ;
req - > in . args [ 1 ] . size = entry - > d_name . len + 1 ;
req - > in . args [ 1 ] . value = entry - > d_name . name ;
return create_new_entry ( fc , req , dir , entry , mode ) ;
args . in . args [ 0 ] . value = & inarg ;
args . in . args [ 1 ] . size = entry - > d_name . len + 1 ;
args . in . args [ 1 ] . value = entry - > d_name . name ;
return create_new_entry ( fc , & args , dir , entry , mode ) ;
}
static int fuse_create ( struct inode * dir , struct dentry * entry , umode_t mode ,
@ -640,9 +610,7 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
{
struct fuse_mkdir_in inarg ;
struct fuse_conn * fc = get_fuse_conn ( dir ) ;
struct fuse_req * req = fuse_get_req_nopages ( fc ) ;
if ( IS_ERR ( req ) )
return PTR_ERR ( req ) ;
FUSE_ARGS ( args ) ;
if ( ! fc - > dont_mask )
mode & = ~ current_umask ( ) ;
@ -650,13 +618,13 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
memset ( & inarg , 0 , sizeof ( inarg ) ) ;
inarg . mode = mode ;
inarg . umask = current_umask ( ) ;
req - > in . h . opcode = FUSE_MKDIR ;
req - > in . numargs = 2 ;
req - > in . args [ 0 ] . size = sizeof ( inarg ) ;
req - > in . args [ 0 ] . value = & inarg ;
req - > in . args [ 1 ] . size = entry - > d_name . len + 1 ;
req - > in . args [ 1 ] . value = entry - > d_name . name ;
return create_new_entry ( fc , req , dir , entry , S_IFDIR ) ;
args . in . h . opcode = FUSE_MKDIR ;
args . in . numargs = 2 ;
args . in . args [ 0 ] . size = sizeof ( inarg ) ;
args . in . args [ 0 ] . value = & inarg ;
args . in . args [ 1 ] . size = entry - > d_name . len + 1 ;
args . in . args [ 1 ] . value = entry - > d_name . name ;
return create_new_entry ( fc , & args , dir , entry , S_IFDIR ) ;
}
static int fuse_symlink ( struct inode * dir , struct dentry * entry ,
@ -664,17 +632,15 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry,
{
struct fuse_conn * fc = get_fuse_conn ( dir ) ;
unsigned len = strlen ( link ) + 1 ;
struct fuse_req * req = fuse_get_req_nopages ( fc ) ;
if ( IS_ERR ( req ) )
return PTR_ERR ( req ) ;
FUSE_ARGS ( args ) ;
req - > in . h . opcode = FUSE_SYMLINK ;
req - > in . numargs = 2 ;
req - > in . args [ 0 ] . size = entry - > d_name . len + 1 ;
req - > in . args [ 0 ] . value = entry - > d_name . name ;
req - > in . args [ 1 ] . size = len ;
req - > in . args [ 1 ] . value = link ;
return create_new_entry ( fc , req , dir , entry , S_IFLNK ) ;
args . in . h . opcode = FUSE_SYMLINK ;
args . in . numargs = 2 ;
args . in . args [ 0 ] . size = entry - > d_name . len + 1 ;
args . in . args [ 0 ] . value = entry - > d_name . name ;
args . in . args [ 1 ] . size = len ;
args . in . args [ 1 ] . value = link ;
return create_new_entry ( fc , & args , dir , entry , S_IFLNK ) ;
}
static inline void fuse_update_ctime ( struct inode * inode )
@ -689,18 +655,14 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
{
int err ;
struct fuse_conn * fc = get_fuse_conn ( dir ) ;
struct fuse_req * req = fuse_get_req_nopages ( fc ) ;
if ( IS_ERR ( req ) )
return PTR_ERR ( req ) ;
req - > in . h . opcode = FUSE_UNLINK ;
req - > in . h . nodeid = get_node_id ( dir ) ;
req - > in . numargs = 1 ;
req - > in . args [ 0 ] . size = entry - > d_name . len + 1 ;
req - > in . args [ 0 ] . value = entry - > d_name . name ;
fuse_request_send ( fc , req ) ;
err = req - > out . h . error ;
fuse_put_request ( fc , req ) ;
FUSE_ARGS ( args ) ;
args . in . h . opcode = FUSE_UNLINK ;
args . in . h . nodeid = get_node_id ( dir ) ;
args . in . numargs = 1 ;
args . in . args [ 0 ] . size = entry - > d_name . len + 1 ;
args . in . args [ 0 ] . value = entry - > d_name . name ;
err = fuse_simple_request ( fc , & args ) ;
if ( ! err ) {
struct inode * inode = entry - > d_inode ;
struct fuse_inode * fi = get_fuse_inode ( inode ) ;
@ -729,18 +691,14 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
{
int err ;
struct fuse_conn * fc = get_fuse_conn ( dir ) ;
struct fuse_req * req = fuse_get_req_nopages ( fc ) ;
if ( IS_ERR ( req ) )
return PTR_ERR ( req ) ;
req - > in . h . opcode = FUSE_RMDIR ;
req - > in . h . nodeid = get_node_id ( dir ) ;
req - > in . numargs = 1 ;
req - > in . args [ 0 ] . size = entry - > d_name . len + 1 ;
req - > in . args [ 0 ] . value = entry - > d_name . name ;
fuse_request_send ( fc , req ) ;
err = req - > out . h . error ;
fuse_put_request ( fc , req ) ;
FUSE_ARGS ( args ) ;
args . in . h . opcode = FUSE_RMDIR ;
args . in . h . nodeid = get_node_id ( dir ) ;
args . in . numargs = 1 ;
args . in . args [ 0 ] . size = entry - > d_name . len + 1 ;
args . in . args [ 0 ] . value = entry - > d_name . name ;
err = fuse_simple_request ( fc , & args ) ;
if ( ! err ) {
clear_nlink ( entry - > d_inode ) ;
fuse_invalidate_attr ( dir ) ;
@ -757,27 +715,21 @@ static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
int err ;
struct fuse_rename2_in inarg ;
struct fuse_conn * fc = get_fuse_conn ( olddir ) ;
struct fuse_req * req ;
req = fuse_get_req_nopages ( fc ) ;
if ( IS_ERR ( req ) )
return PTR_ERR ( req ) ;
FUSE_ARGS ( args ) ;
memset ( & inarg , 0 , argsize ) ;
inarg . newdir = get_node_id ( newdir ) ;
inarg . flags = flags ;
req - > in . h . opcode = opcode ;
req - > in . h . nodeid = get_node_id ( olddir ) ;
req - > in . numargs = 3 ;
req - > in . args [ 0 ] . size = argsize ;
req - > in . args [ 0 ] . value = & inarg ;
req - > in . args [ 1 ] . size = oldent - > d_name . len + 1 ;
req - > in . args [ 1 ] . value = oldent - > d_name . name ;
req - > in . args [ 2 ] . size = newent - > d_name . len + 1 ;
req - > in . args [ 2 ] . value = newent - > d_name . name ;
fuse_request_send ( fc , req ) ;
err = req - > out . h . error ;
fuse_put_request ( fc , req ) ;
args . in . h . opcode = opcode ;
args . in . h . nodeid = get_node_id ( olddir ) ;
args . in . numargs = 3 ;
args . in . args [ 0 ] . size = argsize ;
args . in . args [ 0 ] . value = & inarg ;
args . in . args [ 1 ] . size = oldent - > d_name . len + 1 ;
args . in . args [ 1 ] . value = oldent - > d_name . name ;
args . in . args [ 2 ] . size = newent - > d_name . len + 1 ;
args . in . args [ 2 ] . value = newent - > d_name . name ;
err = fuse_simple_request ( fc , & args ) ;
if ( ! err ) {
/* ctime changes */
fuse_invalidate_attr ( oldent - > d_inode ) ;
@ -849,19 +801,17 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
struct fuse_link_in inarg ;
struct inode * inode = entry - > d_inode ;
struct fuse_conn * fc = get_fuse_conn ( inode ) ;
struct fuse_req * req = fuse_get_req_nopages ( fc ) ;
if ( IS_ERR ( req ) )
return PTR_ERR ( req ) ;
FUSE_ARGS ( args ) ;
memset ( & inarg , 0 , sizeof ( inarg ) ) ;
inarg . oldnodeid = get_node_id ( inode ) ;
req - > in . h . opcode = FUSE_LINK ;
req - > in . numargs = 2 ;
req - > in . args [ 0 ] . size = sizeof ( inarg ) ;
req - > in . args [ 0 ] . value = & inarg ;
req - > in . args [ 1 ] . size = newent - > d_name . len + 1 ;
req - > in . args [ 1 ] . value = newent - > d_name . name ;
err = create_new_entry ( fc , req , newdir , newent , inode - > i_mode ) ;
args . in . h . opcode = FUSE_LINK ;
args . in . numargs = 2 ;
args . in . args [ 0 ] . size = sizeof ( inarg ) ;
args . in . args [ 0 ] . value = & inarg ;
args . in . args [ 1 ] . size = newent - > d_name . len + 1 ;
args . in . args [ 1 ] . value = newent - > d_name . name ;
err = create_new_entry ( fc , & args , newdir , newent , inode - > i_mode ) ;
/* Contrary to "normal" filesystems it can happen that link
makes two " logical " inodes point to the same " physical "
inode . We invalidate the attributes of the old one , so it
@ -929,13 +879,9 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
struct fuse_getattr_in inarg ;
struct fuse_attr_out outarg ;
struct fuse_conn * fc = get_fuse_conn ( inode ) ;
struct fuse_req * req ;
FUSE_ARGS ( args ) ;
u64 attr_version ;
req = fuse_get_req_nopages ( fc ) ;
if ( IS_ERR ( req ) )
return PTR_ERR ( req ) ;
attr_version = fuse_get_attr_version ( fc ) ;
memset ( & inarg , 0 , sizeof ( inarg ) ) ;
@ -947,20 +893,18 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
inarg . getattr_flags | = FUSE_GETATTR_FH ;
inarg . fh = ff - > fh ;
}
req - > in . h . opcode = FUSE_GETATTR ;
req - > in . h . nodeid = get_node_id ( inode ) ;
req - > in . numargs = 1 ;
req - > in . args [ 0 ] . size = sizeof ( inarg ) ;
req - > in . args [ 0 ] . value = & inarg ;
req - > out . numargs = 1 ;
args . in . h . opcode = FUSE_GETATTR ;
args . in . h . nodeid = get_node_id ( inode ) ;
args . in . numargs = 1 ;
args . in . args [ 0 ] . size = sizeof ( inarg ) ;
args . in . args [ 0 ] . value = & inarg ;
args . out . numargs = 1 ;
if ( fc - > minor < 9 )
req - > out . args [ 0 ] . size = FUSE_COMPAT_ATTR_OUT_SIZE ;
args . out . args [ 0 ] . size = FUSE_COMPAT_ATTR_OUT_SIZE ;
else
req - > out . args [ 0 ] . size = sizeof ( outarg ) ;
req - > out . args [ 0 ] . value = & outarg ;
fuse_request_send ( fc , req ) ;
err = req - > out . h . error ;
fuse_put_request ( fc , req ) ;
args . out . args [ 0 ] . size = sizeof ( outarg ) ;
args . out . args [ 0 ] . value = & outarg ;
err = fuse_simple_request ( fc , & args ) ;
if ( ! err ) {
if ( ( inode - > i_mode ^ outarg . attr . mode ) & S_IFMT ) {
make_bad_inode ( inode ) ;
@ -1102,7 +1046,7 @@ int fuse_allow_current_process(struct fuse_conn *fc)
static int fuse_access ( struct inode * inode , int mask )
{
struct fuse_conn * fc = get_fuse_conn ( inode ) ;
struct fuse_req * req ;
FUSE_ARGS ( args ) ;
struct fuse_access_in inarg ;
int err ;
@ -1111,20 +1055,14 @@ static int fuse_access(struct inode *inode, int mask)
if ( fc - > no_access )
return 0 ;
req = fuse_get_req_nopages ( fc ) ;
if ( IS_ERR ( req ) )
return PTR_ERR ( req ) ;
memset ( & inarg , 0 , sizeof ( inarg ) ) ;
inarg . mask = mask & ( MAY_READ | MAY_WRITE | MAY_EXEC ) ;
req - > in . h . opcode = FUSE_ACCESS ;
req - > in . h . nodeid = get_node_id ( inode ) ;
req - > in . numargs = 1 ;
req - > in . args [ 0 ] . size = sizeof ( inarg ) ;
req - > in . args [ 0 ] . value = & inarg ;
fuse_request_send ( fc , req ) ;
err = req - > out . h . error ;
fuse_put_request ( fc , req ) ;
args . in . h . opcode = FUSE_ACCESS ;
args . in . h . nodeid = get_node_id ( inode ) ;
args . in . numargs = 1 ;
args . in . args [ 0 ] . size = sizeof ( inarg ) ;
args . in . args [ 0 ] . value = & inarg ;
err = fuse_simple_request ( fc , & args ) ;
if ( err = = - ENOSYS ) {
fc - > no_access = 1 ;
err = 0 ;
@ -1445,31 +1383,27 @@ static char *read_link(struct dentry *dentry)
{
struct inode * inode = dentry - > d_inode ;
struct fuse_conn * fc = get_fuse_conn ( inode ) ;
struct fuse_req * req = fuse_get_req_nopages ( fc ) ;
FUSE_ARGS ( args ) ;
char * link ;
if ( IS_ERR ( req ) )
return ERR_CAST ( req ) ;
ssize_t ret ;
link = ( char * ) __get_free_page ( GFP_KERNEL ) ;
if ( ! link ) {
link = ERR_PTR ( - ENOMEM ) ;
goto out ;
}
req - > in . h . opcode = FUSE_READLINK ;
req - > in . h . nodeid = get_node_id ( inode ) ;
req - > out . argvar = 1 ;
req - > out . numargs = 1 ;
req - > out . args [ 0 ] . size = PAGE_SIZE - 1 ;
req - > out . args [ 0 ] . value = link ;
fuse_request_send ( fc , req ) ;
if ( req - > out . h . error ) {
if ( ! link )
return ERR_PTR ( - ENOMEM ) ;
args . in . h . opcode = FUSE_READLINK ;
args . in . h . nodeid = get_node_id ( inode ) ;
args . out . argvar = 1 ;
args . out . numargs = 1 ;
args . out . args [ 0 ] . size = PAGE_SIZE - 1 ;
args . out . args [ 0 ] . value = link ;
ret = fuse_simple_request ( fc , & args ) ;
if ( ret < 0 ) {
free_page ( ( unsigned long ) link ) ;
link = ERR_PTR ( req - > out . h . error ) ;
} else
link [ req - > out . args [ 0 ] . size ] = ' \0 ' ;
out :
fuse_put_request ( fc , req ) ;
link = ERR_PTR ( ret ) ;
} else {
link [ ret ] = ' \0 ' ;
}
fuse_invalidate_atime ( inode ) ;
return link ;
}
@ -1629,22 +1563,22 @@ void fuse_release_nowrite(struct inode *inode)
spin_unlock ( & fc - > lock ) ;
}
static void fuse_setattr_fill ( struct fuse_conn * fc , struct fuse_req * req ,
static void fuse_setattr_fill ( struct fuse_conn * fc , struct fuse_args * args ,
struct inode * inode ,
struct fuse_setattr_in * inarg_p ,
struct fuse_attr_out * outarg_p )
{
req - > in . h . opcode = FUSE_SETATTR ;
req - > in . h . nodeid = get_node_id ( inode ) ;
req - > in . numargs = 1 ;
req - > in . args [ 0 ] . size = sizeof ( * inarg_p ) ;
req - > in . args [ 0 ] . value = inarg_p ;
req - > out . numargs = 1 ;
args - > in . h . opcode = FUSE_SETATTR ;
args - > in . h . nodeid = get_node_id ( inode ) ;
args - > in . numargs = 1 ;
args - > in . args [ 0 ] . size = sizeof ( * inarg_p ) ;
args - > in . args [ 0 ] . value = inarg_p ;
args - > out . numargs = 1 ;
if ( fc - > minor < 9 )
req - > out . args [ 0 ] . size = FUSE_COMPAT_ATTR_OUT_SIZE ;
args - > out . args [ 0 ] . size = FUSE_COMPAT_ATTR_OUT_SIZE ;
else
req - > out . args [ 0 ] . size = sizeof ( * outarg_p ) ;
req - > out . args [ 0 ] . value = outarg_p ;
args - > out . args [ 0 ] . size = sizeof ( * outarg_p ) ;
args - > out . args [ 0 ] . value = outarg_p ;
}
/*
@ -1653,14 +1587,9 @@ static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_req *req,
int fuse_flush_times ( struct inode * inode , struct fuse_file * ff )
{
struct fuse_conn * fc = get_fuse_conn ( inode ) ;
struct fuse_req * req ;
FUSE_ARGS ( args ) ;
struct fuse_setattr_in inarg ;
struct fuse_attr_out outarg ;
int err ;
req = fuse_get_req_nopages ( fc ) ;
if ( IS_ERR ( req ) )
return PTR_ERR ( req ) ;
memset ( & inarg , 0 , sizeof ( inarg ) ) ;
memset ( & outarg , 0 , sizeof ( outarg ) ) ;
@ -1677,12 +1606,9 @@ int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
inarg . valid | = FATTR_FH ;
inarg . fh = ff - > fh ;
}
fuse_setattr_fill ( fc , req , inode , & inarg , & outarg ) ;
fuse_request_send ( fc , req ) ;
err = req - > out . h . error ;
fuse_put_request ( fc , req ) ;
fuse_setattr_fill ( fc , & args , inode , & inarg , & outarg ) ;
return err ;
return fuse_simple_request ( fc , & args ) ;
}
/*
@ -1698,7 +1624,7 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
{
struct fuse_conn * fc = get_fuse_conn ( inode ) ;
struct fuse_inode * fi = get_fuse_inode ( inode ) ;
struct fuse_req * req ;
FUSE_ARGS ( args ) ;
struct fuse_setattr_in inarg ;
struct fuse_attr_out outarg ;
bool is_truncate = false ;
@ -1723,10 +1649,6 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
if ( attr - > ia_valid & ATTR_SIZE )
is_truncate = true ;
req = fuse_get_req_nopages ( fc ) ;
if ( IS_ERR ( req ) )
return PTR_ERR ( req ) ;
if ( is_truncate ) {
fuse_set_nowrite ( inode ) ;
set_bit ( FUSE_I_SIZE_UNSTABLE , & fi - > state ) ;
@ -1747,10 +1669,8 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
inarg . valid | = FATTR_LOCKOWNER ;
inarg . lock_owner = fuse_lock_owner_id ( fc , current - > files ) ;
}
fuse_setattr_fill ( fc , req , inode , & inarg , & outarg ) ;
fuse_request_send ( fc , req ) ;
err = req - > out . h . error ;
fuse_put_request ( fc , req ) ;
fuse_setattr_fill ( fc , & args , inode , & inarg , & outarg ) ;
err = fuse_simple_request ( fc , & args ) ;
if ( err ) {
if ( err = = - EINTR )
fuse_invalidate_attr ( inode ) ;
@ -1837,32 +1757,26 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
{
struct inode * inode = entry - > d_inode ;
struct fuse_conn * fc = get_fuse_conn ( inode ) ;
struct fuse_req * req ;
FUSE_ARGS ( args ) ;
struct fuse_setxattr_in inarg ;
int err ;
if ( fc - > no_setxattr )
return - EOPNOTSUPP ;
req = fuse_get_req_nopages ( fc ) ;
if ( IS_ERR ( req ) )
return PTR_ERR ( req ) ;
memset ( & inarg , 0 , sizeof ( inarg ) ) ;
inarg . size = size ;
inarg . flags = flags ;
req - > in . h . opcode = FUSE_SETXATTR ;
req - > in . h . nodeid = get_node_id ( inode ) ;
req - > in . numargs = 3 ;
req - > in . args [ 0 ] . size = sizeof ( inarg ) ;
req - > in . args [ 0 ] . value = & inarg ;
req - > in . args [ 1 ] . size = strlen ( name ) + 1 ;
req - > in . args [ 1 ] . value = name ;
req - > in . args [ 2 ] . size = size ;
req - > in . args [ 2 ] . value = value ;
fuse_request_send ( fc , req ) ;
err = req - > out . h . error ;
fuse_put_request ( fc , req ) ;
args . in . h . opcode = FUSE_SETXATTR ;
args . in . h . nodeid = get_node_id ( inode ) ;
args . in . numargs = 3 ;
args . in . args [ 0 ] . size = sizeof ( inarg ) ;
args . in . args [ 0 ] . value = & inarg ;
args . in . args [ 1 ] . size = strlen ( name ) + 1 ;
args . in . args [ 1 ] . value = name ;
args . in . args [ 2 ] . size = size ;
args . in . args [ 2 ] . value = value ;
err = fuse_simple_request ( fc , & args ) ;
if ( err = = - ENOSYS ) {
fc - > no_setxattr = 1 ;
err = - EOPNOTSUPP ;
@ -1879,7 +1793,7 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
{
struct inode * inode = entry - > d_inode ;
struct fuse_conn * fc = get_fuse_conn ( inode ) ;
struct fuse_req * req ;
FUSE_ARGS ( args ) ;
struct fuse_getxattr_in inarg ;
struct fuse_getxattr_out outarg ;
ssize_t ret ;
@ -1887,40 +1801,32 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
if ( fc - > no_getxattr )
return - EOPNOTSUPP ;
req = fuse_get_req_nopages ( fc ) ;
if ( IS_ERR ( req ) )
return PTR_ERR ( req ) ;
memset ( & inarg , 0 , sizeof ( inarg ) ) ;
inarg . size = size ;
req - > in . h . opcode = FUSE_GETXATTR ;
req - > in . h . nodeid = get_node_id ( inode ) ;
req - > in . numargs = 2 ;
req - > in . args [ 0 ] . size = sizeof ( inarg ) ;
req - > in . args [ 0 ] . value = & inarg ;
req - > in . args [ 1 ] . size = strlen ( name ) + 1 ;
req - > in . args [ 1 ] . value = name ;
args . in . h . opcode = FUSE_GETXATTR ;
args . in . h . nodeid = get_node_id ( inode ) ;
args . in . numargs = 2 ;
args . in . args [ 0 ] . size = sizeof ( inarg ) ;
args . in . args [ 0 ] . value = & inarg ;
args . in . args [ 1 ] . size = strlen ( name ) + 1 ;
args . in . args [ 1 ] . value = name ;
/* This is really two different operations rolled into one */
req - > out . numargs = 1 ;
args . out . numargs = 1 ;
if ( size ) {
req - > out . argvar = 1 ;
req - > out . args [ 0 ] . size = size ;
req - > out . args [ 0 ] . value = value ;
args . out . argvar = 1 ;
args . out . args [ 0 ] . size = size ;
args . out . args [ 0 ] . value = value ;
} else {
req - > out . args [ 0 ] . size = sizeof ( outarg ) ;
req - > out . args [ 0 ] . value = & outarg ;
args . out . args [ 0 ] . size = sizeof ( outarg ) ;
args . out . args [ 0 ] . value = & outarg ;
}
fuse_request_send ( fc , req ) ;
ret = req - > out . h . error ;
if ( ! ret )
ret = size ? req - > out . args [ 0 ] . size : outarg . size ;
else {
if ( ret = = - ENOSYS ) {
fc - > no_getxattr = 1 ;
ret = - EOPNOTSUPP ;
}
ret = fuse_simple_request ( fc , & args ) ;
if ( ! ret & & ! size )
ret = outarg . size ;
if ( ret = = - ENOSYS ) {
fc - > no_getxattr = 1 ;
ret = - EOPNOTSUPP ;
}
fuse_put_request ( fc , req ) ;
return ret ;
}
@ -1928,7 +1834,7 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
{
struct inode * inode = entry - > d_inode ;
struct fuse_conn * fc = get_fuse_conn ( inode ) ;
struct fuse_req * req ;
FUSE_ARGS ( args ) ;
struct fuse_getxattr_in inarg ;
struct fuse_getxattr_out outarg ;
ssize_t ret ;
@ -1939,38 +1845,30 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
if ( fc - > no_listxattr )
return - EOPNOTSUPP ;
req = fuse_get_req_nopages ( fc ) ;
if ( IS_ERR ( req ) )
return PTR_ERR ( req ) ;
memset ( & inarg , 0 , sizeof ( inarg ) ) ;
inarg . size = size ;
req - > in . h . opcode = FUSE_LISTXATTR ;
req - > in . h . nodeid = get_node_id ( inode ) ;
req - > in . numargs = 1 ;
req - > in . args [ 0 ] . size = sizeof ( inarg ) ;
req - > in . args [ 0 ] . value = & inarg ;
args . in . h . opcode = FUSE_LISTXATTR ;
args . in . h . nodeid = get_node_id ( inode ) ;
args . in . numargs = 1 ;
args . in . args [ 0 ] . size = sizeof ( inarg ) ;
args . in . args [ 0 ] . value = & inarg ;
/* This is really two different operations rolled into one */
req - > out . numargs = 1 ;
args . out . numargs = 1 ;
if ( size ) {
req - > out . argvar = 1 ;
req - > out . args [ 0 ] . size = size ;
req - > out . args [ 0 ] . value = list ;
args . out . argvar = 1 ;
args . out . args [ 0 ] . size = size ;
args . out . args [ 0 ] . value = list ;
} else {
req - > out . args [ 0 ] . size = sizeof ( outarg ) ;
req - > out . args [ 0 ] . value = & outarg ;
args . out . args [ 0 ] . size = sizeof ( outarg ) ;
args . out . args [ 0 ] . value = & outarg ;
}
fuse_request_send ( fc , req ) ;
ret = req - > out . h . error ;
if ( ! ret )
ret = size ? req - > out . args [ 0 ] . size : outarg . size ;
else {
if ( ret = = - ENOSYS ) {
fc - > no_listxattr = 1 ;
ret = - EOPNOTSUPP ;
}
ret = fuse_simple_request ( fc , & args ) ;
if ( ! ret & & ! size )
ret = outarg . size ;
if ( ret = = - ENOSYS ) {
fc - > no_listxattr = 1 ;
ret = - EOPNOTSUPP ;
}
fuse_put_request ( fc , req ) ;
return ret ;
}
@ -1978,24 +1876,18 @@ static int fuse_removexattr(struct dentry *entry, const char *name)
{
struct inode * inode = entry - > d_inode ;
struct fuse_conn * fc = get_fuse_conn ( inode ) ;
struct fuse_req * req ;
FUSE_ARGS ( args ) ;
int err ;
if ( fc - > no_removexattr )
return - EOPNOTSUPP ;
req = fuse_get_req_nopages ( fc ) ;
if ( IS_ERR ( req ) )
return PTR_ERR ( req ) ;
req - > in . h . opcode = FUSE_REMOVEXATTR ;
req - > in . h . nodeid = get_node_id ( inode ) ;
req - > in . numargs = 1 ;
req - > in . args [ 0 ] . size = strlen ( name ) + 1 ;
req - > in . args [ 0 ] . value = name ;
fuse_request_send ( fc , req ) ;
err = req - > out . h . error ;
fuse_put_request ( fc , req ) ;
args . in . h . opcode = FUSE_REMOVEXATTR ;
args . in . h . nodeid = get_node_id ( inode ) ;
args . in . numargs = 1 ;
args . in . args [ 0 ] . size = strlen ( name ) + 1 ;
args . in . args [ 0 ] . value = name ;
err = fuse_simple_request ( fc , & args ) ;
if ( err = = - ENOSYS ) {
fc - > no_removexattr = 1 ;
err = - EOPNOTSUPP ;