diff options
Diffstat (limited to 'fs/nfs/unlink.c')
| -rw-r--r-- | fs/nfs/unlink.c | 20 | 
1 files changed, 15 insertions, 5 deletions
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index bf54fc9ae135..fd61bf0fce63 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c @@ -85,7 +85,7 @@ static const struct rpc_call_ops nfs_unlink_ops = {  	.rpc_call_prepare = nfs_unlink_prepare,  }; -static void nfs_do_call_unlink(struct nfs_unlinkdata *data) +static void nfs_do_call_unlink(struct inode *inode, struct nfs_unlinkdata *data)  {  	struct rpc_message msg = {  		.rpc_argp = &data->args, @@ -105,7 +105,7 @@ static void nfs_do_call_unlink(struct nfs_unlinkdata *data)  	data->args.fh = NFS_FH(dir);  	nfs_fattr_init(data->res.dir_attr); -	NFS_PROTO(dir)->unlink_setup(&msg, data->dentry); +	NFS_PROTO(dir)->unlink_setup(&msg, data->dentry, inode);  	task_setup_data.rpc_client = NFS_CLIENT(dir);  	task = rpc_run_task(&task_setup_data); @@ -113,7 +113,7 @@ static void nfs_do_call_unlink(struct nfs_unlinkdata *data)  		rpc_put_task_async(task);  } -static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data) +static int nfs_call_unlink(struct dentry *dentry, struct inode *inode, struct nfs_unlinkdata *data)  {  	struct inode *dir = d_inode(dentry->d_parent);  	struct dentry *alias; @@ -153,7 +153,7 @@ static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data)  		return ret;  	}  	data->dentry = alias; -	nfs_do_call_unlink(data); +	nfs_do_call_unlink(inode, data);  	return 1;  } @@ -231,7 +231,7 @@ nfs_complete_unlink(struct dentry *dentry, struct inode *inode)  	dentry->d_fsdata = NULL;  	spin_unlock(&dentry->d_lock); -	if (NFS_STALE(inode) || !nfs_call_unlink(dentry, data)) +	if (NFS_STALE(inode) || !nfs_call_unlink(dentry, inode, data))  		nfs_free_unlinkdata(data);  } @@ -448,6 +448,7 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)  	unsigned char silly[SILLYNAME_LEN + 1];  	unsigned long long fileid;  	struct dentry *sdentry; +	struct inode *inode = d_inode(dentry);  	struct rpc_task *task;  	int            error = -EBUSY; @@ -485,6 +486,8 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)  			goto out;  	} while (d_inode(sdentry) != NULL); /* need negative lookup */ +	ihold(inode); +  	/* queue unlink first. Can't do this from rpc_release as it  	 * has to allocate memory  	 */ @@ -509,6 +512,12 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)  	case 0:  		/* The rename succeeded */  		nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); +		spin_lock(&inode->i_lock); +		NFS_I(inode)->attr_gencount = nfs_inc_attr_generation_counter(); +		NFS_I(inode)->cache_validity |= NFS_INO_INVALID_CHANGE +			| NFS_INO_INVALID_CTIME +			| NFS_INO_REVAL_FORCED; +		spin_unlock(&inode->i_lock);  		d_move(dentry, sdentry);  		break;  	case -ERESTARTSYS: @@ -519,6 +528,7 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)  	}  	rpc_put_task(task);  out_dput: +	iput(inode);  	dput(sdentry);  out:  	return error;  |