The academic approach would be to have a discrete, as brief as possible, but complete layer between application and persistence medium (whether it be filesystem, database, or a combination thereof) which counts the size of everything that is added, modified, or removed from persistence and keeps updating the total in the profile.
However, at some point in time you will inevitably run into the problem of having to recalculate everything, so since you will most probably have to write the recalculate-everything code, you might wish (at least in the beginning) to reuse that code and skip the academic solution. So, each time there is an insertion, update or removal, you set a "dirty" flag in the profile, and then you have a separate batch process which looks for "dirty" profiles and recalculates the amount of space occupied, by querying the filesystem, the database, etc.
Of course, this means that quota changes will not be visible immediately, and most importantly, once you have enough customers this approach will be too expensive to be viable, but once you have enough customers you will presumably be rich enough to be able to afford a complete rewrite.
Or, go with the academic solution.