Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 592282cf authored by Mark Fasheh's avatar Mark Fasheh
Browse files

ocfs2: Directory c/mtime update fixes



ocfs2 wasn't updating c/mtime on directories during dirent
creation/deletion. Fix ocfs2_unlink(), ocfs2_rename() and
__ocfs2_add_entry() by adding the proper code to update the struct inode and
push the change out to disk.

This helps rename/unlink on nfs exported file systems in particular as those
clients compare directory time values to avoid a full re-reading a directory
which hasn't changed.

ocfs2_rename() loses some superfluous error handling as a result of this
patch.

Signed-off-by: default avatarMark Fasheh <mark.fasheh@oracle.com>
parent 72bce507
Loading
Loading
Loading
Loading
+37 −32
Original line number Diff line number Diff line
@@ -932,15 +932,16 @@ static int ocfs2_unlink(struct inode *dir,
		goto leave;
	}

	if (S_ISDIR(inode->i_mode)) {
	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
	if (S_ISDIR(inode->i_mode))
		drop_nlink(dir);
		status = ocfs2_mark_inode_dirty(handle, dir,
						parent_node_bh);

	status = ocfs2_mark_inode_dirty(handle, dir, parent_node_bh);
	if (status < 0) {
		mlog_errno(status);
		if (S_ISDIR(inode->i_mode))
			inc_nlink(dir);
	}
	}

leave:
	if (handle)
@@ -1068,6 +1069,7 @@ static int ocfs2_rename(struct inode *old_dir,
	char orphan_name[OCFS2_ORPHAN_NAMELEN + 1];
	struct buffer_head *orphan_entry_bh = NULL;
	struct buffer_head *newfe_bh = NULL;
	struct buffer_head *old_inode_bh = NULL;
	struct buffer_head *insert_entry_bh = NULL;
	struct ocfs2_super *osb = NULL;
	u64 newfe_blkno;
@@ -1079,7 +1081,7 @@ static int ocfs2_rename(struct inode *old_dir,
	struct buffer_head *new_de_bh = NULL, *old_de_bh = NULL; // bhs for above
	struct buffer_head *old_inode_de_bh = NULL; // if old_dentry is a dir,
						    // this is the 1st dirent bh
	nlink_t old_dir_nlink = old_dir->i_nlink, new_dir_nlink = new_dir->i_nlink;
	nlink_t old_dir_nlink = old_dir->i_nlink;

	/* At some point it might be nice to break this function up a
	 * bit. */
@@ -1139,12 +1141,11 @@ static int ocfs2_rename(struct inode *old_dir,
	}

	/*
	 * Though we don't require an inode meta data update if
	 * old_inode is not a directory, we lock anyway here to ensure
	 * the vote thread on other nodes won't have to concurrently
	 * downconvert the inode and the dentry locks.
	 * Aside from allowing a meta data update, the locking here
	 * also ensures that the vote thread on other nodes won't have
	 * to concurrently downconvert the inode and the dentry locks.
	 */
	status = ocfs2_meta_lock(old_inode, NULL, 1);
	status = ocfs2_meta_lock(old_inode, &old_inode_bh, 1);
	if (status < 0) {
		if (status != -ENOENT)
			mlog_errno(status);
@@ -1355,6 +1356,7 @@ static int ocfs2_rename(struct inode *old_dir,

	old_inode->i_ctime = CURRENT_TIME;
	mark_inode_dirty(old_inode);
	ocfs2_mark_inode_dirty(handle, old_inode, old_inode_bh);

	/* now that the name has been added to new_dir, remove the old name */
	status = ocfs2_delete_entry(handle, old_dir, old_de, old_de_bh);
@@ -1384,26 +1386,21 @@ static int ocfs2_rename(struct inode *old_dir,
		}
	}
	mark_inode_dirty(old_dir);
	if (new_inode)
	ocfs2_mark_inode_dirty(handle, old_dir, old_dir_bh);
	if (new_inode) {
		mark_inode_dirty(new_inode);

	if (old_dir != new_dir)
		if (new_dir_nlink != new_dir->i_nlink) {
			if (!new_dir_bh) {
				mlog(ML_ERROR, "need to change nlink for new "
				     "dir %llu from %d to %d but bh is NULL\n",
				     (unsigned long long)OCFS2_I(new_dir)->ip_blkno,
				     (int)new_dir_nlink, new_dir->i_nlink);
			} else {
				struct ocfs2_dinode *fe;
				status = ocfs2_journal_access(handle,
							      new_dir,
							      new_dir_bh,
							      OCFS2_JOURNAL_ACCESS_WRITE);
				fe = (struct ocfs2_dinode *) new_dir_bh->b_data;
				fe->i_links_count = cpu_to_le16(new_dir->i_nlink);
				status = ocfs2_journal_dirty(handle, new_dir_bh);
		ocfs2_mark_inode_dirty(handle, new_inode, newfe_bh);
	}

	if (old_dir != new_dir) {
		/* Keep the same times on both directories.*/
		new_dir->i_ctime = new_dir->i_mtime = old_dir->i_ctime;

		/*
		 * This will also pick up the i_nlink change from the
		 * block above.
		 */
		ocfs2_mark_inode_dirty(handle, new_dir, new_dir_bh);
	}

	if (old_dir_nlink != old_dir->i_nlink) {
@@ -1455,6 +1452,8 @@ bail:
		iput(new_inode);
	if (newfe_bh)
		brelse(newfe_bh);
	if (old_inode_bh)
		brelse(old_inode_bh);
	if (old_dir_bh)
		brelse(old_dir_bh);
	if (new_dir_bh)
@@ -1826,6 +1825,13 @@ static int __ocfs2_add_entry(handle_t *handle,
		     (le16_to_cpu(de->rec_len) >= rec_len)) ||
		    (le16_to_cpu(de->rec_len) >=
		     (OCFS2_DIR_REC_LEN(de->name_len) + rec_len))) {
			dir->i_mtime = dir->i_ctime = CURRENT_TIME;
			retval = ocfs2_mark_inode_dirty(handle, dir, parent_fe_bh);
			if (retval < 0) {
				mlog_errno(retval);
				goto bail;
			}

			status = ocfs2_journal_access(handle, dir, insert_bh,
						      OCFS2_JOURNAL_ACCESS_WRITE);
			/* By now the buffer is marked for journaling */
@@ -1848,7 +1854,6 @@ static int __ocfs2_add_entry(handle_t *handle,
			de->name_len = namelen;
			memcpy(de->name, name, namelen);

			dir->i_mtime = dir->i_ctime = CURRENT_TIME;
			dir->i_version++;
			status = ocfs2_journal_dirty(handle, insert_bh);
			retval = 0;