Commit 2f99c0bc authored by David Howells's avatar David Howells
Browse files

cifs: Remove some code that's no longer used, part 2



Remove some code that was #if'd out with the netfslib conversion.  This is
split into parts for file.c as the diff generator otherwise produces a hard
to read diff for part of it where a big chunk is cut out.

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
cc: Steve French <sfrench@samba.org>
cc: Shyam Prasad N <nspmangalore@gmail.com>
cc: Rohith Surabattula <rohiths.msft@gmail.com>
cc: Jeff Layton <jlayton@kernel.org>
cc: linux-cifs@vger.kernel.org
cc: netfs@lists.linux.dev
cc: linux-fsdevel@vger.kernel.org
cc: linux-mm@kvack.org
parent 742b3443
Loading
Loading
Loading
Loading
+1 −633
Original line number Diff line number Diff line
@@ -2617,639 +2617,6 @@ cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
	return -ENOENT;
}

#if 0 // TODO remove 2773
void
cifs_writedata_release(struct cifs_io_subrequest *wdata)
{
	if (wdata->uncached)
		kref_put(&wdata->ctx->refcount, cifs_aio_ctx_release);
#ifdef CONFIG_CIFS_SMB_DIRECT
	if (wdata->mr) {
		smbd_deregister_mr(wdata->mr);
		wdata->mr = NULL;
	}
#endif

	if (wdata->cfile)
		cifsFileInfo_put(wdata->cfile);

	kfree(wdata);
}

/*
 * Write failed with a retryable error. Resend the write request. It's also
 * possible that the page was redirtied so re-clean the page.
 */
static void
cifs_writev_requeue(struct cifs_io_subrequest *wdata)
{
	int rc = 0;
	struct inode *inode = d_inode(wdata->cfile->dentry);
	struct TCP_Server_Info *server;
	unsigned int rest_len = wdata->subreq.len;
	loff_t fpos = wdata->subreq.start;

	server = tlink_tcon(wdata->cfile->tlink)->ses->server;
	do {
		struct cifs_io_subrequest *wdata2;
		unsigned int wsize, cur_len;

		wsize = server->ops->wp_retry_size(inode);
		if (wsize < rest_len) {
			if (wsize < PAGE_SIZE) {
				rc = -EOPNOTSUPP;
				break;
			}
			cur_len = min(round_down(wsize, PAGE_SIZE), rest_len);
		} else {
			cur_len = rest_len;
		}

		wdata2 = cifs_writedata_alloc(cifs_writev_complete);
		if (!wdata2) {
			rc = -ENOMEM;
			break;
		}

		wdata2->sync_mode = wdata->sync_mode;
		wdata2->subreq.start	= fpos;
		wdata2->subreq.len	= cur_len;
		wdata2->subreq.io_iter = wdata->subreq.io_iter;

		iov_iter_advance(&wdata2->subreq.io_iter, fpos - wdata->subreq.start);
		iov_iter_truncate(&wdata2->subreq.io_iter, wdata2->subreq.len);

		if (iov_iter_is_xarray(&wdata2->subreq.io_iter))
			/* Check for pages having been redirtied and clean
			 * them.  We can do this by walking the xarray.  If
			 * it's not an xarray, then it's a DIO and we shouldn't
			 * be mucking around with the page bits.
			 */
			cifs_undirty_folios(inode, fpos, cur_len);

		rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY,
					    &wdata2->cfile);
		if (!wdata2->cfile) {
			cifs_dbg(VFS, "No writable handle to retry writepages rc=%d\n",
				 rc);
			if (!is_retryable_error(rc))
				rc = -EBADF;
		} else {
			wdata2->pid = wdata2->cfile->pid;
			rc = server->ops->async_writev(wdata2);
		}

		cifs_put_writedata(wdata2);
		if (rc) {
			if (is_retryable_error(rc))
				continue;
			fpos += cur_len;
			rest_len -= cur_len;
			break;
		}

		fpos += cur_len;
		rest_len -= cur_len;
	} while (rest_len > 0);

	/* Clean up remaining pages from the original wdata */
	if (iov_iter_is_xarray(&wdata->subreq.io_iter))
		cifs_pages_write_failed(inode, fpos, rest_len);

	if (rc != 0 && !is_retryable_error(rc))
		mapping_set_error(inode->i_mapping, rc);
	cifs_put_writedata(wdata);
}

void
cifs_writev_complete(struct work_struct *work)
{
	struct cifs_io_subrequest *wdata = container_of(work,
						struct cifs_io_subrequest, work);
	struct inode *inode = d_inode(wdata->cfile->dentry);

	if (wdata->result == 0) {
		spin_lock(&inode->i_lock);
		cifs_update_eof(CIFS_I(inode), wdata->subreq.start, wdata->subreq.len);
		spin_unlock(&inode->i_lock);
		cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
					 wdata->subreq.len);
	} else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
		return cifs_writev_requeue(wdata);

	if (wdata->result == -EAGAIN)
		cifs_pages_write_redirty(inode, wdata->subreq.start, wdata->subreq.len);
	else if (wdata->result < 0)
		cifs_pages_write_failed(inode, wdata->subreq.start, wdata->subreq.len);
	else
		cifs_pages_written_back(inode, wdata->subreq.start, wdata->subreq.len);

	if (wdata->result != -EAGAIN)
		mapping_set_error(inode->i_mapping, wdata->result);
	cifs_put_writedata(wdata);
}

struct cifs_io_subrequest *cifs_writedata_alloc(work_func_t complete)
{
	struct cifs_io_subrequest *wdata;

	wdata = kzalloc(sizeof(*wdata), GFP_NOFS);
	if (wdata != NULL) {
		refcount_set(&wdata->subreq.ref, 1);
		INIT_LIST_HEAD(&wdata->list);
		init_completion(&wdata->done);
		INIT_WORK(&wdata->work, complete);
	}
	return wdata;
}

/*
 * Extend the region to be written back to include subsequent contiguously
 * dirty pages if possible, but don't sleep while doing so.
 */
static void cifs_extend_writeback(struct address_space *mapping,
				  struct xa_state *xas,
				  long *_count,
				  loff_t start,
				  int max_pages,
				  loff_t max_len,
				  size_t *_len)
{
	struct folio_batch batch;
	struct folio *folio;
	unsigned int nr_pages;
	pgoff_t index = (start + *_len) / PAGE_SIZE;
	size_t len;
	bool stop = true;
	unsigned int i;

	folio_batch_init(&batch);

	do {
		/* Firstly, we gather up a batch of contiguous dirty pages
		 * under the RCU read lock - but we can't clear the dirty flags
		 * there if any of those pages are mapped.
		 */
		rcu_read_lock();

		xas_for_each(xas, folio, ULONG_MAX) {
			stop = true;
			if (xas_retry(xas, folio))
				continue;
			if (xa_is_value(folio))
				break;
			if (folio->index != index) {
				xas_reset(xas);
				break;
			}

			if (!folio_try_get_rcu(folio)) {
				xas_reset(xas);
				continue;
			}
			nr_pages = folio_nr_pages(folio);
			if (nr_pages > max_pages) {
				xas_reset(xas);
				break;
			}

			/* Has the page moved or been split? */
			if (unlikely(folio != xas_reload(xas))) {
				folio_put(folio);
				xas_reset(xas);
				break;
			}

			if (!folio_trylock(folio)) {
				folio_put(folio);
				xas_reset(xas);
				break;
			}
			if (!folio_test_dirty(folio) ||
			    folio_test_writeback(folio)) {
				folio_unlock(folio);
				folio_put(folio);
				xas_reset(xas);
				break;
			}

			max_pages -= nr_pages;
			len = folio_size(folio);
			stop = false;

			index += nr_pages;
			*_count -= nr_pages;
			*_len += len;
			if (max_pages <= 0 || *_len >= max_len || *_count <= 0)
				stop = true;

			if (!folio_batch_add(&batch, folio))
				break;
			if (stop)
				break;
		}

		xas_pause(xas);
		rcu_read_unlock();

		/* Now, if we obtained any pages, we can shift them to being
		 * writable and mark them for caching.
		 */
		if (!folio_batch_count(&batch))
			break;

		for (i = 0; i < folio_batch_count(&batch); i++) {
			folio = batch.folios[i];
			/* The folio should be locked, dirty and not undergoing
			 * writeback from the loop above.
			 */
			if (!folio_clear_dirty_for_io(folio))
				WARN_ON(1);
			folio_start_writeback(folio);
			folio_unlock(folio);
		}

		folio_batch_release(&batch);
		cond_resched();
	} while (!stop);
}

/*
 * Write back the locked page and any subsequent non-locked dirty pages.
 */
static ssize_t cifs_write_back_from_locked_folio(struct address_space *mapping,
						 struct writeback_control *wbc,
						 struct xa_state *xas,
						 struct folio *folio,
						 unsigned long long start,
						 unsigned long long end)
{
	struct inode *inode = mapping->host;
	struct TCP_Server_Info *server;
	struct cifs_io_subrequest *wdata;
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
	struct cifs_credits credits_on_stack;
	struct cifs_credits *credits = &credits_on_stack;
	struct cifsFileInfo *cfile = NULL;
	unsigned long long i_size = i_size_read(inode), max_len;
	unsigned int xid;
	size_t wsize;
	size_t len = folio_size(folio);
	long count = wbc->nr_to_write;
	int rc;

	/* The folio should be locked, dirty and not undergoing writeback. */
	if (!folio_clear_dirty_for_io(folio))
		WARN_ON_ONCE(1);
	folio_start_writeback(folio);

	count -= folio_nr_pages(folio);

	xid = get_xid();
	server = cifs_pick_channel(cifs_sb_master_tcon(cifs_sb)->ses);

	rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY, &cfile);
	if (rc) {
		cifs_dbg(VFS, "No writable handle in writepages rc=%d\n", rc);
		goto err_xid;
	}

	rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->wsize,
					   &wsize, credits);
	if (rc != 0)
		goto err_close;

	wdata = cifs_writedata_alloc(cifs_writev_complete);
	if (!wdata) {
		rc = -ENOMEM;
		goto err_uncredit;
	}

	wdata->sync_mode = wbc->sync_mode;
	wdata->subreq.start = folio_pos(folio);
	wdata->pid = cfile->pid;
	wdata->credits = credits_on_stack;
	wdata->cfile = cfile;
	wdata->server = server;
	cfile = NULL;

	/* Find all consecutive lockable dirty pages that have contiguous
	 * written regions, stopping when we find a page that is not
	 * immediately lockable, is not dirty or is missing, or we reach the
	 * end of the range.
	 */
	if (start < i_size) {
		/* Trim the write to the EOF; the extra data is ignored.  Also
		 * put an upper limit on the size of a single storedata op.
		 */
		max_len = wsize;
		max_len = min_t(unsigned long long, max_len, end - start + 1);
		max_len = min_t(unsigned long long, max_len, i_size - start);

		if (len < max_len) {
			int max_pages = INT_MAX;

#ifdef CONFIG_CIFS_SMB_DIRECT
			if (server->smbd_conn)
				max_pages = server->smbd_conn->max_frmr_depth;
#endif
			max_pages -= folio_nr_pages(folio);

			if (max_pages > 0)
				cifs_extend_writeback(mapping, xas, &count, start,
						      max_pages, max_len, &len);
		}
	}
	len = min_t(unsigned long long, len, i_size - start);

	/* We now have a contiguous set of dirty pages, each with writeback
	 * set; the first page is still locked at this point, but all the rest
	 * have been unlocked.
	 */
	folio_unlock(folio);
	wdata->subreq.len = len;

	if (start < i_size) {
		iov_iter_xarray(&wdata->subreq.io_iter, ITER_SOURCE, &mapping->i_pages,
				start, len);

		rc = adjust_credits(wdata->server, &wdata->credits, wdata->subreq.len);
		if (rc)
			goto err_wdata;

		if (wdata->cfile->invalidHandle)
			rc = -EAGAIN;
		else
			rc = wdata->server->ops->async_writev(wdata);
		if (rc >= 0) {
			cifs_put_writedata(wdata);
			goto err_close;
		}
	} else {
		/* The dirty region was entirely beyond the EOF. */
		cifs_pages_written_back(inode, start, len);
		rc = 0;
	}

err_wdata:
	cifs_put_writedata(wdata);
err_uncredit:
	add_credits_and_wake_if(server, credits, 0);
err_close:
	if (cfile)
		cifsFileInfo_put(cfile);
err_xid:
	free_xid(xid);
	if (rc == 0) {
		wbc->nr_to_write = count;
		rc = len;
	} else if (is_retryable_error(rc)) {
		cifs_pages_write_redirty(inode, start, len);
	} else {
		cifs_pages_write_failed(inode, start, len);
		mapping_set_error(mapping, rc);
	}
	/* Indication to update ctime and mtime as close is deferred */
	set_bit(CIFS_INO_MODIFIED_ATTR, &CIFS_I(inode)->flags);
	return rc;
}

/*
 * write a region of pages back to the server
 */
static ssize_t cifs_writepages_begin(struct address_space *mapping,
				     struct writeback_control *wbc,
				     struct xa_state *xas,
				     unsigned long long *_start,
				     unsigned long long end)
{
	struct folio *folio;
	unsigned long long start = *_start;
	ssize_t ret;
	int skips = 0;

search_again:
	/* Find the first dirty page. */
	rcu_read_lock();

	for (;;) {
		folio = xas_find_marked(xas, end / PAGE_SIZE, PAGECACHE_TAG_DIRTY);
		if (xas_retry(xas, folio) || xa_is_value(folio))
			continue;
		if (!folio)
			break;

		if (!folio_try_get_rcu(folio)) {
			xas_reset(xas);
			continue;
		}

		if (unlikely(folio != xas_reload(xas))) {
			folio_put(folio);
			xas_reset(xas);
			continue;
		}

		xas_pause(xas);
		break;
	}
	rcu_read_unlock();
	if (!folio)
		return 0;

	start = folio_pos(folio); /* May regress with THPs */

	/* At this point we hold neither the i_pages lock nor the page lock:
	 * the page may be truncated or invalidated (changing page->mapping to
	 * NULL), or even swizzled back from swapper_space to tmpfs file
	 * mapping
	 */
lock_again:
	if (wbc->sync_mode != WB_SYNC_NONE) {
		ret = folio_lock_killable(folio);
		if (ret < 0)
			return ret;
	} else {
		if (!folio_trylock(folio))
			goto search_again;
	}

	if (folio->mapping != mapping ||
	    !folio_test_dirty(folio)) {
		start += folio_size(folio);
		folio_unlock(folio);
		goto search_again;
	}

	if (folio_test_writeback(folio) ||
	    folio_test_private_2(folio)) { /* [DEPRECATED] */
		folio_unlock(folio);
		if (wbc->sync_mode != WB_SYNC_NONE) {
			folio_wait_writeback(folio);
#ifdef CONFIG_CIFS_FSCACHE
			folio_wait_private_2(folio);
#endif
			goto lock_again;
		}

		start += folio_size(folio);
		if (wbc->sync_mode == WB_SYNC_NONE) {
			if (skips >= 5 || need_resched()) {
				ret = 0;
				goto out;
			}
			skips++;
		}
		goto search_again;
	}

	ret = cifs_write_back_from_locked_folio(mapping, wbc, xas, folio, start, end);
out:
	if (ret > 0)
		*_start = start + ret;
	return ret;
}

/*
 * Write a region of pages back to the server
 */
static int cifs_writepages_region(struct address_space *mapping,
				  struct writeback_control *wbc,
				  unsigned long long *_start,
				  unsigned long long end)
{
	ssize_t ret;

	XA_STATE(xas, &mapping->i_pages, *_start / PAGE_SIZE);

	do {
		ret = cifs_writepages_begin(mapping, wbc, &xas, _start, end);
		if (ret > 0 && wbc->nr_to_write > 0)
			cond_resched();
	} while (ret > 0 && wbc->nr_to_write > 0);

	return ret > 0 ? 0 : ret;
}

/*
 * Write some of the pending data back to the server
 */
static int cifs_writepages(struct address_space *mapping,
			   struct writeback_control *wbc)
{
	loff_t start, end;
	int ret;

	/* We have to be careful as we can end up racing with setattr()
	 * truncating the pagecache since the caller doesn't take a lock here
	 * to prevent it.
	 */

	if (wbc->range_cyclic && mapping->writeback_index) {
		start = mapping->writeback_index * PAGE_SIZE;
		ret = cifs_writepages_region(mapping, wbc, &start, LLONG_MAX);
		if (ret < 0)
			goto out;

		if (wbc->nr_to_write <= 0) {
			mapping->writeback_index = start / PAGE_SIZE;
			goto out;
		}

		start = 0;
		end = mapping->writeback_index * PAGE_SIZE;
		mapping->writeback_index = 0;
		ret = cifs_writepages_region(mapping, wbc, &start, end);
		if (ret == 0)
			mapping->writeback_index = start / PAGE_SIZE;
	} else if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) {
		start = 0;
		ret = cifs_writepages_region(mapping, wbc, &start, LLONG_MAX);
		if (wbc->nr_to_write > 0 && ret == 0)
			mapping->writeback_index = start / PAGE_SIZE;
	} else {
		start = wbc->range_start;
		ret = cifs_writepages_region(mapping, wbc, &start, wbc->range_end);
	}

out:
	return ret;
}

static int cifs_write_end(struct file *file, struct address_space *mapping,
			loff_t pos, unsigned len, unsigned copied,
			struct page *page, void *fsdata)
{
	int rc;
	struct inode *inode = mapping->host;
	struct cifsFileInfo *cfile = file->private_data;
	struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
	struct folio *folio = page_folio(page);
	__u32 pid;

	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
		pid = cfile->pid;
	else
		pid = current->tgid;

	cifs_dbg(FYI, "write_end for page %p from pos %lld with %d bytes\n",
		 page, pos, copied);

	if (folio_test_checked(folio)) {
		if (copied == len)
			folio_mark_uptodate(folio);
		folio_clear_checked(folio);
	} else if (!folio_test_uptodate(folio) && copied == PAGE_SIZE)
		folio_mark_uptodate(folio);

	if (!folio_test_uptodate(folio)) {
		char *page_data;
		unsigned offset = pos & (PAGE_SIZE - 1);
		unsigned int xid;

		xid = get_xid();
		/* this is probably better than directly calling
		   partialpage_write since in this function the file handle is
		   known which we might as well	leverage */
		/* BB check if anything else missing out of ppw
		   such as updating last write time */
		page_data = kmap(page);
		rc = cifs_write(cfile, pid, page_data + offset, copied, &pos);
		/* if (rc < 0) should we set writebehind rc? */
		kunmap(page);

		free_xid(xid);
	} else {
		rc = copied;
		pos += copied;
		set_page_dirty(page);
	}

	if (rc > 0) {
		spin_lock(&inode->i_lock);
		if (pos > inode->i_size) {
			loff_t additional_blocks = (512 - 1 + copied) >> 9;

			i_size_write(inode, pos);
			/*
			 * Estimate new allocation size based on the amount written.
			 * This will be updated from server on close (and on queryinfo)
			 */
			inode->i_blocks = min_t(blkcnt_t, (512 - 1 + pos) >> 9,
						inode->i_blocks + additional_blocks);
		}
		spin_unlock(&inode->i_lock);
	}

	unlock_page(page);
	put_page(page);
	/* Indication to update ctime and mtime as close is deferred */
	set_bit(CIFS_INO_MODIFIED_ATTR, &CIFS_I(inode)->flags);

	return rc;
}
#endif // End netfs removal 2773

/*
 * Flush data on a strict file.
 */
@@ -4565,6 +3932,7 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset)
}
#endif // end netfslib remove 4633


static vm_fault_t cifs_page_mkwrite(struct vm_fault *vmf)
{
	return netfs_page_mkwrite(vmf, NULL);