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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [fs/] [smbfs/] [cache.c] - Blame information for rev 65

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

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

powered by: WebSVN 2.1.0

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