/* * Quota code necessary even when VFS quota support is not compiled * into the kernel. The interesting stuff is over in dquot.c, here * we have symbols for initial quotactl(2) handling, the sysctl(2) * variables, etc - things needed even when quota support disabled. */ #include #include #include #include #include #include #include #include #include #include #include #include /* Check validity of generic quotactl commands */ static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id) { if (type >= MAXQUOTAS) return -EINVAL; if (!sb && cmd != Q_SYNC) return -ENODEV; /* Is operation supported? */ if (sb && !sb->s_qcop) return -ENOSYS; switch (cmd) { case Q_GETFMT: break; case Q_QUOTAON: if (!sb->s_qcop->quota_on) return -ENOSYS; break; case Q_QUOTAOFF: if (!sb->s_qcop->quota_off) return -ENOSYS; break; case Q_SETINFO: if (!sb->s_qcop->set_info) return -ENOSYS; break; case Q_GETINFO: if (!sb->s_qcop->get_info) return -ENOSYS; break; case Q_SETQUOTA: if (!sb->s_qcop->set_dqblk) return -ENOSYS; break; case Q_GETQUOTA: if (!sb->s_qcop->get_dqblk) return -ENOSYS; break; case Q_SYNC: if (sb && !sb->s_qcop->quota_sync) return -ENOSYS; break; default: return -EINVAL; } /* Is quota turned on for commands which need it? */ switch (cmd) { case Q_GETFMT: case Q_GETINFO: case Q_QUOTAOFF: case Q_SETINFO: case Q_SETQUOTA: case Q_GETQUOTA: /* This is just informative test so we are satisfied without a lock */ if (!sb_has_quota_enabled(sb, type)) return -ESRCH; } /* Check privileges */ if (cmd == Q_GETQUOTA) { if (((type == USRQUOTA && current->euid != id) || (type == GRPQUOTA && !in_egroup_p(id))) && !capable(CAP_SYS_ADMIN)) return -EPERM; } else if (cmd != Q_GETFMT && cmd != Q_SYNC && cmd != Q_GETINFO) if (!capable(CAP_SYS_ADMIN)) return -EPERM; return 0; } /* Check validity of XFS Quota Manager commands */ static int xqm_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id) { if (type >= XQM_MAXQUOTAS) return -EINVAL; if (!sb) return -ENODEV; if (!sb->s_qcop) return -ENOSYS; switch (cmd) { case Q_XQUOTAON: case Q_XQUOTAOFF: case Q_XQUOTARM: if (!sb->s_qcop->set_xstate) return -ENOSYS; break; case Q_XGETQSTAT: if (!sb->s_qcop->get_xstate) return -ENOSYS; break; case Q_XSETQLIM: if (!sb->s_qcop->set_xquota) return -ENOSYS; break; case Q_XGETQUOTA: if (!sb->s_qcop->get_xquota) return -ENOSYS; break; case Q_XQUOTASYNC: if (!sb->s_qcop->quota_sync) return -ENOSYS; break; default: return -EINVAL; } /* Check privileges */ if (cmd == Q_XGETQUOTA) { if (((type == XQM_USRQUOTA && current->euid != id) || (type == XQM_GRPQUOTA && !in_egroup_p(id))) && !capable(CAP_SYS_ADMIN)) return -EPERM; } else if (cmd != Q_XGETQSTAT && cmd != Q_XQUOTASYNC) { if (!capable(CAP_SYS_ADMIN)) return -EPERM; } return 0; } static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id) { int error; if (XQM_COMMAND(cmd)) error = xqm_quotactl_valid(sb, type, cmd, id); else error = generic_quotactl_valid(sb, type, cmd, id); if (!error) error = security_quotactl(cmd, type, id, sb); return error; } static void quota_sync_sb(struct super_block *sb, int type) { int cnt; struct inode *discard[MAXQUOTAS]; sb->s_qcop->quota_sync(sb, type); /* This is not very clever (and fast) but currently I don't know about * any other simple way of getting quota data to disk and we must get * them there for userspace to be visible... */ if (sb->s_op->sync_fs) sb->s_op->sync_fs(sb, 1); sync_blockdev(sb->s_bdev); /* Now when everything is written we can discard the pagecache so * that userspace sees the changes. We need i_mutex and so we could * not do it inside dqonoff_sem. Moreover we need to be carefull * about races with quotaoff() (that is the reason why we have own * reference to inode). */ down(&sb_dqopt(sb)->dqonoff_sem); for (cnt = 0; cnt < MAXQUOTAS; cnt++) { discard[cnt] = NULL; if (type != -1 && cnt != type) continue; if (!sb_has_quota_enabled(sb, cnt)) continue; discard[cnt] = igrab(sb_dqopt(sb)->files[cnt]); } up(&sb_dqopt(sb)->dqonoff_sem); for (cnt = 0; cnt < MAXQUOTAS; cnt++) { if (discard[cnt]) { mutex_lock(&discard[cnt]->i_mutex); truncate_inode_pages(&discard[cnt]->i_data, 0); mutex_unlock(&discard[cnt]->i_mutex); iput(discard[cnt]); } } } void sync_dquots(struct super_block *sb, int type) { int cnt, dirty; if (sb) { if (sb->s_qcop->quota_sync) quota_sync_sb(sb, type); return; } spin_lock(&sb_lock); restart: list_for_each_entry(sb, &super_blocks, s_list) { /* This test just improves performance so it needn't be reliable... */ for (cnt = 0, dirty = 0; cnt < MAXQUOTAS; cnt++) if ((type == cnt || type == -1) && sb_has_quota_enabled(sb, cnt) && info_any_dirty(&sb_dqopt(sb)->info[cnt])) dirty = 1; if (!dirty) continue; sb->s_count++; spin_unlock(&sb_lock); down_read(&sb->s_umount); if (sb->s_root && sb->s_qcop->quota_sync) quota_sync_sb(sb, type); up_read(&sb->s_umount); spin_lock(&sb_lock); if (__put_super_and_need_restart(sb)) goto restart; } spin_unlock(&sb_lock); } /* Copy parameters [Some of this is taken from Frohwalt Egerer's original linux-kernel FAQ] What follows is a suggested procedure for reporting Linux bugs. You aren't obliged to use the bug reporting format, it is provided as a guide to the kind of information that can be useful to developers - no more. If the failure includes an "OOPS:" type message in your log or on screen please read "Documentation/oops-tracing.txt" before posting your bug report. This explains what you should do with the "Oops" information to make it useful to the recipient. Send the output to the maintainer of the kernel area that seems to be involved with the problem, and cc the relevant mailing list. Don't worry too much about getting the wrong person. If you are unsure send it to the person responsible for the code relevant to what you were doing. If it occurs repeatably try and describe how to recreate it. That is worth even more than the oops itself. The list of maintainers and mailing lists is in the MAINTAINERS file in this directory. If you know the file name that causes the problem you can use the following command in this directory to find some of the maintainers of that file: perl scripts/get_maintainer.pl -f <filename> If it is a security bug, please copy the Security Contact listed in the MAINTAINERS file. They can help coordinate bugfix and disclosure. See Documentation/SecurityBugs for more information. If you are totally stumped as to whom to send the report, send it to linux-kernel@vger.kernel.org. (For more information on the linux-kernel mailing list see http://www.tux.org/lkml/). This is a suggested format for a bug report sent to the Linux kernel mailing list. Having a standardized bug report form makes it easier for you not to overlook things, and easier for the developers to find the pieces of information they're really interested in. Don't feel you have to follow it. First run the ver_linux script included as scripts/ver_linux, which reports the version of some important subsystems. Run this script with the command "sh scripts/ver_linux". Use that information to fill in all fields of the bug report form, and post it to the mailing list with a subject of "PROBLEM: <one line summary from [1.]>" for easy identification by the developers. [1.] One line summary of the problem: [2.] Full description of the problem/report: [3.] Keywords (i.e., modules, networking, kernel): [4.] Kernel information [4.1.] Kernel version (from /proc/version): [4.2.] Kernel .config file: [5.] Most recent kernel version which did not have the bug: [6.] Output of Oops.. message (if applicable) with symbolic information resolved (see Documentation/oops-tracing.txt) [7.] A small shell script or example program which triggers the problem (if possible) [8.] Environment [8.1.] Software (add the output of the ver_linux script here) [8.2.] Processor information (from /proc/cpuinfo): [8.3.] Module information (from /proc/modules): [8.4.] Loaded driver and hardware information (/proc/ioports, /proc/iomem) [8.5.] PCI information ('lspci -vvv' as root) [8.6.] SCSI information (from /proc/scsi/scsi) [8.7.] Other information that might be relevant to the problem (please look in /proc and include all information that you think to be relevant): [X.] Other notes, patches, fixes, workarounds: Thank you </