diff options
Diffstat (limited to 'fs/cifs/misc.c')
| -rw-r--r-- | fs/cifs/misc.c | 59 | 
1 files changed, 53 insertions, 6 deletions
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 9469f1cf0b46..bb1185fff8cc 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -1,6 +1,5 @@  // SPDX-License-Identifier: LGPL-2.1  /* - *   fs/cifs/misc.c   *   *   Copyright (C) International Business Machines  Corp., 2002,2008   *   Author(s): Steve French ([email protected]) @@ -265,7 +264,8 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,  			/* Uid is not converted */  			buffer->Uid = treeCon->ses->Suid; -			buffer->Mid = get_next_mid(treeCon->ses->server); +			if (treeCon->ses->server) +				buffer->Mid = get_next_mid(treeCon->ses->server);  		}  		if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)  			buffer->Flags2 |= SMBFLG2_DFS; @@ -591,6 +591,7 @@ void cifs_put_writer(struct cifsInodeInfo *cinode)  /**   * cifs_queue_oplock_break - queue the oplock break handler for cfile + * @cfile: The file to break the oplock on   *   * This function is called from the demultiplex thread when it   * receives an oplock break for @cfile. @@ -736,7 +737,7 @@ cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode)  			if (cancel_delayed_work(&cfile->deferred)) {  				tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);  				if (tmp_list == NULL) -					continue; +					break;  				tmp_list->cfile = cfile;  				list_add_tail(&tmp_list->list, &file_head);  			} @@ -767,7 +768,7 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon)  			if (cancel_delayed_work(&cfile->deferred)) {  				tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);  				if (tmp_list == NULL) -					continue; +					break;  				tmp_list->cfile = cfile;  				list_add_tail(&tmp_list->list, &file_head);  			} @@ -781,6 +782,43 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon)  		kfree(tmp_list);  	}  } +void +cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, const char *path) +{ +	struct cifsFileInfo *cfile; +	struct list_head *tmp; +	struct file_list *tmp_list, *tmp_next_list; +	struct list_head file_head; +	void *page; +	const char *full_path; + +	INIT_LIST_HEAD(&file_head); +	page = alloc_dentry_path(); +	spin_lock(&tcon->open_file_lock); +	list_for_each(tmp, &tcon->openFileList) { +		cfile = list_entry(tmp, struct cifsFileInfo, tlist); +		full_path = build_path_from_dentry(cfile->dentry, page); +		if (strstr(full_path, path)) { +			if (delayed_work_pending(&cfile->deferred)) { +				if (cancel_delayed_work(&cfile->deferred)) { +					tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC); +					if (tmp_list == NULL) +						break; +					tmp_list->cfile = cfile; +					list_add_tail(&tmp_list->list, &file_head); +				} +			} +		} +	} +	spin_unlock(&tcon->open_file_lock); + +	list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) { +		_cifsFileInfo_put(tmp_list->cfile, true, false); +		list_del(&tmp_list->list); +		kfree(tmp_list); +	} +	free_dentry_path(page); +}  /* parses DFS refferal V3 structure   * caller is responsible for freeing target_nodes @@ -1029,6 +1067,9 @@ setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw)  /**   * cifs_alloc_hash - allocate hash and hash context together + * @name: The name of the crypto hash algo + * @shash: Where to put the pointer to the hash algo + * @sdesc: Where to put the pointer to the hash descriptor   *   * The caller has to make sure @sdesc is initialized to either NULL or   * a valid context. Both can be freed via cifs_free_hash(). @@ -1067,6 +1108,8 @@ cifs_alloc_hash(const char *name,  /**   * cifs_free_hash - free hash and hash context together + * @shash: Where to find the pointer to the hash algo + * @sdesc: Where to find the pointer to the hash descriptor   *   * Freeing a NULL hash or context is safe.   */ @@ -1082,8 +1125,10 @@ cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc)  /**   * rqst_page_get_length - obtain the length and offset for a page in smb_rqst - * Input: rqst - a smb_rqst, page - a page index for rqst - * Output: *len - the length for this page, *offset - the offset for this page + * @rqst: The request descriptor + * @page: The index of the page to query + * @len: Where to store the length for this page: + * @offset: Where to store the offset for this page   */  void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page,  				unsigned int *len, unsigned int *offset) @@ -1116,6 +1161,8 @@ void extract_unc_hostname(const char *unc, const char **h, size_t *len)  /**   * copy_path_name - copy src path to dst, possibly truncating + * @dst: The destination buffer + * @src: The source name   *   * returns number of bytes written (including trailing nul)   */  |