* @ui_mutex: serializes inode write-back with the rest of VFS operations,
  *            serializes "clean <-> dirty" state changes, serializes bulk-read,
  *            protects @dirty, @bulk_read, @ui_size, and @xattr_size
+ * @xattr_sem: serilizes write operations (remove|set|create) on xattr
  * @ui_lock: protects @synced_i_size
  * @synced_i_size: synchronized size of inode, i.e. the value of inode size
  *                 currently stored on the flash; used only for regular file
        unsigned int bulk_read:1;
        unsigned int compr_type:2;
        struct mutex ui_mutex;
+       struct rw_semaphore xattr_sem;
        spinlock_t ui_lock;
        loff_t synced_i_size;
        loff_t ui_size;
 
        if (!xent)
                return -ENOMEM;
 
+       down_write(&ubifs_inode(host)->xattr_sem);
        /*
         * The extended attribute entries are stored in LNC, so multiple
         * look-ups do not involve reading the flash.
        iput(inode);
 
 out_free:
+       up_write(&ubifs_inode(host)->xattr_sem);
        kfree(xent);
        return err;
 }
        if (!xent)
                return -ENOMEM;
 
+       down_read(&ubifs_inode(host)->xattr_sem);
        xent_key_init(c, &key, host->i_ino, &nm);
        err = ubifs_tnc_lookup_nm(c, &key, xent, &nm);
        if (err) {
                if (err == -ENOENT)
                        err = -ENODATA;
-               goto out_unlock;
+               goto out_cleanup;
        }
 
        inode = iget_xattr(c, le64_to_cpu(xent->inum));
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
-               goto out_unlock;
+               goto out_cleanup;
        }
 
        ui = ubifs_inode(inode);
 out_iput:
        mutex_unlock(&ui->ui_mutex);
        iput(inode);
-out_unlock:
+out_cleanup:
+       up_read(&ubifs_inode(host)->xattr_sem);
        kfree(xent);
        return err;
 }
        dbg_gen("ino %lu ('%pd'), buffer size %zd", host->i_ino,
                dentry, size);
 
+       down_read(&host_ui->xattr_sem);
        len = host_ui->xattr_names + host_ui->xattr_cnt;
-       if (!buffer)
+       if (!buffer) {
                /*
                 * We should return the minimum buffer size which will fit a
                 * null-terminated list of all the extended attribute names.
                 */
-               return len;
+               err = len;
+               goto out_err;
+       }
 
-       if (len > size)
-               return -ERANGE;
+       if (len > size) {
+               err = -ERANGE;
+               goto out_err;
+       }
 
        lowest_xent_key(c, &key, host->i_ino);
        while (1) {
                pxent = xent;
                key_read(c, &xent->key, &key);
        }
-
        kfree(pxent);
+       up_read(&host_ui->xattr_sem);
+
        if (err != -ENOENT) {
                ubifs_err(c, "cannot find next direntry, error %d", err);
                return err;
 
        ubifs_assert(c, written <= size);
        return written;
+
+out_err:
+       up_read(&host_ui->xattr_sem);
+       return err;
 }
 
 static int remove_xattr(struct ubifs_info *c, struct inode *host,
        ubifs_warn(c, "inode %lu has too many xattrs, doing a non-atomic deletion",
                   host->i_ino);
 
+       down_write(&ubifs_inode(host)->xattr_sem);
        lowest_xent_key(c, &key, host->i_ino);
        while (1) {
                xent = ubifs_tnc_next_ent(c, &key, &nm);
                        ubifs_ro_mode(c, err);
                        kfree(pxent);
                        kfree(xent);
-                       return err;
+                       goto out_err;
                }
 
                ubifs_assert(c, ubifs_inode(xino)->xattr);
                        kfree(xent);
                        iput(xino);
                        ubifs_err(c, "cannot remove xattr, error %d", err);
-                       return err;
+                       goto out_err;
                }
 
                iput(xino);
                pxent = xent;
                key_read(c, &xent->key, &key);
        }
-
        kfree(pxent);
+       up_write(&ubifs_inode(host)->xattr_sem);
+
        if (err != -ENOENT) {
                ubifs_err(c, "cannot find next direntry, error %d", err);
                return err;
        }
 
        return 0;
+
+out_err:
+       up_write(&ubifs_inode(host)->xattr_sem);
+       return err;
 }
 
 /**
        if (!xent)
                return -ENOMEM;
 
+       down_write(&ubifs_inode(host)->xattr_sem);
        xent_key_init(c, &key, host->i_ino, &nm);
        err = ubifs_tnc_lookup_nm(c, &key, xent, &nm);
        if (err) {
        iput(inode);
 
 out_free:
+       up_write(&ubifs_inode(host)->xattr_sem);
        kfree(xent);
        return err;
 }