diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-12-04 03:58:56 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-12-04 03:58:56 +0000 |
commit | 1d67e90f19a7acfd9a05dc59678e7d0c5090bd0d (patch) | |
tree | 357efc7b93f8f5102110d20d293f41360ec212fc /fs/smbfs | |
parent | aea27b2e18d69af87e673972246e66657b4fa274 (diff) |
Merge with Linux 2.3.21.
Diffstat (limited to 'fs/smbfs')
-rw-r--r-- | fs/smbfs/cache.c | 79 | ||||
-rw-r--r-- | fs/smbfs/file.c | 42 |
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; |