brintos

brintos / linux-shallow public Read only

0
0
Text · 4.5 KiB · 01424a5 Raw
173 lines · c
1// SPDX-License-Identifier: LGPL-2.12/*3 *   CIFS filesystem cache interface4 *5 *   Copyright (c) 2010 Novell, Inc.6 *   Author(s): Suresh Jayaraman <sjayaraman@suse.de>7 *8 */9#include "fscache.h"10#include "cifsglob.h"11#include "cifs_debug.h"12#include "cifs_fs_sb.h"13#include "cifsproto.h"14 15/*16 * Key for fscache inode.  [!] Contents must match comparisons in cifs_find_inode().17 */18struct cifs_fscache_inode_key {19 20	__le64  uniqueid;	/* server inode number */21	__le64  createtime;	/* creation time on server */22	u8	type;		/* S_IFMT file type */23} __packed;24 25static void cifs_fscache_fill_volume_coherency(26	struct cifs_tcon *tcon,27	struct cifs_fscache_volume_coherency_data *cd)28{29	memset(cd, 0, sizeof(*cd));30	cd->resource_id		= cpu_to_le64(tcon->resource_id);31	cd->vol_create_time	= tcon->vol_create_time;32	cd->vol_serial_number	= cpu_to_le32(tcon->vol_serial_number);33}34 35int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)36{37	struct cifs_fscache_volume_coherency_data cd;38	struct TCP_Server_Info *server = tcon->ses->server;39	struct fscache_volume *vcookie;40	const struct sockaddr *sa = (struct sockaddr *)&server->dstaddr;41	size_t slen, i;42	char *sharename;43	char *key;44	int ret = -ENOMEM;45 46	if (tcon->fscache_acquired)47		return 0;48 49	mutex_lock(&tcon->fscache_lock);50	if (tcon->fscache_acquired) {51		mutex_unlock(&tcon->fscache_lock);52		return 0;53	}54	tcon->fscache_acquired = true;55 56	tcon->fscache = NULL;57	switch (sa->sa_family) {58	case AF_INET:59	case AF_INET6:60		break;61	default:62		mutex_unlock(&tcon->fscache_lock);63		cifs_dbg(VFS, "Unknown network family '%d'\n", sa->sa_family);64		return -EINVAL;65	}66 67	memset(&key, 0, sizeof(key));68 69	sharename = extract_sharename(tcon->tree_name);70	if (IS_ERR(sharename)) {71		mutex_unlock(&tcon->fscache_lock);72		cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__);73		return PTR_ERR(sharename);74	}75 76	slen = strlen(sharename);77	for (i = 0; i < slen; i++)78		if (sharename[i] == '/')79			sharename[i] = ';';80 81	key = kasprintf(GFP_KERNEL, "cifs,%pISpc,%s", sa, sharename);82	if (!key)83		goto out;84 85	cifs_fscache_fill_volume_coherency(tcon, &cd);86	vcookie = fscache_acquire_volume(key,87					 NULL, /* preferred_cache */88					 &cd, sizeof(cd));89	cifs_dbg(FYI, "%s: (%s/0x%p)\n", __func__, key, vcookie);90	if (IS_ERR(vcookie)) {91		if (vcookie != ERR_PTR(-EBUSY)) {92			ret = PTR_ERR(vcookie);93			goto out_2;94		}95		pr_err("Cache volume key already in use (%s)\n", key);96		vcookie = NULL;97		trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,98				    netfs_trace_tcon_ref_see_fscache_collision);99	} else {100		trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,101				    netfs_trace_tcon_ref_see_fscache_okay);102	}103 104	tcon->fscache = vcookie;105	ret = 0;106out_2:107	kfree(key);108out:109	kfree(sharename);110	mutex_unlock(&tcon->fscache_lock);111	return ret;112}113 114void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon)115{116	struct cifs_fscache_volume_coherency_data cd;117 118	cifs_dbg(FYI, "%s: (0x%p)\n", __func__, tcon->fscache);119 120	cifs_fscache_fill_volume_coherency(tcon, &cd);121	fscache_relinquish_volume(tcon->fscache, &cd, false);122	tcon->fscache = NULL;123	trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,124			    netfs_trace_tcon_ref_see_fscache_relinq);125}126 127void cifs_fscache_get_inode_cookie(struct inode *inode)128{129	struct cifs_fscache_inode_coherency_data cd;130	struct cifs_fscache_inode_key key;131	struct cifsInodeInfo *cifsi = CIFS_I(inode);132	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);133	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);134 135	key.uniqueid	= cpu_to_le64(cifsi->uniqueid);136	key.createtime	= cpu_to_le64(cifsi->createtime);137	key.type	= (inode->i_mode & S_IFMT) >> 12;138	cifs_fscache_fill_coherency(&cifsi->netfs.inode, &cd);139 140	cifsi->netfs.cache =141		fscache_acquire_cookie(tcon->fscache, 0,142				       &key, sizeof(key),143				       &cd, sizeof(cd),144				       i_size_read(&cifsi->netfs.inode));145	if (cifsi->netfs.cache)146		mapping_set_release_always(inode->i_mapping);147}148 149void cifs_fscache_unuse_inode_cookie(struct inode *inode, bool update)150{151	if (update) {152		struct cifs_fscache_inode_coherency_data cd;153		loff_t i_size = i_size_read(inode);154 155		cifs_fscache_fill_coherency(inode, &cd);156		fscache_unuse_cookie(cifs_inode_cookie(inode), &cd, &i_size);157	} else {158		fscache_unuse_cookie(cifs_inode_cookie(inode), NULL, NULL);159	}160}161 162void cifs_fscache_release_inode_cookie(struct inode *inode)163{164	struct cifsInodeInfo *cifsi = CIFS_I(inode);165	struct fscache_cookie *cookie = cifs_inode_cookie(inode);166 167	if (cookie) {168		cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cookie);169		fscache_relinquish_cookie(cookie, false);170		cifsi->netfs.cache = NULL;171	}172}173