2005-04-17 02:20:36 +04:00
/*
* linux / fs / hfsplus / inode . c
*
* Copyright ( C ) 2001
* Brad Boyer ( flar @ allandria . com )
* ( C ) 2003 Ardis Technologies < roman @ ardistech . com >
*
* Inode handling routines
*/
# include <linux/mm.h>
# include <linux/fs.h>
# include <linux/pagemap.h>
# include <linux/mpage.h>
Detach sched.h from mm.h
First thing mm.h does is including sched.h solely for can_do_mlock() inline
function which has "current" dereference inside. By dealing with can_do_mlock()
mm.h can be detached from sched.h which is good. See below, why.
This patch
a) removes unconditional inclusion of sched.h from mm.h
b) makes can_do_mlock() normal function in mm/mlock.c
c) exports can_do_mlock() to not break compilation
d) adds sched.h inclusions back to files that were getting it indirectly.
e) adds less bloated headers to some files (asm/signal.h, jiffies.h) that were
getting them indirectly
Net result is:
a) mm.h users would get less code to open, read, preprocess, parse, ... if
they don't need sched.h
b) sched.h stops being dependency for significant number of files:
on x86_64 allmodconfig touching sched.h results in recompile of 4083 files,
after patch it's only 3744 (-8.3%).
Cross-compile tested on
all arm defconfigs, all mips defconfigs, all powerpc defconfigs,
alpha alpha-up
arm
i386 i386-up i386-defconfig i386-allnoconfig
ia64 ia64-up
m68k
mips
parisc parisc-up
powerpc powerpc-up
s390 s390-up
sparc sparc-up
sparc64 sparc64-up
um-x86_64
x86_64 x86_64-up x86_64-defconfig x86_64-allnoconfig
as well as my two usual configs.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-05-21 01:22:52 +04:00
# include <linux/sched.h>
2005-04-17 02:20:36 +04:00
# include "hfsplus_fs.h"
# include "hfsplus_raw.h"
static int hfsplus_readpage ( struct file * file , struct page * page )
{
return block_read_full_page ( page , hfsplus_get_block ) ;
}
static int hfsplus_writepage ( struct page * page , struct writeback_control * wbc )
{
return block_write_full_page ( page , hfsplus_get_block , wbc ) ;
}
2007-10-16 12:25:09 +04:00
static int hfsplus_write_begin ( struct file * file , struct address_space * mapping ,
loff_t pos , unsigned len , unsigned flags ,
struct page * * pagep , void * * fsdata )
2005-04-17 02:20:36 +04:00
{
2010-06-04 13:29:55 +04:00
int ret ;
2007-10-16 12:25:09 +04:00
* pagep = NULL ;
2010-06-04 13:29:55 +04:00
ret = cont_write_begin ( file , mapping , pos , len , flags , pagep , fsdata ,
2007-10-16 12:25:09 +04:00
hfsplus_get_block ,
& HFSPLUS_I ( mapping - > host ) . phys_size ) ;
2010-06-04 13:29:55 +04:00
if ( unlikely ( ret ) ) {
loff_t isize = mapping - > host - > i_size ;
if ( pos + len > isize )
vmtruncate ( mapping - > host , isize ) ;
}
return ret ;
2005-04-17 02:20:36 +04:00
}
static sector_t hfsplus_bmap ( struct address_space * mapping , sector_t block )
{
return generic_block_bmap ( mapping , block , hfsplus_get_block ) ;
}
2005-10-21 11:20:48 +04:00
static int hfsplus_releasepage ( struct page * page , gfp_t mask )
2005-04-17 02:20:36 +04:00
{
struct inode * inode = page - > mapping - > host ;
struct super_block * sb = inode - > i_sb ;
struct hfs_btree * tree ;
struct hfs_bnode * node ;
u32 nidx ;
int i , res = 1 ;
switch ( inode - > i_ino ) {
case HFSPLUS_EXT_CNID :
tree = HFSPLUS_SB ( sb ) . ext_tree ;
break ;
case HFSPLUS_CAT_CNID :
tree = HFSPLUS_SB ( sb ) . cat_tree ;
break ;
case HFSPLUS_ATTR_CNID :
tree = HFSPLUS_SB ( sb ) . attr_tree ;
break ;
default :
BUG ( ) ;
return 0 ;
}
2008-05-13 01:02:21 +04:00
if ( ! tree )
return 0 ;
2005-04-17 02:20:36 +04:00
if ( tree - > node_size > = PAGE_CACHE_SIZE ) {
nidx = page - > index > > ( tree - > node_size_shift - PAGE_CACHE_SHIFT ) ;
spin_lock ( & tree - > hash_lock ) ;
node = hfs_bnode_findhash ( tree , nidx ) ;
if ( ! node )
;
else if ( atomic_read ( & node - > refcnt ) )
res = 0 ;
if ( res & & node ) {
hfs_bnode_unhash ( node ) ;
hfs_bnode_free ( node ) ;
}
spin_unlock ( & tree - > hash_lock ) ;
} else {
nidx = page - > index < < ( PAGE_CACHE_SHIFT - tree - > node_size_shift ) ;
i = 1 < < ( PAGE_CACHE_SHIFT - tree - > node_size_shift ) ;
spin_lock ( & tree - > hash_lock ) ;
do {
node = hfs_bnode_findhash ( tree , nidx + + ) ;
if ( ! node )
continue ;
if ( atomic_read ( & node - > refcnt ) ) {
res = 0 ;
break ;
}
hfs_bnode_unhash ( node ) ;
hfs_bnode_free ( node ) ;
} while ( - - i & & nidx < tree - > node_count ) ;
spin_unlock ( & tree - > hash_lock ) ;
}
return res ? try_to_free_buffers ( page ) : 0 ;
}
static ssize_t hfsplus_direct_IO ( int rw , struct kiocb * iocb ,
const struct iovec * iov , loff_t offset , unsigned long nr_segs )
{
struct file * file = iocb - > ki_filp ;
2006-12-08 13:37:04 +03:00
struct inode * inode = file - > f_path . dentry - > d_inode - > i_mapping - > host ;
2010-06-04 13:29:53 +04:00
ssize_t ret ;
2005-04-17 02:20:36 +04:00
2010-06-04 13:29:53 +04:00
ret = blockdev_direct_IO ( rw , iocb , inode , inode - > i_sb - > s_bdev , iov ,
2006-03-26 13:38:02 +04:00
offset , nr_segs , hfsplus_get_block , NULL ) ;
2010-06-04 13:29:53 +04:00
/*
* In case of error extending write may have instantiated a few
* blocks outside i_size . Trim these off again .
*/
if ( unlikely ( ( rw & WRITE ) & & ret < 0 ) ) {
loff_t isize = i_size_read ( inode ) ;
loff_t end = offset + iov_length ( iov , nr_segs ) ;
if ( end > isize )
vmtruncate ( inode , isize ) ;
}
return ret ;
2005-04-17 02:20:36 +04:00
}
static int hfsplus_writepages ( struct address_space * mapping ,
struct writeback_control * wbc )
{
return mpage_writepages ( mapping , wbc , hfsplus_get_block ) ;
}
2006-06-28 15:26:44 +04:00
const struct address_space_operations hfsplus_btree_aops = {
2005-04-17 02:20:36 +04:00
. readpage = hfsplus_readpage ,
. writepage = hfsplus_writepage ,
. sync_page = block_sync_page ,
2007-10-16 12:25:09 +04:00
. write_begin = hfsplus_write_begin ,
. write_end = generic_write_end ,
2005-04-17 02:20:36 +04:00
. bmap = hfsplus_bmap ,
. releasepage = hfsplus_releasepage ,
} ;
2006-06-28 15:26:44 +04:00
const struct address_space_operations hfsplus_aops = {
2005-04-17 02:20:36 +04:00
. readpage = hfsplus_readpage ,
. writepage = hfsplus_writepage ,
. sync_page = block_sync_page ,
2007-10-16 12:25:09 +04:00
. write_begin = hfsplus_write_begin ,
. write_end = generic_write_end ,
2005-04-17 02:20:36 +04:00
. bmap = hfsplus_bmap ,
. direct_IO = hfsplus_direct_IO ,
. writepages = hfsplus_writepages ,
} ;
2009-02-20 08:55:13 +03:00
const struct dentry_operations hfsplus_dentry_operations = {
2007-07-16 10:41:23 +04:00
. d_hash = hfsplus_hash_dentry ,
. d_compare = hfsplus_compare_dentry ,
} ;
2005-04-17 02:20:36 +04:00
static struct dentry * hfsplus_file_lookup ( struct inode * dir , struct dentry * dentry ,
struct nameidata * nd )
{
struct hfs_find_data fd ;
struct super_block * sb = dir - > i_sb ;
struct inode * inode = NULL ;
int err ;
if ( HFSPLUS_IS_RSRC ( dir ) | | strcmp ( dentry - > d_name . name , " rsrc " ) )
goto out ;
inode = HFSPLUS_I ( dir ) . rsrc_inode ;
if ( inode )
goto out ;
inode = new_inode ( sb ) ;
if ( ! inode )
return ERR_PTR ( - ENOMEM ) ;
inode - > i_ino = dir - > i_ino ;
INIT_LIST_HEAD ( & HFSPLUS_I ( inode ) . open_dir_list ) ;
2008-07-25 12:46:36 +04:00
mutex_init ( & HFSPLUS_I ( inode ) . extents_lock ) ;
2005-04-17 02:20:36 +04:00
HFSPLUS_I ( inode ) . flags = HFSPLUS_FLG_RSRC ;
hfs_find_init ( HFSPLUS_SB ( sb ) . cat_tree , & fd ) ;
err = hfsplus_find_cat ( sb , dir - > i_ino , & fd ) ;
if ( ! err )
err = hfsplus_cat_read_inode ( inode , & fd ) ;
hfs_find_exit ( & fd ) ;
if ( err ) {
iput ( inode ) ;
return ERR_PTR ( err ) ;
}
HFSPLUS_I ( inode ) . rsrc_inode = dir ;
HFSPLUS_I ( dir ) . rsrc_inode = inode ;
igrab ( dir ) ;
hlist_add_head ( & inode - > i_hash , & HFSPLUS_SB ( sb ) . rsrc_inodes ) ;
mark_inode_dirty ( inode ) ;
out :
d_add ( dentry , inode ) ;
return NULL ;
}
static void hfsplus_get_perms ( struct inode * inode , struct hfsplus_perm * perms , int dir )
{
struct super_block * sb = inode - > i_sb ;
u16 mode ;
mode = be16_to_cpu ( perms - > mode ) ;
inode - > i_uid = be32_to_cpu ( perms - > owner ) ;
if ( ! inode - > i_uid & & ! mode )
inode - > i_uid = HFSPLUS_SB ( sb ) . uid ;
inode - > i_gid = be32_to_cpu ( perms - > group ) ;
if ( ! inode - > i_gid & & ! mode )
inode - > i_gid = HFSPLUS_SB ( sb ) . gid ;
if ( dir ) {
mode = mode ? ( mode & S_IALLUGO ) :
( S_IRWXUGO & ~ ( HFSPLUS_SB ( sb ) . umask ) ) ;
mode | = S_IFDIR ;
} else if ( ! mode )
mode = S_IFREG | ( ( S_IRUGO | S_IWUGO ) &
~ ( HFSPLUS_SB ( sb ) . umask ) ) ;
inode - > i_mode = mode ;
HFSPLUS_I ( inode ) . rootflags = perms - > rootflags ;
HFSPLUS_I ( inode ) . userflags = perms - > userflags ;
if ( perms - > rootflags & HFSPLUS_FLG_IMMUTABLE )
inode - > i_flags | = S_IMMUTABLE ;
else
inode - > i_flags & = ~ S_IMMUTABLE ;
if ( perms - > rootflags & HFSPLUS_FLG_APPEND )
inode - > i_flags | = S_APPEND ;
else
inode - > i_flags & = ~ S_APPEND ;
}
static void hfsplus_set_perms ( struct inode * inode , struct hfsplus_perm * perms )
{
if ( inode - > i_flags & S_IMMUTABLE )
perms - > rootflags | = HFSPLUS_FLG_IMMUTABLE ;
else
perms - > rootflags & = ~ HFSPLUS_FLG_IMMUTABLE ;
if ( inode - > i_flags & S_APPEND )
perms - > rootflags | = HFSPLUS_FLG_APPEND ;
else
perms - > rootflags & = ~ HFSPLUS_FLG_APPEND ;
perms - > userflags = HFSPLUS_I ( inode ) . userflags ;
perms - > mode = cpu_to_be16 ( inode - > i_mode ) ;
perms - > owner = cpu_to_be32 ( inode - > i_uid ) ;
perms - > group = cpu_to_be32 ( inode - > i_gid ) ;
perms - > dev = cpu_to_be32 ( HFSPLUS_I ( inode ) . dev ) ;
}
static int hfsplus_file_open ( struct inode * inode , struct file * file )
{
if ( HFSPLUS_IS_RSRC ( inode ) )
inode = HFSPLUS_I ( inode ) . rsrc_inode ;
2008-10-19 07:28:01 +04:00
if ( ! ( file - > f_flags & O_LARGEFILE ) & & i_size_read ( inode ) > MAX_NON_LFS )
return - EOVERFLOW ;
2005-04-17 02:20:36 +04:00
atomic_inc ( & HFSPLUS_I ( inode ) . opencnt ) ;
return 0 ;
}
static int hfsplus_file_release ( struct inode * inode , struct file * file )
{
struct super_block * sb = inode - > i_sb ;
if ( HFSPLUS_IS_RSRC ( inode ) )
inode = HFSPLUS_I ( inode ) . rsrc_inode ;
if ( atomic_dec_and_test ( & HFSPLUS_I ( inode ) . opencnt ) ) {
2006-01-10 02:59:24 +03:00
mutex_lock ( & inode - > i_mutex ) ;
2005-04-17 02:20:36 +04:00
hfsplus_file_truncate ( inode ) ;
if ( inode - > i_flags & S_DEAD ) {
hfsplus_delete_cat ( inode - > i_ino , HFSPLUS_SB ( sb ) . hidden_dir , NULL ) ;
hfsplus_delete_inode ( inode ) ;
}
2006-01-10 02:59:24 +03:00
mutex_unlock ( & inode - > i_mutex ) ;
2005-04-17 02:20:36 +04:00
}
return 0 ;
}
2010-06-04 13:29:59 +04:00
static int hfsplus_setattr ( struct dentry * dentry , struct iattr * attr )
{
struct inode * inode = dentry - > d_inode ;
int error ;
error = inode_change_ok ( inode , attr ) ;
if ( error )
return error ;
return inode_setattr ( inode , attr ) ;
}
2007-02-12 11:55:39 +03:00
static const struct inode_operations hfsplus_file_inode_operations = {
2005-04-17 02:20:36 +04:00
. lookup = hfsplus_file_lookup ,
. truncate = hfsplus_file_truncate ,
2010-06-04 13:29:59 +04:00
. setattr = hfsplus_setattr ,
2005-04-17 02:20:36 +04:00
. setxattr = hfsplus_setxattr ,
. getxattr = hfsplus_getxattr ,
. listxattr = hfsplus_listxattr ,
} ;
2006-03-28 13:56:42 +04:00
static const struct file_operations hfsplus_file_operations = {
2005-04-17 02:20:36 +04:00
. llseek = generic_file_llseek ,
2006-10-01 10:28:48 +04:00
. read = do_sync_read ,
. aio_read = generic_file_aio_read ,
. write = do_sync_write ,
. aio_write = generic_file_aio_write ,
2005-04-17 02:20:36 +04:00
. mmap = generic_file_mmap ,
2007-06-01 13:49:19 +04:00
. splice_read = generic_file_splice_read ,
2005-04-17 02:20:36 +04:00
. fsync = file_fsync ,
. open = hfsplus_file_open ,
. release = hfsplus_file_release ,
2010-04-27 18:24:20 +04:00
. unlocked_ioctl = hfsplus_ioctl ,
2005-04-17 02:20:36 +04:00
} ;
struct inode * hfsplus_new_inode ( struct super_block * sb , int mode )
{
struct inode * inode = new_inode ( sb ) ;
if ( ! inode )
return NULL ;
inode - > i_ino = HFSPLUS_SB ( sb ) . next_cnid + + ;
inode - > i_mode = mode ;
2008-11-14 02:38:54 +03:00
inode - > i_uid = current_fsuid ( ) ;
inode - > i_gid = current_fsgid ( ) ;
2005-04-17 02:20:36 +04:00
inode - > i_nlink = 1 ;
inode - > i_mtime = inode - > i_atime = inode - > i_ctime = CURRENT_TIME_SEC ;
INIT_LIST_HEAD ( & HFSPLUS_I ( inode ) . open_dir_list ) ;
2008-07-25 12:46:36 +04:00
mutex_init ( & HFSPLUS_I ( inode ) . extents_lock ) ;
2005-04-17 02:20:36 +04:00
atomic_set ( & HFSPLUS_I ( inode ) . opencnt , 0 ) ;
HFSPLUS_I ( inode ) . flags = 0 ;
memset ( HFSPLUS_I ( inode ) . first_extents , 0 , sizeof ( hfsplus_extent_rec ) ) ;
memset ( HFSPLUS_I ( inode ) . cached_extents , 0 , sizeof ( hfsplus_extent_rec ) ) ;
HFSPLUS_I ( inode ) . alloc_blocks = 0 ;
HFSPLUS_I ( inode ) . first_blocks = 0 ;
HFSPLUS_I ( inode ) . cached_start = 0 ;
HFSPLUS_I ( inode ) . cached_blocks = 0 ;
HFSPLUS_I ( inode ) . phys_size = 0 ;
HFSPLUS_I ( inode ) . fs_blocks = 0 ;
HFSPLUS_I ( inode ) . rsrc_inode = NULL ;
if ( S_ISDIR ( inode - > i_mode ) ) {
inode - > i_size = 2 ;
HFSPLUS_SB ( sb ) . folder_count + + ;
inode - > i_op = & hfsplus_dir_inode_operations ;
inode - > i_fop = & hfsplus_dir_operations ;
} else if ( S_ISREG ( inode - > i_mode ) ) {
HFSPLUS_SB ( sb ) . file_count + + ;
inode - > i_op = & hfsplus_file_inode_operations ;
inode - > i_fop = & hfsplus_file_operations ;
inode - > i_mapping - > a_ops = & hfsplus_aops ;
HFSPLUS_I ( inode ) . clump_blocks = HFSPLUS_SB ( sb ) . data_clump_blocks ;
} else if ( S_ISLNK ( inode - > i_mode ) ) {
HFSPLUS_SB ( sb ) . file_count + + ;
inode - > i_op = & page_symlink_inode_operations ;
inode - > i_mapping - > a_ops = & hfsplus_aops ;
HFSPLUS_I ( inode ) . clump_blocks = 1 ;
} else
HFSPLUS_SB ( sb ) . file_count + + ;
insert_inode_hash ( inode ) ;
mark_inode_dirty ( inode ) ;
sb - > s_dirt = 1 ;
return inode ;
}
void hfsplus_delete_inode ( struct inode * inode )
{
struct super_block * sb = inode - > i_sb ;
if ( S_ISDIR ( inode - > i_mode ) ) {
HFSPLUS_SB ( sb ) . folder_count - - ;
sb - > s_dirt = 1 ;
return ;
}
HFSPLUS_SB ( sb ) . file_count - - ;
if ( S_ISREG ( inode - > i_mode ) ) {
if ( ! inode - > i_nlink ) {
inode - > i_size = 0 ;
hfsplus_file_truncate ( inode ) ;
}
} else if ( S_ISLNK ( inode - > i_mode ) ) {
inode - > i_size = 0 ;
hfsplus_file_truncate ( inode ) ;
}
sb - > s_dirt = 1 ;
}
void hfsplus_inode_read_fork ( struct inode * inode , struct hfsplus_fork_raw * fork )
{
struct super_block * sb = inode - > i_sb ;
u32 count ;
int i ;
memcpy ( & HFSPLUS_I ( inode ) . first_extents , & fork - > extents ,
sizeof ( hfsplus_extent_rec ) ) ;
for ( count = 0 , i = 0 ; i < 8 ; i + + )
count + = be32_to_cpu ( fork - > extents [ i ] . block_count ) ;
HFSPLUS_I ( inode ) . first_blocks = count ;
memset ( HFSPLUS_I ( inode ) . cached_extents , 0 , sizeof ( hfsplus_extent_rec ) ) ;
HFSPLUS_I ( inode ) . cached_start = 0 ;
HFSPLUS_I ( inode ) . cached_blocks = 0 ;
HFSPLUS_I ( inode ) . alloc_blocks = be32_to_cpu ( fork - > total_blocks ) ;
inode - > i_size = HFSPLUS_I ( inode ) . phys_size = be64_to_cpu ( fork - > total_size ) ;
HFSPLUS_I ( inode ) . fs_blocks = ( inode - > i_size + sb - > s_blocksize - 1 ) > > sb - > s_blocksize_bits ;
inode_set_bytes ( inode , HFSPLUS_I ( inode ) . fs_blocks < < sb - > s_blocksize_bits ) ;
HFSPLUS_I ( inode ) . clump_blocks = be32_to_cpu ( fork - > clump_size ) > > HFSPLUS_SB ( sb ) . alloc_blksz_shift ;
if ( ! HFSPLUS_I ( inode ) . clump_blocks )
HFSPLUS_I ( inode ) . clump_blocks = HFSPLUS_IS_RSRC ( inode ) ? HFSPLUS_SB ( sb ) . rsrc_clump_blocks :
HFSPLUS_SB ( sb ) . data_clump_blocks ;
}
void hfsplus_inode_write_fork ( struct inode * inode , struct hfsplus_fork_raw * fork )
{
memcpy ( & fork - > extents , & HFSPLUS_I ( inode ) . first_extents ,
sizeof ( hfsplus_extent_rec ) ) ;
fork - > total_size = cpu_to_be64 ( inode - > i_size ) ;
fork - > total_blocks = cpu_to_be32 ( HFSPLUS_I ( inode ) . alloc_blocks ) ;
}
int hfsplus_cat_read_inode ( struct inode * inode , struct hfs_find_data * fd )
{
hfsplus_cat_entry entry ;
int res = 0 ;
u16 type ;
type = hfs_bnode_read_u16 ( fd - > bnode , fd - > entryoffset ) ;
HFSPLUS_I ( inode ) . dev = 0 ;
if ( type = = HFSPLUS_FOLDER ) {
struct hfsplus_cat_folder * folder = & entry . folder ;
if ( fd - > entrylength < sizeof ( struct hfsplus_cat_folder ) )
/* panic? */ ;
hfs_bnode_read ( fd - > bnode , & entry , fd - > entryoffset ,
sizeof ( struct hfsplus_cat_folder ) ) ;
hfsplus_get_perms ( inode , & folder - > permissions , 1 ) ;
inode - > i_nlink = 1 ;
inode - > i_size = 2 + be32_to_cpu ( folder - > valence ) ;
inode - > i_atime = hfsp_mt2ut ( folder - > access_date ) ;
inode - > i_mtime = hfsp_mt2ut ( folder - > content_mod_date ) ;
2006-01-19 04:43:09 +03:00
inode - > i_ctime = hfsp_mt2ut ( folder - > attribute_mod_date ) ;
HFSPLUS_I ( inode ) . create_date = folder - > create_date ;
2005-04-17 02:20:36 +04:00
HFSPLUS_I ( inode ) . fs_blocks = 0 ;
inode - > i_op = & hfsplus_dir_inode_operations ;
inode - > i_fop = & hfsplus_dir_operations ;
} else if ( type = = HFSPLUS_FILE ) {
struct hfsplus_cat_file * file = & entry . file ;
if ( fd - > entrylength < sizeof ( struct hfsplus_cat_file ) )
/* panic? */ ;
hfs_bnode_read ( fd - > bnode , & entry , fd - > entryoffset ,
sizeof ( struct hfsplus_cat_file ) ) ;
hfsplus_inode_read_fork ( inode , HFSPLUS_IS_DATA ( inode ) ?
& file - > data_fork : & file - > rsrc_fork ) ;
hfsplus_get_perms ( inode , & file - > permissions , 0 ) ;
inode - > i_nlink = 1 ;
if ( S_ISREG ( inode - > i_mode ) ) {
if ( file - > permissions . dev )
inode - > i_nlink = be32_to_cpu ( file - > permissions . dev ) ;
inode - > i_op = & hfsplus_file_inode_operations ;
inode - > i_fop = & hfsplus_file_operations ;
inode - > i_mapping - > a_ops = & hfsplus_aops ;
} else if ( S_ISLNK ( inode - > i_mode ) ) {
inode - > i_op = & page_symlink_inode_operations ;
inode - > i_mapping - > a_ops = & hfsplus_aops ;
} else {
init_special_inode ( inode , inode - > i_mode ,
be32_to_cpu ( file - > permissions . dev ) ) ;
}
inode - > i_atime = hfsp_mt2ut ( file - > access_date ) ;
inode - > i_mtime = hfsp_mt2ut ( file - > content_mod_date ) ;
2006-01-19 04:43:09 +03:00
inode - > i_ctime = hfsp_mt2ut ( file - > attribute_mod_date ) ;
HFSPLUS_I ( inode ) . create_date = file - > create_date ;
2005-04-17 02:20:36 +04:00
} else {
2006-01-19 04:43:05 +03:00
printk ( KERN_ERR " hfs: bad catalog entry used to create inode \n " ) ;
2005-04-17 02:20:36 +04:00
res = - EIO ;
}
return res ;
}
int hfsplus_cat_write_inode ( struct inode * inode )
{
struct inode * main_inode = inode ;
struct hfs_find_data fd ;
hfsplus_cat_entry entry ;
if ( HFSPLUS_IS_RSRC ( inode ) )
main_inode = HFSPLUS_I ( inode ) . rsrc_inode ;
if ( ! main_inode - > i_nlink )
return 0 ;
if ( hfs_find_init ( HFSPLUS_SB ( main_inode - > i_sb ) . cat_tree , & fd ) )
/* panic? */
return - EIO ;
if ( hfsplus_find_cat ( main_inode - > i_sb , main_inode - > i_ino , & fd ) )
/* panic? */
goto out ;
if ( S_ISDIR ( main_inode - > i_mode ) ) {
struct hfsplus_cat_folder * folder = & entry . folder ;
if ( fd . entrylength < sizeof ( struct hfsplus_cat_folder ) )
/* panic? */ ;
hfs_bnode_read ( fd . bnode , & entry , fd . entryoffset ,
sizeof ( struct hfsplus_cat_folder ) ) ;
/* simple node checks? */
hfsplus_set_perms ( inode , & folder - > permissions ) ;
folder - > access_date = hfsp_ut2mt ( inode - > i_atime ) ;
folder - > content_mod_date = hfsp_ut2mt ( inode - > i_mtime ) ;
folder - > attribute_mod_date = hfsp_ut2mt ( inode - > i_ctime ) ;
folder - > valence = cpu_to_be32 ( inode - > i_size - 2 ) ;
hfs_bnode_write ( fd . bnode , & entry , fd . entryoffset ,
sizeof ( struct hfsplus_cat_folder ) ) ;
} else if ( HFSPLUS_IS_RSRC ( inode ) ) {
struct hfsplus_cat_file * file = & entry . file ;
hfs_bnode_read ( fd . bnode , & entry , fd . entryoffset ,
sizeof ( struct hfsplus_cat_file ) ) ;
hfsplus_inode_write_fork ( inode , & file - > rsrc_fork ) ;
hfs_bnode_write ( fd . bnode , & entry , fd . entryoffset ,
sizeof ( struct hfsplus_cat_file ) ) ;
} else {
struct hfsplus_cat_file * file = & entry . file ;
if ( fd . entrylength < sizeof ( struct hfsplus_cat_file ) )
/* panic? */ ;
hfs_bnode_read ( fd . bnode , & entry , fd . entryoffset ,
sizeof ( struct hfsplus_cat_file ) ) ;
hfsplus_inode_write_fork ( inode , & file - > data_fork ) ;
if ( S_ISREG ( inode - > i_mode ) )
HFSPLUS_I ( inode ) . dev = inode - > i_nlink ;
if ( S_ISCHR ( inode - > i_mode ) | | S_ISBLK ( inode - > i_mode ) )
HFSPLUS_I ( inode ) . dev = kdev_t_to_nr ( inode - > i_rdev ) ;
hfsplus_set_perms ( inode , & file - > permissions ) ;
if ( ( file - > permissions . rootflags | file - > permissions . userflags ) & HFSPLUS_FLG_IMMUTABLE )
file - > flags | = cpu_to_be16 ( HFSPLUS_FILE_LOCKED ) ;
else
file - > flags & = cpu_to_be16 ( ~ HFSPLUS_FILE_LOCKED ) ;
file - > access_date = hfsp_ut2mt ( inode - > i_atime ) ;
file - > content_mod_date = hfsp_ut2mt ( inode - > i_mtime ) ;
file - > attribute_mod_date = hfsp_ut2mt ( inode - > i_ctime ) ;
hfs_bnode_write ( fd . bnode , & entry , fd . entryoffset ,
sizeof ( struct hfsplus_cat_file ) ) ;
}
out :
hfs_find_exit ( & fd ) ;
return 0 ;
}