Merge tag 'for-linus-6.1-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / fs / cifs / cached_dir.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *  Functions to handle the cached directory entries
4  *
5  *  Copyright (c) 2022, Ronnie Sahlberg <lsahlber@redhat.com>
6  */
7
8 #include "cifsglob.h"
9 #include "cifsproto.h"
10 #include "cifs_debug.h"
11 #include "smb2proto.h"
12 #include "cached_dir.h"
13
14 struct cached_fid *init_cached_dir(const char *path);
15
16 /*
17  * Open the and cache a directory handle.
18  * If error then *cfid is not initialized.
19  */
20 int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
21                     const char *path,
22                     struct cifs_sb_info *cifs_sb,
23                     bool lookup_only, struct cached_fid **ret_cfid)
24 {
25         struct cifs_ses *ses;
26         struct TCP_Server_Info *server;
27         struct cifs_open_parms oparms;
28         struct smb2_create_rsp *o_rsp = NULL;
29         struct smb2_query_info_rsp *qi_rsp = NULL;
30         int resp_buftype[2];
31         struct smb_rqst rqst[2];
32         struct kvec rsp_iov[2];
33         struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
34         struct kvec qi_iov[1];
35         int rc, flags = 0;
36         __le16 utf16_path = 0; /* Null - since an open of top of share */
37         u8 oplock = SMB2_OPLOCK_LEVEL_II;
38         struct cifs_fid *pfid;
39         struct dentry *dentry;
40         struct cached_fid *cfid;
41
42         if (tcon == NULL || tcon->nohandlecache ||
43             is_smb1_server(tcon->ses->server))
44                 return -EOPNOTSUPP;
45
46         ses = tcon->ses;
47         server = ses->server;
48
49         if (cifs_sb->root == NULL)
50                 return -ENOENT;
51
52         if (!path[0])
53                 dentry = cifs_sb->root;
54         else
55                 return -ENOENT;
56
57         cfid = tcon->cfids->cfid;
58         if (cfid == NULL) {
59                 cfid = init_cached_dir(path);
60                 tcon->cfids->cfid = cfid;
61         }
62         if (cfid == NULL)
63                 return -ENOMEM;
64
65         mutex_lock(&cfid->fid_mutex);
66         if (cfid->is_valid) {
67                 cifs_dbg(FYI, "found a cached root file handle\n");
68                 *ret_cfid = cfid;
69                 kref_get(&cfid->refcount);
70                 mutex_unlock(&cfid->fid_mutex);
71                 return 0;
72         }
73
74         /*
75          * We do not hold the lock for the open because in case
76          * SMB2_open needs to reconnect, it will end up calling
77          * cifs_mark_open_files_invalid() which takes the lock again
78          * thus causing a deadlock
79          */
80         mutex_unlock(&cfid->fid_mutex);
81
82         if (lookup_only)
83                 return -ENOENT;
84
85         if (smb3_encryption_required(tcon))
86                 flags |= CIFS_TRANSFORM_REQ;
87
88         if (!server->ops->new_lease_key)
89                 return -EIO;
90
91         pfid = &cfid->fid;
92         server->ops->new_lease_key(pfid);
93
94         memset(rqst, 0, sizeof(rqst));
95         resp_buftype[0] = resp_buftype[1] = CIFS_NO_BUFFER;
96         memset(rsp_iov, 0, sizeof(rsp_iov));
97
98         /* Open */
99         memset(&open_iov, 0, sizeof(open_iov));
100         rqst[0].rq_iov = open_iov;
101         rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
102
103         oparms.tcon = tcon;
104         oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_FILE);
105         oparms.desired_access = FILE_READ_ATTRIBUTES;
106         oparms.disposition = FILE_OPEN;
107         oparms.fid = pfid;
108         oparms.reconnect = false;
109
110         rc = SMB2_open_init(tcon, server,
111                             &rqst[0], &oplock, &oparms, &utf16_path);
112         if (rc)
113                 goto oshr_free;
114         smb2_set_next_command(tcon, &rqst[0]);
115
116         memset(&qi_iov, 0, sizeof(qi_iov));
117         rqst[1].rq_iov = qi_iov;
118         rqst[1].rq_nvec = 1;
119
120         rc = SMB2_query_info_init(tcon, server,
121                                   &rqst[1], COMPOUND_FID,
122                                   COMPOUND_FID, FILE_ALL_INFORMATION,
123                                   SMB2_O_INFO_FILE, 0,
124                                   sizeof(struct smb2_file_all_info) +
125                                   PATH_MAX * 2, 0, NULL);
126         if (rc)
127                 goto oshr_free;
128
129         smb2_set_related(&rqst[1]);
130
131         rc = compound_send_recv(xid, ses, server,
132                                 flags, 2, rqst,
133                                 resp_buftype, rsp_iov);
134         mutex_lock(&cfid->fid_mutex);
135
136         /*
137          * Now we need to check again as the cached root might have
138          * been successfully re-opened from a concurrent process
139          */
140
141         if (cfid->is_valid) {
142                 /* work was already done */
143
144                 /* stash fids for close() later */
145                 struct cifs_fid fid = {
146                         .persistent_fid = pfid->persistent_fid,
147                         .volatile_fid = pfid->volatile_fid,
148                 };
149
150                 /*
151                  * caller expects this func to set the fid in cfid to valid
152                  * cached root, so increment the refcount.
153                  */
154                 kref_get(&cfid->refcount);
155
156                 mutex_unlock(&cfid->fid_mutex);
157
158                 if (rc == 0) {
159                         /* close extra handle outside of crit sec */
160                         SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
161                 }
162                 rc = 0;
163                 goto oshr_free;
164         }
165
166         /* Cached root is still invalid, continue normaly */
167
168         if (rc) {
169                 if (rc == -EREMCHG) {
170                         tcon->need_reconnect = true;
171                         pr_warn_once("server share %s deleted\n",
172                                      tcon->tree_name);
173                 }
174                 goto oshr_exit;
175         }
176
177         atomic_inc(&tcon->num_remote_opens);
178
179         o_rsp = (struct smb2_create_rsp *)rsp_iov[0].iov_base;
180         oparms.fid->persistent_fid = o_rsp->PersistentFileId;
181         oparms.fid->volatile_fid = o_rsp->VolatileFileId;
182 #ifdef CONFIG_CIFS_DEBUG2
183         oparms.fid->mid = le64_to_cpu(o_rsp->hdr.MessageId);
184 #endif /* CIFS_DEBUG2 */
185
186         cfid->tcon = tcon;
187         cfid->is_valid = true;
188         cfid->dentry = dentry;
189         if (dentry)
190                 dget(dentry);
191         kref_init(&cfid->refcount);
192
193         /* BB TBD check to see if oplock level check can be removed below */
194         if (o_rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) {
195                 /*
196                  * See commit 2f94a3125b87. Increment the refcount when we
197                  * get a lease for root, release it if lease break occurs
198                  */
199                 kref_get(&cfid->refcount);
200                 cfid->has_lease = true;
201                 smb2_parse_contexts(server, o_rsp,
202                                 &oparms.fid->epoch,
203                                     oparms.fid->lease_key, &oplock,
204                                     NULL, NULL);
205         } else
206                 goto oshr_exit;
207
208         qi_rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base;
209         if (le32_to_cpu(qi_rsp->OutputBufferLength) < sizeof(struct smb2_file_all_info))
210                 goto oshr_exit;
211         if (!smb2_validate_and_copy_iov(
212                                 le16_to_cpu(qi_rsp->OutputBufferOffset),
213                                 sizeof(struct smb2_file_all_info),
214                                 &rsp_iov[1], sizeof(struct smb2_file_all_info),
215                                 (char *)&cfid->file_all_info))
216                 cfid->file_all_info_is_valid = true;
217
218         cfid->time = jiffies;
219
220 oshr_exit:
221         mutex_unlock(&cfid->fid_mutex);
222 oshr_free:
223         SMB2_open_free(&rqst[0]);
224         SMB2_query_info_free(&rqst[1]);
225         free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
226         free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
227         if (rc == 0)
228                 *ret_cfid = cfid;
229
230         return rc;
231 }
232
233 int open_cached_dir_by_dentry(struct cifs_tcon *tcon,
234                               struct dentry *dentry,
235                               struct cached_fid **ret_cfid)
236 {
237         struct cached_fid *cfid;
238
239         cfid = tcon->cfids->cfid;
240         if (cfid == NULL)
241                 return -ENOENT;
242
243         mutex_lock(&cfid->fid_mutex);
244         if (cfid->dentry == dentry) {
245                 cifs_dbg(FYI, "found a cached root file handle by dentry\n");
246                 *ret_cfid = cfid;
247                 kref_get(&cfid->refcount);
248                 mutex_unlock(&cfid->fid_mutex);
249                 return 0;
250         }
251         mutex_unlock(&cfid->fid_mutex);
252         return -ENOENT;
253 }
254
255 static void
256 smb2_close_cached_fid(struct kref *ref)
257 {
258         struct cached_fid *cfid = container_of(ref, struct cached_fid,
259                                                refcount);
260         struct cached_dirent *dirent, *q;
261
262         if (cfid->is_valid) {
263                 cifs_dbg(FYI, "clear cached root file handle\n");
264                 SMB2_close(0, cfid->tcon, cfid->fid.persistent_fid,
265                            cfid->fid.volatile_fid);
266         }
267
268         /*
269          * We only check validity above to send SMB2_close,
270          * but we still need to invalidate these entries
271          * when this function is called
272          */
273         cfid->is_valid = false;
274         cfid->file_all_info_is_valid = false;
275         cfid->has_lease = false;
276         if (cfid->dentry) {
277                 dput(cfid->dentry);
278                 cfid->dentry = NULL;
279         }
280         /*
281          * Delete all cached dirent names
282          */
283         mutex_lock(&cfid->dirents.de_mutex);
284         list_for_each_entry_safe(dirent, q, &cfid->dirents.entries, entry) {
285                 list_del(&dirent->entry);
286                 kfree(dirent->name);
287                 kfree(dirent);
288         }
289         cfid->dirents.is_valid = 0;
290         cfid->dirents.is_failed = 0;
291         cfid->dirents.ctx = NULL;
292         cfid->dirents.pos = 0;
293         mutex_unlock(&cfid->dirents.de_mutex);
294
295 }
296
297 void close_cached_dir(struct cached_fid *cfid)
298 {
299         mutex_lock(&cfid->fid_mutex);
300         kref_put(&cfid->refcount, smb2_close_cached_fid);
301         mutex_unlock(&cfid->fid_mutex);
302 }
303
304 void close_cached_dir_lease_locked(struct cached_fid *cfid)
305 {
306         if (cfid->has_lease) {
307                 cfid->has_lease = false;
308                 kref_put(&cfid->refcount, smb2_close_cached_fid);
309         }
310 }
311
312 void close_cached_dir_lease(struct cached_fid *cfid)
313 {
314         mutex_lock(&cfid->fid_mutex);
315         close_cached_dir_lease_locked(cfid);
316         mutex_unlock(&cfid->fid_mutex);
317 }
318
319 /*
320  * Called from cifs_kill_sb when we unmount a share
321  */
322 void close_all_cached_dirs(struct cifs_sb_info *cifs_sb)
323 {
324         struct rb_root *root = &cifs_sb->tlink_tree;
325         struct rb_node *node;
326         struct cached_fid *cfid;
327         struct cifs_tcon *tcon;
328         struct tcon_link *tlink;
329
330         for (node = rb_first(root); node; node = rb_next(node)) {
331                 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
332                 tcon = tlink_tcon(tlink);
333                 if (IS_ERR(tcon))
334                         continue;
335                 cfid = tcon->cfids->cfid;
336                 if (cfid == NULL)
337                         continue;
338                 mutex_lock(&cfid->fid_mutex);
339                 if (cfid->dentry) {
340                         dput(cfid->dentry);
341                         cfid->dentry = NULL;
342                 }
343                 mutex_unlock(&cfid->fid_mutex);
344         }
345 }
346
347 /*
348  * Invalidate and close all cached dirs when a TCON has been reset
349  * due to a session loss.
350  */
351 void invalidate_all_cached_dirs(struct cifs_tcon *tcon)
352 {
353         struct cached_fid *cfid = tcon->cfids->cfid;
354
355         if (cfid == NULL)
356                 return;
357
358         mutex_lock(&cfid->fid_mutex);
359         cfid->is_valid = false;
360         /* cached handle is not valid, so SMB2_CLOSE won't be sent below */
361         close_cached_dir_lease_locked(cfid);
362         memset(&cfid->fid, 0, sizeof(struct cifs_fid));
363         mutex_unlock(&cfid->fid_mutex);
364 }
365
366 static void
367 smb2_cached_lease_break(struct work_struct *work)
368 {
369         struct cached_fid *cfid = container_of(work,
370                                 struct cached_fid, lease_break);
371
372         close_cached_dir_lease(cfid);
373 }
374
375 int cached_dir_lease_break(struct cifs_tcon *tcon, __u8 lease_key[16])
376 {
377         struct cached_fid *cfid = tcon->cfids->cfid;
378
379         if (cfid == NULL)
380                 return false;
381
382         if (cfid->is_valid &&
383             !memcmp(lease_key,
384                     cfid->fid.lease_key,
385                     SMB2_LEASE_KEY_SIZE)) {
386                 cfid->time = 0;
387                 INIT_WORK(&cfid->lease_break,
388                           smb2_cached_lease_break);
389                 queue_work(cifsiod_wq,
390                            &cfid->lease_break);
391                 return true;
392         }
393         return false;
394 }
395
396 struct cached_fid *init_cached_dir(const char *path)
397 {
398         struct cached_fid *cfid;
399
400         cfid = kzalloc(sizeof(*cfid), GFP_KERNEL);
401         if (!cfid)
402                 return NULL;
403         cfid->path = kstrdup(path, GFP_KERNEL);
404         if (!cfid->path) {
405                 kfree(cfid);
406                 return NULL;
407         }
408
409         INIT_LIST_HEAD(&cfid->dirents.entries);
410         mutex_init(&cfid->dirents.de_mutex);
411         mutex_init(&cfid->fid_mutex);
412         return cfid;
413 }
414
415 void free_cached_dir(struct cached_fid *cfid)
416 {
417         kfree(cfid->path);
418         cfid->path = NULL;
419         kfree(cfid);
420 }
421
422 struct cached_fids *init_cached_dirs(void)
423 {
424         struct cached_fids *cfids;
425
426         cfids = kzalloc(sizeof(*cfids), GFP_KERNEL);
427         if (!cfids)
428                 return NULL;
429         mutex_init(&cfids->cfid_list_mutex);
430         return cfids;
431 }
432
433 void free_cached_dirs(struct cached_fids *cfids)
434 {
435         if (cfids->cfid) {
436                 free_cached_dir(cfids->cfid);
437                 cfids->cfid = NULL;
438         }
439         kfree(cfids);
440 }