Hi!
commit 4cd9973f9ff69e37dd0ba2bd6e6423f8179c329a upstream.
Patch series "ocfs2: fix nfsd over ocfs2 issues", v2.
This is a series of patches to fix issues on nfsd over ocfs2. patch 1 is to avoid inode removed while nfsd access it patch 2 & 3 is to fix a panic issue.
This patch (of 4):
When nfsd is getting file dentry using handle or parent dentry of some dentry, one cluster lock is used to avoid inode removed from other node, but it still could be removed from local node, so use a rw lock to avoid this.
This causes locking imbalance:
@@ -2851,6 +2857,11 @@ int ocfs2_nfs_sync_lock(struct ocfs2_super *osb, int ex) if (ocfs2_is_hard_readonly(osb)) return -EROFS;
- if (ex)
down_write(&osb->nfs_sync_rwlock);
- else
down_read(&osb->nfs_sync_rwlock);
- if (ocfs2_mount_local(osb)) return 0;
... status = ocfs2_cluster_lock(osb, lockres, ex ? LKM_EXMODE :LKM_PRMODE, 0, 0); ... return status; }
When ocfs2_nfs_sync_lock() returns error, caller can not know if the lock was taken or not.
ocfs2_get_dentry() for example will not call ocfs2_nfs_sync_unlock() if sync_lock() failed, resulting in lock imbalance if ocfs2_cluster_lock() fails.
(Totally untested).
Signed-off-by: Pavel Machek (CIP) pavel@denx.de
Best regards, Pavel
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index c141b06811a6..8149fb6f1f0d 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -2867,9 +2867,15 @@ int ocfs2_nfs_sync_lock(struct ocfs2_super *osb, int ex)
status = ocfs2_cluster_lock(osb, lockres, ex ? LKM_EXMODE : LKM_PRMODE, 0, 0); - if (status < 0) + if (status < 0) { mlog(ML_ERROR, "lock on nfs sync lock failed %d\n", status);
+ if (ex) + up_write(&osb->nfs_sync_rwlock); + else + up_read(&osb->nfs_sync_rwlock); + } + return status; }
Best regards, Pavel