diff options
author | Suresh Jayaraman <sjayaraman@suse.de> | 2010-07-05 08:42:27 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2010-08-02 08:40:36 -0400 |
commit | d03382ce9a89dbe27cba25130f0b90c0d631d5c5 (patch) | |
tree | f2561981a606a788259ad10f0ec57f9486f85da4 /fs/cifs | |
parent | 8913007e67106597fed4b9dd3787e8dca6915a83 (diff) |
cifs: define superblock-level cache index objects and register them
Define superblock-level cache index objects (managed by cifsTconInfo structs).
Each superblock object is created in a server-level index object and in itself
an index into which inode-level objects are inserted.
The superblock object is keyed by sharename. The UniqueId/IndexNumber is used to
validate that the exported share is the same since we accessed it last time.
Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/cache.c | 109 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 4 | ||||
-rw-r--r-- | fs/cifs/connect.c | 3 | ||||
-rw-r--r-- | fs/cifs/fscache.c | 17 | ||||
-rw-r--r-- | fs/cifs/fscache.h | 6 | ||||
-rw-r--r-- | fs/cifs/inode.c | 3 |
6 files changed, 142 insertions, 0 deletions
diff --git a/fs/cifs/cache.c b/fs/cifs/cache.c index f46468fb6a90..15532abdac14 100644 --- a/fs/cifs/cache.c +++ b/fs/cifs/cache.c | |||
@@ -106,3 +106,112 @@ const struct fscache_cookie_def cifs_fscache_server_index_def = { | |||
106 | .type = FSCACHE_COOKIE_TYPE_INDEX, | 106 | .type = FSCACHE_COOKIE_TYPE_INDEX, |
107 | .get_key = cifs_server_get_key, | 107 | .get_key = cifs_server_get_key, |
108 | }; | 108 | }; |
109 | |||
110 | /* | ||
111 | * Auxiliary data attached to CIFS superblock within the cache | ||
112 | */ | ||
113 | struct cifs_fscache_super_auxdata { | ||
114 | u64 resource_id; /* unique server resource id */ | ||
115 | }; | ||
116 | |||
117 | static char *extract_sharename(const char *treename) | ||
118 | { | ||
119 | const char *src; | ||
120 | char *delim, *dst; | ||
121 | int len; | ||
122 | |||
123 | /* skip double chars at the beginning */ | ||
124 | src = treename + 2; | ||
125 | |||
126 | /* share name is always preceded by '\\' now */ | ||
127 | delim = strchr(src, '\\'); | ||
128 | if (!delim) | ||
129 | return ERR_PTR(-EINVAL); | ||
130 | delim++; | ||
131 | len = strlen(delim); | ||
132 | |||
133 | /* caller has to free the memory */ | ||
134 | dst = kstrndup(delim, len, GFP_KERNEL); | ||
135 | if (!dst) | ||
136 | return ERR_PTR(-ENOMEM); | ||
137 | |||
138 | return dst; | ||
139 | } | ||
140 | |||
141 | /* | ||
142 | * Superblock object currently keyed by share name | ||
143 | */ | ||
144 | static uint16_t cifs_super_get_key(const void *cookie_netfs_data, void *buffer, | ||
145 | uint16_t maxbuf) | ||
146 | { | ||
147 | const struct cifsTconInfo *tcon = cookie_netfs_data; | ||
148 | char *sharename; | ||
149 | uint16_t len; | ||
150 | |||
151 | sharename = extract_sharename(tcon->treeName); | ||
152 | if (IS_ERR(sharename)) { | ||
153 | cFYI(1, "CIFS: couldn't extract sharename\n"); | ||
154 | sharename = NULL; | ||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | len = strlen(sharename); | ||
159 | if (len > maxbuf) | ||
160 | return 0; | ||
161 | |||
162 | memcpy(buffer, sharename, len); | ||
163 | |||
164 | kfree(sharename); | ||
165 | |||
166 | return len; | ||
167 | } | ||
168 | |||
169 | static uint16_t | ||
170 | cifs_fscache_super_get_aux(const void *cookie_netfs_data, void *buffer, | ||
171 | uint16_t maxbuf) | ||
172 | { | ||
173 | struct cifs_fscache_super_auxdata auxdata; | ||
174 | const struct cifsTconInfo *tcon = cookie_netfs_data; | ||
175 | |||
176 | memset(&auxdata, 0, sizeof(auxdata)); | ||
177 | auxdata.resource_id = tcon->resource_id; | ||
178 | |||
179 | if (maxbuf > sizeof(auxdata)) | ||
180 | maxbuf = sizeof(auxdata); | ||
181 | |||
182 | memcpy(buffer, &auxdata, maxbuf); | ||
183 | |||
184 | return maxbuf; | ||
185 | } | ||
186 | |||
187 | static enum | ||
188 | fscache_checkaux cifs_fscache_super_check_aux(void *cookie_netfs_data, | ||
189 | const void *data, | ||
190 | uint16_t datalen) | ||
191 | { | ||
192 | struct cifs_fscache_super_auxdata auxdata; | ||
193 | const struct cifsTconInfo *tcon = cookie_netfs_data; | ||
194 | |||
195 | if (datalen != sizeof(auxdata)) | ||
196 | return FSCACHE_CHECKAUX_OBSOLETE; | ||
197 | |||
198 | memset(&auxdata, 0, sizeof(auxdata)); | ||
199 | auxdata.resource_id = tcon->resource_id; | ||
200 | |||
201 | if (memcmp(data, &auxdata, datalen) != 0) | ||
202 | return FSCACHE_CHECKAUX_OBSOLETE; | ||
203 | |||
204 | return FSCACHE_CHECKAUX_OKAY; | ||
205 | } | ||
206 | |||
207 | /* | ||
208 | * Superblock object for FS-Cache | ||
209 | */ | ||
210 | const struct fscache_cookie_def cifs_fscache_super_index_def = { | ||
211 | .name = "CIFS.super", | ||
212 | .type = FSCACHE_COOKIE_TYPE_INDEX, | ||
213 | .get_key = cifs_super_get_key, | ||
214 | .get_aux = cifs_fscache_super_get_aux, | ||
215 | .check_aux = cifs_fscache_super_check_aux, | ||
216 | }; | ||
217 | |||
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 793c8e3a0e53..a3e403e7e163 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -299,6 +299,10 @@ struct cifsTconInfo { | |||
299 | bool local_lease:1; /* check leases (only) on local system not remote */ | 299 | bool local_lease:1; /* check leases (only) on local system not remote */ |
300 | bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */ | 300 | bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */ |
301 | bool need_reconnect:1; /* connection reset, tid now invalid */ | 301 | bool need_reconnect:1; /* connection reset, tid now invalid */ |
302 | #ifdef CONFIG_CIFS_FSCACHE | ||
303 | u64 resource_id; /* server resource id */ | ||
304 | struct fscache_cookie *fscache; /* cookie for share */ | ||
305 | #endif | ||
302 | /* BB add field for back pointer to sb struct(s)? */ | 306 | /* BB add field for back pointer to sb struct(s)? */ |
303 | }; | 307 | }; |
304 | 308 | ||
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index b2063ce113ec..6e1fe3a7f27d 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -1837,6 +1837,7 @@ cifs_put_tcon(struct cifsTconInfo *tcon) | |||
1837 | _FreeXid(xid); | 1837 | _FreeXid(xid); |
1838 | 1838 | ||
1839 | tconInfoFree(tcon); | 1839 | tconInfoFree(tcon); |
1840 | cifs_fscache_release_super_cookie(tcon); | ||
1840 | cifs_put_smb_ses(ses); | 1841 | cifs_put_smb_ses(ses); |
1841 | } | 1842 | } |
1842 | 1843 | ||
@@ -1906,6 +1907,8 @@ cifs_get_tcon(struct cifsSesInfo *ses, struct smb_vol *volume_info) | |||
1906 | list_add(&tcon->tcon_list, &ses->tcon_list); | 1907 | list_add(&tcon->tcon_list, &ses->tcon_list); |
1907 | write_unlock(&cifs_tcp_ses_lock); | 1908 | write_unlock(&cifs_tcp_ses_lock); |
1908 | 1909 | ||
1910 | cifs_fscache_get_super_cookie(tcon); | ||
1911 | |||
1909 | return tcon; | 1912 | return tcon; |
1910 | 1913 | ||
1911 | out_fail: | 1914 | out_fail: |
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c index ea97b76f8aa6..eba9beb94a4c 100644 --- a/fs/cifs/fscache.c +++ b/fs/cifs/fscache.c | |||
@@ -39,3 +39,20 @@ void cifs_fscache_release_client_cookie(struct TCP_Server_Info *server) | |||
39 | server->fscache = NULL; | 39 | server->fscache = NULL; |
40 | } | 40 | } |
41 | 41 | ||
42 | void cifs_fscache_get_super_cookie(struct cifsTconInfo *tcon) | ||
43 | { | ||
44 | struct TCP_Server_Info *server = tcon->ses->server; | ||
45 | |||
46 | tcon->fscache = | ||
47 | fscache_acquire_cookie(server->fscache, | ||
48 | &cifs_fscache_super_index_def, tcon); | ||
49 | cFYI(1, "CIFS: get superblock cookie (0x%p/0x%p)", | ||
50 | server->fscache, tcon->fscache); | ||
51 | } | ||
52 | |||
53 | void cifs_fscache_release_super_cookie(struct cifsTconInfo *tcon) | ||
54 | { | ||
55 | cFYI(1, "CIFS: releasing superblock cookie (0x%p)", tcon->fscache); | ||
56 | fscache_relinquish_cookie(tcon->fscache, 0); | ||
57 | tcon->fscache = NULL; | ||
58 | } | ||
diff --git a/fs/cifs/fscache.h b/fs/cifs/fscache.h index 8972306c58a5..d2ba628b72cd 100644 --- a/fs/cifs/fscache.h +++ b/fs/cifs/fscache.h | |||
@@ -29,6 +29,7 @@ | |||
29 | 29 | ||
30 | extern struct fscache_netfs cifs_fscache_netfs; | 30 | extern struct fscache_netfs cifs_fscache_netfs; |
31 | extern const struct fscache_cookie_def cifs_fscache_server_index_def; | 31 | extern const struct fscache_cookie_def cifs_fscache_server_index_def; |
32 | extern const struct fscache_cookie_def cifs_fscache_super_index_def; | ||
32 | 33 | ||
33 | extern int cifs_fscache_register(void); | 34 | extern int cifs_fscache_register(void); |
34 | extern void cifs_fscache_unregister(void); | 35 | extern void cifs_fscache_unregister(void); |
@@ -38,6 +39,8 @@ extern void cifs_fscache_unregister(void); | |||
38 | */ | 39 | */ |
39 | extern void cifs_fscache_get_client_cookie(struct TCP_Server_Info *); | 40 | extern void cifs_fscache_get_client_cookie(struct TCP_Server_Info *); |
40 | extern void cifs_fscache_release_client_cookie(struct TCP_Server_Info *); | 41 | extern void cifs_fscache_release_client_cookie(struct TCP_Server_Info *); |
42 | extern void cifs_fscache_get_super_cookie(struct cifsTconInfo *); | ||
43 | extern void cifs_fscache_release_super_cookie(struct cifsTconInfo *); | ||
41 | 44 | ||
42 | #else /* CONFIG_CIFS_FSCACHE */ | 45 | #else /* CONFIG_CIFS_FSCACHE */ |
43 | static inline int cifs_fscache_register(void) { return 0; } | 46 | static inline int cifs_fscache_register(void) { return 0; } |
@@ -47,6 +50,9 @@ static inline void | |||
47 | cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) {} | 50 | cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) {} |
48 | static inline void | 51 | static inline void |
49 | cifs_fscache_get_client_cookie(struct TCP_Server_Info *server); {} | 52 | cifs_fscache_get_client_cookie(struct TCP_Server_Info *server); {} |
53 | static inline void cifs_fscache_get_super_cookie(struct cifsTconInfo *tcon) {} | ||
54 | static inline void | ||
55 | cifs_fscache_release_super_cookie(struct cifsTconInfo *tcon) {} | ||
50 | 56 | ||
51 | #endif /* CONFIG_CIFS_FSCACHE */ | 57 | #endif /* CONFIG_CIFS_FSCACHE */ |
52 | 58 | ||
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index fe9b2f5fb492..f884cb51622a 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -807,6 +807,9 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | |||
807 | if (!inode) | 807 | if (!inode) |
808 | return ERR_PTR(-ENOMEM); | 808 | return ERR_PTR(-ENOMEM); |
809 | 809 | ||
810 | /* populate tcon->resource_id */ | ||
811 | cifs_sb->tcon->resource_id = CIFS_I(inode)->uniqueid; | ||
812 | |||
810 | if (rc && cifs_sb->tcon->ipc) { | 813 | if (rc && cifs_sb->tcon->ipc) { |
811 | cFYI(1, "ipc connection - fake read inode"); | 814 | cFYI(1, "ipc connection - fake read inode"); |
812 | inode->i_mode |= S_IFDIR; | 815 | inode->i_mode |= S_IFDIR; |