Blame view
fs/jffs2/fs.c
19.8 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 |
/* * JFFS2 -- Journalling Flash File System, Version 2. * |
c00c310ea [JFFS2] Tidy up l... |
4 |
* Copyright © 2001-2007 Red Hat, Inc. |
6088c0587 jffs2: Update cop... |
5 |
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> |
1da177e4c Linux-2.6.12-rc2 |
6 7 8 9 10 |
* * Created by David Woodhouse <dwmw2@infradead.org> * * For licensing information, see the file 'LICENCE' in this directory. * |
1da177e4c Linux-2.6.12-rc2 |
11 |
*/ |
5a528957e jffs2: Use pr_fmt... |
12 |
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
16f7e0fe2 [PATCH] capable/c... |
13 |
#include <linux/capability.h> |
1da177e4c Linux-2.6.12-rc2 |
14 15 |
#include <linux/kernel.h> #include <linux/sched.h> |
5b825c3af sched/headers: Pr... |
16 |
#include <linux/cred.h> |
1da177e4c Linux-2.6.12-rc2 |
17 18 19 20 21 22 23 24 25 26 27 |
#include <linux/fs.h> #include <linux/list.h> #include <linux/mtd/mtd.h> #include <linux/pagemap.h> #include <linux/slab.h> #include <linux/vmalloc.h> #include <linux/vfs.h> #include <linux/crc32.h> #include "nodelist.h" static int jffs2_flash_setup(struct jffs2_sb_info *c); |
9ed437c50 [JFFS2] Fix ACL v... |
28 |
int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) |
1da177e4c Linux-2.6.12-rc2 |
29 30 31 32 33 |
{ struct jffs2_full_dnode *old_metadata, *new_metadata; struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); struct jffs2_raw_inode *ri; |
aef9ab478 [JFFS2] Support n... |
34 |
union jffs2_device_node dev; |
1da177e4c Linux-2.6.12-rc2 |
35 36 37 |
unsigned char *mdata = NULL; int mdatalen = 0; unsigned int ivalid; |
9fe4854cd [JFFS2] Remove fl... |
38 |
uint32_t alloclen; |
1da177e4c Linux-2.6.12-rc2 |
39 |
int ret; |
dd919660a [JFFS2] Use ALLOC... |
40 |
int alloc_type = ALLOC_NORMAL; |
9ed437c50 [JFFS2] Fix ACL v... |
41 |
|
9c261b33a jffs2: Convert mo... |
42 43 |
jffs2_dbg(1, "%s(): ino #%lu ", __func__, inode->i_ino); |
1da177e4c Linux-2.6.12-rc2 |
44 45 46 47 48 49 50 51 |
/* Special cases - we don't want more than one data node for these types on the medium at any time. So setattr must read the original data associated with the node (i.e. the device numbers or the target name) and write it out again with the appropriate data attached */ if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { /* For these, we don't actually need to read the old node */ |
aef9ab478 [JFFS2] Support n... |
52 |
mdatalen = jffs2_encode_dev(&dev, inode->i_rdev); |
1da177e4c Linux-2.6.12-rc2 |
53 |
mdata = (char *)&dev; |
9c261b33a jffs2: Convert mo... |
54 55 56 |
jffs2_dbg(1, "%s(): Writing %d bytes of kdev_t ", __func__, mdatalen); |
1da177e4c Linux-2.6.12-rc2 |
57 |
} else if (S_ISLNK(inode->i_mode)) { |
ced220703 [JFFS2] semaphore... |
58 |
mutex_lock(&f->sem); |
1da177e4c Linux-2.6.12-rc2 |
59 60 |
mdatalen = f->metadata->size; mdata = kmalloc(f->metadata->size, GFP_USER); |
422138dd6 [JFFS2] Fix race ... |
61 |
if (!mdata) { |
ced220703 [JFFS2] semaphore... |
62 |
mutex_unlock(&f->sem); |
1da177e4c Linux-2.6.12-rc2 |
63 |
return -ENOMEM; |
422138dd6 [JFFS2] Fix race ... |
64 |
} |
1da177e4c Linux-2.6.12-rc2 |
65 66 |
ret = jffs2_read_dnode(c, f, f->metadata, mdata, 0, mdatalen); if (ret) { |
ced220703 [JFFS2] semaphore... |
67 |
mutex_unlock(&f->sem); |
1da177e4c Linux-2.6.12-rc2 |
68 69 70 |
kfree(mdata); return ret; } |
ced220703 [JFFS2] semaphore... |
71 |
mutex_unlock(&f->sem); |
9c261b33a jffs2: Convert mo... |
72 73 74 |
jffs2_dbg(1, "%s(): Writing %d bytes of symlink target ", __func__, mdatalen); |
1da177e4c Linux-2.6.12-rc2 |
75 76 77 78 79 80 81 82 |
} ri = jffs2_alloc_raw_inode(); if (!ri) { if (S_ISLNK(inode->i_mode)) kfree(mdata); return -ENOMEM; } |
182ec4eee [JFFS2] Clean up ... |
83 |
|
9fe4854cd [JFFS2] Remove fl... |
84 85 |
ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); |
1da177e4c Linux-2.6.12-rc2 |
86 87 |
if (ret) { jffs2_free_raw_inode(ri); |
61effb519 jffs2: S_ISLNK(mo... |
88 |
if (S_ISLNK(inode->i_mode)) |
1da177e4c Linux-2.6.12-rc2 |
89 90 91 |
kfree(mdata); return ret; } |
ced220703 [JFFS2] semaphore... |
92 |
mutex_lock(&f->sem); |
1da177e4c Linux-2.6.12-rc2 |
93 |
ivalid = iattr->ia_valid; |
182ec4eee [JFFS2] Clean up ... |
94 |
|
1da177e4c Linux-2.6.12-rc2 |
95 96 97 98 99 100 101 |
ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); ri->totlen = cpu_to_je32(sizeof(*ri) + mdatalen); ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); ri->ino = cpu_to_je32(inode->i_ino); ri->version = cpu_to_je32(++f->highest_version); |
0cfe53d3c userns: Convert j... |
102 103 104 105 |
ri->uid = cpu_to_je16((ivalid & ATTR_UID)? from_kuid(&init_user_ns, iattr->ia_uid):i_uid_read(inode)); ri->gid = cpu_to_je16((ivalid & ATTR_GID)? from_kgid(&init_user_ns, iattr->ia_gid):i_gid_read(inode)); |
1da177e4c Linux-2.6.12-rc2 |
106 107 |
if (ivalid & ATTR_MODE) |
857013b87 [JFFS2] Don't str... |
108 |
ri->mode = cpu_to_jemode(iattr->ia_mode); |
1da177e4c Linux-2.6.12-rc2 |
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
else ri->mode = cpu_to_jemode(inode->i_mode); ri->isize = cpu_to_je32((ivalid & ATTR_SIZE)?iattr->ia_size:inode->i_size); ri->atime = cpu_to_je32(I_SEC((ivalid & ATTR_ATIME)?iattr->ia_atime:inode->i_atime)); ri->mtime = cpu_to_je32(I_SEC((ivalid & ATTR_MTIME)?iattr->ia_mtime:inode->i_mtime)); ri->ctime = cpu_to_je32(I_SEC((ivalid & ATTR_CTIME)?iattr->ia_ctime:inode->i_ctime)); ri->offset = cpu_to_je32(0); ri->csize = ri->dsize = cpu_to_je32(mdatalen); ri->compr = JFFS2_COMPR_NONE; if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) { /* It's an extension. Make it a hole node */ ri->compr = JFFS2_COMPR_ZERO; ri->dsize = cpu_to_je32(iattr->ia_size - inode->i_size); ri->offset = cpu_to_je32(inode->i_size); |
dd919660a [JFFS2] Use ALLOC... |
126 127 128 129 |
} else if (ivalid & ATTR_SIZE && !iattr->ia_size) { /* For truncate-to-zero, treat it as deletion because it'll always be obsoleting all previous nodes */ alloc_type = ALLOC_DELETION; |
1da177e4c Linux-2.6.12-rc2 |
130 131 132 133 134 135 |
} ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); if (mdatalen) ri->data_crc = cpu_to_je32(crc32(0, mdata, mdatalen)); else ri->data_crc = cpu_to_je32(0); |
dd919660a [JFFS2] Use ALLOC... |
136 |
new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, alloc_type); |
1da177e4c Linux-2.6.12-rc2 |
137 138 |
if (S_ISLNK(inode->i_mode)) kfree(mdata); |
182ec4eee [JFFS2] Clean up ... |
139 |
|
1da177e4c Linux-2.6.12-rc2 |
140 141 142 |
if (IS_ERR(new_metadata)) { jffs2_complete_reservation(c); jffs2_free_raw_inode(ri); |
ced220703 [JFFS2] semaphore... |
143 |
mutex_unlock(&f->sem); |
1da177e4c Linux-2.6.12-rc2 |
144 145 146 147 148 149 150 |
return PTR_ERR(new_metadata); } /* It worked. Update the inode */ inode->i_atime = ITIME(je32_to_cpu(ri->atime)); inode->i_ctime = ITIME(je32_to_cpu(ri->ctime)); inode->i_mtime = ITIME(je32_to_cpu(ri->mtime)); inode->i_mode = jemode_to_cpu(ri->mode); |
0cfe53d3c userns: Convert j... |
151 152 |
i_uid_write(inode, je16_to_cpu(ri->uid)); i_gid_write(inode, je16_to_cpu(ri->gid)); |
1da177e4c Linux-2.6.12-rc2 |
153 154 155 156 157 |
old_metadata = f->metadata; if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) |
f302cd028 [JFFS2] Namespace... |
158 |
jffs2_truncate_fragtree (c, &f->fragtree, iattr->ia_size); |
1da177e4c Linux-2.6.12-rc2 |
159 160 161 162 |
if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) { jffs2_add_full_dnode_to_inode(c, f, new_metadata); inode->i_size = iattr->ia_size; |
b28ba9fa0 [JFFS2] Set i_blo... |
163 |
inode->i_blocks = (inode->i_size + 511) >> 9; |
1da177e4c Linux-2.6.12-rc2 |
164 165 166 167 168 169 170 171 172 |
f->metadata = NULL; } else { f->metadata = new_metadata; } if (old_metadata) { jffs2_mark_node_obsolete(c, old_metadata->raw); jffs2_free_full_dnode(old_metadata); } jffs2_free_raw_inode(ri); |
ced220703 [JFFS2] semaphore... |
173 |
mutex_unlock(&f->sem); |
1da177e4c Linux-2.6.12-rc2 |
174 |
jffs2_complete_reservation(c); |
2c27c65ed check ATTR_SIZE c... |
175 |
/* We have to do the truncate_setsize() without f->sem held, since |
182ec4eee [JFFS2] Clean up ... |
176 |
some pages may be locked and waiting for it in readpage(). |
1da177e4c Linux-2.6.12-rc2 |
177 178 179 |
We are protected from a simultaneous write() extending i_size back past iattr->ia_size, because do_truncate() holds the generic inode semaphore. */ |
b28ba9fa0 [JFFS2] Set i_blo... |
180 |
if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) { |
2c27c65ed check ATTR_SIZE c... |
181 |
truncate_setsize(inode, iattr->ia_size); |
b28ba9fa0 [JFFS2] Set i_blo... |
182 183 |
inode->i_blocks = (inode->i_size + 511) >> 9; } |
1da177e4c Linux-2.6.12-rc2 |
184 185 186 187 188 189 |
return 0; } int jffs2_setattr(struct dentry *dentry, struct iattr *iattr) { |
2b0143b5c VFS: normal files... |
190 |
struct inode *inode = d_inode(dentry); |
aa98d7cf5 [JFFS2][XATTR] XA... |
191 |
int rc; |
31051c85b fs: Give dentry t... |
192 |
rc = setattr_prepare(dentry, iattr); |
9ed437c50 [JFFS2] Fix ACL v... |
193 194 |
if (rc) return rc; |
f2963d455 jffs2: use generi... |
195 |
rc = jffs2_do_setattr(inode, iattr); |
aa98d7cf5 [JFFS2][XATTR] XA... |
196 |
if (!rc && (iattr->ia_valid & ATTR_MODE)) |
f2963d455 jffs2: use generi... |
197 |
rc = posix_acl_chmod(inode, inode->i_mode); |
9ed437c50 [JFFS2] Fix ACL v... |
198 |
|
aa98d7cf5 [JFFS2][XATTR] XA... |
199 |
return rc; |
1da177e4c Linux-2.6.12-rc2 |
200 |
} |
726c33422 [PATCH] VFS: Perm... |
201 |
int jffs2_statfs(struct dentry *dentry, struct kstatfs *buf) |
1da177e4c Linux-2.6.12-rc2 |
202 |
{ |
726c33422 [PATCH] VFS: Perm... |
203 |
struct jffs2_sb_info *c = JFFS2_SB_INFO(dentry->d_sb); |
1da177e4c Linux-2.6.12-rc2 |
204 205 206 207 208 209 210 211 |
unsigned long avail; buf->f_type = JFFS2_SUPER_MAGIC; buf->f_bsize = 1 << PAGE_SHIFT; buf->f_blocks = c->flash_size >> PAGE_SHIFT; buf->f_files = 0; buf->f_ffree = 0; buf->f_namelen = JFFS2_MAX_NAME_LEN; |
75caf6b5a [JFFS2] Fill in f... |
212 213 |
buf->f_fsid.val[0] = JFFS2_SUPER_MAGIC; buf->f_fsid.val[1] = c->mtd->index; |
1da177e4c Linux-2.6.12-rc2 |
214 215 |
spin_lock(&c->erase_completion_lock); |
1da177e4c Linux-2.6.12-rc2 |
216 217 218 219 220 |
avail = c->dirty_size + c->free_size; if (avail > c->sector_size * c->resv_blocks_write) avail -= c->sector_size * c->resv_blocks_write; else avail = 0; |
e0c8e42f8 [JFFS2] Debug cod... |
221 |
spin_unlock(&c->erase_completion_lock); |
1da177e4c Linux-2.6.12-rc2 |
222 223 |
buf->f_bavail = buf->f_bfree = avail >> PAGE_SHIFT; |
1da177e4c Linux-2.6.12-rc2 |
224 225 |
return 0; } |
b57922d97 convert remaining... |
226 |
void jffs2_evict_inode (struct inode *inode) |
1da177e4c Linux-2.6.12-rc2 |
227 |
{ |
182ec4eee [JFFS2] Clean up ... |
228 |
/* We can forget about this inode for now - drop all |
1da177e4c Linux-2.6.12-rc2 |
229 230 231 232 |
* the nodelists associated with it, etc. */ struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); |
182ec4eee [JFFS2] Clean up ... |
233 |
|
9c261b33a jffs2: Convert mo... |
234 235 236 |
jffs2_dbg(1, "%s(): ino #%lu mode %o ", __func__, inode->i_ino, inode->i_mode); |
91b0abe36 mm + fs: store sh... |
237 |
truncate_inode_pages_final(&inode->i_data); |
dbd5768f8 vfs: Rename end_w... |
238 |
clear_inode(inode); |
1da177e4c Linux-2.6.12-rc2 |
239 240 |
jffs2_do_clear_inode(c, f); } |
5451f79f5 iget: stop JFFS2 ... |
241 |
struct inode *jffs2_iget(struct super_block *sb, unsigned long ino) |
1da177e4c Linux-2.6.12-rc2 |
242 243 244 245 |
{ struct jffs2_inode_info *f; struct jffs2_sb_info *c; struct jffs2_raw_inode latest_node; |
aef9ab478 [JFFS2] Support n... |
246 |
union jffs2_device_node jdev; |
5451f79f5 iget: stop JFFS2 ... |
247 |
struct inode *inode; |
aef9ab478 [JFFS2] Support n... |
248 |
dev_t rdev = 0; |
1da177e4c Linux-2.6.12-rc2 |
249 |
int ret; |
9c261b33a jffs2: Convert mo... |
250 251 |
jffs2_dbg(1, "%s(): ino == %lu ", __func__, ino); |
5451f79f5 iget: stop JFFS2 ... |
252 253 254 255 256 257 |
inode = iget_locked(sb, ino); if (!inode) return ERR_PTR(-ENOMEM); if (!(inode->i_state & I_NEW)) return inode; |
1da177e4c Linux-2.6.12-rc2 |
258 259 260 261 262 |
f = JFFS2_INODE_INFO(inode); c = JFFS2_SB_INFO(inode->i_sb); jffs2_init_inode_info(f); |
ced220703 [JFFS2] semaphore... |
263 |
mutex_lock(&f->sem); |
182ec4eee [JFFS2] Clean up ... |
264 |
|
1da177e4c Linux-2.6.12-rc2 |
265 |
ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node); |
7aaea7605 jffs2: fix unbala... |
266 267 |
if (ret) goto error; |
1da177e4c Linux-2.6.12-rc2 |
268 |
|
1da177e4c Linux-2.6.12-rc2 |
269 |
inode->i_mode = jemode_to_cpu(latest_node.mode); |
0cfe53d3c userns: Convert j... |
270 271 |
i_uid_write(inode, je16_to_cpu(latest_node.uid)); i_gid_write(inode, je16_to_cpu(latest_node.gid)); |
1da177e4c Linux-2.6.12-rc2 |
272 273 274 275 |
inode->i_size = je32_to_cpu(latest_node.isize); inode->i_atime = ITIME(je32_to_cpu(latest_node.atime)); inode->i_mtime = ITIME(je32_to_cpu(latest_node.mtime)); inode->i_ctime = ITIME(je32_to_cpu(latest_node.ctime)); |
bfe868486 filesystems: add ... |
276 |
set_nlink(inode, f->inocache->pino_nlink); |
1da177e4c Linux-2.6.12-rc2 |
277 |
|
1da177e4c Linux-2.6.12-rc2 |
278 |
inode->i_blocks = (inode->i_size + 511) >> 9; |
182ec4eee [JFFS2] Clean up ... |
279 |
|
1da177e4c Linux-2.6.12-rc2 |
280 |
switch (inode->i_mode & S_IFMT) { |
1da177e4c Linux-2.6.12-rc2 |
281 282 283 |
case S_IFLNK: inode->i_op = &jffs2_symlink_inode_operations; |
a8db149fc jffs2: switch to ... |
284 |
inode->i_link = f->target; |
1da177e4c Linux-2.6.12-rc2 |
285 |
break; |
182ec4eee [JFFS2] Clean up ... |
286 |
|
1da177e4c Linux-2.6.12-rc2 |
287 288 289 |
case S_IFDIR: { struct jffs2_full_dirent *fd; |
bfe868486 filesystems: add ... |
290 |
set_nlink(inode, 2); /* parent and '.' */ |
1da177e4c Linux-2.6.12-rc2 |
291 292 293 |
for (fd=f->dents; fd; fd = fd->next) { if (fd->type == DT_DIR && fd->ino) |
d8c76e6f4 [PATCH] r/o bind ... |
294 |
inc_nlink(inode); |
1da177e4c Linux-2.6.12-rc2 |
295 |
} |
1da177e4c Linux-2.6.12-rc2 |
296 297 |
/* Root dir gets i_nlink 3 for some reason */ if (inode->i_ino == 1) |
d8c76e6f4 [PATCH] r/o bind ... |
298 |
inc_nlink(inode); |
1da177e4c Linux-2.6.12-rc2 |
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 |
inode->i_op = &jffs2_dir_inode_operations; inode->i_fop = &jffs2_dir_operations; break; } case S_IFREG: inode->i_op = &jffs2_file_inode_operations; inode->i_fop = &jffs2_file_operations; inode->i_mapping->a_ops = &jffs2_file_address_operations; inode->i_mapping->nrpages = 0; break; case S_IFBLK: case S_IFCHR: /* Read the device numbers from the media */ |
91f802660 JFFS2: avoid usin... |
314 315 |
if (f->metadata->size != sizeof(jdev.old_id) && f->metadata->size != sizeof(jdev.new_id)) { |
da320f055 jffs2: Convert pr... |
316 317 318 |
pr_notice("Device node has strange size %d ", f->metadata->size); |
5451f79f5 iget: stop JFFS2 ... |
319 |
goto error_io; |
aef9ab478 [JFFS2] Support n... |
320 |
} |
9c261b33a jffs2: Convert mo... |
321 322 |
jffs2_dbg(1, "Reading device numbers from flash "); |
5451f79f5 iget: stop JFFS2 ... |
323 324 |
ret = jffs2_read_dnode(c, f, f->metadata, (char *)&jdev, 0, f->metadata->size); if (ret < 0) { |
1da177e4c Linux-2.6.12-rc2 |
325 |
/* Eep */ |
da320f055 jffs2: Convert pr... |
326 327 328 |
pr_notice("Read device numbers for inode %lu failed ", (unsigned long)inode->i_ino); |
5451f79f5 iget: stop JFFS2 ... |
329 |
goto error; |
182ec4eee [JFFS2] Clean up ... |
330 |
} |
91f802660 JFFS2: avoid usin... |
331 332 |
if (f->metadata->size == sizeof(jdev.old_id)) rdev = old_decode_dev(je16_to_cpu(jdev.old_id)); |
aef9ab478 [JFFS2] Support n... |
333 |
else |
91f802660 JFFS2: avoid usin... |
334 |
rdev = new_decode_dev(je32_to_cpu(jdev.new_id)); |
1da177e4c Linux-2.6.12-rc2 |
335 336 337 338 |
case S_IFSOCK: case S_IFIFO: inode->i_op = &jffs2_file_inode_operations; |
aef9ab478 [JFFS2] Support n... |
339 |
init_special_inode(inode, inode->i_mode, rdev); |
1da177e4c Linux-2.6.12-rc2 |
340 341 342 |
break; default: |
da320f055 jffs2: Convert pr... |
343 344 345 |
pr_warn("%s(): Bogus i_mode %o for ino %lu ", __func__, inode->i_mode, (unsigned long)inode->i_ino); |
1da177e4c Linux-2.6.12-rc2 |
346 |
} |
ced220703 [JFFS2] semaphore... |
347 |
mutex_unlock(&f->sem); |
1da177e4c Linux-2.6.12-rc2 |
348 |
|
9c261b33a jffs2: Convert mo... |
349 350 |
jffs2_dbg(1, "jffs2_read_inode() returning "); |
5451f79f5 iget: stop JFFS2 ... |
351 352 353 354 355 356 |
unlock_new_inode(inode); return inode; error_io: ret = -EIO; error: |
ced220703 [JFFS2] semaphore... |
357 |
mutex_unlock(&f->sem); |
5451f79f5 iget: stop JFFS2 ... |
358 359 |
iget_failed(inode); return ERR_PTR(ret); |
1da177e4c Linux-2.6.12-rc2 |
360 |
} |
aa3857295 fs: pass exact ty... |
361 |
void jffs2_dirty_inode(struct inode *inode, int flags) |
1da177e4c Linux-2.6.12-rc2 |
362 363 364 365 |
{ struct iattr iattr; if (!(inode->i_state & I_DIRTY_DATASYNC)) { |
9c261b33a jffs2: Convert mo... |
366 367 368 |
jffs2_dbg(2, "%s(): not calling setattr() for ino #%lu ", __func__, inode->i_ino); |
1da177e4c Linux-2.6.12-rc2 |
369 370 |
return; } |
9c261b33a jffs2: Convert mo... |
371 372 373 |
jffs2_dbg(1, "%s(): calling setattr() for ino #%lu ", __func__, inode->i_ino); |
1da177e4c Linux-2.6.12-rc2 |
374 375 376 377 378 379 380 381 382 383 384 |
iattr.ia_valid = ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_MTIME|ATTR_CTIME; iattr.ia_mode = inode->i_mode; iattr.ia_uid = inode->i_uid; iattr.ia_gid = inode->i_gid; iattr.ia_atime = inode->i_atime; iattr.ia_mtime = inode->i_mtime; iattr.ia_ctime = inode->i_ctime; jffs2_do_setattr(inode, &iattr); } |
92abc475d jffs2: implement ... |
385 |
int jffs2_do_remount_fs(struct super_block *sb, int *flags, char *data) |
1da177e4c Linux-2.6.12-rc2 |
386 387 |
{ struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); |
bc98a42c1 VFS: Convert sb->... |
388 |
if (c->flags & JFFS2_SB_FLAG_RO && !sb_rdonly(sb)) |
1da177e4c Linux-2.6.12-rc2 |
389 390 391 392 393 394 |
return -EROFS; /* We stop if it was running, then restart if it needs to. This also catches the case where it was stopped and this is just a remount to restart it. Flush the writebuffer, if neccecary, else we loose it */ |
bc98a42c1 VFS: Convert sb->... |
395 |
if (!sb_rdonly(sb)) { |
1da177e4c Linux-2.6.12-rc2 |
396 |
jffs2_stop_garbage_collect_thread(c); |
ced220703 [JFFS2] semaphore... |
397 |
mutex_lock(&c->alloc_sem); |
1da177e4c Linux-2.6.12-rc2 |
398 |
jffs2_flush_wbuf_pad(c); |
ced220703 [JFFS2] semaphore... |
399 |
mutex_unlock(&c->alloc_sem); |
182ec4eee [JFFS2] Clean up ... |
400 |
} |
1da177e4c Linux-2.6.12-rc2 |
401 402 403 |
if (!(*flags & MS_RDONLY)) jffs2_start_garbage_collect_thread(c); |
182ec4eee [JFFS2] Clean up ... |
404 |
|
1da177e4c Linux-2.6.12-rc2 |
405 |
*flags |= MS_NOATIME; |
1da177e4c Linux-2.6.12-rc2 |
406 407 |
return 0; } |
1da177e4c Linux-2.6.12-rc2 |
408 409 |
/* jffs2_new_inode: allocate a new inode and inocache, add it to the hash, fill in the raw_inode while you're at it. */ |
d3fb61207 switch posix_acl_... |
410 |
struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, struct jffs2_raw_inode *ri) |
1da177e4c Linux-2.6.12-rc2 |
411 412 413 414 415 416 |
{ struct inode *inode; struct super_block *sb = dir_i->i_sb; struct jffs2_sb_info *c; struct jffs2_inode_info *f; int ret; |
9c261b33a jffs2: Convert mo... |
417 418 419 |
jffs2_dbg(1, "%s(): dir_i %ld, mode 0x%x ", __func__, dir_i->i_ino, mode); |
1da177e4c Linux-2.6.12-rc2 |
420 421 |
c = JFFS2_SB_INFO(sb); |
182ec4eee [JFFS2] Clean up ... |
422 |
|
1da177e4c Linux-2.6.12-rc2 |
423 |
inode = new_inode(sb); |
182ec4eee [JFFS2] Clean up ... |
424 |
|
1da177e4c Linux-2.6.12-rc2 |
425 426 427 428 429 |
if (!inode) return ERR_PTR(-ENOMEM); f = JFFS2_INODE_INFO(inode); jffs2_init_inode_info(f); |
ced220703 [JFFS2] semaphore... |
430 |
mutex_lock(&f->sem); |
1da177e4c Linux-2.6.12-rc2 |
431 432 433 |
memset(ri, 0, sizeof(*ri)); /* Set OS-specific defaults for new inodes */ |
0cfe53d3c userns: Convert j... |
434 |
ri->uid = cpu_to_je16(from_kuid(&init_user_ns, current_fsuid())); |
1da177e4c Linux-2.6.12-rc2 |
435 436 |
if (dir_i->i_mode & S_ISGID) { |
0cfe53d3c userns: Convert j... |
437 |
ri->gid = cpu_to_je16(i_gid_read(dir_i)); |
1da177e4c Linux-2.6.12-rc2 |
438 439 440 |
if (S_ISDIR(mode)) mode |= S_ISGID; } else { |
0cfe53d3c userns: Convert j... |
441 |
ri->gid = cpu_to_je16(from_kgid(&init_user_ns, current_fsgid())); |
1da177e4c Linux-2.6.12-rc2 |
442 |
} |
9ed437c50 [JFFS2] Fix ACL v... |
443 444 445 |
/* POSIX ACLs have to be processed now, at least partly. The umask is only applied if there's no default ACL */ |
cfc8dc6f6 [JFFS2] Tidy up f... |
446 447 |
ret = jffs2_init_acl_pre(dir_i, inode, &mode); if (ret) { |
01887a3a2 jffs2: unlock f->... |
448 449 450 451 |
mutex_unlock(&f->sem); make_bad_inode(inode); iput(inode); return ERR_PTR(ret); |
9ed437c50 [JFFS2] Fix ACL v... |
452 |
} |
1da177e4c Linux-2.6.12-rc2 |
453 454 |
ret = jffs2_do_new_inode (c, f, mode, ri); if (ret) { |
01887a3a2 jffs2: unlock f->... |
455 |
mutex_unlock(&f->sem); |
1da177e4c Linux-2.6.12-rc2 |
456 457 458 459 |
make_bad_inode(inode); iput(inode); return ERR_PTR(ret); } |
bfe868486 filesystems: add ... |
460 |
set_nlink(inode, 1); |
1da177e4c Linux-2.6.12-rc2 |
461 462 |
inode->i_ino = je32_to_cpu(ri->ino); inode->i_mode = jemode_to_cpu(ri->mode); |
0cfe53d3c userns: Convert j... |
463 464 |
i_gid_write(inode, je16_to_cpu(ri->gid)); i_uid_write(inode, je16_to_cpu(ri->uid)); |
02027d42c fs: Replace CURRE... |
465 |
inode->i_atime = inode->i_ctime = inode->i_mtime = current_time(inode); |
1da177e4c Linux-2.6.12-rc2 |
466 |
ri->atime = ri->mtime = ri->ctime = cpu_to_je32(I_SEC(inode->i_mtime)); |
1da177e4c Linux-2.6.12-rc2 |
467 468 |
inode->i_blocks = 0; inode->i_size = 0; |
e72e6497e jffs2: Fix NFS ra... |
469 |
if (insert_inode_locked(inode) < 0) { |
01887a3a2 jffs2: unlock f->... |
470 |
mutex_unlock(&f->sem); |
e72e6497e jffs2: Fix NFS ra... |
471 |
make_bad_inode(inode); |
e72e6497e jffs2: Fix NFS ra... |
472 473 474 |
iput(inode); return ERR_PTR(-EINVAL); } |
1da177e4c Linux-2.6.12-rc2 |
475 476 477 |
return inode; } |
65e5a0e18 jffs2: Dynamicall... |
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 |
static int calculate_inocache_hashsize(uint32_t flash_size) { /* * Pick a inocache hash size based on the size of the medium. * Count how many megabytes we're dealing with, apply a hashsize twice * that size, but rounding down to the usual big powers of 2. And keep * to sensible bounds. */ int size_mb = flash_size / 1024 / 1024; int hashsize = (size_mb * 2) & ~0x3f; if (hashsize < INOCACHE_HASHSIZE_MIN) return INOCACHE_HASHSIZE_MIN; if (hashsize > INOCACHE_HASHSIZE_MAX) return INOCACHE_HASHSIZE_MAX; return hashsize; } |
1da177e4c Linux-2.6.12-rc2 |
497 498 499 500 501 502 503 504 505 |
int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) { struct jffs2_sb_info *c; struct inode *root_i; int ret; size_t blocks; c = JFFS2_SB_INFO(sb); |
e104f1e9d jffs2: do not sup... |
506 507 508 |
/* Do not support the MLC nand */ if (c->mtd->type == MTD_MLCNANDFLASH) return -EINVAL; |
2f82ce1eb [JFFS2] Use a sin... |
509 |
#ifndef CONFIG_JFFS2_FS_WRITEBUFFER |
1da177e4c Linux-2.6.12-rc2 |
510 |
if (c->mtd->type == MTD_NANDFLASH) { |
5a528957e jffs2: Use pr_fmt... |
511 512 |
pr_err("Cannot operate on NAND flash unless jffs2 NAND support is compiled in "); |
1da177e4c Linux-2.6.12-rc2 |
513 514 |
return -EINVAL; } |
8f15fd55f [JFFS2] Add suppo... |
515 |
if (c->mtd->type == MTD_DATAFLASH) { |
5a528957e jffs2: Use pr_fmt... |
516 517 |
pr_err("Cannot operate on DataFlash unless jffs2 DataFlash support is compiled in "); |
8f15fd55f [JFFS2] Add suppo... |
518 519 520 |
return -EINVAL; } #endif |
1da177e4c Linux-2.6.12-rc2 |
521 522 |
c->flash_size = c->mtd->size; |
182ec4eee [JFFS2] Clean up ... |
523 |
c->sector_size = c->mtd->erasesize; |
1da177e4c Linux-2.6.12-rc2 |
524 |
blocks = c->flash_size / c->sector_size; |
1da177e4c Linux-2.6.12-rc2 |
525 526 527 528 529 |
/* * Size alignment check */ if ((c->sector_size * blocks) != c->flash_size) { |
182ec4eee [JFFS2] Clean up ... |
530 |
c->flash_size = c->sector_size * blocks; |
5a528957e jffs2: Use pr_fmt... |
531 532 |
pr_info("Flash size not aligned to erasesize, reducing to %dKiB ", |
1da177e4c Linux-2.6.12-rc2 |
533 534 |
c->flash_size / 1024); } |
1da177e4c Linux-2.6.12-rc2 |
535 |
if (c->flash_size < 5*c->sector_size) { |
5a528957e jffs2: Use pr_fmt... |
536 537 |
pr_err("Too few erase blocks (%d) ", |
da320f055 jffs2: Convert pr... |
538 |
c->flash_size / c->sector_size); |
1da177e4c Linux-2.6.12-rc2 |
539 540 541 542 |
return -EINVAL; } c->cleanmarker_size = sizeof(struct jffs2_unknown_node); |
1da177e4c Linux-2.6.12-rc2 |
543 544 545 546 547 |
/* NAND (or other bizarre) flash... do setup accordingly */ ret = jffs2_flash_setup(c); if (ret) return ret; |
65e5a0e18 jffs2: Dynamicall... |
548 549 |
c->inocache_hashsize = calculate_inocache_hashsize(c->flash_size); c->inocache_list = kcalloc(c->inocache_hashsize, sizeof(struct jffs2_inode_cache *), GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
550 551 552 553 |
if (!c->inocache_list) { ret = -ENOMEM; goto out_wbuf; } |
1da177e4c Linux-2.6.12-rc2 |
554 |
|
aa98d7cf5 [JFFS2][XATTR] XA... |
555 |
jffs2_init_xattr_subsystem(c); |
1da177e4c Linux-2.6.12-rc2 |
556 557 |
if ((ret = jffs2_do_mount_fs(c))) goto out_inohash; |
9c261b33a jffs2: Convert mo... |
558 559 |
jffs2_dbg(1, "%s(): Getting root inode ", __func__); |
5451f79f5 iget: stop JFFS2 ... |
560 561 |
root_i = jffs2_iget(sb, 1); if (IS_ERR(root_i)) { |
9c261b33a jffs2: Convert mo... |
562 563 |
jffs2_dbg(1, "get root inode failed "); |
5451f79f5 iget: stop JFFS2 ... |
564 565 |
ret = PTR_ERR(root_i); goto out_root; |
1da177e4c Linux-2.6.12-rc2 |
566 |
} |
5451f79f5 iget: stop JFFS2 ... |
567 |
ret = -ENOMEM; |
623ff7739 Merge tag 'for-li... |
568 569 |
jffs2_dbg(1, "%s(): d_make_root() ", __func__); |
48fde701a switch open-coded... |
570 |
sb->s_root = d_make_root(root_i); |
1da177e4c Linux-2.6.12-rc2 |
571 |
if (!sb->s_root) |
48fde701a switch open-coded... |
572 |
goto out_root; |
1da177e4c Linux-2.6.12-rc2 |
573 |
|
1da177e4c Linux-2.6.12-rc2 |
574 |
sb->s_maxbytes = 0xFFFFFFFF; |
09cbfeaf1 mm, fs: get rid o... |
575 576 |
sb->s_blocksize = PAGE_SIZE; sb->s_blocksize_bits = PAGE_SHIFT; |
1da177e4c Linux-2.6.12-rc2 |
577 |
sb->s_magic = JFFS2_SUPER_MAGIC; |
bc98a42c1 VFS: Convert sb->... |
578 |
if (!sb_rdonly(sb)) |
1da177e4c Linux-2.6.12-rc2 |
579 580 |
jffs2_start_garbage_collect_thread(c); return 0; |
5451f79f5 iget: stop JFFS2 ... |
581 |
out_root: |
1da177e4c Linux-2.6.12-rc2 |
582 583 |
jffs2_free_ino_caches(c); jffs2_free_raw_node_refs(c); |
1d5cfdb07 tree wide: use kv... |
584 |
kvfree(c->blocks); |
1da177e4c Linux-2.6.12-rc2 |
585 |
out_inohash: |
aa98d7cf5 [JFFS2][XATTR] XA... |
586 |
jffs2_clear_xattr_subsystem(c); |
1da177e4c Linux-2.6.12-rc2 |
587 588 589 590 591 592 593 594 595 596 597 598 599 600 |
kfree(c->inocache_list); out_wbuf: jffs2_flash_cleanup(c); return ret; } void jffs2_gc_release_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) { iput(OFNI_EDONI_2SFFJ(f)); } struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, |
1b690b487 [JFFS2] Invert la... |
601 |
int inum, int unlinked) |
1da177e4c Linux-2.6.12-rc2 |
602 603 604 |
{ struct inode *inode; struct jffs2_inode_cache *ic; |
1b690b487 [JFFS2] Invert la... |
605 606 |
if (unlinked) { |
1da177e4c Linux-2.6.12-rc2 |
607 |
/* The inode has zero nlink but its nodes weren't yet marked |
182ec4eee [JFFS2] Clean up ... |
608 |
obsolete. This has to be because we're still waiting for |
1da177e4c Linux-2.6.12-rc2 |
609 |
the final (close() and) iput() to happen. |
182ec4eee [JFFS2] Clean up ... |
610 |
There's a possibility that the final iput() could have |
1da177e4c Linux-2.6.12-rc2 |
611 612 613 614 |
happened while we were contemplating. In order to ensure that we don't cause a new read_inode() (which would fail) for the inode in question, we use ilookup() in this case instead of iget(). |
182ec4eee [JFFS2] Clean up ... |
615 |
The nlink can't _become_ zero at this point because we're |
1da177e4c Linux-2.6.12-rc2 |
616 617 618 619 620 |
holding the alloc_sem, and jffs2_do_unlink() would also need that while decrementing nlink on any inode. */ inode = ilookup(OFNI_BS_2SFFJ(c), inum); if (!inode) { |
9c261b33a jffs2: Convert mo... |
621 622 623 |
jffs2_dbg(1, "ilookup() failed for ino #%u; inode is probably deleted. ", inum); |
1da177e4c Linux-2.6.12-rc2 |
624 625 626 627 |
spin_lock(&c->inocache_lock); ic = jffs2_get_ino_cache(c, inum); if (!ic) { |
9c261b33a jffs2: Convert mo... |
628 629 630 |
jffs2_dbg(1, "Inode cache for ino #%u is gone ", inum); |
1da177e4c Linux-2.6.12-rc2 |
631 632 633 634 635 |
spin_unlock(&c->inocache_lock); return NULL; } if (ic->state != INO_STATE_CHECKEDABSENT) { /* Wait for progress. Don't just loop */ |
9c261b33a jffs2: Convert mo... |
636 637 638 |
jffs2_dbg(1, "Waiting for ino #%u in state %d ", ic->ino, ic->state); |
1da177e4c Linux-2.6.12-rc2 |
639 640 641 642 643 644 645 646 647 648 649 650 |
sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); } else { spin_unlock(&c->inocache_lock); } return NULL; } } else { /* Inode has links to it still; they're not going away because jffs2_do_unlink() would need the alloc_sem and we have it. Just iget() it, and if read_inode() is necessary that's OK. */ |
5451f79f5 iget: stop JFFS2 ... |
651 652 653 |
inode = jffs2_iget(OFNI_BS_2SFFJ(c), inum); if (IS_ERR(inode)) return ERR_CAST(inode); |
1da177e4c Linux-2.6.12-rc2 |
654 655 |
} if (is_bad_inode(inode)) { |
da320f055 jffs2: Convert pr... |
656 657 658 |
pr_notice("Eep. read_inode() failed for ino #%u. unlinked %d ", inum, unlinked); |
1da177e4c Linux-2.6.12-rc2 |
659 660 661 662 663 664 665 |
/* NB. This will happen again. We need to do something appropriate here. */ iput(inode); return ERR_PTR(-EIO); } return JFFS2_INODE_INFO(inode); } |
182ec4eee [JFFS2] Clean up ... |
666 667 |
unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, struct jffs2_inode_info *f, |
1da177e4c Linux-2.6.12-rc2 |
668 669 670 671 672 |
unsigned long offset, unsigned long *priv) { struct inode *inode = OFNI_EDONI_2SFFJ(f); struct page *pg; |
09cbfeaf1 mm, fs: get rid o... |
673 |
pg = read_cache_page(inode->i_mapping, offset >> PAGE_SHIFT, |
1da177e4c Linux-2.6.12-rc2 |
674 675 676 |
(void *)jffs2_do_readpage_unlock, inode); if (IS_ERR(pg)) return (void *)pg; |
182ec4eee [JFFS2] Clean up ... |
677 |
|
1da177e4c Linux-2.6.12-rc2 |
678 679 680 681 682 683 684 685 686 687 688 |
*priv = (unsigned long)pg; return kmap(pg); } void jffs2_gc_release_page(struct jffs2_sb_info *c, unsigned char *ptr, unsigned long *priv) { struct page *pg = (void *)*priv; kunmap(pg); |
09cbfeaf1 mm, fs: get rid o... |
689 |
put_page(pg); |
1da177e4c Linux-2.6.12-rc2 |
690 691 692 693 |
} static int jffs2_flash_setup(struct jffs2_sb_info *c) { int ret = 0; |
182ec4eee [JFFS2] Clean up ... |
694 |
|
1da177e4c Linux-2.6.12-rc2 |
695 696 697 698 699 700 |
if (jffs2_cleanmarker_oob(c)) { /* NAND flash... do setup accordingly */ ret = jffs2_nand_flash_setup(c); if (ret) return ret; } |
8f15fd55f [JFFS2] Add suppo... |
701 702 703 704 705 706 |
/* and Dataflash */ if (jffs2_dataflash(c)) { ret = jffs2_dataflash_setup(c); if (ret) return ret; } |
59da721a2 [JFFS2] Teach JFF... |
707 708 709 710 711 712 713 |
/* and Intel "Sibley" flash */ if (jffs2_nor_wbuf_flash(c)) { ret = jffs2_nor_wbuf_flash_setup(c); if (ret) return ret; } |
0029da3bf JFFS2: add UBI su... |
714 715 716 717 718 719 |
/* and an UBI volume */ if (jffs2_ubivol(c)) { ret = jffs2_ubivol_setup(c); if (ret) return ret; } |
1da177e4c Linux-2.6.12-rc2 |
720 721 722 723 724 725 726 727 |
return ret; } void jffs2_flash_cleanup(struct jffs2_sb_info *c) { if (jffs2_cleanmarker_oob(c)) { jffs2_nand_flash_cleanup(c); } |
8f15fd55f [JFFS2] Add suppo... |
728 729 730 731 |
/* and DataFlash */ if (jffs2_dataflash(c)) { jffs2_dataflash_cleanup(c); } |
59da721a2 [JFFS2] Teach JFF... |
732 733 734 735 736 |
/* and Intel "Sibley" flash */ if (jffs2_nor_wbuf_flash(c)) { jffs2_nor_wbuf_flash_cleanup(c); } |
0029da3bf JFFS2: add UBI su... |
737 738 739 740 741 |
/* and an UBI volume */ if (jffs2_ubivol(c)) { jffs2_ubivol_cleanup(c); } |
1da177e4c Linux-2.6.12-rc2 |
742 |
} |