.cld_mode = CLM_READ
};
+/*
+ * 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)
{
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");
+ }
}
RETURN(result);
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);
RETURN(0);
}
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;
+ }
}
disk_update:
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);