2005-04-17 02:20:36 +04:00
/*
* ialloc . c
*
* PURPOSE
* Inode allocation handling routines for the OSTA - UDF ( tm ) filesystem .
*
* COPYRIGHT
* This file is distributed under the terms of the GNU General Public
* License ( GPL ) . Copies of the GPL can be obtained from :
* ftp : //prep.ai.mit.edu/pub/gnu/GPL
* Each contributing author retains all rights to their own work .
*
* ( C ) 1998 - 2001 Ben Fennema
*
* HISTORY
*
* 02 / 24 / 99 blf Created .
*
*/
# include "udfdecl.h"
# include <linux/fs.h>
# include <linux/sched.h>
# include <linux/slab.h>
# include "udf_i.h"
# include "udf_sb.h"
2007-07-19 12:47:43 +04:00
void udf_free_inode ( struct inode * inode )
2005-04-17 02:20:36 +04:00
{
struct super_block * sb = inode - > i_sb ;
struct udf_sb_info * sbi = UDF_SB ( sb ) ;
2013-09-13 00:00:15 +04:00
struct logicalVolIntegrityDescImpUse * lvidiu = udf_sb_lvidiu ( sb ) ;
2005-04-17 02:20:36 +04:00
2013-09-13 00:00:15 +04:00
if ( lvidiu ) {
mutex_lock ( & sbi - > s_alloc_mutex ) ;
2005-04-17 02:20:36 +04:00
if ( S_ISDIR ( inode - > i_mode ) )
2008-01-31 00:03:57 +03:00
le32_add_cpu ( & lvidiu - > numDirs , - 1 ) ;
2005-04-17 02:20:36 +04:00
else
2008-01-31 00:03:57 +03:00
le32_add_cpu ( & lvidiu - > numFiles , - 1 ) ;
2009-03-16 20:27:37 +03:00
udf_updated_lvid ( sb ) ;
2013-09-13 00:00:15 +04:00
mutex_unlock ( & sbi - > s_alloc_mutex ) ;
2005-04-17 02:20:36 +04:00
}
2008-10-15 14:29:03 +04:00
udf_free_blocks ( sb , NULL , & UDF_I ( inode ) - > i_location , 0 , 1 ) ;
2005-04-17 02:20:36 +04:00
}
2014-09-04 17:47:41 +04:00
struct inode * udf_new_inode ( struct inode * dir , umode_t mode )
2005-04-17 02:20:36 +04:00
{
struct super_block * sb = dir - > i_sb ;
struct udf_sb_info * sbi = UDF_SB ( sb ) ;
2007-07-19 12:47:43 +04:00
struct inode * inode ;
2010-05-19 18:28:56 +04:00
int block ;
2008-02-08 15:20:42 +03:00
uint32_t start = UDF_I ( dir ) - > i_location . logicalBlockNum ;
2008-02-08 15:20:44 +03:00
struct udf_inode_info * iinfo ;
struct udf_inode_info * dinfo = UDF_I ( dir ) ;
2013-09-13 00:00:15 +04:00
struct logicalVolIntegrityDescImpUse * lvidiu ;
2014-09-04 17:47:41 +04:00
int err ;
2005-04-17 02:20:36 +04:00
inode = new_inode ( sb ) ;
2014-09-04 17:47:41 +04:00
if ( ! inode )
return ERR_PTR ( - ENOMEM ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 15:20:44 +03:00
iinfo = UDF_I ( inode ) ;
2008-08-18 15:44:48 +04:00
if ( UDF_QUERY_FLAG ( inode - > i_sb , UDF_FLAG_USE_EXTENDED_FE ) ) {
iinfo - > i_efe = 1 ;
if ( UDF_VERS_USE_EXTENDED_FE > sbi - > s_udfrev )
sbi - > s_udfrev = UDF_VERS_USE_EXTENDED_FE ;
iinfo - > i_ext . i_data = kzalloc ( inode - > i_sb - > s_blocksize -
sizeof ( struct extendedFileEntry ) ,
GFP_KERNEL ) ;
} else {
iinfo - > i_efe = 0 ;
iinfo - > i_ext . i_data = kzalloc ( inode - > i_sb - > s_blocksize -
sizeof ( struct fileEntry ) ,
GFP_KERNEL ) ;
}
if ( ! iinfo - > i_ext . i_data ) {
iput ( inode ) ;
2014-09-04 17:47:41 +04:00
return ERR_PTR ( - ENOMEM ) ;
2008-08-18 15:44:48 +04:00
}
2006-08-05 23:15:17 +04:00
2014-09-04 17:47:41 +04:00
err = - ENOSPC ;
2008-02-08 15:20:36 +03:00
block = udf_new_block ( dir - > i_sb , NULL ,
2008-02-08 15:20:44 +03:00
dinfo - > i_location . partitionReferenceNum ,
2014-09-04 17:47:41 +04:00
start , & err ) ;
if ( err ) {
2005-04-17 02:20:36 +04:00
iput ( inode ) ;
2014-09-04 17:47:41 +04:00
return ERR_PTR ( err ) ;
2005-04-17 02:20:36 +04:00
}
2013-09-13 00:00:15 +04:00
lvidiu = udf_sb_lvidiu ( sb ) ;
if ( lvidiu ) {
2010-10-20 20:28:46 +04:00
iinfo - > i_unique = lvid_get_unique_id ( sb ) ;
2014-09-04 18:26:19 +04:00
inode - > i_generation = iinfo - > i_unique ;
2010-10-20 20:28:46 +04:00
mutex_lock ( & sbi - > s_alloc_mutex ) ;
2005-04-17 02:20:36 +04:00
if ( S_ISDIR ( mode ) )
2008-01-31 00:03:57 +03:00
le32_add_cpu ( & lvidiu - > numDirs , 1 ) ;
2005-04-17 02:20:36 +04:00
else
2008-01-31 00:03:57 +03:00
le32_add_cpu ( & lvidiu - > numFiles , 1 ) ;
2009-03-16 20:27:37 +03:00
udf_updated_lvid ( sb ) ;
2010-10-20 20:28:46 +04:00
mutex_unlock ( & sbi - > s_alloc_mutex ) ;
2005-04-17 02:20:36 +04:00
}
2010-03-04 17:32:22 +03:00
inode_init_owner ( inode , dir , mode ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 15:20:44 +03:00
iinfo - > i_location . logicalBlockNum = block ;
iinfo - > i_location . partitionReferenceNum =
dinfo - > i_location . partitionReferenceNum ;
2008-10-15 14:29:03 +04:00
inode - > i_ino = udf_get_lb_pblock ( sb , & iinfo - > i_location , 0 ) ;
2005-04-17 02:20:36 +04:00
inode - > i_blocks = 0 ;
2008-02-08 15:20:44 +03:00
iinfo - > i_lenEAttr = 0 ;
iinfo - > i_lenAlloc = 0 ;
iinfo - > i_use = 0 ;
2012-02-14 09:28:42 +04:00
iinfo - > i_checkpoint = 1 ;
2005-04-17 02:20:36 +04:00
if ( UDF_QUERY_FLAG ( inode - > i_sb , UDF_FLAG_USE_AD_IN_ICB ) )
2008-02-08 15:20:44 +03:00
iinfo - > i_alloc_type = ICBTAG_FLAG_AD_IN_ICB ;
2005-04-17 02:20:36 +04:00
else if ( UDF_QUERY_FLAG ( inode - > i_sb , UDF_FLAG_USE_SHORT_AD ) )
2008-02-08 15:20:44 +03:00
iinfo - > i_alloc_type = ICBTAG_FLAG_AD_SHORT ;
2005-04-17 02:20:36 +04:00
else
2008-02-08 15:20:44 +03:00
iinfo - > i_alloc_type = ICBTAG_FLAG_AD_LONG ;
2005-04-17 02:20:36 +04:00
inode - > i_mtime = inode - > i_atime = inode - > i_ctime =
2008-02-08 15:20:44 +03:00
iinfo - > i_crtime = current_fs_time ( inode - > i_sb ) ;
2014-09-04 17:38:11 +04:00
if ( unlikely ( insert_inode_locked ( inode ) < 0 ) ) {
make_bad_inode ( inode ) ;
iput ( inode ) ;
2014-09-04 17:47:41 +04:00
return ERR_PTR ( - EIO ) ;
2014-09-04 17:38:11 +04:00
}
2005-04-17 02:20:36 +04:00
mark_inode_dirty ( inode ) ;
return inode ;
}