OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [smbfs/] [cache.c] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  cache.c
3
 *
4
 * Copyright (C) 1997 by Bill Hawes
5
 *
6
 * Routines to support directory cacheing using the page cache.
7
 * This cache code is almost directly taken from ncpfs.
8
 *
9
 * Please add a note about your changes to smbfs in the ChangeLog file.
10
 */
11
 
12
#include <linux/sched.h>
13
#include <linux/errno.h>
14
#include <linux/kernel.h>
15
#include <linux/mm.h>
16
#include <linux/dirent.h>
17
#include <linux/smb_fs.h>
18
#include <linux/pagemap.h>
19
 
20
#include <asm/page.h>
21
 
22
#include "smb_debug.h"
23
#include "proto.h"
24
 
25
/*
26
 * Force the next attempt to use the cache to be a timeout.
27
 * If we can't find the page that's fine, it will cause a refresh.
28
 */
29
void
30
smb_invalid_dir_cache(struct inode * dir)
31
{
32
        struct smb_sb_info *server = server_from_inode(dir);
33
        union  smb_dir_cache *cache = NULL;
34
        struct page *page = NULL;
35
 
36
        page = grab_cache_page(&dir->i_data, 0);
37
        if (!page)
38
                goto out;
39
 
40
        if (!Page_Uptodate(page))
41
                goto out_unlock;
42
 
43
        cache = kmap(page);
44
        cache->head.time = jiffies - SMB_MAX_AGE(server);
45
 
46
        kunmap(page);
47
        SetPageUptodate(page);
48
out_unlock:
49
        UnlockPage(page);
50
        page_cache_release(page);
51
out:
52
        return;
53
}
54
 
55
/*
56
 * Mark all dentries for 'parent' as invalid, forcing them to be re-read
57
 */
58
void
59
smb_invalidate_dircache_entries(struct dentry *parent)
60
{
61
        struct smb_sb_info *server = server_from_dentry(parent);
62
        struct list_head *next;
63
        struct dentry *dentry;
64
 
65
        spin_lock(&dcache_lock);
66
        next = parent->d_subdirs.next;
67
        while (next != &parent->d_subdirs) {
68
                dentry = list_entry(next, struct dentry, d_child);
69
                dentry->d_fsdata = NULL;
70
                smb_age_dentry(server, dentry);
71
                next = next->next;
72
        }
73
        spin_unlock(&dcache_lock);
74
}
75
 
76
/*
77
 * dget, but require that fpos and parent matches what the dentry contains.
78
 * dentry is not known to be a valid pointer at entry.
79
 */
80
struct dentry *
81
smb_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
82
{
83
        struct dentry *dent = dentry;
84
        struct list_head *next;
85
 
86
        if (d_validate(dent, parent)) {
87
                if (dent->d_name.len <= SMB_MAXNAMELEN &&
88
                    (unsigned long)dent->d_fsdata == fpos) {
89
                        if (!dent->d_inode) {
90
                                dput(dent);
91
                                dent = NULL;
92
                        }
93
                        return dent;
94
                }
95
                dput(dent);
96
        }
97
 
98
        /* If a pointer is invalid, we search the dentry. */
99
        spin_lock(&dcache_lock);
100
        next = parent->d_subdirs.next;
101
        while (next != &parent->d_subdirs) {
102
                dent = list_entry(next, struct dentry, d_child);
103
                if ((unsigned long)dent->d_fsdata == fpos) {
104
                        if (dent->d_inode)
105
                                dget_locked(dent);
106
                        else
107
                                dent = NULL;
108
                        goto out_unlock;
109
                }
110
                next = next->next;
111
        }
112
        dent = NULL;
113
out_unlock:
114
        spin_unlock(&dcache_lock);
115
        return dent;
116
}
117
 
118
 
119
/*
120
 * Create dentry/inode for this file and add it to the dircache.
121
 */
122
int
123
smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
124
               struct smb_cache_control *ctrl, struct qstr *qname,
125
               struct smb_fattr *entry)
126
{
127
        struct dentry *newdent, *dentry = filp->f_dentry;
128
        struct inode *newino, *inode = dentry->d_inode;
129
        struct smb_cache_control ctl = *ctrl;
130
        int valid = 0;
131
        int hashed = 0;
132
        ino_t ino = 0;
133
 
134
        qname->hash = full_name_hash(qname->name, qname->len);
135
 
136
        if (dentry->d_op && dentry->d_op->d_hash)
137
                if (dentry->d_op->d_hash(dentry, qname) != 0)
138
                        goto end_advance;
139
 
140
        newdent = d_lookup(dentry, qname);
141
 
142
        if (!newdent) {
143
                newdent = d_alloc(dentry, qname);
144
                if (!newdent)
145
                        goto end_advance;
146
        } else {
147
                hashed = 1;
148
                memcpy((char *) newdent->d_name.name, qname->name,
149
                       newdent->d_name.len);
150
        }
151
 
152
        if (!newdent->d_inode) {
153
                smb_renew_times(newdent);
154
                entry->f_ino = iunique(inode->i_sb, 2);
155
                newino = smb_iget(inode->i_sb, entry);
156
                if (newino) {
157
                        smb_new_dentry(newdent);
158
                        d_instantiate(newdent, newino);
159
                        if (!hashed)
160
                                d_rehash(newdent);
161
                }
162
        } else
163
                smb_set_inode_attr(newdent->d_inode, entry);
164
 
165
        if (newdent->d_inode) {
166
                ino = newdent->d_inode->i_ino;
167
                newdent->d_fsdata = (void *) ctl.fpos;
168
                smb_new_dentry(newdent);
169
        }
170
 
171
        if (ctl.idx >= SMB_DIRCACHE_SIZE) {
172
                if (ctl.page) {
173
                        kunmap(ctl.page);
174
                        SetPageUptodate(ctl.page);
175
                        UnlockPage(ctl.page);
176
                        page_cache_release(ctl.page);
177
                }
178
                ctl.cache = NULL;
179
                ctl.idx  -= SMB_DIRCACHE_SIZE;
180
                ctl.ofs  += 1;
181
                ctl.page  = grab_cache_page(&inode->i_data, ctl.ofs);
182
                if (ctl.page)
183
                        ctl.cache = kmap(ctl.page);
184
        }
185
        if (ctl.cache) {
186
                ctl.cache->dentry[ctl.idx] = newdent;
187
                valid = 1;
188
        }
189
        dput(newdent);
190
 
191
end_advance:
192
        if (!valid)
193
                ctl.valid = 0;
194
        if (!ctl.filled && (ctl.fpos == filp->f_pos)) {
195
                if (!ino)
196
                        ino = find_inode_number(dentry, qname);
197
                if (!ino)
198
                        ino = iunique(inode->i_sb, 2);
199
                ctl.filled = filldir(dirent, qname->name, qname->len,
200
                                     filp->f_pos, ino, DT_UNKNOWN);
201
                if (!ctl.filled)
202
                        filp->f_pos += 1;
203
        }
204
        ctl.fpos += 1;
205
        ctl.idx  += 1;
206
        *ctrl = ctl;
207
        return (ctl.valid || !ctl.filled);
208
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.