~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to fs/reiserfs/dir.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
 
3
 */
 
4
 
 
5
#include <linux/string.h>
 
6
#include <linux/errno.h>
 
7
#include <linux/fs.h>
 
8
#include <linux/reiserfs_fs.h>
 
9
#include <linux/stat.h>
 
10
#include <linux/buffer_head.h>
 
11
#include <linux/slab.h>
 
12
#include <asm/uaccess.h>
 
13
 
 
14
extern const struct reiserfs_key MIN_KEY;
 
15
 
 
16
static int reiserfs_readdir(struct file *, void *, filldir_t);
 
17
static int reiserfs_dir_fsync(struct file *filp, loff_t start, loff_t end,
 
18
                              int datasync);
 
19
 
 
20
const struct file_operations reiserfs_dir_operations = {
 
21
        .llseek = generic_file_llseek,
 
22
        .read = generic_read_dir,
 
23
        .readdir = reiserfs_readdir,
 
24
        .fsync = reiserfs_dir_fsync,
 
25
        .unlocked_ioctl = reiserfs_ioctl,
 
26
#ifdef CONFIG_COMPAT
 
27
        .compat_ioctl = reiserfs_compat_ioctl,
 
28
#endif
 
29
};
 
30
 
 
31
static int reiserfs_dir_fsync(struct file *filp, loff_t start, loff_t end,
 
32
                              int datasync)
 
33
{
 
34
        struct inode *inode = filp->f_mapping->host;
 
35
        int err;
 
36
 
 
37
        err = filemap_write_and_wait_range(inode->i_mapping, start, end);
 
38
        if (err)
 
39
                return err;
 
40
 
 
41
        mutex_lock(&inode->i_mutex);
 
42
        reiserfs_write_lock(inode->i_sb);
 
43
        err = reiserfs_commit_for_inode(inode);
 
44
        reiserfs_write_unlock(inode->i_sb);
 
45
        mutex_unlock(&inode->i_mutex);
 
46
        if (err < 0)
 
47
                return err;
 
48
        return 0;
 
49
}
 
50
 
 
51
#define store_ih(where,what) copy_item_head (where, what)
 
52
 
 
53
static inline bool is_privroot_deh(struct dentry *dir,
 
54
                                   struct reiserfs_de_head *deh)
 
55
{
 
56
        struct dentry *privroot = REISERFS_SB(dir->d_sb)->priv_root;
 
57
        return (dir == dir->d_parent && privroot->d_inode &&
 
58
                deh->deh_objectid == INODE_PKEY(privroot->d_inode)->k_objectid);
 
59
}
 
60
 
 
61
int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent,
 
62
                           filldir_t filldir, loff_t *pos)
 
63
{
 
64
        struct inode *inode = dentry->d_inode;
 
65
        struct cpu_key pos_key; /* key of current position in the directory (key of directory entry) */
 
66
        INITIALIZE_PATH(path_to_entry);
 
67
        struct buffer_head *bh;
 
68
        int item_num, entry_num;
 
69
        const struct reiserfs_key *rkey;
 
70
        struct item_head *ih, tmp_ih;
 
71
        int search_res;
 
72
        char *local_buf;
 
73
        loff_t next_pos;
 
74
        char small_buf[32];     /* avoid kmalloc if we can */
 
75
        struct reiserfs_dir_entry de;
 
76
        int ret = 0;
 
77
 
 
78
        reiserfs_write_lock(inode->i_sb);
 
79
 
 
80
        reiserfs_check_lock_depth(inode->i_sb, "readdir");
 
81
 
 
82
        /* form key for search the next directory entry using f_pos field of
 
83
           file structure */
 
84
        make_cpu_key(&pos_key, inode, *pos ?: DOT_OFFSET, TYPE_DIRENTRY, 3);
 
85
        next_pos = cpu_key_k_offset(&pos_key);
 
86
 
 
87
        path_to_entry.reada = PATH_READA;
 
88
        while (1) {
 
89
              research:
 
90
                /* search the directory item, containing entry with specified key */
 
91
                search_res =
 
92
                    search_by_entry_key(inode->i_sb, &pos_key, &path_to_entry,
 
93
                                        &de);
 
94
                if (search_res == IO_ERROR) {
 
95
                        // FIXME: we could just skip part of directory which could
 
96
                        // not be read
 
97
                        ret = -EIO;
 
98
                        goto out;
 
99
                }
 
100
                entry_num = de.de_entry_num;
 
101
                bh = de.de_bh;
 
102
                item_num = de.de_item_num;
 
103
                ih = de.de_ih;
 
104
                store_ih(&tmp_ih, ih);
 
105
 
 
106
                /* we must have found item, that is item of this directory, */
 
107
                RFALSE(COMP_SHORT_KEYS(&(ih->ih_key), &pos_key),
 
108
                       "vs-9000: found item %h does not match to dir we readdir %K",
 
109
                       ih, &pos_key);
 
110
                RFALSE(item_num > B_NR_ITEMS(bh) - 1,
 
111
                       "vs-9005 item_num == %d, item amount == %d",
 
112
                       item_num, B_NR_ITEMS(bh));
 
113
 
 
114
                /* and entry must be not more than number of entries in the item */
 
115
                RFALSE(I_ENTRY_COUNT(ih) < entry_num,
 
116
                       "vs-9010: entry number is too big %d (%d)",
 
117
                       entry_num, I_ENTRY_COUNT(ih));
 
118
 
 
119
                if (search_res == POSITION_FOUND
 
120
                    || entry_num < I_ENTRY_COUNT(ih)) {
 
121
                        /* go through all entries in the directory item beginning from the entry, that has been found */
 
122
                        struct reiserfs_de_head *deh =
 
123
                            B_I_DEH(bh, ih) + entry_num;
 
124
 
 
125
                        for (; entry_num < I_ENTRY_COUNT(ih);
 
126
                             entry_num++, deh++) {
 
127
                                int d_reclen;
 
128
                                char *d_name;
 
129
                                off_t d_off;
 
130
                                ino_t d_ino;
 
131
 
 
132
                                if (!de_visible(deh))
 
133
                                        /* it is hidden entry */
 
134
                                        continue;
 
135
                                d_reclen = entry_length(bh, ih, entry_num);
 
136
                                d_name = B_I_DEH_ENTRY_FILE_NAME(bh, ih, deh);
 
137
 
 
138
                                if (d_reclen <= 0 ||
 
139
                                    d_name + d_reclen > bh->b_data + bh->b_size) {
 
140
                                        /* There is corrupted data in entry,
 
141
                                         * We'd better stop here */
 
142
                                        pathrelse(&path_to_entry);
 
143
                                        ret = -EIO;
 
144
                                        goto out;
 
145
                                }
 
146
 
 
147
                                if (!d_name[d_reclen - 1])
 
148
                                        d_reclen = strlen(d_name);
 
149
 
 
150
                                if (d_reclen >
 
151
                                    REISERFS_MAX_NAME(inode->i_sb->
 
152
                                                      s_blocksize)) {
 
153
                                        /* too big to send back to VFS */
 
154
                                        continue;
 
155
                                }
 
156
 
 
157
                                /* Ignore the .reiserfs_priv entry */
 
158
                                if (is_privroot_deh(dentry, deh))
 
159
                                        continue;
 
160
 
 
161
                                d_off = deh_offset(deh);
 
162
                                *pos = d_off;
 
163
                                d_ino = deh_objectid(deh);
 
164
                                if (d_reclen <= 32) {
 
165
                                        local_buf = small_buf;
 
166
                                } else {
 
167
                                        local_buf = kmalloc(d_reclen,
 
168
                                                            GFP_NOFS);
 
169
                                        if (!local_buf) {
 
170
                                                pathrelse(&path_to_entry);
 
171
                                                ret = -ENOMEM;
 
172
                                                goto out;
 
173
                                        }
 
174
                                        if (item_moved(&tmp_ih, &path_to_entry)) {
 
175
                                                kfree(local_buf);
 
176
                                                goto research;
 
177
                                        }
 
178
                                }
 
179
                                // Note, that we copy name to user space via temporary
 
180
                                // buffer (local_buf) because filldir will block if
 
181
                                // user space buffer is swapped out. At that time
 
182
                                // entry can move to somewhere else
 
183
                                memcpy(local_buf, d_name, d_reclen);
 
184
 
 
185
                                /*
 
186
                                 * Since filldir might sleep, we can release
 
187
                                 * the write lock here for other waiters
 
188
                                 */
 
189
                                reiserfs_write_unlock(inode->i_sb);
 
190
                                if (filldir
 
191
                                    (dirent, local_buf, d_reclen, d_off, d_ino,
 
192
                                     DT_UNKNOWN) < 0) {
 
193
                                        reiserfs_write_lock(inode->i_sb);
 
194
                                        if (local_buf != small_buf) {
 
195
                                                kfree(local_buf);
 
196
                                        }
 
197
                                        goto end;
 
198
                                }
 
199
                                reiserfs_write_lock(inode->i_sb);
 
200
                                if (local_buf != small_buf) {
 
201
                                        kfree(local_buf);
 
202
                                }
 
203
                                // next entry should be looked for with such offset
 
204
                                next_pos = deh_offset(deh) + 1;
 
205
 
 
206
                                if (item_moved(&tmp_ih, &path_to_entry)) {
 
207
                                        goto research;
 
208
                                }
 
209
                        }       /* for */
 
210
                }
 
211
 
 
212
                if (item_num != B_NR_ITEMS(bh) - 1)
 
213
                        // end of directory has been reached
 
214
                        goto end;
 
215
 
 
216
                /* item we went through is last item of node. Using right
 
217
                   delimiting key check is it directory end */
 
218
                rkey = get_rkey(&path_to_entry, inode->i_sb);
 
219
                if (!comp_le_keys(rkey, &MIN_KEY)) {
 
220
                        /* set pos_key to key, that is the smallest and greater
 
221
                           that key of the last entry in the item */
 
222
                        set_cpu_key_k_offset(&pos_key, next_pos);
 
223
                        continue;
 
224
                }
 
225
 
 
226
                if (COMP_SHORT_KEYS(rkey, &pos_key)) {
 
227
                        // end of directory has been reached
 
228
                        goto end;
 
229
                }
 
230
 
 
231
                /* directory continues in the right neighboring block */
 
232
                set_cpu_key_k_offset(&pos_key,
 
233
                                     le_key_k_offset(KEY_FORMAT_3_5, rkey));
 
234
 
 
235
        }                       /* while */
 
236
 
 
237
end:
 
238
        *pos = next_pos;
 
239
        pathrelse(&path_to_entry);
 
240
        reiserfs_check_path(&path_to_entry);
 
241
out:
 
242
        reiserfs_write_unlock(inode->i_sb);
 
243
        return ret;
 
244
}
 
245
 
 
246
static int reiserfs_readdir(struct file *file, void *dirent, filldir_t filldir)
 
247
{
 
248
        struct dentry *dentry = file->f_path.dentry;
 
249
        return reiserfs_readdir_dentry(dentry, dirent, filldir, &file->f_pos);
 
250
}
 
251
 
 
252
/* compose directory item containing "." and ".." entries (entries are
 
253
   not aligned to 4 byte boundary) */
 
254
/* the last four params are LE */
 
255
void make_empty_dir_item_v1(char *body, __le32 dirid, __le32 objid,
 
256
                            __le32 par_dirid, __le32 par_objid)
 
257
{
 
258
        struct reiserfs_de_head *deh;
 
259
 
 
260
        memset(body, 0, EMPTY_DIR_SIZE_V1);
 
261
        deh = (struct reiserfs_de_head *)body;
 
262
 
 
263
        /* direntry header of "." */
 
264
        put_deh_offset(&(deh[0]), DOT_OFFSET);
 
265
        /* these two are from make_le_item_head, and are are LE */
 
266
        deh[0].deh_dir_id = dirid;
 
267
        deh[0].deh_objectid = objid;
 
268
        deh[0].deh_state = 0;   /* Endian safe if 0 */
 
269
        put_deh_location(&(deh[0]), EMPTY_DIR_SIZE_V1 - strlen("."));
 
270
        mark_de_visible(&(deh[0]));
 
271
 
 
272
        /* direntry header of ".." */
 
273
        put_deh_offset(&(deh[1]), DOT_DOT_OFFSET);
 
274
        /* key of ".." for the root directory */
 
275
        /* these two are from the inode, and are are LE */
 
276
        deh[1].deh_dir_id = par_dirid;
 
277
        deh[1].deh_objectid = par_objid;
 
278
        deh[1].deh_state = 0;   /* Endian safe if 0 */
 
279
        put_deh_location(&(deh[1]), deh_location(&(deh[0])) - strlen(".."));
 
280
        mark_de_visible(&(deh[1]));
 
281
 
 
282
        /* copy ".." and "." */
 
283
        memcpy(body + deh_location(&(deh[0])), ".", 1);
 
284
        memcpy(body + deh_location(&(deh[1])), "..", 2);
 
285
}
 
286
 
 
287
/* compose directory item containing "." and ".." entries */
 
288
void make_empty_dir_item(char *body, __le32 dirid, __le32 objid,
 
289
                         __le32 par_dirid, __le32 par_objid)
 
290
{
 
291
        struct reiserfs_de_head *deh;
 
292
 
 
293
        memset(body, 0, EMPTY_DIR_SIZE);
 
294
        deh = (struct reiserfs_de_head *)body;
 
295
 
 
296
        /* direntry header of "." */
 
297
        put_deh_offset(&(deh[0]), DOT_OFFSET);
 
298
        /* these two are from make_le_item_head, and are are LE */
 
299
        deh[0].deh_dir_id = dirid;
 
300
        deh[0].deh_objectid = objid;
 
301
        deh[0].deh_state = 0;   /* Endian safe if 0 */
 
302
        put_deh_location(&(deh[0]), EMPTY_DIR_SIZE - ROUND_UP(strlen(".")));
 
303
        mark_de_visible(&(deh[0]));
 
304
 
 
305
        /* direntry header of ".." */
 
306
        put_deh_offset(&(deh[1]), DOT_DOT_OFFSET);
 
307
        /* key of ".." for the root directory */
 
308
        /* these two are from the inode, and are are LE */
 
309
        deh[1].deh_dir_id = par_dirid;
 
310
        deh[1].deh_objectid = par_objid;
 
311
        deh[1].deh_state = 0;   /* Endian safe if 0 */
 
312
        put_deh_location(&(deh[1]),
 
313
                         deh_location(&(deh[0])) - ROUND_UP(strlen("..")));
 
314
        mark_de_visible(&(deh[1]));
 
315
 
 
316
        /* copy ".." and "." */
 
317
        memcpy(body + deh_location(&(deh[0])), ".", 1);
 
318
        memcpy(body + deh_location(&(deh[1])), "..", 2);
 
319
}