All of lore.kernel.org
 help / color / mirror / Atom feed
From: NeilBrown <neilb@suse.com>
To: Kinglong Mee <kinglongmee@gmail.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>,
	"J. Bruce Fields" <bfields@fieldses.org>,
	"linux-nfs@vger.kernel.org" <linux-nfs@vger.kernel.org>,
	linux-fsdevel@vger.kernel.org,
	Trond Myklebust <trond.myklebust@primarydata.com>
Subject: Re: [PATCH] fs-pin: allow pin_remove() to be called other than from ->kill()
Date: Tue, 18 Aug 2015 16:21:39 +1000	[thread overview]
Message-ID: <20150818162139.3c214136@noble> (raw)
In-Reply-To: <55D2CBBE.9080807@gmail.com>

On Tue, 18 Aug 2015 14:07:58 +0800 Kinglong Mee <kinglongmee@gmail.com>
wrote:

> Sorry for my so late reply.
> 
> On 7/29/2015 11:59, NeilBrown wrote:
> > fs-pin currently assumes when either the vfsmount or the fs_pin wants
> > to unpin, pin_kill() will be called.
> > This requires that the ->kill() function can wait for any transient
> > references to the fs_pin to be released.  If the structure containing
> > the fs_pin doesn't already have the ability to wait for references,
> > this can be a burden.
> > 
> > As the fs_pin already has infrastructure for waiting, that can be
> > leveraged to remove the burden.
> > 
> > In this alternate scenario, only the vfsmount calls pin_kill() when it
> > wants to unpin.  The owner of the fs_pin() instead calls pin_remove().
> > 
> > The ->kill() function removes any long-term references, and then calls
> > pin_kill() (recursively).
> > When the last reference on (the structure containing) the fs_pin is
> > dropped, pin_remove() will be called and the (recursive) pin_kill()
> > call will complete.
> > 
> > For this to be safe, the final "put" must *not* free the structure if
> > pin_kill() has already been called, as that could leave ->kill()
> > accessing freed data.
> > 
> > So we provide a return value for pin_remove() which reports the old
> > ->done value.
> > 
> > When final put calls pin_remove() it checks that value.
> > If it was 0, then pin_kill() has not called ->kill and will not,
> > so final put can free the data structure.
> > If it was -1, then pin_kill() has called ->kill, and ->kill will
> > free the data structure - final put must not touch it.
> 
> I find another problem, 
> how can xxx_pin_kill known the last reference of the data have be put?
> 
> eg,
> static void expkey_pin_kill(struct fs_pin *pin)
> {
>         struct svc_expkey *key = container_of(pin, struct svc_expkey, ek_pin);
>         cache_delete_entry(key->cd, &key->h);
>         expkey_destroy(key);
> }
> 
> expkey_pin_kill has call cache_delete_entry() but doesn't know whether
> the last reference has be put (here expkey_put is called)? 
> 
> Before the cache_list is deleted from the cache, a third user gets
> the reference, so that, the third user will be the last put of the cache
> by calling expkey_put, xxx_pin_kill only decrease the reference.

expkey_pin_kill() should call:
  cache_delete_entry()
  pin_kill()
  expkey_destroy()

The "cache_delete_entry()" call removes the only long-term reference.
Any other reference will be transient so it is safe to wait for those.

The 'pin_kill()' call will wait of pin_remove() to be called (it
already does that).
pin_remove() will be called when the last reference is dropped.  As
described above, that pin_remove call will return -1 and so the 'put'
function will not have called expkey_destroy.

Finally the expkey_destroy() function actually frees the data
structure.  No other code can be touching at this point.

Thanks,
NeilBrown


> 
> thanks,
> Kinglong Mee
> 
> > 
> > This makes the 'wait' infrastructure of fs_pin available to any
> > pinning client which wants to use it.
> > 
> > Signed-Off-By: NeilBrown <neilb@suse.com>
> > 
> > ---
> > Hi Al,
> >  do you see this as a workable solution?  I think it will improve the nfsd pining patch
> > a lot.
> > 
> > Thanks,
> > NeilBrown
> > 
> > 
> > diff --git a/fs/fs_pin.c b/fs/fs_pin.c
> > index 611b5408f6ec..b7954a9d17da 100644
> > --- a/fs/fs_pin.c
> > +++ b/fs/fs_pin.c
> > @@ -6,16 +6,32 @@
> >  
> >  static DEFINE_SPINLOCK(pin_lock);
> >  
> > -void pin_remove(struct fs_pin *pin)
> > +/**
> > + * pin_remove - disconnect an fs_pin from the pinned structure.
> > + * @pin:	The struct fs_pin which is pinning something.
> > + *
> > + * Detach a 'pin' which was added by pin_insert().  A return value
> > + * of -1 implies that pin_kill() has already been called and that the
> > + * ->kill() function now owns the data structure containing @pin.
> > + * The function which called pin_remove() must not touch the data structure
> > + * again (unless it is the ->kill() function itself).
> > + * A return value of 0 implies an uneventful disconnect: pin_kill() has not called,
> > + * and will not call, the ->kill() function on this @pin.
> > + * Any other return value is a usage error - e.g. repeated call to pin_remove().
> > + */
> > +int pin_remove(struct fs_pin *pin)
> >  {
> > +	int ret;
> >  	spin_lock(&pin_lock);
> >  	hlist_del_init(&pin->m_list);
> >  	hlist_del_init(&pin->s_list);
> >  	spin_unlock(&pin_lock);
> >  	spin_lock_irq(&pin->wait.lock);
> > +	ret = pin->done;
> >  	pin->done = 1;
> >  	wake_up_locked(&pin->wait);
> >  	spin_unlock_irq(&pin->wait.lock);
> > +	return ret;
> >  }
> >  
> >  void pin_insert_group(struct fs_pin *pin, struct vfsmount *m, struct hlist_head *p)
> > diff --git a/include/linux/fs_pin.h b/include/linux/fs_pin.h
> > index 3886b3bffd7f..2fe9d3ba09e8 100644
> > --- a/include/linux/fs_pin.h
> > +++ b/include/linux/fs_pin.h
> > @@ -18,7 +18,7 @@ static inline void init_fs_pin(struct fs_pin *p, void (*kill)(struct fs_pin *))
> >  	p->kill = kill;
> >  }
> >  
> > -void pin_remove(struct fs_pin *);
> > +int pin_remove(struct fs_pin *);
> >  void pin_insert_group(struct fs_pin *, struct vfsmount *, struct hlist_head *);
> >  void pin_insert(struct fs_pin *, struct vfsmount *);
> >  void pin_kill(struct fs_pin *);
> > 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


  reply	other threads:[~2015-08-18  6:21 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-27  3:05 [PATCH 0/9 v8] NFSD: Pin to vfsmount for nfsd exports cache Kinglong Mee
     [not found] ` <55B5A012.1030006-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2015-07-27  3:06   ` [PATCH 1/9 v8] fs_pin: Initialize value for fs_pin explicitly Kinglong Mee
2015-07-27  3:06     ` Kinglong Mee
2015-07-29  0:25     ` NeilBrown
2015-07-29 19:41       ` J. Bruce Fields
     [not found]         ` <20150729194155.GC21949-uC3wQj2KruNg9hUCZPvPmw@public.gmane.org>
2015-07-29 21:48           ` NeilBrown
2015-07-29 21:48             ` NeilBrown
2015-07-30  0:36             ` J. Bruce Fields
2015-07-30 12:28               ` Kinglong Mee
2015-07-27  3:07   ` [PATCH 2/9 v8] fs_pin: Export functions for specific filesystem Kinglong Mee
2015-07-27  3:07     ` Kinglong Mee
2015-07-29  0:30     ` NeilBrown
2015-07-30 12:31       ` Kinglong Mee
2015-07-27  3:07   ` [PATCH 3/9 v8] path: New helpers path_get_pin/path_put_unpin for path pin Kinglong Mee
2015-07-27  3:07     ` Kinglong Mee
2015-07-27  3:09   ` [PATCH 6/9 v8] sunrpc/nfsd: Remove redundant code by exports seq_operations functions Kinglong Mee
2015-07-27  3:09     ` Kinglong Mee
2015-07-29  2:15     ` NeilBrown
2015-07-27  3:12   ` [PATCH 9/9 v8] nfsd: Allows user un-mounting filesystem where nfsd exports base on Kinglong Mee
2015-07-27  3:12     ` Kinglong Mee
     [not found]     ` <55B5A186.7040004-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2015-07-29  3:56       ` NeilBrown
2015-07-29  3:56         ` NeilBrown
2015-07-30 13:30         ` Kinglong Mee
2015-07-30 13:30           ` Kinglong Mee
2015-07-29  3:59       ` [PATCH] fs-pin: allow pin_remove() to be called other than from ->kill() NeilBrown
2015-07-29  3:59         ` NeilBrown
2015-08-10 11:37         ` Kinglong Mee
2015-08-18  6:07         ` Kinglong Mee
2015-08-18  6:07           ` Kinglong Mee
2015-08-18  6:21           ` NeilBrown [this message]
2015-08-18  6:37             ` Kinglong Mee
2015-08-18  6:37               ` Kinglong Mee
2015-07-27  3:08 ` [PATCH 4/9 v8] fs: New helper legitimize_mntget() for getting a legitimize mnt Kinglong Mee
     [not found]   ` <55B5A0B0.7060604-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2015-07-29  2:06     ` NeilBrown
2015-07-29  2:06       ` NeilBrown
2015-07-30 13:17       ` Kinglong Mee
2015-07-27  3:09 ` [PATCH 5/9 v8] sunrpc: Store cache_detail in seq_file's private directly Kinglong Mee
2015-07-29  2:11   ` NeilBrown
2015-07-27  3:10 ` [PATCH 7/9 v8] sunrpc: Switch to using hash list instead single list Kinglong Mee
2015-07-29  2:19   ` NeilBrown
2015-07-29 19:51     ` J. Bruce Fields
2015-07-29 19:51       ` J. Bruce Fields
     [not found]       ` <20150729195151.GD21949-uC3wQj2KruNg9hUCZPvPmw@public.gmane.org>
2015-07-30 13:01         ` Kinglong Mee
2015-07-30 13:01           ` Kinglong Mee
2015-07-27  3:10 ` [PATCH 8/9 v8] sunrpc: New helper cache_delete_entry for deleting cache_head directly Kinglong Mee
     [not found]   ` <55B5A135.9050800-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2015-07-29  2:29     ` NeilBrown
2015-07-29  2:29       ` NeilBrown
2015-07-30 13:14       ` Kinglong Mee
2015-07-30 13:14         ` Kinglong Mee

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=20150818162139.3c214136@noble \
    --to=neilb@suse.com \
    --cc=bfields@fieldses.org \
    --cc=kinglongmee@gmail.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=trond.myklebust@primarydata.com \
    --cc=viro@zeniv.linux.org.uk \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.