2019-05-31 11:09:56 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2006-01-16 19:50:04 +03:00
/*
* Copyright ( C ) Sistina Software , Inc . 1997 - 2003 All rights reserved .
2006-05-18 23:09:15 +04:00
* Copyright ( C ) 2004 - 2006 Red Hat , Inc . All rights reserved .
2006-01-16 19:50:04 +03:00
*/
# include <linux/spinlock.h>
# include <linux/completion.h>
# include <linux/buffer_head.h>
2006-02-28 01:23:27 +03:00
# include <linux/gfs2_ondisk.h>
2011-01-07 09:49:57 +03:00
# include <linux/namei.h>
2006-03-28 23:14:04 +04:00
# include <linux/crc32.h>
2006-01-16 19:50:04 +03:00
# include "gfs2.h"
2006-02-28 01:23:27 +03:00
# include "incore.h"
2006-01-16 19:50:04 +03:00
# include "dir.h"
# include "glock.h"
2008-10-14 19:05:55 +04:00
# include "super.h"
2006-02-28 01:23:27 +03:00
# include "util.h"
2007-05-15 18:37:50 +04:00
# include "inode.h"
2006-01-16 19:50:04 +03:00
/**
* gfs2_drevalidate - Check directory lookup consistency
* @ dentry : the mapping to check
2012-06-11 00:03:43 +04:00
* @ flags : lookup flags
2006-01-16 19:50:04 +03:00
*
* Check to make sure the lookup necessary to arrive at this inode from its
* parent is still good .
*
* Returns : 1 if the dentry is ok , 0 if it isn ' t
*/
2012-06-11 00:03:43 +04:00
static int gfs2_drevalidate ( struct dentry * dentry , unsigned int flags )
2006-01-16 19:50:04 +03:00
{
2011-01-07 09:49:57 +03:00
struct dentry * parent ;
struct gfs2_sbd * sdp ;
struct gfs2_inode * dip ;
struct inode * inode ;
2006-01-16 19:50:04 +03:00
struct gfs2_holder d_gh ;
2007-05-15 18:37:50 +04:00
struct gfs2_inode * ip = NULL ;
2019-08-06 20:52:21 +03:00
int error , valid = 0 ;
2008-02-22 19:07:18 +03:00
int had_lock = 0 ;
2006-01-16 19:50:04 +03:00
2012-06-11 00:03:43 +04:00
if ( flags & LOOKUP_RCU )
2011-01-07 09:49:57 +03:00
return - ECHILD ;
parent = dget_parent ( dentry ) ;
2015-03-18 01:25:59 +03:00
sdp = GFS2_SB ( d_inode ( parent ) ) ;
dip = GFS2_I ( d_inode ( parent ) ) ;
inode = d_inode ( dentry ) ;
2011-01-07 09:49:57 +03:00
2007-05-15 18:37:50 +04:00
if ( inode ) {
if ( is_bad_inode ( inode ) )
2019-08-06 20:52:21 +03:00
goto out ;
2007-05-15 18:37:50 +04:00
ip = GFS2_I ( inode ) ;
}
2006-01-16 19:50:04 +03:00
2019-08-06 20:52:21 +03:00
if ( sdp - > sd_lockstruct . ls_ops - > lm_mount = = NULL ) {
valid = 1 ;
goto out ;
}
2006-03-20 20:30:04 +03:00
2008-02-22 19:07:18 +03:00
had_lock = ( gfs2_glock_is_locked_by_me ( dip - > i_gl ) ! = NULL ) ;
2007-02-06 11:52:16 +03:00
if ( ! had_lock ) {
error = gfs2_glock_nq_init ( dip - > i_gl , LM_ST_SHARED , 0 , & d_gh ) ;
if ( error )
2019-08-06 20:52:21 +03:00
goto out ;
2006-01-16 19:50:04 +03:00
}
2019-08-06 20:52:21 +03:00
error = gfs2_dir_check ( d_inode ( parent ) , & dentry - > d_name , ip ) ;
valid = inode ? ! error : ( error = = - ENOENT ) ;
2006-01-16 19:50:04 +03:00
2007-02-06 11:52:16 +03:00
if ( ! had_lock )
gfs2_glock_dq_uninit ( & d_gh ) ;
2019-08-06 20:52:21 +03:00
out :
2006-01-16 19:50:04 +03:00
dput ( parent ) ;
2019-08-06 20:52:21 +03:00
return valid ;
2006-01-16 19:50:04 +03:00
}
2013-05-22 02:22:44 +04:00
static int gfs2_dhash ( const struct dentry * dentry , struct qstr * str )
2006-03-20 20:30:04 +03:00
{
str - > hash = gfs2_disk_hash ( str - > name , str - > len ) ;
return 0 ;
}
2023-03-23 19:26:02 +03:00
static int gfs2_dentry_delete ( const struct dentry * dentry )
{
struct gfs2_inode * ginode ;
if ( d_really_is_negative ( dentry ) )
return 0 ;
ginode = GFS2_I ( d_inode ( dentry ) ) ;
if ( ! gfs2_holder_initialized ( & ginode - > i_iopen_gh ) )
return 0 ;
if ( test_bit ( GLF_DEMOTE , & ginode - > i_iopen_gh . gh_gl - > gl_flags ) )
return 1 ;
return 0 ;
}
2009-02-20 09:00:05 +03:00
const struct dentry_operations gfs2_dops = {
2006-01-16 19:50:04 +03:00
. d_revalidate = gfs2_drevalidate ,
2006-03-20 20:30:04 +03:00
. d_hash = gfs2_dhash ,
2023-03-23 19:26:02 +03:00
. d_delete = gfs2_dentry_delete ,
2006-01-16 19:50:04 +03:00
} ;