summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
fc4b46d)
Writing client may not report accurate allocated block numbers when
dirty pages has not been writting back to OSTs, some "cp" or "tar" may
skip the file because it thinks it is completely sparse.
This patch makes writing client consider dirty pages when reporting
allocated blocks, lest the file be treated as a completely sparse one.
Signed-off-by: Bobi Jam <bobijam@whamcloud.com>
Change-Id: I985d50a44ea1e917bf8e1cba3b5cb770eec35c3f
Reviewed-on: http://review.whamcloud.com/1647
Tested-by: Hudson
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
#ifndef LCLIENT_H
#define LCLIENT_H
#ifndef LCLIENT_H
#define LCLIENT_H
+blkcnt_t dirty_cnt(struct inode *inode);
+
int cl_glimpse_size(struct inode *inode);
int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io,
struct inode *inode, struct cl_object *clob);
int cl_glimpse_size(struct inode *inode);
int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io,
struct inode *inode, struct cl_object *clob);
+/*
+ * Check whether file has possible unwriten pages.
+ *
+ * \retval 1 file is mmap-ed or has dirty pages
+ * 0 otherwise
+ */
+blkcnt_t dirty_cnt(struct inode *inode)
+{
+ blkcnt_t cnt = 0;
+#ifdef __KERNEL__
+ struct ccc_object *vob = cl_inode2ccc(inode);
+ void *results[1];
+
+ if (inode->i_mapping != NULL)
+ cnt += radix_tree_gang_lookup_tag(&inode->i_mapping->page_tree,
+ results, 0, 1,
+ PAGECACHE_TAG_DIRTY);
+ if (cnt == 0 && cfs_atomic_read(&vob->cob_mmap_cnt) > 0)
+ cnt = 1;
+
+#endif
+ return (cnt > 0) ? 1 : 0;
+}
+
int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io,
struct inode *inode, struct cl_object *clob)
{
int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io,
struct inode *inode, struct cl_object *clob)
{
lock = cl_lock_request(env, io, descr, "glimpse",
cfs_current());
cio->cui_glimpse = 0;
lock = cl_lock_request(env, io, descr, "glimpse",
cfs_current());
cio->cui_glimpse = 0;
- if (!IS_ERR(lock)) {
- result = cl_wait(env, lock);
- if (result == 0) {
- cl_merge_lvb(inode);
- cl_unuse(env, lock);
+
+ if (IS_ERR(lock))
+ RETURN(PTR_ERR(lock));
+
+ result = cl_wait(env, lock);
+ if (result == 0) {
+ cl_merge_lvb(inode);
+ if (cl_isize_read(inode) > 0 &&
+ inode->i_blocks == 0) {
+ /*
+ * LU-417: Add dirty pages block count
+ * lest i_blocks reports 0, some "cp" or
+ * "tar" may think it's a completely
+ * sparse file and skip it.
+ */
+ inode->i_blocks = dirty_cnt(inode);
- cl_lock_release(env, lock,
- "glimpse", cfs_current());
- } else
- result = PTR_ERR(lock);
- } else
+ cl_unuse(env, lock);
+ }
+ cl_lock_release(env, lock, "glimpse", cfs_current());
+ } else {
CDEBUG(D_DLMTRACE, "No objects for inode\n");
CDEBUG(D_DLMTRACE, "No objects for inode\n");
lvb->lvb_mtime = cl_inode_mtime(inode);
lvb->lvb_atime = cl_inode_atime(inode);
lvb->lvb_ctime = cl_inode_ctime(inode);
lvb->lvb_mtime = cl_inode_mtime(inode);
lvb->lvb_atime = cl_inode_atime(inode);
lvb->lvb_ctime = cl_inode_ctime(inode);
+ /*
+ * LU-417: Add dirty pages block count lest i_blocks reports 0, some
+ * "cp" or "tar" on remote node may think it's a completely sparse file
+ * and skip it.
+ */
+ if (lvb->lvb_size > 0 && lvb->lvb_blocks == 0)
+ lvb->lvb_blocks = dirty_cnt(inode);
lvb->lvb_ctime, new->lvb_ctime);
lvb->lvb_ctime = new->lvb_ctime;
}
lvb->lvb_ctime, new->lvb_ctime);
lvb->lvb_ctime = new->lvb_ctime;
}
+ if (new->lvb_blocks > lvb->lvb_blocks || !increase_only) {
+ CDEBUG(D_DLMTRACE, "res: "LPU64" updating lvb blocks: "
+ LPU64" -> "LPU64"\n", res->lr_name.name[0],
+ lvb->lvb_blocks, new->lvb_blocks);
+ lvb->lvb_blocks = new->lvb_blocks;
+ }
lvb->lvb_ctime, LTIME_S(inode->i_ctime));
lvb->lvb_ctime = LTIME_S(inode->i_ctime);
}
lvb->lvb_ctime, LTIME_S(inode->i_ctime));
lvb->lvb_ctime = LTIME_S(inode->i_ctime);
}
- if (lvb->lvb_blocks != inode->i_blocks) {
+ if (inode->i_blocks > lvb->lvb_blocks || !increase_only) {
CDEBUG(D_DLMTRACE,"res: "LPU64" updating lvb blocks from disk: "
LPU64" -> %llu\n", res->lr_name.name[0],
lvb->lvb_blocks, (unsigned long long)inode->i_blocks);
CDEBUG(D_DLMTRACE,"res: "LPU64" updating lvb blocks from disk: "
LPU64" -> %llu\n", res->lr_name.name[0],
lvb->lvb_blocks, (unsigned long long)inode->i_blocks);