import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / fs / jffs2 / write.c
1 /*
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: write.c,v 1.30.2.2 2003/11/02 13:51:18 dwmw2 Exp $
35  *
36  */
37
38 #include <linux/kernel.h>
39 #include <linux/fs.h>
40 #include <linux/jffs2.h>
41 #include <linux/mtd/mtd.h>
42 #include "nodelist.h"
43 #include <linux/crc32.h>
44
45 /* jffs2_new_inode: allocate a new inode and inocache, add it to the hash,
46    fill in the raw_inode while you're at it. */
47 struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_inode *ri)
48 {
49         struct inode *inode;
50         struct super_block *sb = dir_i->i_sb;
51         struct jffs2_inode_cache *ic;
52         struct jffs2_sb_info *c;
53         struct jffs2_inode_info *f;
54
55         D1(printk(KERN_DEBUG "jffs2_new_inode(): dir_i %ld, mode 0x%x\n", dir_i->i_ino, mode));
56
57         c = JFFS2_SB_INFO(sb);
58         memset(ri, 0, sizeof(*ri));
59
60         ic = jffs2_alloc_inode_cache();
61         if (!ic) {
62                 return ERR_PTR(-ENOMEM);
63         }
64         memset(ic, 0, sizeof(*ic));
65         
66         inode = new_inode(sb);
67         
68         if (!inode) {
69                 jffs2_free_inode_cache(ic);
70                 return ERR_PTR(-ENOMEM);
71         }
72
73         /* Alloc jffs2_inode_info when that's split in 2.5 */
74
75         f = JFFS2_INODE_INFO(inode);
76         memset(f, 0, sizeof(*f));
77         init_MUTEX_LOCKED(&f->sem);
78         f->inocache = ic;
79         inode->i_nlink = f->inocache->nlink = 1;
80         f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
81         f->inocache->ino = ri->ino = inode->i_ino = ++c->highest_ino;
82         D1(printk(KERN_DEBUG "jffs2_new_inode(): Assigned ino# %d\n", ri->ino));
83         jffs2_add_ino_cache(c, f->inocache);
84
85         ri->magic = JFFS2_MAGIC_BITMASK;
86         ri->nodetype = JFFS2_NODETYPE_INODE;
87         ri->totlen = PAD(sizeof(*ri));
88         ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4);
89         ri->mode = mode;
90         f->highest_version = ri->version = 1;
91         ri->uid = current->fsuid;
92         if (dir_i->i_mode & S_ISGID) {
93                 ri->gid = dir_i->i_gid;
94                 if (S_ISDIR(mode))
95                         ri->mode |= S_ISGID;
96         } else {
97                 ri->gid = current->fsgid;
98         }
99         inode->i_mode = ri->mode;
100         inode->i_gid = ri->gid;
101         inode->i_uid = ri->uid;
102         inode->i_atime = inode->i_ctime = inode->i_mtime = 
103                 ri->atime = ri->mtime = ri->ctime = CURRENT_TIME;
104         inode->i_blksize = PAGE_SIZE;
105         inode->i_blocks = 0;
106         inode->i_size = 0;
107
108         insert_inode_hash(inode);
109
110         return inode;
111 }
112
113 /* This ought to be in core MTD code. All registered MTD devices
114    without writev should have this put in place. Bug the MTD
115    maintainer */
116 static int mtd_fake_writev(struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, loff_t to, size_t *retlen)
117 {
118         unsigned long i;
119         size_t totlen = 0, thislen;
120         int ret = 0;
121
122         for (i=0; i<count; i++) {
123                 ret = mtd->write(mtd, to, vecs[i].iov_len, &thislen, vecs[i].iov_base);
124                 totlen += thislen;
125                 if (ret || thislen != vecs[i].iov_len)
126                         break;
127                 to += vecs[i].iov_len;
128         }
129         if (retlen)
130                 *retlen = totlen;
131         return ret;
132 }
133
134
135 static inline int mtd_writev(struct mtd_info *mtd, const struct iovec *vecs, unsigned long count, loff_t to, size_t *retlen)
136 {
137         if (mtd->writev)
138                 return mtd->writev(mtd,vecs,count,to,retlen);
139         else
140                 return mtd_fake_writev(mtd, vecs, count, to, retlen);
141 }
142
143 static void writecheck(struct mtd_info *mtd, __u32 ofs)
144 {
145         unsigned char buf[16];
146         ssize_t retlen;
147         int ret, i;
148
149         ret = mtd->read(mtd, ofs, 16, &retlen, buf);
150         if (ret && retlen != 16) {
151                 D1(printk(KERN_DEBUG "read failed or short in writecheck(). ret %d, retlen %d\n", ret, retlen));
152                 return;
153         }
154         ret = 0;
155         for (i=0; i<16; i++) {
156                 if (buf[i] != 0xff)
157                         ret = 1;
158         }
159         if (ret) {
160                 printk(KERN_WARNING "ARGH. About to write node to 0x%08x on flash, but there's data already there:\n", ofs);
161                 printk(KERN_WARNING "0x%08x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", 
162                        ofs,
163                        buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
164                        buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
165         }
166 }
167
168         
169         
170
171 /* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it, 
172    write it to the flash, link it into the existing inode/fragment list */
173
174 struct jffs2_full_dnode *jffs2_write_dnode(struct inode *inode, struct jffs2_raw_inode *ri, const unsigned char *data, __u32 datalen, __u32 flash_ofs,  __u32 *writelen)
175
176 {
177         struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
178         struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
179         struct jffs2_raw_node_ref *raw;
180         struct jffs2_full_dnode *fn;
181         ssize_t retlen;
182         struct iovec vecs[2];
183         int ret;
184
185         D1(if(ri->hdr_crc != crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)) {
186                 printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dnode()\n");
187                 BUG();
188         }
189            );
190         vecs[0].iov_base = ri;
191         vecs[0].iov_len = sizeof(*ri);
192         vecs[1].iov_base = (unsigned char *)data;
193         vecs[1].iov_len = datalen;
194
195         writecheck(c->mtd, flash_ofs);
196
197         if (ri->totlen != sizeof(*ri) + datalen) {
198                 printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08x) + datalen (0x%08x)\n", ri->totlen, sizeof(*ri), datalen);
199         }
200         raw = jffs2_alloc_raw_node_ref();
201         if (!raw)
202                 return ERR_PTR(-ENOMEM);
203         
204         fn = jffs2_alloc_full_dnode();
205         if (!fn) {
206                 jffs2_free_raw_node_ref(raw);
207                 return ERR_PTR(-ENOMEM);
208         }
209         raw->flash_offset = flash_ofs;
210         raw->totlen = PAD(ri->totlen);
211         raw->next_phys = NULL;
212
213         fn->ofs = ri->offset;
214         fn->size = ri->dsize;
215         fn->frags = 0;
216         fn->raw = raw;
217
218         ret = mtd_writev(c->mtd, vecs, 2, flash_ofs, &retlen);
219         if (ret || (retlen != sizeof(*ri) + datalen)) {
220                 printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %d\n", 
221                        sizeof(*ri)+datalen, flash_ofs, ret, retlen);
222                 /* Mark the space as dirtied */
223                 if (retlen) {
224                         /* Doesn't belong to any inode */
225                         raw->next_in_ino = NULL;
226
227                         /* Don't change raw->size to match retlen. We may have 
228                            written the node header already, and only the data will
229                            seem corrupted, in which case the scan would skip over
230                            any node we write before the original intended end of 
231                            this node */
232                         jffs2_add_physical_node_ref(c, raw, sizeof(*ri)+datalen, 1);
233                         jffs2_mark_node_obsolete(c, raw);
234                 } else {
235                         printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset);
236                         jffs2_free_raw_node_ref(raw);
237                 }
238
239                 /* Release the full_dnode which is now useless, and return */
240                 jffs2_free_full_dnode(fn);
241                 if (writelen)
242                         *writelen = retlen;
243                 return ERR_PTR(ret?ret:-EIO);
244         }
245         /* Mark the space used */
246         jffs2_add_physical_node_ref(c, raw, retlen, 0);
247
248         /* Link into per-inode list */
249         raw->next_in_ino = f->inocache->nodes;
250         f->inocache->nodes = raw;
251
252         D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n", flash_ofs, ri->dsize, ri->csize, ri->node_crc, ri->data_crc, ri->totlen));
253         if (writelen)
254                 *writelen = retlen;
255
256         f->inocache->nodes = raw;
257         return fn;
258 }
259
260 struct jffs2_full_dirent *jffs2_write_dirent(struct inode *inode, struct jffs2_raw_dirent *rd, const unsigned char *name, __u32 namelen, __u32 flash_ofs,  __u32 *writelen)
261 {
262         struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
263         struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
264         struct jffs2_raw_node_ref *raw;
265         struct jffs2_full_dirent *fd;
266         ssize_t retlen;
267         struct iovec vecs[2];
268         int ret;
269
270         D1(printk(KERN_DEBUG "jffs2_write_dirent(ino #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x)\n", rd->pino, name, name, rd->ino, rd->name_crc));
271         writecheck(c->mtd, flash_ofs);
272
273         D1(if(rd->hdr_crc != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) {
274                 printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n");
275                 BUG();
276         }
277            );
278
279         vecs[0].iov_base = rd;
280         vecs[0].iov_len = sizeof(*rd);
281         vecs[1].iov_base = (unsigned char *)name;
282         vecs[1].iov_len = namelen;
283         
284         raw = jffs2_alloc_raw_node_ref();
285
286         if (!raw)
287                 return ERR_PTR(-ENOMEM);
288
289         fd = jffs2_alloc_full_dirent(namelen+1);
290         if (!fd) {
291                 jffs2_free_raw_node_ref(raw);
292                 return ERR_PTR(-ENOMEM);
293         }
294         raw->flash_offset = flash_ofs;
295         raw->totlen = PAD(rd->totlen);
296         raw->next_in_ino = f->inocache->nodes;
297         f->inocache->nodes = raw;
298         raw->next_phys = NULL;
299
300         fd->version = rd->version;
301         fd->ino = rd->ino;
302         fd->nhash = full_name_hash(name, strlen(name));
303         fd->type = rd->type;
304         memcpy(fd->name, name, namelen);
305         fd->name[namelen]=0;
306         fd->raw = raw;
307
308         ret = mtd_writev(c->mtd, vecs, 2, flash_ofs, &retlen);
309                 if (ret || (retlen != sizeof(*rd) + namelen)) {
310                         printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %d\n", 
311                                sizeof(*rd)+namelen, flash_ofs, ret, retlen);
312                 /* Mark the space as dirtied */
313                         if (retlen) {
314                                 jffs2_add_physical_node_ref(c, raw, sizeof(*rd)+namelen, 1);
315                                 jffs2_mark_node_obsolete(c, raw);
316                         } else {
317                                 printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset);
318                                 jffs2_free_raw_node_ref(raw);
319                         }
320
321                 /* Release the full_dnode which is now useless, and return */
322                 jffs2_free_full_dirent(fd);
323                 if (writelen)
324                         *writelen = retlen;
325                 return ERR_PTR(ret?ret:-EIO);
326         }
327         /* Mark the space used */
328         jffs2_add_physical_node_ref(c, raw, retlen, 0);
329         if (writelen)
330                 *writelen = retlen;
331
332         f->inocache->nodes = raw;
333         return fd;
334 }