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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [freevxfs/] [vxfs_lookup.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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
#ident "$Id: vxfs_lookup.c,v 1.1.1.1 2004-04-15 01:11:44 phoenix Exp $"
31
 
32
/*
33
 * Veritas filesystem driver - lookup and other directory related code.
34
 */
35
#include <linux/fs.h>
36
#include <linux/sched.h>
37
#include <linux/mm.h>
38
#include <linux/highmem.h>
39
#include <linux/kernel.h>
40
#include <linux/pagemap.h>
41
 
42
#include "vxfs.h"
43
#include "vxfs_dir.h"
44
#include "vxfs_inode.h"
45
#include "vxfs_extern.h"
46
 
47
/*
48
 * Number of VxFS blocks per page.
49
 */
50
#define VXFS_BLOCK_PER_PAGE(sbp)  ((PAGE_CACHE_SIZE / (sbp)->s_blocksize))
51
 
52
 
53
static struct dentry *  vxfs_lookup(struct inode *, struct dentry *);
54
static int              vxfs_readdir(struct file *, void *, filldir_t);
55
 
56
struct inode_operations vxfs_dir_inode_ops = {
57
        .lookup =               vxfs_lookup,
58
};
59
 
60
struct file_operations vxfs_dir_operations = {
61
        .readdir =              vxfs_readdir,
62
};
63
 
64
 
65
static __inline__ u_long
66
dir_pages(struct inode *inode)
67
{
68
        return (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
69
}
70
 
71
static __inline__ u_long
72
dir_blocks(struct inode *ip)
73
{
74
        u_long                  bsize = ip->i_sb->s_blocksize;
75
        return (ip->i_size + bsize - 1) & ~(bsize - 1);
76
}
77
 
78
/*
79
 * NOTE! unlike strncmp, vxfs_match returns 1 for success, 0 for failure.
80
 *
81
 * len <= VXFS_NAMELEN and de != NULL are guaranteed by caller.
82
 */
83
static __inline__ int
84
vxfs_match(int len, const char * const name, struct vxfs_direct *de)
85
{
86
        if (len != de->d_namelen)
87
                return 0;
88
        if (!de->d_ino)
89
                return 0;
90
        return !memcmp(name, de->d_name, len);
91
}
92
 
93
static __inline__ struct vxfs_direct *
94
vxfs_next_entry(struct vxfs_direct *de)
95
{
96
        return ((struct vxfs_direct *)((char*)de + de->d_reclen));
97
}
98
 
99
/**
100
 * vxfs_find_entry - find a mathing directory entry for a dentry
101
 * @ip:         directory inode
102
 * @dp:         dentry for which we want to find a direct
103
 * @ppp:        gets filled with the page the return value sits in
104
 *
105
 * Description:
106
 *   vxfs_find_entry finds a &struct vxfs_direct for the VFS directory
107
 *   cache entry @dp.  @ppp will be filled with the page the return
108
 *   value resides in.
109
 *
110
 * Returns:
111
 *   The wanted direct on success, else a NULL pointer.
112
 */
113
static struct vxfs_direct *
114
vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
115
{
116
        u_long                          npages, page, nblocks, pblocks, block;
117
        u_long                          bsize = ip->i_sb->s_blocksize;
118
        const char                      *name = dp->d_name.name;
119
        int                             namelen = dp->d_name.len;
120
 
121
        npages = dir_pages(ip);
122
        nblocks = dir_blocks(ip);
123
        pblocks = VXFS_BLOCK_PER_PAGE(ip->i_sb);
124
 
125
        for (page = 0; page < npages; page++) {
126
                caddr_t                 kaddr;
127
                struct page             *pp;
128
 
129
                pp = vxfs_get_page(ip->i_mapping, page);
130
                if (IS_ERR(pp))
131
                        continue;
132
                kaddr = (caddr_t)page_address(pp);
133
 
134
                for (block = 0; block <= nblocks && block <= pblocks; block++) {
135
                        caddr_t                 baddr, limit;
136
                        struct vxfs_dirblk      *dbp;
137
                        struct vxfs_direct      *de;
138
 
139
                        baddr = kaddr + (block * bsize);
140
                        limit = baddr + bsize - VXFS_DIRLEN(1);
141
 
142
                        dbp = (struct vxfs_dirblk *)baddr;
143
                        de = (struct vxfs_direct *)(baddr + VXFS_DIRBLKOV(dbp));
144
 
145
                        for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
146
                                if (!de->d_reclen)
147
                                        break;
148
                                if (!de->d_ino)
149
                                        continue;
150
                                if (vxfs_match(namelen, name, de)) {
151
                                        *ppp = pp;
152
                                        return (de);
153
                                }
154
                        }
155
                }
156
                vxfs_put_page(pp);
157
        }
158
 
159
        return NULL;
160
}
161
 
162
/**
163
 * vxfs_inode_by_name - find inode number for dentry
164
 * @dip:        directory to search in
165
 * @dp:         dentry we seach for
166
 *
167
 * Description:
168
 *   vxfs_inode_by_name finds out the inode number of
169
 *   the path component described by @dp in @dip.
170
 *
171
 * Returns:
172
 *   The wanted inode number on success, else Zero.
173
 */
174
static ino_t
175
vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
176
{
177
        struct vxfs_direct              *de;
178
        struct page                     *pp;
179
        ino_t                           ino = 0;
180
 
181
        de = vxfs_find_entry(dip, dp, &pp);
182
        if (de) {
183
                ino = de->d_ino;
184
                kunmap(pp);
185
                page_cache_release(pp);
186
        }
187
 
188
        return (ino);
189
}
190
 
191
/**
192
 * vxfs_lookup - lookup pathname component
193
 * @dip:        dir in which we lookup
194
 * @dp:         dentry we lookup
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)
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
        ino = vxfs_inode_by_name(dip, dp);
214
        if (ino == 0)
215
                return NULL;
216
 
217
        ip = iget(dip->i_sb, ino);
218
        if (!ip)
219
                return ERR_PTR(-EACCES);
220
        d_add(dp, ip);
221
        return NULL;
222
}
223
 
224
/**
225
 * vxfs_readdir - read a directory
226
 * @fp:         the directory to read
227
 * @retp:       return buffer
228
 * @filler:     filldir callback
229
 *
230
 * Description:
231
 *   vxfs_readdir fills @retp with directory entries from @fp
232
 *   using the VFS supplied callback @filler.
233
 *
234
 * Returns:
235
 *   Zero.
236
 */
237
static int
238
vxfs_readdir(struct file *fp, void *retp, filldir_t filler)
239
{
240
        struct inode            *ip = fp->f_dentry->d_inode;
241
        struct super_block      *sbp = ip->i_sb;
242
        u_long                  bsize = sbp->s_blocksize;
243
        u_long                  page, npages, block, pblocks, nblocks, offset;
244
        loff_t                  pos;
245
 
246
        switch ((long)fp->f_pos) {
247
        case 0:
248
                if (filler(retp, ".", 1, fp->f_pos, ip->i_ino, DT_DIR) < 0)
249
                        goto out;
250
                fp->f_pos++;
251
                /* fallthrough */
252
        case 1:
253
                if (filler(retp, "..", 2, fp->f_pos, VXFS_INO(ip)->vii_dotdot, DT_DIR) < 0)
254
                        goto out;
255
                fp->f_pos++;
256
                /* fallthrough */
257
        }
258
 
259
        pos = fp->f_pos - 2;
260
 
261
        if (pos > VXFS_DIRROUND(ip->i_size))
262
                return 0;
263
 
264
        npages = dir_pages(ip);
265
        nblocks = dir_blocks(ip);
266
        pblocks = VXFS_BLOCK_PER_PAGE(sbp);
267
 
268
        page = pos >> PAGE_CACHE_SHIFT;
269
        offset = pos & ~PAGE_CACHE_MASK;
270
        block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks;
271
 
272
        for (; page < npages; page++, block = 0) {
273
                caddr_t                 kaddr;
274
                struct page             *pp;
275
 
276
                pp = vxfs_get_page(ip->i_mapping, page);
277
                if (IS_ERR(pp))
278
                        continue;
279
                kaddr = (caddr_t)page_address(pp);
280
 
281
                for (; block <= nblocks && block <= pblocks; block++) {
282
                        caddr_t                 baddr, limit;
283
                        struct vxfs_dirblk      *dbp;
284
                        struct vxfs_direct      *de;
285
 
286
                        baddr = kaddr + (block * bsize);
287
                        limit = baddr + bsize - VXFS_DIRLEN(1);
288
 
289
                        dbp = (struct vxfs_dirblk *)baddr;
290
                        de = (struct vxfs_direct *)
291
                                (offset ?
292
                                 (kaddr + offset) :
293
                                 (baddr + VXFS_DIRBLKOV(dbp)));
294
 
295
                        for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
296
                                int     over;
297
 
298
                                if (!de->d_reclen)
299
                                        break;
300
                                if (!de->d_ino)
301
                                        continue;
302
 
303
                                offset = (caddr_t)de - kaddr;
304
                                over = filler(retp, de->d_name, de->d_namelen,
305
                                        ((page << PAGE_CACHE_SHIFT) | offset) + 2,
306
                                        de->d_ino, DT_UNKNOWN);
307
                                if (over) {
308
                                        vxfs_put_page(pp);
309
                                        goto done;
310
                                }
311
                        }
312
                        offset = 0;
313
                }
314
                vxfs_put_page(pp);
315
                offset = 0;
316
        }
317
 
318
done:
319
        fp->f_pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
320
out:
321
        return 0;
322
}

powered by: WebSVN 2.1.0

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