2005-04-17 02:20:36 +04:00
/*
2005-11-02 06:58:39 +03:00
* Copyright ( c ) 2000 - 2005 Silicon Graphics , Inc .
* All Rights Reserved .
2005-04-17 02:20:36 +04:00
*
2005-11-02 06:58:39 +03:00
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License as
2005-04-17 02:20:36 +04:00
* published by the Free Software Foundation .
*
2005-11-02 06:58:39 +03:00
* This program is distributed in the hope that it would be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
2005-04-17 02:20:36 +04:00
*
2005-11-02 06:58:39 +03:00
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write the Free Software Foundation ,
* Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA
2005-04-17 02:20:36 +04:00
*/
# include "xfs.h"
# include "xfs_fs.h"
2005-11-02 06:38:42 +03:00
# include "xfs_bit.h"
2005-04-17 02:20:36 +04:00
# include "xfs_log.h"
2005-11-02 06:38:42 +03:00
# include "xfs_inum.h"
2005-04-17 02:20:36 +04:00
# include "xfs_trans.h"
# include "xfs_sb.h"
# include "xfs_ag.h"
# include "xfs_dir2.h"
# include "xfs_alloc.h"
# include "xfs_dmapi.h"
# include "xfs_quota.h"
# include "xfs_mount.h"
# include "xfs_bmap_btree.h"
2005-11-02 06:38:42 +03:00
# include "xfs_alloc_btree.h"
2005-04-17 02:20:36 +04:00
# include "xfs_ialloc_btree.h"
# include "xfs_dir2_sf.h"
2005-11-02 06:38:42 +03:00
# include "xfs_attr_sf.h"
2005-04-17 02:20:36 +04:00
# include "xfs_dinode.h"
# include "xfs_inode.h"
# include "xfs_bmap.h"
2005-11-02 06:38:42 +03:00
# include "xfs_btree.h"
# include "xfs_ialloc.h"
2005-04-17 02:20:36 +04:00
# include "xfs_rtalloc.h"
# include "xfs_error.h"
# include "xfs_itable.h"
# include "xfs_rw.h"
# include "xfs_acl.h"
# include "xfs_attr.h"
# include "xfs_buf_item.h"
# include "xfs_utils.h"
2007-08-29 04:58:01 +04:00
# include "xfs_vnodeops.h"
2005-04-17 02:20:36 +04:00
2006-01-11 23:17:46 +03:00
# include <linux/capability.h>
2005-04-17 02:20:36 +04:00
# include <linux/xattr.h>
# include <linux/namei.h>
2006-01-11 07:35:44 +03:00
# include <linux/security.h>
2005-04-17 02:20:36 +04:00
2006-01-11 07:35:17 +03:00
/*
* Bring the atime in the XFS inode uptodate .
* Used before logging the inode to disk or when the Linux inode goes away .
*/
void
xfs_synchronize_atime (
xfs_inode_t * ip )
{
2006-06-09 11:00:52 +04:00
bhv_vnode_t * vp ;
2006-01-11 07:35:17 +03:00
vp = XFS_ITOV_NULL ( ip ) ;
if ( vp ) {
2007-08-29 05:53:12 +04:00
ip - > i_d . di_atime . t_sec = ( __int32_t ) vp - > i_atime . tv_sec ;
ip - > i_d . di_atime . t_nsec = ( __int32_t ) vp - > i_atime . tv_nsec ;
2006-01-11 07:35:17 +03:00
}
}
2005-11-02 03:43:58 +03:00
/*
* Change the requested timestamp in the given inode .
* We don ' t lock across timestamp updates , and we don ' t log them but
* we do record the fact that there is dirty information in core .
*
* NOTE - - callers MUST combine XFS_ICHGTIME_MOD or XFS_ICHGTIME_CHG
* with XFS_ICHGTIME_ACC to be sure that access time
* update will take . Calling first with XFS_ICHGTIME_ACC
* and then XFS_ICHGTIME_MOD may fail to modify the access
* timestamp if the filesystem is mounted noacctm .
*/
void
xfs_ichgtime (
xfs_inode_t * ip ,
int flags )
{
2006-03-17 09:25:36 +03:00
struct inode * inode = vn_to_inode ( XFS_ITOV ( ip ) ) ;
2005-11-02 03:43:58 +03:00
timespec_t tv ;
nanotime ( & tv ) ;
if ( flags & XFS_ICHGTIME_MOD ) {
inode - > i_mtime = tv ;
ip - > i_d . di_mtime . t_sec = ( __int32_t ) tv . tv_sec ;
ip - > i_d . di_mtime . t_nsec = ( __int32_t ) tv . tv_nsec ;
}
if ( flags & XFS_ICHGTIME_ACC ) {
inode - > i_atime = tv ;
ip - > i_d . di_atime . t_sec = ( __int32_t ) tv . tv_sec ;
ip - > i_d . di_atime . t_nsec = ( __int32_t ) tv . tv_nsec ;
}
if ( flags & XFS_ICHGTIME_CHG ) {
inode - > i_ctime = tv ;
ip - > i_d . di_ctime . t_sec = ( __int32_t ) tv . tv_sec ;
ip - > i_d . di_ctime . t_nsec = ( __int32_t ) tv . tv_nsec ;
}
/*
* We update the i_update_core field _after_ changing
* the timestamps in order to coordinate properly with
* xfs_iflush ( ) so that we don ' t lose timestamp updates .
* This keeps us from having to hold the inode lock
* while doing this . We use the SYNCHRONIZE macro to
* ensure that the compiler does not reorder the update
* of i_update_core above the timestamp updates above .
*/
SYNCHRONIZE ( ) ;
ip - > i_update_core = 1 ;
2007-12-07 06:09:11 +03:00
if ( ! ( inode - > i_state & I_NEW ) )
2005-11-02 03:43:58 +03:00
mark_inode_dirty_sync ( inode ) ;
}
/*
* Variant on the above which avoids querying the system clock
* in situations where we know the Linux inode timestamps have
* just been updated ( and so we can update our inode cheaply ) .
*/
void
xfs_ichgtime_fast (
xfs_inode_t * ip ,
struct inode * inode ,
int flags )
{
timespec_t * tvp ;
/*
2006-01-11 07:35:17 +03:00
* Atime updates for read ( ) & friends are handled lazily now , and
* explicit updates must go through xfs_ichgtime ( )
2005-11-02 03:43:58 +03:00
*/
2006-01-11 07:35:17 +03:00
ASSERT ( ( flags & XFS_ICHGTIME_ACC ) = = 0 ) ;
2005-11-02 03:43:58 +03:00
/*
2006-01-11 07:35:17 +03:00
* We ' re not supposed to change timestamps in readonly - mounted
* filesystems . Throw it away if anyone asks us .
2005-11-02 03:43:58 +03:00
*/
2006-01-11 07:35:17 +03:00
if ( unlikely ( IS_RDONLY ( inode ) ) )
2005-11-02 03:43:58 +03:00
return ;
if ( flags & XFS_ICHGTIME_MOD ) {
tvp = & inode - > i_mtime ;
ip - > i_d . di_mtime . t_sec = ( __int32_t ) tvp - > tv_sec ;
ip - > i_d . di_mtime . t_nsec = ( __int32_t ) tvp - > tv_nsec ;
}
if ( flags & XFS_ICHGTIME_CHG ) {
tvp = & inode - > i_ctime ;
ip - > i_d . di_ctime . t_sec = ( __int32_t ) tvp - > tv_sec ;
ip - > i_d . di_ctime . t_nsec = ( __int32_t ) tvp - > tv_nsec ;
}
/*
* We update the i_update_core field _after_ changing
* the timestamps in order to coordinate properly with
* xfs_iflush ( ) so that we don ' t lose timestamp updates .
* This keeps us from having to hold the inode lock
* while doing this . We use the SYNCHRONIZE macro to
* ensure that the compiler does not reorder the update
* of i_update_core above the timestamp updates above .
*/
SYNCHRONIZE ( ) ;
ip - > i_update_core = 1 ;
2007-12-07 06:09:11 +03:00
if ( ! ( inode - > i_state & I_NEW ) )
2005-11-02 03:43:58 +03:00
mark_inode_dirty_sync ( inode ) ;
}
2005-04-17 02:20:36 +04:00
/*
* Pull the link count and size up from the xfs inode to the linux inode
*/
STATIC void
2006-03-14 06:00:51 +03:00
xfs_validate_fields (
2007-09-19 09:27:39 +04:00
struct inode * inode )
2005-04-17 02:20:36 +04:00
{
2007-09-19 09:27:39 +04:00
struct xfs_inode * ip = XFS_I ( inode ) ;
loff_t size ;
inode - > i_nlink = ip - > i_d . di_nlink ;
inode - > i_blocks =
XFS_FSB_TO_BB ( ip - > i_mount , ip - > i_d . di_nblocks +
ip - > i_delayed_blks ) ;
/* we're under i_sem so i_size can't change under us */
size = XFS_ISIZE ( ip ) ;
if ( i_size_read ( inode ) ! = size )
i_size_write ( inode , size ) ;
2005-04-17 02:20:36 +04:00
}
2006-01-11 07:35:44 +03:00
/*
* Hook in SELinux . This is not quite correct yet , what we really need
* here ( as we do for default ACLs ) is a mechanism by which creation of
* these attrs can be journalled at inode creation time ( along with the
* inode , of course , such that log replay can ' t cause these to be lost ) .
*/
STATIC int
2006-03-14 06:00:51 +03:00
xfs_init_security (
2006-06-09 11:00:52 +04:00
bhv_vnode_t * vp ,
2006-01-11 07:35:44 +03:00
struct inode * dir )
{
2006-03-17 09:25:36 +03:00
struct inode * ip = vn_to_inode ( vp ) ;
2006-01-11 07:35:44 +03:00
size_t length ;
void * value ;
char * name ;
int error ;
error = security_inode_init_security ( ip , dir , & name , & value , & length ) ;
if ( error ) {
if ( error = = - EOPNOTSUPP )
return 0 ;
return - error ;
}
2007-08-29 04:58:01 +04:00
error = xfs_attr_set ( XFS_I ( ip ) , name , value ,
length , ATTR_SECURE ) ;
2006-01-11 07:35:44 +03:00
if ( ! error )
2007-08-29 05:44:37 +04:00
xfs_iflags_set ( XFS_I ( ip ) , XFS_IMODIFIED ) ;
2006-01-11 07:35:44 +03:00
kfree ( name ) ;
kfree ( value ) ;
return error ;
}
2005-04-17 02:20:36 +04:00
/*
* Determine whether a process has a valid fs_struct ( kernel daemons
* like knfsd don ' t have an fs_struct ) .
*
* XXX ( hch ) : nfsd is broken , better fix it instead .
*/
2007-02-10 10:34:56 +03:00
STATIC_INLINE int
2006-03-14 06:00:51 +03:00
xfs_has_fs_struct ( struct task_struct * task )
2005-04-17 02:20:36 +04:00
{
return ( task - > fs ! = init_task . fs ) ;
}
2007-02-10 10:34:56 +03:00
STATIC void
2006-03-14 06:00:51 +03:00
xfs_cleanup_inode (
2007-08-29 04:58:01 +04:00
struct inode * dir ,
2006-06-09 11:00:52 +04:00
bhv_vnode_t * vp ,
2006-03-14 05:33:36 +03:00
struct dentry * dentry ,
2006-02-01 04:14:34 +03:00
int mode )
{
struct dentry teardown = { } ;
/* Oh, the horror.
2006-03-14 05:33:36 +03:00
* If we can ' t add the ACL or we fail in
2006-03-14 06:00:51 +03:00
* xfs_init_security we must back out .
2006-02-01 04:14:34 +03:00
* ENOSPC can hit here , among other things .
*/
2006-03-17 09:25:36 +03:00
teardown . d_inode = vn_to_inode ( vp ) ;
2006-02-01 04:14:34 +03:00
teardown . d_name = dentry - > d_name ;
if ( S_ISDIR ( mode ) )
2007-08-29 04:58:01 +04:00
xfs_rmdir ( XFS_I ( dir ) , & teardown ) ;
2006-02-01 04:14:34 +03:00
else
2007-08-29 04:58:01 +04:00
xfs_remove ( XFS_I ( dir ) , & teardown ) ;
2006-02-01 04:14:34 +03:00
VN_RELE ( vp ) ;
}
2005-04-17 02:20:36 +04:00
STATIC int
2006-03-14 06:00:51 +03:00
xfs_vn_mknod (
2005-04-17 02:20:36 +04:00
struct inode * dir ,
struct dentry * dentry ,
int mode ,
dev_t rdev )
{
struct inode * ip ;
2006-06-09 11:00:52 +04:00
bhv_vnode_t * vp = NULL , * dvp = vn_from_inode ( dir ) ;
2005-04-17 02:20:36 +04:00
xfs_acl_t * default_acl = NULL ;
attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS ;
int error ;
/*
* Irix uses Missed ' em ' V split , but doesn ' t want to see
* the upper 5 bits of ( 14 bit ) major .
*/
2006-03-14 05:33:36 +03:00
if ( unlikely ( ! sysv_valid_dev ( rdev ) | | MAJOR ( rdev ) & ~ 0x1ff ) )
2005-04-17 02:20:36 +04:00
return - EINVAL ;
2006-03-14 05:33:36 +03:00
if ( unlikely ( test_default_acl & & test_default_acl ( dvp ) ) ) {
if ( ! _ACL_ALLOC ( default_acl ) ) {
2005-04-17 02:20:36 +04:00
return - ENOMEM ;
2006-03-14 05:33:36 +03:00
}
2005-04-17 02:20:36 +04:00
if ( ! _ACL_GET_DEFAULT ( dvp , default_acl ) ) {
_ACL_FREE ( default_acl ) ;
default_acl = NULL ;
}
}
2006-03-14 06:00:51 +03:00
if ( IS_POSIXACL ( dir ) & & ! default_acl & & xfs_has_fs_struct ( current ) )
2005-04-17 02:20:36 +04:00
mode & = ~ current - > fs - > umask ;
switch ( mode & S_IFMT ) {
case S_IFCHR : case S_IFBLK : case S_IFIFO : case S_IFSOCK :
2007-10-11 12:09:12 +04:00
rdev = sysv_encode_dev ( rdev ) ;
2005-04-17 02:20:36 +04:00
case S_IFREG :
2007-10-11 12:09:12 +04:00
error = xfs_create ( XFS_I ( dir ) , dentry , mode , rdev , & vp , NULL ) ;
2005-04-17 02:20:36 +04:00
break ;
case S_IFDIR :
2007-10-11 12:09:12 +04:00
error = xfs_mkdir ( XFS_I ( dir ) , dentry , mode , & vp , NULL ) ;
2005-04-17 02:20:36 +04:00
break ;
default :
error = EINVAL ;
break ;
}
2006-03-14 05:33:36 +03:00
if ( unlikely ( ! error ) ) {
2006-03-14 06:00:51 +03:00
error = xfs_init_security ( vp , dir ) ;
2006-02-01 04:14:34 +03:00
if ( error )
2007-08-29 04:58:01 +04:00
xfs_cleanup_inode ( dir , vp , dentry , mode ) ;
2006-02-01 04:14:34 +03:00
}
2006-01-11 07:35:44 +03:00
2006-03-14 05:33:36 +03:00
if ( unlikely ( default_acl ) ) {
2005-04-17 02:20:36 +04:00
if ( ! error ) {
2007-10-11 12:09:12 +04:00
error = _ACL_INHERIT ( vp , mode , default_acl ) ;
2006-03-14 05:33:36 +03:00
if ( ! error )
2007-08-29 05:53:12 +04:00
xfs_iflags_set ( XFS_I ( vp ) , XFS_IMODIFIED ) ;
2006-02-01 04:14:34 +03:00
else
2007-08-29 04:58:01 +04:00
xfs_cleanup_inode ( dir , vp , dentry , mode ) ;
2005-04-17 02:20:36 +04:00
}
_ACL_FREE ( default_acl ) ;
}
2006-03-14 05:33:36 +03:00
if ( likely ( ! error ) ) {
2005-04-17 02:20:36 +04:00
ASSERT ( vp ) ;
2006-03-17 09:25:36 +03:00
ip = vn_to_inode ( vp ) ;
2005-04-17 02:20:36 +04:00
2007-12-21 02:58:56 +03:00
if ( S_ISDIR ( mode ) )
2007-09-19 09:27:39 +04:00
xfs_validate_fields ( ip ) ;
2005-04-17 02:20:36 +04:00
d_instantiate ( dentry , ip ) ;
2007-09-19 09:27:39 +04:00
xfs_validate_fields ( dir ) ;
2005-04-17 02:20:36 +04:00
}
return - error ;
}
STATIC int
2006-03-14 06:00:51 +03:00
xfs_vn_create (
2005-04-17 02:20:36 +04:00
struct inode * dir ,
struct dentry * dentry ,
int mode ,
struct nameidata * nd )
{
2006-03-14 06:00:51 +03:00
return xfs_vn_mknod ( dir , dentry , mode , 0 ) ;
2005-04-17 02:20:36 +04:00
}
STATIC int
2006-03-14 06:00:51 +03:00
xfs_vn_mkdir (
2005-04-17 02:20:36 +04:00
struct inode * dir ,
struct dentry * dentry ,
int mode )
{
2006-03-14 06:00:51 +03:00
return xfs_vn_mknod ( dir , dentry , mode | S_IFDIR , 0 ) ;
2005-04-17 02:20:36 +04:00
}
STATIC struct dentry *
2006-03-14 06:00:51 +03:00
xfs_vn_lookup (
2005-04-17 02:20:36 +04:00
struct inode * dir ,
struct dentry * dentry ,
struct nameidata * nd )
{
2007-08-29 04:58:01 +04:00
bhv_vnode_t * cvp ;
2005-04-17 02:20:36 +04:00
int error ;
if ( dentry - > d_name . len > = MAXNAMELEN )
return ERR_PTR ( - ENAMETOOLONG ) ;
2007-08-29 04:58:01 +04:00
error = xfs_lookup ( XFS_I ( dir ) , dentry , & cvp ) ;
2006-06-09 11:00:52 +04:00
if ( unlikely ( error ) ) {
2005-04-17 02:20:36 +04:00
if ( unlikely ( error ! = ENOENT ) )
return ERR_PTR ( - error ) ;
d_add ( dentry , NULL ) ;
return NULL ;
}
2006-03-17 09:25:36 +03:00
return d_splice_alias ( vn_to_inode ( cvp ) , dentry ) ;
2005-04-17 02:20:36 +04:00
}
STATIC int
2006-03-14 06:00:51 +03:00
xfs_vn_link (
2005-04-17 02:20:36 +04:00
struct dentry * old_dentry ,
struct inode * dir ,
struct dentry * dentry )
{
struct inode * ip ; /* inode of guy being linked to */
2006-06-09 11:00:52 +04:00
bhv_vnode_t * vp ; /* vp of name being linked */
2005-04-17 02:20:36 +04:00
int error ;
ip = old_dentry - > d_inode ; /* inode being linked to */
2006-03-17 09:25:36 +03:00
vp = vn_from_inode ( ip ) ;
2005-04-17 02:20:36 +04:00
2006-06-27 10:13:46 +04:00
VN_HOLD ( vp ) ;
2007-08-29 04:58:01 +04:00
error = xfs_link ( XFS_I ( dir ) , vp , dentry ) ;
2006-06-27 10:13:46 +04:00
if ( unlikely ( error ) ) {
VN_RELE ( vp ) ;
} else {
2007-08-29 05:44:37 +04:00
xfs_iflags_set ( XFS_I ( dir ) , XFS_IMODIFIED ) ;
2007-09-19 09:27:39 +04:00
xfs_validate_fields ( ip ) ;
2005-04-17 02:20:36 +04:00
d_instantiate ( dentry , ip ) ;
}
return - error ;
}
STATIC int
2006-03-14 06:00:51 +03:00
xfs_vn_unlink (
2005-04-17 02:20:36 +04:00
struct inode * dir ,
struct dentry * dentry )
{
struct inode * inode ;
int error ;
inode = dentry - > d_inode ;
2007-08-29 04:58:01 +04:00
error = xfs_remove ( XFS_I ( dir ) , dentry ) ;
2006-03-14 05:33:36 +03:00
if ( likely ( ! error ) ) {
2007-09-19 09:27:39 +04:00
xfs_validate_fields ( dir ) ; /* size needs update */
xfs_validate_fields ( inode ) ;
2005-04-17 02:20:36 +04:00
}
return - error ;
}
STATIC int
2006-03-14 06:00:51 +03:00
xfs_vn_symlink (
2005-04-17 02:20:36 +04:00
struct inode * dir ,
struct dentry * dentry ,
const char * symname )
{
struct inode * ip ;
2006-06-09 11:00:52 +04:00
bhv_vnode_t * cvp ; /* used to lookup symlink to put in dentry */
2005-04-17 02:20:36 +04:00
int error ;
2007-10-11 12:09:12 +04:00
mode_t mode ;
2005-04-17 02:20:36 +04:00
cvp = NULL ;
2007-10-11 12:09:12 +04:00
mode = S_IFLNK |
2005-09-02 10:46:51 +04:00
( irix_symlink_mode ? 0777 & ~ current - > fs - > umask : S_IRWXUGO ) ;
2005-04-17 02:20:36 +04:00
2007-10-11 12:09:12 +04:00
error = xfs_symlink ( XFS_I ( dir ) , dentry , ( char * ) symname , mode ,
& cvp , NULL ) ;
2006-01-16 07:54:05 +03:00
if ( likely ( ! error & & cvp ) ) {
2006-03-14 06:00:51 +03:00
error = xfs_init_security ( cvp , dir ) ;
2006-01-16 07:54:05 +03:00
if ( likely ( ! error ) ) {
2006-03-17 09:25:36 +03:00
ip = vn_to_inode ( cvp ) ;
2006-01-16 07:54:05 +03:00
d_instantiate ( dentry , ip ) ;
2007-09-19 09:27:39 +04:00
xfs_validate_fields ( dir ) ;
xfs_validate_fields ( ip ) ;
2006-03-17 09:26:34 +03:00
} else {
2007-08-29 04:58:01 +04:00
xfs_cleanup_inode ( dir , cvp , dentry , 0 ) ;
2006-01-16 07:54:05 +03:00
}
2005-04-17 02:20:36 +04:00
}
return - error ;
}
STATIC int
2006-03-14 06:00:51 +03:00
xfs_vn_rmdir (
2005-04-17 02:20:36 +04:00
struct inode * dir ,
struct dentry * dentry )
{
struct inode * inode = dentry - > d_inode ;
int error ;
2007-08-29 04:58:01 +04:00
error = xfs_rmdir ( XFS_I ( dir ) , dentry ) ;
2006-03-14 05:33:36 +03:00
if ( likely ( ! error ) ) {
2007-09-19 09:27:39 +04:00
xfs_validate_fields ( inode ) ;
xfs_validate_fields ( dir ) ;
2005-04-17 02:20:36 +04:00
}
return - error ;
}
STATIC int
2006-03-14 06:00:51 +03:00
xfs_vn_rename (
2005-04-17 02:20:36 +04:00
struct inode * odir ,
struct dentry * odentry ,
struct inode * ndir ,
struct dentry * ndentry )
{
struct inode * new_inode = ndentry - > d_inode ;
2006-06-09 11:00:52 +04:00
bhv_vnode_t * tvp ; /* target directory */
2005-04-17 02:20:36 +04:00
int error ;
2006-03-17 09:25:36 +03:00
tvp = vn_from_inode ( ndir ) ;
2005-04-17 02:20:36 +04:00
2007-08-29 04:58:01 +04:00
error = xfs_rename ( XFS_I ( odir ) , odentry , tvp , ndentry ) ;
2006-03-14 05:33:36 +03:00
if ( likely ( ! error ) ) {
if ( new_inode )
2007-09-19 09:27:39 +04:00
xfs_validate_fields ( new_inode ) ;
xfs_validate_fields ( odir ) ;
2006-03-14 05:33:36 +03:00
if ( ndir ! = odir )
2007-09-19 09:27:39 +04:00
xfs_validate_fields ( ndir ) ;
2006-03-14 05:33:36 +03:00
}
return - error ;
2005-04-17 02:20:36 +04:00
}
/*
* careful here - this function can get called recursively , so
* we need to be very careful about how much stack we use .
* uio is kmalloced for this reason . . .
*/
[PATCH] Fix up symlink function pointers
This fixes up the symlink functions for the calling convention change:
* afs, autofs4, befs, devfs, freevxfs, jffs2, jfs, ncpfs, procfs,
smbfs, sysvfs, ufs, xfs - prototype change for ->follow_link()
* befs, smbfs, xfs - same for ->put_link()
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-08-20 03:17:39 +04:00
STATIC void *
2006-03-14 06:00:51 +03:00
xfs_vn_follow_link (
2005-04-17 02:20:36 +04:00
struct dentry * dentry ,
struct nameidata * nd )
{
char * link ;
2007-08-28 07:59:03 +04:00
int error = - ENOMEM ;
2005-04-17 02:20:36 +04:00
2006-09-27 12:49:39 +04:00
link = kmalloc ( MAXPATHLEN + 1 , GFP_KERNEL ) ;
2007-08-28 07:59:03 +04:00
if ( ! link )
goto out_err ;
2005-04-17 02:20:36 +04:00
2007-08-29 04:58:01 +04:00
error = - xfs_readlink ( XFS_I ( dentry - > d_inode ) , link ) ;
2007-08-28 07:59:03 +04:00
if ( unlikely ( error ) )
goto out_kfree ;
2005-04-17 02:20:36 +04:00
nd_set_link ( nd , link ) ;
[PATCH] Fix up symlink function pointers
This fixes up the symlink functions for the calling convention change:
* afs, autofs4, befs, devfs, freevxfs, jffs2, jfs, ncpfs, procfs,
smbfs, sysvfs, ufs, xfs - prototype change for ->follow_link()
* befs, smbfs, xfs - same for ->put_link()
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-08-20 03:17:39 +04:00
return NULL ;
2007-08-28 07:59:03 +04:00
out_kfree :
kfree ( link ) ;
out_err :
nd_set_link ( nd , ERR_PTR ( error ) ) ;
return NULL ;
2005-04-17 02:20:36 +04:00
}
2005-09-05 05:47:01 +04:00
STATIC void
2006-03-14 06:00:51 +03:00
xfs_vn_put_link (
2005-09-05 05:47:01 +04:00
struct dentry * dentry ,
struct nameidata * nd ,
void * p )
2005-04-17 02:20:36 +04:00
{
2005-09-05 05:47:01 +04:00
char * s = nd_get_link ( nd ) ;
2005-04-17 02:20:36 +04:00
if ( ! IS_ERR ( s ) )
kfree ( s ) ;
}
# ifdef CONFIG_XFS_POSIX_ACL
STATIC int
2006-03-14 06:00:51 +03:00
xfs_vn_permission (
2005-04-17 02:20:36 +04:00
struct inode * inode ,
int mode ,
struct nameidata * nd )
{
2007-08-29 04:58:01 +04:00
return - xfs_access ( XFS_I ( inode ) , mode < < 6 , NULL ) ;
2005-04-17 02:20:36 +04:00
}
# else
2006-03-14 06:00:51 +03:00
# define xfs_vn_permission NULL
2005-04-17 02:20:36 +04:00
# endif
STATIC int
2006-03-14 06:00:51 +03:00
xfs_vn_getattr (
2005-04-17 02:20:36 +04:00
struct vfsmount * mnt ,
struct dentry * dentry ,
struct kstat * stat )
{
struct inode * inode = dentry - > d_inode ;
2006-09-28 05:01:22 +04:00
bhv_vattr_t vattr = { . va_mask = XFS_AT_STAT } ;
int error ;
2005-04-17 02:20:36 +04:00
2007-08-29 04:58:01 +04:00
error = xfs_getattr ( XFS_I ( inode ) , & vattr , ATTR_LAZY ) ;
2006-09-28 05:01:22 +04:00
if ( likely ( ! error ) ) {
stat - > size = i_size_read ( inode ) ;
stat - > dev = inode - > i_sb - > s_dev ;
stat - > rdev = ( vattr . va_rdev = = 0 ) ? 0 :
MKDEV ( sysv_major ( vattr . va_rdev ) & 0x1ff ,
sysv_minor ( vattr . va_rdev ) ) ;
stat - > mode = vattr . va_mode ;
stat - > nlink = vattr . va_nlink ;
stat - > uid = vattr . va_uid ;
stat - > gid = vattr . va_gid ;
stat - > ino = vattr . va_nodeid ;
stat - > atime = vattr . va_atime ;
stat - > mtime = vattr . va_mtime ;
stat - > ctime = vattr . va_ctime ;
stat - > blocks = vattr . va_nblocks ;
stat - > blksize = vattr . va_blocksize ;
}
2006-06-09 08:58:20 +04:00
return - error ;
2005-04-17 02:20:36 +04:00
}
STATIC int
2006-03-14 06:00:51 +03:00
xfs_vn_setattr (
2005-04-17 02:20:36 +04:00
struct dentry * dentry ,
struct iattr * attr )
{
struct inode * inode = dentry - > d_inode ;
unsigned int ia_valid = attr - > ia_valid ;
2006-06-09 11:07:12 +04:00
bhv_vattr_t vattr = { 0 } ;
2005-04-17 02:20:36 +04:00
int flags = 0 ;
int error ;
if ( ia_valid & ATTR_UID ) {
vattr . va_mask | = XFS_AT_UID ;
vattr . va_uid = attr - > ia_uid ;
}
if ( ia_valid & ATTR_GID ) {
vattr . va_mask | = XFS_AT_GID ;
vattr . va_gid = attr - > ia_gid ;
}
if ( ia_valid & ATTR_SIZE ) {
vattr . va_mask | = XFS_AT_SIZE ;
vattr . va_size = attr - > ia_size ;
}
if ( ia_valid & ATTR_ATIME ) {
vattr . va_mask | = XFS_AT_ATIME ;
vattr . va_atime = attr - > ia_atime ;
2006-04-11 09:12:45 +04:00
inode - > i_atime = attr - > ia_atime ;
2005-04-17 02:20:36 +04:00
}
if ( ia_valid & ATTR_MTIME ) {
vattr . va_mask | = XFS_AT_MTIME ;
vattr . va_mtime = attr - > ia_mtime ;
}
if ( ia_valid & ATTR_CTIME ) {
vattr . va_mask | = XFS_AT_CTIME ;
vattr . va_ctime = attr - > ia_ctime ;
}
if ( ia_valid & ATTR_MODE ) {
vattr . va_mask | = XFS_AT_MODE ;
vattr . va_mode = attr - > ia_mode ;
if ( ! in_group_p ( inode - > i_gid ) & & ! capable ( CAP_FSETID ) )
inode - > i_mode & = ~ S_ISGID ;
}
if ( ia_valid & ( ATTR_MTIME_SET | ATTR_ATIME_SET ) )
flags | = ATTR_UTIME ;
# ifdef ATTR_NO_BLOCK
if ( ( ia_valid & ATTR_NO_BLOCK ) )
flags | = ATTR_NONBLOCK ;
# endif
2007-08-29 04:58:01 +04:00
error = xfs_setattr ( XFS_I ( inode ) , & vattr , flags , NULL ) ;
2006-03-14 05:33:36 +03:00
if ( likely ( ! error ) )
2007-09-19 09:27:49 +04:00
vn_revalidate ( vn_from_inode ( inode ) ) ;
2006-03-14 05:33:36 +03:00
return - error ;
2005-04-17 02:20:36 +04:00
}
STATIC void
2006-03-14 06:00:51 +03:00
xfs_vn_truncate (
2005-04-17 02:20:36 +04:00
struct inode * inode )
{
2006-03-29 04:44:40 +04:00
block_truncate_page ( inode - > i_mapping , inode - > i_size , xfs_get_blocks ) ;
2005-04-17 02:20:36 +04:00
}
STATIC int
2006-03-14 06:00:51 +03:00
xfs_vn_setxattr (
2005-04-17 02:20:36 +04:00
struct dentry * dentry ,
const char * name ,
const void * data ,
size_t size ,
int flags )
{
2006-06-09 11:00:52 +04:00
bhv_vnode_t * vp = vn_from_inode ( dentry - > d_inode ) ;
2005-04-17 02:20:36 +04:00
char * attr = ( char * ) name ;
attrnames_t * namesp ;
int xflags = 0 ;
int error ;
namesp = attr_lookup_namespace ( attr , attr_namespaces , ATTR_NAMECOUNT ) ;
if ( ! namesp )
return - EOPNOTSUPP ;
attr + = namesp - > attr_namelen ;
error = namesp - > attr_capable ( vp , NULL ) ;
if ( error )
return error ;
/* Convert Linux syscall to XFS internal ATTR flags */
if ( flags & XATTR_CREATE )
xflags | = ATTR_CREATE ;
if ( flags & XATTR_REPLACE )
xflags | = ATTR_REPLACE ;
xflags | = namesp - > attr_flag ;
return namesp - > attr_set ( vp , attr , ( void * ) data , size , xflags ) ;
}
STATIC ssize_t
2006-03-14 06:00:51 +03:00
xfs_vn_getxattr (
2005-04-17 02:20:36 +04:00
struct dentry * dentry ,
const char * name ,
void * data ,
size_t size )
{
2006-06-09 11:00:52 +04:00
bhv_vnode_t * vp = vn_from_inode ( dentry - > d_inode ) ;
2005-04-17 02:20:36 +04:00
char * attr = ( char * ) name ;
attrnames_t * namesp ;
int xflags = 0 ;
ssize_t error ;
namesp = attr_lookup_namespace ( attr , attr_namespaces , ATTR_NAMECOUNT ) ;
if ( ! namesp )
return - EOPNOTSUPP ;
attr + = namesp - > attr_namelen ;
error = namesp - > attr_capable ( vp , NULL ) ;
if ( error )
return error ;
/* Convert Linux syscall to XFS internal ATTR flags */
if ( ! size ) {
xflags | = ATTR_KERNOVAL ;
data = NULL ;
}
xflags | = namesp - > attr_flag ;
return namesp - > attr_get ( vp , attr , ( void * ) data , size , xflags ) ;
}
STATIC ssize_t
2006-03-14 06:00:51 +03:00
xfs_vn_listxattr (
2005-04-17 02:20:36 +04:00
struct dentry * dentry ,
char * data ,
size_t size )
{
2006-06-09 11:00:52 +04:00
bhv_vnode_t * vp = vn_from_inode ( dentry - > d_inode ) ;
2005-04-17 02:20:36 +04:00
int error , xflags = ATTR_KERNAMELS ;
ssize_t result ;
if ( ! size )
xflags | = ATTR_KERNOVAL ;
xflags | = capable ( CAP_SYS_ADMIN ) ? ATTR_KERNFULLS : ATTR_KERNORMALS ;
error = attr_generic_list ( vp , data , size , xflags , & result ) ;
if ( error < 0 )
return error ;
return result ;
}
STATIC int
2006-03-14 06:00:51 +03:00
xfs_vn_removexattr (
2005-04-17 02:20:36 +04:00
struct dentry * dentry ,
const char * name )
{
2006-06-09 11:00:52 +04:00
bhv_vnode_t * vp = vn_from_inode ( dentry - > d_inode ) ;
2005-04-17 02:20:36 +04:00
char * attr = ( char * ) name ;
attrnames_t * namesp ;
int xflags = 0 ;
int error ;
namesp = attr_lookup_namespace ( attr , attr_namespaces , ATTR_NAMECOUNT ) ;
if ( ! namesp )
return - EOPNOTSUPP ;
attr + = namesp - > attr_namelen ;
error = namesp - > attr_capable ( vp , NULL ) ;
if ( error )
return error ;
xflags | = namesp - > attr_flag ;
return namesp - > attr_remove ( vp , attr , xflags ) ;
}
2007-02-12 11:55:40 +03:00
const struct inode_operations xfs_inode_operations = {
2006-03-14 06:00:51 +03:00
. permission = xfs_vn_permission ,
. truncate = xfs_vn_truncate ,
. getattr = xfs_vn_getattr ,
. setattr = xfs_vn_setattr ,
. setxattr = xfs_vn_setxattr ,
. getxattr = xfs_vn_getxattr ,
. listxattr = xfs_vn_listxattr ,
. removexattr = xfs_vn_removexattr ,
2005-04-17 02:20:36 +04:00
} ;
2007-02-12 11:55:40 +03:00
const struct inode_operations xfs_dir_inode_operations = {
2006-03-14 06:00:51 +03:00
. create = xfs_vn_create ,
. lookup = xfs_vn_lookup ,
. link = xfs_vn_link ,
. unlink = xfs_vn_unlink ,
. symlink = xfs_vn_symlink ,
. mkdir = xfs_vn_mkdir ,
. rmdir = xfs_vn_rmdir ,
. mknod = xfs_vn_mknod ,
. rename = xfs_vn_rename ,
. permission = xfs_vn_permission ,
. getattr = xfs_vn_getattr ,
. setattr = xfs_vn_setattr ,
. setxattr = xfs_vn_setxattr ,
. getxattr = xfs_vn_getxattr ,
. listxattr = xfs_vn_listxattr ,
. removexattr = xfs_vn_removexattr ,
2005-04-17 02:20:36 +04:00
} ;
2007-02-12 11:55:40 +03:00
const struct inode_operations xfs_symlink_inode_operations = {
2005-04-17 02:20:36 +04:00
. readlink = generic_readlink ,
2006-03-14 06:00:51 +03:00
. follow_link = xfs_vn_follow_link ,
. put_link = xfs_vn_put_link ,
. permission = xfs_vn_permission ,
. getattr = xfs_vn_getattr ,
. setattr = xfs_vn_setattr ,
. setxattr = xfs_vn_setxattr ,
. getxattr = xfs_vn_getxattr ,
. listxattr = xfs_vn_listxattr ,
. removexattr = xfs_vn_removexattr ,
2005-04-17 02:20:36 +04:00
} ;