OSDN Git Service

Merge branch 'for-3.20/core' of git://git.kernel.dk/linux-block
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / fs / block_dev.c
index a9f9279..975266b 100644 (file)
@@ -421,6 +421,46 @@ int bdev_write_page(struct block_device *bdev, sector_t sector,
 }
 EXPORT_SYMBOL_GPL(bdev_write_page);
 
+/**
+ * bdev_direct_access() - Get the address for directly-accessibly memory
+ * @bdev: The device containing the memory
+ * @sector: The offset within the device
+ * @addr: Where to put the address of the memory
+ * @pfn: The Page Frame Number for the memory
+ * @size: The number of bytes requested
+ *
+ * If a block device is made up of directly addressable memory, this function
+ * will tell the caller the PFN and the address of the memory.  The address
+ * may be directly dereferenced within the kernel without the need to call
+ * ioremap(), kmap() or similar.  The PFN is suitable for inserting into
+ * page tables.
+ *
+ * Return: negative errno if an error occurs, otherwise the number of bytes
+ * accessible at this address.
+ */
+long bdev_direct_access(struct block_device *bdev, sector_t sector,
+                       void **addr, unsigned long *pfn, long size)
+{
+       long avail;
+       const struct block_device_operations *ops = bdev->bd_disk->fops;
+
+       if (size < 0)
+               return size;
+       if (!ops->direct_access)
+               return -EOPNOTSUPP;
+       if ((sector + DIV_ROUND_UP(size, 512)) >
+                                       part_nr_sects_read(bdev->bd_part))
+               return -ERANGE;
+       sector += get_start_sect(bdev);
+       if (sector % (PAGE_SIZE / 512))
+               return -EINVAL;
+       avail = ops->direct_access(bdev, sector, addr, pfn, size);
+       if (!avail)
+               return -ERANGE;
+       return min(avail, size);
+}
+EXPORT_SYMBOL_GPL(bdev_direct_access);
+
 /*
  * pseudo-fs
  */