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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [fs/] [jffs2/] [v2_0/] [src/] [dir-ecos.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
/*
2
 * JFFS2 -- Journalling Flash File System, Version 2.
3
 *
4
 * Copyright (C) 2001, 2002 Red Hat, Inc.
5
 *
6
 * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
7
 *
8
 * For licensing information, see the file 'LICENCE' in this directory.
9
 *
10
 * $Id: dir-ecos.c,v 1.1.1.1 2004-02-14 13:29:19 phoenix Exp $
11
 *
12
 */
13
 
14
#include <linux/kernel.h>
15
#include <linux/crc32.h>
16
#include "nodelist.h"
17
 
18
/***********************************************************************/
19
 
20
 
21
/* We keep the dirent list sorted in increasing order of name hash,
22
   and we use the same hash function as the dentries. Makes this
23
   nice and simple
24
*/
25
struct inode *jffs2_lookup(struct inode *dir_i, struct qstr *d_name)
26
{
27
        struct jffs2_inode_info *dir_f;
28
        struct jffs2_sb_info *c;
29
        struct jffs2_full_dirent *fd = NULL, *fd_list;
30
        uint32_t ino = 0;
31
        struct inode *inode = NULL;
32
 
33
        D1(printk("jffs2_lookup()\n"));
34
 
35
        dir_f = JFFS2_INODE_INFO(dir_i);
36
        c = JFFS2_SB_INFO(dir_i->i_sb);
37
 
38
        down(&dir_f->sem);
39
 
40
        /* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */
41
        for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= d_name->hash; fd_list = fd_list->next) {
42
                if (fd_list->nhash == d_name->hash &&
43
                    (!fd || fd_list->version > fd->version) &&
44
                    strlen(fd_list->name) == d_name->len &&
45
                    !strncmp(fd_list->name, d_name->name, d_name->len)) {
46
                        fd = fd_list;
47
                }
48
        }
49
        if (fd)
50
                ino = fd->ino;
51
        up(&dir_f->sem);
52
        if (ino) {
53
                inode = iget(dir_i->i_sb, ino);
54
                if (!inode) {
55
                        printk("iget() failed for ino #%u\n", ino);
56
                        return (ERR_PTR(-EIO));
57
                }
58
        }
59
 
60
        return inode;
61
}
62
 
63
/***********************************************************************/
64
 
65
 
66
 
67
int jffs2_create(struct inode *dir_i, struct qstr *d_name, int mode,
68
                 struct inode **new_i)
69
{
70
        struct jffs2_raw_inode *ri;
71
        struct jffs2_inode_info *f, *dir_f;
72
        struct jffs2_sb_info *c;
73
        struct inode *inode;
74
        int ret;
75
 
76
        ri = jffs2_alloc_raw_inode();
77
        if (!ri)
78
                return -ENOMEM;
79
 
80
        c = JFFS2_SB_INFO(dir_i->i_sb);
81
 
82
        D1(printk(KERN_DEBUG "jffs2_create()\n"));
83
 
84
        inode = jffs2_new_inode(dir_i, mode, ri);
85
 
86
        if (IS_ERR(inode)) {
87
                D1(printk(KERN_DEBUG "jffs2_new_inode() failed\n"));
88
                jffs2_free_raw_inode(ri);
89
                return PTR_ERR(inode);
90
        }
91
 
92
        f = JFFS2_INODE_INFO(inode);
93
        dir_f = JFFS2_INODE_INFO(dir_i);
94
 
95
        ret = jffs2_do_create(c, dir_f, f, ri,
96
                              d_name->name, d_name->len);
97
 
98
        if (ret) {
99
                jffs2_clear_inode(inode);
100
                make_bad_inode(inode);
101
                iput(inode);
102
                jffs2_free_raw_inode(ri);
103
                return ret;
104
        }
105
 
106
        jffs2_free_raw_inode(ri);
107
 
108
        D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d)\n",
109
                  inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink));
110
        *new_i = inode;
111
        return 0;
112
}
113
 
114
/***********************************************************************/
115
 
116
 
117
int jffs2_unlink(struct inode *dir_i, struct inode *d_inode, struct qstr *d_name)
118
{
119
        struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb);
120
        struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
121
        struct jffs2_inode_info *dead_f = JFFS2_INODE_INFO(d_inode);
122
        int ret;
123
 
124
        ret = jffs2_do_unlink(c, dir_f, d_name->name,
125
                               d_name->len, dead_f);
126
        if (dead_f->inocache)
127
                d_inode->i_nlink = dead_f->inocache->nlink;
128
        return ret;
129
}
130
/***********************************************************************/
131
 
132
 
133
int jffs2_link (struct inode *old_d_inode, struct inode *dir_i, struct qstr *d_name)
134
{
135
        struct jffs2_sb_info *c = JFFS2_SB_INFO(old_d_inode->i_sb);
136
        struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_d_inode);
137
        struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
138
        int ret;
139
 
140
        /* XXX: This is ugly */
141
        uint8_t type = (old_d_inode->i_mode & S_IFMT) >> 12;
142
        if (!type) type = DT_REG;
143
 
144
        ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, d_name->name, d_name->len);
145
 
146
        if (!ret) {
147
                down(&f->sem);
148
                old_d_inode->i_nlink = ++f->inocache->nlink;
149
                up(&f->sem);
150
        }
151
        return ret;
152
}
153
 
154
int jffs2_mkdir (struct inode *dir_i, struct qstr *d_name, int mode, struct inode **new_i)
155
{
156
        struct jffs2_inode_info *f, *dir_f;
157
        struct jffs2_sb_info *c;
158
        struct inode *inode;
159
        struct jffs2_raw_inode *ri;
160
        struct jffs2_raw_dirent *rd;
161
        struct jffs2_full_dnode *fn;
162
        struct jffs2_full_dirent *fd;
163
        int namelen;
164
        uint32_t alloclen, phys_ofs;
165
        uint32_t writtenlen;
166
        int ret;
167
 
168
        mode |= S_IFDIR;
169
 
170
        ri = jffs2_alloc_raw_inode();
171
        if (!ri)
172
                return -ENOMEM;
173
 
174
        c = JFFS2_SB_INFO(dir_i->i_sb);
175
 
176
        /* Try to reserve enough space for both node and dirent.
177
         * Just the node will do for now, though
178
         */
179
        namelen = d_name->len;
180
        ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL);
181
 
182
        if (ret) {
183
                jffs2_free_raw_inode(ri);
184
                return ret;
185
        }
186
 
187
        inode = jffs2_new_inode(dir_i, mode, ri);
188
 
189
        if (IS_ERR(inode)) {
190
                jffs2_free_raw_inode(ri);
191
                jffs2_complete_reservation(c);
192
                return PTR_ERR(inode);
193
        }
194
 
195
        f = JFFS2_INODE_INFO(inode);
196
 
197
        ri->data_crc = cpu_to_je32(0);
198
        ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
199
 
200
        fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, &writtenlen);
201
 
202
        jffs2_free_raw_inode(ri);
203
 
204
        if (IS_ERR(fn)) {
205
                /* Eeek. Wave bye bye */
206
                up(&f->sem);
207
                jffs2_complete_reservation(c);
208
                jffs2_clear_inode(inode);
209
                return PTR_ERR(fn);
210
        }
211
        /* No data here. Only a metadata node, which will be
212
           obsoleted by the first data write
213
        */
214
        f->metadata = fn;
215
        up(&f->sem);
216
 
217
        /* Work out where to put the dirent node now. */
218
        writtenlen = PAD(writtenlen);
219
        phys_ofs += writtenlen;
220
        alloclen -= writtenlen;
221
 
222
        if (alloclen < sizeof(*rd)+namelen) {
223
                /* Not enough space left in this chunk. Get some more */
224
                jffs2_complete_reservation(c);
225
                ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL);
226
                if (ret) {
227
                        /* Eep. */
228
                        jffs2_clear_inode(inode);
229
                        return ret;
230
                }
231
        }
232
 
233
        rd = jffs2_alloc_raw_dirent();
234
        if (!rd) {
235
                /* Argh. Now we treat it like a normal delete */
236
                jffs2_complete_reservation(c);
237
                jffs2_clear_inode(inode);
238
                return -ENOMEM;
239
        }
240
 
241
        dir_f = JFFS2_INODE_INFO(dir_i);
242
        down(&dir_f->sem);
243
 
244
        rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
245
        rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
246
        rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
247
        rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
248
 
249
        rd->pino = cpu_to_je32(dir_i->i_ino);
250
        rd->version = cpu_to_je32(++dir_f->highest_version);
251
        rd->ino = cpu_to_je32(inode->i_ino);
252
        rd->mctime = cpu_to_je32(cyg_timestamp());
253
        rd->nsize = namelen;
254
        rd->type = DT_DIR;
255
        rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
256
        rd->name_crc = cpu_to_je32(crc32(0, d_name->name, namelen));
257
 
258
        fd = jffs2_write_dirent(c, dir_f, rd, d_name->name, namelen, phys_ofs, &writtenlen);
259
 
260
        jffs2_complete_reservation(c);
261
        jffs2_free_raw_dirent(rd);
262
 
263
        if (IS_ERR(fd)) {
264
                /* dirent failed to write. Delete the inode normally
265
                   as if it were the final unlink() */
266
                up(&dir_f->sem);
267
                jffs2_clear_inode(inode);
268
                return PTR_ERR(fd);
269
        }
270
 
271
        /* Link the fd into the inode's list, obsoleting an old
272
           one if necessary. */
273
        jffs2_add_fd_to_list(c, fd, &dir_f->dents);
274
        up(&dir_f->sem);
275
 
276
        *new_i = inode;
277
        return 0;
278
}
279
 
280
int jffs2_rmdir (struct inode *dir_i, struct inode *d_inode, struct qstr *d_name)
281
{
282
        struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode);
283
        struct jffs2_full_dirent *fd;
284
 
285
        for (fd = f->dents ; fd; fd = fd->next) {
286
                if (fd->ino)
287
                        return EPERM; //-ENOTEMPTY;
288
        }
289
        return jffs2_unlink(dir_i, d_inode, d_name);
290
}
291
 
292
int jffs2_rename (struct inode *old_dir_i, struct inode *d_inode, struct qstr *old_d_name,
293
                        struct inode *new_dir_i, struct qstr *new_d_name)
294
{
295
        int ret;
296
        struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb);
297
        struct jffs2_inode_info *victim_f = NULL;
298
        uint8_t type;
299
 
300
#if 0 /* FIXME -- this really doesn't belong in individual file systems. 
301
         The fileio code ought to do this for us, or at least part of it */
302
        if (new_dentry->d_inode) {
303
                if (S_ISDIR(d_inode->i_mode) &&
304
                    !S_ISDIR(new_dentry->d_inode->i_mode)) {
305
                        /* Cannot rename directory over non-directory */
306
                        return -EINVAL;
307
                }
308
 
309
                victim_f = JFFS2_INODE_INFO(new_dentry->d_inode);
310
 
311
                if (S_ISDIR(new_dentry->d_inode->i_mode)) {
312
                        struct jffs2_full_dirent *fd;
313
 
314
                        if (!S_ISDIR(d_inode->i_mode)) {
315
                                /* Cannot rename non-directory over directory */
316
                                return -EINVAL;
317
                        }
318
                        down(&victim_f->sem);
319
                        for (fd = victim_f->dents; fd; fd = fd->next) {
320
                                if (fd->ino) {
321
                                        up(&victim_f->sem);
322
                                        return -ENOTEMPTY;
323
                                }
324
                        }
325
                        up(&victim_f->sem);
326
                }
327
        }
328
#endif
329
 
330
        /* XXX: We probably ought to alloc enough space for
331
           both nodes at the same time. Writing the new link,
332
           then getting -ENOSPC, is quite bad :)
333
        */
334
 
335
        /* Make a hard link */
336
 
337
        /* XXX: This is ugly */
338
        type = (d_inode->i_mode & S_IFMT) >> 12;
339
        if (!type) type = DT_REG;
340
 
341
        ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i),
342
                            d_inode->i_ino, type,
343
                            new_d_name->name, new_d_name->len);
344
 
345
        if (ret)
346
                return ret;
347
 
348
        if (victim_f) {
349
                /* There was a victim. Kill it off nicely */
350
                /* Don't oops if the victim was a dirent pointing to an
351
                   inode which didn't exist. */
352
                if (victim_f->inocache) {
353
                        down(&victim_f->sem);
354
                        victim_f->inocache->nlink--;
355
                        up(&victim_f->sem);
356
                }
357
        }
358
 
359
        /* Unlink the original */
360
        ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i),
361
                      old_d_name->name, old_d_name->len, NULL);
362
 
363
        if (ret) {
364
                /* Oh shit. We really ought to make a single node which can do both atomically */
365
                struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode);
366
                down(&f->sem);
367
                if (f->inocache)
368
                        d_inode->i_nlink = f->inocache->nlink++;
369
                up(&f->sem);
370
 
371
                printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret);
372
        }
373
        return ret;
374
}
375
 

powered by: WebSVN 2.1.0

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