For example, if we are taking the snapshot of a SCSI device, before start of the snapshot (before introduction of the pseudo layer) SCSI major number will point to its own request_fn and queue function. Once the snapshot is on, SCSI major number will point to pseudo devices request_fn and queue function and the pseudo device major number will point to the SCSI device request_fn and queue function. We can thus introduce the pseudo device layer. But this is not a good solution. ll_rw_block() does different types of optimization's for different types of devices [5]. So, in this method ll_rw_block() code has to do all those optimization's for the original device major number if there is no pseudo layer and same optimization's has to be done for pseudo major number if there is a pseudo layer. Such an implementation will again become somewhat similar to implementation of LVM as explained in section 2 and thus will not be a simple, separate module and has to be (hacked!) integrated into the kernel.
This problem has been solved by having a pseudo layer always on top of the original device driver layer. When ever snapshots are on, the required work such as COW push and logging will be effected by the driver. If there is no snapshot, the pseudo request function simply transfers the requests from the pseudo device to the original device.