struct llog_cookie och_cookie;
struct mdc_open_data *och_mod;
__u32 och_magic;
+ int och_flags;
};
#define OBD_CLIENT_HANDLE_MAGIC 0xd15ea5ed
op_data.attr.ia_valid = ATTR_MODE | ATTR_ATIME_SET |
ATTR_MTIME_SET | ATTR_CTIME_SET;
- if (!S_ISREG(llu_i2stat(inode)->st_mode)) {
- op_data.attr.ia_valid |= ATTR_SIZE | ATTR_BLOCKS;
- } else {
- /* Inode cannot be dirty. Close the epoch. */
- op_data.flags |= MF_EPOCH_CLOSE;
- /* XXX: Send CHANGE flag only if Size-on-MDS inode attributes
- * are really changed. */
- op_data.flags |= MF_SOM_CHANGE;
-
- /* Pack Size-on-MDS attrinodes if valid. */
- if ((lli->lli_flags & LLIF_MDS_SIZE_LOCK) ||
- !llu_local_size(inode))
- op_data.attr.ia_valid |=
- OBD_MD_FLSIZE | OBD_MD_FLBLOCKS;
+ if (fd->fd_flags & FMODE_WRITE) {
+ if (!S_ISREG(llu_i2stat(inode)->st_mode)) {
+ op_data.attr.ia_valid |= ATTR_SIZE | ATTR_BLOCKS;
+ } else {
+ /* Inode cannot be dirty. Close the epoch. */
+ op_data.flags |= MF_EPOCH_CLOSE;
+ /* XXX: Send CHANGE flag only if Size-on-MDS inode attributes
+ * are really changed. */
+ op_data.flags |= MF_SOM_CHANGE;
+
+ /* Pack Size-on-MDS attributes if we are in IO epoch and
+ * attributes are valid. */
+ LASSERT(!(lli->lli_flags & LLIF_MDS_SIZE_LOCK));
+ if (!llu_local_size(inode))
+ op_data.attr.ia_valid |=
+ OBD_MD_FLSIZE | OBD_MD_FLBLOCKS;
+ }
}
-
op_data.fid1 = lli->lli_fid;
op_data.attr.ia_atime = st->st_atime;
op_data.attr.ia_mtime = st->st_mtime;
if (rc == -EAGAIN) {
/* We are the last writer, so the MDS has instructed us to get
* the file size and any write cookies, then close again. */
+ LASSERT(fd->fd_flags & FMODE_WRITE);
rc = llu_sizeonmds_update(inode, &och->och_fh);
if (rc) {
CERROR("inode %llu mdc Size-on-MDS update failed: "
static void ll_prepare_close(struct inode *inode, struct md_op_data *op_data,
struct obd_client_handle *och)
{
- struct ll_inode_info *lli = ll_i2info(inode);
- int new_pending = 0;
ENTRY;
op_data->attr.ia_valid = ATTR_MODE | ATTR_ATIME_SET |
ATTR_MTIME_SET | ATTR_CTIME_SET;
- if (!S_ISREG(inode->i_mode)) {
- op_data->attr.ia_valid |= ATTR_SIZE | ATTR_BLOCKS;
+ if (!(och->och_flags & FMODE_WRITE))
goto out;
- }
- spin_lock(&lli->lli_lock);
- if (!(list_empty(&lli->lli_pending_write_llaps)) &&
- !(lli->lli_flags & LLIF_EPOCH_PENDING)) {
- LASSERT(lli->lli_pending_och == NULL);
- /* Inode is dirty and there is no pending write done request
- * yet, DONE_WRITE is to be sent later. */
- lli->lli_flags |= LLIF_EPOCH_PENDING;
- lli->lli_pending_och = och;
- new_pending = 1;
- } else {
- ll_epoch_close(inode, op_data);
- }
- spin_unlock(&lli->lli_lock);
+ if (!S_ISREG(inode->i_mode))
+ op_data->attr.ia_valid |= ATTR_SIZE | ATTR_BLOCKS;
+ else
+ ll_epoch_close(inode, op_data, &och, 0);
- if (new_pending) {
- inode = igrab(inode);
- LASSERT(inode);
- }
out:
ll_pack_inode2opdata(inode, op_data, &och->och_fh);
EXIT;
GOTO(out, rc = -ENOMEM);
ll_prepare_close(inode, op_data, och);
- epoch_close = (op_data->flags & MF_EPOCH_CLOSE) ||
- !S_ISREG(inode->i_mode);
+ epoch_close = (och->och_flags & FMODE_WRITE) &&
+ ((op_data->flags & MF_EPOCH_CLOSE) ||
+ !S_ISREG(inode->i_mode));
rc = md_close(md_exp, op_data, och, &req);
ll_finish_md_op_data(op_data);
inode->i_ino, rc);
}
- if (!epoch_close)
- ll_init_done_writing(inode);
+ if (!epoch_close && (och->och_flags & FMODE_WRITE))
+ ll_queue_done_writing(inode, LLIF_DONE_WRITING);
if (rc == 0) {
rc = ll_objects_destroy(req, inode);
memcpy(&och->och_fh, &body->handle, sizeof(body->handle));
och->och_magic = OBD_CLIENT_HANDLE_MAGIC;
och->och_fid = &lli->lli_fid;
+ och->och_flags = it->it_flags;
lli->lli_ioepoch = body->ioepoch;
return md_set_open_replay_data(md_exp, och, req);
/* Queue DONE_WRITING if
* - done writing is allowed;
* - inode has no no dirty pages; */
-void ll_queue_done_writing(struct inode *inode)
+void ll_queue_done_writing(struct inode *inode, unsigned long flags)
{
struct ll_inode_info *lli = ll_i2info(inode);
spin_lock(&lli->lli_lock);
+ lli->lli_flags |= flags;
+
if ((lli->lli_flags & LLIF_DONE_WRITING) &&
list_empty(&lli->lli_pending_write_llaps)) {
struct ll_close_queue *lcq = ll_i2sbi(inode)->ll_lcq;
spin_unlock(&lli->lli_lock);
}
-/* CLOSE has already occured but has not closed epoch;
- * Let let DONE_WRITING to happen. */
-void ll_init_done_writing(struct inode *inode) {
- struct ll_inode_info *lli = ll_i2info(inode);
- spin_lock(&lli->lli_lock);
- if ((lli->lli_flags & LLIF_EPOCH_PENDING))
- lli->lli_flags |= LLIF_DONE_WRITING;
- spin_unlock(&lli->lli_lock);
- ll_queue_done_writing(inode);
-}
-
/* Close epoch and send Size-on-MDS attribute update if possible.
* Call this under @lli->lli_lock spinlock. */
-void ll_epoch_close(struct inode *inode, struct md_op_data *op_data)
+void ll_epoch_close(struct inode *inode, struct md_op_data *op_data,
+ struct obd_client_handle **och, unsigned long flags)
{
struct ll_inode_info *lli = ll_i2info(inode);
ENTRY;
+ spin_lock(&lli->lli_lock);
+ if (!(list_empty(&lli->lli_pending_write_llaps)) &&
+ !(lli->lli_flags & LLIF_EPOCH_PENDING)) {
+ LASSERT(*och != NULL);
+ LASSERT(lli->lli_pending_och == NULL);
+ /* Inode is dirty and there is no pending write done request
+ * yet, DONE_WRITE is to be sent later. */
+ lli->lli_flags |= LLIF_EPOCH_PENDING;
+ lli->lli_pending_och = *och;
+ spin_unlock(&lli->lli_lock);
+
+ inode = igrab(inode);
+ LASSERT(inode);
+ goto out;
+ }
+
CDEBUG(D_INODE, "Epoch "LPU64" closed on "DFID"\n",
op_data->ioepoch, PFID(&lli->lli_fid));
op_data->flags |= MF_EPOCH_CLOSE;
- /* Pack Size-on-MDS inode attributes only if they has changed */
- if (!(lli->lli_flags & LLIF_SOM_DIRTY))
- goto out;
-
- /* There is already 1 pending DONE_WRITE, do not create another one --
- * close epoch with no attribute change. */
- if (lli->lli_flags & LLIF_EPOCH_PENDING)
- goto out;
+ if (flags & LLIF_DONE_WRITING) {
+ LASSERT(lli->lli_flags & LLIF_SOM_DIRTY);
+ *och = lli->lli_pending_och;
+ lli->lli_pending_och = NULL;
+ lli->lli_flags &= ~(LLIF_DONE_WRITING | LLIF_EPOCH_PENDING |
+ LLIF_EPOCH_PENDING);
+ } else {
+ /* Pack Size-on-MDS inode attributes only if they has changed */
+ if (!(lli->lli_flags & LLIF_SOM_DIRTY)) {
+ spin_unlock(&lli->lli_lock);
+ goto out;
+ }
+
+ /* There is already 1 pending DONE_WRITE, do not create another
+ * one -- close epoch with no attribute change. */
+ if (lli->lli_flags & LLIF_EPOCH_PENDING) {
+ spin_unlock(&lli->lli_lock);
+ goto out;
+ }
+ }
+ spin_unlock(&lli->lli_lock);
op_data->flags |= MF_SOM_CHANGE;
/* Check if Size-on-MDS attributes are valid. */
- if ((lli->lli_flags & LLIF_MDS_SIZE_LOCK) || !ll_local_size(inode)) {
+ LASSERT(!(lli->lli_flags & LLIF_MDS_SIZE_LOCK));
+ if (!ll_local_size(inode)) {
/* Send Size-on-MDS Attributes if valid. */
op_data->attr.ia_valid |= ATTR_MTIME_SET | ATTR_CTIME_SET |
ATTR_SIZE | ATTR_BLOCKS;
/* Send a DONE_WRITING rpc, pack Size-on-MDS attributes into it, if possible */
static void ll_done_writing(struct inode *inode)
{
- struct ll_inode_info *lli = ll_i2info(inode);
+ struct obd_client_handle *och = NULL;
struct md_op_data *op_data;
- struct obd_client_handle *och;
int rc;
ENTRY;
return;
}
- spin_lock(&lli->lli_lock);
- LASSERT(lli->lli_flags & LLIF_SOM_DIRTY);
-
- och = lli->lli_pending_och;
- lli->lli_pending_och = NULL;
- lli->lli_flags &= ~(LLIF_DONE_WRITING | LLIF_EPOCH_PENDING);
- ll_epoch_close(inode, op_data);
- lli->lli_flags &= ~LLIF_SOM_DIRTY;
- spin_unlock(&lli->lli_lock);
-
+ ll_epoch_close(inode, op_data, &och, LLIF_DONE_WRITING);
ll_pack_inode2opdata(inode, op_data, &och->och_fh);
rc = md_done_writing(ll_i2sbi(inode)->ll_md_exp, op_data, och);
int ll_md_close(struct obd_export *md_exp, struct inode *inode,
struct file *file);
int ll_md_real_close(struct inode *inode, int flags);
-void ll_epoch_close(struct inode *inode, struct md_op_data *op_data);
+void ll_epoch_close(struct inode *inode, struct md_op_data *op_data,
+ struct obd_client_handle **och, unsigned long flags);
int ll_sizeonmds_update(struct inode *inode, struct lustre_handle *fh);
int ll_inode_getattr(struct inode *inode, struct obdo *obdo);
int ll_md_setattr(struct inode *inode, struct md_op_data *op_data);
void llap_write_pending(struct inode *inode, struct ll_async_page *llap);
int llap_write_complete(struct inode *inode, struct ll_async_page *llap);
-int ll_inode_dirty(struct inode *inode);
-void ll_queue_done_writing(struct inode *inode);
-void ll_init_done_writing(struct inode *inode);
+int ll_inode_dirty(struct inode *inode, unsigned long flags);
+void ll_queue_done_writing(struct inode *inode, unsigned long flags);
void ll_close_thread_shutdown(struct ll_close_queue *lcq);
int ll_close_thread_start(struct ll_close_queue **lcq_ret);
if (!S_ISREG(inode->i_mode))
RETURN(0);
- /* XXX: pass och here for the recovery purpose. */
CDEBUG(D_INODE, "Epoch "LPU64" closed on "DFID" for truncate\n",
op_data->ioepoch, PFID(&lli->lli_fid));
op_data->flags = MF_EPOCH_CLOSE | MF_SOM_CHANGE;
+ /* XXX: pass och here for the recovery purpose. */
rc = md_done_writing(ll_i2sbi(inode)->ll_md_exp, op_data, NULL);
if (rc == -EAGAIN) {
/* MDS has instructed us to obtain Size-on-MDS attribute
if (cmd & OBD_BRW_WRITE) {
if (llap_write_complete(page->mapping->host, llap))
- ll_queue_done_writing(page->mapping->host);
+ ll_queue_done_writing(page->mapping->host, 0);
}
if (PageWriteback(page)) {
}
if (llap_write_complete(inode, llap))
- ll_queue_done_writing(inode);
+ ll_queue_done_writing(inode, 0);
rc = obd_teardown_async_page(exp, ll_i2info(inode)->lli_smd, NULL,
llap->llap_cookie);