summaryrefslogtreecommitdiffstats
path: root/fs/smbfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/smbfs')
-rw-r--r--fs/smbfs/dir.c2
-rw-r--r--fs/smbfs/file.c30
-rw-r--r--fs/smbfs/inode.c52
3 files changed, 47 insertions, 37 deletions
diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c
index 4f942db80..b820642fe 100644
--- a/fs/smbfs/dir.c
+++ b/fs/smbfs/dir.c
@@ -318,7 +318,7 @@ smb_renew_times(struct dentry * dentry)
for (;;)
{
dentry->d_time = jiffies;
- if (dentry == dentry->d_parent)
+ if (IS_ROOT(dentry))
break;
dentry = dentry->d_parent;
}
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index aff45ef9b..2611ceb61 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -188,13 +188,13 @@ smb_writepage(struct file *file, struct page *page)
}
static int
-smb_updatepage(struct file *file, struct page *page, unsigned long offset, unsigned int count, int sync)
+smb_updatepage(struct file *file, struct page *page, unsigned long offset, unsigned int count)
{
struct dentry *dentry = file->f_dentry;
- pr_debug("SMBFS: smb_updatepage(%s/%s %d@%ld, sync=%d)\n",
+ pr_debug("SMBFS: smb_updatepage(%s/%s %d@%ld)\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
- count, page->offset+offset, sync);
+ count, page->offset+offset);
return smb_writepage_sync(dentry, page, offset, count);
}
@@ -256,6 +256,26 @@ out:
return status;
}
+/*
+ * This does the "real" work of the write. The generic routine has
+ * allocated the page, locked it, done all the page alignment stuff
+ * calculations etc. Now we should just copy the data from user
+ * space and write it back to the real medium..
+ *
+ * If the writer ends up delaying the write, the writer needs to
+ * increment the page use counts until he is done with the page.
+ */
+static long smb_write_one_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
+{
+ long status;
+
+ bytes -= copy_from_user((u8*)page_address(page) + offset, buf, bytes);
+ status = -EFAULT;
+ if (bytes)
+ status = smb_updatepage(file, page, offset, bytes);
+ return status;
+}
+
/*
* Write to a file (through the page cache).
*/
@@ -287,7 +307,7 @@ dentry->d_parent->d_name.name, dentry->d_name.name, result);
if (count > 0)
{
- result = generic_file_write(file, buf, count, ppos);
+ result = generic_file_write(file, buf, count, ppos, smb_write_one_page);
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_file_write: pos=%ld, size=%ld, mtime=%ld, atime=%ld\n",
(long) file->f_pos, dentry->d_inode->i_size, dentry->d_inode->i_mtime,
@@ -386,6 +406,6 @@ struct inode_operations smb_file_inode_operations =
NULL, /* truncate */
smb_file_permission, /* permission */
NULL, /* smap */
- smb_updatepage, /* updatepage */
+ NULL, /* updatepage */
smb_revalidate_inode, /* revalidate */
};
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index 1a278911a..d43292af5 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -36,6 +36,7 @@ static void smb_put_inode(struct inode *);
static void smb_delete_inode(struct inode *);
static void smb_put_super(struct super_block *);
static int smb_statfs(struct super_block *, struct statfs *, int);
+static void smb_set_inode_attr(struct inode *, struct smb_fattr *);
static struct super_operations smb_sops =
{
@@ -67,9 +68,7 @@ smb_invent_inos(unsigned long n)
return ino;
}
-static struct smb_fattr *read_fattr = NULL;
-static struct semaphore read_semaphore = MUTEX;
-
+/* We are always generating a new inode here */
struct inode *
smb_iget(struct super_block *sb, struct smb_fattr *fattr)
{
@@ -77,11 +76,19 @@ smb_iget(struct super_block *sb, struct smb_fattr *fattr)
pr_debug("smb_iget: %p\n", fattr);
- down(&read_semaphore);
- read_fattr = fattr;
- result = iget(sb, fattr->f_ino);
- read_fattr = NULL;
- up(&read_semaphore);
+ result = get_empty_inode();
+ result->i_sb = sb;
+ result->i_dev = sb->s_dev;
+ result->i_ino = fattr->f_ino;
+ memset(&(result->u.smbfs_i), 0, sizeof(result->u.smbfs_i));
+ smb_set_inode_attr(result, fattr);
+ if (S_ISREG(result->i_mode))
+ result->i_op = &smb_file_inode_operations;
+ else if (S_ISDIR(result->i_mode))
+ result->i_op = &smb_dir_inode_operations;
+ else
+ result->i_op = NULL;
+ insert_inode_hash(result);
return result;
}
@@ -147,24 +154,9 @@ smb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr)
static void
smb_read_inode(struct inode *inode)
{
- pr_debug("smb_iget: %p\n", read_fattr);
-
- if (!read_fattr || inode->i_ino != read_fattr->f_ino)
- {
- printk("smb_read_inode called from invalid point\n");
- return;
- }
-
- inode->i_dev = inode->i_sb->s_dev;
- memset(&(inode->u.smbfs_i), 0, sizeof(inode->u.smbfs_i));
- smb_set_inode_attr(inode, read_fattr);
-
- if (S_ISREG(inode->i_mode))
- inode->i_op = &smb_file_inode_operations;
- else if (S_ISDIR(inode->i_mode))
- inode->i_op = &smb_dir_inode_operations;
- else
- inode->i_op = NULL;
+ /* Now it can be called only by NFS */
+ printk("smb_read_inode called from invalid point\n");
+ return;
}
/*
@@ -362,8 +354,8 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
sb->s_op = &smb_sops;
sb->u.smbfs_sb.sock_file = NULL;
- sb->u.smbfs_sb.sem = MUTEX;
- sb->u.smbfs_sb.wait = NULL;
+ init_MUTEX(&sb->u.smbfs_sb.sem);
+ init_waitqueue_head(&sb->u.smbfs_sb.wait);
sb->u.smbfs_sb.conn_pid = 0;
sb->u.smbfs_sb.state = CONN_INVALID; /* no connection yet */
sb->u.smbfs_sb.generation = 0;
@@ -410,7 +402,7 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
if (!root_inode)
goto out_no_root;
- sb->s_root = d_alloc_root(root_inode, NULL);
+ sb->s_root = d_alloc_root(root_inode);
if (!sb->s_root)
goto out_no_root;
@@ -609,8 +601,6 @@ init_module(void)
smb_current_vmalloced = 0;
#endif
- read_semaphore = MUTEX;
-
return init_smb_fs();
}