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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [fs/] [freevxfs/] [vxfs_lookup.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Copyright (c) 2000-2001 Christoph Hellwig.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions, and the following disclaimer,
10
 *    without modification.
11
 * 2. The name of the author may not be used to endorse or promote products
12
 *    derived from this software without specific prior written permission.
13
 *
14
 * Alternatively, this software may be distributed under the terms of the
15
 * GNU General Public License ("GPL").
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
21
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29
 
30
/*
31
 * Veritas filesystem driver - lookup and other directory related code.
32
 */
33
#include <linux/fs.h>
34
#include <linux/time.h>
35
#include <linux/mm.h>
36
#include <linux/highmem.h>
37
#include <linux/kernel.h>
38
#include <linux/pagemap.h>
39
#include <linux/smp_lock.h>
40
 
41
#include "vxfs.h"
42
#include "vxfs_dir.h"
43
#include "vxfs_inode.h"
44
#include "vxfs_extern.h"
45
 
46
/*
47
 * Number of VxFS blocks per page.
48
 */
49
#define VXFS_BLOCK_PER_PAGE(sbp)  ((PAGE_CACHE_SIZE / (sbp)->s_blocksize))
50
 
51
 
52
static struct dentry *  vxfs_lookup(struct inode *, struct dentry *, struct nameidata *);
53
static int              vxfs_readdir(struct file *, void *, filldir_t);
54
 
55
const struct inode_operations vxfs_dir_inode_ops = {
56
        .lookup =               vxfs_lookup,
57
};
58
 
59
const struct file_operations vxfs_dir_operations = {
60
        .readdir =              vxfs_readdir,
61
};
62
 
63
 
64
static inline u_long
65
dir_pages(struct inode *inode)
66
{
67
        return (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
68
}
69
 
70
static inline u_long
71
dir_blocks(struct inode *ip)
72
{
73
        u_long                  bsize = ip->i_sb->s_blocksize;
74
        return (ip->i_size + bsize - 1) & ~(bsize - 1);
75
}
76
 
77
/*
78
 * NOTE! unlike strncmp, vxfs_match returns 1 for success, 0 for failure.
79
 *
80
 * len <= VXFS_NAMELEN and de != NULL are guaranteed by caller.
81
 */
82
static inline int
83
vxfs_match(int len, const char * const name, struct vxfs_direct *de)
84
{
85
        if (len != de->d_namelen)
86
                return 0;
87
        if (!de->d_ino)
88
                return 0;
89
        return !memcmp(name, de->d_name, len);
90
}
91
 
92
static inline struct vxfs_direct *
93
vxfs_next_entry(struct vxfs_direct *de)
94
{
95
        return ((struct vxfs_direct *)((char*)de + de->d_reclen));
96
}
97
 
98
/**
99
 * vxfs_find_entry - find a mathing directory entry for a dentry
100
 * @ip:         directory inode
101
 * @dp:         dentry for which we want to find a direct
102
 * @ppp:        gets filled with the page the return value sits in
103
 *
104
 * Description:
105
 *   vxfs_find_entry finds a &struct vxfs_direct for the VFS directory
106
 *   cache entry @dp.  @ppp will be filled with the page the return
107
 *   value resides in.
108
 *
109
 * Returns:
110
 *   The wanted direct on success, else a NULL pointer.
111
 */
112
static struct vxfs_direct *
113
vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
114
{
115
        u_long                          npages, page, nblocks, pblocks, block;
116
        u_long                          bsize = ip->i_sb->s_blocksize;
117
        const char                      *name = dp->d_name.name;
118
        int                             namelen = dp->d_name.len;
119
 
120
        npages = dir_pages(ip);
121
        nblocks = dir_blocks(ip);
122
        pblocks = VXFS_BLOCK_PER_PAGE(ip->i_sb);
123
 
124
        for (page = 0; page < npages; page++) {
125
                caddr_t                 kaddr;
126
                struct page             *pp;
127
 
128
                pp = vxfs_get_page(ip->i_mapping, page);
129
                if (IS_ERR(pp))
130
                        continue;
131
                kaddr = (caddr_t)page_address(pp);
132
 
133
                for (block = 0; block <= nblocks && block <= pblocks; block++) {
134
                        caddr_t                 baddr, limit;
135
                        struct vxfs_dirblk      *dbp;
136
                        struct vxfs_direct      *de;
137
 
138
                        baddr = kaddr + (block * bsize);
139
                        limit = baddr + bsize - VXFS_DIRLEN(1);
140
 
141
                        dbp = (struct vxfs_dirblk *)baddr;
142
                        de = (struct vxfs_direct *)(baddr + VXFS_DIRBLKOV(dbp));
143
 
144
                        for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
145
                                if (!de->d_reclen)
146
                                        break;
147
                                if (!de->d_ino)
148
                                        continue;
149
                                if (vxfs_match(namelen, name, de)) {
150
                                        *ppp = pp;
151
                                        return (de);
152
                                }
153
                        }
154
                }
155
                vxfs_put_page(pp);
156
        }
157
 
158
        return NULL;
159
}
160
 
161
/**
162
 * vxfs_inode_by_name - find inode number for dentry
163
 * @dip:        directory to search in
164
 * @dp:         dentry we seach for
165
 *
166
 * Description:
167
 *   vxfs_inode_by_name finds out the inode number of
168
 *   the path component described by @dp in @dip.
169
 *
170
 * Returns:
171
 *   The wanted inode number on success, else Zero.
172
 */
173
static ino_t
174
vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
175
{
176
        struct vxfs_direct              *de;
177
        struct page                     *pp;
178
        ino_t                           ino = 0;
179
 
180
        de = vxfs_find_entry(dip, dp, &pp);
181
        if (de) {
182
                ino = de->d_ino;
183
                kunmap(pp);
184
                page_cache_release(pp);
185
        }
186
 
187
        return (ino);
188
}
189
 
190
/**
191
 * vxfs_lookup - lookup pathname component
192
 * @dip:        dir in which we lookup
193
 * @dp:         dentry we lookup
194
 * @nd:         lookup nameidata
195
 *
196
 * Description:
197
 *   vxfs_lookup tries to lookup the pathname component described
198
 *   by @dp in @dip.
199
 *
200
 * Returns:
201
 *   A NULL-pointer on success, else an negative error code encoded
202
 *   in the return pointer.
203
 */
204
static struct dentry *
205
vxfs_lookup(struct inode *dip, struct dentry *dp, struct nameidata *nd)
206
{
207
        struct inode            *ip = NULL;
208
        ino_t                   ino;
209
 
210
        if (dp->d_name.len > VXFS_NAMELEN)
211
                return ERR_PTR(-ENAMETOOLONG);
212
 
213
        lock_kernel();
214
        ino = vxfs_inode_by_name(dip, dp);
215
        if (ino) {
216
                ip = iget(dip->i_sb, ino);
217
                if (!ip) {
218
                        unlock_kernel();
219
                        return ERR_PTR(-EACCES);
220
                }
221
        }
222
        unlock_kernel();
223
        d_add(dp, ip);
224
        return NULL;
225
}
226
 
227
/**
228
 * vxfs_readdir - read a directory
229
 * @fp:         the directory to read
230
 * @retp:       return buffer
231
 * @filler:     filldir callback
232
 *
233
 * Description:
234
 *   vxfs_readdir fills @retp with directory entries from @fp
235
 *   using the VFS supplied callback @filler.
236
 *
237
 * Returns:
238
 *   Zero.
239
 */
240
static int
241
vxfs_readdir(struct file *fp, void *retp, filldir_t filler)
242
{
243
        struct inode            *ip = fp->f_path.dentry->d_inode;
244
        struct super_block      *sbp = ip->i_sb;
245
        u_long                  bsize = sbp->s_blocksize;
246
        u_long                  page, npages, block, pblocks, nblocks, offset;
247
        loff_t                  pos;
248
 
249
        lock_kernel();
250
 
251
        switch ((long)fp->f_pos) {
252
        case 0:
253
                if (filler(retp, ".", 1, fp->f_pos, ip->i_ino, DT_DIR) < 0)
254
                        goto out;
255
                fp->f_pos++;
256
                /* fallthrough */
257
        case 1:
258
                if (filler(retp, "..", 2, fp->f_pos, VXFS_INO(ip)->vii_dotdot, DT_DIR) < 0)
259
                        goto out;
260
                fp->f_pos++;
261
                /* fallthrough */
262
        }
263
 
264
        pos = fp->f_pos - 2;
265
 
266
        if (pos > VXFS_DIRROUND(ip->i_size)) {
267
                unlock_kernel();
268
                return 0;
269
        }
270
 
271
        npages = dir_pages(ip);
272
        nblocks = dir_blocks(ip);
273
        pblocks = VXFS_BLOCK_PER_PAGE(sbp);
274
 
275
        page = pos >> PAGE_CACHE_SHIFT;
276
        offset = pos & ~PAGE_CACHE_MASK;
277
        block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks;
278
 
279
        for (; page < npages; page++, block = 0) {
280
                caddr_t                 kaddr;
281
                struct page             *pp;
282
 
283
                pp = vxfs_get_page(ip->i_mapping, page);
284
                if (IS_ERR(pp))
285
                        continue;
286
                kaddr = (caddr_t)page_address(pp);
287
 
288
                for (; block <= nblocks && block <= pblocks; block++) {
289
                        caddr_t                 baddr, limit;
290
                        struct vxfs_dirblk      *dbp;
291
                        struct vxfs_direct      *de;
292
 
293
                        baddr = kaddr + (block * bsize);
294
                        limit = baddr + bsize - VXFS_DIRLEN(1);
295
 
296
                        dbp = (struct vxfs_dirblk *)baddr;
297
                        de = (struct vxfs_direct *)
298
                                (offset ?
299
                                 (kaddr + offset) :
300
                                 (baddr + VXFS_DIRBLKOV(dbp)));
301
 
302
                        for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
303
                                int     over;
304
 
305
                                if (!de->d_reclen)
306
                                        break;
307
                                if (!de->d_ino)
308
                                        continue;
309
 
310
                                offset = (caddr_t)de - kaddr;
311
                                over = filler(retp, de->d_name, de->d_namelen,
312
                                        ((page << PAGE_CACHE_SHIFT) | offset) + 2,
313
                                        de->d_ino, DT_UNKNOWN);
314
                                if (over) {
315
                                        vxfs_put_page(pp);
316
                                        goto done;
317
                                }
318
                        }
319
                        offset = 0;
320
                }
321
                vxfs_put_page(pp);
322
                offset = 0;
323
        }
324
 
325
done:
326
        fp->f_pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
327
out:
328
        unlock_kernel();
329
        return 0;
330
}

powered by: WebSVN 2.1.0

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