0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "fscache.h"
0010 #include "cifsglob.h"
0011 #include "cifs_debug.h"
0012 #include "cifs_fs_sb.h"
0013 #include "cifsproto.h"
0014
0015 static void cifs_fscache_fill_volume_coherency(
0016 struct cifs_tcon *tcon,
0017 struct cifs_fscache_volume_coherency_data *cd)
0018 {
0019 memset(cd, 0, sizeof(*cd));
0020 cd->resource_id = cpu_to_le64(tcon->resource_id);
0021 cd->vol_create_time = tcon->vol_create_time;
0022 cd->vol_serial_number = cpu_to_le32(tcon->vol_serial_number);
0023 }
0024
0025 int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
0026 {
0027 struct cifs_fscache_volume_coherency_data cd;
0028 struct TCP_Server_Info *server = tcon->ses->server;
0029 struct fscache_volume *vcookie;
0030 const struct sockaddr *sa = (struct sockaddr *)&server->dstaddr;
0031 size_t slen, i;
0032 char *sharename;
0033 char *key;
0034 int ret = -ENOMEM;
0035
0036 tcon->fscache = NULL;
0037 switch (sa->sa_family) {
0038 case AF_INET:
0039 case AF_INET6:
0040 break;
0041 default:
0042 cifs_dbg(VFS, "Unknown network family '%d'\n", sa->sa_family);
0043 return -EINVAL;
0044 }
0045
0046 memset(&key, 0, sizeof(key));
0047
0048 sharename = extract_sharename(tcon->treeName);
0049 if (IS_ERR(sharename)) {
0050 cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__);
0051 return -EINVAL;
0052 }
0053
0054 slen = strlen(sharename);
0055 for (i = 0; i < slen; i++)
0056 if (sharename[i] == '/')
0057 sharename[i] = ';';
0058
0059 key = kasprintf(GFP_KERNEL, "cifs,%pISpc,%s", sa, sharename);
0060 if (!key)
0061 goto out;
0062
0063 cifs_fscache_fill_volume_coherency(tcon, &cd);
0064 vcookie = fscache_acquire_volume(key,
0065 NULL,
0066 &cd, sizeof(cd));
0067 cifs_dbg(FYI, "%s: (%s/0x%p)\n", __func__, key, vcookie);
0068 if (IS_ERR(vcookie)) {
0069 if (vcookie != ERR_PTR(-EBUSY)) {
0070 ret = PTR_ERR(vcookie);
0071 goto out_2;
0072 }
0073 pr_err("Cache volume key already in use (%s)\n", key);
0074 vcookie = NULL;
0075 }
0076
0077 tcon->fscache = vcookie;
0078 ret = 0;
0079 out_2:
0080 kfree(key);
0081 out:
0082 kfree(sharename);
0083 return ret;
0084 }
0085
0086 void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon)
0087 {
0088 struct cifs_fscache_volume_coherency_data cd;
0089
0090 cifs_dbg(FYI, "%s: (0x%p)\n", __func__, tcon->fscache);
0091
0092 cifs_fscache_fill_volume_coherency(tcon, &cd);
0093 fscache_relinquish_volume(tcon->fscache, &cd, false);
0094 tcon->fscache = NULL;
0095 }
0096
0097 void cifs_fscache_get_inode_cookie(struct inode *inode)
0098 {
0099 struct cifs_fscache_inode_coherency_data cd;
0100 struct cifsInodeInfo *cifsi = CIFS_I(inode);
0101 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
0102 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
0103
0104 cifs_fscache_fill_coherency(&cifsi->netfs.inode, &cd);
0105
0106 cifsi->netfs.cache =
0107 fscache_acquire_cookie(tcon->fscache, 0,
0108 &cifsi->uniqueid, sizeof(cifsi->uniqueid),
0109 &cd, sizeof(cd),
0110 i_size_read(&cifsi->netfs.inode));
0111 }
0112
0113 void cifs_fscache_unuse_inode_cookie(struct inode *inode, bool update)
0114 {
0115 if (update) {
0116 struct cifs_fscache_inode_coherency_data cd;
0117 loff_t i_size = i_size_read(inode);
0118
0119 cifs_fscache_fill_coherency(inode, &cd);
0120 fscache_unuse_cookie(cifs_inode_cookie(inode), &cd, &i_size);
0121 } else {
0122 fscache_unuse_cookie(cifs_inode_cookie(inode), NULL, NULL);
0123 }
0124 }
0125
0126 void cifs_fscache_release_inode_cookie(struct inode *inode)
0127 {
0128 struct cifsInodeInfo *cifsi = CIFS_I(inode);
0129 struct fscache_cookie *cookie = cifs_inode_cookie(inode);
0130
0131 if (cookie) {
0132 cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cookie);
0133 fscache_relinquish_cookie(cookie, false);
0134 cifsi->netfs.cache = NULL;
0135 }
0136 }
0137
0138
0139
0140
0141 static int fscache_fallback_read_page(struct inode *inode, struct page *page)
0142 {
0143 struct netfs_cache_resources cres;
0144 struct fscache_cookie *cookie = cifs_inode_cookie(inode);
0145 struct iov_iter iter;
0146 struct bio_vec bvec[1];
0147 int ret;
0148
0149 memset(&cres, 0, sizeof(cres));
0150 bvec[0].bv_page = page;
0151 bvec[0].bv_offset = 0;
0152 bvec[0].bv_len = PAGE_SIZE;
0153 iov_iter_bvec(&iter, READ, bvec, ARRAY_SIZE(bvec), PAGE_SIZE);
0154
0155 ret = fscache_begin_read_operation(&cres, cookie);
0156 if (ret < 0)
0157 return ret;
0158
0159 ret = fscache_read(&cres, page_offset(page), &iter, NETFS_READ_HOLE_FAIL,
0160 NULL, NULL);
0161 fscache_end_operation(&cres);
0162 return ret;
0163 }
0164
0165
0166
0167
0168 static int fscache_fallback_write_page(struct inode *inode, struct page *page,
0169 bool no_space_allocated_yet)
0170 {
0171 struct netfs_cache_resources cres;
0172 struct fscache_cookie *cookie = cifs_inode_cookie(inode);
0173 struct iov_iter iter;
0174 struct bio_vec bvec[1];
0175 loff_t start = page_offset(page);
0176 size_t len = PAGE_SIZE;
0177 int ret;
0178
0179 memset(&cres, 0, sizeof(cres));
0180 bvec[0].bv_page = page;
0181 bvec[0].bv_offset = 0;
0182 bvec[0].bv_len = PAGE_SIZE;
0183 iov_iter_bvec(&iter, WRITE, bvec, ARRAY_SIZE(bvec), PAGE_SIZE);
0184
0185 ret = fscache_begin_write_operation(&cres, cookie);
0186 if (ret < 0)
0187 return ret;
0188
0189 ret = cres.ops->prepare_write(&cres, &start, &len, i_size_read(inode),
0190 no_space_allocated_yet);
0191 if (ret == 0)
0192 ret = fscache_write(&cres, page_offset(page), &iter, NULL, NULL);
0193 fscache_end_operation(&cres);
0194 return ret;
0195 }
0196
0197
0198
0199
0200 int __cifs_readpage_from_fscache(struct inode *inode, struct page *page)
0201 {
0202 int ret;
0203
0204 cifs_dbg(FYI, "%s: (fsc:%p, p:%p, i:0x%p\n",
0205 __func__, cifs_inode_cookie(inode), page, inode);
0206
0207 ret = fscache_fallback_read_page(inode, page);
0208 if (ret < 0)
0209 return ret;
0210
0211
0212 SetPageUptodate(page);
0213 return 0;
0214 }
0215
0216 void __cifs_readpage_to_fscache(struct inode *inode, struct page *page)
0217 {
0218 cifs_dbg(FYI, "%s: (fsc: %p, p: %p, i: %p)\n",
0219 __func__, cifs_inode_cookie(inode), page, inode);
0220
0221 fscache_fallback_write_page(inode, page, true);
0222 }
0223
0224
0225
0226
0227 int __cifs_fscache_query_occupancy(struct inode *inode,
0228 pgoff_t first, unsigned int nr_pages,
0229 pgoff_t *_data_first,
0230 unsigned int *_data_nr_pages)
0231 {
0232 struct netfs_cache_resources cres;
0233 struct fscache_cookie *cookie = cifs_inode_cookie(inode);
0234 loff_t start, data_start;
0235 size_t len, data_len;
0236 int ret;
0237
0238 ret = fscache_begin_read_operation(&cres, cookie);
0239 if (ret < 0)
0240 return ret;
0241
0242 start = first * PAGE_SIZE;
0243 len = nr_pages * PAGE_SIZE;
0244 ret = cres.ops->query_occupancy(&cres, start, len, PAGE_SIZE,
0245 &data_start, &data_len);
0246 if (ret == 0) {
0247 *_data_first = data_start / PAGE_SIZE;
0248 *_data_nr_pages = len / PAGE_SIZE;
0249 }
0250
0251 fscache_end_operation(&cres);
0252 return ret;
0253 }