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 276c960e68SChristian Brauner static int jffs2_create (struct mnt_idmap *, struct inode *, 28549c7297SChristian Brauner struct dentry *, umode_t, 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 *); 33*7a77db95SChristian Brauner static int jffs2_symlink (struct mnt_idmap *, struct inode *, 34549c7297SChristian Brauner struct dentry *, const char *); 35549c7297SChristian Brauner static int jffs2_mkdir (struct user_namespace *, struct inode *,struct dentry *, 36549c7297SChristian Brauner umode_t); 371da177e4SLinus Torvalds static int jffs2_rmdir (struct inode *,struct dentry *); 38549c7297SChristian Brauner static int jffs2_mknod (struct user_namespace *, struct inode *,struct dentry *, 39549c7297SChristian Brauner umode_t,dev_t); 40549c7297SChristian Brauner static int jffs2_rename (struct user_namespace *, struct inode *, 41549c7297SChristian Brauner struct dentry *, struct inode *, struct dentry *, 42f03b8ad8SMiklos Szeredi unsigned int); 431da177e4SLinus Torvalds 444b6f5d20SArjan van de Ven const struct file_operations jffs2_dir_operations = 451da177e4SLinus Torvalds { 461da177e4SLinus Torvalds .read = generic_read_dir, 47c51da20cSAl Viro .iterate_shared=jffs2_readdir, 480533400bSStoyan Gaydarov .unlocked_ioctl=jffs2_ioctl, 493222a3e5SChristoph Hellwig .fsync = jffs2_fsync, 503222a3e5SChristoph Hellwig .llseek = generic_file_llseek, 511da177e4SLinus Torvalds }; 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds 5492e1d5beSArjan van de Ven const struct inode_operations jffs2_dir_inode_operations = 551da177e4SLinus Torvalds { 56265489f0SDavid Woodhouse .create = jffs2_create, 57265489f0SDavid Woodhouse .lookup = jffs2_lookup, 581da177e4SLinus Torvalds .link = jffs2_link, 591da177e4SLinus Torvalds .unlink = jffs2_unlink, 601da177e4SLinus Torvalds .symlink = jffs2_symlink, 611da177e4SLinus Torvalds .mkdir = jffs2_mkdir, 621da177e4SLinus Torvalds .rmdir = jffs2_rmdir, 631da177e4SLinus Torvalds .mknod = jffs2_mknod, 641da177e4SLinus Torvalds .rename = jffs2_rename, 65cac2f8b8SChristian Brauner .get_inode_acl = jffs2_get_acl, 66f2963d45SChristoph Hellwig .set_acl = jffs2_set_acl, 671da177e4SLinus Torvalds .setattr = jffs2_setattr, 68aa98d7cfSKaiGai Kohei .listxattr = jffs2_listxattr, 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 1636c960e68SChristian Brauner static int jffs2_create(struct mnt_idmap *idmap, struct inode *dir_i, 164549c7297SChristian Brauner struct dentry *dentry, 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 207c4592b9cSArnd Bergmann 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 2151e2e547aSAl Viro d_instantiate_new(dentry, inode); 2161da177e4SLinus Torvalds return 0; 217aa98d7cfSKaiGai Kohei 218aa98d7cfSKaiGai Kohei fail: 21941cce647SAl Viro iget_failed(inode); 220aa98d7cfSKaiGai Kohei jffs2_free_raw_inode(ri); 221aa98d7cfSKaiGai Kohei return ret; 2221da177e4SLinus Torvalds } 2231da177e4SLinus Torvalds 2241da177e4SLinus Torvalds /***********************************************************************/ 2251da177e4SLinus Torvalds 2261da177e4SLinus Torvalds 2271da177e4SLinus Torvalds static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry) 2281da177e4SLinus Torvalds { 2291da177e4SLinus Torvalds struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb); 2301da177e4SLinus Torvalds struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); 2312b0143b5SDavid Howells struct jffs2_inode_info *dead_f = JFFS2_INODE_INFO(d_inode(dentry)); 2321da177e4SLinus Torvalds int ret; 233c4592b9cSArnd Bergmann uint32_t now = JFFS2_NOW(); 2341da177e4SLinus Torvalds 2351da177e4SLinus Torvalds ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, 2363a69e0cdSArtem B. Bityutskiy dentry->d_name.len, dead_f, now); 2371da177e4SLinus Torvalds if (dead_f->inocache) 2382b0143b5SDavid Howells set_nlink(d_inode(dentry), dead_f->inocache->pino_nlink); 2393a69e0cdSArtem B. Bityutskiy if (!ret) 240c4592b9cSArnd Bergmann dir_i->i_mtime = dir_i->i_ctime = ITIME(now); 2411da177e4SLinus Torvalds return ret; 2421da177e4SLinus Torvalds } 2431da177e4SLinus Torvalds /***********************************************************************/ 2441da177e4SLinus Torvalds 2451da177e4SLinus Torvalds 2461da177e4SLinus Torvalds static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct dentry *dentry) 2471da177e4SLinus Torvalds { 248fc64005cSAl Viro struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dentry->d_sb); 2492b0143b5SDavid Howells struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode(old_dentry)); 2501da177e4SLinus Torvalds struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); 2511da177e4SLinus Torvalds int ret; 2521da177e4SLinus Torvalds uint8_t type; 2533a69e0cdSArtem B. Bityutskiy uint32_t now; 2541da177e4SLinus Torvalds 2551da177e4SLinus Torvalds /* Don't let people make hard links to bad inodes. */ 2561da177e4SLinus Torvalds if (!f->inocache) 2571da177e4SLinus Torvalds return -EIO; 2581da177e4SLinus Torvalds 259e36cb0b8SDavid Howells if (d_is_dir(old_dentry)) 2601da177e4SLinus Torvalds return -EPERM; 2611da177e4SLinus Torvalds 2621da177e4SLinus Torvalds /* XXX: This is ugly */ 2632b0143b5SDavid Howells type = (d_inode(old_dentry)->i_mode & S_IFMT) >> 12; 2641da177e4SLinus Torvalds if (!type) type = DT_REG; 2651da177e4SLinus Torvalds 266c4592b9cSArnd Bergmann now = JFFS2_NOW(); 2673a69e0cdSArtem B. Bityutskiy ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, dentry->d_name.name, dentry->d_name.len, now); 2681da177e4SLinus Torvalds 2691da177e4SLinus Torvalds if (!ret) { 270ced22070SDavid Woodhouse mutex_lock(&f->sem); 2712b0143b5SDavid Howells set_nlink(d_inode(old_dentry), ++f->inocache->pino_nlink); 272ced22070SDavid Woodhouse mutex_unlock(&f->sem); 2732b0143b5SDavid Howells d_instantiate(dentry, d_inode(old_dentry)); 274c4592b9cSArnd Bergmann dir_i->i_mtime = dir_i->i_ctime = ITIME(now); 2752b0143b5SDavid Howells ihold(d_inode(old_dentry)); 2761da177e4SLinus Torvalds } 2771da177e4SLinus Torvalds return ret; 2781da177e4SLinus Torvalds } 2791da177e4SLinus Torvalds 2801da177e4SLinus Torvalds /***********************************************************************/ 2811da177e4SLinus Torvalds 282*7a77db95SChristian Brauner static int jffs2_symlink (struct mnt_idmap *idmap, struct inode *dir_i, 283549c7297SChristian Brauner 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); 407c4592b9cSArnd Bergmann rd->mctime = cpu_to_je32(JFFS2_NOW()); 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 425c4592b9cSArnd Bergmann 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 4361e2e547aSAl Viro d_instantiate_new(dentry, inode); 4371da177e4SLinus Torvalds return 0; 438f324e4cbSDavid Woodhouse 439f324e4cbSDavid Woodhouse fail: 44041cce647SAl Viro iget_failed(inode); 441f324e4cbSDavid Woodhouse return ret; 4421da177e4SLinus Torvalds } 4431da177e4SLinus Torvalds 4441da177e4SLinus Torvalds 445549c7297SChristian Brauner static int jffs2_mkdir (struct user_namespace *mnt_userns, struct inode *dir_i, 446549c7297SChristian Brauner 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); 551c4592b9cSArnd Bergmann rd->mctime = cpu_to_je32(JFFS2_NOW()); 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 569c4592b9cSArnd Bergmann 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 5811e2e547aSAl Viro d_instantiate_new(dentry, inode); 5821da177e4SLinus Torvalds return 0; 583f324e4cbSDavid Woodhouse 584f324e4cbSDavid Woodhouse fail: 58541cce647SAl Viro iget_failed(inode); 586f324e4cbSDavid Woodhouse return ret; 5871da177e4SLinus Torvalds } 5881da177e4SLinus Torvalds 5891da177e4SLinus Torvalds static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry) 5901da177e4SLinus Torvalds { 59127c72b04SDavid Woodhouse struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb); 59227c72b04SDavid Woodhouse struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i); 5932b0143b5SDavid Howells struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode(dentry)); 5941da177e4SLinus Torvalds struct jffs2_full_dirent *fd; 5951da177e4SLinus Torvalds int ret; 596c4592b9cSArnd Bergmann uint32_t now = JFFS2_NOW(); 5971da177e4SLinus Torvalds 598798b7347SZhe Li mutex_lock(&f->sem); 5991da177e4SLinus Torvalds for (fd = f->dents ; fd; fd = fd->next) { 600798b7347SZhe Li if (fd->ino) { 601798b7347SZhe Li mutex_unlock(&f->sem); 6021da177e4SLinus Torvalds return -ENOTEMPTY; 6031da177e4SLinus Torvalds } 604798b7347SZhe Li } 605798b7347SZhe Li mutex_unlock(&f->sem); 60627c72b04SDavid Woodhouse 60727c72b04SDavid Woodhouse ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, 60827c72b04SDavid Woodhouse dentry->d_name.len, f, now); 60927c72b04SDavid Woodhouse if (!ret) { 610c4592b9cSArnd Bergmann dir_i->i_mtime = dir_i->i_ctime = ITIME(now); 6112b0143b5SDavid Howells clear_nlink(d_inode(dentry)); 6129a53c3a7SDave Hansen drop_nlink(dir_i); 61327c72b04SDavid Woodhouse } 6141da177e4SLinus Torvalds return ret; 6151da177e4SLinus Torvalds } 6161da177e4SLinus Torvalds 617549c7297SChristian Brauner static int jffs2_mknod (struct user_namespace *mnt_userns, struct inode *dir_i, 618549c7297SChristian Brauner struct dentry *dentry, umode_t mode, dev_t rdev) 6191da177e4SLinus Torvalds { 6201da177e4SLinus Torvalds struct jffs2_inode_info *f, *dir_f; 6211da177e4SLinus Torvalds struct jffs2_sb_info *c; 6221da177e4SLinus Torvalds struct inode *inode; 6231da177e4SLinus Torvalds struct jffs2_raw_inode *ri; 6241da177e4SLinus Torvalds struct jffs2_raw_dirent *rd; 6251da177e4SLinus Torvalds struct jffs2_full_dnode *fn; 6261da177e4SLinus Torvalds struct jffs2_full_dirent *fd; 6271da177e4SLinus Torvalds int namelen; 628aef9ab47SDavid Woodhouse union jffs2_device_node dev; 6291da177e4SLinus Torvalds int devlen = 0; 6309fe4854cSDavid Woodhouse uint32_t alloclen; 6311da177e4SLinus Torvalds int ret; 6321da177e4SLinus Torvalds 6331da177e4SLinus Torvalds ri = jffs2_alloc_raw_inode(); 6341da177e4SLinus Torvalds if (!ri) 6351da177e4SLinus Torvalds return -ENOMEM; 6361da177e4SLinus Torvalds 6371da177e4SLinus Torvalds c = JFFS2_SB_INFO(dir_i->i_sb); 6381da177e4SLinus Torvalds 639aef9ab47SDavid Woodhouse if (S_ISBLK(mode) || S_ISCHR(mode)) 640aef9ab47SDavid Woodhouse devlen = jffs2_encode_dev(&dev, rdev); 6411da177e4SLinus Torvalds 6421da177e4SLinus Torvalds /* Try to reserve enough space for both node and dirent. 6431da177e4SLinus Torvalds * Just the node will do for now, though 6441da177e4SLinus Torvalds */ 6451da177e4SLinus Torvalds namelen = dentry->d_name.len; 6469fe4854cSDavid Woodhouse ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &alloclen, 647e631ddbaSFerenc Havasi ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); 6481da177e4SLinus Torvalds 6491da177e4SLinus Torvalds if (ret) { 6501da177e4SLinus Torvalds jffs2_free_raw_inode(ri); 6511da177e4SLinus Torvalds return ret; 6521da177e4SLinus Torvalds } 6531da177e4SLinus Torvalds 654cfc8dc6fSKaiGai Kohei inode = jffs2_new_inode(dir_i, mode, ri); 6551da177e4SLinus Torvalds 6561da177e4SLinus Torvalds if (IS_ERR(inode)) { 6571da177e4SLinus Torvalds jffs2_free_raw_inode(ri); 6581da177e4SLinus Torvalds jffs2_complete_reservation(c); 6591da177e4SLinus Torvalds return PTR_ERR(inode); 6601da177e4SLinus Torvalds } 6611da177e4SLinus Torvalds inode->i_op = &jffs2_file_inode_operations; 6621da177e4SLinus Torvalds init_special_inode(inode, inode->i_mode, rdev); 6631da177e4SLinus Torvalds 6641da177e4SLinus Torvalds f = JFFS2_INODE_INFO(inode); 6651da177e4SLinus Torvalds 6661da177e4SLinus Torvalds ri->dsize = ri->csize = cpu_to_je32(devlen); 6671da177e4SLinus Torvalds ri->totlen = cpu_to_je32(sizeof(*ri) + devlen); 6681da177e4SLinus Torvalds ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); 6691da177e4SLinus Torvalds 6701da177e4SLinus Torvalds ri->compr = JFFS2_COMPR_NONE; 6711da177e4SLinus Torvalds ri->data_crc = cpu_to_je32(crc32(0, &dev, devlen)); 6721da177e4SLinus Torvalds ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); 6731da177e4SLinus Torvalds 6749fe4854cSDavid Woodhouse fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, ALLOC_NORMAL); 6751da177e4SLinus Torvalds 6761da177e4SLinus Torvalds jffs2_free_raw_inode(ri); 6771da177e4SLinus Torvalds 6781da177e4SLinus Torvalds if (IS_ERR(fn)) { 6791da177e4SLinus Torvalds /* Eeek. Wave bye bye */ 680ced22070SDavid Woodhouse mutex_unlock(&f->sem); 6811da177e4SLinus Torvalds jffs2_complete_reservation(c); 682f324e4cbSDavid Woodhouse ret = PTR_ERR(fn); 683f324e4cbSDavid Woodhouse goto fail; 6841da177e4SLinus Torvalds } 6851da177e4SLinus Torvalds /* No data here. Only a metadata node, which will be 6861da177e4SLinus Torvalds obsoleted by the first data write 6871da177e4SLinus Torvalds */ 6881da177e4SLinus Torvalds f->metadata = fn; 689ced22070SDavid Woodhouse mutex_unlock(&f->sem); 6901da177e4SLinus Torvalds 6911da177e4SLinus Torvalds jffs2_complete_reservation(c); 692aa98d7cfSKaiGai Kohei 6932a7dba39SEric Paris ret = jffs2_init_security(inode, dir_i, &dentry->d_name); 694f324e4cbSDavid Woodhouse if (ret) 695f324e4cbSDavid Woodhouse goto fail; 696f324e4cbSDavid Woodhouse 697cfc8dc6fSKaiGai Kohei ret = jffs2_init_acl_post(inode); 698f324e4cbSDavid Woodhouse if (ret) 699f324e4cbSDavid Woodhouse goto fail; 700aa98d7cfSKaiGai Kohei 7019fe4854cSDavid Woodhouse ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, 702e631ddbaSFerenc Havasi ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); 703f324e4cbSDavid Woodhouse if (ret) 704f324e4cbSDavid Woodhouse goto fail; 7051da177e4SLinus Torvalds 7061da177e4SLinus Torvalds rd = jffs2_alloc_raw_dirent(); 7071da177e4SLinus Torvalds if (!rd) { 7081da177e4SLinus Torvalds /* Argh. Now we treat it like a normal delete */ 7091da177e4SLinus Torvalds jffs2_complete_reservation(c); 710f324e4cbSDavid Woodhouse ret = -ENOMEM; 711f324e4cbSDavid Woodhouse goto fail; 7121da177e4SLinus Torvalds } 7131da177e4SLinus Torvalds 7141da177e4SLinus Torvalds dir_f = JFFS2_INODE_INFO(dir_i); 715ced22070SDavid Woodhouse mutex_lock(&dir_f->sem); 7161da177e4SLinus Torvalds 7171da177e4SLinus Torvalds rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 7181da177e4SLinus Torvalds rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); 7191da177e4SLinus Torvalds rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); 7201da177e4SLinus Torvalds rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); 7211da177e4SLinus Torvalds 7221da177e4SLinus Torvalds rd->pino = cpu_to_je32(dir_i->i_ino); 7231da177e4SLinus Torvalds rd->version = cpu_to_je32(++dir_f->highest_version); 7241da177e4SLinus Torvalds rd->ino = cpu_to_je32(inode->i_ino); 725c4592b9cSArnd Bergmann rd->mctime = cpu_to_je32(JFFS2_NOW()); 7261da177e4SLinus Torvalds rd->nsize = namelen; 7271da177e4SLinus Torvalds 7281da177e4SLinus Torvalds /* XXX: This is ugly. */ 7291da177e4SLinus Torvalds rd->type = (mode & S_IFMT) >> 12; 7301da177e4SLinus Torvalds 7311da177e4SLinus Torvalds rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); 7321da177e4SLinus Torvalds rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); 7331da177e4SLinus Torvalds 7349fe4854cSDavid Woodhouse fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL); 7351da177e4SLinus Torvalds 7361da177e4SLinus Torvalds if (IS_ERR(fd)) { 7371da177e4SLinus Torvalds /* dirent failed to write. Delete the inode normally 7381da177e4SLinus Torvalds as if it were the final unlink() */ 7391da177e4SLinus Torvalds jffs2_complete_reservation(c); 7401da177e4SLinus Torvalds jffs2_free_raw_dirent(rd); 741ced22070SDavid Woodhouse mutex_unlock(&dir_f->sem); 742f324e4cbSDavid Woodhouse ret = PTR_ERR(fd); 743f324e4cbSDavid Woodhouse goto fail; 7441da177e4SLinus Torvalds } 7451da177e4SLinus Torvalds 746c4592b9cSArnd Bergmann dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime)); 7471da177e4SLinus Torvalds 7481da177e4SLinus Torvalds jffs2_free_raw_dirent(rd); 7491da177e4SLinus Torvalds 7501da177e4SLinus Torvalds /* Link the fd into the inode's list, obsoleting an old 7511da177e4SLinus Torvalds one if necessary. */ 7521da177e4SLinus Torvalds jffs2_add_fd_to_list(c, fd, &dir_f->dents); 7531da177e4SLinus Torvalds 754ced22070SDavid Woodhouse mutex_unlock(&dir_f->sem); 7551da177e4SLinus Torvalds jffs2_complete_reservation(c); 7561da177e4SLinus Torvalds 7571e2e547aSAl Viro d_instantiate_new(dentry, inode); 7581da177e4SLinus Torvalds return 0; 759f324e4cbSDavid Woodhouse 760f324e4cbSDavid Woodhouse fail: 76141cce647SAl Viro iget_failed(inode); 762f324e4cbSDavid Woodhouse return ret; 7631da177e4SLinus Torvalds } 7641da177e4SLinus Torvalds 765549c7297SChristian Brauner static int jffs2_rename (struct user_namespace *mnt_userns, 766549c7297SChristian Brauner struct inode *old_dir_i, struct dentry *old_dentry, 767f03b8ad8SMiklos Szeredi struct inode *new_dir_i, struct dentry *new_dentry, 768f03b8ad8SMiklos Szeredi unsigned int flags) 7691da177e4SLinus Torvalds { 7701da177e4SLinus Torvalds int ret; 7711da177e4SLinus Torvalds struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb); 7721da177e4SLinus Torvalds struct jffs2_inode_info *victim_f = NULL; 7731da177e4SLinus Torvalds uint8_t type; 7743a69e0cdSArtem B. Bityutskiy uint32_t now; 7751da177e4SLinus Torvalds 776f03b8ad8SMiklos Szeredi if (flags & ~RENAME_NOREPLACE) 777f03b8ad8SMiklos Szeredi return -EINVAL; 778f03b8ad8SMiklos Szeredi 7791da177e4SLinus Torvalds /* The VFS will check for us and prevent trying to rename a 7801da177e4SLinus Torvalds * file over a directory and vice versa, but if it's a directory, 7811da177e4SLinus Torvalds * the VFS can't check whether the victim is empty. The filesystem 7821da177e4SLinus Torvalds * needs to do that for itself. 7831da177e4SLinus Torvalds */ 7842b0143b5SDavid Howells if (d_really_is_positive(new_dentry)) { 7852b0143b5SDavid Howells victim_f = JFFS2_INODE_INFO(d_inode(new_dentry)); 786e36cb0b8SDavid Howells if (d_is_dir(new_dentry)) { 7871da177e4SLinus Torvalds struct jffs2_full_dirent *fd; 7881da177e4SLinus Torvalds 789ced22070SDavid Woodhouse mutex_lock(&victim_f->sem); 7901da177e4SLinus Torvalds for (fd = victim_f->dents; fd; fd = fd->next) { 7911da177e4SLinus Torvalds if (fd->ino) { 792ced22070SDavid Woodhouse mutex_unlock(&victim_f->sem); 7931da177e4SLinus Torvalds return -ENOTEMPTY; 7941da177e4SLinus Torvalds } 7951da177e4SLinus Torvalds } 796ced22070SDavid Woodhouse mutex_unlock(&victim_f->sem); 7971da177e4SLinus Torvalds } 7981da177e4SLinus Torvalds } 7991da177e4SLinus Torvalds 8001da177e4SLinus Torvalds /* XXX: We probably ought to alloc enough space for 8011da177e4SLinus Torvalds both nodes at the same time. Writing the new link, 8021da177e4SLinus Torvalds then getting -ENOSPC, is quite bad :) 8031da177e4SLinus Torvalds */ 8041da177e4SLinus Torvalds 8051da177e4SLinus Torvalds /* Make a hard link */ 8061da177e4SLinus Torvalds 8071da177e4SLinus Torvalds /* XXX: This is ugly */ 8082b0143b5SDavid Howells type = (d_inode(old_dentry)->i_mode & S_IFMT) >> 12; 8091da177e4SLinus Torvalds if (!type) type = DT_REG; 8101da177e4SLinus Torvalds 811c4592b9cSArnd Bergmann now = JFFS2_NOW(); 8121da177e4SLinus Torvalds ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i), 8132b0143b5SDavid Howells d_inode(old_dentry)->i_ino, type, 8143a69e0cdSArtem B. Bityutskiy new_dentry->d_name.name, new_dentry->d_name.len, now); 8151da177e4SLinus Torvalds 8161da177e4SLinus Torvalds if (ret) 8171da177e4SLinus Torvalds return ret; 8181da177e4SLinus Torvalds 8191da177e4SLinus Torvalds if (victim_f) { 8201da177e4SLinus Torvalds /* There was a victim. Kill it off nicely */ 821e36cb0b8SDavid Howells if (d_is_dir(new_dentry)) 8222b0143b5SDavid Howells clear_nlink(d_inode(new_dentry)); 82322ba747fSAl Viro else 8242b0143b5SDavid Howells drop_nlink(d_inode(new_dentry)); 8251da177e4SLinus Torvalds /* Don't oops if the victim was a dirent pointing to an 8261da177e4SLinus Torvalds inode which didn't exist. */ 8271da177e4SLinus Torvalds if (victim_f->inocache) { 828ced22070SDavid Woodhouse mutex_lock(&victim_f->sem); 829e36cb0b8SDavid Howells if (d_is_dir(new_dentry)) 83027c72b04SDavid Woodhouse victim_f->inocache->pino_nlink = 0; 83127c72b04SDavid Woodhouse else 83227c72b04SDavid Woodhouse victim_f->inocache->pino_nlink--; 833ced22070SDavid Woodhouse mutex_unlock(&victim_f->sem); 8341da177e4SLinus Torvalds } 8351da177e4SLinus Torvalds } 8361da177e4SLinus Torvalds 8371da177e4SLinus Torvalds /* If it was a directory we moved, and there was no victim, 8381da177e4SLinus Torvalds increase i_nlink on its new parent */ 839e36cb0b8SDavid Howells if (d_is_dir(old_dentry) && !victim_f) 840d8c76e6fSDave Hansen inc_nlink(new_dir_i); 8411da177e4SLinus Torvalds 8421da177e4SLinus Torvalds /* Unlink the original */ 8431da177e4SLinus Torvalds ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), 8443a69e0cdSArtem B. Bityutskiy old_dentry->d_name.name, old_dentry->d_name.len, NULL, now); 8451da177e4SLinus Torvalds 8461da177e4SLinus Torvalds /* We don't touch inode->i_nlink */ 8471da177e4SLinus Torvalds 8481da177e4SLinus Torvalds if (ret) { 8491da177e4SLinus Torvalds /* Oh shit. We really ought to make a single node which can do both atomically */ 8502b0143b5SDavid Howells struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode(old_dentry)); 851ced22070SDavid Woodhouse mutex_lock(&f->sem); 8522b0143b5SDavid Howells inc_nlink(d_inode(old_dentry)); 853e36cb0b8SDavid Howells if (f->inocache && !d_is_dir(old_dentry)) 85427c72b04SDavid Woodhouse f->inocache->pino_nlink++; 855ced22070SDavid Woodhouse mutex_unlock(&f->sem); 8561da177e4SLinus Torvalds 857da320f05SJoe Perches pr_notice("%s(): Link succeeded, unlink failed (err %d). You now have a hard link\n", 858da320f05SJoe Perches __func__, ret); 859f9381284SAl Viro /* 860f9381284SAl Viro * We can't keep the target in dcache after that. 861f9381284SAl Viro * For one thing, we can't afford dentry aliases for directories. 862f9381284SAl Viro * For another, if there was a victim, we _can't_ set new inode 863f9381284SAl Viro * for that sucker and we have to trigger mount eviction - the 864f9381284SAl Viro * caller won't do it on its own since we are returning an error. 865f9381284SAl Viro */ 866f9381284SAl Viro d_invalidate(new_dentry); 867c4592b9cSArnd Bergmann new_dir_i->i_mtime = new_dir_i->i_ctime = ITIME(now); 8681da177e4SLinus Torvalds return ret; 8691da177e4SLinus Torvalds } 8701da177e4SLinus Torvalds 871e36cb0b8SDavid Howells if (d_is_dir(old_dentry)) 8729a53c3a7SDave Hansen drop_nlink(old_dir_i); 8731da177e4SLinus Torvalds 874c4592b9cSArnd Bergmann new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = ITIME(now); 8753a69e0cdSArtem B. Bityutskiy 8761da177e4SLinus Torvalds return 0; 8771da177e4SLinus Torvalds } 8781da177e4SLinus Torvalds 879