Commit 54be1f6c authored by Paulo Alcantara's avatar Paulo Alcantara Committed by Steve French
Browse files

cifs: Add DFS cache routines



* Add new dfs_cache.[ch] files

* Add new /proc/fs/cifs/dfscache file
  - dump current cache when read
  - clear current cache when writing "0" to it

* Add delayed_work to periodically refresh cache entries

The new interface will be used for caching DFS referrals, as well as
supporting client target failover.

The DFS cache is a hashtable that maps UNC paths to cache entries.

A cache entry contains:
- the UNC path it is mapped on
- how much the the UNC path the entry consumes
- flags
- a Time-To-Live after which the entry expires
- a list of possible targets (linked lists of UNC paths)
- a "hint target" pointing the last known working target or the first
  target if none were tried. This hint lets cifs.ko remember and try
  working targets first.

* Looking for an entry in the cache is done with dfs_cache_find()
  - if no valid entries are found, a DFS query is made, stored in the
    cache and returned
  - the full target list can be copied and returned to avoid race
    conditions and looped on with the help with the
    dfs_cache_tgt_iterator

* Updating the target hint to the next target is done with
  dfs_cache_update_tgthint()

These functions have a dfs_cache_noreq_XXX() version that doesn't
fetches referrals if no entries are found. These versions don't
require the tcp/ses/tcon/cifs_sb parameters as a result.

Expired entries cannot be used and since they have a pretty short TTL
[1] in order for them to be useful for failover the DFS cache adds a
delayed work called periodically to keep them fresh.

Since we might not have available connections to issue the referral
request when refreshing we need to store volume_info structs with
credentials and other needed info to be able to connect to the right
server.

1: Windows defaults: 5mn for domain-based referrals, 30mn for regular
links

Signed-off-by: default avatarPaulo Alcantara <palcantara@suse.de>
Signed-off-by: default avatarAurelien Aptel <aaptel@suse.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent e7b602f4
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@ cifs-$(CONFIG_CIFS_ACL) += cifsacl.o

cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o

cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o
cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o dfs_cache.o

cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o

+12 −0
Original line number Diff line number Diff line
@@ -30,6 +30,9 @@
#include "cifsproto.h"
#include "cifs_debug.h"
#include "cifsfs.h"
#ifdef CONFIG_CIFS_DFS_UPCALL
#include "dfs_cache.h"
#endif
#ifdef CONFIG_CIFS_SMB_DIRECT
#include "smbdirect.h"
#endif
@@ -629,6 +632,11 @@ cifs_proc_init(void)
		    &cifs_security_flags_proc_fops);
	proc_create("LookupCacheEnabled", 0644, proc_fs_cifs,
		    &cifs_lookup_cache_proc_fops);

#ifdef CONFIG_CIFS_DFS_UPCALL
	proc_create("dfscache", 0644, proc_fs_cifs, &dfscache_proc_fops);
#endif

#ifdef CONFIG_CIFS_SMB_DIRECT
	proc_create("rdma_readwrite_threshold", 0644, proc_fs_cifs,
		&cifs_rdma_readwrite_threshold_proc_fops);
@@ -663,6 +671,10 @@ cifs_proc_clean(void)
	remove_proc_entry("SecurityFlags", proc_fs_cifs);
	remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
	remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);

#ifdef CONFIG_CIFS_DFS_UPCALL
	remove_proc_entry("dfscache", proc_fs_cifs);
#endif
#ifdef CONFIG_CIFS_SMB_DIRECT
	remove_proc_entry("rdma_readwrite_threshold", proc_fs_cifs);
	remove_proc_entry("smbd_max_frmr_depth", proc_fs_cifs);
+5 −0
Original line number Diff line number Diff line
@@ -1014,6 +1014,11 @@ struct cifs_tcon {
	struct list_head pending_opens;	/* list of incomplete opens */
	struct cached_fid crfid; /* Cached root fid */
	/* BB add field for back pointer to sb struct(s)? */
#ifdef CONFIG_CIFS_DFS_UPCALL
	char *dfs_path;
	int remap:2;
	struct list_head ulist; /* cache update list */
#endif
};

/*
+3 −0
Original line number Diff line number Diff line
@@ -527,6 +527,9 @@ extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8,
extern void
cifs_cleanup_volume_info_contents(struct smb_vol *volume_info);

extern struct TCP_Server_Info *
cifs_find_tcp_session(struct smb_vol *vol);

void cifs_readdata_release(struct kref *refcount);
int cifs_async_readv(struct cifs_readdata *rdata);
int cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid);
+1 −1
Original line number Diff line number Diff line
@@ -2295,7 +2295,7 @@ static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
	return 1;
}

static struct TCP_Server_Info *
struct TCP_Server_Info *
cifs_find_tcp_session(struct smb_vol *vol)
{
	struct TCP_Server_Info *server;
Loading