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

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
...@@ -2617,639 +2617,6 @@ cifs_get_readable_path(struct cifs_tcon *tcon, const char *name, ...@@ -2617,639 +2617,6 @@ cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
return -ENOENT; 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. * 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) ...@@ -4565,6 +3932,7 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset)
} }
#endif // end netfslib remove 4633 #endif // end netfslib remove 4633
static vm_fault_t cifs_page_mkwrite(struct vm_fault *vmf) static vm_fault_t cifs_page_mkwrite(struct vm_fault *vmf)
{ {
return netfs_page_mkwrite(vmf, NULL); return netfs_page_mkwrite(vmf, NULL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment