11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * JFFS2 -- Journalling Flash File System, Version 2. 31da177e4SLinus Torvalds * 4c00c310eSDavid Woodhouse * Copyright © 2001-2007 Red Hat, Inc. 56088c058SDavid Woodhouse * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * Created by David Woodhouse <dwmw2@infradead.org> 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * For licensing information, see the file 'LICENCE' in this directory. 101da177e4SLinus Torvalds * 111da177e4SLinus Torvalds */ 121da177e4SLinus Torvalds 135a528957SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 145a528957SJoe Perches 151da177e4SLinus Torvalds #include <linux/kernel.h> 161da177e4SLinus Torvalds #include <linux/slab.h> 171da177e4SLinus Torvalds #include <linux/fs.h> 181da177e4SLinus Torvalds #include <linux/crc32.h> 191da177e4SLinus Torvalds #include <linux/jffs2.h> 20cbb9a561SDavid Woodhouse #include "jffs2_fs_i.h" 21cbb9a561SDavid Woodhouse #include "jffs2_fs_sb.h" 221da177e4SLinus Torvalds #include <linux/time.h> 231da177e4SLinus Torvalds #include "nodelist.h" 241da177e4SLinus Torvalds 250312fa7cSAl Viro static int jffs2_readdir (struct file *, struct dir_context *); 261da177e4SLinus Torvalds 274acdaf27SAl Viro static int jffs2_create (struct inode *,struct dentry *,umode_t, 28ebfc3b49SAl Viro bool); 291da177e4SLinus Torvalds static struct dentry *jffs2_lookup (struct inode *,struct dentry *, 3000cd8dd3SAl Viro unsigned int); 311da177e4SLinus Torvalds static int jffs2_link (struct dentry *,struct inode *,struct dentry *); 321da177e4SLinus Torvalds static int jffs2_unlink (struct inode *,struct dentry *); 331da177e4SLinus Torvalds static int jffs2_symlink (struct inode *,struct dentry *,const char *); 3418bb1db3SAl Viro static int jffs2_mkdir (struct inode *,struct dentry *,umode_t); 351da177e4SLinus Torvalds static int jffs2_rmdir (struct inode *,struct dentry *); 361a67aafbSAl Viro static int jffs2_mknod (struct inode *,struct dentry *,umode_t,dev_t); 371da177e4SLinus Torvalds static int jffs2_rename (struct inode *, struct dentry *, 38*f03b8ad8SMiklos Szeredi struct inode *, struct dentry *, 39*f03b8ad8SMiklos Szeredi unsigned int); 401da177e4SLinus Torvalds 414b6f5d20SArjan van de Ven const struct file_operations jffs2_dir_operations = 421da177e4SLinus Torvalds { 431da177e4SLinus Torvalds .read = generic_read_dir, 44c51da20cSAl Viro .iterate_shared=jffs2_readdir, 450533400bSStoyan Gaydarov .unlocked_ioctl=jffs2_ioctl, 463222a3e5SChristoph Hellwig .fsync = jffs2_fsync, 473222a3e5SChristoph Hellwig .llseek = generic_file_llseek, 481da177e4SLinus Torvalds }; 491da177e4SLinus Torvalds 501da177e4SLinus Torvalds 5192e1d5beSArjan van de Ven const struct inode_operations jffs2_dir_inode_operations = 521da177e4SLinus Torvalds { 53265489f0SDavid Woodhouse .create = jffs2_create, 54265489f0SDavid Woodhouse .lookup = jffs2_lookup, 551da177e4SLinus Torvalds .link = jffs2_link, 561da177e4SLinus Torvalds .unlink = jffs2_unlink, 571da177e4SLinus Torvalds .symlink = jffs2_symlink, 581da177e4SLinus Torvalds .mkdir = jffs2_mkdir, 591da177e4SLinus Torvalds .rmdir = jffs2_rmdir, 601da177e4SLinus Torvalds .mknod = jffs2_mknod, 61*f03b8ad8SMiklos Szeredi .rename2 = jffs2_rename, 624e34e719SChristoph Hellwig .get_acl = jffs2_get_acl, 63f2963d45SChristoph Hellwig .set_acl = jffs2_set_acl, 641da177e4SLinus Torvalds .setattr = jffs2_setattr, 65aa98d7cfSKaiGai Kohei .setxattr = jffs2_setxattr, 66aa98d7cfSKaiGai Kohei .getxattr = jffs2_getxattr, 67aa98d7cfSKaiGai Kohei .listxattr = jffs2_listxattr, 68aa98d7cfSKaiGai Kohei .removexattr = jffs2_removexattr 691da177e4SLinus Torvalds }; 701da177e4SLinus Torvalds 711da177e4SLinus Torvalds /***********************************************************************/ 721da177e4SLinus Torvalds 731da177e4SLinus Torvalds 741da177e4SLinus Torvalds /* We keep the dirent list sorted in increasing order of name hash, 751da177e4SLinus Torvalds and we use the same hash function as the dentries. Makes this 761da177e4SLinus Torvalds nice and simple 771da177e4SLinus Torvalds */ 781da177e4SLinus Torvalds static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target, 7900cd8dd3SAl Viro unsigned int flags) 801da177e4SLinus Torvalds { 811da177e4SLinus Torvalds struct jffs2_inode_info *dir_f; 821da177e4SLinus Torvalds struct jffs2_full_dirent *fd = NULL, *fd_list; 831da177e4SLinus Torvalds uint32_t ino = 0; 841da177e4SLinus Torvalds struct inode *inode = NULL; 858387ff25SLinus Torvalds unsigned int nhash; 861da177e4SLinus Torvalds 879c261b33SJoe Perches jffs2_dbg(1, "jffs2_lookup()\n"); 881da177e4SLinus Torvalds 89373d5e71SRichard Purdie if (target->d_name.len > JFFS2_MAX_NAME_LEN) 90373d5e71SRichard Purdie return ERR_PTR(-ENAMETOOLONG); 91373d5e71SRichard Purdie 921da177e4SLinus Torvalds dir_f = JFFS2_INODE_INFO(dir_i); 931da177e4SLinus Torvalds 948387ff25SLinus Torvalds /* The 'nhash' on the fd_list is not the same as the dentry hash */ 958387ff25SLinus Torvalds nhash = full_name_hash(NULL, target->d_name.name, target->d_name.len); 968387ff25SLinus Torvalds 97ced22070SDavid Woodhouse mutex_lock(&dir_f->sem); 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds /* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */ 1008387ff25SLinus Torvalds for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= nhash; fd_list = fd_list->next) { 1018387ff25SLinus Torvalds if (fd_list->nhash == nhash && 1021da177e4SLinus Torvalds (!fd || fd_list->version > fd->version) && 1031da177e4SLinus Torvalds strlen(fd_list->name) == target->d_name.len && 1041da177e4SLinus Torvalds !strncmp(fd_list->name, target->d_name.name, target->d_name.len)) { 1051da177e4SLinus Torvalds fd = fd_list; 1061da177e4SLinus Torvalds } 1071da177e4SLinus Torvalds } 1081da177e4SLinus Torvalds if (fd) 1091da177e4SLinus Torvalds ino = fd->ino; 110ced22070SDavid Woodhouse mutex_unlock(&dir_f->sem); 1111da177e4SLinus Torvalds if (ino) { 1125451f79fSDavid Howells inode = jffs2_iget(dir_i->i_sb, ino); 113a9049376SAl Viro if (IS_ERR(inode)) 114da320f05SJoe Perches pr_warn("iget() failed for ino #%u\n", ino); 1151da177e4SLinus Torvalds } 1161da177e4SLinus Torvalds 1178966c5e0SDavid Woodhouse return d_splice_alias(inode, target); 1181da177e4SLinus Torvalds } 1191da177e4SLinus Torvalds 1201da177e4SLinus Torvalds /***********************************************************************/ 1211da177e4SLinus Torvalds 1221da177e4SLinus Torvalds 1230312fa7cSAl Viro static int jffs2_readdir(struct file *file, struct dir_context *ctx) 1241da177e4SLinus Torvalds { 1250312fa7cSAl Viro struct inode *inode = file_inode(file); 1260312fa7cSAl Viro struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); 1271da177e4SLinus Torvalds struct jffs2_full_dirent *fd; 1280312fa7cSAl Viro unsigned long curofs = 1; 1291da177e4SLinus Torvalds 1300312fa7cSAl Viro jffs2_dbg(1, "jffs2_readdir() for dir_i #%lu\n", inode->i_ino); 1311da177e4SLinus Torvalds 1320312fa7cSAl Viro if (!dir_emit_dots(file, ctx)) 1330312fa7cSAl Viro return 0; 1341da177e4SLinus Torvalds 135ced22070SDavid Woodhouse mutex_lock(&f->sem); 1361da177e4SLinus Torvalds for (fd = f->dents; fd; fd = fd->next) { 1371da177e4SLinus Torvalds curofs++; 1380312fa7cSAl Viro /* First loop: curofs = 2; pos = 2 */ 1390312fa7cSAl Viro if (curofs < ctx->pos) { 1409c261b33SJoe Perches jffs2_dbg(2, "Skipping dirent: \"%s\", ino #%u, type %d, because curofs %ld < offset %ld\n", 1410312fa7cSAl Viro fd->name, fd->ino, fd->type, curofs, (unsigned long)ctx->pos); 1421da177e4SLinus Torvalds continue; 1431da177e4SLinus Torvalds } 1441da177e4SLinus Torvalds if (!fd->ino) { 1459c261b33SJoe Perches jffs2_dbg(2, "Skipping deletion dirent \"%s\"\n", 1469c261b33SJoe Perches fd->name); 1470312fa7cSAl Viro ctx->pos++; 1481da177e4SLinus Torvalds continue; 1491da177e4SLinus Torvalds } 1509c261b33SJoe Perches jffs2_dbg(2, "Dirent %ld: \"%s\", ino #%u, type %d\n", 1510312fa7cSAl Viro (unsigned long)ctx->pos, fd->name, fd->ino, fd->type); 1520312fa7cSAl Viro if (!dir_emit(ctx, fd->name, strlen(fd->name), fd->ino, fd->type)) 1531da177e4SLinus Torvalds break; 1540312fa7cSAl Viro ctx->pos++; 1551da177e4SLinus Torvalds } 156ced22070SDavid Woodhouse mutex_unlock(&f->sem); 1571da177e4SLinus Torvalds return 0; 1581da177e4SLinus Torvalds } 1591da177e4SLinus Torvalds 1601da177e4SLinus Torvalds /***********************************************************************/ 1611da177e4SLinus Torvalds 1621da177e4SLinus Torvalds 1634acdaf27SAl Viro static int jffs2_create(struct inode *dir_i, struct dentry *dentry, 164ebfc3b49SAl Viro umode_t mode, bool excl) 1651da177e4SLinus Torvalds { 1661da177e4SLinus Torvalds struct jffs2_raw_inode *ri; 1671da177e4SLinus Torvalds struct jffs2_inode_info *f, *dir_f; 1681da177e4SLinus Torvalds struct jffs2_sb_info *c; 1691da177e4SLinus Torvalds struct inode *inode; 1701da177e4SLinus Torvalds int ret; 1711da177e4SLinus Torvalds 1721da177e4SLinus Torvalds ri = jffs2_alloc_raw_inode(); 1731da177e4SLinus Torvalds if (!ri) 1741da177e4SLinus Torvalds return -ENOMEM; 1751da177e4SLinus Torvalds 1761da177e4SLinus Torvalds c = JFFS2_SB_INFO(dir_i->i_sb); 1771da177e4SLinus Torvalds 1789c261b33SJoe Perches jffs2_dbg(1, "%s()\n", __func__); 1791da177e4SLinus Torvalds 180cfc8dc6fSKaiGai Kohei inode = jffs2_new_inode(dir_i, mode, ri); 1811da177e4SLinus Torvalds 1821da177e4SLinus Torvalds if (IS_ERR(inode)) { 1839c261b33SJoe Perches jffs2_dbg(1, "jffs2_new_inode() failed\n"); 1841da177e4SLinus Torvalds jffs2_free_raw_inode(ri); 1851da177e4SLinus Torvalds return PTR_ERR(inode); 1861da177e4SLinus Torvalds } 1871da177e4SLinus Torvalds 1881da177e4SLinus Torvalds inode->i_op = &jffs2_file_inode_operations; 1891da177e4SLinus Torvalds inode->i_fop = &jffs2_file_operations; 1901da177e4SLinus Torvalds inode->i_mapping->a_ops = &jffs2_file_address_operations; 1911da177e4SLinus Torvalds inode->i_mapping->nrpages = 0; 1921da177e4SLinus Torvalds 1931da177e4SLinus Torvalds f = JFFS2_INODE_INFO(inode); 1941da177e4SLinus Torvalds dir_f = JFFS2_INODE_INFO(dir_i); 1951da177e4SLinus Torvalds 196590fe34cSDavid Woodhouse /* jffs2_do_create() will want to lock it, _after_ reserving 197590fe34cSDavid Woodhouse space and taking c-alloc_sem. If we keep it locked here, 198590fe34cSDavid Woodhouse lockdep gets unhappy (although it's a false positive; 199590fe34cSDavid Woodhouse nothing else will be looking at this inode yet so there's 200590fe34cSDavid Woodhouse no chance of AB-BA deadlock involving its f->sem). */ 201590fe34cSDavid Woodhouse mutex_unlock(&f->sem); 202590fe34cSDavid Woodhouse 2032a7dba39SEric Paris ret = jffs2_do_create(c, dir_f, f, ri, &dentry->d_name); 204aa98d7cfSKaiGai Kohei if (ret) 205aa98d7cfSKaiGai Kohei goto fail; 2061da177e4SLinus Torvalds 2071da177e4SLinus Torvalds dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime)); 2081da177e4SLinus Torvalds 2091da177e4SLinus Torvalds jffs2_free_raw_inode(ri); 2101da177e4SLinus Torvalds 2119c261b33SJoe Perches jffs2_dbg(1, "%s(): Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld\n", 2129c261b33SJoe Perches __func__, inode->i_ino, inode->i_mode, inode->i_nlink, 2139c261b33SJoe Perches f->inocache->pino_nlink, inode->i_mapping->nrpages); 214e72e6497SDavid Woodhouse 215e72e6497SDavid Woodhouse unlock_new_inode(inode); 2168fc37ec5SAl Viro d_instantiate(dentry, inode); 2171da177e4SLinus Torvalds return 0; 218aa98d7cfSKaiGai Kohei 219aa98d7cfSKaiGai Kohei fail: 22041cce647SAl Viro iget_failed(inode); 221aa98d7cfSKaiGai Kohei jffs2_free_raw_inode(ri); 222aa98d7cfSKaiGai Kohei return ret; 2231da177e4SLinus Torvalds } 2241da177e4SLinus Torvalds 2251da177e4SLinus Torvalds /***********************************************************************/ 2261da177e4SLinus Torvalds 2271da177e4SLinus Torvalds 2281da177e4SLinus Torvalds static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry) 2291da177e4SLinus Torvalds { 2301da177e4SLinus Torvalds struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb); 2311da177e4SLinus Torvalds struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); 2322b0143b5SDavid Howells struct jffs2_inode_info *dead_f = JFFS2_INODE_INFO(d_inode(dentry)); 2331da177e4SLinus Torvalds int ret; 2343a69e0cdSArtem B. Bityutskiy uint32_t now = get_seconds(); 2351da177e4SLinus Torvalds 2361da177e4SLinus Torvalds ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, 2373a69e0cdSArtem B. Bityutskiy dentry->d_name.len, dead_f, now); 2381da177e4SLinus Torvalds if (dead_f->inocache) 2392b0143b5SDavid Howells set_nlink(d_inode(dentry), dead_f->inocache->pino_nlink); 2403a69e0cdSArtem B. Bityutskiy if (!ret) 2413a69e0cdSArtem B. Bityutskiy dir_i->i_mtime = dir_i->i_ctime = ITIME(now); 2421da177e4SLinus Torvalds return ret; 2431da177e4SLinus Torvalds } 2441da177e4SLinus Torvalds /***********************************************************************/ 2451da177e4SLinus Torvalds 2461da177e4SLinus Torvalds 2471da177e4SLinus Torvalds static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct dentry *dentry) 2481da177e4SLinus Torvalds { 249fc64005cSAl Viro struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dentry->d_sb); 2502b0143b5SDavid Howells struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode(old_dentry)); 2511da177e4SLinus Torvalds struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); 2521da177e4SLinus Torvalds int ret; 2531da177e4SLinus Torvalds uint8_t type; 2543a69e0cdSArtem B. Bityutskiy uint32_t now; 2551da177e4SLinus Torvalds 2561da177e4SLinus Torvalds /* Don't let people make hard links to bad inodes. */ 2571da177e4SLinus Torvalds if (!f->inocache) 2581da177e4SLinus Torvalds return -EIO; 2591da177e4SLinus Torvalds 260e36cb0b8SDavid Howells if (d_is_dir(old_dentry)) 2611da177e4SLinus Torvalds return -EPERM; 2621da177e4SLinus Torvalds 2631da177e4SLinus Torvalds /* XXX: This is ugly */ 2642b0143b5SDavid Howells type = (d_inode(old_dentry)->i_mode & S_IFMT) >> 12; 2651da177e4SLinus Torvalds if (!type) type = DT_REG; 2661da177e4SLinus Torvalds 2673a69e0cdSArtem B. Bityutskiy now = get_seconds(); 2683a69e0cdSArtem B. Bityutskiy ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, dentry->d_name.name, dentry->d_name.len, now); 2691da177e4SLinus Torvalds 2701da177e4SLinus Torvalds if (!ret) { 271ced22070SDavid Woodhouse mutex_lock(&f->sem); 2722b0143b5SDavid Howells set_nlink(d_inode(old_dentry), ++f->inocache->pino_nlink); 273ced22070SDavid Woodhouse mutex_unlock(&f->sem); 2742b0143b5SDavid Howells d_instantiate(dentry, d_inode(old_dentry)); 2753a69e0cdSArtem B. Bityutskiy dir_i->i_mtime = dir_i->i_ctime = ITIME(now); 2762b0143b5SDavid Howells ihold(d_inode(old_dentry)); 2771da177e4SLinus Torvalds } 2781da177e4SLinus Torvalds return ret; 2791da177e4SLinus Torvalds } 2801da177e4SLinus Torvalds 2811da177e4SLinus Torvalds /***********************************************************************/ 2821da177e4SLinus Torvalds 2831da177e4SLinus Torvalds static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char *target) 2841da177e4SLinus Torvalds { 2851da177e4SLinus Torvalds struct jffs2_inode_info *f, *dir_f; 2861da177e4SLinus Torvalds struct jffs2_sb_info *c; 2871da177e4SLinus Torvalds struct inode *inode; 2881da177e4SLinus Torvalds struct jffs2_raw_inode *ri; 2891da177e4SLinus Torvalds struct jffs2_raw_dirent *rd; 2901da177e4SLinus Torvalds struct jffs2_full_dnode *fn; 2911da177e4SLinus Torvalds struct jffs2_full_dirent *fd; 2921da177e4SLinus Torvalds int namelen; 2939fe4854cSDavid Woodhouse uint32_t alloclen; 29432f1a95dSArtem B. Bityuckiy int ret, targetlen = strlen(target); 2951da177e4SLinus Torvalds 2961da177e4SLinus Torvalds /* FIXME: If you care. We'd need to use frags for the target 2971da177e4SLinus Torvalds if it grows much more than this */ 29832f1a95dSArtem B. Bityuckiy if (targetlen > 254) 299bde86fecSAdrian Hunter return -ENAMETOOLONG; 3001da177e4SLinus Torvalds 3011da177e4SLinus Torvalds ri = jffs2_alloc_raw_inode(); 3021da177e4SLinus Torvalds 3031da177e4SLinus Torvalds if (!ri) 3041da177e4SLinus Torvalds return -ENOMEM; 3051da177e4SLinus Torvalds 3061da177e4SLinus Torvalds c = JFFS2_SB_INFO(dir_i->i_sb); 3071da177e4SLinus Torvalds 3081da177e4SLinus Torvalds /* Try to reserve enough space for both node and dirent. 3091da177e4SLinus Torvalds * Just the node will do for now, though 3101da177e4SLinus Torvalds */ 3111da177e4SLinus Torvalds namelen = dentry->d_name.len; 3129fe4854cSDavid Woodhouse ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &alloclen, 313e631ddbaSFerenc Havasi ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); 3141da177e4SLinus Torvalds 3151da177e4SLinus Torvalds if (ret) { 3161da177e4SLinus Torvalds jffs2_free_raw_inode(ri); 3171da177e4SLinus Torvalds return ret; 3181da177e4SLinus Torvalds } 3191da177e4SLinus Torvalds 320cfc8dc6fSKaiGai Kohei inode = jffs2_new_inode(dir_i, S_IFLNK | S_IRWXUGO, ri); 3211da177e4SLinus Torvalds 3221da177e4SLinus Torvalds if (IS_ERR(inode)) { 3231da177e4SLinus Torvalds jffs2_free_raw_inode(ri); 3241da177e4SLinus Torvalds jffs2_complete_reservation(c); 3251da177e4SLinus Torvalds return PTR_ERR(inode); 3261da177e4SLinus Torvalds } 3271da177e4SLinus Torvalds 3281da177e4SLinus Torvalds inode->i_op = &jffs2_symlink_inode_operations; 3291da177e4SLinus Torvalds 3301da177e4SLinus Torvalds f = JFFS2_INODE_INFO(inode); 3311da177e4SLinus Torvalds 33232f1a95dSArtem B. Bityuckiy inode->i_size = targetlen; 3331da177e4SLinus Torvalds ri->isize = ri->dsize = ri->csize = cpu_to_je32(inode->i_size); 3341da177e4SLinus Torvalds ri->totlen = cpu_to_je32(sizeof(*ri) + inode->i_size); 3351da177e4SLinus Torvalds ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); 3361da177e4SLinus Torvalds 3371da177e4SLinus Torvalds ri->compr = JFFS2_COMPR_NONE; 33832f1a95dSArtem B. Bityuckiy ri->data_crc = cpu_to_je32(crc32(0, target, targetlen)); 3391da177e4SLinus Torvalds ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); 3401da177e4SLinus Torvalds 3419fe4854cSDavid Woodhouse fn = jffs2_write_dnode(c, f, ri, target, targetlen, ALLOC_NORMAL); 3421da177e4SLinus Torvalds 3431da177e4SLinus Torvalds jffs2_free_raw_inode(ri); 3441da177e4SLinus Torvalds 3451da177e4SLinus Torvalds if (IS_ERR(fn)) { 3461da177e4SLinus Torvalds /* Eeek. Wave bye bye */ 347ced22070SDavid Woodhouse mutex_unlock(&f->sem); 3481da177e4SLinus Torvalds jffs2_complete_reservation(c); 349f324e4cbSDavid Woodhouse ret = PTR_ERR(fn); 350f324e4cbSDavid Woodhouse goto fail; 3511da177e4SLinus Torvalds } 35232f1a95dSArtem B. Bityuckiy 3532b79adccSArtem B. Bityutskiy /* We use f->target field to store the target path. */ 35404aadf36SJulia Lawall f->target = kmemdup(target, targetlen + 1, GFP_KERNEL); 3552b79adccSArtem B. Bityutskiy if (!f->target) { 356da320f05SJoe Perches pr_warn("Can't allocate %d bytes of memory\n", targetlen + 1); 357ced22070SDavid Woodhouse mutex_unlock(&f->sem); 35832f1a95dSArtem B. Bityuckiy jffs2_complete_reservation(c); 359f324e4cbSDavid Woodhouse ret = -ENOMEM; 360f324e4cbSDavid Woodhouse goto fail; 36132f1a95dSArtem B. Bityuckiy } 362a8db149fSAl Viro inode->i_link = f->target; 36332f1a95dSArtem B. Bityuckiy 3649c261b33SJoe Perches jffs2_dbg(1, "%s(): symlink's target '%s' cached\n", 3659c261b33SJoe Perches __func__, (char *)f->target); 36632f1a95dSArtem B. Bityuckiy 3671da177e4SLinus Torvalds /* No data here. Only a metadata node, which will be 3681da177e4SLinus Torvalds obsoleted by the first data write 3691da177e4SLinus Torvalds */ 3701da177e4SLinus Torvalds f->metadata = fn; 371ced22070SDavid Woodhouse mutex_unlock(&f->sem); 3721da177e4SLinus Torvalds 3731da177e4SLinus Torvalds jffs2_complete_reservation(c); 374aa98d7cfSKaiGai Kohei 3752a7dba39SEric Paris ret = jffs2_init_security(inode, dir_i, &dentry->d_name); 376f324e4cbSDavid Woodhouse if (ret) 377f324e4cbSDavid Woodhouse goto fail; 378f324e4cbSDavid Woodhouse 379cfc8dc6fSKaiGai Kohei ret = jffs2_init_acl_post(inode); 380f324e4cbSDavid Woodhouse if (ret) 381f324e4cbSDavid Woodhouse goto fail; 382aa98d7cfSKaiGai Kohei 3839fe4854cSDavid Woodhouse ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, 384e631ddbaSFerenc Havasi ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); 385f324e4cbSDavid Woodhouse if (ret) 386f324e4cbSDavid Woodhouse goto fail; 3871da177e4SLinus Torvalds 3881da177e4SLinus Torvalds rd = jffs2_alloc_raw_dirent(); 3891da177e4SLinus Torvalds if (!rd) { 3901da177e4SLinus Torvalds /* Argh. Now we treat it like a normal delete */ 3911da177e4SLinus Torvalds jffs2_complete_reservation(c); 392f324e4cbSDavid Woodhouse ret = -ENOMEM; 393f324e4cbSDavid Woodhouse goto fail; 3941da177e4SLinus Torvalds } 3951da177e4SLinus Torvalds 3961da177e4SLinus Torvalds dir_f = JFFS2_INODE_INFO(dir_i); 397ced22070SDavid Woodhouse mutex_lock(&dir_f->sem); 3981da177e4SLinus Torvalds 3991da177e4SLinus Torvalds rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 4001da177e4SLinus Torvalds rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); 4011da177e4SLinus Torvalds rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); 4021da177e4SLinus Torvalds rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); 4031da177e4SLinus Torvalds 4041da177e4SLinus Torvalds rd->pino = cpu_to_je32(dir_i->i_ino); 4051da177e4SLinus Torvalds rd->version = cpu_to_je32(++dir_f->highest_version); 4061da177e4SLinus Torvalds rd->ino = cpu_to_je32(inode->i_ino); 4071da177e4SLinus Torvalds rd->mctime = cpu_to_je32(get_seconds()); 4081da177e4SLinus Torvalds rd->nsize = namelen; 4091da177e4SLinus Torvalds rd->type = DT_LNK; 4101da177e4SLinus Torvalds rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); 4111da177e4SLinus Torvalds rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); 4121da177e4SLinus Torvalds 4139fe4854cSDavid Woodhouse fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL); 4141da177e4SLinus Torvalds 4151da177e4SLinus Torvalds if (IS_ERR(fd)) { 4161da177e4SLinus Torvalds /* dirent failed to write. Delete the inode normally 4171da177e4SLinus Torvalds as if it were the final unlink() */ 4181da177e4SLinus Torvalds jffs2_complete_reservation(c); 4191da177e4SLinus Torvalds jffs2_free_raw_dirent(rd); 420ced22070SDavid Woodhouse mutex_unlock(&dir_f->sem); 421f324e4cbSDavid Woodhouse ret = PTR_ERR(fd); 422f324e4cbSDavid Woodhouse goto fail; 4231da177e4SLinus Torvalds } 4241da177e4SLinus Torvalds 4251da177e4SLinus Torvalds dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime)); 4261da177e4SLinus Torvalds 4271da177e4SLinus Torvalds jffs2_free_raw_dirent(rd); 4281da177e4SLinus Torvalds 4291da177e4SLinus Torvalds /* Link the fd into the inode's list, obsoleting an old 4301da177e4SLinus Torvalds one if necessary. */ 4311da177e4SLinus Torvalds jffs2_add_fd_to_list(c, fd, &dir_f->dents); 4321da177e4SLinus Torvalds 433ced22070SDavid Woodhouse mutex_unlock(&dir_f->sem); 4341da177e4SLinus Torvalds jffs2_complete_reservation(c); 4351da177e4SLinus Torvalds 436e72e6497SDavid Woodhouse unlock_new_inode(inode); 4378fc37ec5SAl Viro d_instantiate(dentry, inode); 4381da177e4SLinus Torvalds return 0; 439f324e4cbSDavid Woodhouse 440f324e4cbSDavid Woodhouse fail: 44141cce647SAl Viro iget_failed(inode); 442f324e4cbSDavid Woodhouse return ret; 4431da177e4SLinus Torvalds } 4441da177e4SLinus Torvalds 4451da177e4SLinus Torvalds 44618bb1db3SAl Viro static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, umode_t mode) 4471da177e4SLinus Torvalds { 4481da177e4SLinus Torvalds struct jffs2_inode_info *f, *dir_f; 4491da177e4SLinus Torvalds struct jffs2_sb_info *c; 4501da177e4SLinus Torvalds struct inode *inode; 4511da177e4SLinus Torvalds struct jffs2_raw_inode *ri; 4521da177e4SLinus Torvalds struct jffs2_raw_dirent *rd; 4531da177e4SLinus Torvalds struct jffs2_full_dnode *fn; 4541da177e4SLinus Torvalds struct jffs2_full_dirent *fd; 4551da177e4SLinus Torvalds int namelen; 4569fe4854cSDavid Woodhouse uint32_t alloclen; 4571da177e4SLinus Torvalds int ret; 4581da177e4SLinus Torvalds 4591da177e4SLinus Torvalds mode |= S_IFDIR; 4601da177e4SLinus Torvalds 4611da177e4SLinus Torvalds ri = jffs2_alloc_raw_inode(); 4621da177e4SLinus Torvalds if (!ri) 4631da177e4SLinus Torvalds return -ENOMEM; 4641da177e4SLinus Torvalds 4651da177e4SLinus Torvalds c = JFFS2_SB_INFO(dir_i->i_sb); 4661da177e4SLinus Torvalds 4671da177e4SLinus Torvalds /* Try to reserve enough space for both node and dirent. 4681da177e4SLinus Torvalds * Just the node will do for now, though 4691da177e4SLinus Torvalds */ 4701da177e4SLinus Torvalds namelen = dentry->d_name.len; 4719fe4854cSDavid Woodhouse ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL, 472e631ddbaSFerenc Havasi JFFS2_SUMMARY_INODE_SIZE); 4731da177e4SLinus Torvalds 4741da177e4SLinus Torvalds if (ret) { 4751da177e4SLinus Torvalds jffs2_free_raw_inode(ri); 4761da177e4SLinus Torvalds return ret; 4771da177e4SLinus Torvalds } 4781da177e4SLinus Torvalds 479cfc8dc6fSKaiGai Kohei inode = jffs2_new_inode(dir_i, mode, ri); 4801da177e4SLinus Torvalds 4811da177e4SLinus Torvalds if (IS_ERR(inode)) { 4821da177e4SLinus Torvalds jffs2_free_raw_inode(ri); 4831da177e4SLinus Torvalds jffs2_complete_reservation(c); 4841da177e4SLinus Torvalds return PTR_ERR(inode); 4851da177e4SLinus Torvalds } 4861da177e4SLinus Torvalds 4871da177e4SLinus Torvalds inode->i_op = &jffs2_dir_inode_operations; 4881da177e4SLinus Torvalds inode->i_fop = &jffs2_dir_operations; 4891da177e4SLinus Torvalds 4901da177e4SLinus Torvalds f = JFFS2_INODE_INFO(inode); 4911da177e4SLinus Torvalds 49227c72b04SDavid Woodhouse /* Directories get nlink 2 at start */ 493bfe86848SMiklos Szeredi set_nlink(inode, 2); 49427c72b04SDavid Woodhouse /* but ic->pino_nlink is the parent ino# */ 49527c72b04SDavid Woodhouse f->inocache->pino_nlink = dir_i->i_ino; 49627c72b04SDavid Woodhouse 4971da177e4SLinus Torvalds ri->data_crc = cpu_to_je32(0); 4981da177e4SLinus Torvalds ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); 4991da177e4SLinus Torvalds 5009fe4854cSDavid Woodhouse fn = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL); 5011da177e4SLinus Torvalds 5021da177e4SLinus Torvalds jffs2_free_raw_inode(ri); 5031da177e4SLinus Torvalds 5041da177e4SLinus Torvalds if (IS_ERR(fn)) { 5051da177e4SLinus Torvalds /* Eeek. Wave bye bye */ 506ced22070SDavid Woodhouse mutex_unlock(&f->sem); 5071da177e4SLinus Torvalds jffs2_complete_reservation(c); 508f324e4cbSDavid Woodhouse ret = PTR_ERR(fn); 509f324e4cbSDavid Woodhouse goto fail; 5101da177e4SLinus Torvalds } 5111da177e4SLinus Torvalds /* No data here. Only a metadata node, which will be 5121da177e4SLinus Torvalds obsoleted by the first data write 5131da177e4SLinus Torvalds */ 5141da177e4SLinus Torvalds f->metadata = fn; 515ced22070SDavid Woodhouse mutex_unlock(&f->sem); 5161da177e4SLinus Torvalds 5171da177e4SLinus Torvalds jffs2_complete_reservation(c); 518aa98d7cfSKaiGai Kohei 5192a7dba39SEric Paris ret = jffs2_init_security(inode, dir_i, &dentry->d_name); 520f324e4cbSDavid Woodhouse if (ret) 521f324e4cbSDavid Woodhouse goto fail; 522f324e4cbSDavid Woodhouse 523cfc8dc6fSKaiGai Kohei ret = jffs2_init_acl_post(inode); 524f324e4cbSDavid Woodhouse if (ret) 525f324e4cbSDavid Woodhouse goto fail; 526aa98d7cfSKaiGai Kohei 5279fe4854cSDavid Woodhouse ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, 528e631ddbaSFerenc Havasi ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); 529f324e4cbSDavid Woodhouse if (ret) 530f324e4cbSDavid Woodhouse goto fail; 5311da177e4SLinus Torvalds 5321da177e4SLinus Torvalds rd = jffs2_alloc_raw_dirent(); 5331da177e4SLinus Torvalds if (!rd) { 5341da177e4SLinus Torvalds /* Argh. Now we treat it like a normal delete */ 5351da177e4SLinus Torvalds jffs2_complete_reservation(c); 536f324e4cbSDavid Woodhouse ret = -ENOMEM; 537f324e4cbSDavid Woodhouse goto fail; 5381da177e4SLinus Torvalds } 5391da177e4SLinus Torvalds 5401da177e4SLinus Torvalds dir_f = JFFS2_INODE_INFO(dir_i); 541ced22070SDavid Woodhouse mutex_lock(&dir_f->sem); 5421da177e4SLinus Torvalds 5431da177e4SLinus Torvalds rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 5441da177e4SLinus Torvalds rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); 5451da177e4SLinus Torvalds rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); 5461da177e4SLinus Torvalds rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); 5471da177e4SLinus Torvalds 5481da177e4SLinus Torvalds rd->pino = cpu_to_je32(dir_i->i_ino); 5491da177e4SLinus Torvalds rd->version = cpu_to_je32(++dir_f->highest_version); 5501da177e4SLinus Torvalds rd->ino = cpu_to_je32(inode->i_ino); 5511da177e4SLinus Torvalds rd->mctime = cpu_to_je32(get_seconds()); 5521da177e4SLinus Torvalds rd->nsize = namelen; 5531da177e4SLinus Torvalds rd->type = DT_DIR; 5541da177e4SLinus Torvalds rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); 5551da177e4SLinus Torvalds rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); 5561da177e4SLinus Torvalds 5579fe4854cSDavid Woodhouse fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL); 5581da177e4SLinus Torvalds 5591da177e4SLinus Torvalds if (IS_ERR(fd)) { 5601da177e4SLinus Torvalds /* dirent failed to write. Delete the inode normally 5611da177e4SLinus Torvalds as if it were the final unlink() */ 5621da177e4SLinus Torvalds jffs2_complete_reservation(c); 5631da177e4SLinus Torvalds jffs2_free_raw_dirent(rd); 564ced22070SDavid Woodhouse mutex_unlock(&dir_f->sem); 565f324e4cbSDavid Woodhouse ret = PTR_ERR(fd); 566f324e4cbSDavid Woodhouse goto fail; 5671da177e4SLinus Torvalds } 5681da177e4SLinus Torvalds 5691da177e4SLinus Torvalds dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime)); 570d8c76e6fSDave Hansen inc_nlink(dir_i); 5711da177e4SLinus Torvalds 5721da177e4SLinus Torvalds jffs2_free_raw_dirent(rd); 5731da177e4SLinus Torvalds 5741da177e4SLinus Torvalds /* Link the fd into the inode's list, obsoleting an old 5751da177e4SLinus Torvalds one if necessary. */ 5761da177e4SLinus Torvalds jffs2_add_fd_to_list(c, fd, &dir_f->dents); 5771da177e4SLinus Torvalds 578ced22070SDavid Woodhouse mutex_unlock(&dir_f->sem); 5791da177e4SLinus Torvalds jffs2_complete_reservation(c); 5801da177e4SLinus Torvalds 581e72e6497SDavid Woodhouse unlock_new_inode(inode); 5828fc37ec5SAl Viro d_instantiate(dentry, inode); 5831da177e4SLinus Torvalds return 0; 584f324e4cbSDavid Woodhouse 585f324e4cbSDavid Woodhouse fail: 58641cce647SAl Viro iget_failed(inode); 587f324e4cbSDavid Woodhouse return ret; 5881da177e4SLinus Torvalds } 5891da177e4SLinus Torvalds 5901da177e4SLinus Torvalds static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry) 5911da177e4SLinus Torvalds { 59227c72b04SDavid Woodhouse struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb); 59327c72b04SDavid Woodhouse struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); 5942b0143b5SDavid Howells struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode(dentry)); 5951da177e4SLinus Torvalds struct jffs2_full_dirent *fd; 5961da177e4SLinus Torvalds int ret; 59727c72b04SDavid Woodhouse uint32_t now = get_seconds(); 5981da177e4SLinus Torvalds 5991da177e4SLinus Torvalds for (fd = f->dents ; fd; fd = fd->next) { 6001da177e4SLinus Torvalds if (fd->ino) 6011da177e4SLinus Torvalds return -ENOTEMPTY; 6021da177e4SLinus Torvalds } 60327c72b04SDavid Woodhouse 60427c72b04SDavid Woodhouse ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, 60527c72b04SDavid Woodhouse dentry->d_name.len, f, now); 60627c72b04SDavid Woodhouse if (!ret) { 60727c72b04SDavid Woodhouse dir_i->i_mtime = dir_i->i_ctime = ITIME(now); 6082b0143b5SDavid Howells clear_nlink(d_inode(dentry)); 6099a53c3a7SDave Hansen drop_nlink(dir_i); 61027c72b04SDavid Woodhouse } 6111da177e4SLinus Torvalds return ret; 6121da177e4SLinus Torvalds } 6131da177e4SLinus Torvalds 6141a67aafbSAl Viro static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, umode_t mode, dev_t rdev) 6151da177e4SLinus Torvalds { 6161da177e4SLinus Torvalds struct jffs2_inode_info *f, *dir_f; 6171da177e4SLinus Torvalds struct jffs2_sb_info *c; 6181da177e4SLinus Torvalds struct inode *inode; 6191da177e4SLinus Torvalds struct jffs2_raw_inode *ri; 6201da177e4SLinus Torvalds struct jffs2_raw_dirent *rd; 6211da177e4SLinus Torvalds struct jffs2_full_dnode *fn; 6221da177e4SLinus Torvalds struct jffs2_full_dirent *fd; 6231da177e4SLinus Torvalds int namelen; 624aef9ab47SDavid Woodhouse union jffs2_device_node dev; 6251da177e4SLinus Torvalds int devlen = 0; 6269fe4854cSDavid Woodhouse uint32_t alloclen; 6271da177e4SLinus Torvalds int ret; 6281da177e4SLinus Torvalds 6291da177e4SLinus Torvalds ri = jffs2_alloc_raw_inode(); 6301da177e4SLinus Torvalds if (!ri) 6311da177e4SLinus Torvalds return -ENOMEM; 6321da177e4SLinus Torvalds 6331da177e4SLinus Torvalds c = JFFS2_SB_INFO(dir_i->i_sb); 6341da177e4SLinus Torvalds 635aef9ab47SDavid Woodhouse if (S_ISBLK(mode) || S_ISCHR(mode)) 636aef9ab47SDavid Woodhouse devlen = jffs2_encode_dev(&dev, rdev); 6371da177e4SLinus Torvalds 6381da177e4SLinus Torvalds /* Try to reserve enough space for both node and dirent. 6391da177e4SLinus Torvalds * Just the node will do for now, though 6401da177e4SLinus Torvalds */ 6411da177e4SLinus Torvalds namelen = dentry->d_name.len; 6429fe4854cSDavid Woodhouse ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &alloclen, 643e631ddbaSFerenc Havasi ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); 6441da177e4SLinus Torvalds 6451da177e4SLinus Torvalds if (ret) { 6461da177e4SLinus Torvalds jffs2_free_raw_inode(ri); 6471da177e4SLinus Torvalds return ret; 6481da177e4SLinus Torvalds } 6491da177e4SLinus Torvalds 650cfc8dc6fSKaiGai Kohei inode = jffs2_new_inode(dir_i, mode, ri); 6511da177e4SLinus Torvalds 6521da177e4SLinus Torvalds if (IS_ERR(inode)) { 6531da177e4SLinus Torvalds jffs2_free_raw_inode(ri); 6541da177e4SLinus Torvalds jffs2_complete_reservation(c); 6551da177e4SLinus Torvalds return PTR_ERR(inode); 6561da177e4SLinus Torvalds } 6571da177e4SLinus Torvalds inode->i_op = &jffs2_file_inode_operations; 6581da177e4SLinus Torvalds init_special_inode(inode, inode->i_mode, rdev); 6591da177e4SLinus Torvalds 6601da177e4SLinus Torvalds f = JFFS2_INODE_INFO(inode); 6611da177e4SLinus Torvalds 6621da177e4SLinus Torvalds ri->dsize = ri->csize = cpu_to_je32(devlen); 6631da177e4SLinus Torvalds ri->totlen = cpu_to_je32(sizeof(*ri) + devlen); 6641da177e4SLinus Torvalds ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); 6651da177e4SLinus Torvalds 6661da177e4SLinus Torvalds ri->compr = JFFS2_COMPR_NONE; 6671da177e4SLinus Torvalds ri->data_crc = cpu_to_je32(crc32(0, &dev, devlen)); 6681da177e4SLinus Torvalds ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); 6691da177e4SLinus Torvalds 6709fe4854cSDavid Woodhouse fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, ALLOC_NORMAL); 6711da177e4SLinus Torvalds 6721da177e4SLinus Torvalds jffs2_free_raw_inode(ri); 6731da177e4SLinus Torvalds 6741da177e4SLinus Torvalds if (IS_ERR(fn)) { 6751da177e4SLinus Torvalds /* Eeek. Wave bye bye */ 676ced22070SDavid Woodhouse mutex_unlock(&f->sem); 6771da177e4SLinus Torvalds jffs2_complete_reservation(c); 678f324e4cbSDavid Woodhouse ret = PTR_ERR(fn); 679f324e4cbSDavid Woodhouse goto fail; 6801da177e4SLinus Torvalds } 6811da177e4SLinus Torvalds /* No data here. Only a metadata node, which will be 6821da177e4SLinus Torvalds obsoleted by the first data write 6831da177e4SLinus Torvalds */ 6841da177e4SLinus Torvalds f->metadata = fn; 685ced22070SDavid Woodhouse mutex_unlock(&f->sem); 6861da177e4SLinus Torvalds 6871da177e4SLinus Torvalds jffs2_complete_reservation(c); 688aa98d7cfSKaiGai Kohei 6892a7dba39SEric Paris ret = jffs2_init_security(inode, dir_i, &dentry->d_name); 690f324e4cbSDavid Woodhouse if (ret) 691f324e4cbSDavid Woodhouse goto fail; 692f324e4cbSDavid Woodhouse 693cfc8dc6fSKaiGai Kohei ret = jffs2_init_acl_post(inode); 694f324e4cbSDavid Woodhouse if (ret) 695f324e4cbSDavid Woodhouse goto fail; 696aa98d7cfSKaiGai Kohei 6979fe4854cSDavid Woodhouse ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, 698e631ddbaSFerenc Havasi ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); 699f324e4cbSDavid Woodhouse if (ret) 700f324e4cbSDavid Woodhouse goto fail; 7011da177e4SLinus Torvalds 7021da177e4SLinus Torvalds rd = jffs2_alloc_raw_dirent(); 7031da177e4SLinus Torvalds if (!rd) { 7041da177e4SLinus Torvalds /* Argh. Now we treat it like a normal delete */ 7051da177e4SLinus Torvalds jffs2_complete_reservation(c); 706f324e4cbSDavid Woodhouse ret = -ENOMEM; 707f324e4cbSDavid Woodhouse goto fail; 7081da177e4SLinus Torvalds } 7091da177e4SLinus Torvalds 7101da177e4SLinus Torvalds dir_f = JFFS2_INODE_INFO(dir_i); 711ced22070SDavid Woodhouse mutex_lock(&dir_f->sem); 7121da177e4SLinus Torvalds 7131da177e4SLinus Torvalds rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 7141da177e4SLinus Torvalds rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); 7151da177e4SLinus Torvalds rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); 7161da177e4SLinus Torvalds rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); 7171da177e4SLinus Torvalds 7181da177e4SLinus Torvalds rd->pino = cpu_to_je32(dir_i->i_ino); 7191da177e4SLinus Torvalds rd->version = cpu_to_je32(++dir_f->highest_version); 7201da177e4SLinus Torvalds rd->ino = cpu_to_je32(inode->i_ino); 7211da177e4SLinus Torvalds rd->mctime = cpu_to_je32(get_seconds()); 7221da177e4SLinus Torvalds rd->nsize = namelen; 7231da177e4SLinus Torvalds 7241da177e4SLinus Torvalds /* XXX: This is ugly. */ 7251da177e4SLinus Torvalds rd->type = (mode & S_IFMT) >> 12; 7261da177e4SLinus Torvalds 7271da177e4SLinus Torvalds rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); 7281da177e4SLinus Torvalds rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); 7291da177e4SLinus Torvalds 7309fe4854cSDavid Woodhouse fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL); 7311da177e4SLinus Torvalds 7321da177e4SLinus Torvalds if (IS_ERR(fd)) { 7331da177e4SLinus Torvalds /* dirent failed to write. Delete the inode normally 7341da177e4SLinus Torvalds as if it were the final unlink() */ 7351da177e4SLinus Torvalds jffs2_complete_reservation(c); 7361da177e4SLinus Torvalds jffs2_free_raw_dirent(rd); 737ced22070SDavid Woodhouse mutex_unlock(&dir_f->sem); 738f324e4cbSDavid Woodhouse ret = PTR_ERR(fd); 739f324e4cbSDavid Woodhouse goto fail; 7401da177e4SLinus Torvalds } 7411da177e4SLinus Torvalds 7421da177e4SLinus Torvalds dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime)); 7431da177e4SLinus Torvalds 7441da177e4SLinus Torvalds jffs2_free_raw_dirent(rd); 7451da177e4SLinus Torvalds 7461da177e4SLinus Torvalds /* Link the fd into the inode's list, obsoleting an old 7471da177e4SLinus Torvalds one if necessary. */ 7481da177e4SLinus Torvalds jffs2_add_fd_to_list(c, fd, &dir_f->dents); 7491da177e4SLinus Torvalds 750ced22070SDavid Woodhouse mutex_unlock(&dir_f->sem); 7511da177e4SLinus Torvalds jffs2_complete_reservation(c); 7521da177e4SLinus Torvalds 753e72e6497SDavid Woodhouse unlock_new_inode(inode); 7548fc37ec5SAl Viro d_instantiate(dentry, inode); 7551da177e4SLinus Torvalds return 0; 756f324e4cbSDavid Woodhouse 757f324e4cbSDavid Woodhouse fail: 75841cce647SAl Viro iget_failed(inode); 759f324e4cbSDavid Woodhouse return ret; 7601da177e4SLinus Torvalds } 7611da177e4SLinus Torvalds 7621da177e4SLinus Torvalds static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, 763*f03b8ad8SMiklos Szeredi struct inode *new_dir_i, struct dentry *new_dentry, 764*f03b8ad8SMiklos Szeredi unsigned int flags) 7651da177e4SLinus Torvalds { 7661da177e4SLinus Torvalds int ret; 7671da177e4SLinus Torvalds struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb); 7681da177e4SLinus Torvalds struct jffs2_inode_info *victim_f = NULL; 7691da177e4SLinus Torvalds uint8_t type; 7703a69e0cdSArtem B. Bityutskiy uint32_t now; 7711da177e4SLinus Torvalds 772*f03b8ad8SMiklos Szeredi if (flags & ~RENAME_NOREPLACE) 773*f03b8ad8SMiklos Szeredi return -EINVAL; 774*f03b8ad8SMiklos Szeredi 7751da177e4SLinus Torvalds /* The VFS will check for us and prevent trying to rename a 7761da177e4SLinus Torvalds * file over a directory and vice versa, but if it's a directory, 7771da177e4SLinus Torvalds * the VFS can't check whether the victim is empty. The filesystem 7781da177e4SLinus Torvalds * needs to do that for itself. 7791da177e4SLinus Torvalds */ 7802b0143b5SDavid Howells if (d_really_is_positive(new_dentry)) { 7812b0143b5SDavid Howells victim_f = JFFS2_INODE_INFO(d_inode(new_dentry)); 782e36cb0b8SDavid Howells if (d_is_dir(new_dentry)) { 7831da177e4SLinus Torvalds struct jffs2_full_dirent *fd; 7841da177e4SLinus Torvalds 785ced22070SDavid Woodhouse mutex_lock(&victim_f->sem); 7861da177e4SLinus Torvalds for (fd = victim_f->dents; fd; fd = fd->next) { 7871da177e4SLinus Torvalds if (fd->ino) { 788ced22070SDavid Woodhouse mutex_unlock(&victim_f->sem); 7891da177e4SLinus Torvalds return -ENOTEMPTY; 7901da177e4SLinus Torvalds } 7911da177e4SLinus Torvalds } 792ced22070SDavid Woodhouse mutex_unlock(&victim_f->sem); 7931da177e4SLinus Torvalds } 7941da177e4SLinus Torvalds } 7951da177e4SLinus Torvalds 7961da177e4SLinus Torvalds /* XXX: We probably ought to alloc enough space for 7971da177e4SLinus Torvalds both nodes at the same time. Writing the new link, 7981da177e4SLinus Torvalds then getting -ENOSPC, is quite bad :) 7991da177e4SLinus Torvalds */ 8001da177e4SLinus Torvalds 8011da177e4SLinus Torvalds /* Make a hard link */ 8021da177e4SLinus Torvalds 8031da177e4SLinus Torvalds /* XXX: This is ugly */ 8042b0143b5SDavid Howells type = (d_inode(old_dentry)->i_mode & S_IFMT) >> 12; 8051da177e4SLinus Torvalds if (!type) type = DT_REG; 8061da177e4SLinus Torvalds 8073a69e0cdSArtem B. Bityutskiy now = get_seconds(); 8081da177e4SLinus Torvalds ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i), 8092b0143b5SDavid Howells d_inode(old_dentry)->i_ino, type, 8103a69e0cdSArtem B. Bityutskiy new_dentry->d_name.name, new_dentry->d_name.len, now); 8111da177e4SLinus Torvalds 8121da177e4SLinus Torvalds if (ret) 8131da177e4SLinus Torvalds return ret; 8141da177e4SLinus Torvalds 8151da177e4SLinus Torvalds if (victim_f) { 8161da177e4SLinus Torvalds /* There was a victim. Kill it off nicely */ 817e36cb0b8SDavid Howells if (d_is_dir(new_dentry)) 8182b0143b5SDavid Howells clear_nlink(d_inode(new_dentry)); 81922ba747fSAl Viro else 8202b0143b5SDavid Howells drop_nlink(d_inode(new_dentry)); 8211da177e4SLinus Torvalds /* Don't oops if the victim was a dirent pointing to an 8221da177e4SLinus Torvalds inode which didn't exist. */ 8231da177e4SLinus Torvalds if (victim_f->inocache) { 824ced22070SDavid Woodhouse mutex_lock(&victim_f->sem); 825e36cb0b8SDavid Howells if (d_is_dir(new_dentry)) 82627c72b04SDavid Woodhouse victim_f->inocache->pino_nlink = 0; 82727c72b04SDavid Woodhouse else 82827c72b04SDavid Woodhouse victim_f->inocache->pino_nlink--; 829ced22070SDavid Woodhouse mutex_unlock(&victim_f->sem); 8301da177e4SLinus Torvalds } 8311da177e4SLinus Torvalds } 8321da177e4SLinus Torvalds 8331da177e4SLinus Torvalds /* If it was a directory we moved, and there was no victim, 8341da177e4SLinus Torvalds increase i_nlink on its new parent */ 835e36cb0b8SDavid Howells if (d_is_dir(old_dentry) && !victim_f) 836d8c76e6fSDave Hansen inc_nlink(new_dir_i); 8371da177e4SLinus Torvalds 8381da177e4SLinus Torvalds /* Unlink the original */ 8391da177e4SLinus Torvalds ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), 8403a69e0cdSArtem B. Bityutskiy old_dentry->d_name.name, old_dentry->d_name.len, NULL, now); 8411da177e4SLinus Torvalds 8421da177e4SLinus Torvalds /* We don't touch inode->i_nlink */ 8431da177e4SLinus Torvalds 8441da177e4SLinus Torvalds if (ret) { 8451da177e4SLinus Torvalds /* Oh shit. We really ought to make a single node which can do both atomically */ 8462b0143b5SDavid Howells struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode(old_dentry)); 847ced22070SDavid Woodhouse mutex_lock(&f->sem); 8482b0143b5SDavid Howells inc_nlink(d_inode(old_dentry)); 849e36cb0b8SDavid Howells if (f->inocache && !d_is_dir(old_dentry)) 85027c72b04SDavid Woodhouse f->inocache->pino_nlink++; 851ced22070SDavid Woodhouse mutex_unlock(&f->sem); 8521da177e4SLinus Torvalds 853da320f05SJoe Perches pr_notice("%s(): Link succeeded, unlink failed (err %d). You now have a hard link\n", 854da320f05SJoe Perches __func__, ret); 855f9381284SAl Viro /* 856f9381284SAl Viro * We can't keep the target in dcache after that. 857f9381284SAl Viro * For one thing, we can't afford dentry aliases for directories. 858f9381284SAl Viro * For another, if there was a victim, we _can't_ set new inode 859f9381284SAl Viro * for that sucker and we have to trigger mount eviction - the 860f9381284SAl Viro * caller won't do it on its own since we are returning an error. 861f9381284SAl Viro */ 862f9381284SAl Viro d_invalidate(new_dentry); 8633a69e0cdSArtem B. Bityutskiy new_dir_i->i_mtime = new_dir_i->i_ctime = ITIME(now); 8641da177e4SLinus Torvalds return ret; 8651da177e4SLinus Torvalds } 8661da177e4SLinus Torvalds 867e36cb0b8SDavid Howells if (d_is_dir(old_dentry)) 8689a53c3a7SDave Hansen drop_nlink(old_dir_i); 8691da177e4SLinus Torvalds 8703a69e0cdSArtem B. Bityutskiy new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = ITIME(now); 8713a69e0cdSArtem B. Bityutskiy 8721da177e4SLinus Torvalds return 0; 8731da177e4SLinus Torvalds } 8741da177e4SLinus Torvalds 875