ubifs: Add full hash lookup support
[linux-2.6-block.git] / fs / ubifs / journal.c
index 0b9da5b6e0f966192408b4ddd1ec18bf7ce9555a..0698cccc62239c9795fc55a0afb8241ec94193c9 100644 (file)
@@ -78,16 +78,6 @@ static inline void zero_ino_node_unused(struct ubifs_ino_node *ino)
 static inline void zero_dent_node_unused(struct ubifs_dent_node *dent)
 {
        dent->padding1 = 0;
-       memset(dent->padding2, 0, 4);
-}
-
-/**
- * zero_data_node_unused - zero out unused fields of an on-flash data node.
- * @data: the data node to zero out
- */
-static inline void zero_data_node_unused(struct ubifs_data_node *data)
-{
-       memset(data->padding, 0, 2);
 }
 
 /**
@@ -539,7 +529,7 @@ static void mark_inode_clean(struct ubifs_info *c, struct ubifs_inode *ui)
  * success. In case of failure, a negative error code is returned.
  */
 int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
-                    const struct qstr *nm, const struct inode *inode,
+                    const struct fscrypt_name *nm, const struct inode *inode,
                     int deletion, int xent)
 {
        int err, dlen, ilen, len, lnum, ino_offs, dent_offs;
@@ -551,11 +541,11 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
        struct ubifs_ino_node *ino;
        union ubifs_key dent_key, ino_key;
 
-       dbg_jnl("ino %lu, dent '%.*s', data len %d in dir ino %lu",
-               inode->i_ino, nm->len, nm->name, ui->data_len, dir->i_ino);
+       //dbg_jnl("ino %lu, dent '%.*s', data len %d in dir ino %lu",
+       //      inode->i_ino, nm->len, nm->name, ui->data_len, dir->i_ino);
        ubifs_assert(mutex_is_locked(&host_ui->ui_mutex));
 
-       dlen = UBIFS_DENT_NODE_SZ + nm->len + 1;
+       dlen = UBIFS_DENT_NODE_SZ + fname_len(nm) + 1;
        ilen = UBIFS_INO_NODE_SZ;
 
        /*
@@ -596,9 +586,10 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
        key_write(c, &dent_key, dent->key);
        dent->inum = deletion ? 0 : cpu_to_le64(inode->i_ino);
        dent->type = get_dent_type(inode->i_mode);
-       dent->nlen = cpu_to_le16(nm->len);
-       memcpy(dent->name, nm->name, nm->len);
-       dent->name[nm->len] = '\0';
+       dent->nlen = cpu_to_le16(fname_len(nm));
+       memcpy(dent->name, fname_name(nm), fname_len(nm));
+       dent->name[fname_len(nm)] = '\0';
+
        zero_dent_node_unused(dent);
        ubifs_prep_grp_node(c, dent, dlen, 0);
 
@@ -697,14 +688,18 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
                         const union ubifs_key *key, const void *buf, int len)
 {
        struct ubifs_data_node *data;
-       int err, lnum, offs, compr_type, out_len;
+       int err, lnum, offs, compr_type, out_len, compr_len;
        int dlen = COMPRESSED_DATA_NODE_BUF_SZ, allocated = 1;
        struct ubifs_inode *ui = ubifs_inode(inode);
+       bool encrypted = ubifs_crypt_is_encrypted(inode);
 
        dbg_jnlk(key, "ino %lu, blk %u, len %d, key ",
                (unsigned long)key_inum(c, key), key_block(c, key), len);
        ubifs_assert(len <= UBIFS_BLOCK_SIZE);
 
+       if (encrypted)
+               dlen += UBIFS_CIPHER_BLOCK_SIZE;
+
        data = kmalloc(dlen, GFP_NOFS | __GFP_NOWARN);
        if (!data) {
                /*
@@ -722,7 +717,6 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
        data->ch.node_type = UBIFS_DATA_NODE;
        key_write(c, key, &data->key);
        data->size = cpu_to_le32(len);
-       zero_data_node_unused(data);
 
        if (!(ui->flags & UBIFS_COMPR_FL))
                /* Compression is disabled for this inode */
@@ -730,9 +724,18 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
        else
                compr_type = ui->compr_type;
 
-       out_len = dlen - UBIFS_DATA_NODE_SZ;
-       ubifs_compress(c, buf, len, &data->data, &out_len, &compr_type);
-       ubifs_assert(out_len <= UBIFS_BLOCK_SIZE);
+       out_len = compr_len = dlen - UBIFS_DATA_NODE_SZ;
+       ubifs_compress(c, buf, len, &data->data, &compr_len, &compr_type);
+       ubifs_assert(compr_len <= UBIFS_BLOCK_SIZE);
+
+       if (encrypted) {
+               err = ubifs_encrypt(inode, data, compr_len, &out_len, key_block(c, key));
+               if (err)
+                       goto out_free;
+
+       } else {
+               data->compr_size = 0;
+       }
 
        dlen = UBIFS_DATA_NODE_SZ + out_len;
        data->compr_type = cpu_to_le16(compr_type);
@@ -907,6 +910,149 @@ int ubifs_jnl_delete_inode(struct ubifs_info *c, const struct inode *inode)
        return err;
 }
 
+/**
+ * ubifs_jnl_xrename - cross rename two directory entries.
+ * @c: UBIFS file-system description object
+ * @fst_dir: parent inode of 1st directory entry to exchange
+ * @fst_inode: 1st inode to exchange
+ * @fst_nm: name of 1st inode to exchange
+ * @snd_dir: parent inode of 2nd directory entry to exchange
+ * @snd_inode: 2nd inode to exchange
+ * @snd_nm: name of 2nd inode to exchange
+ * @sync: non-zero if the write-buffer has to be synchronized
+ *
+ * This function implements the cross rename operation which may involve
+ * writing 2 inodes and 2 directory entries. It marks the written inodes as clean
+ * and returns zero on success. In case of failure, a negative error code is
+ * returned.
+ */
+int ubifs_jnl_xrename(struct ubifs_info *c, const struct inode *fst_dir,
+                     const struct inode *fst_inode,
+                     const struct fscrypt_name *fst_nm,
+                     const struct inode *snd_dir,
+                     const struct inode *snd_inode,
+                     const struct fscrypt_name *snd_nm, int sync)
+{
+       union ubifs_key key;
+       struct ubifs_dent_node *dent1, *dent2;
+       int err, dlen1, dlen2, lnum, offs, len, plen = UBIFS_INO_NODE_SZ;
+       int aligned_dlen1, aligned_dlen2;
+       int twoparents = (fst_dir != snd_dir);
+       void *p;
+
+       //dbg_jnl("dent '%pd' in dir ino %lu between dent '%pd' in dir ino %lu",
+       //      fst_dentry, fst_dir->i_ino, snd_dentry, snd_dir->i_ino);
+
+       ubifs_assert(ubifs_inode(fst_dir)->data_len == 0);
+       ubifs_assert(ubifs_inode(snd_dir)->data_len == 0);
+       ubifs_assert(mutex_is_locked(&ubifs_inode(fst_dir)->ui_mutex));
+       ubifs_assert(mutex_is_locked(&ubifs_inode(snd_dir)->ui_mutex));
+
+       dlen1 = UBIFS_DENT_NODE_SZ + fname_len(snd_nm) + 1;
+       dlen2 = UBIFS_DENT_NODE_SZ + fname_len(fst_nm) + 1;
+       aligned_dlen1 = ALIGN(dlen1, 8);
+       aligned_dlen2 = ALIGN(dlen2, 8);
+
+       len = aligned_dlen1 + aligned_dlen2 + ALIGN(plen, 8);
+       if (twoparents)
+               len += plen;
+
+       dent1 = kmalloc(len, GFP_NOFS);
+       if (!dent1)
+               return -ENOMEM;
+
+       /* Make reservation before allocating sequence numbers */
+       err = make_reservation(c, BASEHD, len);
+       if (err)
+               goto out_free;
+
+       /* Make new dent for 1st entry */
+       dent1->ch.node_type = UBIFS_DENT_NODE;
+       dent_key_init_flash(c, &dent1->key, snd_dir->i_ino, snd_nm);
+       dent1->inum = cpu_to_le64(fst_inode->i_ino);
+       dent1->type = get_dent_type(fst_inode->i_mode);
+       dent1->nlen = cpu_to_le16(fname_len(snd_nm));
+       memcpy(dent1->name, fname_name(snd_nm), fname_len(snd_nm));
+       dent1->name[fname_len(snd_nm)] = '\0';
+       zero_dent_node_unused(dent1);
+       ubifs_prep_grp_node(c, dent1, dlen1, 0);
+
+       /* Make new dent for 2nd entry */
+       dent2 = (void *)dent1 + aligned_dlen1;
+       dent2->ch.node_type = UBIFS_DENT_NODE;
+       dent_key_init_flash(c, &dent2->key, fst_dir->i_ino, fst_nm);
+       dent2->inum = cpu_to_le64(snd_inode->i_ino);
+       dent2->type = get_dent_type(snd_inode->i_mode);
+       dent2->nlen = cpu_to_le16(fname_len(fst_nm));
+       memcpy(dent2->name, fname_name(fst_nm), fname_len(fst_nm));
+       dent2->name[fname_len(fst_nm)] = '\0';
+       zero_dent_node_unused(dent2);
+       ubifs_prep_grp_node(c, dent2, dlen2, 0);
+
+       p = (void *)dent2 + aligned_dlen2;
+       if (!twoparents)
+               pack_inode(c, p, fst_dir, 1);
+       else {
+               pack_inode(c, p, fst_dir, 0);
+               p += ALIGN(plen, 8);
+               pack_inode(c, p, snd_dir, 1);
+       }
+
+       err = write_head(c, BASEHD, dent1, len, &lnum, &offs, sync);
+       if (err)
+               goto out_release;
+       if (!sync) {
+               struct ubifs_wbuf *wbuf = &c->jheads[BASEHD].wbuf;
+
+               ubifs_wbuf_add_ino_nolock(wbuf, fst_dir->i_ino);
+               ubifs_wbuf_add_ino_nolock(wbuf, snd_dir->i_ino);
+       }
+       release_head(c, BASEHD);
+
+       dent_key_init(c, &key, snd_dir->i_ino, snd_nm);
+       err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen1, snd_nm);
+       if (err)
+               goto out_ro;
+
+       offs += aligned_dlen1;
+       dent_key_init(c, &key, fst_dir->i_ino, fst_nm);
+       err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen2, fst_nm);
+       if (err)
+               goto out_ro;
+
+       offs += aligned_dlen2;
+
+       ino_key_init(c, &key, fst_dir->i_ino);
+       err = ubifs_tnc_add(c, &key, lnum, offs, plen);
+       if (err)
+               goto out_ro;
+
+       if (twoparents) {
+               offs += ALIGN(plen, 8);
+               ino_key_init(c, &key, snd_dir->i_ino);
+               err = ubifs_tnc_add(c, &key, lnum, offs, plen);
+               if (err)
+                       goto out_ro;
+       }
+
+       finish_reservation(c);
+
+       mark_inode_clean(c, ubifs_inode(fst_dir));
+       if (twoparents)
+               mark_inode_clean(c, ubifs_inode(snd_dir));
+       kfree(dent1);
+       return 0;
+
+out_release:
+       release_head(c, BASEHD);
+out_ro:
+       ubifs_ro_mode(c, err);
+       finish_reservation(c);
+out_free:
+       kfree(dent1);
+       return err;
+}
+
 /**
  * ubifs_jnl_rename - rename a directory entry.
  * @c: UBIFS file-system description object
@@ -917,35 +1063,36 @@ int ubifs_jnl_delete_inode(struct ubifs_info *c, const struct inode *inode)
  * @sync: non-zero if the write-buffer has to be synchronized
  *
  * This function implements the re-name operation which may involve writing up
- * to 3 inodes and 2 directory entries. It marks the written inodes as clean
+ * to 4 inodes and 2 directory entries. It marks the written inodes as clean
  * and returns zero on success. In case of failure, a negative error code is
  * returned.
  */
 int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
-                    const struct dentry *old_dentry,
+                    const struct inode *old_inode,
+                    const struct fscrypt_name *old_nm,
                     const struct inode *new_dir,
-                    const struct dentry *new_dentry, int sync)
+                    const struct inode *new_inode,
+                    const struct fscrypt_name *new_nm,
+                    const struct inode *whiteout, int sync)
 {
        void *p;
        union ubifs_key key;
        struct ubifs_dent_node *dent, *dent2;
        int err, dlen1, dlen2, ilen, lnum, offs, len;
-       const struct inode *old_inode = d_inode(old_dentry);
-       const struct inode *new_inode = d_inode(new_dentry);
        int aligned_dlen1, aligned_dlen2, plen = UBIFS_INO_NODE_SZ;
        int last_reference = !!(new_inode && new_inode->i_nlink == 0);
        int move = (old_dir != new_dir);
        struct ubifs_inode *uninitialized_var(new_ui);
 
-       dbg_jnl("dent '%pd' in dir ino %lu to dent '%pd' in dir ino %lu",
-               old_dentry, old_dir->i_ino, new_dentry, new_dir->i_ino);
+       //dbg_jnl("dent '%pd' in dir ino %lu to dent '%pd' in dir ino %lu",
+       //      old_dentry, old_dir->i_ino, new_dentry, new_dir->i_ino);
        ubifs_assert(ubifs_inode(old_dir)->data_len == 0);
        ubifs_assert(ubifs_inode(new_dir)->data_len == 0);
        ubifs_assert(mutex_is_locked(&ubifs_inode(old_dir)->ui_mutex));
        ubifs_assert(mutex_is_locked(&ubifs_inode(new_dir)->ui_mutex));
 
-       dlen1 = UBIFS_DENT_NODE_SZ + new_dentry->d_name.len + 1;
-       dlen2 = UBIFS_DENT_NODE_SZ + old_dentry->d_name.len + 1;
+       dlen1 = UBIFS_DENT_NODE_SZ + fname_len(new_nm) + 1;
+       dlen2 = UBIFS_DENT_NODE_SZ + fname_len(old_nm) + 1;
        if (new_inode) {
                new_ui = ubifs_inode(new_inode);
                ubifs_assert(mutex_is_locked(&new_ui->ui_mutex));
@@ -958,7 +1105,7 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
        aligned_dlen1 = ALIGN(dlen1, 8);
        aligned_dlen2 = ALIGN(dlen2, 8);
        len = aligned_dlen1 + aligned_dlen2 + ALIGN(ilen, 8) + ALIGN(plen, 8);
-       if (old_dir != new_dir)
+       if (move)
                len += plen;
        dent = kmalloc(len, GFP_NOFS);
        if (!dent)
@@ -971,25 +1118,30 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
 
        /* Make new dent */
        dent->ch.node_type = UBIFS_DENT_NODE;
-       dent_key_init_flash(c, &dent->key, new_dir->i_ino, &new_dentry->d_name);
+       dent_key_init_flash(c, &dent->key, new_dir->i_ino, new_nm);
        dent->inum = cpu_to_le64(old_inode->i_ino);
        dent->type = get_dent_type(old_inode->i_mode);
-       dent->nlen = cpu_to_le16(new_dentry->d_name.len);
-       memcpy(dent->name, new_dentry->d_name.name, new_dentry->d_name.len);
-       dent->name[new_dentry->d_name.len] = '\0';
+       dent->nlen = cpu_to_le16(fname_len(new_nm));
+       memcpy(dent->name, fname_name(new_nm), fname_len(new_nm));
+       dent->name[fname_len(new_nm)] = '\0';
        zero_dent_node_unused(dent);
        ubifs_prep_grp_node(c, dent, dlen1, 0);
 
-       /* Make deletion dent */
        dent2 = (void *)dent + aligned_dlen1;
        dent2->ch.node_type = UBIFS_DENT_NODE;
-       dent_key_init_flash(c, &dent2->key, old_dir->i_ino,
-                           &old_dentry->d_name);
-       dent2->inum = 0;
-       dent2->type = DT_UNKNOWN;
-       dent2->nlen = cpu_to_le16(old_dentry->d_name.len);
-       memcpy(dent2->name, old_dentry->d_name.name, old_dentry->d_name.len);
-       dent2->name[old_dentry->d_name.len] = '\0';
+       dent_key_init_flash(c, &dent2->key, old_dir->i_ino, old_nm);
+
+       if (whiteout) {
+               dent2->inum = cpu_to_le64(whiteout->i_ino);
+               dent2->type = get_dent_type(whiteout->i_mode);
+       } else {
+               /* Make deletion dent */
+               dent2->inum = 0;
+               dent2->type = DT_UNKNOWN;
+       }
+       dent2->nlen = cpu_to_le16(fname_len(old_nm));
+       memcpy(dent2->name, fname_name(old_nm), fname_len(old_nm));
+       dent2->name[fname_len(old_nm)] = '\0';
        zero_dent_node_unused(dent2);
        ubifs_prep_grp_node(c, dent2, dlen2, 0);
 
@@ -1030,21 +1182,31 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
        }
        release_head(c, BASEHD);
 
-       dent_key_init(c, &key, new_dir->i_ino, &new_dentry->d_name);
-       err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen1, &new_dentry->d_name);
+       dent_key_init(c, &key, new_dir->i_ino, new_nm);
+       err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen1, new_nm);
        if (err)
                goto out_ro;
 
-       err = ubifs_add_dirt(c, lnum, dlen2);
-       if (err)
-               goto out_ro;
+       offs += aligned_dlen1;
+       if (whiteout) {
+               dent_key_init(c, &key, old_dir->i_ino, old_nm);
+               err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen2, old_nm);
+               if (err)
+                       goto out_ro;
 
-       dent_key_init(c, &key, old_dir->i_ino, &old_dentry->d_name);
-       err = ubifs_tnc_remove_nm(c, &key, &old_dentry->d_name);
-       if (err)
-               goto out_ro;
+               ubifs_delete_orphan(c, whiteout->i_ino);
+       } else {
+               err = ubifs_add_dirt(c, lnum, dlen2);
+               if (err)
+                       goto out_ro;
 
-       offs += aligned_dlen1 + aligned_dlen2;
+               dent_key_init(c, &key, old_dir->i_ino, old_nm);
+               err = ubifs_tnc_remove_nm(c, &key, old_nm);
+               if (err)
+                       goto out_ro;
+       }
+
+       offs += aligned_dlen2;
        if (new_inode) {
                ino_key_init(c, &key, new_inode->i_ino);
                err = ubifs_tnc_add(c, &key, lnum, offs, ilen);
@@ -1058,7 +1220,7 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
        if (err)
                goto out_ro;
 
-       if (old_dir != new_dir) {
+       if (move) {
                offs += ALIGN(plen, 8);
                ino_key_init(c, &key, new_dir->i_ino);
                err = ubifs_tnc_add(c, &key, lnum, offs, plen);
@@ -1093,31 +1255,55 @@ out_free:
 }
 
 /**
- * recomp_data_node - re-compress a truncated data node.
+ * truncate_data_node - re-compress/encrypt a truncated data node.
+ * @c: UBIFS file-system description object
+ * @inode: inode which referes to the data node
+ * @block: data block number
  * @dn: data node to re-compress
  * @new_len: new length
  *
  * This function is used when an inode is truncated and the last data node of
- * the inode has to be re-compressed and re-written.
+ * the inode has to be re-compressed/encrypted and re-written.
  */
-static int recomp_data_node(const struct ubifs_info *c,
-                           struct ubifs_data_node *dn, int *new_len)
+static int truncate_data_node(const struct ubifs_info *c, const struct inode *inode,
+                             unsigned int block, struct ubifs_data_node *dn,
+                             int *new_len)
 {
        void *buf;
-       int err, len, compr_type, out_len;
+       int err, dlen, compr_type, out_len, old_dlen;
 
        out_len = le32_to_cpu(dn->size);
        buf = kmalloc(out_len * WORST_COMPR_FACTOR, GFP_NOFS);
        if (!buf)
                return -ENOMEM;
 
-       len = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
+       dlen = old_dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
        compr_type = le16_to_cpu(dn->compr_type);
-       err = ubifs_decompress(c, &dn->data, len, buf, &out_len, compr_type);
-       if (err)
-               goto out;
 
-       ubifs_compress(c, buf, *new_len, &dn->data, &out_len, &compr_type);
+       if (ubifs_crypt_is_encrypted(inode)) {
+               err = ubifs_decrypt(inode, dn, &dlen, block);
+               if (err)
+                       goto out;
+       }
+
+       if (compr_type != UBIFS_COMPR_NONE) {
+               err = ubifs_decompress(c, &dn->data, dlen, buf, &out_len, compr_type);
+               if (err)
+                       goto out;
+
+               ubifs_compress(c, buf, *new_len, &dn->data, &out_len, &compr_type);
+       }
+
+       if (ubifs_crypt_is_encrypted(inode)) {
+               err = ubifs_encrypt(inode, dn, out_len, &old_dlen, block);
+               if (err)
+                       goto out;
+
+               out_len = old_dlen;
+       } else {
+               dn->compr_size = 0;
+       }
+
        ubifs_assert(out_len <= UBIFS_BLOCK_SIZE);
        dn->compr_type = cpu_to_le16(compr_type);
        dn->size = cpu_to_le32(*new_len);
@@ -1189,17 +1375,9 @@ int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode,
                        if (le32_to_cpu(dn->size) <= dlen)
                                dlen = 0; /* Nothing to do */
                        else {
-                               int compr_type = le16_to_cpu(dn->compr_type);
-
-                               if (compr_type != UBIFS_COMPR_NONE) {
-                                       err = recomp_data_node(c, dn, &dlen);
-                                       if (err)
-                                               goto out_free;
-                               } else {
-                                       dn->size = cpu_to_le32(dlen);
-                                       dlen += UBIFS_DATA_NODE_SZ;
-                               }
-                               zero_data_node_unused(dn);
+                               err = truncate_data_node(c, inode, blk, dn, &dlen);
+                               if (err)
+                                       goto out_free;
                        }
                }
        }
@@ -1284,7 +1462,8 @@ out_free:
  * error code in case of failure.
  */
 int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host,
-                          const struct inode *inode, const struct qstr *nm)
+                          const struct inode *inode,
+                          const struct fscrypt_name *nm)
 {
        int err, xlen, hlen, len, lnum, xent_offs, aligned_xlen;
        struct ubifs_dent_node *xent;
@@ -1293,9 +1472,9 @@ int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host,
        int sync = IS_DIRSYNC(host);
        struct ubifs_inode *host_ui = ubifs_inode(host);
 
-       dbg_jnl("host %lu, xattr ino %lu, name '%s', data len %d",
-               host->i_ino, inode->i_ino, nm->name,
-               ubifs_inode(inode)->data_len);
+       //dbg_jnl("host %lu, xattr ino %lu, name '%s', data len %d",
+       //      host->i_ino, inode->i_ino, nm->name,
+       //      ubifs_inode(inode)->data_len);
        ubifs_assert(inode->i_nlink == 0);
        ubifs_assert(mutex_is_locked(&host_ui->ui_mutex));
 
@@ -1303,7 +1482,7 @@ int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host,
         * Since we are deleting the inode, we do not bother to attach any data
         * to it and assume its length is %UBIFS_INO_NODE_SZ.
         */
-       xlen = UBIFS_DENT_NODE_SZ + nm->len + 1;
+       xlen = UBIFS_DENT_NODE_SZ + fname_len(nm) + 1;
        aligned_xlen = ALIGN(xlen, 8);
        hlen = host_ui->data_len + UBIFS_INO_NODE_SZ;
        len = aligned_xlen + UBIFS_INO_NODE_SZ + ALIGN(hlen, 8);
@@ -1324,9 +1503,9 @@ int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host,
        key_write(c, &xent_key, xent->key);
        xent->inum = 0;
        xent->type = get_dent_type(inode->i_mode);
-       xent->nlen = cpu_to_le16(nm->len);
-       memcpy(xent->name, nm->name, nm->len);
-       xent->name[nm->len] = '\0';
+       xent->nlen = cpu_to_le16(fname_len(nm));
+       memcpy(xent->name, fname_name(nm), fname_len(nm));
+       xent->name[fname_len(nm)] = '\0';
        zero_dent_node_unused(xent);
        ubifs_prep_grp_node(c, xent, xlen, 0);