aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/idmap.c
diff options
context:
space:
mode:
authorStanislav Kinsbursky <skinsbursky@parallels.com>2012-02-27 13:05:37 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-02-27 13:36:35 -0500
commite9dbca8d732e20b8d31a3094a8669c014e7ee262 (patch)
treebb77ebab17bc03f7e534df359474685bc87ff09d /fs/nfs/idmap.c
parentda3b462296e421e8f54b54b7d2706488661c36e2 (diff)
NFS: release per-net clients lock before calling PipeFS dentries creation
v3: 1) Lookup for client is performed from the beginning of the list on each PipeFS event handling operation. Lockdep is sad otherwise, because inode mutex is taken on PipeFS dentry creation, which can be called on mount notification, where this per-net client lock is taken on clients list walk. Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/idmap.c')
-rw-r--r--fs/nfs/idmap.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index b5c6d8eb7e03..d4db3b6f4b8e 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -553,23 +553,41 @@ static int __rpc_pipefs_event(struct nfs_client *clp, unsigned long event,
553 return err; 553 return err;
554} 554}
555 555
556static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event, 556static struct nfs_client *nfs_get_client_for_event(struct net *net, int event)
557 void *ptr)
558{ 557{
559 struct super_block *sb = ptr; 558 struct nfs_net *nn = net_generic(net, nfs_net_id);
560 struct nfs_net *nn = net_generic(sb->s_fs_info, nfs_net_id); 559 struct dentry *cl_dentry;
561 struct nfs_client *clp; 560 struct nfs_client *clp;
562 int error = 0;
563 561
564 spin_lock(&nn->nfs_client_lock); 562 spin_lock(&nn->nfs_client_lock);
565 list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) { 563 list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) {
566 if (clp->rpc_ops != &nfs_v4_clientops) 564 if (clp->rpc_ops != &nfs_v4_clientops)
567 continue; 565 continue;
566 cl_dentry = clp->cl_idmap->idmap_pipe->dentry;
567 if (((event == RPC_PIPEFS_MOUNT) && cl_dentry) ||
568 ((event == RPC_PIPEFS_UMOUNT) && !cl_dentry))
569 continue;
570 atomic_inc(&clp->cl_count);
571 spin_unlock(&nn->nfs_client_lock);
572 return clp;
573 }
574 spin_unlock(&nn->nfs_client_lock);
575 return NULL;
576}
577
578static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event,
579 void *ptr)
580{
581 struct super_block *sb = ptr;
582 struct nfs_client *clp;
583 int error = 0;
584
585 while ((clp = nfs_get_client_for_event(sb->s_fs_info, event))) {
568 error = __rpc_pipefs_event(clp, event, sb); 586 error = __rpc_pipefs_event(clp, event, sb);
587 nfs_put_client(clp);
569 if (error) 588 if (error)
570 break; 589 break;
571 } 590 }
572 spin_unlock(&nn->nfs_client_lock);
573 return error; 591 return error;
574} 592}
575 593