Author: denis
Update of /cvs/free/rpms/open-vm-tools-kmod/devel
In directory se02.es.rpmfusion.net:/tmp/cvs-serv535
Added Files:
open-vm-tools-130226-vmhgfs.patch
Log Message:
Update to upstream 130226. Added new kernel module pvscsi. Added patch for vmhgfs compile
open-vm-tools-130226-vmhgfs.patch:
--- NEW FILE open-vm-tools-130226-vmhgfs.patch ---
--- modules/linux/vmhgfs/page.c
+++ modules/linux/vmhgfs/page.c
@@ -48,6 +48,15 @@
struct page *page,
unsigned pageFrom,
unsigned pageTo);
+static void HgfsDoWriteBegin(struct page *page,
+ unsigned pageFrom,
+ unsigned pageTo);
+static int HgfsDoWriteEnd(struct file *file,
+ struct page *page,
+ unsigned pageFrom,
+ unsigned pageTo,
+ loff_t writeTo,
+ unsigned copied);
/* HGFS address space operations. */
static int HgfsReadpage(struct file *file,
@@ -58,6 +67,31 @@
#else
static int HgfsWritepage(struct page *page);
#endif
+
+/*
+ * Write aop interface has changed in 2.6.28. Specifically,
+ * the page locking semantics and requirement to handle
+ * short writes. We already handle short writes, so no major
+ * changes needed. write_begin is expected to return a locked
+ * page and write_end is expected to unlock the page and drop
+ * the reference before returning.
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+static int HgfsWriteBegin(struct file *file,
+ struct address_space *mapping,
+ loff_t pos,
+ unsigned len,
+ unsigned flags,
+ struct page **page,
+ void **clientData);
+static int HgfsWriteEnd(struct file *file,
+ struct address_space *mapping,
+ loff_t pos,
+ unsigned len,
+ unsigned copied,
+ struct page *page,
+ void *clientData);
+#else
static int HgfsPrepareWrite(struct file *file,
struct page *page,
unsigned pageFrom,
@@ -66,13 +100,19 @@
struct page *page,
unsigned pageFrom,
unsigned pageTo);
+#endif
/* HGFS address space operations structure. */
struct address_space_operations HgfsAddressSpaceOperations = {
.readpage = HgfsReadpage,
.writepage = HgfsWritepage,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+ .write_begin = HgfsWriteBegin,
+ .write_end = HgfsWriteEnd,
+#else
.prepare_write = HgfsPrepareWrite,
.commit_write = HgfsCommitWrite,
+#endif
#ifdef HGFS_ENABLE_WRITEBACK
.set_page_dirty = __set_page_dirty_nobuffers,
#endif
@@ -684,14 +724,14 @@
/*
*-----------------------------------------------------------------------------
*
- * HgfsPrepareWrite --
+ * HgfsDoWriteBegin --
*
- * Called by the generic write path to set up a write request for a page.
- * We're expected to do any pre-allocation and housekeeping prior to
- * receiving the write.
+ * Helper function for HgfsWriteBegin / HgfsPrepareWrite.
+ *
+ * Initialize the page if the file is to be appended.
*
* Results:
- * Always zero.
+ * None.
*
* Side effects:
* None.
@@ -699,12 +739,12 @@
*-----------------------------------------------------------------------------
*/
-static int
-HgfsPrepareWrite(struct file *file, // IN: Ignored
- struct page *page, // IN: Page to prepare
- unsigned pageFrom, // IN: Beginning page offset
- unsigned pageTo) // IN: Ending page offset
+static void
+HgfsDoWriteBegin(struct page *page, // IN: Page to be written
+ unsigned pageFrom, // IN: Starting page offset
+ unsigned pageTo) // IN: Ending page offset
{
+ ASSERT(page);
#ifdef HGFS_ENABLE_WRITEBACK
loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
loff_t currentFileSize = compat_i_size_read(page->mapping->host);
@@ -728,6 +768,35 @@
flush_dcache_page(page);
}
#endif
+}
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28)
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsPrepareWrite --
+ *
+ * Called by the generic write path to set up a write request for a page.
+ * We're expected to do any pre-allocation and housekeeping prior to
+ * receiving the write.
+ *
+ * Results:
+ * Always zero.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+HgfsPrepareWrite(struct file *file, // IN: Ignored
+ struct page *page, // IN: Page to prepare
+ unsigned pageFrom, // IN: Beginning page offset
+ unsigned pageTo) // IN: Ending page offset
+{
+ HgfsDoWriteBegin(page, pageFrom, pageTo);
/*
* Prior to 2.4.10, our caller expected to call page_address(page) between
@@ -744,48 +813,94 @@
return 0;
}
+#else
+
/*
*-----------------------------------------------------------------------------
*
- * HgfsCommitWrite --
+ * HgfsWriteBegin --
+ *
+ * Called by the generic write path to set up a write request for a page.
+ * We're expected to do any pre-allocation and housekeeping prior to
+ * receiving the write.
*
- * This function is the more common write path for HGFS, called from
- * generic_file_buffered_write. It is much simpler for us than
- * HgfsWritepage above: the caller has obtained a reference to the page
- * and will unlock it when we're done. And we don't need to worry about
- * properly marking the writeback bit, either. See mm/filemap.c in the
- * kernel for details about how we are called.
+ * This function is expected to return a locked page.
*
* Results:
- * Zero on succes, non-zero on error.
+ * Zero on success, non-zero error otherwise.
*
* Side effects:
- * None.
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+HgfsWriteBegin(struct file *file, // IN: File to be written
+ struct address_space *mapping, // IN: Mapping
+ loff_t pos, // IN: File position
+ unsigned len, // IN: Bytes to be written
+ unsigned flags, // IN: Write flags
+ struct page **pagePtr, // OUT: Locked page
+ void **clientData) // OUT: Opaque to pass to write_end,
unused
+{
+ pgoff_t index = pos >> PAGE_CACHE_SHIFT;
+ unsigned pageFrom = pos & (PAGE_CACHE_SHIFT - 1);
+ unsigned pageTo = pos + len;
+ struct page *page;
+
+ page = __grab_cache_page(mapping, index);
+ if (page == NULL) {
+ return -ENOMEM;
+ }
+ *pagePtr = page;
+
+ HgfsDoWriteBegin(page, pageFrom, pageTo);
+ return 0;
+}
+#endif
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsDoWriteEnd --
+ *
+ * Helper function for HgfsWriteEnd.
+ *
+ * This function updates the inode->i_size, conditionally marks the page
+ * updated and carries out the actual write in case of partial page writes.
+ *
+ * Results:
+ * Zero on succes, non-zero on error.
+ *
+ * Side effects:
+ * None.
*
*-----------------------------------------------------------------------------
*/
static int
-HgfsCommitWrite(struct file *file, // IN: File we're writing to
- struct page *page, // IN: Page we're writing from
- unsigned pageFrom, // IN: Beginning page offset
- unsigned pageTo) // IN: Ending page offset
+HgfsDoWriteEnd(struct file *file, // IN: File we're writing to
+ struct page *page, // IN: Page we're writing from
+ unsigned pageFrom, // IN: Starting page offset
+ unsigned pageTo, // IN: Ending page offset
+ loff_t writeTo, // IN: File position to write to
+ unsigned copied) // IN: Number of bytes copied to the page
{
HgfsHandle handle;
struct inode *inode;
loff_t currentFileSize;
loff_t offset;
- loff_t writeTo;
ASSERT(file);
ASSERT(page);
inode = page->mapping->host;
currentFileSize = compat_i_size_read(inode);
offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
- writeTo = offset + pageTo;
- /* See coment in HgfsPrepareWrite. */
+ /* See comment in HgfsPrepareWrite. */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 10)
kunmap(page);
#endif
@@ -795,14 +910,14 @@
}
/* We wrote a complete page, so it is up to date. */
- if ((pageTo - pageFrom) == PAGE_CACHE_SIZE) {
+ if (copied == PAGE_CACHE_SIZE) {
SetPageUptodate(page);
}
#ifdef HGFS_ENABLE_WRITEBACK
/*
* Check if this is a partial write to a new page, which was
- * initialized in HgfsPrepareWrite.
+ * initialized in HgfsDoWriteBegin.
*/
if ((offset >= currentFileSize) ||
((pageFrom == 0) && (writeTo >= currentFileSize))) {
@@ -821,13 +936,109 @@
/*
* We've recieved a partial write to page that is not uptodate, so
* do the write now while the page is still locked. Another
- * alternative would be to read the page in HgfsPrepareWrite, which
+ * alternative would be to read the page in HgfsDoWriteBegin, which
* would make it uptodate (ie a complete cached page).
*/
handle = FILE_GET_FI_P(file)->handle;
- LOG(6, (KERN_DEBUG "VMware hgfs: HgfsCommitWrite: writing to handle %u\n",
+ LOG(6, (KERN_DEBUG "VMware hgfs: %s: writing to handle %u\n", __FUNCTION__,
handle));
return HgfsDoWritepage(handle, page, pageFrom, pageTo);
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28)
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsCommitWrite --
+ *
+ * This function is the more common write path for HGFS, called from
+ * generic_file_buffered_write. It is much simpler for us than
+ * HgfsWritepage above: the caller has obtained a reference to the page
+ * and will unlock it when we're done. And we don't need to worry about
+ * properly marking the writeback bit, either. See mm/filemap.c in the
+ * kernel for details about how we are called.
+ *
+ * Results:
+ * Zero on succes, non-zero on error.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+HgfsCommitWrite(struct file *file, // IN: File to write
+ struct page *page, // IN: Page to write from
+ unsigned pageFrom, // IN: Starting page offset
+ unsigned pageTo) // IN: Ending page offset
+{
+ loff_t offset;
+ loff_t writeTo;
+ unsigned copied;
+
+ ASSERT(page);
+ ASSERT(file);
+
+ offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
+ writeTo = offset + pageTo;
+ copied = pageTo - pageFrom;
+
+ return HgfsDoWriteEnd(file, page, pageFrom, pageTo, writeTo, copied);
+}
+
+#else
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsWriteEnd --
+ *
+ * This function is the more common write path for HGFS, called from
+ * generic_file_buffered_write. It is much simpler for us than
+ * HgfsWritepage above: write_begin has obtained a reference to the page
+ * and we will unlock it when we're done. And we don't need to worry about
+ * properly marking the writeback bit, either. See mm/filemap.c in the
+ * kernel for details about how we are called.
+ *
+ * This function should unlock the page and reduce the refcount.
+ *
+ * Results:
+ * Number of bytes written or negative error
+ *
+ * Side effects:
+ * Unlocks the page and drops the reference.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+HgfsWriteEnd(struct file *file, // IN: File to write
+ struct address_space *mapping, // IN: Mapping
+ loff_t pos, // IN: File position
+ unsigned len, // IN: len passed from write_begin
+ unsigned copied, // IN: Number of actually copied bytes
+ struct page *page, // IN: Page to write from
+ void *clientData) // IN: From write_begin, unused.
+{
+ unsigned pageFrom = pos & (PAGE_CACHE_SIZE - 1);
+ unsigned pageTo = pageFrom + copied;
+ loff_t writeTo = pos + copied;
+ int ret;
+
+ ASSERT(file);
+ ASSERT(mapping);
+ ASSERT(page);
+
+ ret = HgfsDoWriteEnd(file, page, pageFrom, pageTo, writeTo, copied);
+ if (ret == 0) {
+ ret = copied;
+ }
+
+ compat_unlock_page(page);
+ page_cache_release(page);
+ return ret;
+}
+#endif