- llap = llap_from_page(page);
- if (IS_ERR(llap))
- GOTO(out, rc = PTR_ERR(llap));
-
- page_cache_get(page);
- if (llap->llap_write_queued) {
- LL_CDEBUG_PAGE(D_PAGE, page, "marking urgent\n");
- rc = obd_set_async_flags(exp, ll_i2info(inode)->lli_smd, NULL,
- llap->llap_cookie,
- ASYNC_READY | ASYNC_URGENT);
+ rc = obd_brw_async(rw == WRITE ? OBD_BRW_WRITE : OBD_BRW_READ,
+ ll_i2dtexp(inode), oinfo, page_count,
+ pga, NULL, set);
+ if (rc == 0)
+ rc = size;
+
+ OBD_FREE(pga, sizeof(*pga) * page_count);
+ RETURN(rc);
+}
+
+/* This is the maximum size of a single O_DIRECT request, based on a 128kB
+ * kmalloc limit. We need to fit all of the brw_page structs, each one
+ * representing PAGE_SIZE worth of user data, into a single buffer, and
+ * then truncate this to be a full-sized RPC. This is 22MB for 4kB pages. */
+#define MAX_DIO_SIZE ((128 * 1024 / sizeof(struct brw_page) * CFS_PAGE_SIZE) & \
+ ~(PTLRPC_MAX_BRW_SIZE - 1))
+static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
+ const struct iovec *iov, loff_t file_offset,
+ unsigned long nr_segs)
+{
+ struct file *file = iocb->ki_filp;
+ struct inode *inode = file->f_mapping->host;
+ ssize_t count = iov_length(iov, nr_segs), tot_bytes = 0;
+ struct ll_inode_info *lli = ll_i2info(inode);
+ struct lov_stripe_md *lsm = lli->lli_smd;
+ struct ptlrpc_request_set *set;
+ struct obd_info oinfo;
+ struct obdo oa;
+ unsigned long seg = 0;
+ size_t size = MAX_DIO_SIZE;
+ int opc;
+ ENTRY;
+
+ if (!lli->lli_smd || !lli->lli_smd->lsm_object_id)
+ RETURN(-EBADF);
+
+ /* FIXME: io smaller than PAGE_SIZE is broken on ia64 ??? */
+ if ((file_offset & ~CFS_PAGE_MASK) || (count & ~CFS_PAGE_MASK))
+ RETURN(-EINVAL);
+
+ CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), size="LPSZ" (max %lu), "
+ "offset=%lld=%llx, pages "LPSZ" (max %lu)\n",
+ inode->i_ino, inode->i_generation, inode, count, MAX_DIO_SIZE,
+ file_offset, file_offset, count >> CFS_PAGE_SHIFT,
+ MAX_DIO_SIZE >> CFS_PAGE_SHIFT);
+
+ if (rw == WRITE) {
+ ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_DIRECT_WRITE, count);
+ opc = CAPA_OPC_OSS_WRITE;
+ llap_write_pending(inode, NULL);