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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * JFFS2 -- Journalling Flash File System, Version 2.
3
 *
4
 * Copyright (C) 2001 Red Hat, Inc.
5
 *
6
 * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
7
 *
8
 * The original JFFS, from which the design for JFFS2 was derived,
9
 * was designed and implemented by Axis Communications AB.
10
 *
11
 * The contents of this file are subject to the Red Hat eCos Public
12
 * License Version 1.1 (the "Licence"); you may not use this file
13
 * except in compliance with the Licence.  You may obtain a copy of
14
 * the Licence at http://www.redhat.com/
15
 *
16
 * Software distributed under the Licence is distributed on an "AS IS"
17
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
18
 * See the Licence for the specific language governing rights and
19
 * limitations under the Licence.
20
 *
21
 * The Original Code is JFFS2 - Journalling Flash File System, version 2
22
 *
23
 * Alternatively, the contents of this file may be used under the
24
 * terms of the GNU General Public License version 2 (the "GPL"), in
25
 * which case the provisions of the GPL are applicable instead of the
26
 * above.  If you wish to allow the use of your version of this file
27
 * only under the terms of the GPL and not to allow others to use your
28
 * version of this file under the RHEPL, indicate your decision by
29
 * deleting the provisions above and replace them with the notice and
30
 * other provisions required by the GPL.  If you do not delete the
31
 * provisions above, a recipient may use your version of this file
32
 * under either the RHEPL or the GPL.
33
 *
34
 * $Id: dir.c,v 1.1.1.1 2004-04-15 01:11:03 phoenix Exp $
35
 *
36
 */
37
 
38
#include <linux/kernel.h>
39
#include <linux/slab.h>
40
#include <linux/fs.h>
41
#include <linux/mtd/compatmac.h> /* For completion */
42
#include <linux/jffs2.h>
43
#include <linux/jffs2_fs_i.h>
44
#include <linux/jffs2_fs_sb.h>
45
#include "nodelist.h"
46
#include <linux/crc32.h>
47
 
48
static int jffs2_readdir (struct file *, void *, filldir_t);
49
 
50
static int jffs2_create (struct inode *,struct dentry *,int);
51
static struct dentry *jffs2_lookup (struct inode *,struct dentry *);
52
static int jffs2_link (struct dentry *,struct inode *,struct dentry *);
53
static int jffs2_unlink (struct inode *,struct dentry *);
54
static int jffs2_symlink (struct inode *,struct dentry *,const char *);
55
static int jffs2_mkdir (struct inode *,struct dentry *,int);
56
static int jffs2_rmdir (struct inode *,struct dentry *);
57
static int jffs2_mknod (struct inode *,struct dentry *,int,int);
58
static int jffs2_rename (struct inode *, struct dentry *,
59
                        struct inode *, struct dentry *);
60
 
61
struct file_operations jffs2_dir_operations =
62
{
63
        read:           generic_read_dir,
64
        readdir:        jffs2_readdir,
65
        ioctl:          jffs2_ioctl,
66
        fsync:          jffs2_null_fsync
67
};
68
 
69
 
70
struct inode_operations jffs2_dir_inode_operations =
71
{
72
        create:         jffs2_create,
73
        lookup:         jffs2_lookup,
74
        link:           jffs2_link,
75
        unlink:         jffs2_unlink,
76
        symlink:        jffs2_symlink,
77
        mkdir:          jffs2_mkdir,
78
        rmdir:          jffs2_rmdir,
79
        mknod:          jffs2_mknod,
80
        rename:         jffs2_rename,
81
        setattr:        jffs2_setattr,
82
};
83
 
84
/***********************************************************************/
85
 
86
 
87
/* We keep the dirent list sorted in increasing order of name hash,
88
   and we use the same hash function as the dentries. Makes this
89
   nice and simple
90
*/
91
static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target)
92
{
93
        struct jffs2_inode_info *dir_f;
94
        struct jffs2_sb_info *c;
95
        struct jffs2_full_dirent *fd = NULL, *fd_list;
96
        __u32 ino = 0;
97
        struct inode *inode = NULL;
98
 
99
        D1(printk(KERN_DEBUG "jffs2_lookup()\n"));
100
 
101
        dir_f = JFFS2_INODE_INFO(dir_i);
102
        c = JFFS2_SB_INFO(dir_i->i_sb);
103
 
104
        down(&dir_f->sem);
105
 
106
        /* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */
107
        for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= target->d_name.hash; fd_list = fd_list->next) {
108
                if (fd_list->nhash == target->d_name.hash &&
109
                    (!fd || fd_list->version > fd->version) &&
110
                    strlen(fd_list->name) == target->d_name.len &&
111
                    !strncmp(fd_list->name, target->d_name.name, target->d_name.len)) {
112
                        fd = fd_list;
113
                }
114
        }
115
        if (fd)
116
                ino = fd->ino;
117
        up(&dir_f->sem);
118
        if (ino) {
119
                inode = iget(dir_i->i_sb, ino);
120
                if (!inode) {
121
                        printk(KERN_WARNING "iget() failed for ino #%u\n", ino);
122
                        return (ERR_PTR(-EIO));
123
                }
124
        }
125
 
126
        d_add(target, inode);
127
 
128
        return NULL;
129
}
130
 
131
/***********************************************************************/
132
 
133
 
134
static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
135
{
136
        struct jffs2_inode_info *f;
137
        struct jffs2_sb_info *c;
138
        struct inode *inode = filp->f_dentry->d_inode;
139
        struct jffs2_full_dirent *fd;
140
        unsigned long offset, curofs;
141
 
142
        D1(printk(KERN_DEBUG "jffs2_readdir() for dir_i #%lu\n", filp->f_dentry->d_inode->i_ino));
143
 
144
        f = JFFS2_INODE_INFO(inode);
145
        c = JFFS2_SB_INFO(inode->i_sb);
146
 
147
        offset = filp->f_pos;
148
 
149
        if (offset == 0) {
150
                D1(printk(KERN_DEBUG "Dirent 0: \".\", ino #%lu\n", inode->i_ino));
151
                if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0)
152
                        goto out;
153
                offset++;
154
        }
155
        if (offset == 1) {
156
                D1(printk(KERN_DEBUG "Dirent 1: \"..\", ino #%lu\n", filp->f_dentry->d_parent->d_inode->i_ino));
157
                if (filldir(dirent, "..", 2, 1, filp->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
158
                        goto out;
159
                offset++;
160
        }
161
 
162
        curofs=1;
163
        down(&f->sem);
164
        for (fd = f->dents; fd; fd = fd->next) {
165
 
166
                curofs++;
167
                /* First loop: curofs = 2; offset = 2 */
168
                if (curofs < offset) {
169
                        D2(printk(KERN_DEBUG "Skipping dirent: \"%s\", ino #%u, type %d, because curofs %ld < offset %ld\n",
170
                                  fd->name, fd->ino, fd->type, curofs, offset));
171
                        continue;
172
                }
173
                if (!fd->ino) {
174
                        D2(printk(KERN_DEBUG "Skipping deletion dirent \"%s\"\n", fd->name));
175
                        offset++;
176
                        continue;
177
                }
178
                D2(printk(KERN_DEBUG "Dirent %ld: \"%s\", ino #%u, type %d\n", offset, fd->name, fd->ino, fd->type));
179
                if (filldir(dirent, fd->name, strlen(fd->name), offset, fd->ino, fd->type) < 0)
180
                        break;
181
                offset++;
182
        }
183
        up(&f->sem);
184
 out:
185
        filp->f_pos = offset;
186
        return 0;
187
}
188
 
189
/***********************************************************************/
190
 
191
static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode)
192
{
193
        struct jffs2_inode_info *f, *dir_f;
194
        struct jffs2_sb_info *c;
195
        struct inode *inode;
196
        struct jffs2_raw_inode *ri;
197
        struct jffs2_raw_dirent *rd;
198
        struct jffs2_full_dnode *fn;
199
        struct jffs2_full_dirent *fd;
200
        int namelen;
201
        __u32 alloclen, phys_ofs;
202
        __u32 writtenlen;
203
        int ret;
204
 
205
        ri = jffs2_alloc_raw_inode();
206
        if (!ri)
207
                return -ENOMEM;
208
 
209
        c = JFFS2_SB_INFO(dir_i->i_sb);
210
 
211
        D1(printk(KERN_DEBUG "jffs2_create()\n"));
212
 
213
        /* Try to reserve enough space for both node and dirent.
214
         * Just the node will do for now, though
215
         */
216
        namelen = dentry->d_name.len;
217
        ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL);
218
        D1(printk(KERN_DEBUG "jffs2_create(): reserved 0x%x bytes\n", alloclen));
219
        if (ret) {
220
                jffs2_free_raw_inode(ri);
221
                return ret;
222
        }
223
 
224
        inode = jffs2_new_inode(dir_i, mode, ri);
225
 
226
        if (IS_ERR(inode)) {
227
                D1(printk(KERN_DEBUG "jffs2_new_inode() failed\n"));
228
                jffs2_free_raw_inode(ri);
229
                jffs2_complete_reservation(c);
230
                return PTR_ERR(inode);
231
        }
232
 
233
        inode->i_op = &jffs2_file_inode_operations;
234
        inode->i_fop = &jffs2_file_operations;
235
        inode->i_mapping->a_ops = &jffs2_file_address_operations;
236
        inode->i_mapping->nrpages = 0;
237
 
238
        f = JFFS2_INODE_INFO(inode);
239
 
240
        ri->data_crc = 0;
241
        ri->node_crc = crc32(0, ri, sizeof(*ri)-8);
242
 
243
        fn = jffs2_write_dnode(inode, ri, NULL, 0, phys_ofs, &writtenlen);
244
        D1(printk(KERN_DEBUG "jffs2_create created file with mode 0x%x\n", ri->mode));
245
        jffs2_free_raw_inode(ri);
246
 
247
        if (IS_ERR(fn)) {
248
                D1(printk(KERN_DEBUG "jffs2_write_dnode() failed\n"));
249
                /* Eeek. Wave bye bye */
250
                up(&f->sem);
251
                jffs2_complete_reservation(c);
252
                jffs2_clear_inode(inode);
253
                return PTR_ERR(fn);
254
        }
255
        /* No data here. Only a metadata node, which will be
256
           obsoleted by the first data write
257
        */
258
        f->metadata = fn;
259
 
260
        /* Work out where to put the dirent node now. */
261
        writtenlen = PAD(writtenlen);
262
        phys_ofs += writtenlen;
263
        alloclen -= writtenlen;
264
        up(&f->sem);
265
 
266
        if (alloclen < sizeof(*rd)+namelen) {
267
                /* Not enough space left in this chunk. Get some more */
268
                jffs2_complete_reservation(c);
269
                ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL);
270
 
271
                if (ret) {
272
                        /* Eep. */
273
                        D1(printk(KERN_DEBUG "jffs2_reserve_space() for dirent failed\n"));
274
                        jffs2_clear_inode(inode);
275
                        return ret;
276
                }
277
        }
278
 
279
        rd = jffs2_alloc_raw_dirent();
280
        if (!rd) {
281
                /* Argh. Now we treat it like a normal delete */
282
                jffs2_complete_reservation(c);
283
                jffs2_clear_inode(inode);
284
                return -ENOMEM;
285
        }
286
 
287
        dir_f = JFFS2_INODE_INFO(dir_i);
288
        down(&dir_f->sem);
289
 
290
        rd->magic = JFFS2_MAGIC_BITMASK;
291
        rd->nodetype = JFFS2_NODETYPE_DIRENT;
292
        rd->totlen = sizeof(*rd) + namelen;
293
        rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4);
294
 
295
        rd->pino = dir_i->i_ino;
296
        rd->version = ++dir_f->highest_version;
297
        rd->ino = inode->i_ino;
298
        rd->mctime = CURRENT_TIME;
299
        rd->nsize = namelen;
300
        rd->type = DT_REG;
301
        rd->node_crc = crc32(0, rd, sizeof(*rd)-8);
302
        rd->name_crc = crc32(0, dentry->d_name.name, namelen);
303
 
304
        fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen);
305
 
306
        jffs2_complete_reservation(c);
307
 
308
        if (IS_ERR(fd)) {
309
                /* dirent failed to write. Delete the inode normally
310
                   as if it were the final unlink() */
311
                jffs2_free_raw_dirent(rd);
312
                up(&dir_f->sem);
313
                jffs2_clear_inode(inode);
314
                return PTR_ERR(fd);
315
        }
316
 
317
        dir_i->i_mtime = dir_i->i_ctime = rd->mctime;
318
 
319
        jffs2_free_raw_dirent(rd);
320
 
321
        /* Link the fd into the inode's list, obsoleting an old
322
           one if necessary. */
323
        jffs2_add_fd_to_list(c, fd, &dir_f->dents);
324
        up(&dir_f->sem);
325
 
326
        d_instantiate(dentry, inode);
327
 
328
        D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld\n",
329
                  inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink, inode->i_mapping->nrpages));
330
        return 0;
331
}
332
 
333
/***********************************************************************/
334
 
335
static int jffs2_do_unlink(struct inode *dir_i, struct dentry *dentry, int rename)
336
{
337
        struct jffs2_inode_info *dir_f, *f;
338
        struct jffs2_sb_info *c;
339
        struct jffs2_raw_dirent *rd;
340
        struct jffs2_full_dirent *fd;
341
        __u32 alloclen, phys_ofs;
342
        int ret;
343
 
344
        c = JFFS2_SB_INFO(dir_i->i_sb);
345
 
346
        rd = jffs2_alloc_raw_dirent();
347
        if (!rd)
348
                return -ENOMEM;
349
 
350
        ret = jffs2_reserve_space(c, sizeof(*rd)+dentry->d_name.len, &phys_ofs, &alloclen, ALLOC_DELETION);
351
        if (ret) {
352
                jffs2_free_raw_dirent(rd);
353
                return ret;
354
        }
355
 
356
        dir_f = JFFS2_INODE_INFO(dir_i);
357
        down(&dir_f->sem);
358
 
359
        /* Build a deletion node */
360
        rd->magic = JFFS2_MAGIC_BITMASK;
361
        rd->nodetype = JFFS2_NODETYPE_DIRENT;
362
        rd->totlen = sizeof(*rd) + dentry->d_name.len;
363
        rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4);
364
 
365
        rd->pino = dir_i->i_ino;
366
        rd->version = ++dir_f->highest_version;
367
        rd->ino = 0;
368
        rd->mctime = CURRENT_TIME;
369
        rd->nsize = dentry->d_name.len;
370
        rd->type = DT_UNKNOWN;
371
        rd->node_crc = crc32(0, rd, sizeof(*rd)-8);
372
        rd->name_crc = crc32(0, dentry->d_name.name, dentry->d_name.len);
373
 
374
        fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, dentry->d_name.len, phys_ofs, NULL);
375
 
376
        jffs2_complete_reservation(c);
377
        jffs2_free_raw_dirent(rd);
378
 
379
        if (IS_ERR(fd)) {
380
                up(&dir_f->sem);
381
                return PTR_ERR(fd);
382
        }
383
 
384
        /* File it. This will mark the old one obsolete. */
385
        jffs2_add_fd_to_list(c, fd, &dir_f->dents);
386
        up(&dir_f->sem);
387
 
388
        if (!rename) {
389
                f = JFFS2_INODE_INFO(dentry->d_inode);
390
                down(&f->sem);
391
 
392
                while (f->dents) {
393
                        /* There can be only deleted ones */
394
                        fd = f->dents;
395
 
396
                        f->dents = fd->next;
397
 
398
                        if (fd->ino) {
399
                                printk(KERN_WARNING "Deleting inode #%u with active dentry \"%s\"->ino #%u\n",
400
                                       f->inocache->ino, fd->name, fd->ino);
401
                        } else {
402
                                D1(printk(KERN_DEBUG "Removing deletion dirent for \"%s\" from dir ino #%u\n", fd->name, f->inocache->ino));
403
                        }
404
                        jffs2_mark_node_obsolete(c, fd->raw);
405
                        jffs2_free_full_dirent(fd);
406
                }
407
                /* Don't oops on unlinking a bad inode */
408
                if (f->inocache)
409
                        f->inocache->nlink--;
410
                dentry->d_inode->i_nlink--;
411
                up(&f->sem);
412
        }
413
 
414
        return 0;
415
}
416
 
417
static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry)
418
{
419
        return jffs2_do_unlink(dir_i, dentry, 0);
420
}
421
/***********************************************************************/
422
 
423
static int jffs2_do_link (struct dentry *old_dentry, struct inode *dir_i, struct dentry *dentry, int rename)
424
{
425
        struct jffs2_inode_info *dir_f, *f;
426
        struct jffs2_sb_info *c;
427
        struct jffs2_raw_dirent *rd;
428
        struct jffs2_full_dirent *fd;
429
        __u32 alloclen, phys_ofs;
430
        int ret;
431
 
432
        c = JFFS2_SB_INFO(dir_i->i_sb);
433
 
434
        rd = jffs2_alloc_raw_dirent();
435
        if (!rd)
436
                return -ENOMEM;
437
 
438
        ret = jffs2_reserve_space(c, sizeof(*rd)+dentry->d_name.len, &phys_ofs, &alloclen, ALLOC_NORMAL);
439
        if (ret) {
440
                jffs2_free_raw_dirent(rd);
441
                return ret;
442
        }
443
 
444
        dir_f = JFFS2_INODE_INFO(dir_i);
445
        down(&dir_f->sem);
446
 
447
        /* Build a deletion node */
448
        rd->magic = JFFS2_MAGIC_BITMASK;
449
        rd->nodetype = JFFS2_NODETYPE_DIRENT;
450
        rd->totlen = sizeof(*rd) + dentry->d_name.len;
451
        rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4);
452
 
453
        rd->pino = dir_i->i_ino;
454
        rd->version = ++dir_f->highest_version;
455
        rd->ino = old_dentry->d_inode->i_ino;
456
        rd->mctime = CURRENT_TIME;
457
        rd->nsize = dentry->d_name.len;
458
 
459
        /* XXX: This is ugly. */
460
        rd->type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12;
461
        if (!rd->type) rd->type = DT_REG;
462
 
463
        rd->node_crc = crc32(0, rd, sizeof(*rd)-8);
464
        rd->name_crc = crc32(0, dentry->d_name.name, dentry->d_name.len);
465
 
466
        fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, dentry->d_name.len, phys_ofs, NULL);
467
 
468
        jffs2_complete_reservation(c);
469
        jffs2_free_raw_dirent(rd);
470
 
471
        if (IS_ERR(fd)) {
472
                up(&dir_f->sem);
473
                return PTR_ERR(fd);
474
        }
475
 
476
        /* File it. This will mark the old one obsolete. */
477
        jffs2_add_fd_to_list(c, fd, &dir_f->dents);
478
        up(&dir_f->sem);
479
 
480
        if (!rename) {
481
                f = JFFS2_INODE_INFO(old_dentry->d_inode);
482
                down(&f->sem);
483
                old_dentry->d_inode->i_nlink = ++f->inocache->nlink;
484
                up(&f->sem);
485
        }
486
        return 0;
487
}
488
 
489
static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct dentry *dentry)
490
{
491
        int ret;
492
 
493
        /* Can't link a bad inode. */
494
        if (!JFFS2_INODE_INFO(old_dentry->d_inode)->inocache)
495
                return -EIO;
496
 
497
        if (S_ISDIR(old_dentry->d_inode->i_mode))
498
                return -EPERM;
499
 
500
        ret = jffs2_do_link(old_dentry, dir_i, dentry, 0);
501
        if (!ret) {
502
                d_instantiate(dentry, old_dentry->d_inode);
503
                atomic_inc(&old_dentry->d_inode->i_count);
504
        }
505
        return ret;
506
}
507
 
508
/***********************************************************************/
509
 
510
static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char *target)
511
{
512
        struct jffs2_inode_info *f, *dir_f;
513
        struct jffs2_sb_info *c;
514
        struct inode *inode;
515
        struct jffs2_raw_inode *ri;
516
        struct jffs2_raw_dirent *rd;
517
        struct jffs2_full_dnode *fn;
518
        struct jffs2_full_dirent *fd;
519
        int namelen;
520
        __u32 alloclen, phys_ofs;
521
        __u32 writtenlen;
522
        int ret;
523
 
524
        /* FIXME: If you care. We'd need to use frags for the target
525
           if it grows much more than this */
526
        if (strlen(target) > 254)
527
                return -EINVAL;
528
 
529
        ri = jffs2_alloc_raw_inode();
530
 
531
        if (!ri)
532
                return -ENOMEM;
533
 
534
        c = JFFS2_SB_INFO(dir_i->i_sb);
535
 
536
        /* Try to reserve enough space for both node and dirent.
537
         * Just the node will do for now, though
538
         */
539
        namelen = dentry->d_name.len;
540
        ret = jffs2_reserve_space(c, sizeof(*ri) + strlen(target), &phys_ofs, &alloclen, ALLOC_NORMAL);
541
 
542
        if (ret) {
543
                jffs2_free_raw_inode(ri);
544
                return ret;
545
        }
546
 
547
        inode = jffs2_new_inode(dir_i, S_IFLNK | S_IRWXUGO, ri);
548
 
549
        if (IS_ERR(inode)) {
550
                jffs2_free_raw_inode(ri);
551
                jffs2_complete_reservation(c);
552
                return PTR_ERR(inode);
553
        }
554
 
555
        inode->i_op = &jffs2_symlink_inode_operations;
556
 
557
        f = JFFS2_INODE_INFO(inode);
558
 
559
        inode->i_size = ri->isize = ri->dsize = ri->csize = strlen(target);
560
        ri->totlen = sizeof(*ri) + ri->dsize;
561
        ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4);
562
 
563
        ri->compr = JFFS2_COMPR_NONE;
564
        ri->data_crc = crc32(0, target, strlen(target));
565
        ri->node_crc = crc32(0, ri, sizeof(*ri)-8);
566
 
567
        fn = jffs2_write_dnode(inode, ri, target, strlen(target), phys_ofs, &writtenlen);
568
 
569
        jffs2_free_raw_inode(ri);
570
 
571
        if (IS_ERR(fn)) {
572
                /* Eeek. Wave bye bye */
573
                up(&f->sem);
574
                jffs2_complete_reservation(c);
575
                jffs2_clear_inode(inode);
576
                return PTR_ERR(fn);
577
        }
578
        /* No data here. Only a metadata node, which will be
579
           obsoleted by the first data write
580
        */
581
        f->metadata = fn;
582
        up(&f->sem);
583
 
584
        /* Work out where to put the dirent node now. */
585
        writtenlen = (writtenlen+3)&~3;
586
        phys_ofs += writtenlen;
587
        alloclen -= writtenlen;
588
 
589
        if (alloclen < sizeof(*rd)+namelen) {
590
                /* Not enough space left in this chunk. Get some more */
591
                jffs2_complete_reservation(c);
592
                ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL);
593
                if (ret) {
594
                        /* Eep. */
595
                        jffs2_clear_inode(inode);
596
                        return ret;
597
                }
598
        }
599
 
600
        rd = jffs2_alloc_raw_dirent();
601
        if (!rd) {
602
                /* Argh. Now we treat it like a normal delete */
603
                jffs2_complete_reservation(c);
604
                jffs2_clear_inode(inode);
605
                return -ENOMEM;
606
        }
607
 
608
        dir_f = JFFS2_INODE_INFO(dir_i);
609
        down(&dir_f->sem);
610
 
611
        rd->magic = JFFS2_MAGIC_BITMASK;
612
        rd->nodetype = JFFS2_NODETYPE_DIRENT;
613
        rd->totlen = sizeof(*rd) + namelen;
614
        rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4);
615
 
616
        rd->pino = dir_i->i_ino;
617
        rd->version = ++dir_f->highest_version;
618
        rd->ino = inode->i_ino;
619
        rd->mctime = CURRENT_TIME;
620
        rd->nsize = namelen;
621
        rd->type = DT_LNK;
622
        rd->node_crc = crc32(0, rd, sizeof(*rd)-8);
623
        rd->name_crc = crc32(0, dentry->d_name.name, namelen);
624
 
625
        fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen);
626
 
627
        jffs2_complete_reservation(c);
628
 
629
        if (IS_ERR(fd)) {
630
                /* dirent failed to write. Delete the inode normally
631
                   as if it were the final unlink() */
632
                jffs2_free_raw_dirent(rd);
633
                up(&dir_f->sem);
634
                jffs2_clear_inode(inode);
635
                return PTR_ERR(fd);
636
        }
637
 
638
        dir_i->i_mtime = dir_i->i_ctime = rd->mctime;
639
 
640
        jffs2_free_raw_dirent(rd);
641
 
642
        /* Link the fd into the inode's list, obsoleting an old
643
           one if necessary. */
644
        jffs2_add_fd_to_list(c, fd, &dir_f->dents);
645
        up(&dir_f->sem);
646
 
647
        d_instantiate(dentry, inode);
648
        return 0;
649
}
650
 
651
 
652
static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
653
{
654
        struct jffs2_inode_info *f, *dir_f;
655
        struct jffs2_sb_info *c;
656
        struct inode *inode;
657
        struct jffs2_raw_inode *ri;
658
        struct jffs2_raw_dirent *rd;
659
        struct jffs2_full_dnode *fn;
660
        struct jffs2_full_dirent *fd;
661
        int namelen;
662
        __u32 alloclen, phys_ofs;
663
        __u32 writtenlen;
664
        int ret;
665
 
666
        mode |= S_IFDIR;
667
 
668
        ri = jffs2_alloc_raw_inode();
669
        if (!ri)
670
                return -ENOMEM;
671
 
672
        c = JFFS2_SB_INFO(dir_i->i_sb);
673
 
674
        /* Try to reserve enough space for both node and dirent.
675
         * Just the node will do for now, though
676
         */
677
        namelen = dentry->d_name.len;
678
        ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL);
679
 
680
        if (ret) {
681
                jffs2_free_raw_inode(ri);
682
                return ret;
683
        }
684
 
685
        inode = jffs2_new_inode(dir_i, mode, ri);
686
 
687
        if (IS_ERR(inode)) {
688
                jffs2_free_raw_inode(ri);
689
                jffs2_complete_reservation(c);
690
                return PTR_ERR(inode);
691
        }
692
 
693
        inode->i_op = &jffs2_dir_inode_operations;
694
        inode->i_fop = &jffs2_dir_operations;
695
 
696
        f = JFFS2_INODE_INFO(inode);
697
 
698
        ri->data_crc = 0;
699
        ri->node_crc = crc32(0, ri, sizeof(*ri)-8);
700
 
701
        fn = jffs2_write_dnode(inode, ri, NULL, 0, phys_ofs, &writtenlen);
702
 
703
        jffs2_free_raw_inode(ri);
704
 
705
        if (IS_ERR(fn)) {
706
                /* Eeek. Wave bye bye */
707
                up(&f->sem);
708
                jffs2_complete_reservation(c);
709
                jffs2_clear_inode(inode);
710
                return PTR_ERR(fn);
711
        }
712
        /* No data here. Only a metadata node, which will be
713
           obsoleted by the first data write
714
        */
715
        f->metadata = fn;
716
        up(&f->sem);
717
 
718
        /* Work out where to put the dirent node now. */
719
        writtenlen = PAD(writtenlen);
720
        phys_ofs += writtenlen;
721
        alloclen -= writtenlen;
722
 
723
        if (alloclen < sizeof(*rd)+namelen) {
724
                /* Not enough space left in this chunk. Get some more */
725
                jffs2_complete_reservation(c);
726
                ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL);
727
                if (ret) {
728
                        /* Eep. */
729
                        jffs2_clear_inode(inode);
730
                        return ret;
731
                }
732
        }
733
 
734
        rd = jffs2_alloc_raw_dirent();
735
        if (!rd) {
736
                /* Argh. Now we treat it like a normal delete */
737
                jffs2_complete_reservation(c);
738
                jffs2_clear_inode(inode);
739
                return -ENOMEM;
740
        }
741
 
742
        dir_f = JFFS2_INODE_INFO(dir_i);
743
        down(&dir_f->sem);
744
 
745
        rd->magic = JFFS2_MAGIC_BITMASK;
746
        rd->nodetype = JFFS2_NODETYPE_DIRENT;
747
        rd->totlen = sizeof(*rd) + namelen;
748
        rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4);
749
 
750
        rd->pino = dir_i->i_ino;
751
        rd->version = ++dir_f->highest_version;
752
        rd->ino = inode->i_ino;
753
        rd->mctime = CURRENT_TIME;
754
        rd->nsize = namelen;
755
        rd->type = DT_DIR;
756
        rd->node_crc = crc32(0, rd, sizeof(*rd)-8);
757
        rd->name_crc = crc32(0, dentry->d_name.name, namelen);
758
 
759
        fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen);
760
 
761
        jffs2_complete_reservation(c);
762
 
763
        if (IS_ERR(fd)) {
764
                /* dirent failed to write. Delete the inode normally
765
                   as if it were the final unlink() */
766
                jffs2_free_raw_dirent(rd);
767
                up(&dir_f->sem);
768
                jffs2_clear_inode(inode);
769
                return PTR_ERR(fd);
770
        }
771
 
772
        dir_i->i_mtime = dir_i->i_ctime = rd->mctime;
773
 
774
        jffs2_free_raw_dirent(rd);
775
 
776
        /* Link the fd into the inode's list, obsoleting an old
777
           one if necessary. */
778
        jffs2_add_fd_to_list(c, fd, &dir_f->dents);
779
        up(&dir_f->sem);
780
 
781
        d_instantiate(dentry, inode);
782
        return 0;
783
}
784
 
785
static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry)
786
{
787
        struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode);
788
        struct jffs2_full_dirent *fd;
789
 
790
        for (fd = f->dents ; fd; fd = fd->next) {
791
                if (fd->ino)
792
                        return -ENOTEMPTY;
793
        }
794
        return jffs2_unlink(dir_i, dentry);
795
}
796
 
797
static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, int rdev)
798
{
799
        struct jffs2_inode_info *f, *dir_f;
800
        struct jffs2_sb_info *c;
801
        struct inode *inode;
802
        struct jffs2_raw_inode *ri;
803
        struct jffs2_raw_dirent *rd;
804
        struct jffs2_full_dnode *fn;
805
        struct jffs2_full_dirent *fd;
806
        int namelen;
807
        unsigned short dev;
808
        int devlen = 0;
809
        __u32 alloclen, phys_ofs;
810
        __u32 writtenlen;
811
        int ret;
812
 
813
        ri = jffs2_alloc_raw_inode();
814
        if (!ri)
815
                return -ENOMEM;
816
 
817
        c = JFFS2_SB_INFO(dir_i->i_sb);
818
 
819
        if (S_ISBLK(mode) || S_ISCHR(mode)) {
820
                dev = (MAJOR(to_kdev_t(rdev)) << 8) | MINOR(to_kdev_t(rdev));
821
                devlen = sizeof(dev);
822
        }
823
 
824
        /* Try to reserve enough space for both node and dirent.
825
         * Just the node will do for now, though
826
         */
827
        namelen = dentry->d_name.len;
828
        ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &phys_ofs, &alloclen, ALLOC_NORMAL);
829
 
830
        if (ret) {
831
                jffs2_free_raw_inode(ri);
832
                return ret;
833
        }
834
 
835
        inode = jffs2_new_inode(dir_i, mode, ri);
836
 
837
        if (IS_ERR(inode)) {
838
                jffs2_free_raw_inode(ri);
839
                jffs2_complete_reservation(c);
840
                return PTR_ERR(inode);
841
        }
842
        inode->i_op = &jffs2_file_inode_operations;
843
        init_special_inode(inode, inode->i_mode, rdev);
844
 
845
        f = JFFS2_INODE_INFO(inode);
846
 
847
        ri->dsize = ri->csize = devlen;
848
        ri->totlen = sizeof(*ri) + ri->csize;
849
        ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4);
850
 
851
        ri->compr = JFFS2_COMPR_NONE;
852
        ri->data_crc = crc32(0, &dev, devlen);
853
        ri->node_crc = crc32(0, ri, sizeof(*ri)-8);
854
 
855
        fn = jffs2_write_dnode(inode, ri, (char *)&dev, devlen, phys_ofs, &writtenlen);
856
 
857
        jffs2_free_raw_inode(ri);
858
 
859
        if (IS_ERR(fn)) {
860
                /* Eeek. Wave bye bye */
861
                up(&f->sem);
862
                jffs2_complete_reservation(c);
863
                jffs2_clear_inode(inode);
864
                return PTR_ERR(fn);
865
        }
866
        /* No data here. Only a metadata node, which will be
867
           obsoleted by the first data write
868
        */
869
        f->metadata = fn;
870
        up(&f->sem);
871
 
872
        /* Work out where to put the dirent node now. */
873
        writtenlen = (writtenlen+3)&~3;
874
        phys_ofs += writtenlen;
875
        alloclen -= writtenlen;
876
 
877
        if (alloclen < sizeof(*rd)+namelen) {
878
                /* Not enough space left in this chunk. Get some more */
879
                jffs2_complete_reservation(c);
880
                ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL);
881
                if (ret) {
882
                        /* Eep. */
883
                        jffs2_clear_inode(inode);
884
                        return ret;
885
                }
886
        }
887
 
888
        rd = jffs2_alloc_raw_dirent();
889
        if (!rd) {
890
                /* Argh. Now we treat it like a normal delete */
891
                jffs2_complete_reservation(c);
892
                jffs2_clear_inode(inode);
893
                return -ENOMEM;
894
        }
895
 
896
        dir_f = JFFS2_INODE_INFO(dir_i);
897
        down(&dir_f->sem);
898
 
899
        rd->magic = JFFS2_MAGIC_BITMASK;
900
        rd->nodetype = JFFS2_NODETYPE_DIRENT;
901
        rd->totlen = sizeof(*rd) + namelen;
902
        rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4);
903
 
904
        rd->pino = dir_i->i_ino;
905
        rd->version = ++dir_f->highest_version;
906
        rd->ino = inode->i_ino;
907
        rd->mctime = CURRENT_TIME;
908
        rd->nsize = namelen;
909
 
910
        /* XXX: This is ugly. */
911
        rd->type = (mode & S_IFMT) >> 12;
912
 
913
        rd->node_crc = crc32(0, rd, sizeof(*rd)-8);
914
        rd->name_crc = crc32(0, dentry->d_name.name, namelen);
915
 
916
        fd = jffs2_write_dirent(dir_i, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen);
917
 
918
        jffs2_complete_reservation(c);
919
 
920
        if (IS_ERR(fd)) {
921
                /* dirent failed to write. Delete the inode normally
922
                   as if it were the final unlink() */
923
                jffs2_free_raw_dirent(rd);
924
                up(&dir_f->sem);
925
                jffs2_clear_inode(inode);
926
                return PTR_ERR(fd);
927
        }
928
 
929
        dir_i->i_mtime = dir_i->i_ctime = rd->mctime;
930
 
931
        jffs2_free_raw_dirent(rd);
932
 
933
        /* Link the fd into the inode's list, obsoleting an old
934
           one if necessary. */
935
        jffs2_add_fd_to_list(c, fd, &dir_f->dents);
936
        up(&dir_f->sem);
937
 
938
        d_instantiate(dentry, inode);
939
 
940
        return 0;
941
}
942
 
943
static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
944
                        struct inode *new_dir_i, struct dentry *new_dentry)
945
{
946
        int ret;
947
        struct jffs2_inode_info *victim_f = NULL;
948
 
949
        /* The VFS will check for us and prevent trying to rename a
950
         * file over a directory and vice versa, but if it's a directory,
951
         * the VFS can't check whether the victim is empty. The filesystem
952
         * needs to do that for itself.
953
         */
954
        if (new_dentry->d_inode) {
955
                victim_f = JFFS2_INODE_INFO(new_dentry->d_inode);
956
                if (S_ISDIR(new_dentry->d_inode->i_mode)) {
957
                        struct jffs2_full_dirent *fd;
958
 
959
                        down(&victim_f->sem);
960
                        for (fd = victim_f->dents; fd; fd = fd->next) {
961
                                if (fd->ino) {
962
                                        up(&victim_f->sem);
963
                                        return -ENOTEMPTY;
964
                                }
965
                        }
966
                        up(&victim_f->sem);
967
                }
968
        }
969
 
970
        /* XXX: We probably ought to alloc enough space for
971
           both nodes at the same time. Writing the new link,
972
           then getting -ENOSPC, is quite bad :)
973
        */
974
 
975
        /* Make a hard link */
976
        ret = jffs2_do_link(old_dentry, new_dir_i, new_dentry, 1);
977
        if (ret)
978
                return ret;
979
 
980
        if (victim_f) {
981
                /* There was a victim. Kill it off nicely */
982
                new_dentry->d_inode->i_nlink--;
983
                /* Don't oops if the victim was a dirent pointing to an
984
                   inode which didn't exist. */
985
                if (victim_f->inocache) {
986
                        down(&victim_f->sem);
987
                        victim_f->inocache->nlink--;
988
                        up(&victim_f->sem);
989
                }
990
        }
991
 
992
        /* Unlink the original */
993
        ret = jffs2_do_unlink(old_dir_i, old_dentry, 1);
994
 
995
        if (ret) {
996
                /* Oh shit. We really ought to make a single node which can do both atomically */
997
                struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode);
998
                down(&f->sem);
999
                if (f->inocache)
1000
                        old_dentry->d_inode->i_nlink = f->inocache->nlink++;
1001
                up(&f->sem);
1002
 
1003
                printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret);
1004
                /* Might as well let the VFS know */
1005
                d_instantiate(new_dentry, old_dentry->d_inode);
1006
                atomic_inc(&old_dentry->d_inode->i_count);
1007
        }
1008
        return ret;
1009
}
1010
 

powered by: WebSVN 2.1.0

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