source: rtems/cpukit/libfs/src/jffs2/src/dir-rtems.c @ 0ec9bbc

Last change on this file since 0ec9bbc was 0ec9bbc, checked in by Linus Torvalds <torvalds@…>, on Jun 10, 2016 at 2:51:30 PM

vfs: make the string hashes salt the hash

We always mixed in the parent pointer into the dentry name hash, but we
did it late at lookup time. It turns out that we can simplify that
lookup-time action by salting the hash with the parent pointer early
instead of late.

A few other users of our string hashes also wanted to mix in their own
pointers into the hash, and those are updated to use the same mechanism.

Hash users that don't have any particular initial salt can just use the
NULL pointer as a no-salt.

Cc: Vegard Nossum <vegard.nossum@…>
Cc: George Spelvin <linux@…>
Cc: Al Viro <viro@…>
Signed-off-by: Linus Torvalds <torvalds@…>

  • Property mode set to 100644
File size: 10.9 KB
Line 
1#include "rtems-jffs2-config.h"
2
3/*
4 * JFFS2 -- Journalling Flash File System, Version 2.
5 *
6 * Copyright © 2001-2003 Free Software Foundation, Inc.
7 * Copyright © 2001-2007 Red Hat, Inc.
8 * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
9 * Copyright © 2013 embedded brains GmbH <rtems@embedded-brains.de>
10 *
11 * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
12 *
13 * Port to the RTEMS by embedded brains GmbH.
14 *
15 * For licensing information, see the file 'LICENCE' in this directory.
16 *
17 * $Id: dir-ecos.c,v 1.11 2005/02/08 19:36:27 lunn Exp $
18 *
19 */
20
21#include <linux/kernel.h>
22#include <linux/crc32.h>
23#include "nodelist.h"
24
25/***********************************************************************/
26
27/* Takes length argument because it can be either NUL-terminated or '/'-terminated */
28struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *name, size_t namelen)
29{
30        struct jffs2_inode_info *dir_f;
31        struct jffs2_full_dirent *fd = NULL, *fd_list;
32        uint32_t ino = 0;
33        uint32_t hash = full_name_hash(NULL, name, namelen);
34        struct _inode *inode = NULL;
35
36        D1(printk("jffs2_lookup()\n"));
37
38        dir_f = JFFS2_INODE_INFO(dir_i);
39
40        mutex_lock(&dir_f->sem);
41
42        /* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */
43        for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= hash; fd_list = fd_list->next) {
44                if (fd_list->nhash == hash &&
45                    (!fd || fd_list->version > fd->version) &&
46                    strlen((char *)fd_list->name) == namelen &&
47                    !strncmp((char *)fd_list->name, (char *)name, namelen)) {
48                        fd = fd_list;
49                }
50        }
51        if (fd)
52                ino = fd->ino;
53        mutex_unlock(&dir_f->sem);
54        if (ino) {
55                inode = jffs2_iget(dir_i->i_sb, ino);
56                if (IS_ERR(inode)) {
57                        printk("jffs2_iget() failed for ino #%lu\n", ino);
58                        return inode;
59                } else {
60                        inode->i_fd = fd;
61                }
62        }
63
64        return inode;
65}
66
67/***********************************************************************/
68
69
70
71int jffs2_create(struct _inode *dir_i, const char *d_name, size_t d_namelen, int mode)
72{
73        struct jffs2_raw_inode *ri;
74        struct jffs2_inode_info *f, *dir_f;
75        struct jffs2_sb_info *c;
76        struct _inode *inode;
77        int ret;
78        struct qstr qstr;
79
80        qstr.name = d_name;
81        qstr.len = d_namelen;
82
83        ri = jffs2_alloc_raw_inode();
84        if (!ri)
85                return -ENOMEM;
86
87        c = JFFS2_SB_INFO(dir_i->i_sb);
88
89        D1(printk(KERN_DEBUG "jffs2_create()\n"));
90
91        inode = jffs2_new_inode(dir_i, mode, ri);
92
93        if (IS_ERR(inode)) {
94                D1(printk(KERN_DEBUG "jffs2_new_inode() failed\n"));
95                jffs2_free_raw_inode(ri);
96                return PTR_ERR(inode);
97        }
98
99        f = JFFS2_INODE_INFO(inode);
100        dir_f = JFFS2_INODE_INFO(dir_i);
101
102        ret = jffs2_do_create(c, dir_f, f, ri, &qstr);
103
104        if (ret) {
105                inode->i_nlink = 0;
106                jffs2_iput(inode);
107                jffs2_free_raw_inode(ri);
108                return ret;
109        }
110
111        dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime));
112
113        jffs2_free_raw_inode(ri);
114
115        D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d)\n",
116                  inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->pino_nlink));
117        jffs2_iput(inode);
118        return 0;
119}
120
121/***********************************************************************/
122
123
124int jffs2_unlink(struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name, size_t d_namelen)
125{
126        struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb);
127        struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
128        struct jffs2_inode_info *dead_f = JFFS2_INODE_INFO(d_inode);
129        int ret;
130
131        ret = jffs2_do_unlink(c, dir_f, (const char *)d_name,
132                               d_namelen, dead_f, get_seconds());
133        if (dead_f->inocache)
134                d_inode->i_nlink = dead_f->inocache->pino_nlink;
135        return ret;
136}
137/***********************************************************************/
138
139
140int jffs2_link (struct _inode *old_d_inode, struct _inode *dir_i, const unsigned char *d_name, size_t d_namelen)
141{
142        struct jffs2_sb_info *c = JFFS2_SB_INFO(old_d_inode->i_sb);
143        struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_d_inode);
144        struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
145        int ret;
146
147        /* XXX: This is ugly */
148        uint8_t type = (old_d_inode->i_mode & S_IFMT) >> 12;
149        if (!type) type = DT_REG;
150
151        ret = jffs2_do_link(c, dir_f, f->inocache->ino, type,
152                            (const char * )d_name,
153                            d_namelen, get_seconds());
154
155        if (!ret) {
156                mutex_lock(&f->sem);
157                old_d_inode->i_nlink = ++f->inocache->pino_nlink;
158                mutex_unlock(&f->sem);
159        }
160        return ret;
161}
162
163/***********************************************************************/
164
165int jffs2_mknod(
166        struct _inode *dir_i,
167        const unsigned char *d_name,
168        size_t d_namelen,
169        int mode,
170        const unsigned char *data,
171        size_t datalen
172)
173{
174        struct jffs2_inode_info *f, *dir_f;
175        struct jffs2_sb_info *c;
176        struct _inode *inode;
177        struct jffs2_raw_inode *ri;
178        struct jffs2_raw_dirent *rd;
179        struct jffs2_full_dnode *fn;
180        struct jffs2_full_dirent *fd;
181        uint32_t alloclen;
182        int ret;
183
184        /* FIXME: If you care. We'd need to use frags for the data
185           if it grows much more than this */
186        if (datalen > 254)
187                return -ENAMETOOLONG;
188
189        ri = jffs2_alloc_raw_inode();
190
191        if (!ri)
192                return -ENOMEM;
193
194        c = JFFS2_SB_INFO(dir_i->i_sb);
195
196        /* Try to reserve enough space for both node and dirent.
197         * Just the node will do for now, though
198         */
199        ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &alloclen,
200                                  ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
201
202        if (ret) {
203                jffs2_free_raw_inode(ri);
204                return ret;
205        }
206
207        inode = jffs2_new_inode(dir_i, mode, ri);
208
209        if (IS_ERR(inode)) {
210                jffs2_free_raw_inode(ri);
211                jffs2_complete_reservation(c);
212                return PTR_ERR(inode);
213        }
214
215        f = JFFS2_INODE_INFO(inode);
216
217        inode->i_size = datalen;
218        ri->isize = ri->dsize = ri->csize = cpu_to_je32(inode->i_size);
219        ri->totlen = cpu_to_je32(sizeof(*ri) + inode->i_size);
220        ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
221
222        ri->compr = JFFS2_COMPR_NONE;
223        ri->data_crc = cpu_to_je32(crc32(0, data, datalen));
224        ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
225
226        fn = jffs2_write_dnode(c, f, ri, data, datalen, ALLOC_NORMAL);
227
228        jffs2_free_raw_inode(ri);
229
230        if (IS_ERR(fn)) {
231                /* Eeek. Wave bye bye */
232                mutex_unlock(&f->sem);
233                jffs2_complete_reservation(c);
234                ret = PTR_ERR(fn);
235                goto fail;
236        }
237
238        if (S_ISLNK(mode)) {
239                /* We use f->target field to store the target path. */
240                f->target = kmemdup(data, datalen + 1, GFP_KERNEL);
241                if (!f->target) {
242                        pr_warn("Can't allocate %d bytes of memory\n", datalen + 1);
243                        mutex_unlock(&f->sem);
244                        jffs2_complete_reservation(c);
245                        ret = -ENOMEM;
246                        goto fail;
247                }
248
249                jffs2_dbg(1, "%s(): symlink's target '%s' cached\n",
250                          __func__, (char *)f->target);
251        }
252
253        /* No data here. Only a metadata node, which will be
254           obsoleted by the first data write
255        */
256        f->metadata = fn;
257        mutex_unlock(&f->sem);
258
259        jffs2_complete_reservation(c);
260
261        ret = jffs2_reserve_space(c, sizeof(*rd)+d_namelen, &alloclen,
262                                  ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(d_namelen));
263        if (ret)
264                goto fail;
265
266        rd = jffs2_alloc_raw_dirent();
267        if (!rd) {
268                /* Argh. Now we treat it like a normal delete */
269                jffs2_complete_reservation(c);
270                ret = -ENOMEM;
271                goto fail;
272        }
273
274        dir_f = JFFS2_INODE_INFO(dir_i);
275        mutex_lock(&dir_f->sem);
276
277        rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
278        rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
279        rd->totlen = cpu_to_je32(sizeof(*rd) + d_namelen);
280        rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
281
282        rd->pino = cpu_to_je32(dir_i->i_ino);
283        rd->version = cpu_to_je32(++dir_f->highest_version);
284        rd->ino = cpu_to_je32(inode->i_ino);
285        rd->mctime = cpu_to_je32(get_seconds());
286        rd->nsize = d_namelen;
287
288        /* XXX: This is ugly. */
289        rd->type = (mode & S_IFMT) >> 12;
290
291        rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
292        rd->name_crc = cpu_to_je32(crc32(0, d_name, d_namelen));
293
294        fd = jffs2_write_dirent(c, dir_f, rd, d_name, d_namelen, ALLOC_NORMAL);
295
296        if (IS_ERR(fd)) {
297                /* dirent failed to write. Delete the inode normally
298                   as if it were the final unlink() */
299                jffs2_complete_reservation(c);
300                jffs2_free_raw_dirent(rd);
301                mutex_unlock(&dir_f->sem);
302                ret = PTR_ERR(fd);
303                goto fail;
304        }
305
306        dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
307
308        jffs2_free_raw_dirent(rd);
309
310        /* Link the fd into the inode's list, obsoleting an old
311           one if necessary. */
312        jffs2_add_fd_to_list(c, fd, &dir_f->dents);
313
314        mutex_unlock(&dir_f->sem);
315        jffs2_complete_reservation(c);
316
317 fail:
318        jffs2_iput(inode);
319
320        return ret;
321}
322
323int jffs2_rmdir (struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name, size_t d_namelen)
324{
325        struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode);
326        struct jffs2_full_dirent *fd;
327
328        for (fd = f->dents ; fd; fd = fd->next) {
329                if (fd->ino)
330                        return -ENOTEMPTY;
331        }
332        return jffs2_unlink(dir_i, d_inode, d_name, d_namelen);
333}
334
335int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsigned char *old_d_name, size_t old_d_namelen,
336                  struct _inode *new_dir_i, const unsigned char *new_d_name, size_t new_d_namelen)
337{
338        int ret;
339        struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb);
340        struct jffs2_inode_info *victim_f = NULL;
341        uint8_t type;
342        uint32_t now;
343
344#if 0 /* FIXME -- this really doesn't belong in individual file systems.
345         The fileio code ought to do this for us, or at least part of it */
346        if (new_dentry->d_inode) {
347                if (S_ISDIR(d_inode->i_mode) &&
348                    !S_ISDIR(new_dentry->d_inode->i_mode)) {
349                        /* Cannot rename directory over non-directory */
350                        return -EINVAL;
351                }
352
353                victim_f = JFFS2_INODE_INFO(new_dentry->d_inode);
354
355                if (S_ISDIR(new_dentry->d_inode->i_mode)) {
356                        struct jffs2_full_dirent *fd;
357
358                        if (!S_ISDIR(d_inode->i_mode)) {
359                                /* Cannot rename non-directory over directory */
360                                return -EINVAL;
361                        }
362                        mutex_lock(&victim_f->sem);
363                        for (fd = victim_f->dents; fd; fd = fd->next) {
364                                if (fd->ino) {
365                                        mutex_unlock(&victim_f->sem);
366                                        return -ENOTEMPTY;
367                                }
368                        }
369                        mutex_unlock(&victim_f->sem);
370                }
371        }
372#endif
373
374        /* XXX: We probably ought to alloc enough space for
375           both nodes at the same time. Writing the new link,
376           then getting -ENOSPC, is quite bad :)
377        */
378
379        /* Make a hard link */
380
381        /* XXX: This is ugly */
382        type = (d_inode->i_mode & S_IFMT) >> 12;
383        if (!type) type = DT_REG;
384
385        now = get_seconds();
386        ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i),
387                            d_inode->i_ino, type,
388                            (const char *)new_d_name,
389                            new_d_namelen, now);
390
391        if (ret)
392                return ret;
393
394        if (victim_f) {
395                /* There was a victim. Kill it off nicely */
396                /* Don't oops if the victim was a dirent pointing to an
397                   inode which didn't exist. */
398                if (victim_f->inocache) {
399                        mutex_lock(&victim_f->sem);
400                        victim_f->inocache->pino_nlink--;
401                        mutex_unlock(&victim_f->sem);
402                }
403        }
404
405        /* Unlink the original */
406        ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i),
407                              (const char *)old_d_name,
408                              old_d_namelen, NULL, now);
409
410        if (ret) {
411                /* Oh shit. We really ought to make a single node which can do both atomically */
412                struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode);
413                mutex_lock(&f->sem);
414                if (f->inocache)
415                        d_inode->i_nlink = f->inocache->pino_nlink++;
416                mutex_unlock(&f->sem);
417
418                printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret);
419        }
420        return ret;
421}
Note: See TracBrowser for help on using the repository browser.