Blame view
fs/jffs2/dir.c
22.9 KB
1da177e4c
|
1 2 3 |
/* * JFFS2 -- Journalling Flash File System, Version 2. * |
c00c310ea
|
4 |
* Copyright © 2001-2007 Red Hat, Inc. |
6088c0587
|
5 |
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> |
1da177e4c
|
6 7 8 9 10 |
* * Created by David Woodhouse <dwmw2@infradead.org> * * For licensing information, see the file 'LICENCE' in this directory. * |
1da177e4c
|
11 12 13 14 |
*/ #include <linux/kernel.h> #include <linux/slab.h> |
1da177e4c
|
15 16 17 |
#include <linux/fs.h> #include <linux/crc32.h> #include <linux/jffs2.h> |
cbb9a5617
|
18 19 |
#include "jffs2_fs_i.h" #include "jffs2_fs_sb.h" |
1da177e4c
|
20 21 |
#include <linux/time.h> #include "nodelist.h" |
1da177e4c
|
22 23 24 25 26 27 28 29 30 31 32 |
static int jffs2_readdir (struct file *, void *, filldir_t); static int jffs2_create (struct inode *,struct dentry *,int, struct nameidata *); static struct dentry *jffs2_lookup (struct inode *,struct dentry *, struct nameidata *); static int jffs2_link (struct dentry *,struct inode *,struct dentry *); static int jffs2_unlink (struct inode *,struct dentry *); static int jffs2_symlink (struct inode *,struct dentry *,const char *); static int jffs2_mkdir (struct inode *,struct dentry *,int); static int jffs2_rmdir (struct inode *,struct dentry *); |
265489f01
|
33 |
static int jffs2_mknod (struct inode *,struct dentry *,int,dev_t); |
1da177e4c
|
34 |
static int jffs2_rename (struct inode *, struct dentry *, |
ef53cb02f
|
35 |
struct inode *, struct dentry *); |
1da177e4c
|
36 |
|
4b6f5d20b
|
37 |
const struct file_operations jffs2_dir_operations = |
1da177e4c
|
38 39 40 |
{ .read = generic_read_dir, .readdir = jffs2_readdir, |
0533400b7
|
41 |
.unlocked_ioctl=jffs2_ioctl, |
3222a3e55
|
42 43 |
.fsync = jffs2_fsync, .llseek = generic_file_llseek, |
1da177e4c
|
44 |
}; |
92e1d5be9
|
45 |
const struct inode_operations jffs2_dir_inode_operations = |
1da177e4c
|
46 |
{ |
265489f01
|
47 48 |
.create = jffs2_create, .lookup = jffs2_lookup, |
1da177e4c
|
49 50 51 52 53 54 55 |
.link = jffs2_link, .unlink = jffs2_unlink, .symlink = jffs2_symlink, .mkdir = jffs2_mkdir, .rmdir = jffs2_rmdir, .mknod = jffs2_mknod, .rename = jffs2_rename, |
4e34e719e
|
56 |
.get_acl = jffs2_get_acl, |
1da177e4c
|
57 |
.setattr = jffs2_setattr, |
aa98d7cf5
|
58 59 60 61 |
.setxattr = jffs2_setxattr, .getxattr = jffs2_getxattr, .listxattr = jffs2_listxattr, .removexattr = jffs2_removexattr |
1da177e4c
|
62 63 64 65 66 67 |
}; /***********************************************************************/ /* We keep the dirent list sorted in increasing order of name hash, |
182ec4eee
|
68 |
and we use the same hash function as the dentries. Makes this |
1da177e4c
|
69 70 71 72 73 74 |
nice and simple */ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target, struct nameidata *nd) { struct jffs2_inode_info *dir_f; |
1da177e4c
|
75 76 77 78 79 80 |
struct jffs2_full_dirent *fd = NULL, *fd_list; uint32_t ino = 0; struct inode *inode = NULL; D1(printk(KERN_DEBUG "jffs2_lookup() ")); |
373d5e718
|
81 82 |
if (target->d_name.len > JFFS2_MAX_NAME_LEN) return ERR_PTR(-ENAMETOOLONG); |
1da177e4c
|
83 |
dir_f = JFFS2_INODE_INFO(dir_i); |
1da177e4c
|
84 |
|
ced220703
|
85 |
mutex_lock(&dir_f->sem); |
1da177e4c
|
86 87 88 |
/* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */ for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= target->d_name.hash; fd_list = fd_list->next) { |
182ec4eee
|
89 |
if (fd_list->nhash == target->d_name.hash && |
1da177e4c
|
90 91 92 93 94 95 96 97 |
(!fd || fd_list->version > fd->version) && strlen(fd_list->name) == target->d_name.len && !strncmp(fd_list->name, target->d_name.name, target->d_name.len)) { fd = fd_list; } } if (fd) ino = fd->ino; |
ced220703
|
98 |
mutex_unlock(&dir_f->sem); |
1da177e4c
|
99 |
if (ino) { |
5451f79f5
|
100 |
inode = jffs2_iget(dir_i->i_sb, ino); |
a9049376e
|
101 |
if (IS_ERR(inode)) |
1da177e4c
|
102 103 |
printk(KERN_WARNING "iget() failed for ino #%u ", ino); |
1da177e4c
|
104 |
} |
8966c5e0f
|
105 |
return d_splice_alias(inode, target); |
1da177e4c
|
106 107 108 109 110 111 112 113 |
} /***********************************************************************/ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir) { struct jffs2_inode_info *f; |
ec2e203c8
|
114 |
struct inode *inode = filp->f_path.dentry->d_inode; |
1da177e4c
|
115 116 |
struct jffs2_full_dirent *fd; unsigned long offset, curofs; |
ec2e203c8
|
117 118 |
D1(printk(KERN_DEBUG "jffs2_readdir() for dir_i #%lu ", filp->f_path.dentry->d_inode->i_ino)); |
1da177e4c
|
119 120 |
f = JFFS2_INODE_INFO(inode); |
1da177e4c
|
121 122 123 124 125 126 127 128 129 130 131 |
offset = filp->f_pos; if (offset == 0) { D1(printk(KERN_DEBUG "Dirent 0: \".\", ino #%lu ", inode->i_ino)); if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0) goto out; offset++; } if (offset == 1) { |
ec2e203c8
|
132 |
unsigned long pino = parent_ino(filp->f_path.dentry); |
1da177e4c
|
133 134 135 136 137 138 139 140 |
D1(printk(KERN_DEBUG "Dirent 1: \"..\", ino #%lu ", pino)); if (filldir(dirent, "..", 2, 1, pino, DT_DIR) < 0) goto out; offset++; } curofs=1; |
ced220703
|
141 |
mutex_lock(&f->sem); |
1da177e4c
|
142 143 144 145 146 |
for (fd = f->dents; fd; fd = fd->next) { curofs++; /* First loop: curofs = 2; offset = 2 */ if (curofs < offset) { |
182ec4eee
|
147 148 |
D2(printk(KERN_DEBUG "Skipping dirent: \"%s\", ino #%u, type %d, because curofs %ld < offset %ld ", |
1da177e4c
|
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
fd->name, fd->ino, fd->type, curofs, offset)); continue; } if (!fd->ino) { D2(printk(KERN_DEBUG "Skipping deletion dirent \"%s\" ", fd->name)); offset++; continue; } D2(printk(KERN_DEBUG "Dirent %ld: \"%s\", ino #%u, type %d ", offset, fd->name, fd->ino, fd->type)); if (filldir(dirent, fd->name, strlen(fd->name), offset, fd->ino, fd->type) < 0) break; offset++; } |
ced220703
|
164 |
mutex_unlock(&f->sem); |
1da177e4c
|
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
out: filp->f_pos = offset; return 0; } /***********************************************************************/ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode, struct nameidata *nd) { struct jffs2_raw_inode *ri; struct jffs2_inode_info *f, *dir_f; struct jffs2_sb_info *c; struct inode *inode; int ret; ri = jffs2_alloc_raw_inode(); if (!ri) return -ENOMEM; |
182ec4eee
|
185 |
|
1da177e4c
|
186 187 188 189 |
c = JFFS2_SB_INFO(dir_i->i_sb); D1(printk(KERN_DEBUG "jffs2_create() ")); |
cfc8dc6f6
|
190 |
inode = jffs2_new_inode(dir_i, mode, ri); |
1da177e4c
|
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
if (IS_ERR(inode)) { D1(printk(KERN_DEBUG "jffs2_new_inode() failed ")); jffs2_free_raw_inode(ri); return PTR_ERR(inode); } 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; f = JFFS2_INODE_INFO(inode); dir_f = JFFS2_INODE_INFO(dir_i); |
590fe34c4
|
206 207 208 209 210 211 |
/* jffs2_do_create() will want to lock it, _after_ reserving space and taking c-alloc_sem. If we keep it locked here, lockdep gets unhappy (although it's a false positive; nothing else will be looking at this inode yet so there's no chance of AB-BA deadlock involving its f->sem). */ mutex_unlock(&f->sem); |
2a7dba391
|
212 |
ret = jffs2_do_create(c, dir_f, f, ri, &dentry->d_name); |
aa98d7cf5
|
213 214 |
if (ret) goto fail; |
1da177e4c
|
215 216 217 218 |
dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime)); jffs2_free_raw_inode(ri); |
1da177e4c
|
219 220 221 |
D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld ", |
27c72b040
|
222 223 |
inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->pino_nlink, inode->i_mapping->nrpages)); |
e72e6497e
|
224 225 226 |
d_instantiate(dentry, inode); unlock_new_inode(inode); |
1da177e4c
|
227 |
return 0; |
aa98d7cf5
|
228 229 |
fail: |
41cce647f
|
230 |
iget_failed(inode); |
aa98d7cf5
|
231 232 |
jffs2_free_raw_inode(ri); return ret; |
1da177e4c
|
233 234 235 236 237 238 239 240 241 242 243 |
} /***********************************************************************/ static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry) { struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb); struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); struct jffs2_inode_info *dead_f = JFFS2_INODE_INFO(dentry->d_inode); int ret; |
3a69e0cd2
|
244 |
uint32_t now = get_seconds(); |
1da177e4c
|
245 |
|
182ec4eee
|
246 |
ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, |
3a69e0cd2
|
247 |
dentry->d_name.len, dead_f, now); |
1da177e4c
|
248 |
if (dead_f->inocache) |
bfe868486
|
249 |
set_nlink(dentry->d_inode, dead_f->inocache->pino_nlink); |
3a69e0cd2
|
250 251 |
if (!ret) dir_i->i_mtime = dir_i->i_ctime = ITIME(now); |
1da177e4c
|
252 253 254 255 256 257 258 259 260 261 262 263 |
return ret; } /***********************************************************************/ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct dentry *dentry) { struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dentry->d_inode->i_sb); struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode); struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); int ret; uint8_t type; |
3a69e0cd2
|
264 |
uint32_t now; |
1da177e4c
|
265 266 267 268 269 270 271 272 273 274 275 |
/* Don't let people make hard links to bad inodes. */ if (!f->inocache) return -EIO; if (S_ISDIR(old_dentry->d_inode->i_mode)) return -EPERM; /* XXX: This is ugly */ type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12; if (!type) type = DT_REG; |
3a69e0cd2
|
276 277 |
now = get_seconds(); ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, dentry->d_name.name, dentry->d_name.len, now); |
1da177e4c
|
278 279 |
if (!ret) { |
ced220703
|
280 |
mutex_lock(&f->sem); |
bfe868486
|
281 |
set_nlink(old_dentry->d_inode, ++f->inocache->pino_nlink); |
ced220703
|
282 |
mutex_unlock(&f->sem); |
1da177e4c
|
283 |
d_instantiate(dentry, old_dentry->d_inode); |
3a69e0cd2
|
284 |
dir_i->i_mtime = dir_i->i_ctime = ITIME(now); |
7de9c6ee3
|
285 |
ihold(old_dentry->d_inode); |
1da177e4c
|
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 |
} return ret; } /***********************************************************************/ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char *target) { struct jffs2_inode_info *f, *dir_f; struct jffs2_sb_info *c; struct inode *inode; struct jffs2_raw_inode *ri; struct jffs2_raw_dirent *rd; struct jffs2_full_dnode *fn; struct jffs2_full_dirent *fd; int namelen; |
9fe4854cd
|
302 |
uint32_t alloclen; |
32f1a95d5
|
303 |
int ret, targetlen = strlen(target); |
1da177e4c
|
304 305 306 |
/* FIXME: If you care. We'd need to use frags for the target if it grows much more than this */ |
32f1a95d5
|
307 |
if (targetlen > 254) |
bde86fec7
|
308 |
return -ENAMETOOLONG; |
1da177e4c
|
309 310 311 312 313 |
ri = jffs2_alloc_raw_inode(); if (!ri) return -ENOMEM; |
182ec4eee
|
314 |
|
1da177e4c
|
315 |
c = JFFS2_SB_INFO(dir_i->i_sb); |
182ec4eee
|
316 317 318 |
/* Try to reserve enough space for both node and dirent. * Just the node will do for now, though |
1da177e4c
|
319 320 |
*/ namelen = dentry->d_name.len; |
9fe4854cd
|
321 322 |
ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); |
1da177e4c
|
323 324 325 326 327 |
if (ret) { jffs2_free_raw_inode(ri); return ret; } |
cfc8dc6f6
|
328 |
inode = jffs2_new_inode(dir_i, S_IFLNK | S_IRWXUGO, ri); |
1da177e4c
|
329 330 331 332 333 334 335 336 337 338 |
if (IS_ERR(inode)) { jffs2_free_raw_inode(ri); jffs2_complete_reservation(c); return PTR_ERR(inode); } inode->i_op = &jffs2_symlink_inode_operations; f = JFFS2_INODE_INFO(inode); |
32f1a95d5
|
339 |
inode->i_size = targetlen; |
1da177e4c
|
340 341 342 343 344 |
ri->isize = ri->dsize = ri->csize = cpu_to_je32(inode->i_size); ri->totlen = cpu_to_je32(sizeof(*ri) + inode->i_size); ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); ri->compr = JFFS2_COMPR_NONE; |
32f1a95d5
|
345 |
ri->data_crc = cpu_to_je32(crc32(0, target, targetlen)); |
1da177e4c
|
346 |
ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); |
182ec4eee
|
347 |
|
9fe4854cd
|
348 |
fn = jffs2_write_dnode(c, f, ri, target, targetlen, ALLOC_NORMAL); |
1da177e4c
|
349 350 351 352 353 |
jffs2_free_raw_inode(ri); if (IS_ERR(fn)) { /* Eeek. Wave bye bye */ |
ced220703
|
354 |
mutex_unlock(&f->sem); |
1da177e4c
|
355 |
jffs2_complete_reservation(c); |
f324e4cb2
|
356 357 |
ret = PTR_ERR(fn); goto fail; |
1da177e4c
|
358 |
} |
32f1a95d5
|
359 |
|
2b79adcca
|
360 |
/* We use f->target field to store the target path. */ |
04aadf36d
|
361 |
f->target = kmemdup(target, targetlen + 1, GFP_KERNEL); |
2b79adcca
|
362 |
if (!f->target) { |
32f1a95d5
|
363 364 |
printk(KERN_WARNING "Can't allocate %d bytes of memory ", targetlen + 1); |
ced220703
|
365 |
mutex_unlock(&f->sem); |
32f1a95d5
|
366 |
jffs2_complete_reservation(c); |
f324e4cb2
|
367 368 |
ret = -ENOMEM; goto fail; |
32f1a95d5
|
369 |
} |
2b79adcca
|
370 371 |
D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached ", (char *)f->target)); |
32f1a95d5
|
372 |
|
182ec4eee
|
373 |
/* No data here. Only a metadata node, which will be |
1da177e4c
|
374 375 376 |
obsoleted by the first data write */ f->metadata = fn; |
ced220703
|
377 |
mutex_unlock(&f->sem); |
1da177e4c
|
378 379 |
jffs2_complete_reservation(c); |
aa98d7cf5
|
380 |
|
2a7dba391
|
381 |
ret = jffs2_init_security(inode, dir_i, &dentry->d_name); |
f324e4cb2
|
382 383 |
if (ret) goto fail; |
cfc8dc6f6
|
384 |
ret = jffs2_init_acl_post(inode); |
f324e4cb2
|
385 386 |
if (ret) goto fail; |
aa98d7cf5
|
387 |
|
9fe4854cd
|
388 389 |
ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); |
f324e4cb2
|
390 391 |
if (ret) goto fail; |
1da177e4c
|
392 393 394 395 396 |
rd = jffs2_alloc_raw_dirent(); if (!rd) { /* Argh. Now we treat it like a normal delete */ jffs2_complete_reservation(c); |
f324e4cb2
|
397 398 |
ret = -ENOMEM; goto fail; |
1da177e4c
|
399 400 401 |
} dir_f = JFFS2_INODE_INFO(dir_i); |
ced220703
|
402 |
mutex_lock(&dir_f->sem); |
1da177e4c
|
403 404 405 406 407 408 409 410 411 412 413 414 415 416 |
rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); rd->pino = cpu_to_je32(dir_i->i_ino); rd->version = cpu_to_je32(++dir_f->highest_version); rd->ino = cpu_to_je32(inode->i_ino); rd->mctime = cpu_to_je32(get_seconds()); rd->nsize = namelen; rd->type = DT_LNK; rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); |
9fe4854cd
|
417 |
fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL); |
1da177e4c
|
418 419 |
if (IS_ERR(fd)) { |
182ec4eee
|
420 |
/* dirent failed to write. Delete the inode normally |
1da177e4c
|
421 422 423 |
as if it were the final unlink() */ jffs2_complete_reservation(c); jffs2_free_raw_dirent(rd); |
ced220703
|
424 |
mutex_unlock(&dir_f->sem); |
f324e4cb2
|
425 426 |
ret = PTR_ERR(fd); goto fail; |
1da177e4c
|
427 428 429 430 431 432 433 434 435 |
} dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime)); jffs2_free_raw_dirent(rd); /* Link the fd into the inode's list, obsoleting an old one if necessary. */ jffs2_add_fd_to_list(c, fd, &dir_f->dents); |
ced220703
|
436 |
mutex_unlock(&dir_f->sem); |
1da177e4c
|
437 438 439 |
jffs2_complete_reservation(c); d_instantiate(dentry, inode); |
e72e6497e
|
440 |
unlock_new_inode(inode); |
1da177e4c
|
441 |
return 0; |
f324e4cb2
|
442 443 |
fail: |
41cce647f
|
444 |
iget_failed(inode); |
f324e4cb2
|
445 |
return ret; |
1da177e4c
|
446 447 448 449 450 451 452 453 454 455 456 457 458 |
} static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) { struct jffs2_inode_info *f, *dir_f; struct jffs2_sb_info *c; struct inode *inode; struct jffs2_raw_inode *ri; struct jffs2_raw_dirent *rd; struct jffs2_full_dnode *fn; struct jffs2_full_dirent *fd; int namelen; |
9fe4854cd
|
459 |
uint32_t alloclen; |
1da177e4c
|
460 461 462 463 464 465 466 |
int ret; mode |= S_IFDIR; ri = jffs2_alloc_raw_inode(); if (!ri) return -ENOMEM; |
182ec4eee
|
467 |
|
1da177e4c
|
468 |
c = JFFS2_SB_INFO(dir_i->i_sb); |
182ec4eee
|
469 470 |
/* Try to reserve enough space for both node and dirent. * Just the node will do for now, though |
1da177e4c
|
471 472 |
*/ namelen = dentry->d_name.len; |
9fe4854cd
|
473 474 |
ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); |
1da177e4c
|
475 476 477 478 479 |
if (ret) { jffs2_free_raw_inode(ri); return ret; } |
cfc8dc6f6
|
480 |
inode = jffs2_new_inode(dir_i, mode, ri); |
1da177e4c
|
481 482 483 484 485 486 487 488 489 |
if (IS_ERR(inode)) { jffs2_free_raw_inode(ri); jffs2_complete_reservation(c); return PTR_ERR(inode); } inode->i_op = &jffs2_dir_inode_operations; inode->i_fop = &jffs2_dir_operations; |
1da177e4c
|
490 491 |
f = JFFS2_INODE_INFO(inode); |
27c72b040
|
492 |
/* Directories get nlink 2 at start */ |
bfe868486
|
493 |
set_nlink(inode, 2); |
27c72b040
|
494 495 |
/* but ic->pino_nlink is the parent ino# */ f->inocache->pino_nlink = dir_i->i_ino; |
1da177e4c
|
496 497 |
ri->data_crc = cpu_to_je32(0); ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); |
182ec4eee
|
498 |
|
9fe4854cd
|
499 |
fn = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL); |
1da177e4c
|
500 501 502 503 504 |
jffs2_free_raw_inode(ri); if (IS_ERR(fn)) { /* Eeek. Wave bye bye */ |
ced220703
|
505 |
mutex_unlock(&f->sem); |
1da177e4c
|
506 |
jffs2_complete_reservation(c); |
f324e4cb2
|
507 508 |
ret = PTR_ERR(fn); goto fail; |
1da177e4c
|
509 |
} |
182ec4eee
|
510 |
/* No data here. Only a metadata node, which will be |
1da177e4c
|
511 512 513 |
obsoleted by the first data write */ f->metadata = fn; |
ced220703
|
514 |
mutex_unlock(&f->sem); |
1da177e4c
|
515 516 |
jffs2_complete_reservation(c); |
aa98d7cf5
|
517 |
|
2a7dba391
|
518 |
ret = jffs2_init_security(inode, dir_i, &dentry->d_name); |
f324e4cb2
|
519 520 |
if (ret) goto fail; |
cfc8dc6f6
|
521 |
ret = jffs2_init_acl_post(inode); |
f324e4cb2
|
522 523 |
if (ret) goto fail; |
aa98d7cf5
|
524 |
|
9fe4854cd
|
525 526 |
ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); |
f324e4cb2
|
527 528 |
if (ret) goto fail; |
182ec4eee
|
529 |
|
1da177e4c
|
530 531 532 533 |
rd = jffs2_alloc_raw_dirent(); if (!rd) { /* Argh. Now we treat it like a normal delete */ jffs2_complete_reservation(c); |
f324e4cb2
|
534 535 |
ret = -ENOMEM; goto fail; |
1da177e4c
|
536 537 538 |
} dir_f = JFFS2_INODE_INFO(dir_i); |
ced220703
|
539 |
mutex_lock(&dir_f->sem); |
1da177e4c
|
540 541 542 543 544 545 546 547 548 549 550 551 552 553 |
rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); rd->pino = cpu_to_je32(dir_i->i_ino); rd->version = cpu_to_je32(++dir_f->highest_version); rd->ino = cpu_to_je32(inode->i_ino); rd->mctime = cpu_to_je32(get_seconds()); rd->nsize = namelen; rd->type = DT_DIR; rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); |
9fe4854cd
|
554 |
fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL); |
182ec4eee
|
555 |
|
1da177e4c
|
556 |
if (IS_ERR(fd)) { |
182ec4eee
|
557 |
/* dirent failed to write. Delete the inode normally |
1da177e4c
|
558 559 560 |
as if it were the final unlink() */ jffs2_complete_reservation(c); jffs2_free_raw_dirent(rd); |
ced220703
|
561 |
mutex_unlock(&dir_f->sem); |
f324e4cb2
|
562 563 |
ret = PTR_ERR(fd); goto fail; |
1da177e4c
|
564 565 566 |
} dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime)); |
d8c76e6f4
|
567 |
inc_nlink(dir_i); |
1da177e4c
|
568 569 570 571 572 573 |
jffs2_free_raw_dirent(rd); /* Link the fd into the inode's list, obsoleting an old one if necessary. */ jffs2_add_fd_to_list(c, fd, &dir_f->dents); |
ced220703
|
574 |
mutex_unlock(&dir_f->sem); |
1da177e4c
|
575 576 577 |
jffs2_complete_reservation(c); d_instantiate(dentry, inode); |
e72e6497e
|
578 |
unlock_new_inode(inode); |
1da177e4c
|
579 |
return 0; |
f324e4cb2
|
580 581 |
fail: |
41cce647f
|
582 |
iget_failed(inode); |
f324e4cb2
|
583 |
return ret; |
1da177e4c
|
584 585 586 587 |
} static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry) { |
27c72b040
|
588 589 |
struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb); struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); |
1da177e4c
|
590 591 592 |
struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode); struct jffs2_full_dirent *fd; int ret; |
27c72b040
|
593 |
uint32_t now = get_seconds(); |
1da177e4c
|
594 595 596 597 598 |
for (fd = f->dents ; fd; fd = fd->next) { if (fd->ino) return -ENOTEMPTY; } |
27c72b040
|
599 600 601 602 603 604 |
ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, dentry->d_name.len, f, now); if (!ret) { dir_i->i_mtime = dir_i->i_ctime = ITIME(now); clear_nlink(dentry->d_inode); |
9a53c3a78
|
605 |
drop_nlink(dir_i); |
27c72b040
|
606 |
} |
1da177e4c
|
607 608 |
return ret; } |
265489f01
|
609 |
static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, dev_t rdev) |
1da177e4c
|
610 611 612 613 614 615 616 617 618 |
{ struct jffs2_inode_info *f, *dir_f; struct jffs2_sb_info *c; struct inode *inode; struct jffs2_raw_inode *ri; struct jffs2_raw_dirent *rd; struct jffs2_full_dnode *fn; struct jffs2_full_dirent *fd; int namelen; |
aef9ab478
|
619 |
union jffs2_device_node dev; |
1da177e4c
|
620 |
int devlen = 0; |
9fe4854cd
|
621 |
uint32_t alloclen; |
1da177e4c
|
622 |
int ret; |
aef9ab478
|
623 |
if (!new_valid_dev(rdev)) |
1da177e4c
|
624 625 626 627 628 |
return -EINVAL; ri = jffs2_alloc_raw_inode(); if (!ri) return -ENOMEM; |
182ec4eee
|
629 |
|
1da177e4c
|
630 |
c = JFFS2_SB_INFO(dir_i->i_sb); |
182ec4eee
|
631 |
|
aef9ab478
|
632 633 |
if (S_ISBLK(mode) || S_ISCHR(mode)) devlen = jffs2_encode_dev(&dev, rdev); |
182ec4eee
|
634 635 636 |
/* Try to reserve enough space for both node and dirent. * Just the node will do for now, though |
1da177e4c
|
637 638 |
*/ namelen = dentry->d_name.len; |
9fe4854cd
|
639 |
ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &alloclen, |
aef9ab478
|
640 |
ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); |
1da177e4c
|
641 642 643 644 645 |
if (ret) { jffs2_free_raw_inode(ri); return ret; } |
cfc8dc6f6
|
646 |
inode = jffs2_new_inode(dir_i, mode, ri); |
1da177e4c
|
647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 |
if (IS_ERR(inode)) { jffs2_free_raw_inode(ri); jffs2_complete_reservation(c); return PTR_ERR(inode); } inode->i_op = &jffs2_file_inode_operations; init_special_inode(inode, inode->i_mode, rdev); f = JFFS2_INODE_INFO(inode); ri->dsize = ri->csize = cpu_to_je32(devlen); ri->totlen = cpu_to_je32(sizeof(*ri) + devlen); ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); ri->compr = JFFS2_COMPR_NONE; ri->data_crc = cpu_to_je32(crc32(0, &dev, devlen)); ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); |
182ec4eee
|
665 |
|
9fe4854cd
|
666 |
fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, ALLOC_NORMAL); |
1da177e4c
|
667 668 669 670 671 |
jffs2_free_raw_inode(ri); if (IS_ERR(fn)) { /* Eeek. Wave bye bye */ |
ced220703
|
672 |
mutex_unlock(&f->sem); |
1da177e4c
|
673 |
jffs2_complete_reservation(c); |
f324e4cb2
|
674 675 |
ret = PTR_ERR(fn); goto fail; |
1da177e4c
|
676 |
} |
182ec4eee
|
677 |
/* No data here. Only a metadata node, which will be |
1da177e4c
|
678 679 680 |
obsoleted by the first data write */ f->metadata = fn; |
ced220703
|
681 |
mutex_unlock(&f->sem); |
1da177e4c
|
682 683 |
jffs2_complete_reservation(c); |
aa98d7cf5
|
684 |
|
2a7dba391
|
685 |
ret = jffs2_init_security(inode, dir_i, &dentry->d_name); |
f324e4cb2
|
686 687 |
if (ret) goto fail; |
cfc8dc6f6
|
688 |
ret = jffs2_init_acl_post(inode); |
f324e4cb2
|
689 690 |
if (ret) goto fail; |
aa98d7cf5
|
691 |
|
9fe4854cd
|
692 693 |
ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); |
f324e4cb2
|
694 695 |
if (ret) goto fail; |
1da177e4c
|
696 697 698 699 700 |
rd = jffs2_alloc_raw_dirent(); if (!rd) { /* Argh. Now we treat it like a normal delete */ jffs2_complete_reservation(c); |
f324e4cb2
|
701 702 |
ret = -ENOMEM; goto fail; |
1da177e4c
|
703 704 705 |
} dir_f = JFFS2_INODE_INFO(dir_i); |
ced220703
|
706 |
mutex_lock(&dir_f->sem); |
1da177e4c
|
707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 |
rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); rd->pino = cpu_to_je32(dir_i->i_ino); rd->version = cpu_to_je32(++dir_f->highest_version); rd->ino = cpu_to_je32(inode->i_ino); rd->mctime = cpu_to_je32(get_seconds()); rd->nsize = namelen; /* XXX: This is ugly. */ rd->type = (mode & S_IFMT) >> 12; rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); |
9fe4854cd
|
724 |
fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL); |
182ec4eee
|
725 |
|
1da177e4c
|
726 |
if (IS_ERR(fd)) { |
182ec4eee
|
727 |
/* dirent failed to write. Delete the inode normally |
1da177e4c
|
728 729 730 |
as if it were the final unlink() */ jffs2_complete_reservation(c); jffs2_free_raw_dirent(rd); |
ced220703
|
731 |
mutex_unlock(&dir_f->sem); |
f324e4cb2
|
732 733 |
ret = PTR_ERR(fd); goto fail; |
1da177e4c
|
734 735 736 737 738 739 740 741 742 |
} dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime)); jffs2_free_raw_dirent(rd); /* Link the fd into the inode's list, obsoleting an old one if necessary. */ jffs2_add_fd_to_list(c, fd, &dir_f->dents); |
ced220703
|
743 |
mutex_unlock(&dir_f->sem); |
1da177e4c
|
744 745 746 |
jffs2_complete_reservation(c); d_instantiate(dentry, inode); |
e72e6497e
|
747 |
unlock_new_inode(inode); |
1da177e4c
|
748 |
return 0; |
f324e4cb2
|
749 750 |
fail: |
41cce647f
|
751 |
iget_failed(inode); |
f324e4cb2
|
752 |
return ret; |
1da177e4c
|
753 754 755 |
} static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, |
ef53cb02f
|
756 |
struct inode *new_dir_i, struct dentry *new_dentry) |
1da177e4c
|
757 758 759 760 761 |
{ int ret; struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb); struct jffs2_inode_info *victim_f = NULL; uint8_t type; |
3a69e0cd2
|
762 |
uint32_t now; |
1da177e4c
|
763 |
|
182ec4eee
|
764 |
/* The VFS will check for us and prevent trying to rename a |
1da177e4c
|
765 766 767 768 769 770 771 772 |
* file over a directory and vice versa, but if it's a directory, * the VFS can't check whether the victim is empty. The filesystem * needs to do that for itself. */ if (new_dentry->d_inode) { victim_f = JFFS2_INODE_INFO(new_dentry->d_inode); if (S_ISDIR(new_dentry->d_inode->i_mode)) { struct jffs2_full_dirent *fd; |
ced220703
|
773 |
mutex_lock(&victim_f->sem); |
1da177e4c
|
774 775 |
for (fd = victim_f->dents; fd; fd = fd->next) { if (fd->ino) { |
ced220703
|
776 |
mutex_unlock(&victim_f->sem); |
1da177e4c
|
777 778 779 |
return -ENOTEMPTY; } } |
ced220703
|
780 |
mutex_unlock(&victim_f->sem); |
1da177e4c
|
781 782 783 784 |
} } /* XXX: We probably ought to alloc enough space for |
182ec4eee
|
785 |
both nodes at the same time. Writing the new link, |
1da177e4c
|
786 787 788 789 |
then getting -ENOSPC, is quite bad :) */ /* Make a hard link */ |
182ec4eee
|
790 |
|
1da177e4c
|
791 792 793 |
/* XXX: This is ugly */ type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12; if (!type) type = DT_REG; |
3a69e0cd2
|
794 |
now = get_seconds(); |
182ec4eee
|
795 |
ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i), |
1da177e4c
|
796 |
old_dentry->d_inode->i_ino, type, |
3a69e0cd2
|
797 |
new_dentry->d_name.name, new_dentry->d_name.len, now); |
1da177e4c
|
798 799 800 801 802 803 |
if (ret) return ret; if (victim_f) { /* There was a victim. Kill it off nicely */ |
22ba747f6
|
804 805 806 807 |
if (S_ISDIR(new_dentry->d_inode->i_mode)) clear_nlink(new_dentry->d_inode); else drop_nlink(new_dentry->d_inode); |
1da177e4c
|
808 809 810 |
/* Don't oops if the victim was a dirent pointing to an inode which didn't exist. */ if (victim_f->inocache) { |
ced220703
|
811 |
mutex_lock(&victim_f->sem); |
27c72b040
|
812 813 814 815 |
if (S_ISDIR(new_dentry->d_inode->i_mode)) victim_f->inocache->pino_nlink = 0; else victim_f->inocache->pino_nlink--; |
ced220703
|
816 |
mutex_unlock(&victim_f->sem); |
1da177e4c
|
817 818 |
} } |
182ec4eee
|
819 |
/* If it was a directory we moved, and there was no victim, |
1da177e4c
|
820 821 |
increase i_nlink on its new parent */ if (S_ISDIR(old_dentry->d_inode->i_mode) && !victim_f) |
d8c76e6f4
|
822 |
inc_nlink(new_dir_i); |
1da177e4c
|
823 824 |
/* Unlink the original */ |
182ec4eee
|
825 |
ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), |
3a69e0cd2
|
826 |
old_dentry->d_name.name, old_dentry->d_name.len, NULL, now); |
1da177e4c
|
827 828 829 830 831 832 |
/* We don't touch inode->i_nlink */ if (ret) { /* Oh shit. We really ought to make a single node which can do both atomically */ struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode); |
ced220703
|
833 |
mutex_lock(&f->sem); |
d8c76e6f4
|
834 |
inc_nlink(old_dentry->d_inode); |
27c72b040
|
835 836 |
if (f->inocache && !S_ISDIR(old_dentry->d_inode->i_mode)) f->inocache->pino_nlink++; |
ced220703
|
837 |
mutex_unlock(&f->sem); |
1da177e4c
|
838 839 840 841 842 |
printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link ", ret); /* Might as well let the VFS know */ d_instantiate(new_dentry, old_dentry->d_inode); |
7de9c6ee3
|
843 |
ihold(old_dentry->d_inode); |
3a69e0cd2
|
844 |
new_dir_i->i_mtime = new_dir_i->i_ctime = ITIME(now); |
1da177e4c
|
845 846 847 848 |
return ret; } if (S_ISDIR(old_dentry->d_inode->i_mode)) |
9a53c3a78
|
849 |
drop_nlink(old_dir_i); |
1da177e4c
|
850 |
|
3a69e0cd2
|
851 |
new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = ITIME(now); |
1da177e4c
|
852 853 |
return 0; } |