patch-2.1.56 linux/fs/smbfs/file.c

Next file: linux/fs/smbfs/inode.c
Previous file: linux/fs/smbfs/dir.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.55/linux/fs/smbfs/file.c linux/fs/smbfs/file.c
@@ -19,6 +19,10 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
+#define SMBFS_PARANOIA 1
+/* #define SMBFS_DEBUG_VERBOSE 1 */
+/* #define pr_debug printk */
+
 static inline int
 min(int a, int b)
 {
@@ -26,8 +30,10 @@
 }
 
 static int
-smb_fsync(struct inode *inode, struct file *file)
+smb_fsync(struct file *file, struct dentry * dentry)
 {
+	printk("smb_fsync: sync file %s/%s\n", 
+		dentry->d_parent->d_name.name, dentry->d_name.name);
 	return 0;
 }
 
@@ -39,6 +45,7 @@
 {
 	unsigned long offset = page->offset;
 	char *buffer = (char *) page_address(page);
+	struct dentry * dentry = inode->u.smbfs_i.dentry;
 	int rsize = SMB_SERVER(inode)->opt.max_xmit - (SMB_HEADER_LEN+15);
 	int result, refresh = 0;
 	int count = PAGE_SIZE;
@@ -46,14 +53,26 @@
 	pr_debug("SMB: smb_readpage_sync(%p)\n", page);
 	clear_bit(PG_error, &page->flags);
 
-	result = smb_open(inode, O_RDONLY);
+	result = -EIO;
+	if (!dentry) {
+		printk("smb_readpage_sync: no dentry for inode %ld\n",
+			inode->i_ino);
+		goto io_error;
+	}
+ 
+	result = smb_open(dentry, O_RDONLY);
 	if (result < 0)
 		goto io_error;
+	/* Should revalidate inode ... */
 
 	do {
 		if (count < rsize)
 			rsize = count;
 
+#ifdef SMBFS_DEBUG_VERBOSE
+printk("smb_readpage: reading %s/%s, offset=%ld, buffer=%p, size=%d\n",
+dentry->d_parent->d_name.name, dentry->d_name.name, offset, buffer, rsize);
+#endif
 		result = smb_proc_read(inode, offset, rsize, buffer);
 		if (result < 0)
 			goto io_error;
@@ -81,15 +100,17 @@
 int
 smb_readpage(struct inode *inode, struct page *page)
 {
-	unsigned long	address;
-	int		error = -1;
+	int		error;
 
 	pr_debug("SMB: smb_readpage %08lx\n", page_address(page));
+#ifdef SMBFS_PARANOIA
+	if (test_bit(PG_locked, &page->flags))
+		printk("smb_readpage: page already locked!\n");
+#endif
 	set_bit(PG_locked, &page->flags);
-	address = page_address(page);
 	atomic_inc(&page->count);
 	error = smb_readpage_sync(inode, page);
-	free_page(address);
+	__free_page(page);
 	return error;
 }
 
@@ -123,6 +144,11 @@
 			clear_bit(PG_uptodate, &page->flags);
 			goto io_error;
 		}
+		/* N.B. what if result < wsize?? */
+#ifdef SMBFS_PARANOIA
+if (result < wsize)
+printk("smb_writepage_sync: short write, wsize=%d, result=%d\n", wsize, result);
+#endif
 		refresh = 1;
 		buffer += wsize;
 		offset += wsize;
@@ -135,6 +161,7 @@
 		smb_refresh_inode(inode);
 
 	clear_bit(PG_locked, &page->flags);
+	wake_up(&page->wait);
 	return written ? written : result;
 }
 
@@ -145,7 +172,17 @@
 static int
 smb_writepage(struct inode *inode, struct page *page)
 {
-	return smb_writepage_sync(inode, page, 0, PAGE_SIZE);
+	int 	result;
+
+#ifdef SMBFS_PARANOIA
+	if (test_bit(PG_locked, &page->flags))
+		printk("smb_writepage: page already locked!\n");
+#endif
+	set_bit(PG_locked, &page->flags);
+	atomic_inc(&page->count);
+	result = smb_writepage_sync(inode, page, 0, PAGE_SIZE);
+	__free_page(page);
+	return result;
 }
 
 static int
@@ -153,15 +190,35 @@
 	       unsigned long offset, unsigned int count, int sync)
 {
 	u8		*page_addr;
+	int 	result;
 
 	pr_debug("SMB:      smb_updatepage(%x/%ld %d@%ld, sync=%d)\n",
 		 inode->i_dev, inode->i_ino,
 		 count, page->offset+offset, sync);
 
+#ifdef SMBFS_PARANOIA
+	if (test_bit(PG_locked, &page->flags))
+		printk("smb_updatepage: page already locked!\n");
+#endif
+	set_bit(PG_locked, &page->flags);
+	atomic_inc(&page->count);
+
 	page_addr = (u8 *) page_address(page);
 
-	copy_from_user(page_addr + offset, buffer, count);
-	return smb_writepage_sync(inode, page, offset, count);
+	if (copy_from_user(page_addr + offset, buffer, count))
+		goto bad_fault;
+	result = smb_writepage_sync(inode, page, offset, count);
+out:
+	__free_page(page);
+	return result;
+
+bad_fault:
+	printk("smb_updatepage: fault at page=%p buffer=%p\n", page, buffer);
+	result = -EFAULT;
+	clear_bit(PG_uptodate, &page->flags);
+	clear_bit(PG_locked, &page->flags);
+	wake_up(&page->wait);
+	goto out;
 }
 
 static long
@@ -175,23 +232,26 @@
 		 count, (unsigned long) file->f_pos);
 
 	status = smb_revalidate_inode(inode);
-	if (status < 0)
-		return status;
-
-	return generic_file_read(inode, file, buf, count);
+	if (status >= 0)
+	{
+		status = generic_file_read(inode, file, buf, count);
+	}
+	return status;
 }
 
 static int
-smb_file_mmap(struct inode * inode, struct file * file,
-				struct vm_area_struct * vma)
+smb_file_mmap(struct file * file, struct vm_area_struct * vma)
 {
+	struct dentry * dentry = file->f_dentry;
+	struct inode * inode = dentry->d_inode;
 	int	status;
 
 	status = smb_revalidate_inode(inode);
-	if (status < 0)
-		return status;
-
-	return generic_file_mmap(inode, file, vma);
+	if (status >= 0)
+	{
+		status = generic_file_mmap(file, vma);
+	}
+	return status;
 }
 
 /* 
@@ -207,28 +267,34 @@
 		 inode->i_dev, inode->i_ino, inode->i_count,
 		 count, (unsigned long) file->f_pos);
 
+	result = -EINVAL;
 	if (!inode) {
 		printk("smb_file_write: inode = NULL\n");
-		return -EINVAL;
+		goto out;
 	}
 
 	result = smb_revalidate_inode(inode);
 	if (result < 0)
-		return result;
+		goto out;
 
-	result = smb_open(inode, O_WRONLY);
+	result = smb_open(file->f_dentry, O_WRONLY);
 	if (result < 0)
-		return result;
+		goto out;
 
+	result = -EINVAL;
 	if (!S_ISREG(inode->i_mode)) {
 		printk("smb_file_write: write to non-file, mode %07o\n",
 			inode->i_mode);
-		return -EINVAL;
+		goto out;
 	}
-	if (count <= 0)
-		return 0;
 
-	return generic_file_write(inode, file, buf, count);
+	result = 0;
+	if (count > 0)
+	{
+		result = generic_file_write(inode, file, buf, count);
+	}
+out:
+	return result;
 }
 
 static struct file_operations smb_file_operations =

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov