diff -urN ocfs2.1226/src/dlm.c ocfs2/src/dlm.c --- ocfs2.1226/src/dlm.c 2004-06-30 16:53:48.000000000 +0800 +++ ocfs2/src/dlm.c 2004-06-30 16:47:27.332114776 +0800 @@ -731,6 +731,53 @@ return status; } /* ocfs_update_master_on_open */ +/* + * ocfs_notify_truncate_on_wopen() + * inode is definitely non NULL + */ +int ocfs_notify_truncate_on_wopen (ocfs_super * osb, struct inode *inode, unsigned int mode) +{ + int status = -EAGAIN; + int disk_vote = 0; + ocfs_lock_res *lockres = GET_INODE_LOCKRES(inode); + + LOG_ENTRY (); + + if(!(mode&(O_WRONLY|O_RDWR))) { + status = 0; + goto bail; + } + + while (status == -EAGAIN) { + ocfs_acquire_lockres(lockres, 0); // ocfs_file_open + + status = new_lock_function(osb, lockres->lock_type, + FLAG_TRUNCATE_PAGES, NULL, &disk_vote, inode); + if (status < 0) { + if (status != -EAGAIN) + LOG_ERROR_STATUS (status); + ocfs_release_lockres (lockres); // ocfs_file_open ocfs_symlink + if (status == -EAGAIN) { + ocfs_sleep (500); + if (ocfs_task_interruptible (osb)) { + LOG_TRACE_ARGS("interrupted... lockid=%llu\n", + OCFS_I(inode)->ip_blkno << inode->i_sb->s_blocksize_bits); + status = -EINTR; + goto bail; + } + continue; + } + + goto bail; + } + ocfs_release_lockres (lockres); // ocfs_file_open + } + +bail: + LOG_EXIT_STATUS (status); + return status; +} /* ocfs_notify_truncate_on_wopen */ + enum { invalid_path = 0, fast_path, @@ -1277,7 +1324,8 @@ /* on a master change... */ need_to_zap_buffers = 1; /* need to dump local buffers */ need_lock_write = 1; /* and rewrite the lock */ - } else if (flags & (FLAG_ADD_OIN_MAP | FLAG_DROP_READONLY)) { + } else if (flags & (FLAG_ADD_OIN_MAP | FLAG_DROP_READONLY | + FLAG_TRUNCATE_PAGES)) { need_lock_write = 0; need_to_zap_buffers = 0; } else if (flags & (FLAG_READDIR | FLAG_FILE_RELEASE_CACHE)) { @@ -1305,7 +1353,7 @@ /* figure out who to vote with */ if (flags & (FLAG_REMASTER | FLAG_FILE_DELETE | FLAG_FILE_RENAME | FLAG_DROP_READONLY | - FLAG_RELEASE_DENTRY)) { + FLAG_RELEASE_DENTRY | FLAG_TRUNCATE_PAGES)) { ocfs_node_map_dup(osb, &vote_map, &osb->publ_map); /* broadcast */ /* only nodes that see this is readonly */ if (flags & FLAG_DROP_READONLY) @@ -1373,6 +1421,10 @@ if (flags & FLAG_ADD_OIN_MAP) goto bail; + /* just alerting owner on open */ + if (flags & FLAG_TRUNCATE_PAGES) + goto bail; + /* drop readonly should remove anyone who has responded */ if (flags & FLAG_DROP_READONLY) { ocfs_node_map_set(&lockres->readonly_map, &vote_map); diff -urN ocfs2.1226/src/dlm.h ocfs2/src/dlm.h --- ocfs2.1226/src/dlm.h 2004-06-30 16:53:48.000000000 +0800 +++ ocfs2/src/dlm.h 2004-06-30 16:28:42.663090456 +0800 @@ -47,6 +47,8 @@ ocfs_journal_handle *handle); int ocfs_update_master_on_open(ocfs_super *osb, struct inode *inode, ocfs_journal_handle *handle); +int ocfs_notify_truncate_on_wopen(ocfs_super *osb, struct inode *inode, + unsigned int mode); int ocfs_wait_for_lock_release(ocfs_super *osb, __u64 offset, __u32 time_to_wait, __u32 lock_type, struct inode *inode); diff -urN ocfs2.1226/src/file.c ocfs2/src/file.c --- ocfs2.1226/src/file.c 2004-06-30 16:53:48.000000000 +0800 +++ ocfs2/src/file.c 2004-06-30 16:32:07.574939120 +0800 @@ -241,14 +241,19 @@ goto leave; } - status = ocfs_inode_fill_ext_map (osb, fe_bh, inode); - if (status < 0) { - up_write(&OCFS_I(inode)->ip_io_sem); - LOG_ERROR_STATUS(status); - goto leave; + if(OCFS_I(inode)->ip_ext_map.initialized && + OCFS_I(inode)->ip_ext_map.count == 0) { + status = ocfs_inode_fill_ext_map (osb, fe_bh, inode); + if (status < 0) { + up_write(&OCFS_I(inode)->ip_io_sem); + LOG_ERROR_STATUS(status); + goto leave; + } } } + ocfs_notify_truncate_on_wopen(osb, inode, mode); + up_write(&OCFS_I(inode)->ip_io_sem); /* yes, hold onto ip_sem. */ @@ -277,13 +282,10 @@ } status = 0; } else { - ocfs_extent_map_destroy (&OCFS_I(inode)->ip_ext_map); - ocfs_extent_map_init (&OCFS_I(inode)->ip_ext_map); if (mode & O_DIRECT) OCFS_SET_FLAG(OCFS_I(inode)->ip_open_flags, OCFS_OIN_OPEN_FOR_DIRECTIO); else { OCFS_CLEAR_FLAG(OCFS_I(inode)->ip_open_flags, OCFS_OIN_OPEN_FOR_DIRECTIO); - truncate_pages = 1; } } @@ -294,17 +296,7 @@ have_oin_sem = 0; } - if (truncate_pages) { - status = ocfs_sync_inode(inode); - if (status) - goto leave; - - if (inode->i_data.nrpages) - ocfs_truncate_inode_pages(inode, 0); - } - - - status = 0; + status = ocfs_sync_inode(inode); leave: if (have_oin_sem) { @@ -374,9 +366,6 @@ atomic_read(&dentry->d_count)); if (last_close) { - ocfs_extent_map_destroy (&OCFS_I(inode)->ip_ext_map); - ocfs_extent_map_init (&OCFS_I(inode)->ip_ext_map); - if (OCFS_I(inode)->ip_open_flags & OCFS_OIN_OPEN_FOR_DIRECTIO) OCFS_CLEAR_FLAG(OCFS_I(inode)->ip_open_flags, OCFS_OIN_OPEN_FOR_DIRECTIO); @@ -402,11 +391,6 @@ up (&(OCFS_I(inode)->ip_sem)); ocfs_sync_inode(inode); - if (last_close) { - if (inode->i_data.nrpages) - ocfs_truncate_inode_pages(inode, 0); - } - bail: if (dec) iput(inode); @@ -1487,12 +1471,14 @@ goto bail; } } - if (needs_trunc) + if (needs_trunc) ocfs_truncate_inode_pages(inode, 0); - if (inode->i_size > newsize) + if (inode->i_size > newsize) { + ocfs_truncate_inode_pages(inode, newsize); status = ocfs_truncate_file(osb, newsize, inode); + } else { status = ocfs_extend_file(osb, newsize, NULL, inode, attr, 0, NULL); diff -urN ocfs2.1226/src/inode.c ocfs2/src/inode.c --- ocfs2.1226/src/inode.c 2004-06-30 16:53:48.000000000 +0800 +++ ocfs2/src/inode.c 2004-06-30 16:44:44.800823288 +0800 @@ -120,6 +120,22 @@ #endif }; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +/* + * ocfs_ilookup() + * blkno is *required* + */ +struct inode *ocfs_ilookup(ocfs_super *osb, u64 blkno) +{ + ocfs_find_inode_args args; + + args.blkno = blkno; + args.flags = 0; + args.ino = ino_from_blkno(osb->sb, blkno); + return ilookup5(osb->sb, args.ino, ocfs_find_actor, &args); +} +#endif + /* * ocfs_iget() * blkno is *required* @@ -148,6 +164,15 @@ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) inode = iget5_locked (sb, args.ino, ocfs_find_actor, ocfs_init_locked_inode, &args); + /* inode was *not* in the inode cache. 2.6.x requires + * us to do our own read_inode call and unlock it + * afterwards. */ + if (inode && inode->i_state & I_NEW) { + LOG_TRACE_STR("Inode was not in inode cache, reading " + "it."); + ocfs_read_locked_inode(inode, &args); + unlock_new_inode(inode); + } #else inode = iget4 (sb, args.ino, ocfs_find_inode, &args); #endif @@ -167,22 +192,6 @@ if (inode) { LOG_TRACE_ARGS("returning inode with number %llu\n", OCFS_I(inode)->ip_blkno); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - /* inode was *not* in the inode cache. 2.6.x requires - * us to do our own read_inode call and unlock it - * afterwards. */ - if (inode->i_state & I_NEW) { - LOG_TRACE_STR("Inode was not in inode cache, reading " - "it."); - if (ocfs_read_locked_inode(inode, &args) < 0) { - LOG_ERROR_ARGS("bad inode: i_ino=%lu\n", inode->i_ino); - make_bad_inode(inode); - iput(inode); - inode = NULL; - } else - unlock_new_inode(inode); - } -#endif } LOG_EXIT_PTR(inode); @@ -494,6 +503,11 @@ } fe = (ocfs2_dinode *) bh->b_data; + if(!IS_VALID_FILE_ENTRY(fe)) { + make_bad_inode (inode); + goto bail; + } + sysfile = le32_to_cpu(fe->i_flags) & OCFS2_SYSTEM_FL; if (S_ISCHR(fe->i_mode) || S_ISBLK(fe->i_mode)) inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev)); diff -urN ocfs2.1226/src/inode.h ocfs2/src/inode.h --- ocfs2.1226/src/inode.h 2004-06-30 16:53:48.000000000 +0800 +++ ocfs2/src/inode.h 2004-06-30 16:28:42.670089392 +0800 @@ -35,6 +35,9 @@ void ocfs_clear_inode(struct inode *inode); void ocfs_delete_inode(struct inode *inode); struct inode *ocfs_iget(ocfs_super *osb, __u64 feoff); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +struct inode *ocfs_ilookup(ocfs_super *osb, __u64 feoff); +#endif int ocfs_inode_init_private(struct inode *inode); int ocfs_inode_revalidate(struct dentry *dentry); int ocfs_populate_inode(struct inode *inode, ocfs2_dinode *fe, Binary files ocfs2.1226/src/.namei.c.swp and ocfs2/src/.namei.c.swp differ diff -urN ocfs2.1226/src/nm.c ocfs2/src/nm.c --- ocfs2.1226/src/nm.c 2004-06-30 16:53:48.000000000 +0800 +++ ocfs2/src/nm.c 2004-07-01 09:22:02.801064544 +0800 @@ -47,6 +47,7 @@ #include "util.h" #include "volcfg.h" #include "vote.h" +#include "extmap.h" #include "ocfs_journal.h" #include "buffer_head_io.h" @@ -93,7 +94,8 @@ "REMASTER_REQUESTOR", // remaster lock to requestor "DROP_READONLY", // RO cachelock needs to convert to RW "READONLY", - "RELEASE_DENTRY" + "RELEASE_DENTRY", + "TRUNCATE_PAGES" }; #endif @@ -517,6 +519,8 @@ vote_type = RELEASE_CACHE; else if (flags & FLAG_FILE_UPDATE_OIN) { vote_type = UPDATE_OIN_INODE; + } else if (flags & FLAG_TRUNCATE_PAGES) { + vote_type = TRUNCATE_PAGES; } else if (lockres->master_node_num == osb->node_num) { if (flags & FLAG_CHANGE_MASTER) vote_type = CHANGE_MASTER; @@ -535,7 +539,8 @@ vote_type = REMASTER_REQUESTOR; } - if (inode == NULL && vote_type != DELETE_RELEASE) + if (inode == NULL && + (vote_type != DELETE_RELEASE && vote_type != TRUNCATE_PAGES)) vote_type = INVALID_REQUEST; done: LOG_EXIT_STATUS(vote_type); @@ -759,8 +764,22 @@ if ((flags & FLAG_FILE_DELETE) && (flags & FLAG_RELEASE_LOCK)) inode = NULL; else { - inode = ocfs_iget(osb, - lock_id >> osb->sb->s_blocksize_bits); + if(flags & FLAG_TRUNCATE_PAGES) { + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + inode = ocfs_ilookup(osb, + lock_id >> osb->sb->s_blocksize_bits); + #else + inode = ocfs_iget(osb, + lock_id >> osb->sb->s_blocksize_bits); + #endif + if(!inode) + goto truncate_page_out; + } + else { + inode = ocfs_iget(osb, + lock_id >> osb->sb->s_blocksize_bits); + } + if (!inode) { status = -EFAIL; LOG_ERROR_ARGS("Could not find inode: lock_id = %llu, " @@ -799,6 +818,7 @@ lockflags = (OCFS_I(inode)->ip_flags & OCFS_INODE_SYSTEM_FILE) ? 0 : OCFS_BH_CACHED; +truncate_page_out: /* fail here if no inode, unless this is a delete/rename release */ vote_type = get_process_vote_action(osb, lockres, node_num, flags, status, &master_alive, inode); @@ -1193,6 +1213,16 @@ open_handle = 1; break; + case TRUNCATE_PAGES: + LOG_TRACE_STR("TRUNCATE_PAGES"); + if(inode) { + ocfs_truncate_inode_pages(inode, 0); + ocfs_extent_map_destroy(&OCFS_I(inode)->ip_ext_map); + ocfs_extent_map_init(&OCFS_I(inode)->ip_ext_map); + } + vote_response = FLAG_VOTE_NODE; + break; + case INVALID_REQUEST: default: LOG_TRACE_STR("INVALID_REQUEST"); @@ -1200,7 +1230,8 @@ break; } - up_write(&OCFS_I(inode)->ip_io_sem); + if(inode) + up_write(&OCFS_I(inode)->ip_io_sem); have_io_sem = 0; if (inode && (flags & (FLAG_FILE_EXTEND|FLAG_FILE_TRUNCATE)) && diff -urN ocfs2.1226/src/ocfs.h ocfs2/src/ocfs.h --- ocfs2.1226/src/ocfs.h 2004-06-30 16:53:48.000000000 +0800 +++ ocfs2/src/ocfs.h 2004-06-30 16:28:42.674088784 +0800 @@ -89,7 +89,8 @@ REMASTER_REQUESTOR, // remaster lock to requestor DROP_READONLY, // RO cachelock needs to convert to RW READONLY, // a RW or RO cachelock, requesting RO - RELEASE_DENTRY + RELEASE_DENTRY, + TRUNCATE_PAGES // truncate page caches of a file }; #define OCFS_MAX_DLM_PKT_SIZE 256 @@ -135,7 +136,7 @@ #define FLAG_DIR 0x00001000 #define FLAG_REMASTER 0x00002000 #define FLAG_FAST_PATH_LOCK 0x00004000 -#define FLAG_FILE_UNUSED5 0x00008000 +#define FLAG_TRUNCATE_PAGES 0x00008000 #define FLAG_FILE_UNUSED6 0x00010000 //#define FLAG_DEL_NAME 0x00020000 //#define FLAG_DEL_INODE 0x00040000 Binary files ocfs2.1226/src/.ocfs.h.swp and ocfs2/src/.ocfs.h.swp differ