summaryrefslogtreecommitdiffstats
path: root/fs/smbfs
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-12-04 03:58:56 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-12-04 03:58:56 +0000
commit1d67e90f19a7acfd9a05dc59678e7d0c5090bd0d (patch)
tree357efc7b93f8f5102110d20d293f41360ec212fc /fs/smbfs
parentaea27b2e18d69af87e673972246e66657b4fa274 (diff)
Merge with Linux 2.3.21.
Diffstat (limited to 'fs/smbfs')
-rw-r--r--fs/smbfs/cache.c79
-rw-r--r--fs/smbfs/file.c42
2 files changed, 88 insertions, 33 deletions
diff --git a/fs/smbfs/cache.c b/fs/smbfs/cache.c
index 36f1650ac..14d61aba0 100644
--- a/fs/smbfs/cache.c
+++ b/fs/smbfs/cache.c
@@ -14,12 +14,67 @@
#include <linux/mm.h>
#include <linux/dirent.h>
#include <linux/smb_fs.h>
+#include <linux/pagemap.h>
#include <asm/page.h>
#define SMBFS_PARANOIA 1
/* #define SMBFS_DEBUG_VERBOSE 1 */
+#ifdef SMBFS_DEBUG_VERBOSE
+/*
+ * Print a cache_dirent->name, max 80 chars
+ * You can't just printk non-null terminated strings ...
+ */
+printk_name(const char *name, int len)
+{
+ char buf[81];
+
+ if(len > 80)
+ len = 80;
+ strncpy(buf, name, len);
+ buf[len] = 0;
+ printk(buf);
+}
+#endif
+
+/*
+ * Get a page for this inode, if new is set then we want to allocate
+ * the page if it isn't in memory. As I understand it the rest of the
+ * smb-cache code assumes we return a locked page.
+ */
+unsigned long
+get_cached_page(struct inode * inode, unsigned long offset, int new)
+{
+ struct page * page;
+ struct page ** hash;
+ unsigned long new_page;
+
+ again:
+ hash = page_hash(inode, offset);
+ page = __find_lock_page(inode, offset, hash);
+ if(!page && new) {
+ /* not in cache, alloc a new page */
+ new_page = page_cache_alloc();
+ if (!new_page)
+ return 0;
+ clear_page(new_page); /* smb code assumes pages are zeroed */
+ page = page_cache_entry(new_page);
+ if (add_to_page_cache_unique(page, inode, offset, hash)) {
+ /* Hmm, a page has materialized in the
+ cache. Fine. Go back and get that page
+ instead ... throwing away this one first. */
+ put_cached_page((unsigned long) page);
+ goto again;
+ }
+ }
+ if(!page)
+ return 0;
+ if(!PageLocked(page))
+ printk(KERN_ERR "smbfs/cache.c: page isn't locked! This could be fun ...\n");
+ return page_address(page);
+}
+
static inline struct inode *
get_cache_inode(struct cache_head *cachep)
{
@@ -38,8 +93,8 @@ smb_get_dircache(struct dentry * dentry)
struct cache_head * cachep;
#ifdef SMBFS_DEBUG_VERBOSE
-printk("smb_get_dircache: finding cache for %s/%s\n",
-dentry->d_parent->d_name.name, dentry->d_name.name);
+ printk("smb_get_dircache: finding cache for %s/%s\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name);
#endif
cachep = (struct cache_head *) get_cached_page(inode, 0, 1);
if (!cachep)
@@ -140,8 +195,10 @@ smb_add_to_cache(struct cache_head * cachep, struct cache_dirent *entry,
unsigned int needed = len + sizeof(struct cache_entry);
#ifdef SMBFS_DEBUG_VERBOSE
-printk("smb_add_to_cache: cache inode %p, status %d, adding %s at %ld\n",
-inode, cachep->status, entry->name, fpos);
+printk("smb_add_to_cache: cache inode %p, status %d, adding ",
+ inode, cachep->status);
+printk_name(entry->name, entry->len);
+printk(" at %ld\n", fpos);
#endif
/*
* Don't do anything if we've had an error ...
@@ -169,8 +226,10 @@ inode, cachep->status, entry->name, fpos);
block->cb_data.table[nent].ino = entry->ino;
cachep->entries++;
#ifdef SMBFS_DEBUG_VERBOSE
-printk("smb_add_to_cache: added entry %s, len=%d, pos=%ld, entries=%d\n",
-entry->name, len, fpos, cachep->entries);
+printk("smb_add_to_cache: added entry ");
+printk_name(entry->name, entry->len);
+printk(", len=%d, pos=%ld, entries=%d\n",
+len, fpos, cachep->entries);
#endif
return;
}
@@ -231,7 +290,7 @@ printk("smb_find_in_cache: cache %p, looking for pos=%ld\n", cachep, pos);
nent = pos - next_pos;
next_pos += index->num_entries;
if (pos >= next_pos)
- continue;
+ continue;
/*
* The entry is in this block. Note: we return
* then name as a reference with _no_ null byte.
@@ -242,8 +301,9 @@ printk("smb_find_in_cache: cache %p, looking for pos=%ld\n", cachep, pos);
offset = block->cb_data.table[nent].offset;
entry->name = &block->cb_data.names[offset];
#ifdef SMBFS_DEBUG_VERBOSE
-printk("smb_find_in_cache: found %s, len=%d, pos=%ld\n",
-entry->name, entry->len, pos);
+printk("smb_find_in_cache: found ");
+printk_name(entry->name, entry->len);
+printk(", len=%d, pos=%ld\n", entry->len, pos);
#endif
break;
}
@@ -312,4 +372,3 @@ smb_invalid_dir_cache(struct inode * dir)
dir->u.smbfs_i.cache_valid &= ~SMB_F_CACHEVALID;
dir->u.smbfs_i.oldmtime = 0;
}
-
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index 682b511f6..1aa6b711e 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -32,13 +32,6 @@ min(int a, int b)
return a < b ? a : b;
}
-static inline void
-smb_unlock_page(struct page *page)
-{
- clear_bit(PG_locked, &page->flags);
- wake_up(&page->wait);
-}
-
static int
smb_fsync(struct file *file, struct dentry * dentry)
{
@@ -61,7 +54,9 @@ smb_readpage_sync(struct dentry *dentry, struct page *page)
int count = PAGE_SIZE;
int result;
- clear_bit(PG_error, &page->flags);
+ /* We can't replace this with ClearPageError. why? is it a problem?
+ fs/buffer.c:brw_page does the same. */
+ /* clear_bit(PG_error, &page->flags); */
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_readpage_sync: file %s/%s, count=%d@%ld, rsize=%d\n",
@@ -94,11 +89,11 @@ dentry->d_parent->d_name.name, dentry->d_name.name, result);
} while (count);
memset(buffer, 0, count);
- set_bit(PG_uptodate, &page->flags);
+ SetPageUptodate(page);
result = 0;
io_error:
- smb_unlock_page(page);
+ UnlockPage(page);
return result;
}
@@ -110,13 +105,13 @@ smb_readpage(struct file *file, struct page *page)
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");
+ if (!PageLocked(page))
+ printk("smb_readpage: page not already locked!\n");
#endif
- set_bit(PG_locked, &page->flags);
- atomic_inc(&page->count);
+
+ get_page(page);
error = smb_readpage_sync(dentry, page);
- free_page(page_address(page));
+ put_page(page);
return error;
}
@@ -169,6 +164,8 @@ printk("smb_writepage_sync: short write, wsize=%d, result=%d\n", wsize, result);
/*
* Write a page to the server. This will be used for NFS swapping only
* (for now), and we currently do this synchronously only.
+ *
+ * We are called with the page locked and the caller unlocks.
*/
static int
smb_writepage(struct file *file, struct page *page)
@@ -177,14 +174,13 @@ smb_writepage(struct file *file, struct page *page)
int result;
#ifdef SMBFS_PARANOIA
- if (test_bit(PG_locked, &page->flags))
- printk("smb_writepage: page already locked!\n");
+ if (!PageLocked(page))
+ printk("smb_writepage: page not already locked!\n");
#endif
- set_bit(PG_locked, &page->flags);
- atomic_inc(&page->count);
+ get_page(page);
result = smb_writepage_sync(dentry, page, 0, PAGE_SIZE);
- smb_unlock_page(page);
- free_page(page_address(page));
+ SetPageUptodate(page);
+ put_page(page);
return result;
}
@@ -266,9 +262,9 @@ out:
* 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)
+static int smb_write_one_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
{
- long status;
+ int status;
bytes -= copy_from_user((u8*)page_address(page) + offset, buf, bytes);
status = -EFAULT;