|
|
|
@@ -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 */
|
|
|
|
|