xref: /openbmc/linux/fs/ntfs/quota.c (revision a1d312de)
1a1d312deSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * quota.c - NTFS kernel quota ($Quota) handling.  Part of the Linux-NTFS
41da177e4SLinus Torvalds  *	     project.
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Copyright (c) 2004 Anton Altaparmakov
71da177e4SLinus Torvalds  */
81da177e4SLinus Torvalds 
91da177e4SLinus Torvalds #ifdef NTFS_RW
101da177e4SLinus Torvalds 
111da177e4SLinus Torvalds #include "index.h"
121da177e4SLinus Torvalds #include "quota.h"
131da177e4SLinus Torvalds #include "debug.h"
141da177e4SLinus Torvalds #include "ntfs.h"
151da177e4SLinus Torvalds 
161da177e4SLinus Torvalds /**
171da177e4SLinus Torvalds  * ntfs_mark_quotas_out_of_date - mark the quotas out of date on an ntfs volume
181da177e4SLinus Torvalds  * @vol:	ntfs volume on which to mark the quotas out of date
191da177e4SLinus Torvalds  *
20c49c3111SRichard Knutsson  * Mark the quotas out of date on the ntfs volume @vol and return 'true' on
21c49c3111SRichard Knutsson  * success and 'false' on error.
221da177e4SLinus Torvalds  */
ntfs_mark_quotas_out_of_date(ntfs_volume * vol)23c49c3111SRichard Knutsson bool ntfs_mark_quotas_out_of_date(ntfs_volume *vol)
241da177e4SLinus Torvalds {
251da177e4SLinus Torvalds 	ntfs_index_context *ictx;
261da177e4SLinus Torvalds 	QUOTA_CONTROL_ENTRY *qce;
271da177e4SLinus Torvalds 	const le32 qid = QUOTA_DEFAULTS_ID;
281da177e4SLinus Torvalds 	int err;
291da177e4SLinus Torvalds 
301da177e4SLinus Torvalds 	ntfs_debug("Entering.");
311da177e4SLinus Torvalds 	if (NVolQuotaOutOfDate(vol))
321da177e4SLinus Torvalds 		goto done;
331da177e4SLinus Torvalds 	if (!vol->quota_ino || !vol->quota_q_ino) {
341da177e4SLinus Torvalds 		ntfs_error(vol->sb, "Quota inodes are not open.");
35c49c3111SRichard Knutsson 		return false;
361da177e4SLinus Torvalds 	}
375955102cSAl Viro 	inode_lock(vol->quota_q_ino);
381da177e4SLinus Torvalds 	ictx = ntfs_index_ctx_get(NTFS_I(vol->quota_q_ino));
391da177e4SLinus Torvalds 	if (!ictx) {
401da177e4SLinus Torvalds 		ntfs_error(vol->sb, "Failed to get index context.");
411da177e4SLinus Torvalds 		goto err_out;
421da177e4SLinus Torvalds 	}
431da177e4SLinus Torvalds 	err = ntfs_index_lookup(&qid, sizeof(qid), ictx);
441da177e4SLinus Torvalds 	if (err) {
451da177e4SLinus Torvalds 		if (err == -ENOENT)
461da177e4SLinus Torvalds 			ntfs_error(vol->sb, "Quota defaults entry is not "
471da177e4SLinus Torvalds 					"present.");
481da177e4SLinus Torvalds 		else
491da177e4SLinus Torvalds 			ntfs_error(vol->sb, "Lookup of quota defaults entry "
501da177e4SLinus Torvalds 					"failed.");
511da177e4SLinus Torvalds 		goto err_out;
521da177e4SLinus Torvalds 	}
531da177e4SLinus Torvalds 	if (ictx->data_len < offsetof(QUOTA_CONTROL_ENTRY, sid)) {
541da177e4SLinus Torvalds 		ntfs_error(vol->sb, "Quota defaults entry size is invalid.  "
551da177e4SLinus Torvalds 				"Run chkdsk.");
561da177e4SLinus Torvalds 		goto err_out;
571da177e4SLinus Torvalds 	}
581da177e4SLinus Torvalds 	qce = (QUOTA_CONTROL_ENTRY*)ictx->data;
591da177e4SLinus Torvalds 	if (le32_to_cpu(qce->version) != QUOTA_VERSION) {
601da177e4SLinus Torvalds 		ntfs_error(vol->sb, "Quota defaults entry version 0x%x is not "
611da177e4SLinus Torvalds 				"supported.", le32_to_cpu(qce->version));
621da177e4SLinus Torvalds 		goto err_out;
631da177e4SLinus Torvalds 	}
641da177e4SLinus Torvalds 	ntfs_debug("Quota defaults flags = 0x%x.", le32_to_cpu(qce->flags));
651da177e4SLinus Torvalds 	/* If quotas are already marked out of date, no need to do anything. */
661da177e4SLinus Torvalds 	if (qce->flags & QUOTA_FLAG_OUT_OF_DATE)
671da177e4SLinus Torvalds 		goto set_done;
681da177e4SLinus Torvalds 	/*
691da177e4SLinus Torvalds 	 * If quota tracking is neither requested, nor enabled and there are no
701da177e4SLinus Torvalds 	 * pending deletes, no need to mark the quotas out of date.
711da177e4SLinus Torvalds 	 */
721da177e4SLinus Torvalds 	if (!(qce->flags & (QUOTA_FLAG_TRACKING_ENABLED |
731da177e4SLinus Torvalds 			QUOTA_FLAG_TRACKING_REQUESTED |
741da177e4SLinus Torvalds 			QUOTA_FLAG_PENDING_DELETES)))
751da177e4SLinus Torvalds 		goto set_done;
761da177e4SLinus Torvalds 	/*
771da177e4SLinus Torvalds 	 * Set the QUOTA_FLAG_OUT_OF_DATE bit thus marking quotas out of date.
781da177e4SLinus Torvalds 	 * This is verified on WinXP to be sufficient to cause windows to
791da177e4SLinus Torvalds 	 * rescan the volume on boot and update all quota entries.
801da177e4SLinus Torvalds 	 */
811da177e4SLinus Torvalds 	qce->flags |= QUOTA_FLAG_OUT_OF_DATE;
821da177e4SLinus Torvalds 	/* Ensure the modified flags are written to disk. */
831da177e4SLinus Torvalds 	ntfs_index_entry_flush_dcache_page(ictx);
841da177e4SLinus Torvalds 	ntfs_index_entry_mark_dirty(ictx);
851da177e4SLinus Torvalds set_done:
861da177e4SLinus Torvalds 	ntfs_index_ctx_put(ictx);
875955102cSAl Viro 	inode_unlock(vol->quota_q_ino);
881da177e4SLinus Torvalds 	/*
891da177e4SLinus Torvalds 	 * We set the flag so we do not try to mark the quotas out of date
901da177e4SLinus Torvalds 	 * again on remount.
911da177e4SLinus Torvalds 	 */
921da177e4SLinus Torvalds 	NVolSetQuotaOutOfDate(vol);
931da177e4SLinus Torvalds done:
941da177e4SLinus Torvalds 	ntfs_debug("Done.");
95c49c3111SRichard Knutsson 	return true;
961da177e4SLinus Torvalds err_out:
971da177e4SLinus Torvalds 	if (ictx)
981da177e4SLinus Torvalds 		ntfs_index_ctx_put(ictx);
995955102cSAl Viro 	inode_unlock(vol->quota_q_ino);
100c49c3111SRichard Knutsson 	return false;
1011da177e4SLinus Torvalds }
1021da177e4SLinus Torvalds 
1031da177e4SLinus Torvalds #endif /* NTFS_RW */
104