diff --git a/Documentation/filesystems/ubifs.txt b/Documentation/filesystems/ubifs.txt
index acc80442a3bb..86285aa17cd8 100644
--- a/Documentation/filesystems/ubifs.txt
+++ b/Documentation/filesystems/ubifs.txt
@@ -98,7 +98,12 @@ auth_key=		specify the key used for authenticating the filesystem.
 auth_hash_name=		The hash algorithm used for authentication. Used for
 			both hashing and for creating HMACs. Typical values
 			include "sha256" or "sha512"
-
+usrquota		Enable user disk quota support
+			(requires CONFIG_QUOTA).
+grpquota		Enable group disk quota support
+			(requires CONFIG_QUOTA).
+prjquota		Enable project disk quota support
+			(requires CONFIG_QUOTA).
 
 Quick usage instructions
 ========================
diff --git a/fs/ubifs/Makefile b/fs/ubifs/Makefile
index 5c4b845754a7..07f657f5ea8f 100644
--- a/fs/ubifs/Makefile
+++ b/fs/ubifs/Makefile
@@ -9,3 +9,4 @@ ubifs-y += misc.o
 ubifs-$(CONFIG_FS_ENCRYPTION) += crypto.o
 ubifs-$(CONFIG_UBIFS_FS_XATTR) += xattr.o
 ubifs-$(CONFIG_UBIFS_FS_AUTHENTICATION) += auth.o
+ubifs-$(CONFIG_QUOTA) += quota.o
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index e2d3dfb67ae3..b7a2c255ffcd 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -113,6 +113,11 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir,
 			 current_time(inode);
 	inode->i_mapping->nrpages = 0;
 
+	dquot_initialize(inode);
+	err = dquot_alloc_inode(inode);
+	if (err)
+		goto fail_drop;
+
 	if (ubifs_inode(dir)->flags & UBIFS_PROJINHERIT_FL)
 		ui->projid = ubifs_inode(dir)->projid;
 	else
@@ -158,8 +163,8 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir,
 			spin_unlock(&c->cnt_lock);
 			ubifs_err(c, "out of inode numbers");
 			make_bad_inode(inode);
-			iput(inode);
-			return ERR_PTR(-EINVAL);
+			err = -EINVAL;
+			goto fail_free;
 		}
 		ubifs_warn(c, "running out of inode numbers (current %lu, max %u)",
 			   (unsigned long)c->highest_inum, INUM_WATERMARK);
@@ -187,6 +192,13 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir,
 	}
 
 	return inode;
+
+fail_free:
+	dquot_free_inode(inode);
+fail_drop:
+	dquot_drop(inode);
+	iput(inode);
+	return ERR_PTR(err);
 }
 
 static int dbg_check_name(const struct ubifs_info *c,
@@ -776,6 +788,8 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
 	unsigned int saved_nlink = inode->i_nlink;
 	struct fscrypt_name nm;
 
+	dquot_initialize(inode);
+
 	/*
 	 * Budget request settings: deletion direntry, deletion inode (+1 for
 	 * @dirtied_ino), changing the parent directory inode. If budgeting
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index cd52585c8f4f..9ae998febcf1 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -427,8 +427,10 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping,
 	struct ubifs_inode *ui = ubifs_inode(inode);
 	pgoff_t index = pos >> PAGE_SHIFT;
 	int uninitialized_var(err), appending = !!(pos + len > inode->i_size);
+	int quota_size = 0;
 	int skipped_read = 0;
 	struct page *page;
+	int ret = 0;
 
 	ubifs_assert(c, ubifs_inode(inode)->ui_size == inode->i_size);
 	ubifs_assert(c, !c->ro_media && !c->ro_mount);
@@ -436,6 +438,16 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping,
 	if (unlikely(c->ro_error))
 		return -EROFS;
 
+	quota_size = ((pos + len) - inode->i_size);
+	if (quota_size < 0)
+		quota_size = 0;
+	if (S_ISREG(inode->i_mode)) {
+		dquot_initialize(inode);
+		ret = dquot_alloc_space_nodirty(inode, quota_size);
+		if (unlikely(ret))
+			return ret;
+	}
+
 	/* Try out the fast-path part first */
 	page = grab_cache_page_write_begin(mapping, index, flags);
 	if (unlikely(!page))
@@ -541,6 +553,7 @@ static int ubifs_write_end(struct file *file, struct address_space *mapping,
 	struct ubifs_inode *ui = ubifs_inode(inode);
 	struct ubifs_info *c = inode->i_sb->s_fs_info;
 	loff_t end_pos = pos + len;
+	int quota_size = 0;
 	int appending = !!(end_pos > inode->i_size);
 
 	dbg_gen("ino %lu, pos %llu, pg %lu, len %u, copied %d, i_size %lld",
@@ -559,6 +572,11 @@ static int ubifs_write_end(struct file *file, struct address_space *mapping,
 		dbg_gen("copied %d instead of %d, read page and repeat",
 			copied, len);
 		cancel_budget(c, page, ui, appending);
+		quota_size = ((pos + len) - inode->i_size);
+		if (quota_size < 0)
+			quota_size = 0;
+		if (S_ISREG(inode->i_mode))
+			dquot_free_space_nodirty(inode, quota_size);
 		ClearPageChecked(page);
 
 		/*
@@ -1115,6 +1133,7 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode,
 	int err;
 	struct ubifs_budget_req req;
 	loff_t old_size = inode->i_size, new_size = attr->ia_size;
+	loff_t quota_size = (old_size - new_size);
 	int offset = new_size & (UBIFS_BLOCK_SIZE - 1), budgeted = 1;
 	struct ubifs_inode *ui = ubifs_inode(inode);
 
@@ -1194,6 +1213,10 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode,
 	do_attr_changes(inode, attr);
 	err = ubifs_jnl_truncate(c, inode, old_size, new_size);
 	mutex_unlock(&ui->ui_mutex);
+	if (quota_size < 0)
+		quota_size = 0;
+	if (S_ISREG(inode->i_mode))
+		dquot_free_space_nodirty(inode, quota_size);
 
 out_budg:
 	if (budgeted)
@@ -1230,6 +1253,17 @@ static int do_setattr(struct ubifs_info *c, struct inode *inode,
 
 	if (attr->ia_valid & ATTR_SIZE) {
 		dbg_gen("size %lld -> %lld", inode->i_size, new_size);
+		if (S_ISREG(inode->i_mode)) {
+			if (new_size > inode->i_size) {
+				err = dquot_alloc_space_nodirty(inode, new_size - inode->i_size);
+				if (err) {
+					ubifs_release_budget(c, &req);
+					return err;
+				}
+			} else {
+				dquot_free_space_nodirty(inode, inode->i_size - new_size);
+			}
+		}
 		truncate_setsize(inode, new_size);
 	}
 
@@ -1281,6 +1315,15 @@ int ubifs_setattr(struct dentry *dentry, struct iattr *attr)
 	if (err)
 		return err;
 
+	if (is_quota_modification(inode, attr))
+		dquot_initialize(inode);
+	if ((attr->ia_valid & ATTR_UID && !uid_eq(attr->ia_uid, inode->i_uid)) ||
+	    (attr->ia_valid & ATTR_GID && !gid_eq(attr->ia_gid, inode->i_gid))) {
+		err = dquot_transfer(inode, attr);
+		if (err)
+			return err;
+	}
+
 	if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size < inode->i_size)
 		/* Truncation to a smaller size */
 		err = do_truncation(c, inode, attr);
diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c
index 92a782f3fdc2..d812b16e25f7 100644
--- a/fs/ubifs/ioctl.c
+++ b/fs/ubifs/ioctl.c
@@ -157,16 +157,48 @@ static int ubifs_ioctl_check_project(struct ubifs_inode *ui, struct fsxattr *fa)
 	return 0;
 }
 
+#ifdef CONFIG_QUOTA
+static int ubifs_transfer_project_quota(struct inode *inode, kprojid_t kprojid)
+{
+	struct dquot *transfer_to[MAXQUOTAS] = {};
+	struct ubifs_info *c = inode->i_sb->s_fs_info;
+	struct super_block *sb = c->vfs_sb;
+	int err = 0;
+
+	err = dquot_initialize(inode);
+	if (err)
+		return err;
+
+	transfer_to[PRJQUOTA] = dqget(sb, make_kqid_projid(kprojid));
+	if (!IS_ERR(transfer_to[PRJQUOTA])) {
+		err = __dquot_transfer(inode, transfer_to);
+		dqput(transfer_to[PRJQUOTA]);
+	}
+
+	return err;
+}
+#else
+static int ubifs_transfer_project_quota(struct inode *inode, kprojid_t kprojid)
+{
+	return 0;
+}
+#endif
+
 static int ubifs_ioc_setproject(struct file *file, __u32 projid)
 {
 	struct inode *inode = file_inode(file);
 	struct ubifs_inode *ui = ubifs_inode(inode);
 	kprojid_t kprojid;
+	int err;
 
 	kprojid = make_kprojid(&init_user_ns, (projid_t)projid);
 	if (projid_eq(kprojid, ui->projid))
 		return 0;
 
+	err = ubifs_transfer_project_quota(inode, kprojid);
+	if (err)
+		return err;
+
 	ui->projid = kprojid;
 
 	return 0;
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
index d8961993f9dd..cba061c74c41 100644
--- a/fs/ubifs/journal.c
+++ b/fs/ubifs/journal.c
@@ -630,6 +630,8 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
 			goto out_finish;
 		}
 		ui->del_cmtno = c->cmt_no;
+		if (S_ISREG(inode->i_mode))
+			dquot_free_space_nodirty((struct inode *)inode, inode->i_size);
 	}
 
 	err = write_head(c, BASEHD, dent, len, &lnum, &dent_offs, sync);
diff --git a/fs/ubifs/quota.c b/fs/ubifs/quota.c
new file mode 100644
index 000000000000..82aa1f067825
--- /dev/null
+++ b/fs/ubifs/quota.c
@@ -0,0 +1,609 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * This file is part of UBIFS.
+ *
+ * Copyright (C) 2019 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
+ */
+#include "ubifs.h"
+
+struct ubifs_dqblk {
+	struct mem_dqblk dqblk;
+	struct rb_node rb;
+	struct kqid kqid;
+};
+
+/**
+ * ubifs_dqblk_insert - find qid in tree
+ * @c: UBIFS file-system description object
+ * @new: The new entry to insert
+ *
+ * This inserts a new entry to the dqblk tree which is sorted by qids. Caller
+ * must make sure this entry doesn't exist already.
+ */
+static void ubifs_dqblk_insert(struct ubifs_info *c, struct ubifs_dqblk *new)
+{
+	struct rb_root *root = &c->dqblk_tree[new->kqid.type];
+	struct rb_node **link = &root->rb_node, *parent = NULL;
+	struct ubifs_dqblk *ud;
+
+	/* Go to the bottom of the tree */
+	while (*link) {
+		parent = *link;
+
+		ud = rb_entry(parent, struct ubifs_dqblk, rb);
+
+		if (qid_lt(new->kqid, ud->kqid))
+			link = &(*link)->rb_left;
+		else
+			link = &(*link)->rb_right;
+	}
+
+	/* Put the new node there */
+	rb_link_node(&new->rb, parent, link);
+	rb_insert_color(&new->rb, root);
+}
+
+/**
+ * ubifs_dqblk_find - find qid in tree
+ * @c: UBIFS file-system description object
+ * @qid: The qid to look for
+ *
+ * This walks the dqblk tree and searches a given qid. Returns the dqblk entry
+ * when found or NULL otherwise.
+ */
+static struct ubifs_dqblk *ubifs_dqblk_find(struct ubifs_info *c,
+					    struct kqid qid)
+{
+	struct rb_node *node = c->dqblk_tree[qid.type].rb_node;
+
+	while (node) {
+		struct ubifs_dqblk *ud = rb_entry(node, struct ubifs_dqblk, rb);
+
+		if (qid_eq(qid, ud->kqid))
+			return ud;
+
+		if (qid_lt(qid, ud->kqid))
+			node = node->rb_left;
+		else
+			node = node->rb_right;
+	}
+
+	return NULL;
+}
+
+/**
+ * ubifs_dqblk_find_next - find the next qid
+ * @c: UBIFS file-system description object
+ * @qid: The qid to look for
+ *
+ * Find the next dqblk entry with a qid that is bigger or equally big than the
+ * given qid. Returns the next dqblk entry if found or NULL if no dqblk exists
+ * with a qid that is at least equally big.
+ */
+static struct ubifs_dqblk *ubifs_dqblk_find_next(struct ubifs_info *c,
+						 struct kqid qid)
+{
+	struct rb_node *node = c->dqblk_tree[qid.type].rb_node;
+	struct ubifs_dqblk *next = NULL;
+
+	while (node) {
+		struct ubifs_dqblk *ud = rb_entry(node, struct ubifs_dqblk, rb);
+
+		if (qid_eq(qid, ud->kqid))
+			return ud;
+
+		if (qid_lt(qid, ud->kqid)) {
+			if (!next || qid_lt(ud->kqid, next->kqid))
+				next = ud;
+
+			node = node->rb_left;
+		} else {
+			node = node->rb_right;
+		}
+	}
+
+	return next;
+}
+
+/**
+ * ubifs_dqblk_get - get dqblk entry for given qid
+ * @c: UBIFS file-system description object
+ * @qid: The qid to look for
+ *
+ * This searches the given qid in the dqblk tree and returns it if found. If not,
+ * a new dqblk entry is created, inserted into the dqblk tree and returned.
+ */
+static struct ubifs_dqblk *ubifs_dqblk_get(struct ubifs_info *c,
+					   struct kqid qid)
+{
+	struct ubifs_dqblk *ud;
+
+	ud = ubifs_dqblk_find(c, qid);
+	if (ud)
+		return ud;
+
+	ud = kzalloc(sizeof(*ud), GFP_KERNEL);
+	if (!ud)
+		return NULL;
+
+	ud->kqid = qid;
+
+	ubifs_dqblk_insert(c, ud);
+
+	return ud;
+}
+
+/**
+ * ubifs_check_quota_file - check if quota file is valid for this format
+ * @sb: The superblock
+ * @type: Quota type
+ *
+ * We currently do not store any quota file on flash. It's completely in RAM and
+ * thus always valid.
+ */
+static int ubifs_check_quota_file(struct super_block *sb, int type)
+{
+	return 1;
+}
+
+/**
+ * ubifs_read_file_info - read quota file info
+ * @sb: The superblock
+ * @type: Quota type
+ *
+ * We currently do not store any quota info on flash. Just fill in default
+ * values.
+ */
+static int ubifs_read_file_info(struct super_block *sb, int type)
+{
+	struct quota_info *dqopt = sb_dqopt(sb);
+	struct mem_dqinfo *info = &dqopt->info[type];
+
+	down_read(&dqopt->dqio_sem);
+
+	/*
+	 * Used space is stored as unsigned 64-bit value in bytes but
+	 * quota core supports only signed 64-bit values so use that
+	 * as a limit
+	 */
+	info->dqi_max_spc_limit = 0x7fffffffffffffffLL; /* 2^63-1 */
+	info->dqi_max_ino_limit = 0x7fffffffffffffffLL;
+	info->dqi_bgrace = 0;
+	info->dqi_igrace = 0;
+	info->dqi_flags = 0;
+
+	up_read(&dqopt->dqio_sem);
+
+	return 0;
+}
+
+/**
+ * ubifs_write_file_info - write quota file to device
+ * @sb: The superblock
+ * @type: Quota type
+ *
+ * We currently do not store any quota file on flash. Nothing to do here.
+ */
+static int ubifs_write_file_info(struct super_block *sb, int type)
+{
+	return 0;
+}
+
+/**
+ * ubifs_read_dquot - read dquot from device
+ * @dquot: The dquot entry to read
+ *
+ * For us this means finding the entry in the dquot tree.
+ */
+static int ubifs_read_dquot(struct dquot *dquot)
+{
+	struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
+	struct ubifs_info *c = dquot->dq_sb->s_fs_info;
+	struct ubifs_dqblk *ud;
+	int ret = 0;
+
+	down_read(&dqopt->dqio_sem);
+
+	ud = ubifs_dqblk_find(c, dquot->dq_id);
+	if (ud)
+		dquot->dq_dqb = ud->dqblk;
+	else
+		ret = -ENOENT;
+
+	up_read(&dqopt->dqio_sem);
+
+	return 0;
+}
+
+/**
+ * ubifs_write_dquot - write dquot to device
+ * @dquot: The dquot entry to read
+ *
+ * For us this means finding or creating the entry in the dquot tree and setting
+ * it to the dquots contents.
+ */
+static int ubifs_write_dquot(struct dquot *dquot)
+{
+	struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
+	struct ubifs_info *c = dquot->dq_sb->s_fs_info;
+	int ret = 0;
+	struct ubifs_dqblk *ud;
+
+	down_write(&dqopt->dqio_sem);
+
+	ud = ubifs_dqblk_get(c, dquot->dq_id);
+	if (!ud) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ud->dqblk = dquot->dq_dqb;
+
+out:
+	up_write(&dqopt->dqio_sem);
+
+	return ret;
+}
+
+/**
+ * ubifs_release_dquot - release memory associated to a dquot entry
+ * @dquot: The dquot entry
+ *
+ * Nothing to do here, we didn't allocate anything. Our data is freed at unmount
+ * time.
+ */
+static int ubifs_release_dquot(struct dquot *dquot)
+{
+	return 0;
+}
+
+/**
+ * ubifs_free_file_info - free memory allocated during reading the file info
+ * @sb: The superblock
+ * @type: Quota type
+ *
+ * Nothing to do here.
+ */
+static int ubifs_free_file_info(struct super_block *sb, int type)
+{
+	return 0;
+}
+
+static int ubifs_get_next_id(struct super_block *sb, struct kqid *qid)
+{
+	struct quota_info *dqopt = sb_dqopt(sb);
+	struct ubifs_info *c = sb->s_fs_info;
+	struct ubifs_dqblk *ud;
+	int ret = 0;
+
+	down_read(&dqopt->dqio_sem);
+
+	ud = ubifs_dqblk_find_next(c, *qid);
+	if (!ud) {
+		ret = -ENOENT;
+		goto out;
+	}
+
+	*qid = ud->kqid;
+out:
+	up_read(&dqopt->dqio_sem);
+
+	return ret;
+}
+
+static const struct quota_format_ops ubifs_format_ops = {
+	.check_quota_file	= ubifs_check_quota_file,
+	.read_file_info		= ubifs_read_file_info,
+	.write_file_info	= ubifs_write_file_info,
+	.free_file_info		= ubifs_free_file_info,
+	.read_dqblk		= ubifs_read_dquot,
+	.commit_dqblk		= ubifs_write_dquot,
+	.release_dqblk		= ubifs_release_dquot,
+	.get_next_id		= ubifs_get_next_id,
+};
+
+/**
+ * add_inode_quota - read quota informations for an inode
+ * @c: UBIFS file-system description object
+ * @zbr: The zbranch to read the inode from
+ *
+ * This reads the inode as referred to by @zbr from the medium and
+ * extracts the quota relevant informations. Returns 0 for success
+ * or a negative error code otherwise.
+ */
+static int add_inode_quota(struct ubifs_info *c, struct ubifs_zbranch *zbr)
+{
+	struct ubifs_ino_node *ino;
+	int err, type = key_type(c, &zbr->key);
+	struct kqid qid[MAXQUOTAS];
+	kprojid_t kprojid;
+	kgid_t kgid;
+	kuid_t kuid;
+	int i;
+
+	if (type != UBIFS_INO_KEY) {
+		ubifs_err(c, "%s called on non INO node %d", __func__, type);
+		return 0;
+	}
+
+	if (zbr->len < UBIFS_CH_SZ) {
+		ubifs_err(c, "bad leaf length %d (LEB %d:%d)",
+				zbr->len, zbr->lnum, zbr->offs);
+		return -EINVAL;
+	}
+
+	ino = kmalloc(zbr->len, GFP_NOFS);
+	if (!ino)
+		return -ENOMEM;
+
+	err = ubifs_tnc_read_node(c, zbr, ino);
+	if (err) {
+		ubifs_err(c, "cannot read leaf node at LEB %d:%d, error %d",
+				zbr->lnum, zbr->offs, err);
+		goto out_free;
+	}
+
+	kuid = make_kuid(&init_user_ns, le32_to_cpu(ino->uid));
+	qid[USRQUOTA] = make_kqid_uid(kuid);
+
+	kgid = make_kgid(&init_user_ns, le32_to_cpu(ino->gid));
+	qid[GRPQUOTA] = make_kqid_gid(kgid);
+
+	kprojid = make_kprojid(&init_user_ns, le32_to_cpu(ino->projid));
+	qid[PRJQUOTA] = make_kqid_projid(kprojid);
+
+	for (i = 0; i < UBIFS_MAXQUOTAS; i++) {
+		struct ubifs_dqblk *ud;
+
+		ud = ubifs_dqblk_get(c, qid[i]);
+		if (!ud) {
+			err = -ENOMEM;
+			goto out_free;
+		}
+
+		if (S_ISREG(le32_to_cpu(ino->mode)))
+			ud->dqblk.dqb_curspace += le64_to_cpu(ino->size);
+		ud->dqblk.dqb_curinodes++;
+	}
+
+	err = 0;
+
+out_free:
+	kfree(ino);
+
+	return err;
+}
+
+/**
+ * get_next_parent_inum - get the next inum
+ * @c: UBIFS file-system description object
+ * @znode: The znode to start searching from
+ * @inum: The next inum returned here
+ *
+ * Helper function for ubifs_quota_walk_index(). If we know the next inum we
+ * find up the tree is still the same as we just handled we do not have to walk
+ * down the tree but can skip these branches. Returns 0 for success or -ENOENT
+ * when we can't go further to the upper-right but hit the root node instead.
+ */
+static int get_next_parent_inum(struct ubifs_info *c, struct ubifs_znode *znode,
+				ino_t *inum)
+{
+	struct ubifs_znode *zp;
+
+	while (1) {
+		int nn;
+
+		zp = znode->parent;
+		if (!zp)
+			return -ENOENT;
+
+		nn = znode->iip + 1;
+		znode = zp;
+
+		if (nn < znode->child_cnt) {
+			*inum = key_inum(c, &znode->zbranch[nn].key);
+			return 0;
+		}
+	}
+}
+
+/**
+ * ubifs_quota_walk_index - Collect quota info
+ * @c: UBIFS file-system description object
+ *
+ * This function walks the whole index and collects the quota usage information
+ * for all inodes. Returns 0 for success or a negative error code otherwise.
+ */
+static int ubifs_quota_walk_index(struct ubifs_info *c)
+{
+	int err;
+	struct ubifs_znode *znode;
+	int i, nn = 0;
+	ino_t inum = 0, pinum;
+
+	if (!c->zroot.znode) {
+		c->zroot.znode = ubifs_load_znode(c, &c->zroot, NULL, 0);
+		if (IS_ERR(c->zroot.znode)) {
+			err = PTR_ERR(c->zroot.znode);
+			c->zroot.znode = NULL;
+			return err;
+		}
+	}
+
+	znode = c->zroot.znode;
+
+	while (1) {
+		while (znode->level != 0) {
+			znode = ubifs_get_znode(c, znode, nn);
+			if (IS_ERR(znode))
+				return PTR_ERR(znode);
+			nn = 0;
+		}
+
+		for (i = 0; i < znode->child_cnt; i++) {
+			if (inum == key_inum(c, &znode->zbranch[i].key))
+				continue;
+
+			add_inode_quota(c, &znode->zbranch[i]);
+			inum = key_inum(c, &znode->zbranch[i].key);
+		}
+
+		while (1) {
+			struct ubifs_znode *zp;
+
+			zp = znode->parent;
+			if (!zp)
+				return 0;
+
+			nn = znode->iip + 1;
+			znode = zp;
+
+			err = get_next_parent_inum(c, znode, &pinum);
+
+			/*
+			 * Optimization: When the next parent node is still for
+			 * the inode we just handled we can skip parsing our
+			 * children.
+			 */
+			if (!err && pinum == inum)
+				continue;
+
+			/*
+			 * Optimization: We can skip scanning all child nodes
+			 * which are for the same inode as we already looked at.
+			 */
+			while (nn < znode->child_cnt - 1 &&
+			       inum == key_inum(c, &znode->zbranch[nn + 1].key))
+				nn++;
+
+			if (nn < znode->child_cnt)
+				break;
+		}
+	}
+}
+
+/**
+ * ubifs_enable_quotas - enable quota
+ * @c: UBIFS file-system description object
+ *
+ * Enable usage tracking for all quota types.
+ */
+int ubifs_enable_quotas(struct ubifs_info *c)
+{
+	struct super_block *sb = c->vfs_sb;
+	struct quota_info *dqopt = sb_dqopt(sb);
+	int type, ret;
+
+	if (!c->quota_enable)
+		return 0;
+
+	dqopt->flags |= DQUOT_QUOTA_SYS_FILE | DQUOT_NOLIST_DIRTY;
+
+	for (type = 0; type < UBIFS_MAXQUOTAS; type++) {
+		if (!(c->quota_enable & (1 << type)))
+			continue;
+
+		ret = dquot_enable_sb(sb, type, QFMT_UBIFS,
+				   DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
+		if (ret)
+			goto out_quota_off;
+
+		c->dqblk_tree[type] = RB_ROOT;
+	}
+
+	return ubifs_quota_walk_index(c);
+
+out_quota_off:
+	ubifs_disable_quotas(c);
+
+	return ret;
+}
+
+/**
+ * ubifs_disable_quotas - disable quota
+ * @c: UBIFS file-system description object
+ *
+ * Disable quota for UBFIS.
+ */
+void ubifs_disable_quotas(struct ubifs_info *c)
+{
+	struct rb_node *n;
+	struct ubifs_dqblk *ud;
+	int type;
+
+	if (!c->quota_enable)
+		return;
+
+	dquot_disable(c->vfs_sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
+
+	for (type = 0; type < UBIFS_MAXQUOTAS; type++) {
+		while ((n = rb_first(&c->dqblk_tree[type]))) {
+			ud = rb_entry(n, struct ubifs_dqblk, rb);
+			rb_erase(n, &c->dqblk_tree[type]);
+			kfree(ud);
+		}
+	}
+}
+
+static int ubifs_get_projid(struct inode *inode, kprojid_t *projid)
+{
+	struct ubifs_inode *ui = ubifs_inode(inode);
+
+	*projid = ui->projid;
+
+	return 0;
+}
+
+static const struct dquot_operations ubifs_dquot_operations = {
+	.write_dquot	= dquot_commit,
+	.acquire_dquot	= dquot_acquire,
+	.release_dquot	= dquot_release,
+	.mark_dirty	= dquot_mark_dquot_dirty,
+	.write_info	= dquot_commit_info,
+	.alloc_dquot	= dquot_alloc,
+	.destroy_dquot	= dquot_destroy,
+	.get_next_id	= dquot_get_next_id,
+	.get_projid	= ubifs_get_projid,
+};
+
+static const struct quotactl_ops ubifs_quotactl_ops = {
+	.get_state	= dquot_get_state,
+	.set_info	= dquot_set_dqinfo,
+	.get_dqblk	= dquot_get_dqblk,
+	.set_dqblk	= dquot_set_dqblk,
+	.get_nextdqblk	= dquot_get_next_dqblk,
+};
+
+static struct quota_format_type ubifs_quota_format = {
+	.qf_fmt_id	= QFMT_UBIFS,
+	.qf_ops		= &ubifs_format_ops,
+	.qf_owner	= THIS_MODULE
+};
+
+int ubifs_register_quota_format(void)
+{
+	return register_quota_format(&ubifs_quota_format);
+}
+
+void ubifs_unregister_quota_format(void)
+{
+	return unregister_quota_format(&ubifs_quota_format);
+}
+
+/**
+ * ubifs_init_quota - init quota ops for UBIFS
+ * @c: UBIFS file-system description object
+ *
+ * This inits the quota operations for UBIFS
+ */
+void ubifs_init_quota(struct ubifs_info *c)
+{
+	struct super_block *sb = c->vfs_sb;
+
+	if (!c->quota_enable)
+		return;
+
+	sb->dq_op = &ubifs_dquot_operations;
+	sb->s_qcop = &ubifs_quotactl_ops;
+	sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP | QTYPE_MASK_PRJ;
+}
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 281f34789e32..475f8ae7b8af 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -151,6 +151,7 @@ struct inode *ubifs_iget(struct super_block *sb, unsigned long inum)
 
 	switch (inode->i_mode & S_IFMT) {
 	case S_IFREG:
+		inode_set_bytes(inode, ino->size);
 		inode->i_mapping->a_ops = &ubifs_file_address_operations;
 		inode->i_op = &ubifs_file_inode_operations;
 		inode->i_fop = &ubifs_file_operations;
@@ -354,6 +355,7 @@ static void ubifs_evict_inode(struct inode *inode)
 	if (is_bad_inode(inode))
 		goto out;
 
+	dquot_initialize(inode);
 	ui->ui_size = inode->i_size = 0;
 	err = ubifs_jnl_delete_inode(c, inode);
 	if (err)
@@ -363,7 +365,7 @@ static void ubifs_evict_inode(struct inode *inode)
 		 */
 		ubifs_err(c, "can't delete inode %lu, error %d",
 			  inode->i_ino, err);
-
+	dquot_free_inode(inode);
 out:
 	if (ui->dirty)
 		ubifs_release_dirty_inode_budget(c, ui);
@@ -373,6 +375,7 @@ static void ubifs_evict_inode(struct inode *inode)
 		smp_wmb();
 	}
 done:
+	dquot_drop(inode);
 	clear_inode(inode);
 	fscrypt_put_encryption_info(inode);
 }
@@ -435,6 +438,9 @@ static int ubifs_show_options(struct seq_file *s, struct dentry *root)
 	else if (c->mount_opts.chk_data_crc == 1)
 		seq_puts(s, ",no_chk_data_crc");
 
+	if (c->quota_enable)
+		seq_puts(s, ",quota");
+
 	if (c->mount_opts.override_compr) {
 		seq_printf(s, ",compr=%s",
 			   ubifs_compr_name(c, c->mount_opts.compr_type));
@@ -927,6 +933,29 @@ static int check_volume_empty(struct ubifs_info *c)
 	return 0;
 }
 
+#ifdef CONFIG_QUOTA
+static struct dquot **ubifs_get_dquots(struct inode *inode)
+{
+	return ubifs_inode(inode)->i_dquot;
+}
+
+static ssize_t ubifs_quota_read(struct super_block *sb, int type, char *data,
+				size_t len, loff_t off)
+{
+	BUG();
+
+	return 0;
+}
+
+static ssize_t ubifs_quota_write(struct super_block *sb, int type, const char *data,
+				 size_t len, loff_t off)
+{
+	BUG();
+
+	return 0;
+}
+#endif
+
 /*
  * UBIFS mount options.
  *
@@ -954,6 +983,9 @@ enum {
 	Opt_auth_key,
 	Opt_auth_hash_name,
 	Opt_ignore,
+	Opt_usrquota,
+	Opt_grpquota,
+	Opt_prjquota,
 	Opt_err,
 };
 
@@ -970,6 +1002,9 @@ static const match_table_t tokens = {
 	{Opt_ignore, "ubi=%s"},
 	{Opt_ignore, "vol=%s"},
 	{Opt_assert, "assert=%s"},
+	{Opt_usrquota, "usrquota"},
+	{Opt_grpquota, "grpquota"},
+	{Opt_prjquota, "prjquota"},
 	{Opt_err, NULL},
 };
 
@@ -1104,6 +1139,23 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options,
 			break;
 		case Opt_ignore:
 			break;
+#ifdef CONFIG_QUOTA
+		case Opt_usrquota:
+			c->quota_enable |= 1 << USRQUOTA;
+			break;
+		case Opt_grpquota:
+			c->quota_enable |= 1 << GRPQUOTA;
+			break;
+		case Opt_prjquota:
+			c->quota_enable |= 1 << PRJQUOTA;
+			break;
+#else
+		case Opt_usrquota:
+		case Opt_grpquota:
+		case Opt_prjquota:
+			ubifs_err(c, "quota operations not supported");
+			break;
+#endif
 		default:
 		{
 			unsigned long flag;
@@ -1800,6 +1852,7 @@ static int ubifs_remount_rw(struct ubifs_info *c)
 		 */
 		err = dbg_check_space_info(c);
 	}
+	c->vfs_sb->s_flags &= ~SB_RDONLY;
 
 	mutex_unlock(&c->umount_mutex);
 	return err;
@@ -1869,6 +1922,7 @@ static void ubifs_remount_ro(struct ubifs_info *c)
 	err = dbg_check_space_info(c);
 	if (err)
 		ubifs_ro_mode(c, err);
+	c->vfs_sb->s_flags |= SB_RDONLY;
 	mutex_unlock(&c->umount_mutex);
 }
 
@@ -1879,6 +1933,8 @@ static void ubifs_put_super(struct super_block *sb)
 
 	ubifs_msg(c, "un-mount UBI device %d", c->vi.ubi_num);
 
+	ubifs_disable_quotas(c);
+
 	/*
 	 * The following asserts are only valid if there has not been a failure
 	 * of the media. For example, there will be dirty inodes if we failed
@@ -1976,11 +2032,17 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data)
 		err = ubifs_remount_rw(c);
 		if (err)
 			return err;
+		err = dquot_resume(sb, -1);
+		if (err)
+			return err;
 	} else if (!c->ro_mount && (*flags & SB_RDONLY)) {
 		if (c->ro_error) {
 			ubifs_msg(c, "cannot re-mount R/O due to prior errors");
 			return -EROFS;
 		}
+		err = dquot_suspend(sb, -1);
+		if (err)
+			return err;
 		ubifs_remount_ro(c);
 	}
 
@@ -2012,6 +2074,11 @@ const struct super_operations ubifs_super_operations = {
 	.remount_fs    = ubifs_remount_fs,
 	.show_options  = ubifs_show_options,
 	.sync_fs       = ubifs_sync_fs,
+#ifdef CONFIG_QUOTA
+	.get_dquots    = ubifs_get_dquots,
+	.quota_read    = ubifs_quota_read,
+	.quota_write   = ubifs_quota_write,
+#endif
 };
 
 /**
@@ -2172,6 +2239,8 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
 #endif
 	fscrypt_set_ops(sb, &ubifs_crypt_operations);
 
+	ubifs_init_quota(c);
+
 	mutex_lock(&c->umount_mutex);
 	err = mount_ubifs(c);
 	if (err) {
@@ -2186,6 +2255,10 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
 		goto out_umount;
 	}
 
+	err = ubifs_enable_quotas(c);
+	if (err)
+		goto out_umount;
+
 	sb->s_root = d_make_root(root);
 	if (!sb->s_root) {
 		err = -ENOMEM;
@@ -2394,6 +2467,10 @@ static int __init ubifs_init(void)
 
 	dbg_debugfs_init();
 
+	err = ubifs_register_quota_format();
+	if (err)
+		goto out_compressors;
+
 	err = register_filesystem(&ubifs_fs_type);
 	if (err) {
 		pr_err("UBIFS error (pid %d): cannot register file system, error %d",
@@ -2404,6 +2481,8 @@ static int __init ubifs_init(void)
 
 out_dbg:
 	dbg_debugfs_exit();
+	ubifs_unregister_quota_format();
+out_compressors:
 	ubifs_compressors_exit();
 out_shrinker:
 	unregister_shrinker(&ubifs_shrinker_info);
@@ -2429,6 +2508,7 @@ static void __exit ubifs_exit(void)
 	 */
 	rcu_barrier();
 	kmem_cache_destroy(ubifs_inode_slab);
+	ubifs_unregister_quota_format();
 	unregister_filesystem(&ubifs_fs_type);
 }
 module_exit(ubifs_exit);
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
index 188fa036e655..624568365ad3 100644
--- a/fs/ubifs/tnc.c
+++ b/fs/ubifs/tnc.c
@@ -600,7 +600,7 @@ struct ubifs_znode *ubifs_get_znode(struct ubifs_info *c,
  * This function returns %0 if the next TNC entry is found, %-ENOENT if there is
  * no next entry, or a negative error code otherwise.
  */
-static int tnc_next(struct ubifs_info *c, struct ubifs_znode **zn, int *n)
+int tnc_next(struct ubifs_info *c, struct ubifs_znode **zn, int *n)
 {
 	struct ubifs_znode *znode = *zn;
 	int nn = *n;
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index fd9e52749ef7..79755ac4732f 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -27,6 +27,7 @@
 #include <linux/security.h>
 #include <linux/xattr.h>
 #include <linux/random.h>
+#include <linux/quotaops.h>
 #include <crypto/hash_info.h>
 #include <crypto/hash.h>
 #include <crypto/algapi.h>
@@ -157,6 +158,8 @@
 
 #define UBIFS_DEF_PROJID 0
 
+#define UBIFS_MAXQUOTAS 3
+
 /*
  * Lockdep classes for UBIFS inode @ui_mutex.
  */
@@ -416,6 +419,9 @@ struct ubifs_inode {
 	loff_t synced_i_size;
 	loff_t ui_size;
 	int flags;
+#ifdef CONFIG_QUOTA
+	struct dquot *i_dquot[UBIFS_MAXQUOTAS];
+#endif
 	kprojid_t projid;
 	pgoff_t last_page_read;
 	pgoff_t read_in_a_row;
@@ -1045,6 +1051,7 @@ struct ubifs_debug_info;
  * @rw_incompat: the media is not R/W compatible
  * @assert_action: action to take when a ubifs_assert() fails
  * @authenticated: flag indigating the FS is mounted in authenticated mode
+ * @quota_enable: If true, quota is enabled on this filesystem
  *
  * @tnc_mutex: protects the Tree Node Cache (TNC), @zroot, @cnext, @enext, and
  *             @calc_idx_sz
@@ -1386,6 +1393,9 @@ struct ubifs_info {
 	struct ubi_device_info di;
 	struct ubi_volume_info vi;
 
+	unsigned int quota_enable;
+	struct rb_root dqblk_tree[UBIFS_MAXQUOTAS];
+
 	struct rb_root orph_tree;
 	struct list_head orph_list;
 	struct list_head orph_new;
@@ -2108,6 +2118,32 @@ static inline bool ubifs_crypt_is_encrypted(const struct inode *inode)
 	return ui->flags & UBIFS_CRYPT_FL;
 }
 
+/* quota.c */
+#ifdef CONFIG_QUOTA
+int ubifs_register_quota_format(void);
+void ubifs_unregister_quota_format(void);
+void ubifs_init_quota(struct ubifs_info *c);
+int ubifs_enable_quotas(struct ubifs_info *c);
+void ubifs_disable_quotas(struct ubifs_info *c);
+#else
+static inline int ubifs_register_quota_format(void)
+{
+	return 0;
+}
+static inline void ubifs_unregister_quota_format(void)
+{
+}
+static inline void ubifs_init_quota(struct ubifs_info *c)
+{
+}
+static inline int ubifs_enable_quotas(struct ubifs_info *c)
+{
+	return 0;
+}
+static inline void ubifs_disable_quotas(struct ubifs_info *c)
+{
+}
+#endif
 /* Normal UBIFS messages */
 __printf(2, 3)
 void ubifs_msg(const struct ubifs_info *c, const char *fmt, ...);
diff --git a/include/uapi/linux/quota.h b/include/uapi/linux/quota.h
index e1787c0df601..7082868ca225 100644
--- a/include/uapi/linux/quota.h
+++ b/include/uapi/linux/quota.h
@@ -78,6 +78,7 @@
 #define	QFMT_VFS_V0 2
 #define QFMT_OCFS2 3
 #define	QFMT_VFS_V1 4
+#define QFMT_UBIFS 5
 
 /* Size of block in which space limits are passed through the quota
  * interface */
