W dniu 21 kwietnia 2011 14:39 użytkownik Arnd Bergmann <arnd@xxxxxxxx> napisał: > On Thursday 21 April 2011, Michał Mirosław wrote: >> W dniu 21 kwietnia 2011 13:15 użytkownik Arnd Bergmann <arnd@xxxxxxxx> napisał: > >> static int mmc_blk_compat_ioctl(struct block_device *bdev, fmode_t mode, >> unsigned int cmd, unsigned long arg) >> { >> struct mmc_ioc_cmd blk; >> >> if (cmd != MMC_IOC_CMD) >> return -EINVAL; >> >> copy_from_user(compat_ptr(arg), &blk) ... >> blk.data_ptr = compat_ptr(blk.__data_ptr_storage32); >> >> return mmc_blk_ioctl_cmd(bdev, &blk); >> } > > Yes, this works, but it requires having a compat_ioctl() handler function that > knows about the data structure, which we generally try to avoid. > The same method would even work if you only had a pointer member in the > structure and did not even attempt to make the structure compatible. Not really. If the structures were different, you would need write code to translate it fully (this doesn't really apply for this simple case, where there is only one pointer at the end of the structure). My example only fixes/converts pointers in place. The compat/native handler could be made in one function that takes another bool arg and ioctl handlers would look like the code below. In this scheme you avoid having to duplicate ioctl handler at all and let compiler optimize out conditionals (you can even force __mmc_blk_ioctl() inline to make sure of it). #ifndef CONFIG_COMPAT static inline void *compat_ptr(unsigned long) { BUG(); return NULL; } #endif static int __mmc_blk_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg, bool compat32) { void __user *p; ... p = compat32 ? compat_ptr(arg) : (void *)arg; ... if (compat32) blk.data_ptr = compat_ptr(blk.__data_ptr_storage32); ... } static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { return __mmc_blk_ioctl(bdev, mode, cmd, arg, false); } #ifdef CONFIG_COMPAT static int mmc_blk_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { return __mmc_blk_ioctl(bdev, mode, cmd, arg, true); } #endif -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html