public inbox for linux-nfs@vger.kernel.org
 help / color / mirror / Atom feed
From: Christoph Hellwig <hch@infradead.org>
To: Ben Myers <bpm@sgi.com>
Cc: linux-nfs@vger.kernel.org
Subject: Re: [RFC PATCH 1/2] commit_metadata export operation and nfsd_sync2
Date: Wed, 10 Feb 2010 03:56:14 -0500	[thread overview]
Message-ID: <20100210085614.GA21875@infradead.org> (raw)
In-Reply-To: <20100210003331.6021.55867.stgit@case>


Thanks, this looks very good!  A few comments below:

>  	status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr,
> -				0, (time_t)0);
> +				0, (time_t)0, 0);

While you're at it you might want to remove all those superflous time_t
cases - the C propagation rules take care of it when just passing a "0".

> diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
> index 5a754f7..4c8e1d8 100644
> --- a/fs/nfsd/nfs4recover.c
> +++ b/fs/nfsd/nfs4recover.c
> @@ -120,7 +120,7 @@ static void
>  nfsd4_sync_rec_dir(void)
>  {
>  	mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
> -	nfsd_sync_dir(rec_dir.dentry);
> +	nfsd_sync2(rec_dir.dentry, NULL);
>  	mutex_unlock(&rec_dir.dentry->d_inode->i_mutex);

This call should be changed to just use vfs_fsync as it doesn't
need the special semantics with the i_mutex already held - we take
it just for nfsd_sync_dir here.  That also has the advantage that
nfsd_sync_dir or its replacement can be private to vfs.c now.

>  /*
> + * Commit parent and child to stable storage.  You may pass NULL for parent or
> + * child.  This expects i_mutex to be held on the parent and not to be held on
> + * the child.
>   */
>  int
> +nfsd_sync2(struct dentry *parent, struct dentry *child)

I think both the local routine and the method should be the the same.
The commit_metadata seems a quite a bit better than sync2 for that.


I also think the EX_ISSYNC check should be taken into it instead
of beeing duplicated, which would require it to take a file handle argument.

> +	const struct export_operations *export_ops = NULL;
> +	struct inode *p_inode = NULL, *c_inode = NULL;

Normally we'd just use parent and child for this, or posisbly
just inode and child.

> +	if (parent) {
> +		p_inode = parent->d_inode;
> +		WARN_ON(!mutex_is_locked(&p_inode->i_mutex));
> +		export_ops = parent->d_sb->s_export_op;
> +	}
> +	if (child) {
> +		c_inode = child->d_inode;
> +		WARN_ON(mutex_is_locked(&c_inode->i_mutex));
> +		export_ops = child->d_sb->s_export_op;
> +	}

A better calling convention would be for the first paramter to
always be non-zero (and we could take the file handle for that one),
with only the second argument beeing optional.  That would require
using the same method for the fallback sync, which we should do anyway.

Currently the only caller passing a NULL first argument is
nfsd_setattr.  If we use ->write_inode as fallback we could just
pass it as first, if using ->fsync we'd need to take i_mutex before,
but we might just stick to using ->write_inode to keep things
simple (and get rid of the NULL file pointer in ->fsync).

> +	if (export_ops->commit_metadata) {
> +		if (parent) 
> +			error = filemap_write_and_wait(p_inode->i_mapping);
> +		if (child) 
> +		       	error2 = filemap_write_and_wait(c_inode->i_mapping);

I think Trond explained that we do not want force data to disk here.

> +		if (!error) {
> +			if (child)
> +				mutex_lock(&c_inode->i_mutex);
> +			error = export_ops->commit_metadata(parent, child);
> +			if (child)
> +				mutex_unlock(&c_inode->i_mutex);

Note that at least xfs doesn't care about the i_mutex here.

> +		if (parent) {
> +			error = filemap_write_and_wait(p_inode->i_mapping);
> +			if (!error && p_inode->i_fop->fsync) 
> +				error = p_inode->i_fop->fsync(NULL, parent, 0);
> +		}
> +		if (child)
> +			write_inode_now(c_inode, 1);
> +	}

Btw, as we don't need to write data to disk this should be a
sync_inode calls with the following second argument:

struct writeback_control wbc = {
	.sync_mode = WB_SYNC_ALL,
	.nr_to_write = 0, /* metadata-only */
};

>  
> @@ -1321,14 +1355,14 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
>  		goto out_nfserr;
>  	}
>  
> +	err = nfsd_create_setattr(rqstp, resfhp, iap);
>  	if (EX_ISSYNC(fhp->fh_export)) {
> -		err = nfserrno(nfsd_sync_dir(dentry));
> -		write_inode_now(dchild->d_inode, 1);
> +		err2 = nfserrno(nfsd_sync2(dentry,
> +					IS_ERR(dchild) ? NULL : dchild));

I can't see how you could ever get a dchild that is an error pointer
here.

> @@ -1484,6 +1510,14 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
>  		err = fh_update(resfhp);
>  
>   out:
> +	if (!err) {
> +		if (EX_ISSYNC(fhp->fh_export)) {
> +			host_err = nfsd_sync2(created ? dentry : NULL,
> +				       	!IS_ERR(dchild) ? dchild : NULL);
> +			err = nfserrno(host_err);
> +		}
> +	}
> +

The placement of this call looks incorrect to me.  We don't want
this after the out label which is used for errors, but directly after
the nfsd_create_setattr call, and most importantly before the
mnt_drop_write after which we're not allowed to the filesystem anymore.
That also makes sure we'll never get dchild or dentry as an error
pointer.


  reply	other threads:[~2010-02-10  8:56 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-02-10  0:33 [RFC PATCH 0/2] nfsd sync export_op (was 'wsync export option') Ben Myers
2010-02-10  0:33 ` [RFC PATCH 1/2] commit_metadata export operation and nfsd_sync2 Ben Myers
2010-02-10  8:56   ` Christoph Hellwig [this message]
2010-02-10 19:53     ` bpm
2010-02-10 21:56       ` Christoph Hellwig
2010-02-10  0:33 ` [RFC PATCH 2/2] xfs_export_operations.commit_metadata Ben Myers
2010-02-10  9:07   ` Christoph Hellwig
2010-02-10 10:11     ` Christoph Hellwig
2010-02-10 20:15     ` bpm
2010-02-10 21:29       ` Dave Chinner
2010-02-10 21:57       ` Christoph Hellwig

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100210085614.GA21875@infradead.org \
    --to=hch@infradead.org \
    --cc=bpm@sgi.com \
    --cc=linux-nfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox