In this paper, we address the problem of dynamic allocation of storage bandwidth to application classes so as to meet their response time requirements. We present an approach based on reinforcement learning to address this problem. We argue that a simple learning-based approach may not be practical since it incurs significant memory and search space overheads. To address this issue, we use application-specific knowledge to design an efficient, practical learning-based technique for dynamic storage bandwidth allocation. Our approach can react to dynamically changing workloads, provide isolation to application classes and is stable under overload. We implement our techniques into the Linux kernel and evaluate it using prototype experimentation and trace-driven simulations. Our results show that (i) the use of learning enables the storage system to to reduce the number of QoS violations by a factor of 2.1 and (ii) the implementation overheads of employing such techniques in operating system kernels is small.