2005-04-17 02:20:36 +04:00
/*
* JFFS2 - - Journalling Flash File System , Version 2.
*
2007-04-25 17:16:47 +04:00
* Copyright © 2001 - 2007 Red Hat , Inc .
2010-08-08 17:15:22 +04:00
* Copyright © 2004 - 2010 David Woodhouse < dwmw2 @ infradead . org >
2005-04-17 02:20:36 +04:00
*
* Created by David Woodhouse < dwmw2 @ infradead . org >
*
* For licensing information , see the file ' LICENCE ' in this directory .
*
*/
2012-02-16 03:56:45 +04:00
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2005-04-17 02:20:36 +04:00
# include <linux/kernel.h>
# include <linux/slab.h>
# include <linux/fs.h>
# include <linux/crc32.h>
# include <linux/jffs2.h>
2006-05-03 16:07:27 +04:00
# include "jffs2_fs_i.h"
# include "jffs2_fs_sb.h"
2005-04-17 02:20:36 +04:00
# include <linux/time.h>
# include "nodelist.h"
2013-05-18 02:08:49 +04:00
static int jffs2_readdir ( struct file * , struct dir_context * ) ;
2005-04-17 02:20:36 +04:00
2011-07-26 09:42:34 +04:00
static int jffs2_create ( struct inode * , struct dentry * , umode_t ,
2012-06-11 02:05:36 +04:00
bool ) ;
2005-04-17 02:20:36 +04:00
static struct dentry * jffs2_lookup ( struct inode * , struct dentry * ,
2012-06-11 01:13:09 +04:00
unsigned int ) ;
2005-04-17 02:20:36 +04:00
static int jffs2_link ( struct dentry * , struct inode * , struct dentry * ) ;
static int jffs2_unlink ( struct inode * , struct dentry * ) ;
static int jffs2_symlink ( struct inode * , struct dentry * , const char * ) ;
2011-07-26 09:41:39 +04:00
static int jffs2_mkdir ( struct inode * , struct dentry * , umode_t ) ;
2005-04-17 02:20:36 +04:00
static int jffs2_rmdir ( struct inode * , struct dentry * ) ;
2011-07-26 09:52:52 +04:00
static int jffs2_mknod ( struct inode * , struct dentry * , umode_t , dev_t ) ;
2005-04-17 02:20:36 +04:00
static int jffs2_rename ( struct inode * , struct dentry * ,
2007-07-10 13:01:22 +04:00
struct inode * , struct dentry * ) ;
2005-04-17 02:20:36 +04:00
2006-03-28 13:56:42 +04:00
const struct file_operations jffs2_dir_operations =
2005-04-17 02:20:36 +04:00
{
. read = generic_read_dir ,
2016-05-01 05:37:34 +03:00
. iterate_shared = jffs2_readdir ,
2008-07-07 16:45:59 +04:00
. unlocked_ioctl = jffs2_ioctl ,
2008-09-03 23:53:01 +04:00
. fsync = jffs2_fsync ,
. llseek = generic_file_llseek ,
2005-04-17 02:20:36 +04:00
} ;
2007-02-12 11:55:39 +03:00
const struct inode_operations jffs2_dir_inode_operations =
2005-04-17 02:20:36 +04:00
{
2005-07-06 16:13:13 +04:00
. create = jffs2_create ,
. lookup = jffs2_lookup ,
2005-04-17 02:20:36 +04:00
. link = jffs2_link ,
. unlink = jffs2_unlink ,
. symlink = jffs2_symlink ,
. mkdir = jffs2_mkdir ,
. rmdir = jffs2_rmdir ,
. mknod = jffs2_mknod ,
. rename = jffs2_rename ,
2011-07-23 19:37:31 +04:00
. get_acl = jffs2_get_acl ,
2013-12-20 17:16:47 +04:00
. set_acl = jffs2_set_acl ,
2005-04-17 02:20:36 +04:00
. setattr = jffs2_setattr ,
2006-05-13 10:09:47 +04:00
. setxattr = jffs2_setxattr ,
. getxattr = jffs2_getxattr ,
. listxattr = jffs2_listxattr ,
. removexattr = jffs2_removexattr
2005-04-17 02:20:36 +04:00
} ;
/***********************************************************************/
/* We keep the dirent list sorted in increasing order of name hash,
2005-11-07 14:16:07 +03:00
and we use the same hash function as the dentries . Makes this
2005-04-17 02:20:36 +04:00
nice and simple
*/
static struct dentry * jffs2_lookup ( struct inode * dir_i , struct dentry * target ,
2012-06-11 01:13:09 +04:00
unsigned int flags )
2005-04-17 02:20:36 +04:00
{
struct jffs2_inode_info * dir_f ;
struct jffs2_full_dirent * fd = NULL , * fd_list ;
uint32_t ino = 0 ;
struct inode * inode = NULL ;
2012-02-16 03:56:43 +04:00
jffs2_dbg ( 1 , " jffs2_lookup() \n " ) ;
2005-04-17 02:20:36 +04:00
2006-04-18 05:05:46 +04:00
if ( target - > d_name . len > JFFS2_MAX_NAME_LEN )
return ERR_PTR ( - ENAMETOOLONG ) ;
2005-04-17 02:20:36 +04:00
dir_f = JFFS2_INODE_INFO ( dir_i ) ;
2008-04-22 18:13:40 +04:00
mutex_lock ( & dir_f - > sem ) ;
2005-04-17 02:20:36 +04:00
/* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */
for ( fd_list = dir_f - > dents ; fd_list & & fd_list - > nhash < = target - > d_name . hash ; fd_list = fd_list - > next ) {
2005-11-07 14:16:07 +03:00
if ( fd_list - > nhash = = target - > d_name . hash & &
2005-04-17 02:20:36 +04:00
( ! fd | | fd_list - > version > fd - > version ) & &
strlen ( fd_list - > name ) = = target - > d_name . len & &
! strncmp ( fd_list - > name , target - > d_name . name , target - > d_name . len ) ) {
fd = fd_list ;
}
}
if ( fd )
ino = fd - > ino ;
2008-04-22 18:13:40 +04:00
mutex_unlock ( & dir_f - > sem ) ;
2005-04-17 02:20:36 +04:00
if ( ino ) {
2008-02-07 11:15:42 +03:00
inode = jffs2_iget ( dir_i - > i_sb , ino ) ;
2011-07-09 05:20:11 +04:00
if ( IS_ERR ( inode ) )
2012-02-16 03:56:44 +04:00
pr_warn ( " iget() failed for ino #%u \n " , ino ) ;
2005-04-17 02:20:36 +04:00
}
2008-08-18 18:36:47 +04:00
return d_splice_alias ( inode , target ) ;
2005-04-17 02:20:36 +04:00
}
/***********************************************************************/
2013-05-18 02:08:49 +04:00
static int jffs2_readdir ( struct file * file , struct dir_context * ctx )
2005-04-17 02:20:36 +04:00
{
2013-05-18 02:08:49 +04:00
struct inode * inode = file_inode ( file ) ;
struct jffs2_inode_info * f = JFFS2_INODE_INFO ( inode ) ;
2005-04-17 02:20:36 +04:00
struct jffs2_full_dirent * fd ;
2013-05-18 02:08:49 +04:00
unsigned long curofs = 1 ;
2005-04-17 02:20:36 +04:00
2013-05-18 02:08:49 +04:00
jffs2_dbg ( 1 , " jffs2_readdir() for dir_i #%lu \n " , inode - > i_ino ) ;
2005-04-17 02:20:36 +04:00
2013-05-18 02:08:49 +04:00
if ( ! dir_emit_dots ( file , ctx ) )
return 0 ;
2005-04-17 02:20:36 +04:00
2008-04-22 18:13:40 +04:00
mutex_lock ( & f - > sem ) ;
2005-04-17 02:20:36 +04:00
for ( fd = f - > dents ; fd ; fd = fd - > next ) {
curofs + + ;
2013-05-18 02:08:49 +04:00
/* First loop: curofs = 2; pos = 2 */
if ( curofs < ctx - > pos ) {
2012-02-16 03:56:43 +04:00
jffs2_dbg ( 2 , " Skipping dirent: \" %s \" , ino #%u, type %d, because curofs %ld < offset %ld \n " ,
2013-05-18 02:08:49 +04:00
fd - > name , fd - > ino , fd - > type , curofs , ( unsigned long ) ctx - > pos ) ;
2005-04-17 02:20:36 +04:00
continue ;
}
if ( ! fd - > ino ) {
2012-02-16 03:56:43 +04:00
jffs2_dbg ( 2 , " Skipping deletion dirent \" %s \" \n " ,
fd - > name ) ;
2013-05-18 02:08:49 +04:00
ctx - > pos + + ;
2005-04-17 02:20:36 +04:00
continue ;
}
2012-02-16 03:56:43 +04:00
jffs2_dbg ( 2 , " Dirent %ld: \" %s \" , ino #%u, type %d \n " ,
2013-05-18 02:08:49 +04:00
( unsigned long ) ctx - > pos , fd - > name , fd - > ino , fd - > type ) ;
if ( ! dir_emit ( ctx , fd - > name , strlen ( fd - > name ) , fd - > ino , fd - > type ) )
2005-04-17 02:20:36 +04:00
break ;
2013-05-18 02:08:49 +04:00
ctx - > pos + + ;
2005-04-17 02:20:36 +04:00
}
2008-04-22 18:13:40 +04:00
mutex_unlock ( & f - > sem ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
/***********************************************************************/
2011-07-26 09:42:34 +04:00
static int jffs2_create ( struct inode * dir_i , struct dentry * dentry ,
2012-06-11 02:05:36 +04:00
umode_t mode , bool excl )
2005-04-17 02:20:36 +04:00
{
struct jffs2_raw_inode * ri ;
struct jffs2_inode_info * f , * dir_f ;
struct jffs2_sb_info * c ;
struct inode * inode ;
int ret ;
ri = jffs2_alloc_raw_inode ( ) ;
if ( ! ri )
return - ENOMEM ;
2005-11-07 14:16:07 +03:00
2005-04-17 02:20:36 +04:00
c = JFFS2_SB_INFO ( dir_i - > i_sb ) ;
2012-02-16 03:56:43 +04:00
jffs2_dbg ( 1 , " %s() \n " , __func__ ) ;
2005-04-17 02:20:36 +04:00
2007-09-14 10:16:35 +04:00
inode = jffs2_new_inode ( dir_i , mode , ri ) ;
2005-04-17 02:20:36 +04:00
if ( IS_ERR ( inode ) ) {
2012-02-16 03:56:43 +04:00
jffs2_dbg ( 1 , " jffs2_new_inode() failed \n " ) ;
2005-04-17 02:20:36 +04:00
jffs2_free_raw_inode ( ri ) ;
return PTR_ERR ( inode ) ;
}
inode - > i_op = & jffs2_file_inode_operations ;
inode - > i_fop = & jffs2_file_operations ;
inode - > i_mapping - > a_ops = & jffs2_file_address_operations ;
inode - > i_mapping - > nrpages = 0 ;
f = JFFS2_INODE_INFO ( inode ) ;
dir_f = JFFS2_INODE_INFO ( dir_i ) ;
2008-05-01 18:53:28 +04:00
/* jffs2_do_create() will want to lock it, _after_ reserving
space and taking c - alloc_sem . If we keep it locked here ,
lockdep gets unhappy ( although it ' s a false positive ;
nothing else will be looking at this inode yet so there ' s
no chance of AB - BA deadlock involving its f - > sem ) . */
mutex_unlock ( & f - > sem ) ;
2011-02-01 19:05:39 +03:00
ret = jffs2_do_create ( c , dir_f , f , ri , & dentry - > d_name ) ;
2006-05-13 10:09:47 +04:00
if ( ret )
goto fail ;
2005-04-17 02:20:36 +04:00
dir_i - > i_mtime = dir_i - > i_ctime = ITIME ( je32_to_cpu ( ri - > ctime ) ) ;
jffs2_free_raw_inode ( ri ) ;
2012-02-16 03:56:43 +04:00
jffs2_dbg ( 1 , " %s(): Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld \n " ,
__func__ , inode - > i_ino , inode - > i_mode , inode - > i_nlink ,
f - > inocache - > pino_nlink , inode - > i_mapping - > nrpages ) ;
2010-06-03 11:09:12 +04:00
unlock_new_inode ( inode ) ;
2012-07-19 09:18:15 +04:00
d_instantiate ( dentry , inode ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2006-05-13 10:09:47 +04:00
fail :
2010-06-08 21:24:56 +04:00
iget_failed ( inode ) ;
2006-05-13 10:09:47 +04:00
jffs2_free_raw_inode ( ri ) ;
return ret ;
2005-04-17 02:20:36 +04:00
}
/***********************************************************************/
static int jffs2_unlink ( struct inode * dir_i , struct dentry * dentry )
{
struct jffs2_sb_info * c = JFFS2_SB_INFO ( dir_i - > i_sb ) ;
struct jffs2_inode_info * dir_f = JFFS2_INODE_INFO ( dir_i ) ;
2015-03-18 01:25:59 +03:00
struct jffs2_inode_info * dead_f = JFFS2_INODE_INFO ( d_inode ( dentry ) ) ;
2005-04-17 02:20:36 +04:00
int ret ;
2005-08-17 17:46:26 +04:00
uint32_t now = get_seconds ( ) ;
2005-04-17 02:20:36 +04:00
2005-11-07 14:16:07 +03:00
ret = jffs2_do_unlink ( c , dir_f , dentry - > d_name . name ,
2005-08-17 17:46:26 +04:00
dentry - > d_name . len , dead_f , now ) ;
2005-04-17 02:20:36 +04:00
if ( dead_f - > inocache )
2015-03-18 01:25:59 +03:00
set_nlink ( d_inode ( dentry ) , dead_f - > inocache - > pino_nlink ) ;
2005-08-17 17:46:26 +04:00
if ( ! ret )
dir_i - > i_mtime = dir_i - > i_ctime = ITIME ( now ) ;
2005-04-17 02:20:36 +04:00
return ret ;
}
/***********************************************************************/
static int jffs2_link ( struct dentry * old_dentry , struct inode * dir_i , struct dentry * dentry )
{
2016-04-10 08:33:30 +03:00
struct jffs2_sb_info * c = JFFS2_SB_INFO ( old_dentry - > d_sb ) ;
2015-03-18 01:25:59 +03:00
struct jffs2_inode_info * f = JFFS2_INODE_INFO ( d_inode ( old_dentry ) ) ;
2005-04-17 02:20:36 +04:00
struct jffs2_inode_info * dir_f = JFFS2_INODE_INFO ( dir_i ) ;
int ret ;
uint8_t type ;
2005-08-17 17:46:26 +04:00
uint32_t now ;
2005-04-17 02:20:36 +04:00
/* Don't let people make hard links to bad inodes. */
if ( ! f - > inocache )
return - EIO ;
VFS: (Scripted) Convert S_ISLNK/DIR/REG(dentry->d_inode) to d_is_*(dentry)
Convert the following where appropriate:
(1) S_ISLNK(dentry->d_inode) to d_is_symlink(dentry).
(2) S_ISREG(dentry->d_inode) to d_is_reg(dentry).
(3) S_ISDIR(dentry->d_inode) to d_is_dir(dentry). This is actually more
complicated than it appears as some calls should be converted to
d_can_lookup() instead. The difference is whether the directory in
question is a real dir with a ->lookup op or whether it's a fake dir with
a ->d_automount op.
In some circumstances, we can subsume checks for dentry->d_inode not being
NULL into this, provided we the code isn't in a filesystem that expects
d_inode to be NULL if the dirent really *is* negative (ie. if we're going to
use d_inode() rather than d_backing_inode() to get the inode pointer).
Note that the dentry type field may be set to something other than
DCACHE_MISS_TYPE when d_inode is NULL in the case of unionmount, where the VFS
manages the fall-through from a negative dentry to a lower layer. In such a
case, the dentry type of the negative union dentry is set to the same as the
type of the lower dentry.
However, if you know d_inode is not NULL at the call site, then you can use
the d_is_xxx() functions even in a filesystem.
There is one further complication: a 0,0 chardev dentry may be labelled
DCACHE_WHITEOUT_TYPE rather than DCACHE_SPECIAL_TYPE. Strictly, this was
intended for special directory entry types that don't have attached inodes.
The following perl+coccinelle script was used:
use strict;
my @callers;
open($fd, 'git grep -l \'S_IS[A-Z].*->d_inode\' |') ||
die "Can't grep for S_ISDIR and co. callers";
@callers = <$fd>;
close($fd);
unless (@callers) {
print "No matches\n";
exit(0);
}
my @cocci = (
'@@',
'expression E;',
'@@',
'',
'- S_ISLNK(E->d_inode->i_mode)',
'+ d_is_symlink(E)',
'',
'@@',
'expression E;',
'@@',
'',
'- S_ISDIR(E->d_inode->i_mode)',
'+ d_is_dir(E)',
'',
'@@',
'expression E;',
'@@',
'',
'- S_ISREG(E->d_inode->i_mode)',
'+ d_is_reg(E)' );
my $coccifile = "tmp.sp.cocci";
open($fd, ">$coccifile") || die $coccifile;
print($fd "$_\n") || die $coccifile foreach (@cocci);
close($fd);
foreach my $file (@callers) {
chomp $file;
print "Processing ", $file, "\n";
system("spatch", "--sp-file", $coccifile, $file, "--in-place", "--no-show-diff") == 0 ||
die "spatch failed";
}
[AV: overlayfs parts skipped]
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2015-01-29 15:02:35 +03:00
if ( d_is_dir ( old_dentry ) )
2005-04-17 02:20:36 +04:00
return - EPERM ;
/* XXX: This is ugly */
2015-03-18 01:25:59 +03:00
type = ( d_inode ( old_dentry ) - > i_mode & S_IFMT ) > > 12 ;
2005-04-17 02:20:36 +04:00
if ( ! type ) type = DT_REG ;
2005-08-17 17:46:26 +04:00
now = get_seconds ( ) ;
ret = jffs2_do_link ( c , dir_f , f - > inocache - > ino , type , dentry - > d_name . name , dentry - > d_name . len , now ) ;
2005-04-17 02:20:36 +04:00
if ( ! ret ) {
2008-04-22 18:13:40 +04:00
mutex_lock ( & f - > sem ) ;
2015-03-18 01:25:59 +03:00
set_nlink ( d_inode ( old_dentry ) , + + f - > inocache - > pino_nlink ) ;
2008-04-22 18:13:40 +04:00
mutex_unlock ( & f - > sem ) ;
2015-03-18 01:25:59 +03:00
d_instantiate ( dentry , d_inode ( old_dentry ) ) ;
2005-08-17 17:46:26 +04:00
dir_i - > i_mtime = dir_i - > i_ctime = ITIME ( now ) ;
2015-03-18 01:25:59 +03:00
ihold ( d_inode ( old_dentry ) ) ;
2005-04-17 02:20:36 +04:00
}
return ret ;
}
/***********************************************************************/
static int jffs2_symlink ( struct inode * dir_i , struct dentry * dentry , const char * target )
{
struct jffs2_inode_info * f , * dir_f ;
struct jffs2_sb_info * c ;
struct inode * inode ;
struct jffs2_raw_inode * ri ;
struct jffs2_raw_dirent * rd ;
struct jffs2_full_dnode * fn ;
struct jffs2_full_dirent * fd ;
int namelen ;
2006-05-23 03:38:06 +04:00
uint32_t alloclen ;
2005-03-01 13:50:52 +03:00
int ret , targetlen = strlen ( target ) ;
2005-04-17 02:20:36 +04:00
/* FIXME: If you care. We'd need to use frags for the target
if it grows much more than this */
2005-03-01 13:50:52 +03:00
if ( targetlen > 254 )
2008-08-14 12:57:45 +04:00
return - ENAMETOOLONG ;
2005-04-17 02:20:36 +04:00
ri = jffs2_alloc_raw_inode ( ) ;
if ( ! ri )
return - ENOMEM ;
2005-11-07 14:16:07 +03:00
2005-04-17 02:20:36 +04:00
c = JFFS2_SB_INFO ( dir_i - > i_sb ) ;
2005-11-07 14:16:07 +03:00
/* Try to reserve enough space for both node and dirent.
* Just the node will do for now , though
2005-04-17 02:20:36 +04:00
*/
namelen = dentry - > d_name . len ;
2006-05-23 03:38:06 +04:00
ret = jffs2_reserve_space ( c , sizeof ( * ri ) + targetlen , & alloclen ,
ALLOC_NORMAL , JFFS2_SUMMARY_INODE_SIZE ) ;
2005-04-17 02:20:36 +04:00
if ( ret ) {
jffs2_free_raw_inode ( ri ) ;
return ret ;
}
2007-09-14 10:16:35 +04:00
inode = jffs2_new_inode ( dir_i , S_IFLNK | S_IRWXUGO , ri ) ;
2005-04-17 02:20:36 +04:00
if ( IS_ERR ( inode ) ) {
jffs2_free_raw_inode ( ri ) ;
jffs2_complete_reservation ( c ) ;
return PTR_ERR ( inode ) ;
}
inode - > i_op = & jffs2_symlink_inode_operations ;
f = JFFS2_INODE_INFO ( inode ) ;
2005-03-01 13:50:52 +03:00
inode - > i_size = targetlen ;
2005-04-17 02:20:36 +04:00
ri - > isize = ri - > dsize = ri - > csize = cpu_to_je32 ( inode - > i_size ) ;
ri - > totlen = cpu_to_je32 ( sizeof ( * ri ) + inode - > i_size ) ;
ri - > hdr_crc = cpu_to_je32 ( crc32 ( 0 , ri , sizeof ( struct jffs2_unknown_node ) - 4 ) ) ;
ri - > compr = JFFS2_COMPR_NONE ;
2005-03-01 13:50:52 +03:00
ri - > data_crc = cpu_to_je32 ( crc32 ( 0 , target , targetlen ) ) ;
2005-04-17 02:20:36 +04:00
ri - > node_crc = cpu_to_je32 ( crc32 ( 0 , ri , sizeof ( * ri ) - 8 ) ) ;
2005-11-07 14:16:07 +03:00
2006-05-23 03:38:06 +04:00
fn = jffs2_write_dnode ( c , f , ri , target , targetlen , ALLOC_NORMAL ) ;
2005-04-17 02:20:36 +04:00
jffs2_free_raw_inode ( ri ) ;
if ( IS_ERR ( fn ) ) {
/* Eeek. Wave bye bye */
2008-04-22 18:13:40 +04:00
mutex_unlock ( & f - > sem ) ;
2005-04-17 02:20:36 +04:00
jffs2_complete_reservation ( c ) ;
2010-06-03 11:03:39 +04:00
ret = PTR_ERR ( fn ) ;
goto fail ;
2005-04-17 02:20:36 +04:00
}
2005-03-01 13:50:52 +03:00
2005-07-17 15:13:51 +04:00
/* We use f->target field to store the target path. */
2010-10-17 23:56:15 +04:00
f - > target = kmemdup ( target , targetlen + 1 , GFP_KERNEL ) ;
2005-07-17 15:13:51 +04:00
if ( ! f - > target ) {
2012-02-16 03:56:44 +04:00
pr_warn ( " Can't allocate %d bytes of memory \n " , targetlen + 1 ) ;
2008-04-22 18:13:40 +04:00
mutex_unlock ( & f - > sem ) ;
2005-03-01 13:50:52 +03:00
jffs2_complete_reservation ( c ) ;
2010-06-03 11:03:39 +04:00
ret = - ENOMEM ;
goto fail ;
2005-03-01 13:50:52 +03:00
}
2015-05-02 17:21:20 +03:00
inode - > i_link = f - > target ;
2005-03-01 13:50:52 +03:00
2012-02-16 03:56:43 +04:00
jffs2_dbg ( 1 , " %s(): symlink's target '%s' cached \n " ,
__func__ , ( char * ) f - > target ) ;
2005-03-01 13:50:52 +03:00
2005-11-07 14:16:07 +03:00
/* No data here. Only a metadata node, which will be
2005-04-17 02:20:36 +04:00
obsoleted by the first data write
*/
f - > metadata = fn ;
2008-04-22 18:13:40 +04:00
mutex_unlock ( & f - > sem ) ;
2005-04-17 02:20:36 +04:00
jffs2_complete_reservation ( c ) ;
2006-05-13 10:09:47 +04:00
2011-02-01 19:05:39 +03:00
ret = jffs2_init_security ( inode , dir_i , & dentry - > d_name ) ;
2010-06-03 11:03:39 +04:00
if ( ret )
goto fail ;
2007-09-14 10:16:35 +04:00
ret = jffs2_init_acl_post ( inode ) ;
2010-06-03 11:03:39 +04:00
if ( ret )
goto fail ;
2006-05-13 10:09:47 +04:00
2006-05-23 03:38:06 +04:00
ret = jffs2_reserve_space ( c , sizeof ( * rd ) + namelen , & alloclen ,
ALLOC_NORMAL , JFFS2_SUMMARY_DIRENT_SIZE ( namelen ) ) ;
2010-06-03 11:03:39 +04:00
if ( ret )
goto fail ;
2005-04-17 02:20:36 +04:00
rd = jffs2_alloc_raw_dirent ( ) ;
if ( ! rd ) {
/* Argh. Now we treat it like a normal delete */
jffs2_complete_reservation ( c ) ;
2010-06-03 11:03:39 +04:00
ret = - ENOMEM ;
goto fail ;
2005-04-17 02:20:36 +04:00
}
dir_f = JFFS2_INODE_INFO ( dir_i ) ;
2008-04-22 18:13:40 +04:00
mutex_lock ( & dir_f - > sem ) ;
2005-04-17 02:20:36 +04:00
rd - > magic = cpu_to_je16 ( JFFS2_MAGIC_BITMASK ) ;
rd - > nodetype = cpu_to_je16 ( JFFS2_NODETYPE_DIRENT ) ;
rd - > totlen = cpu_to_je32 ( sizeof ( * rd ) + namelen ) ;
rd - > hdr_crc = cpu_to_je32 ( crc32 ( 0 , rd , sizeof ( struct jffs2_unknown_node ) - 4 ) ) ;
rd - > pino = cpu_to_je32 ( dir_i - > i_ino ) ;
rd - > version = cpu_to_je32 ( + + dir_f - > highest_version ) ;
rd - > ino = cpu_to_je32 ( inode - > i_ino ) ;
rd - > mctime = cpu_to_je32 ( get_seconds ( ) ) ;
rd - > nsize = namelen ;
rd - > type = DT_LNK ;
rd - > node_crc = cpu_to_je32 ( crc32 ( 0 , rd , sizeof ( * rd ) - 8 ) ) ;
rd - > name_crc = cpu_to_je32 ( crc32 ( 0 , dentry - > d_name . name , namelen ) ) ;
2006-05-23 03:38:06 +04:00
fd = jffs2_write_dirent ( c , dir_f , rd , dentry - > d_name . name , namelen , ALLOC_NORMAL ) ;
2005-04-17 02:20:36 +04:00
if ( IS_ERR ( fd ) ) {
2005-11-07 14:16:07 +03:00
/* dirent failed to write. Delete the inode normally
2005-04-17 02:20:36 +04:00
as if it were the final unlink ( ) */
jffs2_complete_reservation ( c ) ;
jffs2_free_raw_dirent ( rd ) ;
2008-04-22 18:13:40 +04:00
mutex_unlock ( & dir_f - > sem ) ;
2010-06-03 11:03:39 +04:00
ret = PTR_ERR ( fd ) ;
goto fail ;
2005-04-17 02:20:36 +04:00
}
dir_i - > i_mtime = dir_i - > i_ctime = ITIME ( je32_to_cpu ( rd - > mctime ) ) ;
jffs2_free_raw_dirent ( rd ) ;
/* Link the fd into the inode's list, obsoleting an old
one if necessary . */
jffs2_add_fd_to_list ( c , fd , & dir_f - > dents ) ;
2008-04-22 18:13:40 +04:00
mutex_unlock ( & dir_f - > sem ) ;
2005-04-17 02:20:36 +04:00
jffs2_complete_reservation ( c ) ;
2010-06-03 11:09:12 +04:00
unlock_new_inode ( inode ) ;
2012-07-19 09:18:15 +04:00
d_instantiate ( dentry , inode ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2010-06-03 11:03:39 +04:00
fail :
2010-06-08 21:24:56 +04:00
iget_failed ( inode ) ;
2010-06-03 11:03:39 +04:00
return ret ;
2005-04-17 02:20:36 +04:00
}
2011-07-26 09:41:39 +04:00
static int jffs2_mkdir ( struct inode * dir_i , struct dentry * dentry , umode_t mode )
2005-04-17 02:20:36 +04:00
{
struct jffs2_inode_info * f , * dir_f ;
struct jffs2_sb_info * c ;
struct inode * inode ;
struct jffs2_raw_inode * ri ;
struct jffs2_raw_dirent * rd ;
struct jffs2_full_dnode * fn ;
struct jffs2_full_dirent * fd ;
int namelen ;
2006-05-23 03:38:06 +04:00
uint32_t alloclen ;
2005-04-17 02:20:36 +04:00
int ret ;
mode | = S_IFDIR ;
ri = jffs2_alloc_raw_inode ( ) ;
if ( ! ri )
return - ENOMEM ;
2005-11-07 14:16:07 +03:00
2005-04-17 02:20:36 +04:00
c = JFFS2_SB_INFO ( dir_i - > i_sb ) ;
2005-11-07 14:16:07 +03:00
/* Try to reserve enough space for both node and dirent.
* Just the node will do for now , though
2005-04-17 02:20:36 +04:00
*/
namelen = dentry - > d_name . len ;
2006-05-23 03:38:06 +04:00
ret = jffs2_reserve_space ( c , sizeof ( * ri ) , & alloclen , ALLOC_NORMAL ,
JFFS2_SUMMARY_INODE_SIZE ) ;
2005-04-17 02:20:36 +04:00
if ( ret ) {
jffs2_free_raw_inode ( ri ) ;
return ret ;
}
2007-09-14 10:16:35 +04:00
inode = jffs2_new_inode ( dir_i , mode , ri ) ;
2005-04-17 02:20:36 +04:00
if ( IS_ERR ( inode ) ) {
jffs2_free_raw_inode ( ri ) ;
jffs2_complete_reservation ( c ) ;
return PTR_ERR ( inode ) ;
}
inode - > i_op = & jffs2_dir_inode_operations ;
inode - > i_fop = & jffs2_dir_operations ;
f = JFFS2_INODE_INFO ( inode ) ;
2008-05-01 21:47:17 +04:00
/* Directories get nlink 2 at start */
2011-10-28 16:13:29 +04:00
set_nlink ( inode , 2 ) ;
2008-05-01 21:47:17 +04:00
/* but ic->pino_nlink is the parent ino# */
f - > inocache - > pino_nlink = dir_i - > i_ino ;
2005-04-17 02:20:36 +04:00
ri - > data_crc = cpu_to_je32 ( 0 ) ;
ri - > node_crc = cpu_to_je32 ( crc32 ( 0 , ri , sizeof ( * ri ) - 8 ) ) ;
2005-11-07 14:16:07 +03:00
2006-05-23 03:38:06 +04:00
fn = jffs2_write_dnode ( c , f , ri , NULL , 0 , ALLOC_NORMAL ) ;
2005-04-17 02:20:36 +04:00
jffs2_free_raw_inode ( ri ) ;
if ( IS_ERR ( fn ) ) {
/* Eeek. Wave bye bye */
2008-04-22 18:13:40 +04:00
mutex_unlock ( & f - > sem ) ;
2005-04-17 02:20:36 +04:00
jffs2_complete_reservation ( c ) ;
2010-06-03 11:03:39 +04:00
ret = PTR_ERR ( fn ) ;
goto fail ;
2005-04-17 02:20:36 +04:00
}
2005-11-07 14:16:07 +03:00
/* No data here. Only a metadata node, which will be
2005-04-17 02:20:36 +04:00
obsoleted by the first data write
*/
f - > metadata = fn ;
2008-04-22 18:13:40 +04:00
mutex_unlock ( & f - > sem ) ;
2005-04-17 02:20:36 +04:00
jffs2_complete_reservation ( c ) ;
2006-05-13 10:09:47 +04:00
2011-02-01 19:05:39 +03:00
ret = jffs2_init_security ( inode , dir_i , & dentry - > d_name ) ;
2010-06-03 11:03:39 +04:00
if ( ret )
goto fail ;
2007-09-14 10:16:35 +04:00
ret = jffs2_init_acl_post ( inode ) ;
2010-06-03 11:03:39 +04:00
if ( ret )
goto fail ;
2006-05-13 10:09:47 +04:00
2006-05-23 03:38:06 +04:00
ret = jffs2_reserve_space ( c , sizeof ( * rd ) + namelen , & alloclen ,
ALLOC_NORMAL , JFFS2_SUMMARY_DIRENT_SIZE ( namelen ) ) ;
2010-06-03 11:03:39 +04:00
if ( ret )
goto fail ;
2005-11-07 14:16:07 +03:00
2005-04-17 02:20:36 +04:00
rd = jffs2_alloc_raw_dirent ( ) ;
if ( ! rd ) {
/* Argh. Now we treat it like a normal delete */
jffs2_complete_reservation ( c ) ;
2010-06-03 11:03:39 +04:00
ret = - ENOMEM ;
goto fail ;
2005-04-17 02:20:36 +04:00
}
dir_f = JFFS2_INODE_INFO ( dir_i ) ;
2008-04-22 18:13:40 +04:00
mutex_lock ( & dir_f - > sem ) ;
2005-04-17 02:20:36 +04:00
rd - > magic = cpu_to_je16 ( JFFS2_MAGIC_BITMASK ) ;
rd - > nodetype = cpu_to_je16 ( JFFS2_NODETYPE_DIRENT ) ;
rd - > totlen = cpu_to_je32 ( sizeof ( * rd ) + namelen ) ;
rd - > hdr_crc = cpu_to_je32 ( crc32 ( 0 , rd , sizeof ( struct jffs2_unknown_node ) - 4 ) ) ;
rd - > pino = cpu_to_je32 ( dir_i - > i_ino ) ;
rd - > version = cpu_to_je32 ( + + dir_f - > highest_version ) ;
rd - > ino = cpu_to_je32 ( inode - > i_ino ) ;
rd - > mctime = cpu_to_je32 ( get_seconds ( ) ) ;
rd - > nsize = namelen ;
rd - > type = DT_DIR ;
rd - > node_crc = cpu_to_je32 ( crc32 ( 0 , rd , sizeof ( * rd ) - 8 ) ) ;
rd - > name_crc = cpu_to_je32 ( crc32 ( 0 , dentry - > d_name . name , namelen ) ) ;
2006-05-23 03:38:06 +04:00
fd = jffs2_write_dirent ( c , dir_f , rd , dentry - > d_name . name , namelen , ALLOC_NORMAL ) ;
2005-11-07 14:16:07 +03:00
2005-04-17 02:20:36 +04:00
if ( IS_ERR ( fd ) ) {
2005-11-07 14:16:07 +03:00
/* dirent failed to write. Delete the inode normally
2005-04-17 02:20:36 +04:00
as if it were the final unlink ( ) */
jffs2_complete_reservation ( c ) ;
jffs2_free_raw_dirent ( rd ) ;
2008-04-22 18:13:40 +04:00
mutex_unlock ( & dir_f - > sem ) ;
2010-06-03 11:03:39 +04:00
ret = PTR_ERR ( fd ) ;
goto fail ;
2005-04-17 02:20:36 +04:00
}
dir_i - > i_mtime = dir_i - > i_ctime = ITIME ( je32_to_cpu ( rd - > mctime ) ) ;
2006-10-01 10:29:04 +04:00
inc_nlink ( dir_i ) ;
2005-04-17 02:20:36 +04:00
jffs2_free_raw_dirent ( rd ) ;
/* Link the fd into the inode's list, obsoleting an old
one if necessary . */
jffs2_add_fd_to_list ( c , fd , & dir_f - > dents ) ;
2008-04-22 18:13:40 +04:00
mutex_unlock ( & dir_f - > sem ) ;
2005-04-17 02:20:36 +04:00
jffs2_complete_reservation ( c ) ;
2010-06-03 11:09:12 +04:00
unlock_new_inode ( inode ) ;
2012-07-19 09:18:15 +04:00
d_instantiate ( dentry , inode ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2010-06-03 11:03:39 +04:00
fail :
2010-06-08 21:24:56 +04:00
iget_failed ( inode ) ;
2010-06-03 11:03:39 +04:00
return ret ;
2005-04-17 02:20:36 +04:00
}
static int jffs2_rmdir ( struct inode * dir_i , struct dentry * dentry )
{
2008-05-01 21:47:17 +04:00
struct jffs2_sb_info * c = JFFS2_SB_INFO ( dir_i - > i_sb ) ;
struct jffs2_inode_info * dir_f = JFFS2_INODE_INFO ( dir_i ) ;
2015-03-18 01:25:59 +03:00
struct jffs2_inode_info * f = JFFS2_INODE_INFO ( d_inode ( dentry ) ) ;
2005-04-17 02:20:36 +04:00
struct jffs2_full_dirent * fd ;
int ret ;
2008-05-01 21:47:17 +04:00
uint32_t now = get_seconds ( ) ;
2005-04-17 02:20:36 +04:00
for ( fd = f - > dents ; fd ; fd = fd - > next ) {
if ( fd - > ino )
return - ENOTEMPTY ;
}
2008-05-01 21:47:17 +04:00
ret = jffs2_do_unlink ( c , dir_f , dentry - > d_name . name ,
dentry - > d_name . len , f , now ) ;
if ( ! ret ) {
dir_i - > i_mtime = dir_i - > i_ctime = ITIME ( now ) ;
2015-03-18 01:25:59 +03:00
clear_nlink ( d_inode ( dentry ) ) ;
2006-10-01 10:29:03 +04:00
drop_nlink ( dir_i ) ;
2008-05-01 21:47:17 +04:00
}
2005-04-17 02:20:36 +04:00
return ret ;
}
2011-07-26 09:52:52 +04:00
static int jffs2_mknod ( struct inode * dir_i , struct dentry * dentry , umode_t mode , dev_t rdev )
2005-04-17 02:20:36 +04:00
{
struct jffs2_inode_info * f , * dir_f ;
struct jffs2_sb_info * c ;
struct inode * inode ;
struct jffs2_raw_inode * ri ;
struct jffs2_raw_dirent * rd ;
struct jffs2_full_dnode * fn ;
struct jffs2_full_dirent * fd ;
int namelen ;
2006-05-19 03:28:49 +04:00
union jffs2_device_node dev ;
2005-04-17 02:20:36 +04:00
int devlen = 0 ;
2006-05-23 03:38:06 +04:00
uint32_t alloclen ;
2005-04-17 02:20:36 +04:00
int ret ;
ri = jffs2_alloc_raw_inode ( ) ;
if ( ! ri )
return - ENOMEM ;
2005-11-07 14:16:07 +03:00
2005-04-17 02:20:36 +04:00
c = JFFS2_SB_INFO ( dir_i - > i_sb ) ;
2005-11-07 14:16:07 +03:00
2006-05-19 03:28:49 +04:00
if ( S_ISBLK ( mode ) | | S_ISCHR ( mode ) )
devlen = jffs2_encode_dev ( & dev , rdev ) ;
2005-11-07 14:16:07 +03:00
/* Try to reserve enough space for both node and dirent.
* Just the node will do for now , though
2005-04-17 02:20:36 +04:00
*/
namelen = dentry - > d_name . len ;
2006-05-23 03:38:06 +04:00
ret = jffs2_reserve_space ( c , sizeof ( * ri ) + devlen , & alloclen ,
2006-05-19 03:28:49 +04:00
ALLOC_NORMAL , JFFS2_SUMMARY_INODE_SIZE ) ;
2005-04-17 02:20:36 +04:00
if ( ret ) {
jffs2_free_raw_inode ( ri ) ;
return ret ;
}
2007-09-14 10:16:35 +04:00
inode = jffs2_new_inode ( dir_i , mode , ri ) ;
2005-04-17 02:20:36 +04:00
if ( IS_ERR ( inode ) ) {
jffs2_free_raw_inode ( ri ) ;
jffs2_complete_reservation ( c ) ;
return PTR_ERR ( inode ) ;
}
inode - > i_op = & jffs2_file_inode_operations ;
init_special_inode ( inode , inode - > i_mode , rdev ) ;
f = JFFS2_INODE_INFO ( inode ) ;
ri - > dsize = ri - > csize = cpu_to_je32 ( devlen ) ;
ri - > totlen = cpu_to_je32 ( sizeof ( * ri ) + devlen ) ;
ri - > hdr_crc = cpu_to_je32 ( crc32 ( 0 , ri , sizeof ( struct jffs2_unknown_node ) - 4 ) ) ;
ri - > compr = JFFS2_COMPR_NONE ;
ri - > data_crc = cpu_to_je32 ( crc32 ( 0 , & dev , devlen ) ) ;
ri - > node_crc = cpu_to_je32 ( crc32 ( 0 , ri , sizeof ( * ri ) - 8 ) ) ;
2005-11-07 14:16:07 +03:00
2006-05-23 03:38:06 +04:00
fn = jffs2_write_dnode ( c , f , ri , ( char * ) & dev , devlen , ALLOC_NORMAL ) ;
2005-04-17 02:20:36 +04:00
jffs2_free_raw_inode ( ri ) ;
if ( IS_ERR ( fn ) ) {
/* Eeek. Wave bye bye */
2008-04-22 18:13:40 +04:00
mutex_unlock ( & f - > sem ) ;
2005-04-17 02:20:36 +04:00
jffs2_complete_reservation ( c ) ;
2010-06-03 11:03:39 +04:00
ret = PTR_ERR ( fn ) ;
goto fail ;
2005-04-17 02:20:36 +04:00
}
2005-11-07 14:16:07 +03:00
/* No data here. Only a metadata node, which will be
2005-04-17 02:20:36 +04:00
obsoleted by the first data write
*/
f - > metadata = fn ;
2008-04-22 18:13:40 +04:00
mutex_unlock ( & f - > sem ) ;
2005-04-17 02:20:36 +04:00
jffs2_complete_reservation ( c ) ;
2006-05-13 10:09:47 +04:00
2011-02-01 19:05:39 +03:00
ret = jffs2_init_security ( inode , dir_i , & dentry - > d_name ) ;
2010-06-03 11:03:39 +04:00
if ( ret )
goto fail ;
2007-09-14 10:16:35 +04:00
ret = jffs2_init_acl_post ( inode ) ;
2010-06-03 11:03:39 +04:00
if ( ret )
goto fail ;
2006-05-13 10:09:47 +04:00
2006-05-23 03:38:06 +04:00
ret = jffs2_reserve_space ( c , sizeof ( * rd ) + namelen , & alloclen ,
ALLOC_NORMAL , JFFS2_SUMMARY_DIRENT_SIZE ( namelen ) ) ;
2010-06-03 11:03:39 +04:00
if ( ret )
goto fail ;
2005-04-17 02:20:36 +04:00
rd = jffs2_alloc_raw_dirent ( ) ;
if ( ! rd ) {
/* Argh. Now we treat it like a normal delete */
jffs2_complete_reservation ( c ) ;
2010-06-03 11:03:39 +04:00
ret = - ENOMEM ;
goto fail ;
2005-04-17 02:20:36 +04:00
}
dir_f = JFFS2_INODE_INFO ( dir_i ) ;
2008-04-22 18:13:40 +04:00
mutex_lock ( & dir_f - > sem ) ;
2005-04-17 02:20:36 +04:00
rd - > magic = cpu_to_je16 ( JFFS2_MAGIC_BITMASK ) ;
rd - > nodetype = cpu_to_je16 ( JFFS2_NODETYPE_DIRENT ) ;
rd - > totlen = cpu_to_je32 ( sizeof ( * rd ) + namelen ) ;
rd - > hdr_crc = cpu_to_je32 ( crc32 ( 0 , rd , sizeof ( struct jffs2_unknown_node ) - 4 ) ) ;
rd - > pino = cpu_to_je32 ( dir_i - > i_ino ) ;
rd - > version = cpu_to_je32 ( + + dir_f - > highest_version ) ;
rd - > ino = cpu_to_je32 ( inode - > i_ino ) ;
rd - > mctime = cpu_to_je32 ( get_seconds ( ) ) ;
rd - > nsize = namelen ;
/* XXX: This is ugly. */
rd - > type = ( mode & S_IFMT ) > > 12 ;
rd - > node_crc = cpu_to_je32 ( crc32 ( 0 , rd , sizeof ( * rd ) - 8 ) ) ;
rd - > name_crc = cpu_to_je32 ( crc32 ( 0 , dentry - > d_name . name , namelen ) ) ;
2006-05-23 03:38:06 +04:00
fd = jffs2_write_dirent ( c , dir_f , rd , dentry - > d_name . name , namelen , ALLOC_NORMAL ) ;
2005-11-07 14:16:07 +03:00
2005-04-17 02:20:36 +04:00
if ( IS_ERR ( fd ) ) {
2005-11-07 14:16:07 +03:00
/* dirent failed to write. Delete the inode normally
2005-04-17 02:20:36 +04:00
as if it were the final unlink ( ) */
jffs2_complete_reservation ( c ) ;
jffs2_free_raw_dirent ( rd ) ;
2008-04-22 18:13:40 +04:00
mutex_unlock ( & dir_f - > sem ) ;
2010-06-03 11:03:39 +04:00
ret = PTR_ERR ( fd ) ;
goto fail ;
2005-04-17 02:20:36 +04:00
}
dir_i - > i_mtime = dir_i - > i_ctime = ITIME ( je32_to_cpu ( rd - > mctime ) ) ;
jffs2_free_raw_dirent ( rd ) ;
/* Link the fd into the inode's list, obsoleting an old
one if necessary . */
jffs2_add_fd_to_list ( c , fd , & dir_f - > dents ) ;
2008-04-22 18:13:40 +04:00
mutex_unlock ( & dir_f - > sem ) ;
2005-04-17 02:20:36 +04:00
jffs2_complete_reservation ( c ) ;
2010-06-03 11:09:12 +04:00
unlock_new_inode ( inode ) ;
2012-07-19 09:18:15 +04:00
d_instantiate ( dentry , inode ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2010-06-03 11:03:39 +04:00
fail :
2010-06-08 21:24:56 +04:00
iget_failed ( inode ) ;
2010-06-03 11:03:39 +04:00
return ret ;
2005-04-17 02:20:36 +04:00
}
static int jffs2_rename ( struct inode * old_dir_i , struct dentry * old_dentry ,
2007-07-10 13:01:22 +04:00
struct inode * new_dir_i , struct dentry * new_dentry )
2005-04-17 02:20:36 +04:00
{
int ret ;
struct jffs2_sb_info * c = JFFS2_SB_INFO ( old_dir_i - > i_sb ) ;
struct jffs2_inode_info * victim_f = NULL ;
uint8_t type ;
2005-08-17 17:46:26 +04:00
uint32_t now ;
2005-04-17 02:20:36 +04:00
2005-11-07 14:16:07 +03:00
/* The VFS will check for us and prevent trying to rename a
2005-04-17 02:20:36 +04:00
* file over a directory and vice versa , but if it ' s a directory ,
* the VFS can ' t check whether the victim is empty . The filesystem
* needs to do that for itself .
*/
2015-03-18 01:25:59 +03:00
if ( d_really_is_positive ( new_dentry ) ) {
victim_f = JFFS2_INODE_INFO ( d_inode ( new_dentry ) ) ;
VFS: (Scripted) Convert S_ISLNK/DIR/REG(dentry->d_inode) to d_is_*(dentry)
Convert the following where appropriate:
(1) S_ISLNK(dentry->d_inode) to d_is_symlink(dentry).
(2) S_ISREG(dentry->d_inode) to d_is_reg(dentry).
(3) S_ISDIR(dentry->d_inode) to d_is_dir(dentry). This is actually more
complicated than it appears as some calls should be converted to
d_can_lookup() instead. The difference is whether the directory in
question is a real dir with a ->lookup op or whether it's a fake dir with
a ->d_automount op.
In some circumstances, we can subsume checks for dentry->d_inode not being
NULL into this, provided we the code isn't in a filesystem that expects
d_inode to be NULL if the dirent really *is* negative (ie. if we're going to
use d_inode() rather than d_backing_inode() to get the inode pointer).
Note that the dentry type field may be set to something other than
DCACHE_MISS_TYPE when d_inode is NULL in the case of unionmount, where the VFS
manages the fall-through from a negative dentry to a lower layer. In such a
case, the dentry type of the negative union dentry is set to the same as the
type of the lower dentry.
However, if you know d_inode is not NULL at the call site, then you can use
the d_is_xxx() functions even in a filesystem.
There is one further complication: a 0,0 chardev dentry may be labelled
DCACHE_WHITEOUT_TYPE rather than DCACHE_SPECIAL_TYPE. Strictly, this was
intended for special directory entry types that don't have attached inodes.
The following perl+coccinelle script was used:
use strict;
my @callers;
open($fd, 'git grep -l \'S_IS[A-Z].*->d_inode\' |') ||
die "Can't grep for S_ISDIR and co. callers";
@callers = <$fd>;
close($fd);
unless (@callers) {
print "No matches\n";
exit(0);
}
my @cocci = (
'@@',
'expression E;',
'@@',
'',
'- S_ISLNK(E->d_inode->i_mode)',
'+ d_is_symlink(E)',
'',
'@@',
'expression E;',
'@@',
'',
'- S_ISDIR(E->d_inode->i_mode)',
'+ d_is_dir(E)',
'',
'@@',
'expression E;',
'@@',
'',
'- S_ISREG(E->d_inode->i_mode)',
'+ d_is_reg(E)' );
my $coccifile = "tmp.sp.cocci";
open($fd, ">$coccifile") || die $coccifile;
print($fd "$_\n") || die $coccifile foreach (@cocci);
close($fd);
foreach my $file (@callers) {
chomp $file;
print "Processing ", $file, "\n";
system("spatch", "--sp-file", $coccifile, $file, "--in-place", "--no-show-diff") == 0 ||
die "spatch failed";
}
[AV: overlayfs parts skipped]
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2015-01-29 15:02:35 +03:00
if ( d_is_dir ( new_dentry ) ) {
2005-04-17 02:20:36 +04:00
struct jffs2_full_dirent * fd ;
2008-04-22 18:13:40 +04:00
mutex_lock ( & victim_f - > sem ) ;
2005-04-17 02:20:36 +04:00
for ( fd = victim_f - > dents ; fd ; fd = fd - > next ) {
if ( fd - > ino ) {
2008-04-22 18:13:40 +04:00
mutex_unlock ( & victim_f - > sem ) ;
2005-04-17 02:20:36 +04:00
return - ENOTEMPTY ;
}
}
2008-04-22 18:13:40 +04:00
mutex_unlock ( & victim_f - > sem ) ;
2005-04-17 02:20:36 +04:00
}
}
/* XXX: We probably ought to alloc enough space for
2005-11-07 14:16:07 +03:00
both nodes at the same time . Writing the new link ,
2005-04-17 02:20:36 +04:00
then getting - ENOSPC , is quite bad : )
*/
/* Make a hard link */
2005-11-07 14:16:07 +03:00
2005-04-17 02:20:36 +04:00
/* XXX: This is ugly */
2015-03-18 01:25:59 +03:00
type = ( d_inode ( old_dentry ) - > i_mode & S_IFMT ) > > 12 ;
2005-04-17 02:20:36 +04:00
if ( ! type ) type = DT_REG ;
2005-08-17 17:46:26 +04:00
now = get_seconds ( ) ;
2005-11-07 14:16:07 +03:00
ret = jffs2_do_link ( c , JFFS2_INODE_INFO ( new_dir_i ) ,
2015-03-18 01:25:59 +03:00
d_inode ( old_dentry ) - > i_ino , type ,
2005-08-17 17:46:26 +04:00
new_dentry - > d_name . name , new_dentry - > d_name . len , now ) ;
2005-04-17 02:20:36 +04:00
if ( ret )
return ret ;
if ( victim_f ) {
/* There was a victim. Kill it off nicely */
VFS: (Scripted) Convert S_ISLNK/DIR/REG(dentry->d_inode) to d_is_*(dentry)
Convert the following where appropriate:
(1) S_ISLNK(dentry->d_inode) to d_is_symlink(dentry).
(2) S_ISREG(dentry->d_inode) to d_is_reg(dentry).
(3) S_ISDIR(dentry->d_inode) to d_is_dir(dentry). This is actually more
complicated than it appears as some calls should be converted to
d_can_lookup() instead. The difference is whether the directory in
question is a real dir with a ->lookup op or whether it's a fake dir with
a ->d_automount op.
In some circumstances, we can subsume checks for dentry->d_inode not being
NULL into this, provided we the code isn't in a filesystem that expects
d_inode to be NULL if the dirent really *is* negative (ie. if we're going to
use d_inode() rather than d_backing_inode() to get the inode pointer).
Note that the dentry type field may be set to something other than
DCACHE_MISS_TYPE when d_inode is NULL in the case of unionmount, where the VFS
manages the fall-through from a negative dentry to a lower layer. In such a
case, the dentry type of the negative union dentry is set to the same as the
type of the lower dentry.
However, if you know d_inode is not NULL at the call site, then you can use
the d_is_xxx() functions even in a filesystem.
There is one further complication: a 0,0 chardev dentry may be labelled
DCACHE_WHITEOUT_TYPE rather than DCACHE_SPECIAL_TYPE. Strictly, this was
intended for special directory entry types that don't have attached inodes.
The following perl+coccinelle script was used:
use strict;
my @callers;
open($fd, 'git grep -l \'S_IS[A-Z].*->d_inode\' |') ||
die "Can't grep for S_ISDIR and co. callers";
@callers = <$fd>;
close($fd);
unless (@callers) {
print "No matches\n";
exit(0);
}
my @cocci = (
'@@',
'expression E;',
'@@',
'',
'- S_ISLNK(E->d_inode->i_mode)',
'+ d_is_symlink(E)',
'',
'@@',
'expression E;',
'@@',
'',
'- S_ISDIR(E->d_inode->i_mode)',
'+ d_is_dir(E)',
'',
'@@',
'expression E;',
'@@',
'',
'- S_ISREG(E->d_inode->i_mode)',
'+ d_is_reg(E)' );
my $coccifile = "tmp.sp.cocci";
open($fd, ">$coccifile") || die $coccifile;
print($fd "$_\n") || die $coccifile foreach (@cocci);
close($fd);
foreach my $file (@callers) {
chomp $file;
print "Processing ", $file, "\n";
system("spatch", "--sp-file", $coccifile, $file, "--in-place", "--no-show-diff") == 0 ||
die "spatch failed";
}
[AV: overlayfs parts skipped]
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2015-01-29 15:02:35 +03:00
if ( d_is_dir ( new_dentry ) )
2015-03-18 01:25:59 +03:00
clear_nlink ( d_inode ( new_dentry ) ) ;
2011-07-21 23:57:47 +04:00
else
2015-03-18 01:25:59 +03:00
drop_nlink ( d_inode ( new_dentry ) ) ;
2005-04-17 02:20:36 +04:00
/* Don't oops if the victim was a dirent pointing to an
inode which didn ' t exist . */
if ( victim_f - > inocache ) {
2008-04-22 18:13:40 +04:00
mutex_lock ( & victim_f - > sem ) ;
VFS: (Scripted) Convert S_ISLNK/DIR/REG(dentry->d_inode) to d_is_*(dentry)
Convert the following where appropriate:
(1) S_ISLNK(dentry->d_inode) to d_is_symlink(dentry).
(2) S_ISREG(dentry->d_inode) to d_is_reg(dentry).
(3) S_ISDIR(dentry->d_inode) to d_is_dir(dentry). This is actually more
complicated than it appears as some calls should be converted to
d_can_lookup() instead. The difference is whether the directory in
question is a real dir with a ->lookup op or whether it's a fake dir with
a ->d_automount op.
In some circumstances, we can subsume checks for dentry->d_inode not being
NULL into this, provided we the code isn't in a filesystem that expects
d_inode to be NULL if the dirent really *is* negative (ie. if we're going to
use d_inode() rather than d_backing_inode() to get the inode pointer).
Note that the dentry type field may be set to something other than
DCACHE_MISS_TYPE when d_inode is NULL in the case of unionmount, where the VFS
manages the fall-through from a negative dentry to a lower layer. In such a
case, the dentry type of the negative union dentry is set to the same as the
type of the lower dentry.
However, if you know d_inode is not NULL at the call site, then you can use
the d_is_xxx() functions even in a filesystem.
There is one further complication: a 0,0 chardev dentry may be labelled
DCACHE_WHITEOUT_TYPE rather than DCACHE_SPECIAL_TYPE. Strictly, this was
intended for special directory entry types that don't have attached inodes.
The following perl+coccinelle script was used:
use strict;
my @callers;
open($fd, 'git grep -l \'S_IS[A-Z].*->d_inode\' |') ||
die "Can't grep for S_ISDIR and co. callers";
@callers = <$fd>;
close($fd);
unless (@callers) {
print "No matches\n";
exit(0);
}
my @cocci = (
'@@',
'expression E;',
'@@',
'',
'- S_ISLNK(E->d_inode->i_mode)',
'+ d_is_symlink(E)',
'',
'@@',
'expression E;',
'@@',
'',
'- S_ISDIR(E->d_inode->i_mode)',
'+ d_is_dir(E)',
'',
'@@',
'expression E;',
'@@',
'',
'- S_ISREG(E->d_inode->i_mode)',
'+ d_is_reg(E)' );
my $coccifile = "tmp.sp.cocci";
open($fd, ">$coccifile") || die $coccifile;
print($fd "$_\n") || die $coccifile foreach (@cocci);
close($fd);
foreach my $file (@callers) {
chomp $file;
print "Processing ", $file, "\n";
system("spatch", "--sp-file", $coccifile, $file, "--in-place", "--no-show-diff") == 0 ||
die "spatch failed";
}
[AV: overlayfs parts skipped]
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2015-01-29 15:02:35 +03:00
if ( d_is_dir ( new_dentry ) )
2008-05-01 21:47:17 +04:00
victim_f - > inocache - > pino_nlink = 0 ;
else
victim_f - > inocache - > pino_nlink - - ;
2008-04-22 18:13:40 +04:00
mutex_unlock ( & victim_f - > sem ) ;
2005-04-17 02:20:36 +04:00
}
}
2005-11-07 14:16:07 +03:00
/* If it was a directory we moved, and there was no victim,
2005-04-17 02:20:36 +04:00
increase i_nlink on its new parent */
VFS: (Scripted) Convert S_ISLNK/DIR/REG(dentry->d_inode) to d_is_*(dentry)
Convert the following where appropriate:
(1) S_ISLNK(dentry->d_inode) to d_is_symlink(dentry).
(2) S_ISREG(dentry->d_inode) to d_is_reg(dentry).
(3) S_ISDIR(dentry->d_inode) to d_is_dir(dentry). This is actually more
complicated than it appears as some calls should be converted to
d_can_lookup() instead. The difference is whether the directory in
question is a real dir with a ->lookup op or whether it's a fake dir with
a ->d_automount op.
In some circumstances, we can subsume checks for dentry->d_inode not being
NULL into this, provided we the code isn't in a filesystem that expects
d_inode to be NULL if the dirent really *is* negative (ie. if we're going to
use d_inode() rather than d_backing_inode() to get the inode pointer).
Note that the dentry type field may be set to something other than
DCACHE_MISS_TYPE when d_inode is NULL in the case of unionmount, where the VFS
manages the fall-through from a negative dentry to a lower layer. In such a
case, the dentry type of the negative union dentry is set to the same as the
type of the lower dentry.
However, if you know d_inode is not NULL at the call site, then you can use
the d_is_xxx() functions even in a filesystem.
There is one further complication: a 0,0 chardev dentry may be labelled
DCACHE_WHITEOUT_TYPE rather than DCACHE_SPECIAL_TYPE. Strictly, this was
intended for special directory entry types that don't have attached inodes.
The following perl+coccinelle script was used:
use strict;
my @callers;
open($fd, 'git grep -l \'S_IS[A-Z].*->d_inode\' |') ||
die "Can't grep for S_ISDIR and co. callers";
@callers = <$fd>;
close($fd);
unless (@callers) {
print "No matches\n";
exit(0);
}
my @cocci = (
'@@',
'expression E;',
'@@',
'',
'- S_ISLNK(E->d_inode->i_mode)',
'+ d_is_symlink(E)',
'',
'@@',
'expression E;',
'@@',
'',
'- S_ISDIR(E->d_inode->i_mode)',
'+ d_is_dir(E)',
'',
'@@',
'expression E;',
'@@',
'',
'- S_ISREG(E->d_inode->i_mode)',
'+ d_is_reg(E)' );
my $coccifile = "tmp.sp.cocci";
open($fd, ">$coccifile") || die $coccifile;
print($fd "$_\n") || die $coccifile foreach (@cocci);
close($fd);
foreach my $file (@callers) {
chomp $file;
print "Processing ", $file, "\n";
system("spatch", "--sp-file", $coccifile, $file, "--in-place", "--no-show-diff") == 0 ||
die "spatch failed";
}
[AV: overlayfs parts skipped]
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2015-01-29 15:02:35 +03:00
if ( d_is_dir ( old_dentry ) & & ! victim_f )
2006-10-01 10:29:04 +04:00
inc_nlink ( new_dir_i ) ;
2005-04-17 02:20:36 +04:00
/* Unlink the original */
2005-11-07 14:16:07 +03:00
ret = jffs2_do_unlink ( c , JFFS2_INODE_INFO ( old_dir_i ) ,
2005-08-17 17:46:26 +04:00
old_dentry - > d_name . name , old_dentry - > d_name . len , NULL , now ) ;
2005-04-17 02:20:36 +04:00
/* We don't touch inode->i_nlink */
if ( ret ) {
/* Oh shit. We really ought to make a single node which can do both atomically */
2015-03-18 01:25:59 +03:00
struct jffs2_inode_info * f = JFFS2_INODE_INFO ( d_inode ( old_dentry ) ) ;
2008-04-22 18:13:40 +04:00
mutex_lock ( & f - > sem ) ;
2015-03-18 01:25:59 +03:00
inc_nlink ( d_inode ( old_dentry ) ) ;
VFS: (Scripted) Convert S_ISLNK/DIR/REG(dentry->d_inode) to d_is_*(dentry)
Convert the following where appropriate:
(1) S_ISLNK(dentry->d_inode) to d_is_symlink(dentry).
(2) S_ISREG(dentry->d_inode) to d_is_reg(dentry).
(3) S_ISDIR(dentry->d_inode) to d_is_dir(dentry). This is actually more
complicated than it appears as some calls should be converted to
d_can_lookup() instead. The difference is whether the directory in
question is a real dir with a ->lookup op or whether it's a fake dir with
a ->d_automount op.
In some circumstances, we can subsume checks for dentry->d_inode not being
NULL into this, provided we the code isn't in a filesystem that expects
d_inode to be NULL if the dirent really *is* negative (ie. if we're going to
use d_inode() rather than d_backing_inode() to get the inode pointer).
Note that the dentry type field may be set to something other than
DCACHE_MISS_TYPE when d_inode is NULL in the case of unionmount, where the VFS
manages the fall-through from a negative dentry to a lower layer. In such a
case, the dentry type of the negative union dentry is set to the same as the
type of the lower dentry.
However, if you know d_inode is not NULL at the call site, then you can use
the d_is_xxx() functions even in a filesystem.
There is one further complication: a 0,0 chardev dentry may be labelled
DCACHE_WHITEOUT_TYPE rather than DCACHE_SPECIAL_TYPE. Strictly, this was
intended for special directory entry types that don't have attached inodes.
The following perl+coccinelle script was used:
use strict;
my @callers;
open($fd, 'git grep -l \'S_IS[A-Z].*->d_inode\' |') ||
die "Can't grep for S_ISDIR and co. callers";
@callers = <$fd>;
close($fd);
unless (@callers) {
print "No matches\n";
exit(0);
}
my @cocci = (
'@@',
'expression E;',
'@@',
'',
'- S_ISLNK(E->d_inode->i_mode)',
'+ d_is_symlink(E)',
'',
'@@',
'expression E;',
'@@',
'',
'- S_ISDIR(E->d_inode->i_mode)',
'+ d_is_dir(E)',
'',
'@@',
'expression E;',
'@@',
'',
'- S_ISREG(E->d_inode->i_mode)',
'+ d_is_reg(E)' );
my $coccifile = "tmp.sp.cocci";
open($fd, ">$coccifile") || die $coccifile;
print($fd "$_\n") || die $coccifile foreach (@cocci);
close($fd);
foreach my $file (@callers) {
chomp $file;
print "Processing ", $file, "\n";
system("spatch", "--sp-file", $coccifile, $file, "--in-place", "--no-show-diff") == 0 ||
die "spatch failed";
}
[AV: overlayfs parts skipped]
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2015-01-29 15:02:35 +03:00
if ( f - > inocache & & ! d_is_dir ( old_dentry ) )
2008-05-01 21:47:17 +04:00
f - > inocache - > pino_nlink + + ;
2008-04-22 18:13:40 +04:00
mutex_unlock ( & f - > sem ) ;
2005-04-17 02:20:36 +04:00
2012-02-16 03:56:44 +04:00
pr_notice ( " %s(): Link succeeded, unlink failed (err %d). You now have a hard link \n " ,
__func__ , ret ) ;
2016-03-08 07:07:10 +03:00
/*
* We can ' t keep the target in dcache after that .
* For one thing , we can ' t afford dentry aliases for directories .
* For another , if there was a victim , we _can ' t_ set new inode
* for that sucker and we have to trigger mount eviction - the
* caller won ' t do it on its own since we are returning an error .
*/
d_invalidate ( new_dentry ) ;
2005-08-17 17:46:26 +04:00
new_dir_i - > i_mtime = new_dir_i - > i_ctime = ITIME ( now ) ;
2005-04-17 02:20:36 +04:00
return ret ;
}
VFS: (Scripted) Convert S_ISLNK/DIR/REG(dentry->d_inode) to d_is_*(dentry)
Convert the following where appropriate:
(1) S_ISLNK(dentry->d_inode) to d_is_symlink(dentry).
(2) S_ISREG(dentry->d_inode) to d_is_reg(dentry).
(3) S_ISDIR(dentry->d_inode) to d_is_dir(dentry). This is actually more
complicated than it appears as some calls should be converted to
d_can_lookup() instead. The difference is whether the directory in
question is a real dir with a ->lookup op or whether it's a fake dir with
a ->d_automount op.
In some circumstances, we can subsume checks for dentry->d_inode not being
NULL into this, provided we the code isn't in a filesystem that expects
d_inode to be NULL if the dirent really *is* negative (ie. if we're going to
use d_inode() rather than d_backing_inode() to get the inode pointer).
Note that the dentry type field may be set to something other than
DCACHE_MISS_TYPE when d_inode is NULL in the case of unionmount, where the VFS
manages the fall-through from a negative dentry to a lower layer. In such a
case, the dentry type of the negative union dentry is set to the same as the
type of the lower dentry.
However, if you know d_inode is not NULL at the call site, then you can use
the d_is_xxx() functions even in a filesystem.
There is one further complication: a 0,0 chardev dentry may be labelled
DCACHE_WHITEOUT_TYPE rather than DCACHE_SPECIAL_TYPE. Strictly, this was
intended for special directory entry types that don't have attached inodes.
The following perl+coccinelle script was used:
use strict;
my @callers;
open($fd, 'git grep -l \'S_IS[A-Z].*->d_inode\' |') ||
die "Can't grep for S_ISDIR and co. callers";
@callers = <$fd>;
close($fd);
unless (@callers) {
print "No matches\n";
exit(0);
}
my @cocci = (
'@@',
'expression E;',
'@@',
'',
'- S_ISLNK(E->d_inode->i_mode)',
'+ d_is_symlink(E)',
'',
'@@',
'expression E;',
'@@',
'',
'- S_ISDIR(E->d_inode->i_mode)',
'+ d_is_dir(E)',
'',
'@@',
'expression E;',
'@@',
'',
'- S_ISREG(E->d_inode->i_mode)',
'+ d_is_reg(E)' );
my $coccifile = "tmp.sp.cocci";
open($fd, ">$coccifile") || die $coccifile;
print($fd "$_\n") || die $coccifile foreach (@cocci);
close($fd);
foreach my $file (@callers) {
chomp $file;
print "Processing ", $file, "\n";
system("spatch", "--sp-file", $coccifile, $file, "--in-place", "--no-show-diff") == 0 ||
die "spatch failed";
}
[AV: overlayfs parts skipped]
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2015-01-29 15:02:35 +03:00
if ( d_is_dir ( old_dentry ) )
2006-10-01 10:29:03 +04:00
drop_nlink ( old_dir_i ) ;
2005-04-17 02:20:36 +04:00
2005-08-17 17:46:26 +04:00
new_dir_i - > i_mtime = new_dir_i - > i_ctime = old_dir_i - > i_mtime = old_dir_i - > i_ctime = ITIME ( now ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}