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