summaryrefslogtreecommitdiffstats
path: root/module/zfs/zpl_file.c
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2011-05-06 12:23:34 -0700
committerBrian Behlendorf <[email protected]>2011-05-06 12:33:45 -0700
commit3117dd0b9005eb76e483b9772c493883b82998bb (patch)
tree48406e7d6154f424879a3f6cf7100f407d16fc95 /module/zfs/zpl_file.c
parent6ee44e32be259706aed9b1439b71971a165b198c (diff)
Handle NULL in nfsd .fsync() hook
How nfsd handles .fsync() has been changed a couple of times in the recent kernels. But basically there are three cases we need to consider. Linux 2.6.12 - 2.6.33 * The .fsync() hook takes 3 arguments * The nfsd will call .fsync() with a NULL file struct pointer. Linux 2.6.34 * The .fsync() hook takes 3 arguments * The nfsd no longer calls .fsync() but instead used sync_inode() Linux 2.6.35 - 2.6.x * The .fsync() hook takes 2 arguments * The nfsd no longer calls .fsync() but instead used sync_inode() For once it looks like we've gotten lucky. The first two cases can actually be collased in to one if we stop using the file struct pointer entirely. Since the dentry is still passed in both cases this is possible. The last case can then be safely handled by unconditionally using the dentry in the file struct pointer now that we know the nfsd caller has been removed. Closes #230
Diffstat (limited to 'module/zfs/zpl_file.c')
-rw-r--r--module/zfs/zpl_file.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/module/zfs/zpl_file.c b/module/zfs/zpl_file.c
index c8a3fedb7..de66ff4b4 100644
--- a/module/zfs/zpl_file.c
+++ b/module/zfs/zpl_file.c
@@ -76,13 +76,32 @@ zpl_readdir(struct file *filp, void *dirent, filldir_t filldir)
return (error);
}
-ZPL_FSYNC_PROTO(zpl_fsync, filp, unused_dentry, datasync)
+/*
+ * 2.6.35 API change,
+ * As of 2.6.35 the dentry argument to the .fsync() vfs hook was deemed
+ * redundant. The dentry is still accessible via filp->f_path.dentry,
+ * and we are guaranteed that filp will never be NULL.
+ *
+ * 2.6.34 API change,
+ * Prior to 2.6.34 the nfsd kernel server would pass a NULL file struct *
+ * to the .fsync() hook. For this reason, we must be careful not to use
+ * filp unconditionally in the 3 argument case.
+ */
+#ifdef HAVE_2ARGS_FSYNC
+static int
+zpl_fsync(struct file *filp, int datasync)
+{
+ struct dentry *dentry = filp->f_path.dentry;
+#else
+static int
+zpl_fsync(struct file *filp, struct dentry *dentry, int datasync)
{
+#endif /* HAVE_2ARGS_FSYNC */
cred_t *cr = CRED();
int error;
crhold(cr);
- error = -zfs_fsync(filp->f_path.dentry->d_inode, datasync, cr);
+ error = -zfs_fsync(dentry->d_inode, datasync, cr);
crfree(cr);
ASSERT3S(error, <=, 0);