Received: by 2002:a05:6a10:af89:0:0:0:0 with SMTP id iu9csp1520059pxb; Wed, 12 Jan 2022 17:12:49 -0800 (PST) X-Google-Smtp-Source: ABdhPJyahhMgljXbrUX8WLamhE6iiVLqyNIZ/FBqIZL0RdcMpBIcPU8SYYDrgt33LqtAUV1criqr X-Received: by 2002:a17:906:6a1a:: with SMTP id qw26mr1822465ejc.46.1642036369553; Wed, 12 Jan 2022 17:12:49 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1642036369; cv=none; d=google.com; s=arc-20160816; b=WOM9J4dsXAbTqTNWq4wP2AiEZ2MSj2UYY7eC8nVQwpEQ07+Ctd6HB/LyV8jJFc7bz2 MSNnrphtF/QPaoDAYI+CsX6d7+HAliDEtfjC/86NIXuvHP9TsLs6yjLvosInhSMC1Lj9 uKyS4gN3uDDhT0EAxAFkUpSxID/igr5t6PVuhsOmS0wXk370usrpPfZP3jzUYMLKoIf+ UL4mwhGrRz3D3JJ7/ypAVxmr5TJ/Fptlq6lKmqdHpgkELB05gxBHjnynRCXZ3HUgdZlv 5BgA6Nh+w7Kgb4SSeePzRpUOI7Tj4HQrB0nhliY9GkzSGM7QWycVkre0cdtfe93/GAfV 36Qw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:message-id:date:content-transfer-encoding :content-id:mime-version:subject:cc:to:references:in-reply-to:from :organization:dkim-signature; bh=akkQ6Ecla+xiqsXojAcBOs9ebFPCv7cFDXlXcfhJ6J8=; b=URKUAIsLUtKIYLldCJSv6fJ64AMmdN/jv6alF77yZzh2tNrw7AA0m4LGDtVnL14gVd VdKXTWzLKiJK9t81RPdQhDOEzp8jEPX9scfBAu8lYNxq3rIHW2dVk/+bEU0AlVfdhJNP ED2h8OE82XU7MRkWCqGjX600enDykNTDc56Z6IfYMaPjyoGX4yUnkQKhRS0W7+8JqruB MgGEEaEAD9FZE5lilWIYxgDybE6wVnOa7RCqcQbsqRVIoMGC9cTRk+2mrlE5tiZ5ynV5 6ys4YOpKW86RASP7ZcCPCJ2aGnP1GWQWA4bEXmti7izRLwweJr/7ualkoqKewCj8wz5k 238w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=i3ibyYQ1; spf=pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id p8si51561edr.396.2022.01.12.17.12.18; Wed, 12 Jan 2022 17:12:49 -0800 (PST) Received-SPF: pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=i3ibyYQ1; spf=pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233893AbiALV4f (ORCPT + 99 others); Wed, 12 Jan 2022 16:56:35 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:25551 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233849AbiALV4e (ORCPT ); Wed, 12 Jan 2022 16:56:34 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1642024588; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=akkQ6Ecla+xiqsXojAcBOs9ebFPCv7cFDXlXcfhJ6J8=; b=i3ibyYQ1PRl0EnWkOBXMygtgqAIbGtYdgLnB3iKyn08vmLVL0odDGGhGZg/r/VwOdOhSfI XyXcRjY1Lei+YOafYC19c9fwjCSHNIn7mkkQup8TA60nbpdS18Otc9buGdYopeqv+NuPq7 ML7PWPDkx1ysRCF2cB8oUuyutvCCPug= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-300-lpOH86hQNbKrKK8Q6wM25g-1; Wed, 12 Jan 2022 16:56:24 -0500 X-MC-Unique: lpOH86hQNbKrKK8Q6wM25g-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 16C20100C609; Wed, 12 Jan 2022 21:56:23 +0000 (UTC) Received: from warthog.procyon.org.uk (unknown [10.33.36.165]) by smtp.corp.redhat.com (Postfix) with ESMTP id C62E14E2BD; Wed, 12 Jan 2022 21:56:19 +0000 (UTC) Organization: Red Hat UK Ltd. Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SI4 1TE, United Kingdom. Registered in England and Wales under Company Registration No. 3798903 From: David Howells In-Reply-To: <164021579335.640689.2681324337038770579.stgit@warthog.procyon.org.uk> References: <164021579335.640689.2681324337038770579.stgit@warthog.procyon.org.uk> <164021479106.640689.17404516570194656552.stgit@warthog.procyon.org.uk> To: linux-cachefs@redhat.com Cc: dhowells@redhat.com, Steve French , Shyam Prasad N , Murphy Zhou , Jeff Layton , Matthew Wilcox , Linus Torvalds , linux-cifs@vger.kernel.org, linux-afs@lists.infradead.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs-developer@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v6] cifs: Support fscache indexing rewrite MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-ID: <1318952.1642024578.1@warthog.procyon.org.uk> Content-Transfer-Encoding: quoted-printable Date: Wed, 12 Jan 2022 21:56:18 +0000 Message-ID: <1318953.1642024578@warthog.procyon.org.uk> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org [Note: This has been detached from my fscache-rewrite pull request and sta= cked on the branch after the tag point] Change the cifs filesystem to take account of the changes to fscache's indexing rewrite and reenable caching in cifs. The following changes have been made: (1) The fscache_netfs struct is no more, and there's no need to register the filesystem as a whole. (2) The session cookie is now an fscache_volume cookie, allocated with fscache_acquire_volume(). That takes three parameters: a string representing the "volume" in the index, a string naming the cache to use (or NULL) and a u64 that conveys coherency metadata for the volume. For cifs, I've made it render the volume name string as: "cifs,," where the sharename has '/' characters replaced with ';'. This probably needs rethinking a bit as the total name could exceed the maximum filename component length. Further, the coherency data is currently just set to 0. It needs something else doing with it - I wonder if it would suffice simply to sum the resource_id, vol_create_time and vol_serial_number or maybe hash them. (3) The fscache_cookie_def is no more and needed information is passed directly to fscache_acquire_cookie(). The cache no longer calls back into the filesystem, but rather metadata changes are indicated at other times. fscache_acquire_cookie() is passed the same keying and coherency information as before. (4) The functions to set/reset cookies are removed and fscache_use_cookie() and fscache_unuse_cookie() are used instead. fscache_use_cookie() is passed a flag to indicate if the cookie is opened for writing. fscache_unuse_cookie() is passed updates for the metadata if we changed it (ie. if the file was opened for writing). These are called when the file is opened or closed. (5) cifs_setattr_*() are made to call fscache_resize() to change the size of the cache object. (6) The functions to read and write data are stubbed out pending a conversion to use netfslib. Changes =3D=3D=3D=3D=3D=3D=3D ver #6: - Moved the change of gfpflags_allow_blocking() to current_is_kswapd() fo= r cifs here. - Fixed one of the error paths in cifs_atomic_open() to jump around the call to use the cookie. - Fixed an additional successful return in the middle of cifs_open() to use the cookie on the way out. - Only get a volume cookie (and thus inode cookies) when "-o fsc" is supplied to mount. ver #5: - Fixed a couple of bits of cookie handling[2]: - The cookie should be released in cifs_evict_inode(), not cifsFileInfo_put_final(). The cookie needs to persist beyond file closure so that writepages will be able to write to it. - fscache_use_cookie() needs to be called in cifs_atomic_open() as it i= s for cifs_open(). ver #4: - Fixed the use of sizeof with memset. - tcon->vol_create_time is __le64 so doesn't need cpu_to_le64(). ver #3: - Canonicalise the cifs coherency data to make the cache portable. - Set volume coherency data. ver #2: - Use gfpflags_allow_blocking() rather than using flag directly. - Upgraded to -rc4 to allow for upstream changes[1]. - fscache_acquire_volume() now returns errors. Signed-off-by: David Howells Acked-by: Jeff Layton cc: Steve French cc: Shyam Prasad N cc: linux-cifs@vger.kernel.org cc: linux-cachefs@redhat.com Link: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/c= ommit/?id=3D23b55d673d7527b093cd97b7c217c82e70cd1af0 [1] Link: https://lore.kernel.org/r/3419813.1641592362@warthog.procyon.org.uk/= [2] Link: https://lore.kernel.org/r/163819671009.215744.11230627184193298714.s= tgit@warthog.procyon.org.uk/ # v1 Link: https://lore.kernel.org/r/163906982979.143852.10672081929614953210.s= tgit@warthog.procyon.org.uk/ # v2 Link: https://lore.kernel.org/r/163967187187.1823006.247415138444991444.st= git@warthog.procyon.org.uk/ # v3 Link: https://lore.kernel.org/r/164021579335.640689.2681324337038770579.st= git@warthog.procyon.org.uk/ # v4 Link: https://lore.kernel.org/r/3462849.1641593783@warthog.procyon.org.uk/= # v5 --- fs/cifs/Kconfig | 2 = fs/cifs/Makefile | 2 = fs/cifs/cache.c | 105 ---------------- fs/cifs/cifsfs.c | 19 +-- fs/cifs/cifsglob.h | 5 = fs/cifs/connect.c | 12 - fs/cifs/dir.c | 5 = fs/cifs/file.c | 70 +++++++---- fs/cifs/fscache.c | 333 ++++++++++++-----------------------------------= ------ fs/cifs/fscache.h | 126 ++++++-------------- fs/cifs/inode.c | 37 +++-- 11 files changed, 207 insertions(+), 509 deletions(-) diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 346ae8716deb..3b7e3b9e4fd2 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig @@ -188,7 +188,7 @@ config CIFS_SMB_DIRECT = config CIFS_FSCACHE bool "Provide CIFS client caching support" - depends on CIFS=3Dm && FSCACHE_OLD_API || CIFS=3Dy && FSCACHE_OLD_API=3D= y + depends on CIFS=3Dm && FSCACHE || CIFS=3Dy && FSCACHE=3Dy help Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data to be cached locally on disk through the general filesystem cache diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile index 87fcacdf3de7..cc8fdcb35b71 100644 --- a/fs/cifs/Makefile +++ b/fs/cifs/Makefile @@ -25,7 +25,7 @@ cifs-$(CONFIG_CIFS_DFS_UPCALL) +=3D cifs_dfs_ref.o dfs_c= ache.o = cifs-$(CONFIG_CIFS_SWN_UPCALL) +=3D netlink.o cifs_swn.o = -cifs-$(CONFIG_CIFS_FSCACHE) +=3D fscache.o cache.o +cifs-$(CONFIG_CIFS_FSCACHE) +=3D fscache.o = cifs-$(CONFIG_CIFS_SMB_DIRECT) +=3D smbdirect.o = diff --git a/fs/cifs/cache.c b/fs/cifs/cache.c deleted file mode 100644 index 8be57aaedab6..000000000000 --- a/fs/cifs/cache.c +++ /dev/null @@ -1,105 +0,0 @@ -// SPDX-License-Identifier: LGPL-2.1 -/* - * CIFS filesystem cache index structure definitions - * - * Copyright (c) 2010 Novell, Inc. - * Authors(s): Suresh Jayaraman (sjayaraman@suse.de> - * - */ -#include "fscache.h" -#include "cifs_debug.h" - -/* - * CIFS filesystem definition for FS-Cache - */ -struct fscache_netfs cifs_fscache_netfs =3D { - .name =3D "cifs", - .version =3D 0, -}; - -/* - * Register CIFS for caching with FS-Cache - */ -int cifs_fscache_register(void) -{ - return fscache_register_netfs(&cifs_fscache_netfs); -} - -/* - * Unregister CIFS for caching - */ -void cifs_fscache_unregister(void) -{ - fscache_unregister_netfs(&cifs_fscache_netfs); -} - -/* - * Server object for FS-Cache - */ -const struct fscache_cookie_def cifs_fscache_server_index_def =3D { - .name =3D "CIFS.server", - .type =3D FSCACHE_COOKIE_TYPE_INDEX, -}; - -static enum -fscache_checkaux cifs_fscache_super_check_aux(void *cookie_netfs_data, - const void *data, - uint16_t datalen, - loff_t object_size) -{ - struct cifs_fscache_super_auxdata auxdata; - const struct cifs_tcon *tcon =3D cookie_netfs_data; - - if (datalen !=3D sizeof(auxdata)) - return FSCACHE_CHECKAUX_OBSOLETE; - - memset(&auxdata, 0, sizeof(auxdata)); - auxdata.resource_id =3D tcon->resource_id; - auxdata.vol_create_time =3D tcon->vol_create_time; - auxdata.vol_serial_number =3D tcon->vol_serial_number; - - if (memcmp(data, &auxdata, datalen) !=3D 0) - return FSCACHE_CHECKAUX_OBSOLETE; - - return FSCACHE_CHECKAUX_OKAY; -} - -/* - * Superblock object for FS-Cache - */ -const struct fscache_cookie_def cifs_fscache_super_index_def =3D { - .name =3D "CIFS.super", - .type =3D FSCACHE_COOKIE_TYPE_INDEX, - .check_aux =3D cifs_fscache_super_check_aux, -}; - -static enum -fscache_checkaux cifs_fscache_inode_check_aux(void *cookie_netfs_data, - const void *data, - uint16_t datalen, - loff_t object_size) -{ - struct cifs_fscache_inode_auxdata auxdata; - struct cifsInodeInfo *cifsi =3D cookie_netfs_data; - - if (datalen !=3D sizeof(auxdata)) - return FSCACHE_CHECKAUX_OBSOLETE; - - memset(&auxdata, 0, sizeof(auxdata)); - auxdata.eof =3D cifsi->server_eof; - auxdata.last_write_time_sec =3D cifsi->vfs_inode.i_mtime.tv_sec; - auxdata.last_change_time_sec =3D cifsi->vfs_inode.i_ctime.tv_sec; - auxdata.last_write_time_nsec =3D cifsi->vfs_inode.i_mtime.tv_nsec; - auxdata.last_change_time_nsec =3D cifsi->vfs_inode.i_ctime.tv_nsec; - - if (memcmp(data, &auxdata, datalen) !=3D 0) - return FSCACHE_CHECKAUX_OBSOLETE; - - return FSCACHE_CHECKAUX_OKAY; -} - -const struct fscache_cookie_def cifs_fscache_inode_object_def =3D { - .name =3D "CIFS.uniqueid", - .type =3D FSCACHE_COOKIE_TYPE_DATAFILE, - .check_aux =3D cifs_fscache_inode_check_aux, -}; diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index dca42aa87d30..26cf2193c9a2 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -396,6 +396,9 @@ static void cifs_evict_inode(struct inode *inode) { truncate_inode_pages_final(&inode->i_data); + if (inode->i_state & I_PINNING_FSCACHE_WB) + cifs_fscache_unuse_inode_cookie(inode, true); + cifs_fscache_release_inode_cookie(inode); clear_inode(inode); } = @@ -720,6 +723,12 @@ static int cifs_show_stats(struct seq_file *s, struct= dentry *root) } #endif = +static int cifs_write_inode(struct inode *inode, struct writeback_control= *wbc) +{ + fscache_unpin_writeback(wbc, cifs_inode_cookie(inode)); + return 0; +} + static int cifs_drop_inode(struct inode *inode) { struct cifs_sb_info *cifs_sb =3D CIFS_SB(inode->i_sb); @@ -732,6 +741,7 @@ static int cifs_drop_inode(struct inode *inode) static const struct super_operations cifs_super_ops =3D { .statfs =3D cifs_statfs, .alloc_inode =3D cifs_alloc_inode, + .write_inode =3D cifs_write_inode, .free_inode =3D cifs_free_inode, .drop_inode =3D cifs_drop_inode, .evict_inode =3D cifs_evict_inode, @@ -1624,13 +1634,9 @@ init_cifs(void) goto out_destroy_cifsoplockd_wq; } = - rc =3D cifs_fscache_register(); - if (rc) - goto out_destroy_deferredclose_wq; - rc =3D cifs_init_inodecache(); if (rc) - goto out_unreg_fscache; + goto out_destroy_deferredclose_wq; = rc =3D cifs_init_mids(); if (rc) @@ -1692,8 +1698,6 @@ init_cifs(void) cifs_destroy_mids(); out_destroy_inodecache: cifs_destroy_inodecache(); -out_unreg_fscache: - cifs_fscache_unregister(); out_destroy_deferredclose_wq: destroy_workqueue(deferredclose_wq); out_destroy_cifsoplockd_wq: @@ -1729,7 +1733,6 @@ exit_cifs(void) cifs_destroy_request_bufs(); cifs_destroy_mids(); cifs_destroy_inodecache(); - cifs_fscache_unregister(); destroy_workqueue(deferredclose_wq); destroy_workqueue(cifsoplockd_wq); destroy_workqueue(decrypt_wq); diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index be74606724c7..ba6fbb1ad8f3 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -659,9 +659,6 @@ struct TCP_Server_Info { unsigned int total_read; /* total amount of data read in this pass */ atomic_t in_send; /* requests trying to send */ atomic_t num_waiters; /* blocked waiting to get in sendrecv */ -#ifdef CONFIG_CIFS_FSCACHE - struct fscache_cookie *fscache; /* client index cache cookie */ -#endif #ifdef CONFIG_CIFS_STATS2 atomic_t num_cmds[NUMBER_OF_SMB2_COMMANDS]; /* total requests by cmd */ atomic_t smb2slowcmd[NUMBER_OF_SMB2_COMMANDS]; /* count resps > 1 sec */ @@ -1117,7 +1114,7 @@ struct cifs_tcon { __u32 max_bytes_copy; #ifdef CONFIG_CIFS_FSCACHE u64 resource_id; /* server resource id */ - struct fscache_cookie *fscache; /* cookie for share */ + struct fscache_volume *fscache; /* cookie for share */ #endif struct list_head pending_opens; /* list of incomplete opens */ struct cached_fid crfid; /* Cached root fid */ diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 18448dbd762a..a52fd3a30c88 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1396,10 +1396,6 @@ cifs_put_tcp_session(struct TCP_Server_Info *server= , int from_reconnect) = cifs_crypto_secmech_release(server); = - /* fscache server cookies are based on primary channel only */ - if (!CIFS_SERVER_IS_CHAN(server)) - cifs_fscache_release_client_cookie(server); - kfree(server->session_key.response); server->session_key.response =3D NULL; server->session_key.len =3D 0; @@ -1559,14 +1555,6 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx, list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list); spin_unlock(&cifs_tcp_ses_lock); = - /* fscache server cookies are based on primary channel only */ - if (!CIFS_SERVER_IS_CHAN(tcp_ses)) - cifs_fscache_get_client_cookie(tcp_ses); -#ifdef CONFIG_CIFS_FSCACHE - else - tcp_ses->fscache =3D tcp_ses->primary_server->fscache; -#endif /* CONFIG_CIFS_FSCACHE */ - /* queue echo request delayed work */ queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval); = diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 6e8e7cc26ae2..ce9b22aecfba 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -22,6 +22,7 @@ #include "cifs_unicode.h" #include "fs_context.h" #include "cifs_ioctl.h" +#include "fscache.h" = static void renew_parental_timestamps(struct dentry *direntry) @@ -507,8 +508,12 @@ cifs_atomic_open(struct inode *inode, struct dentry *= direntry, server->ops->close(xid, tcon, &fid); cifs_del_pending_open(&open); rc =3D -ENOMEM; + goto out; } = + fscache_use_cookie(cifs_inode_cookie(file_inode(file)), + file->f_mode & FMODE_WRITE); + out: cifs_put_tlink(tlink); out_free_xid: diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 9fee3af83a73..fb77ca1a15d8 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -376,8 +376,6 @@ static void cifsFileInfo_put_final(struct cifsFileInfo= *cifs_file) struct cifsLockInfo *li, *tmp; struct super_block *sb =3D inode->i_sb; = - cifs_fscache_release_inode_cookie(inode); - /* * Delete any outstanding lock records. We'll lose them when the file * is closed anyway. @@ -570,7 +568,7 @@ int cifs_open(struct inode *inode, struct file *file) spin_lock(&CIFS_I(inode)->deferred_lock); cifs_del_deferred_close(cfile); spin_unlock(&CIFS_I(inode)->deferred_lock); - goto out; + goto use_cache; } else { _cifsFileInfo_put(cfile, true, false); } @@ -632,8 +630,6 @@ int cifs_open(struct inode *inode, struct file *file) goto out; } = - cifs_fscache_set_inode_cookie(inode, file); - if ((oplock & CIFS_CREATE_ACTION) && !posix_open_ok && tcon->unix_ext) { /* * Time to set mode which we can not set earlier due to @@ -652,6 +648,19 @@ int cifs_open(struct inode *inode, struct file *file) cfile->pid); } = +use_cache: + fscache_use_cookie(cifs_inode_cookie(file_inode(file)), + file->f_mode & FMODE_WRITE); + if (file->f_flags & O_DIRECT && + (!((file->f_flags & O_ACCMODE) !=3D O_RDONLY) || + file->f_flags & O_APPEND)) { + struct cifs_fscache_inode_coherency_data cd; + cifs_fscache_fill_coherency(file_inode(file), &cd); + fscache_invalidate(cifs_inode_cookie(file_inode(file)), + &cd, i_size_read(file_inode(file)), + FSCACHE_INVAL_DIO_WRITE); + } + out: free_dentry_path(page); free_xid(xid); @@ -876,6 +885,8 @@ int cifs_close(struct inode *inode, struct file *file) struct cifs_sb_info *cifs_sb =3D CIFS_SB(inode->i_sb); struct cifs_deferred_close *dclose; = + cifs_fscache_unuse_inode_cookie(inode, file->f_mode & FMODE_WRITE); + if (file->private_data !=3D NULL) { cfile =3D file->private_data; file->private_data =3D NULL; @@ -886,7 +897,6 @@ int cifs_close(struct inode *inode, struct file *file) dclose) { if (test_and_clear_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) { inode->i_ctime =3D inode->i_mtime =3D current_time(inode); - cifs_fscache_update_inode_cookie(inode); } spin_lock(&cinode->deferred_lock); cifs_add_deferred_close(cfile, dclose); @@ -4198,10 +4208,12 @@ static vm_fault_t cifs_page_mkwrite(struct vm_fault *vmf) { struct page *page =3D vmf->page; - struct file *file =3D vmf->vma->vm_file; - struct inode *inode =3D file_inode(file); = - cifs_fscache_wait_on_page_write(inode, page); +#ifdef CONFIG_CIFS_FSCACHE + if (PageFsCache(page) && + wait_on_page_fscache_killable(page) < 0) + return VM_FAULT_RETRY; +#endif = lock_page(page); return VM_FAULT_LOCKED; @@ -4275,8 +4287,6 @@ cifs_readv_complete(struct work_struct *work) if (rdata->result =3D=3D 0 || (rdata->result =3D=3D -EAGAIN && got_bytes)) cifs_readpage_to_fscache(rdata->mapping->host, page); - else - cifs_fscache_uncache_page(rdata->mapping->host, page); = got_bytes -=3D min_t(unsigned int, PAGE_SIZE, got_bytes); = @@ -4593,11 +4603,6 @@ static int cifs_readpages(struct file *file, struct= address_space *mapping, kref_put(&rdata->refcount, cifs_readdata_release); } = - /* Any pages that have been shown to fscache but didn't get added to - * the pagecache must be uncached before they get returned to the - * allocator. - */ - cifs_fscache_readpages_cancel(mapping->host, page_list); free_xid(xid); return rc; } @@ -4801,17 +4806,19 @@ static int cifs_release_page(struct page *page, gf= p_t gfp) { if (PagePrivate(page)) return 0; - - return cifs_fscache_release_page(page, gfp); + if (PageFsCache(page)) { + if (current_is_kswapd() || !(gfp & __GFP_FS)) + return false; + wait_on_page_fscache(page); + } + fscache_note_page_release(cifs_inode_cookie(page->mapping->host)); + return true; } = static void cifs_invalidate_page(struct page *page, unsigned int offset, unsigned int length) { - struct cifsInodeInfo *cifsi =3D CIFS_I(page->mapping->host); - - if (offset =3D=3D 0 && length =3D=3D PAGE_SIZE) - cifs_fscache_invalidate_page(page, &cifsi->vfs_inode); + wait_on_page_fscache(page); } = static int cifs_launder_page(struct page *page) @@ -4831,7 +4838,7 @@ static int cifs_launder_page(struct page *page) if (clear_page_dirty_for_io(page)) rc =3D cifs_writepage_locked(page, &wbc); = - cifs_fscache_invalidate_page(page, page->mapping->host); + wait_on_page_fscache(page); return rc; } = @@ -4988,6 +4995,19 @@ static void cifs_swap_deactivate(struct file *file) /* do we need to unpin (or unlock) the file */ } = +/* + * Mark a page as having been made dirty and thus needing writeback. We = also + * need to pin the cache object to write back to. + */ +#ifdef CONFIG_CIFS_FSCACHE +static int cifs_set_page_dirty(struct page *page) +{ + return fscache_set_page_dirty(page, cifs_inode_cookie(page->mapping->hos= t)); +} +#else +#define cifs_set_page_dirty __set_page_dirty_nobuffers +#endif + const struct address_space_operations cifs_addr_ops =3D { .readpage =3D cifs_readpage, .readpages =3D cifs_readpages, @@ -4995,7 +5015,7 @@ const struct address_space_operations cifs_addr_ops = =3D { .writepages =3D cifs_writepages, .write_begin =3D cifs_write_begin, .write_end =3D cifs_write_end, - .set_page_dirty =3D __set_page_dirty_nobuffers, + .set_page_dirty =3D cifs_set_page_dirty, .releasepage =3D cifs_release_page, .direct_IO =3D cifs_direct_io, .invalidatepage =3D cifs_invalidate_page, @@ -5020,7 +5040,7 @@ const struct address_space_operations cifs_addr_ops_= smallbuf =3D { .writepages =3D cifs_writepages, .write_begin =3D cifs_write_begin, .write_end =3D cifs_write_end, - .set_page_dirty =3D __set_page_dirty_nobuffers, + .set_page_dirty =3D cifs_set_page_dirty, .releasepage =3D cifs_release_page, .invalidatepage =3D cifs_invalidate_page, .launder_page =3D cifs_launder_page, diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c index 003c5f1f4dfb..efaac4d5ff55 100644 --- a/fs/cifs/fscache.c +++ b/fs/cifs/fscache.c @@ -12,250 +12,136 @@ #include "cifs_fs_sb.h" #include "cifsproto.h" = -/* - * Key layout of CIFS server cache index object - */ -struct cifs_server_key { - __u64 conn_id; -} __packed; - -/* - * Get a cookie for a server object keyed by {IPaddress,port,family} tupl= e - */ -void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) -{ - struct cifs_server_key key; - - /* - * Check if cookie was already initialized so don't reinitialize it. - * In the future, as we integrate with newer fscache features, - * we may want to instead add a check if cookie has changed - */ - if (server->fscache) - return; - - memset(&key, 0, sizeof(key)); - key.conn_id =3D server->conn_id; - - server->fscache =3D - fscache_acquire_cookie(cifs_fscache_netfs.primary_index, - &cifs_fscache_server_index_def, - &key, sizeof(key), - NULL, 0, - server, 0, true); - cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", - __func__, server, server->fscache); -} - -void cifs_fscache_release_client_cookie(struct TCP_Server_Info *server) +static void cifs_fscache_fill_volume_coherency( + struct cifs_tcon *tcon, + struct cifs_fscache_volume_coherency_data *cd) { - cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", - __func__, server, server->fscache); - fscache_relinquish_cookie(server->fscache, NULL, false); - server->fscache =3D NULL; + memset(cd, 0, sizeof(*cd)); + cd->resource_id =3D cpu_to_le64(tcon->resource_id); + cd->vol_create_time =3D tcon->vol_create_time; + cd->vol_serial_number =3D cpu_to_le32(tcon->vol_serial_number); } = -void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) +int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) { + struct cifs_fscache_volume_coherency_data cd; struct TCP_Server_Info *server =3D tcon->ses->server; + struct fscache_volume *vcookie; + const struct sockaddr *sa =3D (struct sockaddr *)&server->dstaddr; + size_t slen, i; char *sharename; - struct cifs_fscache_super_auxdata auxdata; + char *key; + int ret =3D -ENOMEM; = - /* - * Check if cookie was already initialized so don't reinitialize it. - * In the future, as we integrate with newer fscache features, - * we may want to instead add a check if cookie has changed - */ - if (tcon->fscache) - return; + tcon->fscache =3D NULL; + switch (sa->sa_family) { + case AF_INET: + case AF_INET6: + break; + default: + cifs_dbg(VFS, "Unknown network family '%d'\n", sa->sa_family); + return -EINVAL; + } + + memset(&key, 0, sizeof(key)); = sharename =3D extract_sharename(tcon->treeName); if (IS_ERR(sharename)) { cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__); - tcon->fscache =3D NULL; - return; + return -EINVAL; } = - memset(&auxdata, 0, sizeof(auxdata)); - auxdata.resource_id =3D tcon->resource_id; - auxdata.vol_create_time =3D tcon->vol_create_time; - auxdata.vol_serial_number =3D tcon->vol_serial_number; + slen =3D strlen(sharename); + for (i =3D 0; i < slen; i++) + if (sharename[i] =3D=3D '/') + sharename[i] =3D ';'; + + key =3D kasprintf(GFP_KERNEL, "cifs,%pISpc,%s", sa, sharename); + if (!key) + goto out; + + cifs_fscache_fill_volume_coherency(tcon, &cd); + vcookie =3D fscache_acquire_volume(key, + NULL, /* preferred_cache */ + &cd, sizeof(cd)); + cifs_dbg(FYI, "%s: (%s/0x%p)\n", __func__, key, vcookie); + if (IS_ERR(vcookie)) { + if (vcookie !=3D ERR_PTR(-EBUSY)) { + ret =3D PTR_ERR(vcookie); + goto out_2; + } + pr_err("Cache volume key already in use (%s)\n", key); + vcookie =3D NULL; + } = - tcon->fscache =3D - fscache_acquire_cookie(server->fscache, - &cifs_fscache_super_index_def, - sharename, strlen(sharename), - &auxdata, sizeof(auxdata), - tcon, 0, true); + tcon->fscache =3D vcookie; + ret =3D 0; +out_2: + kfree(key); +out: kfree(sharename); - cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", - __func__, server->fscache, tcon->fscache); + return ret; } = void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon) { - struct cifs_fscache_super_auxdata auxdata; - - memset(&auxdata, 0, sizeof(auxdata)); - auxdata.resource_id =3D tcon->resource_id; - auxdata.vol_create_time =3D tcon->vol_create_time; - auxdata.vol_serial_number =3D tcon->vol_serial_number; + struct cifs_fscache_volume_coherency_data cd; = cifs_dbg(FYI, "%s: (0x%p)\n", __func__, tcon->fscache); - fscache_relinquish_cookie(tcon->fscache, &auxdata, false); - tcon->fscache =3D NULL; -} - -static void cifs_fscache_acquire_inode_cookie(struct cifsInodeInfo *cifsi= , - struct cifs_tcon *tcon) -{ - struct cifs_fscache_inode_auxdata auxdata; = - memset(&auxdata, 0, sizeof(auxdata)); - auxdata.eof =3D cifsi->server_eof; - auxdata.last_write_time_sec =3D cifsi->vfs_inode.i_mtime.tv_sec; - auxdata.last_change_time_sec =3D cifsi->vfs_inode.i_ctime.tv_sec; - auxdata.last_write_time_nsec =3D cifsi->vfs_inode.i_mtime.tv_nsec; - auxdata.last_change_time_nsec =3D cifsi->vfs_inode.i_ctime.tv_nsec; - - cifsi->fscache =3D - fscache_acquire_cookie(tcon->fscache, - &cifs_fscache_inode_object_def, - &cifsi->uniqueid, sizeof(cifsi->uniqueid), - &auxdata, sizeof(auxdata), - cifsi, cifsi->vfs_inode.i_size, true); + cifs_fscache_fill_volume_coherency(tcon, &cd); + fscache_relinquish_volume(tcon->fscache, &cd, false); + tcon->fscache =3D NULL; } = -static void cifs_fscache_enable_inode_cookie(struct inode *inode) +void cifs_fscache_get_inode_cookie(struct inode *inode) { + struct cifs_fscache_inode_coherency_data cd; struct cifsInodeInfo *cifsi =3D CIFS_I(inode); struct cifs_sb_info *cifs_sb =3D CIFS_SB(inode->i_sb); struct cifs_tcon *tcon =3D cifs_sb_master_tcon(cifs_sb); = - if (cifsi->fscache) - return; - - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE)) - return; - - cifs_fscache_acquire_inode_cookie(cifsi, tcon); + cifs_fscache_fill_coherency(&cifsi->vfs_inode, &cd); = - cifs_dbg(FYI, "%s: got FH cookie (0x%p/0x%p)\n", - __func__, tcon->fscache, cifsi->fscache); + cifsi->fscache =3D + fscache_acquire_cookie(tcon->fscache, 0, + &cifsi->uniqueid, sizeof(cifsi->uniqueid), + &cd, sizeof(cd), + i_size_read(&cifsi->vfs_inode)); } = -void cifs_fscache_release_inode_cookie(struct inode *inode) +void cifs_fscache_unuse_inode_cookie(struct inode *inode, bool update) { - struct cifs_fscache_inode_auxdata auxdata; - struct cifsInodeInfo *cifsi =3D CIFS_I(inode); - - if (cifsi->fscache) { - memset(&auxdata, 0, sizeof(auxdata)); - auxdata.eof =3D cifsi->server_eof; - auxdata.last_write_time_sec =3D cifsi->vfs_inode.i_mtime.tv_sec; - auxdata.last_change_time_sec =3D cifsi->vfs_inode.i_ctime.tv_sec; - auxdata.last_write_time_nsec =3D cifsi->vfs_inode.i_mtime.tv_nsec; - auxdata.last_change_time_nsec =3D cifsi->vfs_inode.i_ctime.tv_nsec; + if (update) { + struct cifs_fscache_inode_coherency_data cd; + loff_t i_size =3D i_size_read(inode); = - cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache); - /* fscache_relinquish_cookie does not seem to update auxdata */ - fscache_update_cookie(cifsi->fscache, &auxdata); - fscache_relinquish_cookie(cifsi->fscache, &auxdata, false); - cifsi->fscache =3D NULL; + cifs_fscache_fill_coherency(inode, &cd); + fscache_unuse_cookie(cifs_inode_cookie(inode), &cd, &i_size); + } else { + fscache_unuse_cookie(cifs_inode_cookie(inode), NULL, NULL); } } = -void cifs_fscache_update_inode_cookie(struct inode *inode) +void cifs_fscache_release_inode_cookie(struct inode *inode) { - struct cifs_fscache_inode_auxdata auxdata; struct cifsInodeInfo *cifsi =3D CIFS_I(inode); = if (cifsi->fscache) { - memset(&auxdata, 0, sizeof(auxdata)); - auxdata.eof =3D cifsi->server_eof; - auxdata.last_write_time_sec =3D cifsi->vfs_inode.i_mtime.tv_sec; - auxdata.last_change_time_sec =3D cifsi->vfs_inode.i_ctime.tv_sec; - auxdata.last_write_time_nsec =3D cifsi->vfs_inode.i_mtime.tv_nsec; - auxdata.last_change_time_nsec =3D cifsi->vfs_inode.i_ctime.tv_nsec; - cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache); - fscache_update_cookie(cifsi->fscache, &auxdata); - } -} - -void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp= ) -{ - cifs_fscache_enable_inode_cookie(inode); -} - -void cifs_fscache_reset_inode_cookie(struct inode *inode) -{ - struct cifsInodeInfo *cifsi =3D CIFS_I(inode); - struct cifs_sb_info *cifs_sb =3D CIFS_SB(inode->i_sb); - struct cifs_tcon *tcon =3D cifs_sb_master_tcon(cifs_sb); - struct fscache_cookie *old =3D cifsi->fscache; - - if (cifsi->fscache) { - /* retire the current fscache cache and get a new one */ - fscache_relinquish_cookie(cifsi->fscache, NULL, true); - - cifs_fscache_acquire_inode_cookie(cifsi, tcon); - cifs_dbg(FYI, "%s: new cookie 0x%p oldcookie 0x%p\n", - __func__, cifsi->fscache, old); + fscache_relinquish_cookie(cifsi->fscache, false); + cifsi->fscache =3D NULL; } } = -int cifs_fscache_release_page(struct page *page, gfp_t gfp) -{ - if (PageFsCache(page)) { - struct inode *inode =3D page->mapping->host; - struct cifsInodeInfo *cifsi =3D CIFS_I(inode); - - cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", - __func__, page, cifsi->fscache); - if (!fscache_maybe_release_page(cifsi->fscache, page, gfp)) - return 0; - } - - return 1; -} - -static void cifs_readpage_from_fscache_complete(struct page *page, void *= ctx, - int error) -{ - cifs_dbg(FYI, "%s: (0x%p/%d)\n", __func__, page, error); - if (!error) - SetPageUptodate(page); - unlock_page(page); -} - /* * Retrieve a page from FS-Cache */ int __cifs_readpage_from_fscache(struct inode *inode, struct page *page) { - int ret; - cifs_dbg(FYI, "%s: (fsc:%p, p:%p, i:0x%p\n", __func__, CIFS_I(inode)->fscache, page, inode); - ret =3D fscache_read_or_alloc_page(CIFS_I(inode)->fscache, page, - cifs_readpage_from_fscache_complete, - NULL, - GFP_KERNEL); - switch (ret) { - - case 0: /* page found in fscache, read submitted */ - cifs_dbg(FYI, "%s: submitted\n", __func__); - return ret; - case -ENOBUFS: /* page won't be cached */ - case -ENODATA: /* page not in cache */ - cifs_dbg(FYI, "%s: %d\n", __func__, ret); - return 1; - - default: - cifs_dbg(VFS, "unknown error ret =3D %d\n", ret); - } - return ret; + return -ENOBUFS; // Needs conversion to using netfslib } = /* @@ -266,78 +152,19 @@ int __cifs_readpages_from_fscache(struct inode *inod= e, struct list_head *pages, unsigned *nr_pages) { - int ret; - cifs_dbg(FYI, "%s: (0x%p/%u/0x%p)\n", __func__, CIFS_I(inode)->fscache, *nr_pages, inode); - ret =3D fscache_read_or_alloc_pages(CIFS_I(inode)->fscache, mapping, - pages, nr_pages, - cifs_readpage_from_fscache_complete, - NULL, - mapping_gfp_mask(mapping)); - switch (ret) { - case 0: /* read submitted to the cache for all pages */ - cifs_dbg(FYI, "%s: submitted\n", __func__); - return ret; - - case -ENOBUFS: /* some pages are not cached and can't be */ - case -ENODATA: /* some pages are not cached */ - cifs_dbg(FYI, "%s: no page\n", __func__); - return 1; - - default: - cifs_dbg(FYI, "unknown error ret =3D %d\n", ret); - } - - return ret; + return -ENOBUFS; // Needs conversion to using netfslib } = void __cifs_readpage_to_fscache(struct inode *inode, struct page *page) { struct cifsInodeInfo *cifsi =3D CIFS_I(inode); - int ret; = WARN_ON(!cifsi->fscache); = cifs_dbg(FYI, "%s: (fsc: %p, p: %p, i: %p)\n", __func__, cifsi->fscache, page, inode); - ret =3D fscache_write_page(cifsi->fscache, page, - cifsi->vfs_inode.i_size, GFP_KERNEL); - if (ret !=3D 0) - fscache_uncache_page(cifsi->fscache, page); -} - -void __cifs_fscache_readpages_cancel(struct inode *inode, struct list_hea= d *pages) -{ - cifs_dbg(FYI, "%s: (fsc: %p, i: %p)\n", - __func__, CIFS_I(inode)->fscache, inode); - fscache_readpages_cancel(CIFS_I(inode)->fscache, pages); -} - -void __cifs_fscache_invalidate_page(struct page *page, struct inode *inod= e) -{ - struct cifsInodeInfo *cifsi =3D CIFS_I(inode); - struct fscache_cookie *cookie =3D cifsi->fscache; - - cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", __func__, page, cookie); - fscache_wait_on_page_write(cookie, page); - fscache_uncache_page(cookie, page); -} - -void __cifs_fscache_wait_on_page_write(struct inode *inode, struct page *= page) -{ - struct cifsInodeInfo *cifsi =3D CIFS_I(inode); - struct fscache_cookie *cookie =3D cifsi->fscache; - - cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", __func__, page, cookie); - fscache_wait_on_page_write(cookie, page); -} - -void __cifs_fscache_uncache_page(struct inode *inode, struct page *page) -{ - struct cifsInodeInfo *cifsi =3D CIFS_I(inode); - struct fscache_cookie *cookie =3D cifsi->fscache; = - cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", __func__, page, cookie); - fscache_uncache_page(cookie, page); + // Needs conversion to using netfslib } diff --git a/fs/cifs/fscache.h b/fs/cifs/fscache.h index 9baa1d0f22bd..0fc3f9252c84 100644 --- a/fs/cifs/fscache.h +++ b/fs/cifs/fscache.h @@ -13,84 +13,62 @@ = #include "cifsglob.h" = -#ifdef CONFIG_CIFS_FSCACHE - /* - * Auxiliary data attached to CIFS superblock within the cache + * Coherency data attached to CIFS volume within the cache */ -struct cifs_fscache_super_auxdata { - u64 resource_id; /* unique server resource id */ +struct cifs_fscache_volume_coherency_data { + __le64 resource_id; /* unique server resource id */ __le64 vol_create_time; - u32 vol_serial_number; + __le32 vol_serial_number; } __packed; = /* - * Auxiliary data attached to CIFS inode within the cache + * Coherency data attached to CIFS inode within the cache. */ -struct cifs_fscache_inode_auxdata { - u64 last_write_time_sec; - u64 last_change_time_sec; - u32 last_write_time_nsec; - u32 last_change_time_nsec; - u64 eof; +struct cifs_fscache_inode_coherency_data { + __le64 last_write_time_sec; + __le64 last_change_time_sec; + __le32 last_write_time_nsec; + __le32 last_change_time_nsec; }; = -/* - * cache.c - */ -extern struct fscache_netfs cifs_fscache_netfs; -extern const struct fscache_cookie_def cifs_fscache_server_index_def; -extern const struct fscache_cookie_def cifs_fscache_super_index_def; -extern const struct fscache_cookie_def cifs_fscache_inode_object_def; - -extern int cifs_fscache_register(void); -extern void cifs_fscache_unregister(void); +#ifdef CONFIG_CIFS_FSCACHE = /* * fscache.c */ -extern void cifs_fscache_get_client_cookie(struct TCP_Server_Info *); -extern void cifs_fscache_release_client_cookie(struct TCP_Server_Info *); -extern void cifs_fscache_get_super_cookie(struct cifs_tcon *); +extern int cifs_fscache_get_super_cookie(struct cifs_tcon *); extern void cifs_fscache_release_super_cookie(struct cifs_tcon *); = +extern void cifs_fscache_get_inode_cookie(struct inode *); extern void cifs_fscache_release_inode_cookie(struct inode *); -extern void cifs_fscache_update_inode_cookie(struct inode *inode); -extern void cifs_fscache_set_inode_cookie(struct inode *, struct file *); -extern void cifs_fscache_reset_inode_cookie(struct inode *); +extern void cifs_fscache_unuse_inode_cookie(struct inode *, bool); + +static inline +void cifs_fscache_fill_coherency(struct inode *inode, + struct cifs_fscache_inode_coherency_data *cd) +{ + struct cifsInodeInfo *cifsi =3D CIFS_I(inode); + + memset(cd, 0, sizeof(*cd)); + cd->last_write_time_sec =3D cpu_to_le64(cifsi->vfs_inode.i_mtime.tv_se= c); + cd->last_write_time_nsec =3D cpu_to_le32(cifsi->vfs_inode.i_mtime.tv_ns= ec); + cd->last_change_time_sec =3D cpu_to_le64(cifsi->vfs_inode.i_ctime.tv_se= c); + cd->last_change_time_nsec =3D cpu_to_le32(cifsi->vfs_inode.i_ctime.tv_ns= ec); +} + = -extern void __cifs_fscache_invalidate_page(struct page *, struct inode *)= ; -extern void __cifs_fscache_wait_on_page_write(struct inode *inode, struct= page *page); -extern void __cifs_fscache_uncache_page(struct inode *inode, struct page = *page); extern int cifs_fscache_release_page(struct page *page, gfp_t gfp); extern int __cifs_readpage_from_fscache(struct inode *, struct page *); extern int __cifs_readpages_from_fscache(struct inode *, struct address_space *, struct list_head *, unsigned *); -extern void __cifs_fscache_readpages_cancel(struct inode *, struct list_h= ead *); - extern void __cifs_readpage_to_fscache(struct inode *, struct page *); = -static inline void cifs_fscache_invalidate_page(struct page *page, - struct inode *inode) +static inline struct fscache_cookie *cifs_inode_cookie(struct inode *inod= e) { - if (PageFsCache(page)) - __cifs_fscache_invalidate_page(page, inode); -} - -static inline void cifs_fscache_wait_on_page_write(struct inode *inode, - struct page *page) -{ - if (PageFsCache(page)) - __cifs_fscache_wait_on_page_write(inode, page); -} - -static inline void cifs_fscache_uncache_page(struct inode *inode, - struct page *page) -{ - if (PageFsCache(page)) - __cifs_fscache_uncache_page(inode, page); + return CIFS_I(inode)->fscache; } = static inline int cifs_readpage_from_fscache(struct inode *inode, @@ -120,41 +98,20 @@ static inline void cifs_readpage_to_fscache(struct in= ode *inode, __cifs_readpage_to_fscache(inode, page); } = -static inline void cifs_fscache_readpages_cancel(struct inode *inode, - struct list_head *pages) +#else /* CONFIG_CIFS_FSCACHE */ +static inline +void cifs_fscache_fill_coherency(struct inode *inode, + struct cifs_fscache_inode_coherency_data *cd) { - if (CIFS_I(inode)->fscache) - return __cifs_fscache_readpages_cancel(inode, pages); } = -#else /* CONFIG_CIFS_FSCACHE */ -static inline int cifs_fscache_register(void) { return 0; } -static inline void cifs_fscache_unregister(void) {} - -static inline void -cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) {} -static inline void -cifs_fscache_release_client_cookie(struct TCP_Server_Info *server) {} -static inline void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) = {} -static inline void -cifs_fscache_release_super_cookie(struct cifs_tcon *tcon) {} +static inline int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) {= return 0; } +static inline void cifs_fscache_release_super_cookie(struct cifs_tcon *tc= on) {} = +static inline void cifs_fscache_get_inode_cookie(struct inode *inode) {} static inline void cifs_fscache_release_inode_cookie(struct inode *inode)= {} -static inline void cifs_fscache_update_inode_cookie(struct inode *inode) = {} -static inline void cifs_fscache_set_inode_cookie(struct inode *inode, - struct file *filp) {} -static inline void cifs_fscache_reset_inode_cookie(struct inode *inode) {= } -static inline int cifs_fscache_release_page(struct page *page, gfp_t gfp) -{ - return 1; /* May release page */ -} - -static inline void cifs_fscache_invalidate_page(struct page *page, - struct inode *inode) {} -static inline void cifs_fscache_wait_on_page_write(struct inode *inode, - struct page *page) {} -static inline void cifs_fscache_uncache_page(struct inode *inode, - struct page *page) {} +static inline void cifs_fscache_unuse_inode_cookie(struct inode *inode, b= ool update) {} +static inline struct fscache_cookie *cifs_inode_cookie(struct inode *inod= e) { return NULL; } = static inline int cifs_readpage_from_fscache(struct inode *inode, struct page *page) @@ -173,11 +130,6 @@ static inline int cifs_readpages_from_fscache(struct = inode *inode, static inline void cifs_readpage_to_fscache(struct inode *inode, struct page *page) {} = -static inline void cifs_fscache_readpages_cancel(struct inode *inode, - struct list_head *pages) -{ -} - #endif /* CONFIG_CIFS_FSCACHE */ = #endif /* _CIFS_FSCACHE_H */ diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 96d083db1737..b29e651edb21 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1298,10 +1298,7 @@ cifs_iget(struct super_block *sb, struct cifs_fattr= *fattr) inode->i_flags |=3D S_NOATIME | S_NOCMTIME; if (inode->i_state & I_NEW) { inode->i_ino =3D hash; -#ifdef CONFIG_CIFS_FSCACHE - /* initialize per-inode cache cookie pointer */ - CIFS_I(inode)->fscache =3D NULL; -#endif + cifs_fscache_get_inode_cookie(inode); unlock_new_inode(inode); } } @@ -1376,12 +1373,19 @@ struct inode *cifs_root_iget(struct super_block *s= b) inode =3D ERR_PTR(rc); } = - /* - * The cookie is initialized from volume info returned above. - * Inside cifs_fscache_get_super_cookie it checks - * that we do not get super cookie twice. - */ - cifs_fscache_get_super_cookie(tcon); + if (!rc && + (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE)) { + /* + * The cookie is initialized from volume info returned above. + * Inside cifs_fscache_get_super_cookie it checks + * that we do not get super cookie twice. + */ + rc =3D cifs_fscache_get_super_cookie(tcon); + if (rc < 0) { + iget_failed(inode); + inode =3D ERR_PTR(rc); + } + } = out: kfree(path); @@ -2270,6 +2274,8 @@ cifs_dentry_needs_reval(struct dentry *dentry) int cifs_invalidate_mapping(struct inode *inode) { + struct cifs_fscache_inode_coherency_data cd; + struct cifsInodeInfo *cifsi =3D CIFS_I(inode); int rc =3D 0; = if (inode->i_mapping && inode->i_mapping->nrpages !=3D 0) { @@ -2279,7 +2285,8 @@ cifs_invalidate_mapping(struct inode *inode) __func__, inode); } = - cifs_fscache_reset_inode_cookie(inode); + cifs_fscache_fill_coherency(&cifsi->vfs_inode, &cd); + fscache_invalidate(cifs_inode_cookie(inode), &cd, i_size_read(inode), 0)= ; return rc; } = @@ -2784,8 +2791,10 @@ cifs_setattr_unix(struct dentry *direntry, struct i= attr *attrs) goto out; = if ((attrs->ia_valid & ATTR_SIZE) && - attrs->ia_size !=3D i_size_read(inode)) + attrs->ia_size !=3D i_size_read(inode)) { truncate_setsize(inode, attrs->ia_size); + fscache_resize_cookie(cifs_inode_cookie(inode), attrs->ia_size); + } = setattr_copy(&init_user_ns, inode, attrs); mark_inode_dirty(inode); @@ -2980,8 +2989,10 @@ cifs_setattr_nounix(struct dentry *direntry, struct= iattr *attrs) goto cifs_setattr_exit; = if ((attrs->ia_valid & ATTR_SIZE) && - attrs->ia_size !=3D i_size_read(inode)) + attrs->ia_size !=3D i_size_read(inode)) { truncate_setsize(inode, attrs->ia_size); + fscache_resize_cookie(cifs_inode_cookie(inode), attrs->ia_size); + } = setattr_copy(&init_user_ns, inode, attrs); mark_inode_dirty(inode);