From 9eeff6d09450e1144b6b9dc1bdbc222ac2af9d67 Mon Sep 17 00:00:00 2001 From: Fan Yong Date: Thu, 2 Aug 2012 12:29:25 +0800 Subject: [PATCH] LU-359 llite: no close error if application has known failure Don't return error again when close if the application has known former write failure. Rename the per-inode based 'lli_write_rc' as per file-structure based 'fd_last_write' to track the last write/fsync failure. When 'sys_close()' is called against the 'file' structure, we know whether the caller has already known former write/fsync failure or not, then avoid potenical rdundant error handling, like confused error message. Miss to set 'lli_async_rc' if ll_writepage() failed. Signed-off-by: Fan Yong Change-Id: I62d9cd83fc03fad22c994f2a77774ca113a6c057 Reviewed-on: http://review.whamcloud.com/1497 Tested-by: Hudson Reviewed-by: Niu Yawei Reviewed-by: Jinshan Xiong Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/llite/file.c | 61 +++++++++++++++++++++++++------------------ lustre/llite/llite_internal.h | 31 ++++++++++++---------- lustre/llite/llite_lib.c | 13 +++++---- lustre/llite/rw.c | 34 +++++++++++++++++------- 4 files changed, 82 insertions(+), 57 deletions(-) diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 4f7385c..96379d6 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -52,10 +52,11 @@ struct ll_file_data *ll_file_data_get(void) { - struct ll_file_data *fd; + struct ll_file_data *fd; - OBD_SLAB_ALLOC_PTR_GFP(fd, ll_file_data_slab, CFS_ALLOC_IO); - return fd; + OBD_SLAB_ALLOC_PTR_GFP(fd, ll_file_data_slab, CFS_ALLOC_IO); + fd->fd_write_failed = false; + return fd; } static void ll_file_data_put(struct ll_file_data *fd) @@ -825,11 +826,13 @@ void ll_io_init(struct cl_io *io, const struct file *file, int write) } } -static ssize_t ll_file_io_generic(const struct lu_env *env, - struct vvp_io_args *args, struct file *file, - enum cl_io_type iot, loff_t *ppos, size_t count) +static ssize_t +ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args, + struct file *file, enum cl_io_type iot, + loff_t *ppos, size_t count) { - struct ll_inode_info *lli = ll_i2info(file->f_dentry->d_inode); + struct ll_inode_info *lli = ll_i2info(file->f_dentry->d_inode); + struct ll_file_data *fd = LUSTRE_FPRIVATE(file); struct cl_io *io; ssize_t result; ENTRY; @@ -901,13 +904,13 @@ out: if (result >= 0) { ll_stats_ops_tally(ll_i2sbi(file->f_dentry->d_inode), LPROC_LL_WRITE_BYTES, result); - lli->lli_write_rc = 0; - } else { - lli->lli_write_rc = result; - } - } + fd->fd_write_failed = false; + } else { + fd->fd_write_failed = true; + } + } - return result; + return result; } @@ -1975,24 +1978,25 @@ loff_t ll_file_seek(struct file *file, loff_t offset, int origin) int ll_flush(struct file *file, fl_owner_t id) { - struct inode *inode = file->f_dentry->d_inode; - struct ll_inode_info *lli = ll_i2info(inode); - int rc, err; - - LASSERT(!S_ISDIR(inode->i_mode)); + struct inode *inode = file->f_dentry->d_inode; + struct ll_inode_info *lli = ll_i2info(inode); + struct ll_file_data *fd = LUSTRE_FPRIVATE(file); + int rc, err; - /* the application should know write failure already. */ - if (lli->lli_write_rc) - return 0; + LASSERT(!S_ISDIR(inode->i_mode)); - /* catch async errors that were recorded back when async writeback - * failed for pages in this mapping. */ - rc = lli->lli_async_rc; - lli->lli_async_rc = 0; + /* catch async errors that were recorded back when async writeback + * failed for pages in this mapping. */ + rc = lli->lli_async_rc; + lli->lli_async_rc = 0; err = lov_read_and_clear_async_rc(lli->lli_clob); if (rc == 0) rc = err; + /* The application has been told write failure already. + * Do not report failure again. */ + if (fd->fd_write_failed) + return 0; return rc ? -EIO : 0; } @@ -2096,11 +2100,16 @@ int ll_fsync(struct file *file, struct dentry *dentry, int data) lsm = ccc_inode_lsm_get(inode); if (data && lsm) { + struct ll_file_data *fd = LUSTRE_FPRIVATE(file); + err = cl_sync_file_range(inode, 0, OBD_OBJECT_EOF, CL_FSYNC_ALL); if (rc == 0 && err < 0) rc = err; - lli->lli_write_rc = rc < 0 ? rc : 0; + if (rc < 0) + fd->fd_write_failed = true; + else + fd->fd_write_failed = false; } ccc_inode_lsm_put(inode, lsm); diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index e40a434..359731e 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -225,14 +225,14 @@ struct ll_inode_info { cfs_rw_semaphore_t f_trunc_sem; cfs_mutex_t f_write_mutex; + cfs_rw_semaphore_t f_glimpse_sem; + cfs_time_t f_glimpse_time; + cfs_list_t f_agl_list; + __u64 f_agl_index; + /* for writepage() only to communicate to fsync */ - int f_async_rc; - int f_write_rc; + int f_async_rc; - cfs_rw_semaphore_t f_glimpse_sem; - cfs_time_t f_glimpse_time; - cfs_list_t f_agl_list; - __u64 f_agl_index; /* * whenever a process try to read/write the file, the * jobid of the process will be saved here, and it'll @@ -250,15 +250,14 @@ struct ll_inode_info { #define lli_maxbytes u.f.f_maxbytes #define lli_trunc_sem u.f.f_trunc_sem #define lli_write_mutex u.f.f_write_mutex -#define lli_async_rc u.f.f_async_rc -#define lli_write_rc u.f.f_write_rc -#define lli_glimpse_sem u.f.f_glimpse_sem -#define lli_glimpse_time u.f.f_glimpse_time -#define lli_agl_list u.f.f_agl_list -#define lli_agl_index u.f.f_agl_index -#define lli_jobid u.f.f_jobid +#define lli_glimpse_sem u.f.f_glimpse_sem +#define lli_glimpse_time u.f.f_glimpse_time +#define lli_agl_list u.f.f_agl_list +#define lli_agl_index u.f.f_agl_index +#define lli_async_rc u.f.f_async_rc +#define lli_jobid u.f.f_jobid - } u; + } u; /* XXX: For following frequent used members, although they maybe special * used for non-directory object, it is some time-wasting to check @@ -603,6 +602,10 @@ struct ll_file_data { struct ll_file_dir fd_dir; __u32 fd_flags; struct file *fd_file; + /* Indicate whether need to report failure when close. + * true: failure is known, not report again. + * false: unknown failure, should report. */ + bool fd_write_failed; }; struct lov_stripe_md; diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index a42c6d8..1457303 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -906,13 +906,12 @@ void ll_lli_init(struct ll_inode_info *lli) lli->lli_symlink_name = NULL; cfs_init_rwsem(&lli->lli_trunc_sem); cfs_mutex_init(&lli->lli_write_mutex); - lli->lli_async_rc = 0; - lli->lli_write_rc = 0; - cfs_init_rwsem(&lli->lli_glimpse_sem); - lli->lli_glimpse_time = 0; - CFS_INIT_LIST_HEAD(&lli->lli_agl_list); - lli->lli_agl_index = 0; - } + cfs_init_rwsem(&lli->lli_glimpse_sem); + lli->lli_glimpse_time = 0; + CFS_INIT_LIST_HEAD(&lli->lli_agl_list); + lli->lli_agl_index = 0; + lli->lli_async_rc = 0; + } cfs_mutex_init(&lli->lli_layout_mutex); } diff --git a/lustre/llite/rw.c b/lustre/llite/rw.c index cd91dac..310cf45 100644 --- a/lustre/llite/rw.c +++ b/lustre/llite/rw.c @@ -1159,25 +1159,26 @@ out_unlock: int ll_writepage(struct page *vmpage, struct writeback_control *wbc) { - struct inode *inode = vmpage->mapping->host; + struct inode *inode = vmpage->mapping->host; + struct ll_inode_info *lli = ll_i2info(inode); struct lu_env *env; struct cl_io *io; struct cl_page *page; struct cl_object *clob; struct cl_env_nest nest; - int redirtied = 0; + bool redirtied = false; + bool unlocked = false; int result; ENTRY; LASSERT(PageLocked(vmpage)); LASSERT(!PageWriteback(vmpage)); - if (ll_i2dtexp(inode) == NULL) - RETURN(-EINVAL); + LASSERT(ll_i2dtexp(inode) != NULL); - env = cl_env_nested_get(&nest); - if (IS_ERR(env)) - RETURN(PTR_ERR(env)); + env = cl_env_nested_get(&nest); + if (IS_ERR(env)) + GOTO(out, result = PTR_ERR(env)); clob = ll_i2info(inode)->lli_clob; LASSERT(clob != NULL); @@ -1203,14 +1204,17 @@ int ll_writepage(struct page *vmpage, struct writeback_control *wbc) if (!PageError(vmpage)) { redirty_page_for_writepage(wbc, vmpage); result = 0; - redirtied = 1; + redirtied = true; } } cl_page_disown(env, io, page); + unlocked = true; lu_ref_del(&page->cp_reference, "writepage", cfs_current()); cl_page_put(env, page); - } + } else { + result = PTR_ERR(page); + } } cl_io_fini(env, io); @@ -1234,7 +1238,17 @@ int ll_writepage(struct page *vmpage, struct writeback_control *wbc) } cl_env_nested_put(&nest, env); - RETURN(result); + GOTO(out, result); + +out: + if (result < 0) { + if (!lli->lli_async_rc) + lli->lli_async_rc = result; + SetPageError(vmpage); + if (!unlocked) + unlock_page(vmpage); + } + return result; } int ll_writepages(struct address_space *mapping, struct writeback_control *wbc) -- 1.8.3.1