2023-05-22 03:54:34 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2005-04-17 02:20:36 +04:00
/*
* namei . c
*
* PURPOSE
* Inode name handling routines for the OSTA - UDF ( tm ) filesystem .
*
* COPYRIGHT
* ( C ) 1998 - 2004 Ben Fennema
* ( C ) 1999 - 2000 Stelias Computing Inc
*
* HISTORY
*
* 12 / 12 / 98 blf Created . Split out the lookup code from dir . c
* 04 / 19 / 99 blf link , mknod , symlink support
*/
# include "udfdecl.h"
# include "udf_i.h"
# include "udf_sb.h"
# include <linux/string.h>
# include <linux/errno.h>
# include <linux/mm.h>
# include <linux/slab.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>
2008-04-17 11:47:48 +04:00
# include <linux/crc-itu-t.h>
2008-04-30 19:22:06 +04:00
# include <linux/exportfs.h>
2021-11-04 17:22:35 +03:00
# include <linux/iversion.h>
2005-04-17 02:20:36 +04:00
2010-02-01 05:28:48 +03:00
static inline int udf_match ( int len1 , const unsigned char * name1 , int len2 ,
const unsigned char * name2 )
2005-04-17 02:20:36 +04:00
{
if ( len1 ! = len2 )
return 0 ;
2007-07-21 15:37:18 +04:00
2005-04-17 02:20:36 +04:00
return ! memcmp ( name1 , name2 , len1 ) ;
}
2015-04-08 22:23:58 +03:00
/**
2022-10-05 19:28:33 +03:00
* udf_fiiter_find_entry - find entry in given directory .
2015-04-08 22:23:58 +03:00
*
* @ dir : directory inode to search in
* @ child : qstr of the name
2022-10-05 19:28:33 +03:00
* @ iter : iter to use for searching
2015-04-08 22:23:58 +03:00
*
* This function searches in the directory @ dir for a file name @ child . When
2022-10-05 19:28:33 +03:00
* found , @ iter points to the position in the directory with given entry .
2015-04-08 22:23:58 +03:00
*
2022-10-05 19:28:33 +03:00
* Returns 0 on success , < 0 on error ( including - ENOENT ) .
2015-04-08 22:23:58 +03:00
*/
2022-10-05 19:28:33 +03:00
static int udf_fiiter_find_entry ( struct inode * dir , const struct qstr * child ,
struct udf_fileident_iter * iter )
2005-04-17 02:20:36 +04:00
{
2017-10-12 16:48:40 +03:00
int flen ;
2022-10-05 19:28:33 +03:00
unsigned char * fname = NULL ;
struct super_block * sb = dir - > i_sb ;
2008-10-12 08:15:17 +04:00
int isdotdot = child - > len = = 2 & &
child - > name [ 0 ] = = ' . ' & & child - > name [ 1 ] = = ' . ' ;
2022-10-05 19:28:33 +03:00
int ret ;
2005-04-17 02:20:36 +04:00
2008-03-04 16:14:05 +03:00
fname = kmalloc ( UDF_NAME_LEN , GFP_NOFS ) ;
2022-10-05 19:28:33 +03:00
if ( ! fname )
return - ENOMEM ;
2005-04-17 02:20:36 +04:00
2022-10-05 19:28:33 +03:00
for ( ret = udf_fiiter_init ( iter , dir , 0 ) ;
! ret & & iter - > pos < dir - > i_size ;
ret = udf_fiiter_advance ( iter ) ) {
if ( iter - > fi . fileCharacteristics & FID_FILE_CHAR_DELETED ) {
2014-12-19 00:49:12 +03:00
if ( ! UDF_QUERY_FLAG ( sb , UDF_FLAG_UNDELETE ) )
2005-04-17 02:20:36 +04:00
continue ;
}
2007-07-19 12:47:43 +04:00
2022-10-05 19:28:33 +03:00
if ( iter - > fi . fileCharacteristics & FID_FILE_CHAR_HIDDEN ) {
2014-12-19 00:49:12 +03:00
if ( ! UDF_QUERY_FLAG ( sb , UDF_FLAG_UNHIDE ) )
2005-04-17 02:20:36 +04:00
continue ;
}
2022-10-05 19:28:33 +03:00
if ( ( iter - > fi . fileCharacteristics & FID_FILE_CHAR_PARENT ) & &
2010-12-13 01:18:15 +03:00
isdotdot )
goto out_ok ;
2008-04-30 19:22:06 +04:00
2022-10-05 19:28:33 +03:00
if ( ! iter - > fi . lengthFileIdent )
2005-04-17 02:20:36 +04:00
continue ;
2022-10-05 19:28:33 +03:00
flen = udf_get_filename ( sb , iter - > name ,
iter - > fi . lengthFileIdent , fname , UDF_NAME_LEN ) ;
2015-04-08 22:23:58 +03:00
if ( flen < 0 ) {
2022-10-05 19:28:33 +03:00
ret = flen ;
2015-04-08 22:23:58 +03:00
goto out_err ;
}
if ( udf_match ( flen , fname , child - > len , child - > name ) )
2008-03-04 16:14:05 +03:00
goto out_ok ;
2005-04-17 02:20:36 +04:00
}
2022-10-05 19:28:33 +03:00
if ( ! ret )
ret = - ENOENT ;
2007-07-21 15:37:18 +04:00
2015-04-08 22:23:58 +03:00
out_err :
2022-10-05 19:28:33 +03:00
udf_fiiter_release ( iter ) ;
2008-03-04 16:14:05 +03:00
out_ok :
kfree ( fname ) ;
2007-07-21 15:37:18 +04:00
2022-10-05 19:28:33 +03:00
return ret ;
2005-04-17 02:20:36 +04:00
}
2007-07-19 12:47:43 +04:00
static struct dentry * udf_lookup ( struct inode * dir , struct dentry * dentry ,
2012-06-11 01:13:09 +04:00
unsigned int flags )
2005-04-17 02:20:36 +04:00
{
struct inode * inode = NULL ;
2022-10-05 19:36:21 +03:00
struct udf_fileident_iter iter ;
int err ;
2005-04-17 02:20:36 +04:00
2016-01-15 11:44:21 +03:00
if ( dentry - > d_name . len > UDF_NAME_LEN )
2005-04-17 02:20:36 +04:00
return ERR_PTR ( - ENAMETOOLONG ) ;
2022-10-05 19:36:21 +03:00
err = udf_fiiter_find_entry ( dir , & dentry - > d_name , & iter ) ;
if ( err < 0 & & err ! = - ENOENT )
return ERR_PTR ( err ) ;
2015-04-08 22:23:58 +03:00
2022-10-05 19:36:21 +03:00
if ( err = = 0 ) {
2008-10-15 14:29:03 +04:00
struct kernel_lb_addr loc ;
2022-10-05 19:36:21 +03:00
loc = lelb_to_cpu ( iter . fi . icb . extLocation ) ;
udf_fiiter_release ( & iter ) ;
2005-04-17 02:20:36 +04:00
2008-10-15 14:29:03 +04:00
inode = udf_iget ( dir - > i_sb , & loc ) ;
2014-09-04 18:15:51 +04:00
if ( IS_ERR ( inode ) )
return ERR_CAST ( inode ) ;
2005-04-17 02:20:36 +04:00
}
2007-07-21 15:37:18 +04:00
2008-04-30 19:22:06 +04:00
return d_splice_alias ( inode , dentry ) ;
2005-04-17 02:20:36 +04:00
}
2023-01-24 16:49:52 +03:00
static int udf_expand_dir_adinicb ( struct inode * inode , udf_pblk_t * block )
2005-04-17 02:20:36 +04:00
{
2022-10-05 19:10:37 +03:00
udf_pblk_t newblock ;
struct buffer_head * dbh = NULL ;
2008-10-15 14:28:03 +04:00
struct kernel_lb_addr eloc ;
2022-10-05 19:10:37 +03:00
struct extent_position epos ;
uint8_t alloctype ;
struct udf_inode_info * iinfo = UDF_I ( inode ) ;
struct udf_fileident_iter iter ;
uint8_t * impuse ;
int ret ;
2005-04-17 02:20:36 +04:00
2022-10-05 19:10:37 +03:00
if ( UDF_QUERY_FLAG ( inode - > i_sb , UDF_FLAG_USE_SHORT_AD ) )
alloctype = ICBTAG_FLAG_AD_SHORT ;
else
alloctype = ICBTAG_FLAG_AD_LONG ;
2008-03-04 16:14:05 +03:00
2022-10-05 19:10:37 +03:00
if ( ! inode - > i_size ) {
iinfo - > i_alloc_type = alloctype ;
mark_inode_dirty ( inode ) ;
2023-01-24 16:49:52 +03:00
return 0 ;
2007-07-21 15:37:18 +04:00
}
2005-04-17 02:20:36 +04:00
2022-10-05 19:10:37 +03:00
/* alloc block, and copy data to it */
* block = udf_new_block ( inode - > i_sb , inode ,
iinfo - > i_location . partitionReferenceNum ,
2023-01-24 16:49:52 +03:00
iinfo - > i_location . logicalBlockNum , & ret ) ;
2022-10-05 19:10:37 +03:00
if ( ! ( * block ) )
2023-01-24 16:49:52 +03:00
return ret ;
2022-10-05 19:10:37 +03:00
newblock = udf_get_pblock ( inode - > i_sb , * block ,
iinfo - > i_location . partitionReferenceNum ,
0 ) ;
2023-01-24 16:49:52 +03:00
if ( newblock = = 0xffffffff )
return - EFSCORRUPTED ;
2023-01-18 15:27:07 +03:00
dbh = sb_getblk ( inode - > i_sb , newblock ) ;
2022-10-05 19:10:37 +03:00
if ( ! dbh )
2023-01-24 16:49:52 +03:00
return - ENOMEM ;
2022-10-05 19:10:37 +03:00
lock_buffer ( dbh ) ;
memcpy ( dbh - > b_data , iinfo - > i_data , inode - > i_size ) ;
memset ( dbh - > b_data + inode - > i_size , 0 ,
inode - > i_sb - > s_blocksize - inode - > i_size ) ;
set_buffer_uptodate ( dbh ) ;
unlock_buffer ( dbh ) ;
/* Drop inline data, add block instead */
iinfo - > i_alloc_type = alloctype ;
memset ( iinfo - > i_data + iinfo - > i_lenEAttr , 0 , iinfo - > i_lenAlloc ) ;
iinfo - > i_lenAlloc = 0 ;
eloc . logicalBlockNum = * block ;
eloc . partitionReferenceNum =
iinfo - > i_location . partitionReferenceNum ;
iinfo - > i_lenExtents = inode - > i_size ;
epos . bh = NULL ;
epos . block = iinfo - > i_location ;
epos . offset = udf_file_entry_alloc_offset ( inode ) ;
2022-12-19 21:50:14 +03:00
ret = udf_add_aext ( inode , & epos , & eloc , inode - > i_size , 0 ) ;
2022-10-05 19:10:37 +03:00
brelse ( epos . bh ) ;
2022-12-19 21:50:14 +03:00
if ( ret < 0 ) {
2023-01-24 16:49:52 +03:00
brelse ( dbh ) ;
2022-12-19 21:50:14 +03:00
udf_free_blocks ( inode - > i_sb , inode , & eloc , 0 , 1 ) ;
2023-01-24 16:49:52 +03:00
return ret ;
2022-12-19 21:50:14 +03:00
}
2022-10-05 19:10:37 +03:00
mark_inode_dirty ( inode ) ;
2005-04-17 02:20:36 +04:00
2022-10-05 19:10:37 +03:00
/* Now fixup tags in moved directory entries */
for ( ret = udf_fiiter_init ( & iter , inode , 0 ) ;
! ret & & iter . pos < inode - > i_size ;
ret = udf_fiiter_advance ( & iter ) ) {
iter . fi . descTag . tagLocation = cpu_to_le32 ( * block ) ;
if ( iter . fi . lengthOfImpUse ! = cpu_to_le16 ( 0 ) )
impuse = dbh - > b_data + iter . pos +
sizeof ( struct fileIdentDesc ) ;
else
impuse = NULL ;
udf_fiiter_write_fi ( & iter , impuse ) ;
2005-04-17 02:20:36 +04:00
}
2023-01-24 16:49:52 +03:00
brelse ( dbh ) ;
2022-10-05 19:10:37 +03:00
/*
* We don ' t expect the iteration to fail as the directory has been
* already verified to be correct
*/
WARN_ON_ONCE ( ret ) ;
udf_fiiter_release ( & iter ) ;
2005-04-17 02:20:36 +04:00
2023-01-24 16:49:52 +03:00
return 0 ;
2022-10-05 19:10:37 +03:00
}
2005-04-17 02:20:36 +04:00
2022-10-06 14:25:16 +03:00
static int udf_fiiter_add_entry ( struct inode * dir , struct dentry * dentry ,
struct udf_fileident_iter * iter )
{
struct udf_inode_info * dinfo = UDF_I ( dir ) ;
int nfidlen , namelen = 0 ;
int ret ;
int off , blksize = 1 < < dir - > i_blkbits ;
udf_pblk_t block ;
char name [ UDF_NAME_LEN_CS0 ] ;
2005-04-17 02:20:36 +04:00
2022-10-06 14:25:16 +03:00
if ( dentry ) {
if ( ! dentry - > d_name . len )
return - EINVAL ;
namelen = udf_put_filename ( dir - > i_sb , dentry - > d_name . name ,
dentry - > d_name . len ,
name , UDF_NAME_LEN_CS0 ) ;
if ( ! namelen )
return - ENAMETOOLONG ;
}
nfidlen = ALIGN ( sizeof ( struct fileIdentDesc ) + namelen , UDF_NAME_PAD ) ;
for ( ret = udf_fiiter_init ( iter , dir , 0 ) ;
! ret & & iter - > pos < dir - > i_size ;
ret = udf_fiiter_advance ( iter ) ) {
if ( iter - > fi . fileCharacteristics & FID_FILE_CHAR_DELETED ) {
if ( udf_dir_entry_len ( & iter - > fi ) = = nfidlen ) {
iter - > fi . descTag . tagSerialNum = cpu_to_le16 ( 1 ) ;
iter - > fi . fileVersionNum = cpu_to_le16 ( 1 ) ;
iter - > fi . fileCharacteristics = 0 ;
iter - > fi . lengthFileIdent = namelen ;
iter - > fi . lengthOfImpUse = cpu_to_le16 ( 0 ) ;
memcpy ( iter - > namebuf , name , namelen ) ;
iter - > name = iter - > namebuf ;
return 0 ;
2005-04-17 02:20:36 +04:00
}
}
}
2022-10-06 14:25:16 +03:00
if ( ret ) {
udf_fiiter_release ( iter ) ;
return ret ;
2005-04-17 02:20:36 +04:00
}
2022-10-06 14:25:16 +03:00
if ( dinfo - > i_alloc_type = = ICBTAG_FLAG_AD_IN_ICB & &
blksize - udf_ext0_offset ( dir ) - iter - > pos < nfidlen ) {
udf_fiiter_release ( iter ) ;
2023-01-24 16:49:52 +03:00
ret = udf_expand_dir_adinicb ( dir , & block ) ;
if ( ret )
2022-10-06 14:25:16 +03:00
return ret ;
ret = udf_fiiter_init ( iter , dir , dir - > i_size ) ;
if ( ret < 0 )
return ret ;
}
/* Get blocknumber to use for entry tag */
if ( dinfo - > i_alloc_type = = ICBTAG_FLAG_AD_IN_ICB ) {
block = dinfo - > i_location . logicalBlockNum ;
2007-07-19 12:47:43 +04:00
} else {
2022-10-06 14:25:16 +03:00
block = iter - > eloc . logicalBlockNum +
( ( iter - > elen - 1 ) > > dir - > i_blkbits ) ;
2005-04-17 02:20:36 +04:00
}
2022-10-06 14:25:16 +03:00
off = iter - > pos & ( blksize - 1 ) ;
if ( ! off )
off = blksize ;
/* Entry fits into current block? */
if ( blksize - udf_ext0_offset ( dir ) - off > = nfidlen )
goto store_fi ;
ret = udf_fiiter_append_blk ( iter ) ;
if ( ret ) {
udf_fiiter_release ( iter ) ;
return ret ;
}
/* Entry will be completely in the new block? Update tag location... */
if ( ! ( iter - > pos & ( blksize - 1 ) ) )
block = iter - > eloc . logicalBlockNum +
( ( iter - > elen - 1 ) > > dir - > i_blkbits ) ;
store_fi :
memset ( & iter - > fi , 0 , sizeof ( struct fileIdentDesc ) ) ;
if ( UDF_SB ( dir - > i_sb ) - > s_udfrev > = 0x0200 )
udf_new_tag ( ( char * ) ( & iter - > fi ) , TAG_IDENT_FID , 3 , 1 , block ,
2008-10-15 14:28:03 +04:00
sizeof ( struct tag ) ) ;
2005-04-17 02:20:36 +04:00
else
2022-10-06 14:25:16 +03:00
udf_new_tag ( ( char * ) ( & iter - > fi ) , TAG_IDENT_FID , 2 , 1 , block ,
2008-10-15 14:28:03 +04:00
sizeof ( struct tag ) ) ;
2022-10-06 14:25:16 +03:00
iter - > fi . fileVersionNum = cpu_to_le16 ( 1 ) ;
iter - > fi . lengthFileIdent = namelen ;
iter - > fi . lengthOfImpUse = cpu_to_le16 ( 0 ) ;
memcpy ( iter - > namebuf , name , namelen ) ;
iter - > name = iter - > namebuf ;
dir - > i_size + = nfidlen ;
if ( dinfo - > i_alloc_type = = ICBTAG_FLAG_AD_IN_ICB ) {
dinfo - > i_lenAlloc + = nfidlen ;
2007-07-19 12:47:43 +04:00
} else {
2022-10-06 14:25:16 +03:00
/* Truncate last extent to proper size */
udf_fiiter_update_elen ( iter , iter - > elen -
( dinfo - > i_lenExtents - dir - > i_size ) ) ;
2005-04-17 02:20:36 +04:00
}
2022-10-06 14:25:16 +03:00
mark_inode_dirty ( dir ) ;
2008-03-04 16:14:05 +03:00
2022-10-06 14:25:16 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2022-10-05 20:26:59 +03:00
static void udf_fiiter_delete_entry ( struct udf_fileident_iter * iter )
2005-04-17 02:20:36 +04:00
{
2022-10-05 20:26:59 +03:00
iter - > fi . fileCharacteristics | = FID_FILE_CHAR_DELETED ;
if ( UDF_QUERY_FLAG ( iter - > dir - > i_sb , UDF_FLAG_STRICT ) )
memset ( & iter - > fi . icb , 0x00 , sizeof ( struct long_ad ) ) ;
2007-07-21 15:37:18 +04:00
2022-10-05 20:26:59 +03:00
udf_fiiter_write_fi ( iter , NULL ) ;
}
2023-01-25 21:31:38 +03:00
static void udf_add_fid_counter ( struct super_block * sb , bool dir , int val )
{
struct logicalVolIntegrityDescImpUse * lvidiu = udf_sb_lvidiu ( sb ) ;
2007-07-21 15:37:18 +04:00
2023-01-25 21:31:38 +03:00
if ( ! lvidiu )
return ;
mutex_lock ( & UDF_SB ( sb ) - > s_alloc_mutex ) ;
if ( dir )
le32_add_cpu ( & lvidiu - > numDirs , val ) ;
else
le32_add_cpu ( & lvidiu - > numFiles , val ) ;
udf_updated_lvid ( sb ) ;
mutex_unlock ( & UDF_SB ( sb ) - > s_alloc_mutex ) ;
2005-04-17 02:20:36 +04:00
}
2014-09-04 17:34:14 +04:00
static int udf_add_nondir ( struct dentry * dentry , struct inode * inode )
2005-04-17 02:20:36 +04:00
{
2014-09-04 17:34:14 +04:00
struct udf_inode_info * iinfo = UDF_I ( inode ) ;
2015-03-18 01:25:59 +03:00
struct inode * dir = d_inode ( dentry - > d_parent ) ;
2022-10-06 15:08:59 +03:00
struct udf_fileident_iter iter ;
2005-04-17 02:20:36 +04:00
int err ;
2022-10-06 15:08:59 +03:00
err = udf_fiiter_add_entry ( dir , dentry , & iter ) ;
if ( err ) {
2011-10-28 16:13:28 +04:00
inode_dec_link_count ( inode ) ;
2018-05-16 19:25:39 +03:00
discard_new_inode ( inode ) ;
2005-04-17 02:20:36 +04:00
return err ;
}
2022-10-06 15:08:59 +03:00
iter . fi . icb . extLength = cpu_to_le32 ( inode - > i_sb - > s_blocksize ) ;
iter . fi . icb . extLocation = cpu_to_lelb ( iinfo - > i_location ) ;
* ( __le32 * ) ( ( struct allocDescImpUse * ) iter . fi . icb . impUse ) - > impUse =
2008-02-08 15:20:44 +03:00
cpu_to_le32 ( iinfo - > i_unique & 0x00000000FFFFFFFFUL ) ;
2022-10-06 15:08:59 +03:00
udf_fiiter_write_fi ( & iter , NULL ) ;
2023-07-05 22:01:44 +03:00
dir - > i_mtime = inode_set_ctime_current ( dir ) ;
2015-03-24 23:47:25 +03:00
mark_inode_dirty ( dir ) ;
2022-10-06 15:08:59 +03:00
udf_fiiter_release ( & iter ) ;
2023-01-25 21:31:38 +03:00
udf_add_fid_counter ( dir - > i_sb , false , 1 ) ;
2018-05-04 15:23:01 +03:00
d_instantiate_new ( dentry , inode ) ;
2007-07-21 15:37:18 +04:00
2005-04-17 02:20:36 +04:00
return 0 ;
}
2023-01-13 14:49:13 +03:00
static int udf_create ( struct mnt_idmap * idmap , struct inode * dir ,
2021-01-21 16:19:43 +03:00
struct dentry * dentry , umode_t mode , bool excl )
2014-09-04 17:34:14 +04:00
{
2014-09-04 17:47:41 +04:00
struct inode * inode = udf_new_inode ( dir , mode ) ;
2014-09-04 17:34:14 +04:00
2014-09-04 17:47:41 +04:00
if ( IS_ERR ( inode ) )
return PTR_ERR ( inode ) ;
2014-09-04 17:34:14 +04:00
2023-01-24 14:23:04 +03:00
inode - > i_data . a_ops = & udf_aops ;
2014-09-04 17:34:14 +04:00
inode - > i_op = & udf_file_inode_operations ;
inode - > i_fop = & udf_file_operations ;
mark_inode_dirty ( inode ) ;
return udf_add_nondir ( dentry , inode ) ;
}
2023-01-13 14:49:18 +03:00
static int udf_tmpfile ( struct mnt_idmap * idmap , struct inode * dir ,
2022-09-24 08:00:00 +03:00
struct file * file , umode_t mode )
2013-06-12 09:35:33 +04:00
{
2014-09-04 17:47:41 +04:00
struct inode * inode = udf_new_inode ( dir , mode ) ;
2013-06-12 09:35:33 +04:00
2014-09-04 17:47:41 +04:00
if ( IS_ERR ( inode ) )
return PTR_ERR ( inode ) ;
2013-06-12 09:35:33 +04:00
2023-01-24 14:23:04 +03:00
inode - > i_data . a_ops = & udf_aops ;
2013-06-12 09:35:33 +04:00
inode - > i_op = & udf_file_inode_operations ;
inode - > i_fop = & udf_file_operations ;
mark_inode_dirty ( inode ) ;
2022-09-24 08:00:00 +03:00
d_tmpfile ( file , inode ) ;
2014-09-04 17:38:11 +04:00
unlock_new_inode ( inode ) ;
2022-09-24 08:00:00 +03:00
return finish_open_simple ( file , 0 ) ;
2013-06-12 09:35:33 +04:00
}
2023-01-13 14:49:16 +03:00
static int udf_mknod ( struct mnt_idmap * idmap , struct inode * dir ,
2021-01-21 16:19:43 +03:00
struct dentry * dentry , umode_t mode , dev_t rdev )
2005-04-17 02:20:36 +04:00
{
2007-07-19 12:47:43 +04:00
struct inode * inode ;
2005-04-17 02:20:36 +04:00
if ( ! old_valid_dev ( rdev ) )
return - EINVAL ;
2014-09-04 17:47:41 +04:00
inode = udf_new_inode ( dir , mode ) ;
if ( IS_ERR ( inode ) )
return PTR_ERR ( inode ) ;
2007-07-21 15:37:18 +04:00
2014-09-04 17:34:14 +04:00
init_special_inode ( inode , mode , rdev ) ;
return udf_add_nondir ( dentry , inode ) ;
2005-04-17 02:20:36 +04:00
}
2023-01-13 14:49:15 +03:00
static int udf_mkdir ( struct mnt_idmap * idmap , struct inode * dir ,
2021-01-21 16:19:43 +03:00
struct dentry * dentry , umode_t mode )
2005-04-17 02:20:36 +04:00
{
2007-07-19 12:47:43 +04:00
struct inode * inode ;
2022-10-06 15:22:33 +03:00
struct udf_fileident_iter iter ;
2005-04-17 02:20:36 +04:00
int err ;
2008-02-08 15:20:44 +03:00
struct udf_inode_info * dinfo = UDF_I ( dir ) ;
struct udf_inode_info * iinfo ;
2005-04-17 02:20:36 +04:00
2014-09-04 17:47:41 +04:00
inode = udf_new_inode ( dir , S_IFDIR | mode ) ;
if ( IS_ERR ( inode ) )
return PTR_ERR ( inode ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 15:20:44 +03:00
iinfo = UDF_I ( inode ) ;
2005-04-17 02:20:36 +04:00
inode - > i_op = & udf_dir_inode_operations ;
inode - > i_fop = & udf_dir_operations ;
2022-10-06 15:22:33 +03:00
err = udf_fiiter_add_entry ( inode , NULL , & iter ) ;
if ( err ) {
clear_nlink ( inode ) ;
2018-05-16 19:25:39 +03:00
discard_new_inode ( inode ) ;
2022-10-06 15:22:33 +03:00
return err ;
2005-04-17 02:20:36 +04:00
}
2011-10-28 16:13:29 +04:00
set_nlink ( inode , 2 ) ;
2022-10-06 15:22:33 +03:00
iter . fi . icb . extLength = cpu_to_le32 ( inode - > i_sb - > s_blocksize ) ;
iter . fi . icb . extLocation = cpu_to_lelb ( dinfo - > i_location ) ;
* ( __le32 * ) ( ( struct allocDescImpUse * ) iter . fi . icb . impUse ) - > impUse =
2008-02-08 15:20:44 +03:00
cpu_to_le32 ( dinfo - > i_unique & 0x00000000FFFFFFFFUL ) ;
2022-10-06 15:22:33 +03:00
iter . fi . fileCharacteristics =
2008-02-08 15:20:36 +03:00
FID_FILE_CHAR_DIRECTORY | FID_FILE_CHAR_PARENT ;
2022-10-06 15:22:33 +03:00
udf_fiiter_write_fi ( & iter , NULL ) ;
udf_fiiter_release ( & iter ) ;
2005-04-17 02:20:36 +04:00
mark_inode_dirty ( inode ) ;
2022-10-06 15:22:33 +03:00
err = udf_fiiter_add_entry ( dir , dentry , & iter ) ;
if ( err ) {
2011-10-28 16:13:28 +04:00
clear_nlink ( inode ) ;
2018-05-16 19:25:39 +03:00
discard_new_inode ( inode ) ;
2022-10-06 15:22:33 +03:00
return err ;
2005-04-17 02:20:36 +04:00
}
2022-10-06 15:22:33 +03:00
iter . fi . icb . extLength = cpu_to_le32 ( inode - > i_sb - > s_blocksize ) ;
iter . fi . icb . extLocation = cpu_to_lelb ( iinfo - > i_location ) ;
* ( __le32 * ) ( ( struct allocDescImpUse * ) iter . fi . icb . impUse ) - > impUse =
2008-02-08 15:20:44 +03:00
cpu_to_le32 ( iinfo - > i_unique & 0x00000000FFFFFFFFUL ) ;
2022-10-06 15:22:33 +03:00
iter . fi . fileCharacteristics | = FID_FILE_CHAR_DIRECTORY ;
udf_fiiter_write_fi ( & iter , NULL ) ;
udf_fiiter_release ( & iter ) ;
2023-01-25 21:31:38 +03:00
udf_add_fid_counter ( dir - > i_sb , true , 1 ) ;
2006-10-01 10:29:04 +04:00
inc_nlink ( dir ) ;
2023-07-05 22:01:44 +03:00
dir - > i_mtime = inode_set_ctime_current ( dir ) ;
2005-04-17 02:20:36 +04:00
mark_inode_dirty ( dir ) ;
2018-05-04 15:23:01 +03:00
d_instantiate_new ( dentry , inode ) ;
2007-07-21 15:37:18 +04:00
2022-10-06 15:22:33 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
static int empty_dir ( struct inode * dir )
{
2022-10-05 20:10:02 +03:00
struct udf_fileident_iter iter ;
int ret ;
2005-04-17 02:20:36 +04:00
2022-10-05 20:10:02 +03:00
for ( ret = udf_fiiter_init ( & iter , dir , 0 ) ;
! ret & & iter . pos < dir - > i_size ;
ret = udf_fiiter_advance ( & iter ) ) {
if ( iter . fi . lengthFileIdent & &
! ( iter . fi . fileCharacteristics & FID_FILE_CHAR_DELETED ) ) {
udf_fiiter_release ( & iter ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
}
2022-10-05 20:10:02 +03:00
udf_fiiter_release ( & iter ) ;
2007-07-21 15:37:18 +04:00
2005-04-17 02:20:36 +04:00
return 1 ;
}
2007-07-19 12:47:43 +04:00
static int udf_rmdir ( struct inode * dir , struct dentry * dentry )
2005-04-17 02:20:36 +04:00
{
2022-10-05 20:33:23 +03:00
int ret ;
2015-03-18 01:25:59 +03:00
struct inode * inode = d_inode ( dentry ) ;
2022-10-05 20:33:23 +03:00
struct udf_fileident_iter iter ;
2008-10-15 14:28:03 +04:00
struct kernel_lb_addr tloc ;
2005-04-17 02:20:36 +04:00
2022-10-05 20:33:23 +03:00
ret = udf_fiiter_find_entry ( dir , & dentry - > d_name , & iter ) ;
if ( ret )
2005-04-17 02:20:36 +04:00
goto out ;
2022-10-05 20:33:23 +03:00
ret = - EFSCORRUPTED ;
tloc = lelb_to_cpu ( iter . fi . icb . extLocation ) ;
2008-10-15 14:29:03 +04:00
if ( udf_get_lb_pblock ( dir - > i_sb , & tloc , 0 ) ! = inode - > i_ino )
2005-04-17 02:20:36 +04:00
goto end_rmdir ;
2022-10-05 20:33:23 +03:00
ret = - ENOTEMPTY ;
2005-04-17 02:20:36 +04:00
if ( ! empty_dir ( inode ) )
goto end_rmdir ;
2022-10-05 20:33:23 +03:00
udf_fiiter_delete_entry ( & iter ) ;
2005-04-17 02:20:36 +04:00
if ( inode - > i_nlink ! = 2 )
2017-10-12 16:48:41 +03:00
udf_warn ( inode - > i_sb , " empty directory has nlink != 2 (%u) \n " ,
2011-10-10 12:08:04 +04:00
inode - > i_nlink ) ;
2006-10-01 10:29:06 +04:00
clear_nlink ( inode ) ;
2005-04-17 02:20:36 +04:00
inode - > i_size = 0 ;
2007-05-08 11:31:31 +04:00
inode_dec_link_count ( dir ) ;
2023-01-25 21:31:38 +03:00
udf_add_fid_counter ( dir - > i_sb , true , - 1 ) ;
2023-07-05 22:01:44 +03:00
dir - > i_mtime = inode_set_ctime_to_ts ( dir ,
inode_set_ctime_current ( inode ) ) ;
2005-04-17 02:20:36 +04:00
mark_inode_dirty ( dir ) ;
2022-10-05 20:33:23 +03:00
ret = 0 ;
2007-07-21 15:37:18 +04:00
end_rmdir :
2022-10-05 20:33:23 +03:00
udf_fiiter_release ( & iter ) ;
2007-07-21 15:37:18 +04:00
out :
2022-10-05 20:33:23 +03:00
return ret ;
2005-04-17 02:20:36 +04:00
}
2007-07-19 12:47:43 +04:00
static int udf_unlink ( struct inode * dir , struct dentry * dentry )
2005-04-17 02:20:36 +04:00
{
2022-10-05 20:36:49 +03:00
int ret ;
2015-03-18 01:25:59 +03:00
struct inode * inode = d_inode ( dentry ) ;
2022-10-05 20:36:49 +03:00
struct udf_fileident_iter iter ;
2008-10-15 14:28:03 +04:00
struct kernel_lb_addr tloc ;
2005-04-17 02:20:36 +04:00
2022-10-05 20:36:49 +03:00
ret = udf_fiiter_find_entry ( dir , & dentry - > d_name , & iter ) ;
if ( ret )
2005-04-17 02:20:36 +04:00
goto out ;
2022-10-05 20:36:49 +03:00
ret = - EFSCORRUPTED ;
tloc = lelb_to_cpu ( iter . fi . icb . extLocation ) ;
2008-10-15 14:29:03 +04:00
if ( udf_get_lb_pblock ( dir - > i_sb , & tloc , 0 ) ! = inode - > i_ino )
2005-04-17 02:20:36 +04:00
goto end_unlink ;
2007-07-19 12:47:43 +04:00
if ( ! inode - > i_nlink ) {
2017-10-12 16:48:41 +03:00
udf_debug ( " Deleting nonexistent file (%lu), %u \n " ,
2007-07-19 12:47:43 +04:00
inode - > i_ino , inode - > i_nlink ) ;
2011-10-28 16:13:29 +04:00
set_nlink ( inode , 1 ) ;
2005-04-17 02:20:36 +04:00
}
2022-10-05 20:36:49 +03:00
udf_fiiter_delete_entry ( & iter ) ;
2023-07-05 22:01:44 +03:00
dir - > i_mtime = inode_set_ctime_current ( dir ) ;
2005-04-17 02:20:36 +04:00
mark_inode_dirty ( dir ) ;
2006-10-01 10:29:03 +04:00
inode_dec_link_count ( inode ) ;
2023-01-25 21:31:38 +03:00
udf_add_fid_counter ( dir - > i_sb , false , - 1 ) ;
2023-07-05 22:01:44 +03:00
inode_set_ctime_to_ts ( inode , inode_get_ctime ( dir ) ) ;
2022-10-05 20:36:49 +03:00
ret = 0 ;
2007-07-21 15:37:18 +04:00
end_unlink :
2022-10-05 20:36:49 +03:00
udf_fiiter_release ( & iter ) ;
2007-07-21 15:37:18 +04:00
out :
2022-10-05 20:36:49 +03:00
return ret ;
2005-04-17 02:20:36 +04:00
}
2023-01-13 14:49:14 +03:00
static int udf_symlink ( struct mnt_idmap * idmap , struct inode * dir ,
2021-01-21 16:19:43 +03:00
struct dentry * dentry , const char * symname )
2005-04-17 02:20:36 +04:00
{
2017-04-23 21:58:15 +03:00
struct inode * inode = udf_new_inode ( dir , S_IFLNK | 0777 ) ;
2005-04-17 02:20:36 +04:00
struct pathComponent * pc ;
2010-02-01 05:28:48 +03:00
const char * compstart ;
2007-07-21 15:37:18 +04:00
struct extent_position epos = { } ;
2005-04-17 02:20:36 +04:00
int eoffset , elen = 0 ;
2010-02-01 05:28:48 +03:00
uint8_t * ea ;
2005-04-17 02:20:36 +04:00
int err ;
2017-10-12 16:48:40 +03:00
udf_pblk_t block ;
2010-02-01 05:28:48 +03:00
unsigned char * name = NULL ;
2005-04-17 02:20:36 +04:00
int namelen ;
2008-02-08 15:20:44 +03:00
struct udf_inode_info * iinfo ;
2010-10-20 20:28:46 +04:00
struct super_block * sb = dir - > i_sb ;
2005-04-17 02:20:36 +04:00
2014-09-04 17:47:41 +04:00
if ( IS_ERR ( inode ) )
return PTR_ERR ( inode ) ;
2005-04-17 02:20:36 +04:00
2010-11-16 20:40:47 +03:00
iinfo = UDF_I ( inode ) ;
down_write ( & iinfo - > i_data_sem ) ;
2016-01-15 11:44:21 +03:00
name = kmalloc ( UDF_NAME_LEN_CS0 , GFP_NOFS ) ;
2008-03-04 16:14:05 +03:00
if ( ! name ) {
err = - ENOMEM ;
goto out_no_entry ;
}
2005-04-17 02:20:36 +04:00
inode - > i_data . a_ops = & udf_symlink_aops ;
2017-01-02 16:30:31 +03:00
inode - > i_op = & udf_symlink_inode_operations ;
2015-11-17 09:07:57 +03:00
inode_nohighmem ( inode ) ;
2005-04-17 02:20:36 +04:00
2008-02-08 15:20:44 +03:00
if ( iinfo - > i_alloc_type ! = ICBTAG_FLAG_AD_IN_ICB ) {
2008-10-15 14:28:03 +04:00
struct kernel_lb_addr eloc ;
2008-04-28 13:16:19 +04:00
uint32_t bsize ;
2005-04-17 02:20:36 +04:00
2010-10-20 20:28:46 +04:00
block = udf_new_block ( sb , inode ,
2008-02-08 15:20:44 +03:00
iinfo - > i_location . partitionReferenceNum ,
iinfo - > i_location . logicalBlockNum , & err ) ;
2005-04-17 02:20:36 +04:00
if ( ! block )
goto out_no_entry ;
2008-02-08 15:20:44 +03:00
epos . block = iinfo - > i_location ;
2007-05-08 11:35:14 +04:00
epos . offset = udf_file_entry_alloc_offset ( inode ) ;
epos . bh = NULL ;
2005-04-17 02:20:36 +04:00
eloc . logicalBlockNum = block ;
2008-02-08 15:20:36 +03:00
eloc . partitionReferenceNum =
2008-02-08 15:20:44 +03:00
iinfo - > i_location . partitionReferenceNum ;
2010-10-20 20:28:46 +04:00
bsize = sb - > s_blocksize ;
2008-04-28 13:16:19 +04:00
iinfo - > i_lenExtents = bsize ;
2022-12-19 21:54:12 +03:00
err = udf_add_aext ( inode , & epos , & eloc , bsize , 0 ) ;
2007-05-08 11:35:16 +04:00
brelse ( epos . bh ) ;
2022-12-19 21:54:12 +03:00
if ( err < 0 ) {
udf_free_blocks ( sb , inode , & eloc , 0 , 1 ) ;
goto out_no_entry ;
}
2005-04-17 02:20:36 +04:00
2010-10-20 20:28:46 +04:00
block = udf_get_pblock ( sb , block ,
2008-02-08 15:20:44 +03:00
iinfo - > i_location . partitionReferenceNum ,
2008-02-08 15:20:36 +03:00
0 ) ;
2023-01-18 15:27:07 +03:00
epos . bh = sb_getblk ( sb , block ) ;
2021-05-18 13:34:57 +03:00
if ( unlikely ( ! epos . bh ) ) {
err = - ENOMEM ;
2022-12-19 21:54:12 +03:00
udf_free_blocks ( sb , inode , & eloc , 0 , 1 ) ;
2021-05-18 13:34:57 +03:00
goto out_no_entry ;
}
2007-05-08 11:35:14 +04:00
lock_buffer ( epos . bh ) ;
2010-10-20 20:28:46 +04:00
memset ( epos . bh - > b_data , 0x00 , bsize ) ;
2007-05-08 11:35:14 +04:00
set_buffer_uptodate ( epos . bh ) ;
unlock_buffer ( epos . bh ) ;
mark_buffer_dirty_inode ( epos . bh , inode ) ;
ea = epos . bh - > b_data + udf_ext0_offset ( inode ) ;
2008-02-08 15:20:44 +03:00
} else
2020-09-25 13:29:54 +03:00
ea = iinfo - > i_data + iinfo - > i_lenEAttr ;
2005-04-17 02:20:36 +04:00
2010-10-20 20:28:46 +04:00
eoffset = sb - > s_blocksize - udf_ext0_offset ( inode ) ;
2005-04-17 02:20:36 +04:00
pc = ( struct pathComponent * ) ea ;
2007-07-19 12:47:43 +04:00
if ( * symname = = ' / ' ) {
do {
2005-04-17 02:20:36 +04:00
symname + + ;
} while ( * symname = = ' / ' ) ;
pc - > componentType = 1 ;
pc - > lengthComponentIdent = 0 ;
pc - > componentFileVersionNum = 0 ;
elen + = sizeof ( struct pathComponent ) ;
}
err = - ENAMETOOLONG ;
2007-07-19 12:47:43 +04:00
while ( * symname ) {
2005-04-17 02:20:36 +04:00
if ( elen + sizeof ( struct pathComponent ) > eoffset )
goto out_no_entry ;
pc = ( struct pathComponent * ) ( ea + elen ) ;
2010-02-01 05:28:48 +03:00
compstart = symname ;
2005-04-17 02:20:36 +04:00
2007-07-19 12:47:43 +04:00
do {
2005-04-17 02:20:36 +04:00
symname + + ;
} while ( * symname & & * symname ! = ' / ' ) ;
pc - > componentType = 5 ;
pc - > lengthComponentIdent = 0 ;
pc - > componentFileVersionNum = 0 ;
2007-07-19 12:47:43 +04:00
if ( compstart [ 0 ] = = ' . ' ) {
if ( ( symname - compstart ) = = 1 )
2005-04-17 02:20:36 +04:00
pc - > componentType = 4 ;
2008-02-08 15:20:36 +03:00
else if ( ( symname - compstart ) = = 2 & &
compstart [ 1 ] = = ' . ' )
2005-04-17 02:20:36 +04:00
pc - > componentType = 3 ;
}
2007-07-19 12:47:43 +04:00
if ( pc - > componentType = = 5 ) {
2016-01-15 11:44:19 +03:00
namelen = udf_put_filename ( sb , compstart ,
symname - compstart ,
2016-01-15 11:44:21 +03:00
name , UDF_NAME_LEN_CS0 ) ;
2007-07-21 15:37:18 +04:00
if ( ! namelen )
2005-04-17 02:20:36 +04:00
goto out_no_entry ;
2008-02-08 15:20:36 +03:00
if ( elen + sizeof ( struct pathComponent ) + namelen >
eoffset )
2005-04-17 02:20:36 +04:00
goto out_no_entry ;
else
pc - > lengthComponentIdent = namelen ;
memcpy ( pc - > componentIdent , name , namelen ) ;
}
elen + = sizeof ( struct pathComponent ) + pc - > lengthComponentIdent ;
2007-07-19 12:47:43 +04:00
if ( * symname ) {
do {
2005-04-17 02:20:36 +04:00
symname + + ;
} while ( * symname = = ' / ' ) ;
}
}
2007-05-08 11:35:16 +04:00
brelse ( epos . bh ) ;
2005-04-17 02:20:36 +04:00
inode - > i_size = elen ;
2008-02-08 15:20:44 +03:00
if ( iinfo - > i_alloc_type = = ICBTAG_FLAG_AD_IN_ICB )
iinfo - > i_lenAlloc = inode - > i_size ;
2009-12-03 15:39:28 +03:00
else
udf_truncate_tail_extent ( inode ) ;
2005-04-17 02:20:36 +04:00
mark_inode_dirty ( inode ) ;
2013-12-24 01:02:16 +04:00
up_write ( & iinfo - > i_data_sem ) ;
2005-04-17 02:20:36 +04:00
2014-09-04 17:34:14 +04:00
err = udf_add_nondir ( dentry , inode ) ;
2007-07-21 15:37:18 +04:00
out :
2008-03-04 16:14:05 +03:00
kfree ( name ) ;
2005-04-17 02:20:36 +04:00
return err ;
2007-07-21 15:37:18 +04:00
out_no_entry :
2010-11-16 20:40:47 +03:00
up_write ( & iinfo - > i_data_sem ) ;
2006-10-01 10:29:03 +04:00
inode_dec_link_count ( inode ) ;
2018-05-16 19:25:39 +03:00
discard_new_inode ( inode ) ;
2005-04-17 02:20:36 +04:00
goto out ;
}
2007-07-19 12:47:43 +04:00
static int udf_link ( struct dentry * old_dentry , struct inode * dir ,
struct dentry * dentry )
2005-04-17 02:20:36 +04:00
{
2015-03-18 01:25:59 +03:00
struct inode * inode = d_inode ( old_dentry ) ;
2022-10-06 15:59:11 +03:00
struct udf_fileident_iter iter ;
2005-04-17 02:20:36 +04:00
int err ;
2022-10-06 15:59:11 +03:00
err = udf_fiiter_add_entry ( dir , dentry , & iter ) ;
if ( err )
2005-04-17 02:20:36 +04:00
return err ;
2022-10-06 15:59:11 +03:00
iter . fi . icb . extLength = cpu_to_le32 ( inode - > i_sb - > s_blocksize ) ;
iter . fi . icb . extLocation = cpu_to_lelb ( UDF_I ( inode ) - > i_location ) ;
2010-10-20 20:28:46 +04:00
if ( UDF_SB ( inode - > i_sb ) - > s_lvid_bh ) {
2022-10-06 15:59:11 +03:00
* ( __le32 * ) ( ( struct allocDescImpUse * ) iter . fi . icb . impUse ) - > impUse =
2010-10-20 20:28:46 +04:00
cpu_to_le32 ( lvid_get_unique_id ( inode - > i_sb ) ) ;
2005-04-17 02:20:36 +04:00
}
2022-10-06 15:59:11 +03:00
udf_fiiter_write_fi ( & iter , NULL ) ;
udf_fiiter_release ( & iter ) ;
2007-07-21 15:37:18 +04:00
2006-10-01 10:29:04 +04:00
inc_nlink ( inode ) ;
2023-01-25 21:31:38 +03:00
udf_add_fid_counter ( dir - > i_sb , false , 1 ) ;
2023-07-05 22:01:44 +03:00
inode_set_ctime_current ( inode ) ;
2005-04-17 02:20:36 +04:00
mark_inode_dirty ( inode ) ;
2023-07-05 22:01:44 +03:00
dir - > i_mtime = inode_set_ctime_current ( dir ) ;
2015-03-24 23:47:25 +03:00
mark_inode_dirty ( dir ) ;
2010-10-23 19:11:40 +04:00
ihold ( inode ) ;
2005-04-17 02:20:36 +04:00
d_instantiate ( dentry , inode ) ;
2007-07-21 15:37:18 +04:00
2005-04-17 02:20:36 +04:00
return 0 ;
}
/* Anybody can rename anything with this: the permission checks are left to the
* higher - level routines .
*/
2023-01-13 14:49:17 +03:00
static int udf_rename ( struct mnt_idmap * idmap , struct inode * old_dir ,
2021-01-21 16:19:43 +03:00
struct dentry * old_dentry , struct inode * new_dir ,
struct dentry * new_dentry , unsigned int flags )
2005-04-17 02:20:36 +04:00
{
2015-03-18 01:25:59 +03:00
struct inode * old_inode = d_inode ( old_dentry ) ;
struct inode * new_inode = d_inode ( new_dentry ) ;
2022-10-06 17:41:23 +03:00
struct udf_fileident_iter oiter , niter , diriter ;
bool has_diriter = false ;
int retval ;
2008-10-15 14:28:03 +04:00
struct kernel_lb_addr tloc ;
2005-04-17 02:20:36 +04:00
fs: support RENAME_NOREPLACE for local filesystems
This is trivial to do:
- add flags argument to foo_rename()
- check if flags doesn't have any other than RENAME_NOREPLACE
- assign foo_rename() to .rename2 instead of .rename
Filesystems converted:
affs, bfs, exofs, ext2, hfs, hfsplus, jffs2, jfs, logfs, minix, msdos,
nilfs2, omfs, reiserfs, sysvfs, ubifs, udf, ufs, vfat.
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Acked-by: Boaz Harrosh <ooo@electrozaur.com>
Acked-by: Richard Weinberger <richard@nod.at>
Acked-by: Bob Copeland <me@bobcopeland.com>
Acked-by: Jan Kara <jack@suse.cz>
Cc: Theodore Ts'o <tytso@mit.edu>
Cc: Jaegeuk Kim <jaegeuk@kernel.org>
Cc: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Cc: Mikulas Patocka <mpatocka@redhat.com>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Dave Kleikamp <shaggy@kernel.org>
Cc: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Cc: Christoph Hellwig <hch@infradead.org>
2016-09-27 12:03:57 +03:00
if ( flags & ~ RENAME_NOREPLACE )
return - EINVAL ;
2022-10-06 17:41:23 +03:00
retval = udf_fiiter_find_entry ( old_dir , & old_dentry - > d_name , & oiter ) ;
if ( retval )
return retval ;
2005-04-17 02:20:36 +04:00
2022-10-06 17:41:23 +03:00
tloc = lelb_to_cpu ( oiter . fi . icb . extLocation ) ;
if ( udf_get_lb_pblock ( old_dir - > i_sb , & tloc , 0 ) ! = old_inode - > i_ino ) {
retval = - ENOENT ;
goto out_oiter ;
2005-04-17 02:20:36 +04:00
}
2022-10-06 17:41:23 +03:00
if ( S_ISDIR ( old_inode - > i_mode ) ) {
2007-07-19 12:47:43 +04:00
if ( new_inode ) {
2005-04-17 02:20:36 +04:00
retval = - ENOTEMPTY ;
if ( ! empty_dir ( new_inode ) )
2022-10-06 17:41:23 +03:00
goto out_oiter ;
2005-04-17 02:20:36 +04:00
}
2022-10-06 17:41:23 +03:00
retval = udf_fiiter_find_entry ( old_inode , & dotdot_name ,
& diriter ) ;
if ( retval = = - ENOENT ) {
udf_err ( old_inode - > i_sb ,
" directory (ino %lu) has no '..' entry \n " ,
old_inode - > i_ino ) ;
retval = - EFSCORRUPTED ;
2005-04-17 02:20:36 +04:00
}
2023-06-01 13:58:22 +03:00
if ( retval )
2022-10-06 17:41:23 +03:00
goto out_oiter ;
has_diriter = true ;
tloc = lelb_to_cpu ( diriter . fi . icb . extLocation ) ;
2008-10-15 14:29:03 +04:00
if ( udf_get_lb_pblock ( old_inode - > i_sb , & tloc , 0 ) ! =
2022-10-06 17:41:23 +03:00
old_dir - > i_ino ) {
retval = - EFSCORRUPTED ;
udf_err ( old_inode - > i_sb ,
" directory (ino %lu) has parent entry pointing to another inode (%lu != %u) \n " ,
old_inode - > i_ino , old_dir - > i_ino ,
udf_get_lb_pblock ( old_inode - > i_sb , & tloc , 0 ) ) ;
goto out_oiter ;
}
2005-04-17 02:20:36 +04:00
}
2022-10-06 17:41:23 +03:00
retval = udf_fiiter_find_entry ( new_dir , & new_dentry - > d_name , & niter ) ;
if ( retval & & retval ! = - ENOENT )
goto out_oiter ;
/* Entry found but not passed by VFS? */
if ( ! retval & & ! new_inode ) {
retval = - EFSCORRUPTED ;
udf_fiiter_release ( & niter ) ;
goto out_oiter ;
2005-04-17 02:20:36 +04:00
}
2022-10-06 17:41:23 +03:00
/* Entry not found? Need to add one... */
if ( retval ) {
udf_fiiter_release ( & niter ) ;
retval = udf_fiiter_add_entry ( new_dir , new_dentry , & niter ) ;
if ( retval )
goto out_oiter ;
2005-04-17 02:20:36 +04:00
}
/*
* Like most other Unix systems , set the ctime for inodes on a
* rename .
*/
2023-07-05 22:01:44 +03:00
inode_set_ctime_current ( old_inode ) ;
2005-04-17 02:20:36 +04:00
mark_inode_dirty ( old_inode ) ;
/*
* ok , that ' s it
*/
2022-10-06 17:41:23 +03:00
niter . fi . fileVersionNum = oiter . fi . fileVersionNum ;
niter . fi . fileCharacteristics = oiter . fi . fileCharacteristics ;
memcpy ( & ( niter . fi . icb ) , & ( oiter . fi . icb ) , sizeof ( oiter . fi . icb ) ) ;
udf_fiiter_write_fi ( & niter , NULL ) ;
udf_fiiter_release ( & niter ) ;
2005-04-17 02:20:36 +04:00
2022-10-06 17:41:23 +03:00
/*
* The old entry may have moved due to new entry allocation . Find it
* again .
*/
udf_fiiter_release ( & oiter ) ;
retval = udf_fiiter_find_entry ( old_dir , & old_dentry - > d_name , & oiter ) ;
if ( retval ) {
udf_err ( old_dir - > i_sb ,
" failed to find renamed entry again in directory (ino %lu) \n " ,
old_dir - > i_ino ) ;
} else {
udf_fiiter_delete_entry ( & oiter ) ;
udf_fiiter_release ( & oiter ) ;
}
2005-04-17 02:20:36 +04:00
2007-07-19 12:47:43 +04:00
if ( new_inode ) {
2023-07-05 22:01:44 +03:00
inode_set_ctime_current ( new_inode ) ;
2006-10-01 10:29:03 +04:00
inode_dec_link_count ( new_inode ) ;
2023-01-25 21:31:38 +03:00
udf_add_fid_counter ( old_dir - > i_sb , S_ISDIR ( new_inode - > i_mode ) ,
- 1 ) ;
2005-04-17 02:20:36 +04:00
}
2023-07-05 22:01:44 +03:00
old_dir - > i_mtime = inode_set_ctime_current ( old_dir ) ;
new_dir - > i_mtime = inode_set_ctime_current ( new_dir ) ;
2005-04-17 02:20:36 +04:00
mark_inode_dirty ( old_dir ) ;
2015-03-24 23:47:25 +03:00
mark_inode_dirty ( new_dir ) ;
2005-04-17 02:20:36 +04:00
2022-10-06 17:41:23 +03:00
if ( has_diriter ) {
diriter . fi . icb . extLocation =
cpu_to_lelb ( UDF_I ( new_dir ) - > i_location ) ;
udf_update_tag ( ( char * ) & diriter . fi ,
udf_dir_entry_len ( & diriter . fi ) ) ;
udf_fiiter_write_fi ( & diriter , NULL ) ;
udf_fiiter_release ( & diriter ) ;
2008-02-08 15:20:36 +03:00
2006-10-01 10:29:03 +04:00
inode_dec_link_count ( old_dir ) ;
2008-02-08 15:20:36 +03:00
if ( new_inode )
2006-10-01 10:29:03 +04:00
inode_dec_link_count ( new_inode ) ;
2008-02-08 15:20:36 +03:00
else {
2006-10-01 10:29:04 +04:00
inc_nlink ( new_dir ) ;
2005-04-17 02:20:36 +04:00
mark_inode_dirty ( new_dir ) ;
}
}
2022-10-06 17:41:23 +03:00
return 0 ;
out_oiter :
2023-06-01 13:58:22 +03:00
if ( has_diriter )
2022-10-06 17:41:23 +03:00
udf_fiiter_release ( & diriter ) ;
udf_fiiter_release ( & oiter ) ;
2007-07-21 15:37:18 +04:00
2005-04-17 02:20:36 +04:00
return retval ;
}
2008-04-30 19:22:06 +04:00
static struct dentry * udf_get_parent ( struct dentry * child )
{
2008-10-15 14:29:03 +04:00
struct kernel_lb_addr tloc ;
2008-04-30 19:22:06 +04:00
struct inode * inode = NULL ;
2022-10-05 19:48:45 +03:00
struct udf_fileident_iter iter ;
int err ;
2008-04-30 19:22:06 +04:00
2022-10-05 19:48:45 +03:00
err = udf_fiiter_find_entry ( d_inode ( child ) , & dotdot_name , & iter ) ;
if ( err )
return ERR_PTR ( err ) ;
2008-04-30 19:22:06 +04:00
2022-10-05 19:48:45 +03:00
tloc = lelb_to_cpu ( iter . fi . icb . extLocation ) ;
udf_fiiter_release ( & iter ) ;
2016-04-10 08:33:30 +03:00
inode = udf_iget ( child - > d_sb , & tloc ) ;
2014-09-04 18:15:51 +04:00
if ( IS_ERR ( inode ) )
return ERR_CAST ( inode ) ;
2008-04-30 19:22:06 +04:00
2008-08-11 17:49:04 +04:00
return d_obtain_alias ( inode ) ;
2008-04-30 19:22:06 +04:00
}
static struct dentry * udf_nfs_get_inode ( struct super_block * sb , u32 block ,
u16 partref , __u32 generation )
{
struct inode * inode ;
2008-10-15 14:28:03 +04:00
struct kernel_lb_addr loc ;
2008-04-30 19:22:06 +04:00
if ( block = = 0 )
return ERR_PTR ( - ESTALE ) ;
loc . logicalBlockNum = block ;
loc . partitionReferenceNum = partref ;
2008-10-15 14:29:03 +04:00
inode = udf_iget ( sb , & loc ) ;
2008-04-30 19:22:06 +04:00
2014-09-04 18:15:51 +04:00
if ( IS_ERR ( inode ) )
return ERR_CAST ( inode ) ;
2008-04-30 19:22:06 +04:00
if ( generation & & inode - > i_generation ! = generation ) {
iput ( inode ) ;
return ERR_PTR ( - ESTALE ) ;
}
2008-08-11 17:49:04 +04:00
return d_obtain_alias ( inode ) ;
2008-04-30 19:22:06 +04:00
}
static struct dentry * udf_fh_to_dentry ( struct super_block * sb ,
struct fid * fid , int fh_len , int fh_type )
{
2015-05-08 03:16:23 +03:00
if ( fh_len < 3 | |
2008-04-30 19:22:06 +04:00
( fh_type ! = FILEID_UDF_WITH_PARENT & &
fh_type ! = FILEID_UDF_WITHOUT_PARENT ) )
return NULL ;
return udf_nfs_get_inode ( sb , fid - > udf . block , fid - > udf . partref ,
fid - > udf . generation ) ;
}
static struct dentry * udf_fh_to_parent ( struct super_block * sb ,
struct fid * fid , int fh_len , int fh_type )
{
2015-05-08 03:16:23 +03:00
if ( fh_len < 5 | | fh_type ! = FILEID_UDF_WITH_PARENT )
2008-04-30 19:22:06 +04:00
return NULL ;
return udf_nfs_get_inode ( sb , fid - > udf . parent_block ,
fid - > udf . parent_partref ,
fid - > udf . parent_generation ) ;
}
2012-04-02 22:34:06 +04:00
static int udf_encode_fh ( struct inode * inode , __u32 * fh , int * lenp ,
struct inode * parent )
2008-04-30 19:22:06 +04:00
{
int len = * lenp ;
2008-10-15 14:28:03 +04:00
struct kernel_lb_addr location = UDF_I ( inode ) - > i_location ;
2008-04-30 19:22:06 +04:00
struct fid * fid = ( struct fid * ) fh ;
int type = FILEID_UDF_WITHOUT_PARENT ;
2012-04-02 22:34:06 +04:00
if ( parent & & ( len < 5 ) ) {
2011-01-29 16:13:25 +03:00
* lenp = 5 ;
2013-02-17 10:48:11 +04:00
return FILEID_INVALID ;
2011-01-29 16:13:25 +03:00
} else if ( len < 3 ) {
* lenp = 3 ;
2013-02-17 10:48:11 +04:00
return FILEID_INVALID ;
2011-01-29 16:13:25 +03:00
}
2008-04-30 19:22:06 +04:00
* lenp = 3 ;
fid - > udf . block = location . logicalBlockNum ;
fid - > udf . partref = location . partitionReferenceNum ;
2012-07-12 10:46:55 +04:00
fid - > udf . parent_partref = 0 ;
2008-04-30 19:22:06 +04:00
fid - > udf . generation = inode - > i_generation ;
2012-04-02 22:34:06 +04:00
if ( parent ) {
location = UDF_I ( parent ) - > i_location ;
2008-04-30 19:22:06 +04:00
fid - > udf . parent_block = location . logicalBlockNum ;
fid - > udf . parent_partref = location . partitionReferenceNum ;
fid - > udf . parent_generation = inode - > i_generation ;
* lenp = 5 ;
type = FILEID_UDF_WITH_PARENT ;
}
return type ;
}
const struct export_operations udf_export_ops = {
. encode_fh = udf_encode_fh ,
. fh_to_dentry = udf_fh_to_dentry ,
. fh_to_parent = udf_fh_to_parent ,
. get_parent = udf_get_parent ,
} ;
2007-02-12 11:55:40 +03:00
const struct inode_operations udf_dir_inode_operations = {
2007-07-21 15:37:18 +04:00
. lookup = udf_lookup ,
. create = udf_create ,
. link = udf_link ,
. unlink = udf_unlink ,
. symlink = udf_symlink ,
. mkdir = udf_mkdir ,
. rmdir = udf_rmdir ,
. mknod = udf_mknod ,
. rename = udf_rename ,
2013-06-12 09:35:33 +04:00
. tmpfile = udf_tmpfile ,
2005-04-17 02:20:36 +04:00
} ;