Remove some unused #include <linux/dirent.h>'s. Signed-off-by: Adrian Bunk <bunk@kernel.org> Cc: Ralf Baechle <ralf@linux-mips.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
		
			
				
	
	
		
			208 lines
		
	
	
	
		
			4.6 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			208 lines
		
	
	
	
		
			4.6 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 *  cache.c
 | 
						|
 *
 | 
						|
 * Copyright (C) 1997 by Bill Hawes
 | 
						|
 *
 | 
						|
 * Routines to support directory cacheing using the page cache.
 | 
						|
 * This cache code is almost directly taken from ncpfs.
 | 
						|
 *
 | 
						|
 * Please add a note about your changes to smbfs in the ChangeLog file.
 | 
						|
 */
 | 
						|
 | 
						|
#include <linux/time.h>
 | 
						|
#include <linux/errno.h>
 | 
						|
#include <linux/kernel.h>
 | 
						|
#include <linux/mm.h>
 | 
						|
#include <linux/smb_fs.h>
 | 
						|
#include <linux/pagemap.h>
 | 
						|
#include <linux/net.h>
 | 
						|
 | 
						|
#include <asm/page.h>
 | 
						|
 | 
						|
#include "smb_debug.h"
 | 
						|
#include "proto.h"
 | 
						|
 | 
						|
/*
 | 
						|
 * Force the next attempt to use the cache to be a timeout.
 | 
						|
 * If we can't find the page that's fine, it will cause a refresh.
 | 
						|
 */
 | 
						|
void
 | 
						|
smb_invalid_dir_cache(struct inode * dir)
 | 
						|
{
 | 
						|
	struct smb_sb_info *server = server_from_inode(dir);
 | 
						|
	union  smb_dir_cache *cache = NULL;
 | 
						|
	struct page *page = NULL;
 | 
						|
 | 
						|
	page = grab_cache_page(&dir->i_data, 0);
 | 
						|
	if (!page)
 | 
						|
		goto out;
 | 
						|
 | 
						|
	if (!PageUptodate(page))
 | 
						|
		goto out_unlock;
 | 
						|
 | 
						|
	cache = kmap(page);
 | 
						|
	cache->head.time = jiffies - SMB_MAX_AGE(server);
 | 
						|
 | 
						|
	kunmap(page);
 | 
						|
	SetPageUptodate(page);
 | 
						|
out_unlock:
 | 
						|
	unlock_page(page);
 | 
						|
	page_cache_release(page);
 | 
						|
out:
 | 
						|
	return;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Mark all dentries for 'parent' as invalid, forcing them to be re-read
 | 
						|
 */
 | 
						|
void
 | 
						|
smb_invalidate_dircache_entries(struct dentry *parent)
 | 
						|
{
 | 
						|
	struct smb_sb_info *server = server_from_dentry(parent);
 | 
						|
	struct list_head *next;
 | 
						|
	struct dentry *dentry;
 | 
						|
 | 
						|
	spin_lock(&dcache_lock);
 | 
						|
	next = parent->d_subdirs.next;
 | 
						|
	while (next != &parent->d_subdirs) {
 | 
						|
		dentry = list_entry(next, struct dentry, d_u.d_child);
 | 
						|
		dentry->d_fsdata = NULL;
 | 
						|
		smb_age_dentry(server, dentry);
 | 
						|
		next = next->next;
 | 
						|
	}
 | 
						|
	spin_unlock(&dcache_lock);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * dget, but require that fpos and parent matches what the dentry contains.
 | 
						|
 * dentry is not known to be a valid pointer at entry.
 | 
						|
 */
 | 
						|
struct dentry *
 | 
						|
smb_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
 | 
						|
{
 | 
						|
	struct dentry *dent = dentry;
 | 
						|
	struct list_head *next;
 | 
						|
 | 
						|
	if (d_validate(dent, parent)) {
 | 
						|
		if (dent->d_name.len <= SMB_MAXNAMELEN &&
 | 
						|
		    (unsigned long)dent->d_fsdata == fpos) {
 | 
						|
			if (!dent->d_inode) {
 | 
						|
				dput(dent);
 | 
						|
				dent = NULL;
 | 
						|
			}
 | 
						|
			return dent;
 | 
						|
		}
 | 
						|
		dput(dent);
 | 
						|
	}
 | 
						|
 | 
						|
	/* If a pointer is invalid, we search the dentry. */
 | 
						|
	spin_lock(&dcache_lock);
 | 
						|
	next = parent->d_subdirs.next;
 | 
						|
	while (next != &parent->d_subdirs) {
 | 
						|
		dent = list_entry(next, struct dentry, d_u.d_child);
 | 
						|
		if ((unsigned long)dent->d_fsdata == fpos) {
 | 
						|
			if (dent->d_inode)
 | 
						|
				dget_locked(dent);
 | 
						|
			else
 | 
						|
				dent = NULL;
 | 
						|
			goto out_unlock;
 | 
						|
		}
 | 
						|
		next = next->next;
 | 
						|
	}
 | 
						|
	dent = NULL;
 | 
						|
out_unlock:
 | 
						|
	spin_unlock(&dcache_lock);
 | 
						|
	return dent;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Create dentry/inode for this file and add it to the dircache.
 | 
						|
 */
 | 
						|
int
 | 
						|
smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
 | 
						|
	       struct smb_cache_control *ctrl, struct qstr *qname,
 | 
						|
	       struct smb_fattr *entry)
 | 
						|
{
 | 
						|
	struct dentry *newdent, *dentry = filp->f_path.dentry;
 | 
						|
	struct inode *newino, *inode = dentry->d_inode;
 | 
						|
	struct smb_cache_control ctl = *ctrl;
 | 
						|
	int valid = 0;
 | 
						|
	int hashed = 0;
 | 
						|
	ino_t ino = 0;
 | 
						|
 | 
						|
	qname->hash = full_name_hash(qname->name, qname->len);
 | 
						|
 | 
						|
	if (dentry->d_op && dentry->d_op->d_hash)
 | 
						|
		if (dentry->d_op->d_hash(dentry, qname) != 0)
 | 
						|
			goto end_advance;
 | 
						|
 | 
						|
	newdent = d_lookup(dentry, qname);
 | 
						|
 | 
						|
	if (!newdent) {
 | 
						|
		newdent = d_alloc(dentry, qname);
 | 
						|
		if (!newdent)
 | 
						|
			goto end_advance;
 | 
						|
	} else {
 | 
						|
		hashed = 1;
 | 
						|
		memcpy((char *) newdent->d_name.name, qname->name,
 | 
						|
		       newdent->d_name.len);
 | 
						|
	}
 | 
						|
 | 
						|
	if (!newdent->d_inode) {
 | 
						|
		smb_renew_times(newdent);
 | 
						|
		entry->f_ino = iunique(inode->i_sb, 2);
 | 
						|
		newino = smb_iget(inode->i_sb, entry);
 | 
						|
		if (newino) {
 | 
						|
			smb_new_dentry(newdent);
 | 
						|
			d_instantiate(newdent, newino);
 | 
						|
			if (!hashed)
 | 
						|
				d_rehash(newdent);
 | 
						|
		}
 | 
						|
	} else
 | 
						|
		smb_set_inode_attr(newdent->d_inode, entry);
 | 
						|
 | 
						|
        if (newdent->d_inode) {
 | 
						|
		ino = newdent->d_inode->i_ino;
 | 
						|
		newdent->d_fsdata = (void *) ctl.fpos;
 | 
						|
		smb_new_dentry(newdent);
 | 
						|
	}
 | 
						|
 | 
						|
	if (ctl.idx >= SMB_DIRCACHE_SIZE) {
 | 
						|
		if (ctl.page) {
 | 
						|
			kunmap(ctl.page);
 | 
						|
			SetPageUptodate(ctl.page);
 | 
						|
			unlock_page(ctl.page);
 | 
						|
			page_cache_release(ctl.page);
 | 
						|
		}
 | 
						|
		ctl.cache = NULL;
 | 
						|
		ctl.idx  -= SMB_DIRCACHE_SIZE;
 | 
						|
		ctl.ofs  += 1;
 | 
						|
		ctl.page  = grab_cache_page(&inode->i_data, ctl.ofs);
 | 
						|
		if (ctl.page)
 | 
						|
			ctl.cache = kmap(ctl.page);
 | 
						|
	}
 | 
						|
	if (ctl.cache) {
 | 
						|
		ctl.cache->dentry[ctl.idx] = newdent;
 | 
						|
		valid = 1;
 | 
						|
	}
 | 
						|
	dput(newdent);
 | 
						|
 | 
						|
end_advance:
 | 
						|
	if (!valid)
 | 
						|
		ctl.valid = 0;
 | 
						|
	if (!ctl.filled && (ctl.fpos == filp->f_pos)) {
 | 
						|
		if (!ino)
 | 
						|
			ino = find_inode_number(dentry, qname);
 | 
						|
		if (!ino)
 | 
						|
			ino = iunique(inode->i_sb, 2);
 | 
						|
		ctl.filled = filldir(dirent, qname->name, qname->len,
 | 
						|
				     filp->f_pos, ino, DT_UNKNOWN);
 | 
						|
		if (!ctl.filled)
 | 
						|
			filp->f_pos += 1;
 | 
						|
	}
 | 
						|
	ctl.fpos += 1;
 | 
						|
	ctl.idx  += 1;
 | 
						|
	*ctrl = ctl;
 | 
						|
	return (ctl.valid || !ctl.filled);
 | 
						|
}
 |