Problem Description:
You might see a compilation error on your filesystem, which was successfully compiled on versions before linux-3.1.
Scenarios:
You fsync declarations is something like in Kernel older than linux3.1:
int fsync(struct file , struct dentry *, int );
New Declarations:
Root cause:
Kernel Header can not match the fs_ops pointers because of vfs changes.
Solution:
Try defining something like (LINUX_KERNEL_VERSION_MACRO defined as Version number):
int fsync(
struct file *file,
#if (LINUX_KERNEL_VERSION_MACRO < 3.1)
struct dentry *dentry,
#else
loff_t start,
loff_t end,
#endif /* (LINUX_KERNEL_VERSION_MACRO) */
int datasync);
struct file *file,
#if (LINUX_KERNEL_VERSION_MACRO < 3.1)
struct dentry *dentry,
#else
loff_t start,
loff_t end,
#endif /* (LINUX_KERNEL_VERSION_MACRO) */
int datasync);
If I have an older program that uses this version
ReplyDeleteint fsync(struct file , struct dentry *, int );
how do i rewrite it to use the new version, ie can i deduce the parameter values of the two lofft_t parameters from the dentry parameter?
Refer this patch:
ReplyDelete/**
- * vfs_fsync - perform a fsync or fdatasync on a file
+ * generic_sync_file - helper to sync data & metadata to disk
* @file: file to sync
* @dentry: dentry of @file
- * @data: only perform a fdatasync operation
+ * @start: offset in bytes of the beginning of data range to sync
+ * @end: offset in bytes of the end of data range (inclusive)
+ * @what: what should be synced
*
- * Write back data and metadata for @file to disk. If @datasync is
- * set only metadata needed to access modified file data is written.
+ * What the function exactly does is controlled by the @what parameter:
*
- * In case this function is called from nfsd @file may be %NULL and
- * only @dentry is set. This can only happen when the filesystem
- * implements the export_operations API.
+ * If SYNC_SUBMIT_DATA is set, the function submits all pages in the given
+ * range to disk.
+ *
+ * The function always calls ->fsync() callback of the filesystem. If
+ * SYNC_INODE is not set, we pass down the fact that it is just a datasync.
+ *
+ * If SYNC_WAIT_DATA is set, the function waits for writeback to finish
+ * in the given range.
*/
-int vfs_fsync(struct file *file, struct dentry *dentry, int datasync)
+int generic_sync_file(struct file *file, struct dentry *dentry, loff_t start,
+ loff_t end, int what)
{
const struct file_operations *fop;
struct address_space *mapping;
- int err, ret;
+ int err, ret = 0;
/*
* Get mapping and operations from the file in case we have
@@ -212,23 +219,50 @@ int vfs_fsync(struct file *file, struct dentry *dentry, int datasync)
goto out;
}
- ret = filemap_fdatawrite(mapping);
+ if (what & SYNC_SUBMIT_DATA)
+ ret = filemap_fdatawrite_range(mapping, start, end);
/*
* We need to protect against concurrent writers, which could cause
* livelocks in fsync_buffers_list().
*/
mutex_lock(&mapping->host->i_mutex);
- err = fop->fsync(file, dentry, datasync);
+ err = fop->fsync(file, dentry, !(what & SYNC_INODE));
if (!ret)
ret = err;
mutex_unlock(&mapping->host->i_mutex);
- err = filemap_fdatawait(mapping);
- if (!ret)
- ret = err;
+
+ if (what & SYNC_WAIT_DATA) {
+ err = filemap_fdatawait_range(mapping, start, end);
+ if (!ret)
+ ret = err;
+ }
out:
return ret;
}
+EXPORT_SYMBOL(generic_sync_file);
+
+/**
+ * vfs_fsync - perform a fsync or fdatasync on a file
+ * @file: file to sync
+ * @dentry: dentry of @file
+ * @datasync: only perform a fdatasync operation
+ *
+ * Write back data and metadata for @file to disk. If @datasync is
+ * set only metadata needed to access modified file data is written.
+ *
+ * In case this function is called from nfsd @file may be %NULL and
+ * only @dentry is set. This can only happen when the filesystem
+ * implements the export_operations API.
+ */
+int vfs_fsync(struct file *file, struct dentry *dentry, int datasync)
+{
+ int what = SYNC_SUBMIT_DATA | SYNC_WAIT_DATA;
+
+ if (!datasync)
+ what |= SYNC_INODE;
+ return generic_sync_file(file, dentry, 0, LLONG_MAX, what);
+}
@sala limo:
ReplyDeleteeventually, to keep working your existing code, you should use.
Please check the error. I believe, this answer, your question:
============================================================
fsync(struct file file, loff_t start, loff_t end, int datasync)
{
start =0; \\ default value to port older code.
end = LLONG_MAX; \\ default value to port older code.
struct dentry *dentry = file.f_path.dentry; \\ to support portability to older code.
...
...
...
}
@sala Limo:
ReplyDeletePlease refer my following blog for dentry path from struct file*:
http://pankajsaraflinux.blogspot.in/2012/11/linux-file-systems-programming-tricks.html
Eventually you are searching for following pointer:
struct dentry *dentry = file->f_path.dentry;