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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [reiserfs/] [dir.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
 * Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
3
 */
4
 
5
#include <linux/config.h>
6
#include <linux/string.h>
7
#include <linux/errno.h>
8
#include <linux/fs.h>
9
#include <linux/reiserfs_fs.h>
10
#include <linux/stat.h>
11
#include <linux/smp_lock.h>
12
#include <asm/uaccess.h>
13
 
14
extern struct key  MIN_KEY;
15
 
16
static int reiserfs_readdir (struct file *, void *, filldir_t);
17
int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry, int datasync) ;
18
 
19
struct file_operations reiserfs_dir_operations = {
20
    read:       generic_read_dir,
21
    readdir:    reiserfs_readdir,
22
    fsync:      reiserfs_dir_fsync,
23
    ioctl:      reiserfs_ioctl,
24
};
25
 
26
int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry, int datasync) {
27
  lock_kernel();
28
  reiserfs_commit_for_inode(dentry->d_inode) ;
29
  unlock_kernel() ;
30
  return 0 ;
31
}
32
 
33
 
34
#define store_ih(where,what) copy_item_head (where, what)
35
 
36
//
37
static int reiserfs_readdir (struct file * filp, void * dirent, filldir_t filldir)
38
{
39
    struct inode *inode = filp->f_dentry->d_inode;
40
    struct cpu_key pos_key;     /* key of current position in the directory (key of directory entry) */
41
    INITIALIZE_PATH (path_to_entry);
42
    struct buffer_head * bh;
43
    int item_num, entry_num;
44
    const struct key * rkey;
45
    struct item_head * ih, tmp_ih;
46
    int search_res;
47
    char * local_buf;
48
    loff_t next_pos;
49
    char small_buf[32] ; /* avoid kmalloc if we can */
50
    struct reiserfs_dir_entry de;
51
 
52
 
53
    reiserfs_check_lock_depth("readdir") ;
54
 
55
    /* form key for search the next directory entry using f_pos field of
56
       file structure */
57
    make_cpu_key (&pos_key, inode, (filp->f_pos) ? (filp->f_pos) : DOT_OFFSET,
58
                  TYPE_DIRENTRY, 3);
59
    next_pos = cpu_key_k_offset (&pos_key);
60
 
61
    /*  reiserfs_warning (inode->i_sb, "reiserfs_readdir 1: f_pos = %Ld\n", filp->f_pos);*/
62
 
63
    while (1) {
64
    research:
65
        /* search the directory item, containing entry with specified key */
66
        search_res = search_by_entry_key (inode->i_sb, &pos_key, &path_to_entry, &de);
67
        if (search_res == IO_ERROR) {
68
            // FIXME: we could just skip part of directory which could
69
            // not be read
70
            return -EIO;
71
        }
72
        entry_num = de.de_entry_num;
73
        bh = de.de_bh;
74
        item_num = de.de_item_num;
75
        ih = de.de_ih;
76
        store_ih (&tmp_ih, ih);
77
 
78
        /* we must have found item, that is item of this directory, */
79
        RFALSE( COMP_SHORT_KEYS (&(ih->ih_key), &pos_key),
80
                "vs-9000: found item %h does not match to dir we readdir %K",
81
                ih, &pos_key);
82
        RFALSE( item_num > B_NR_ITEMS (bh) - 1,
83
                "vs-9005 item_num == %d, item amount == %d",
84
                item_num, B_NR_ITEMS (bh));
85
 
86
        /* and entry must be not more than number of entries in the item */
87
        RFALSE( I_ENTRY_COUNT (ih) < entry_num,
88
                "vs-9010: entry number is too big %d (%d)",
89
                entry_num, I_ENTRY_COUNT (ih));
90
 
91
        if (search_res == POSITION_FOUND || entry_num < I_ENTRY_COUNT (ih)) {
92
            /* go through all entries in the directory item beginning from the entry, that has been found */
93
            struct reiserfs_de_head * deh = B_I_DEH (bh, ih) + entry_num;
94
 
95
            for (; entry_num < I_ENTRY_COUNT (ih); entry_num ++, deh ++) {
96
                int d_reclen;
97
                char * d_name;
98
                off_t d_off;
99
                ino_t d_ino;
100
 
101
                if (!de_visible (deh))
102
                    /* it is hidden entry */
103
                    continue;
104
                d_reclen = entry_length (bh, ih, entry_num);
105
                d_name = B_I_DEH_ENTRY_FILE_NAME (bh, ih, deh);
106
                if (!d_name[d_reclen - 1])
107
                    d_reclen = strlen (d_name);
108
 
109
                if (d_reclen > REISERFS_MAX_NAME(inode->i_sb->s_blocksize)){
110
                    /* too big to send back to VFS */
111
                    continue ;
112
                }
113
                d_off = deh_offset (deh);
114
                filp->f_pos = d_off ;
115
                d_ino = deh_objectid (deh);
116
                if (d_reclen <= 32) {
117
                  local_buf = small_buf ;
118
                } else {
119
                    local_buf = reiserfs_kmalloc(d_reclen, GFP_NOFS, inode->i_sb) ;
120
                    if (!local_buf) {
121
                        pathrelse (&path_to_entry);
122
                        return -ENOMEM ;
123
                    }
124
                    if (item_moved (&tmp_ih, &path_to_entry)) {
125
                        reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ;
126
                        goto research;
127
                    }
128
                }
129
                // Note, that we copy name to user space via temporary
130
                // buffer (local_buf) because filldir will block if
131
                // user space buffer is swapped out. At that time
132
                // entry can move to somewhere else
133
                memcpy (local_buf, d_name, d_reclen);
134
                if (filldir (dirent, local_buf, d_reclen, d_off, d_ino,
135
                             DT_UNKNOWN) < 0) {
136
                    if (local_buf != small_buf) {
137
                        reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ;
138
                    }
139
                    goto end;
140
                }
141
                if (local_buf != small_buf) {
142
                    reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ;
143
                }
144
 
145
                // next entry should be looked for with such offset
146
                next_pos = deh_offset (deh) + 1;
147
 
148
                if (item_moved (&tmp_ih, &path_to_entry)) {
149
                    goto research;
150
                }
151
            } /* for */
152
        }
153
 
154
        if (item_num != B_NR_ITEMS (bh) - 1)
155
            // end of directory has been reached
156
            goto end;
157
 
158
        /* item we went through is last item of node. Using right
159
           delimiting key check is it directory end */
160
        rkey = get_rkey (&path_to_entry, inode->i_sb);
161
        if (! comp_le_keys (rkey, &MIN_KEY)) {
162
            /* set pos_key to key, that is the smallest and greater
163
               that key of the last entry in the item */
164
            set_cpu_key_k_offset (&pos_key, next_pos);
165
            continue;
166
        }
167
 
168
        if ( COMP_SHORT_KEYS (rkey, &pos_key)) {
169
            // end of directory has been reached
170
            goto end;
171
        }
172
 
173
        /* directory continues in the right neighboring block */
174
        set_cpu_key_k_offset (&pos_key, le_key_k_offset (KEY_FORMAT_3_5, rkey));
175
 
176
    } /* while */
177
 
178
 
179
 end:
180
 
181
    filp->f_pos = next_pos;
182
    pathrelse (&path_to_entry);
183
    reiserfs_check_path(&path_to_entry) ;
184
    UPDATE_ATIME(inode) ;
185
    return 0;
186
}
187
 
188
/* compose directory item containing "." and ".." entries (entries are
189
   not aligned to 4 byte boundary) */
190
/* the last four params are LE */
191
void make_empty_dir_item_v1 (char * body, __u32 dirid, __u32 objid,
192
                             __u32 par_dirid, __u32 par_objid)
193
{
194
    struct reiserfs_de_head * deh;
195
 
196
    memset (body, 0, EMPTY_DIR_SIZE_V1);
197
    deh = (struct reiserfs_de_head *)body;
198
 
199
    /* direntry header of "." */
200
    put_deh_offset( &(deh[0]), DOT_OFFSET );
201
    /* these two are from make_le_item_head, and are are LE */
202
    deh[0].deh_dir_id = dirid;
203
    deh[0].deh_objectid = objid;
204
    deh[0].deh_state = 0; /* Endian safe if 0 */
205
    put_deh_location( &(deh[0]), EMPTY_DIR_SIZE_V1 - strlen( "." ));
206
    mark_de_visible(&(deh[0]));
207
 
208
    /* direntry header of ".." */
209
    put_deh_offset( &(deh[1]), DOT_DOT_OFFSET);
210
    /* key of ".." for the root directory */
211
    /* these two are from the inode, and are are LE */
212
    deh[1].deh_dir_id = par_dirid;
213
    deh[1].deh_objectid = par_objid;
214
    deh[1].deh_state = 0; /* Endian safe if 0 */
215
    put_deh_location( &(deh[1]), deh_location( &(deh[0]) ) - strlen( ".." ) );
216
    mark_de_visible(&(deh[1]));
217
 
218
    /* copy ".." and "." */
219
    memcpy (body + deh_location( &(deh[0]) ), ".", 1);
220
    memcpy (body + deh_location( &(deh[1]) ), "..", 2);
221
}
222
 
223
/* compose directory item containing "." and ".." entries */
224
void make_empty_dir_item (char * body, __u32 dirid, __u32 objid,
225
                          __u32 par_dirid, __u32 par_objid)
226
{
227
    struct reiserfs_de_head * deh;
228
 
229
    memset (body, 0, EMPTY_DIR_SIZE);
230
    deh = (struct reiserfs_de_head *)body;
231
 
232
    /* direntry header of "." */
233
    put_deh_offset( &(deh[0]), DOT_OFFSET );
234
    /* these two are from make_le_item_head, and are are LE */
235
    deh[0].deh_dir_id = dirid;
236
    deh[0].deh_objectid = objid;
237
    deh[0].deh_state = 0; /* Endian safe if 0 */
238
    put_deh_location( &(deh[0]), EMPTY_DIR_SIZE - ROUND_UP( strlen( "." ) ) );
239
    mark_de_visible(&(deh[0]));
240
 
241
    /* direntry header of ".." */
242
    put_deh_offset( &(deh[1]), DOT_DOT_OFFSET );
243
    /* key of ".." for the root directory */
244
    /* these two are from the inode, and are are LE */
245
    deh[1].deh_dir_id = par_dirid;
246
    deh[1].deh_objectid = par_objid;
247
    deh[1].deh_state = 0; /* Endian safe if 0 */
248
    put_deh_location( &(deh[1]), deh_location( &(deh[0])) - ROUND_UP( strlen( ".." ) ) );
249
    mark_de_visible(&(deh[1]));
250
 
251
    /* copy ".." and "." */
252
    memcpy (body + deh_location( &(deh[0]) ), ".", 1);
253
    memcpy (body + deh_location( &(deh[1]) ), "..", 2);
254
}

powered by: WebSVN 2.1.0

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