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