X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fllite%2Frw26.c;h=c1393917fbf41b91c42ae843a9c92982ccd95b77;hp=b7e4c5f2d5e04875e7503b38d688c98a79e698ab;hb=1c359423c13c02974fee7cdd35f6599f022f8f4b;hpb=9ea104bfd11327eb800e76ac80308b33688e23ac diff --git a/lustre/llite/rw26.c b/lustre/llite/rw26.c index b7e4c5f..c139391 100644 --- a/lustre/llite/rw26.c +++ b/lustre/llite/rw26.c @@ -20,6 +20,7 @@ * along with Lustre; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #ifdef HAVE_KERNEL_CONFIG_H #include #endif @@ -47,6 +48,7 @@ #define DEBUG_SUBSYSTEM S_LLITE +//#include #include #include "llite_internal.h" #include @@ -71,13 +73,10 @@ static int ll_invalidatepage(struct page *page, unsigned long offset) #else static void ll_invalidatepage(struct page *page, unsigned long offset) { - if (offset) - return; - if (PagePrivate(page)) + if (offset == 0 && PagePrivate(page)) ll_removepage(page); } #endif - static int ll_releasepage(struct page *page, gfp_t gfp_mask) { if (PagePrivate(page)) @@ -85,6 +84,19 @@ static int ll_releasepage(struct page *page, gfp_t gfp_mask) return 1; } +static int ll_set_page_dirty(struct page *page) +{ + struct ll_async_page *llap; + ENTRY; + + llap = llap_from_page(page, LLAP_ORIGIN_UNKNOWN); + if (IS_ERR(llap)) + RETURN(PTR_ERR(llap)); + + llap_write_pending(page->mapping->host, llap); + RETURN(__set_page_dirty_nobuffers(page)); +} + #define MAX_DIRECTIO_SIZE 2*1024*1024*1024UL static inline int ll_get_user_pages(int rw, unsigned long user_addr, @@ -99,10 +111,10 @@ static inline int ll_get_user_pages(int rw, unsigned long user_addr, return -EFBIG; } - page_count = ((user_addr + size + CFS_PAGE_SIZE - 1) >> CFS_PAGE_SHIFT)- - (user_addr >> CFS_PAGE_SHIFT); + page_count = (user_addr + size + CFS_PAGE_SIZE - 1) >> CFS_PAGE_SHIFT; + page_count -= user_addr >> CFS_PAGE_SHIFT; - OBD_ALLOC_GFP(*pages, page_count * sizeof(**pages), GFP_KERNEL); + OBD_ALLOC_WAIT(*pages, page_count * sizeof(**pages)); if (*pages) { down_read(¤t->mm->mmap_sem); result = get_user_pages(current, current->mm, user_addr, @@ -139,14 +151,16 @@ static ssize_t ll_direct_IO_26_seg(int rw, struct inode *inode, { struct brw_page *pga; struct obdo oa; - int i, rc = 0; + int opc, i, rc = 0; size_t length; + struct obd_capa *ocapa; + loff_t file_offset_orig = file_offset; ENTRY; OBD_ALLOC(pga, sizeof(*pga) * page_count); if (!pga) { CDEBUG(D_VFSTRACE, "sizeof(*pga) = %u page_count = %u\n", - (int)sizeof(*pga), page_count); + (int)sizeof(*pga), page_count); RETURN(-ENOMEM); } @@ -155,7 +169,8 @@ static ssize_t ll_direct_IO_26_seg(int rw, struct inode *inode, pga[i].pg = pages[i]; pga[i].off = file_offset; /* To the end of the page, or the length, whatever is less */ - pga[i].count = min_t(int, CFS_PAGE_SIZE -(file_offset & ~CFS_PAGE_MASK), + pga[i].count = min_t(int, CFS_PAGE_SIZE - + (file_offset & ~CFS_PAGE_MASK), length); pga[i].flag = 0; if (rw == READ) @@ -164,15 +179,25 @@ static ssize_t ll_direct_IO_26_seg(int rw, struct inode *inode, ll_inode_fill_obdo(inode, rw, &oa); + if (rw == WRITE) { + lprocfs_counter_add(ll_i2sbi(inode)->ll_stats, + LPROC_LL_DIRECT_WRITE, size); + opc = CAPA_OPC_OSS_WRITE; + llap_write_pending(inode, NULL); + } else { + lprocfs_counter_add(ll_i2sbi(inode)->ll_stats, + LPROC_LL_DIRECT_READ, size); + opc = CAPA_OPC_OSS_RW; + } + ocapa = ll_osscapa_get(inode, current->fsuid, opc); rc = obd_brw_rqset(rw == WRITE ? OBD_BRW_WRITE : OBD_BRW_READ, - ll_i2obdexp(inode), &oa, lsm, page_count, pga, NULL); - if (rc == 0) { - rc = size; - if (rw == WRITE) { - lov_stripe_lock(lsm); - obd_adjust_kms(ll_i2obdexp(inode), lsm, file_offset, 0); - lov_stripe_unlock(lsm); - } + ll_i2dtexp(inode), &oa, lsm, page_count, pga, NULL, + ocapa); + capa_put(ocapa); + if ((rc > 0) && (rw == WRITE)) { + lov_stripe_lock(lsm); + obd_adjust_kms(ll_i2dtexp(inode), lsm, file_offset_orig + rc, 0); + lov_stripe_unlock(lsm); } OBD_FREE(pga, sizeof(*pga) * page_count); @@ -193,29 +218,27 @@ static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb, 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); - unsigned long seg; + unsigned long seg = 0; size_t size = MAX_DIO_SIZE; ENTRY; if (!lli->lli_smd || !lli->lli_smd->lsm_object_id) RETURN(-EBADF); - /* FIXME: io smaller than CFS_PAGE_SIZE is broken on ia64 ??? */ - if ((file_offset & (~CFS_PAGE_MASK)) || (count & ~CFS_PAGE_MASK)) + /* 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 "LPSZ - "), offset=%lld=%llx, pages "LPSZ" (max "LPSZ")\n", + 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) - lprocfs_counter_add(ll_i2sbi(inode)->ll_stats, - LPROC_LL_DIRECT_WRITE, count); + ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_DIRECT_WRITE, count); else - lprocfs_counter_add(ll_i2sbi(inode)->ll_stats, - LPROC_LL_DIRECT_READ, count); + ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_DIRECT_READ, count); /* Check that all user buffers are aligned as well */ for (seg = 0; seg < nr_segs; seg++) { @@ -264,6 +287,7 @@ static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb, (int)size); continue; } + if (tot_bytes > 0) RETURN(tot_bytes); RETURN(page_count < 0 ? page_count : result); @@ -284,7 +308,7 @@ struct address_space_operations ll_aops = { .direct_IO = ll_direct_IO_26, .writepage = ll_writepage_26, .writepages = generic_writepages, - .set_page_dirty = __set_page_dirty_nobuffers, + .set_page_dirty = ll_set_page_dirty, .sync_page = NULL, .prepare_write = ll_prepare_write, .commit_write = ll_commit_write, @@ -292,58 +316,3 @@ struct address_space_operations ll_aops = { .releasepage = ll_releasepage, .bmap = NULL }; - -static int wait_on_page_locked_range(struct address_space *mapping, - pgoff_t start, pgoff_t end) -{ - pgoff_t index; - struct page *page; - int ret = 0; - - if (end < start) - return 0; - - for(index = start; index < end; index++) { - page = find_get_page(mapping, index); - if (page == NULL) - continue; - - wait_on_page_locked(page); - if (PageError(page)) - ret = -EIO; - cond_resched(); - } - - /* Check for outstanding write errors */ - if (test_and_clear_bit(AS_ENOSPC, &mapping->flags)) - ret = -ENOSPC; - if (test_and_clear_bit(AS_EIO, &mapping->flags)) - ret = -EIO; - - return ret; -} - -int ll_sync_page_range(struct inode *inode, struct address_space *mapping, - loff_t pos, size_t count) -{ - pgoff_t start = pos >> CFS_PAGE_SHIFT; - pgoff_t end = (pos + count - 1) >> CFS_PAGE_SHIFT; - struct writeback_control wbc; - int ret; - - wbc.sync_mode = WB_SYNC_ALL; - wbc.nr_to_write = mapping->nrpages * 2; -#ifdef HAVE_WB_RANGE_START - wbc.range_start = start; - wbc.range_end = end; -#else - wbc.start = start; - wbc.end = end; -#endif - ret = generic_writepages(mapping, &wbc); - - if (ret == 0) - ret = wait_on_page_locked_range(mapping, start, end); - return ret; -} -