filter_io_24.c
来自「lustre 1.6.5 source code」· C语言 代码 · 共 545 行 · 第 1/2 页
C
545 行
rc = fsfilt_send_bio(rw, obd, inode, iobuf); CDEBUG(D_INFO, "tried to %s %d pages, rc = %d\n", rw & OBD_BRW_WRITE ? "write" : "read", iobuf->nr_pages, rc); if (rc > 0) rc = 0; EXIT;cleanup: if (!committed && (rw == OBD_BRW_WRITE)) { int err = fsfilt_commit_async(obd, inode, oti->oti_handle, wait_handle); if (err) CERROR("can't close transaction: %d\n", err); /* * this is error path, so we prefer to return * original error, not this one */ } switch(cleanup_phase) { case 3: case 2: unlock_kiovec(1, &iobuf); case 1: case 0: if (cleanup_phase != 3 && rw == OBD_BRW_WRITE) up(&inode->i_sem); break; default: CERROR("corrupt cleanup_phase (%d)?\n", cleanup_phase); LBUG(); break; } return rc;}/* See if there are unallocated parts in given file region */int filter_range_is_mapped(struct inode *inode, obd_size offset, int len){ int (*fs_bmap)(struct address_space *, long) = inode->i_mapping->a_ops->bmap; int j; /* We can't know if the range is mapped already or not */ if (fs_bmap == NULL) return 0; offset >>= inode->i_blkbits; len >>= inode->i_blkbits; for (j = 0; j < len; j++) if (fs_bmap(inode->i_mapping, offset + j) == 0) return 0; return 1;}/* some kernels require alloc_kiovec callers to zero members through the use of * map_user_kiobuf and unmap_.. we don't use those, so we have a little helper * that makes sure we don't break the rules. */static void clear_kiobuf(struct kiobuf *iobuf){ int i; for (i = 0; i < iobuf->array_len; i++) iobuf->maplist[i] = NULL; iobuf->nr_pages = 0; iobuf->offset = 0; iobuf->length = 0;}struct filter_iobuf *filter_alloc_iobuf(struct filter_obd *filter, int rw, int num_pages){ struct kiobuf *iobuf; int rc; ENTRY; LASSERTF(rw == OBD_BRW_WRITE || rw == OBD_BRW_READ, "%x\n", rw); rc = alloc_kiovec(1, &iobuf); if (rc) RETURN(ERR_PTR(rc)); rc = expand_kiobuf(iobuf, num_pages); if (rc) { free_kiovec(1, &iobuf); RETURN(ERR_PTR(rc)); }#ifdef HAVE_KIOBUF_DOVARY iobuf->dovary = 0; /* this prevents corruption, not present in 2.4.20 */#endif clear_kiobuf(iobuf); RETURN((void *)iobuf);}void filter_free_iobuf(struct filter_iobuf *buf){ struct kiobuf *iobuf = (void *)buf; clear_kiobuf(iobuf); free_kiovec(1, &iobuf);}void filter_iobuf_put(struct filter_obd *filter, struct filter_iobuf *iobuf, struct obd_trans_info *oti){ int thread_id = oti ? oti->oti_thread_id : -1; if (unlikely(thread_id < 0)) { filter_free_iobuf(iobuf); return; } LASSERTF(filter->fo_iobuf_pool[thread_id] == iobuf, "iobuf mismatch for thread %d: pool %p iobuf %p\n", thread_id, filter->fo_iobuf_pool[thread_id], iobuf); clear_kiobuf((void *)iobuf);}int filter_iobuf_add_page(struct obd_device *obd, struct filter_iobuf *buf, struct inode *inode, struct page *page){ struct kiobuf *iobuf = (void *)buf; iobuf->maplist[iobuf->nr_pages++] = page; iobuf->length += CFS_PAGE_SIZE; return 0;}int filter_commitrw_write(struct obd_export *exp, struct obdo *oa, int objcount, struct obd_ioobj *obj, int niocount, struct niobuf_local *res, struct obd_trans_info *oti, int rc){ struct obd_device *obd = exp->exp_obd; struct lvfs_run_ctxt saved; struct niobuf_local *lnb; struct fsfilt_objinfo fso; struct iattr iattr = { 0 }; void *iobuf = NULL; struct inode *inode = NULL; int i, n, cleanup_phase = 0, err; unsigned long now = jiffies; /* DEBUGGING OST TIMEOUTS */ void *wait_handle; ENTRY; LASSERT(oti != NULL); LASSERT(objcount == 1); LASSERT(current->journal_info == NULL); if (rc != 0) GOTO(cleanup, rc); iobuf = filter_iobuf_get(&obd->u.filter, oti); if (IS_ERR(iobuf)) GOTO(cleanup, rc = PTR_ERR(iobuf)); cleanup_phase = 1; fso.fso_dentry = res->dentry; fso.fso_bufcnt = obj->ioo_bufcnt; inode = res->dentry->d_inode; for (i = 0, lnb = res, n = 0; i < obj->ioo_bufcnt; i++, lnb++) { loff_t this_size; /* If overwriting an existing block, we don't need a grant */ if (!(lnb->flags & OBD_BRW_GRANTED) && lnb->rc == -ENOSPC && filter_range_is_mapped(inode, lnb->offset, lnb->len)) lnb->rc = 0; if (lnb->rc) /* ENOSPC, network RPC error */ continue; filter_iobuf_add_page(obd, iobuf, inode, lnb->page); /* We expect these pages to be in offset order, but we'll * be forgiving */ this_size = lnb->offset + lnb->len; if (this_size > iattr.ia_size) iattr.ia_size = this_size; } push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); cleanup_phase = 2; down(&inode->i_sem); oti->oti_handle = fsfilt_brw_start(obd, objcount, &fso, niocount, res, oti); if (IS_ERR(oti->oti_handle)) { up(&inode->i_sem); rc = PTR_ERR(oti->oti_handle); CDEBUG(rc == -ENOSPC ? D_INODE : D_ERROR, "error starting transaction: rc = %d\n", rc); oti->oti_handle = NULL; GOTO(cleanup, rc); } fsfilt_check_slow(obd, now, "brw_start"); i = OBD_MD_FLATIME | OBD_MD_FLMTIME | OBD_MD_FLCTIME; /* If the inode still has SUID+SGID bits set (see filter_precreate()) * then we will accept the UID+GID if sent by the client for * initializing the ownership of this inode. We only allow this to * happen once (so clear these bits) and later only allow setattr. */ if (inode->i_mode & S_ISUID) i |= OBD_MD_FLUID; if (inode->i_mode & S_ISGID) i |= OBD_MD_FLGID; iattr_from_obdo(&iattr, oa, i); if (iattr.ia_valid & (ATTR_UID | ATTR_GID)) { CDEBUG(D_INODE, "update UID/GID to %lu/%lu\n", (unsigned long)oa->o_uid, (unsigned long)oa->o_gid); cap_raise(current->cap_effective, CAP_SYS_RESOURCE); iattr.ia_valid |= ATTR_MODE; iattr.ia_mode = inode->i_mode; if (iattr.ia_valid & ATTR_UID) iattr.ia_mode &= ~S_ISUID; if (iattr.ia_valid & ATTR_GID) iattr.ia_mode &= ~S_ISGID; rc = filter_update_fidea(exp, inode, oti->oti_handle, oa); } /* filter_direct_io drops i_sem */ rc = filter_direct_io(OBD_BRW_WRITE, res->dentry, iobuf, exp, &iattr, oti, &wait_handle); if (rc == 0) obdo_from_inode(oa, inode, FILTER_VALID_FLAGS); fsfilt_check_slow(obd, now, "direct_io"); err = fsfilt_commit_wait(obd, inode, wait_handle); if (err) { CERROR("Failure to commit OST transaction (%d)?\n", err); rc = err; } if (obd->obd_replayable && !rc) LASSERTF(oti->oti_transno <= obd->obd_last_committed, "oti_transno "LPU64" last_committed "LPU64"\n", oti->oti_transno, obd->obd_last_committed); fsfilt_check_slow(obd, now, "commitrw commit");cleanup: filter_grant_commit(exp, niocount, res); switch (cleanup_phase) { case 2: pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); LASSERT(current->journal_info == NULL); case 1: filter_iobuf_put(&obd->u.filter, iobuf, oti); case 0: /* * lnb->page automatically returns back into per-thread page * pool (bug 5137) */ f_dput(res->dentry); } RETURN(rc);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?