diff options
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 169 |
1 files changed, 95 insertions, 74 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index df959bae6728..5630282f2821 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -5418,79 +5418,6 @@ setPermsRetry: return rc; } -int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, - const int notify_subdirs, const __u16 netfid, - __u32 filter, struct file *pfile, int multishot, - const struct nls_table *nls_codepage) -{ - int rc = 0; - struct smb_com_transaction_change_notify_req *pSMB = NULL; - struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL; - struct dir_notify_req *dnotify_req; - int bytes_returned; - - cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid); - rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB, - (void **) &pSMBr); - if (rc) - return rc; - - pSMB->TotalParameterCount = 0 ; - pSMB->TotalDataCount = 0; - pSMB->MaxParameterCount = cpu_to_le32(2); - /* BB find exact data count max from sess structure BB */ - pSMB->MaxDataCount = 0; /* same in little endian or be */ -/* BB VERIFY verify which is correct for above BB */ - pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf - - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); - - pSMB->MaxSetupCount = 4; - pSMB->Reserved = 0; - pSMB->ParameterOffset = 0; - pSMB->DataCount = 0; - pSMB->DataOffset = 0; - pSMB->SetupCount = 4; /* single byte does not need le conversion */ - pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE); - pSMB->ParameterCount = pSMB->TotalParameterCount; - if (notify_subdirs) - pSMB->WatchTree = 1; /* one byte - no le conversion needed */ - pSMB->Reserved2 = 0; - pSMB->CompletionFilter = cpu_to_le32(filter); - pSMB->Fid = netfid; /* file handle always le */ - pSMB->ByteCount = 0; - - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *)pSMBr, &bytes_returned, - CIFS_ASYNC_OP); - if (rc) { - cFYI(1, "Error in Notify = %d", rc); - } else { - /* Add file to outstanding requests */ - /* BB change to kmem cache alloc */ - dnotify_req = kmalloc( - sizeof(struct dir_notify_req), - GFP_KERNEL); - if (dnotify_req) { - dnotify_req->Pid = pSMB->hdr.Pid; - dnotify_req->PidHigh = pSMB->hdr.PidHigh; - dnotify_req->Mid = pSMB->hdr.Mid; - dnotify_req->Tid = pSMB->hdr.Tid; - dnotify_req->Uid = pSMB->hdr.Uid; - dnotify_req->netfid = netfid; - dnotify_req->pfile = pfile; - dnotify_req->filter = filter; - dnotify_req->multishot = multishot; - spin_lock(&GlobalMid_Lock); - list_add_tail(&dnotify_req->lhead, - &GlobalDnotifyReqList); - spin_unlock(&GlobalMid_Lock); - } else - rc = -ENOMEM; - } - cifs_buf_release(pSMB); - return rc; -} - #ifdef CONFIG_CIFS_XATTR /* * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common @@ -5787,5 +5714,99 @@ SetEARetry: return rc; } - #endif + +#ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */ +/* + * Years ago the kernel added a "dnotify" function for Samba server, + * to allow network clients (such as Windows) to display updated + * lists of files in directory listings automatically when + * files are added by one user when another user has the + * same directory open on their desktop. The Linux cifs kernel + * client hooked into the kernel side of this interface for + * the same reason, but ironically when the VFS moved from + * "dnotify" to "inotify" it became harder to plug in Linux + * network file system clients (the most obvious use case + * for notify interfaces is when multiple users can update + * the contents of the same directory - exactly what network + * file systems can do) although the server (Samba) could + * still use it. For the short term we leave the worker + * function ifdeffed out (below) until inotify is fixed + * in the VFS to make it easier to plug in network file + * system clients. If inotify turns out to be permanently + * incompatible for network fs clients, we could instead simply + * expose this config flag by adding a future cifs (and smb2) notify ioctl. + */ +int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, + const int notify_subdirs, const __u16 netfid, + __u32 filter, struct file *pfile, int multishot, + const struct nls_table *nls_codepage) +{ + int rc = 0; + struct smb_com_transaction_change_notify_req *pSMB = NULL; + struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL; + struct dir_notify_req *dnotify_req; + int bytes_returned; + + cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid); + rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB, + (void **) &pSMBr); + if (rc) + return rc; + + pSMB->TotalParameterCount = 0 ; + pSMB->TotalDataCount = 0; + pSMB->MaxParameterCount = cpu_to_le32(2); + /* BB find exact data count max from sess structure BB */ + pSMB->MaxDataCount = 0; /* same in little endian or be */ +/* BB VERIFY verify which is correct for above BB */ + pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf - + MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); + + pSMB->MaxSetupCount = 4; + pSMB->Reserved = 0; + pSMB->ParameterOffset = 0; + pSMB->DataCount = 0; + pSMB->DataOffset = 0; + pSMB->SetupCount = 4; /* single byte does not need le conversion */ + pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE); + pSMB->ParameterCount = pSMB->TotalParameterCount; + if (notify_subdirs) + pSMB->WatchTree = 1; /* one byte - no le conversion needed */ + pSMB->Reserved2 = 0; + pSMB->CompletionFilter = cpu_to_le32(filter); + pSMB->Fid = netfid; /* file handle always le */ + pSMB->ByteCount = 0; + + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, + (struct smb_hdr *)pSMBr, &bytes_returned, + CIFS_ASYNC_OP); + if (rc) { + cFYI(1, "Error in Notify = %d", rc); + } else { + /* Add file to outstanding requests */ + /* BB change to kmem cache alloc */ + dnotify_req = kmalloc( + sizeof(struct dir_notify_req), + GFP_KERNEL); + if (dnotify_req) { + dnotify_req->Pid = pSMB->hdr.Pid; + dnotify_req->PidHigh = pSMB->hdr.PidHigh; + dnotify_req->Mid = pSMB->hdr.Mid; + dnotify_req->Tid = pSMB->hdr.Tid; + dnotify_req->Uid = pSMB->hdr.Uid; + dnotify_req->netfid = netfid; + dnotify_req->pfile = pfile; + dnotify_req->filter = filter; + dnotify_req->multishot = multishot; + spin_lock(&GlobalMid_Lock); + list_add_tail(&dnotify_req->lhead, + &GlobalDnotifyReqList); + spin_unlock(&GlobalMid_Lock); + } else + rc = -ENOMEM; + } + cifs_buf_release(pSMB); + return rc; +} +#endif /* was needed for dnotify, and will be needed for inotify when VFS fix */ |