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

Commit 597b027f authored by Jeff Layton's avatar Jeff Layton
Browse files

cifs: call cifs_update_eof with i_lock held



cifs_update_eof has the potential to be racy if multiple threads are
trying to modify it at the same time. Protect modifications of the
server_eof value with the inode->i_lock.

Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
parent e9492871
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -626,7 +626,7 @@ struct cifsInodeInfo {
	bool delete_pending;		/* DELETE_ON_CLOSE is set */
	bool delete_pending;		/* DELETE_ON_CLOSE is set */
	bool invalid_mapping;		/* pagecache is invalid */
	bool invalid_mapping;		/* pagecache is invalid */
	unsigned long time;		/* jiffies of last update of inode */
	unsigned long time;		/* jiffies of last update of inode */
	u64  server_eof;		/* current file size on server */
	u64  server_eof;		/* current file size on server -- protected by i_lock */
	u64  uniqueid;			/* server inode number */
	u64  uniqueid;			/* server inode number */
	u64  createtime;		/* creation time on server */
	u64  createtime;		/* creation time on server */
#ifdef CONFIG_CIFS_FSCACHE
#ifdef CONFIG_CIFS_FSCACHE
+2 −0
Original line number Original line Diff line number Diff line
@@ -2044,7 +2044,9 @@ cifs_writev_complete(struct work_struct *work)
	int i = 0;
	int i = 0;


	if (wdata->result == 0) {
	if (wdata->result == 0) {
		spin_lock(&inode->i_lock);
		cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
		cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
		spin_unlock(&inode->i_lock);
		cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
		cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
					 wdata->bytes);
					 wdata->bytes);
	} else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
	} else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
+8 −1
Original line number Original line Diff line number Diff line
@@ -1399,7 +1399,10 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
	return rc;
	return rc;
}
}


/* update the file size (if needed) after a write */
/*
 * update the file size (if needed) after a write. Should be called with
 * the inode->i_lock held
 */
void
void
cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
		      unsigned int bytes_written)
		      unsigned int bytes_written)
@@ -1471,7 +1474,9 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid,
				return rc;
				return rc;
			}
			}
		} else {
		} else {
			spin_lock(&dentry->d_inode->i_lock);
			cifs_update_eof(cifsi, *poffset, bytes_written);
			cifs_update_eof(cifsi, *poffset, bytes_written);
			spin_unlock(&dentry->d_inode->i_lock);
			*poffset += bytes_written;
			*poffset += bytes_written;
		}
		}
	}
	}
@@ -2197,7 +2202,9 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
		if (written) {
		if (written) {
			len -= written;
			len -= written;
			total_written += written;
			total_written += written;
			spin_lock(&inode->i_lock);
			cifs_update_eof(CIFS_I(inode), *poffset, written);
			cifs_update_eof(CIFS_I(inode), *poffset, written);
			spin_unlock(&inode->i_lock);
			*poffset += written;
			*poffset += written;
		} else if (rc < 0) {
		} else if (rc < 0) {
			if (!total_written)
			if (!total_written)