Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: [CIFS] CIFS should honour umask [CIFS] Missing flag on negprot needed for some servers to force packet signing [CIFS] whitespace cleanup part 2 [CIFS] whitespace cleanup [CIFS] fix mempool destroy done in wrong order in cifs error path [CIFS] typo in previous patch [CIFS] Fix oops on failed cifs mount (in kthread_stop)
This commit is contained in:
commit
3e2ce4dae9
10 changed files with 283 additions and 265 deletions
|
@ -7,16 +7,16 @@
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||||
* the GNU General Public License for more details.
|
* the GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
@ -39,7 +39,7 @@ cifs_dump_mem(char *label, void *data, int length)
|
||||||
char *charptr = data;
|
char *charptr = data;
|
||||||
char buf[10], line[80];
|
char buf[10], line[80];
|
||||||
|
|
||||||
printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n",
|
printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n",
|
||||||
label, length, data);
|
label, length, data);
|
||||||
for (i = 0; i < length; i += 16) {
|
for (i = 0; i < length; i += 16) {
|
||||||
line[0] = 0;
|
line[0] = 0;
|
||||||
|
@ -60,10 +60,10 @@ cifs_dump_mem(char *label, void *data, int length)
|
||||||
#ifdef CONFIG_CIFS_DEBUG2
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
void cifs_dump_detail(struct smb_hdr * smb)
|
void cifs_dump_detail(struct smb_hdr * smb)
|
||||||
{
|
{
|
||||||
cERROR(1,("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
|
cERROR(1, ("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
|
||||||
smb->Command, smb->Status.CifsError,
|
smb->Command, smb->Status.CifsError,
|
||||||
smb->Flags, smb->Flags2, smb->Mid, smb->Pid));
|
smb->Flags, smb->Flags2, smb->Mid, smb->Pid));
|
||||||
cERROR(1,("smb buf %p len %d", smb, smbCalcSize_LE(smb)));
|
cERROR(1, ("smb buf %p len %d", smb, smbCalcSize_LE(smb)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,36 +72,35 @@ void cifs_dump_mids(struct TCP_Server_Info * server)
|
||||||
struct list_head *tmp;
|
struct list_head *tmp;
|
||||||
struct mid_q_entry * mid_entry;
|
struct mid_q_entry * mid_entry;
|
||||||
|
|
||||||
if(server == NULL)
|
if (server == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cERROR(1,("Dump pending requests:"));
|
cERROR(1, ("Dump pending requests:"));
|
||||||
spin_lock(&GlobalMid_Lock);
|
spin_lock(&GlobalMid_Lock);
|
||||||
list_for_each(tmp, &server->pending_mid_q) {
|
list_for_each(tmp, &server->pending_mid_q) {
|
||||||
mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
|
mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
|
||||||
if(mid_entry) {
|
if (mid_entry) {
|
||||||
cERROR(1,("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d",
|
cERROR(1, ("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d",
|
||||||
mid_entry->midState,
|
mid_entry->midState,
|
||||||
(int)mid_entry->command,
|
(int)mid_entry->command,
|
||||||
mid_entry->pid,
|
mid_entry->pid,
|
||||||
mid_entry->tsk,
|
mid_entry->tsk,
|
||||||
mid_entry->mid));
|
mid_entry->mid));
|
||||||
#ifdef CONFIG_CIFS_STATS2
|
#ifdef CONFIG_CIFS_STATS2
|
||||||
cERROR(1,("IsLarge: %d buf: %p time rcv: %ld now: %ld",
|
cERROR(1, ("IsLarge: %d buf: %p time rcv: %ld now: %ld",
|
||||||
mid_entry->largeBuf,
|
mid_entry->largeBuf,
|
||||||
mid_entry->resp_buf,
|
mid_entry->resp_buf,
|
||||||
mid_entry->when_received,
|
mid_entry->when_received,
|
||||||
jiffies));
|
jiffies));
|
||||||
#endif /* STATS2 */
|
#endif /* STATS2 */
|
||||||
cERROR(1,("IsMult: %d IsEnd: %d", mid_entry->multiRsp,
|
cERROR(1, ("IsMult: %d IsEnd: %d", mid_entry->multiRsp,
|
||||||
mid_entry->multiEnd));
|
mid_entry->multiEnd));
|
||||||
if(mid_entry->resp_buf) {
|
if (mid_entry->resp_buf) {
|
||||||
cifs_dump_detail(mid_entry->resp_buf);
|
cifs_dump_detail(mid_entry->resp_buf);
|
||||||
cifs_dump_mem("existing buf: ",
|
cifs_dump_mem("existing buf: ",
|
||||||
mid_entry->resp_buf,
|
mid_entry->resp_buf,
|
||||||
62 /* fixme */);
|
62 /* fixme */);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
|
@ -129,9 +128,10 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
|
||||||
"Display Internal CIFS Data Structures for Debugging\n"
|
"Display Internal CIFS Data Structures for Debugging\n"
|
||||||
"---------------------------------------------------\n");
|
"---------------------------------------------------\n");
|
||||||
buf += length;
|
buf += length;
|
||||||
length = sprintf(buf,"CIFS Version %s\n",CIFS_VERSION);
|
length = sprintf(buf, "CIFS Version %s\n", CIFS_VERSION);
|
||||||
buf += length;
|
buf += length;
|
||||||
length = sprintf(buf,"Active VFS Requests: %d\n", GlobalTotalActiveXid);
|
length = sprintf(buf,
|
||||||
|
"Active VFS Requests: %d\n", GlobalTotalActiveXid);
|
||||||
buf += length;
|
buf += length;
|
||||||
length = sprintf(buf, "Servers:");
|
length = sprintf(buf, "Servers:");
|
||||||
buf += length;
|
buf += length;
|
||||||
|
@ -141,7 +141,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
|
||||||
list_for_each(tmp, &GlobalSMBSessionList) {
|
list_for_each(tmp, &GlobalSMBSessionList) {
|
||||||
i++;
|
i++;
|
||||||
ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
|
ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
|
||||||
if((ses->serverDomain == NULL) || (ses->serverOS == NULL) ||
|
if ((ses->serverDomain == NULL) || (ses->serverOS == NULL) ||
|
||||||
(ses->serverNOS == NULL)) {
|
(ses->serverNOS == NULL)) {
|
||||||
buf += sprintf(buf, "\nentry for %s not fully "
|
buf += sprintf(buf, "\nentry for %s not fully "
|
||||||
"displayed\n\t", ses->serverName);
|
"displayed\n\t", ses->serverName);
|
||||||
|
@ -149,15 +149,18 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
|
||||||
} else {
|
} else {
|
||||||
length =
|
length =
|
||||||
sprintf(buf,
|
sprintf(buf,
|
||||||
"\n%d) Name: %s Domain: %s Mounts: %d OS: %s \n\tNOS: %s\tCapability: 0x%x\n\tSMB session status: %d\t",
|
"\n%d) Name: %s Domain: %s Mounts: %d OS:"
|
||||||
|
" %s \n\tNOS: %s\tCapability: 0x%x\n\tSMB"
|
||||||
|
" session status: %d\t",
|
||||||
i, ses->serverName, ses->serverDomain,
|
i, ses->serverName, ses->serverDomain,
|
||||||
atomic_read(&ses->inUse),
|
atomic_read(&ses->inUse),
|
||||||
ses->serverOS, ses->serverNOS,
|
ses->serverOS, ses->serverNOS,
|
||||||
ses->capabilities,ses->status);
|
ses->capabilities, ses->status);
|
||||||
buf += length;
|
buf += length;
|
||||||
}
|
}
|
||||||
if(ses->server) {
|
if (ses->server) {
|
||||||
buf += sprintf(buf, "TCP status: %d\n\tLocal Users To Server: %d SecMode: 0x%x Req On Wire: %d",
|
buf += sprintf(buf, "TCP status: %d\n\tLocal Users To "
|
||||||
|
"Server: %d SecMode: 0x%x Req On Wire: %d",
|
||||||
ses->server->tcpStatus,
|
ses->server->tcpStatus,
|
||||||
atomic_read(&ses->server->socketUseCount),
|
atomic_read(&ses->server->socketUseCount),
|
||||||
ses->server->secMode,
|
ses->server->secMode,
|
||||||
|
@ -165,7 +168,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_STATS2
|
#ifdef CONFIG_CIFS_STATS2
|
||||||
buf += sprintf(buf, " In Send: %d In MaxReq Wait: %d",
|
buf += sprintf(buf, " In Send: %d In MaxReq Wait: %d",
|
||||||
atomic_read(&ses->server->inSend),
|
atomic_read(&ses->server->inSend),
|
||||||
atomic_read(&ses->server->num_waiters));
|
atomic_read(&ses->server->num_waiters));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -177,17 +180,19 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
|
||||||
mid_entry = list_entry(tmp1, struct
|
mid_entry = list_entry(tmp1, struct
|
||||||
mid_q_entry,
|
mid_q_entry,
|
||||||
qhead);
|
qhead);
|
||||||
if(mid_entry) {
|
if (mid_entry) {
|
||||||
length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p mid %d\n",
|
length = sprintf(buf,
|
||||||
mid_entry->midState,
|
"State: %d com: %d pid:"
|
||||||
(int)mid_entry->command,
|
" %d tsk: %p mid %d\n",
|
||||||
mid_entry->pid,
|
mid_entry->midState,
|
||||||
mid_entry->tsk,
|
(int)mid_entry->command,
|
||||||
mid_entry->mid);
|
mid_entry->pid,
|
||||||
|
mid_entry->tsk,
|
||||||
|
mid_entry->mid);
|
||||||
buf += length;
|
buf += length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -207,7 +212,8 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
|
||||||
dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
|
dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
|
||||||
length =
|
length =
|
||||||
sprintf(buf,
|
sprintf(buf,
|
||||||
"\n%d) %s Uses: %d Type: %s DevInfo: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d",
|
"\n%d) %s Uses: %d Type: %s DevInfo: 0x%x "
|
||||||
|
"Attributes: 0x%x\nPathComponentMax: %d Status: %d",
|
||||||
i, tcon->treeName,
|
i, tcon->treeName,
|
||||||
atomic_read(&tcon->useCount),
|
atomic_read(&tcon->useCount),
|
||||||
tcon->nativeFileSystem,
|
tcon->nativeFileSystem,
|
||||||
|
@ -215,7 +221,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
|
||||||
le32_to_cpu(tcon->fsAttrInfo.Attributes),
|
le32_to_cpu(tcon->fsAttrInfo.Attributes),
|
||||||
le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
|
le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
|
||||||
tcon->tidStatus);
|
tcon->tidStatus);
|
||||||
buf += length;
|
buf += length;
|
||||||
if (dev_type == FILE_DEVICE_DISK)
|
if (dev_type == FILE_DEVICE_DISK)
|
||||||
length = sprintf(buf, " type: DISK ");
|
length = sprintf(buf, " type: DISK ");
|
||||||
else if (dev_type == FILE_DEVICE_CD_ROM)
|
else if (dev_type == FILE_DEVICE_CD_ROM)
|
||||||
|
@ -224,7 +230,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
|
||||||
length =
|
length =
|
||||||
sprintf(buf, " type: %d ", dev_type);
|
sprintf(buf, " type: %d ", dev_type);
|
||||||
buf += length;
|
buf += length;
|
||||||
if(tcon->tidStatus == CifsNeedReconnect) {
|
if (tcon->tidStatus == CifsNeedReconnect) {
|
||||||
buf += sprintf(buf, "\tDISCONNECTED ");
|
buf += sprintf(buf, "\tDISCONNECTED ");
|
||||||
length += 14;
|
length += 14;
|
||||||
}
|
}
|
||||||
|
@ -238,9 +244,9 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
|
||||||
/* Now calculate total size of returned data */
|
/* Now calculate total size of returned data */
|
||||||
length = buf - original_buf;
|
length = buf - original_buf;
|
||||||
|
|
||||||
if(offset + count >= length)
|
if (offset + count >= length)
|
||||||
*eof = 1;
|
*eof = 1;
|
||||||
if(length < offset) {
|
if (length < offset) {
|
||||||
*eof = 1;
|
*eof = 1;
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -256,18 +262,18 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cifs_stats_write(struct file *file, const char __user *buffer,
|
cifs_stats_write(struct file *file, const char __user *buffer,
|
||||||
unsigned long count, void *data)
|
unsigned long count, void *data)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
int rc;
|
int rc;
|
||||||
struct list_head *tmp;
|
struct list_head *tmp;
|
||||||
struct cifsTconInfo *tcon;
|
struct cifsTconInfo *tcon;
|
||||||
|
|
||||||
rc = get_user(c, buffer);
|
rc = get_user(c, buffer);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
|
if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
|
||||||
read_lock(&GlobalSMBSeslock);
|
read_lock(&GlobalSMBSeslock);
|
||||||
#ifdef CONFIG_CIFS_STATS2
|
#ifdef CONFIG_CIFS_STATS2
|
||||||
atomic_set(&totBufAllocCount, 0);
|
atomic_set(&totBufAllocCount, 0);
|
||||||
|
@ -297,14 +303,14 @@ cifs_stats_write(struct file *file, const char __user *buffer,
|
||||||
read_unlock(&GlobalSMBSeslock);
|
read_unlock(&GlobalSMBSeslock);
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
|
cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
|
||||||
int count, int *eof, void *data)
|
int count, int *eof, void *data)
|
||||||
{
|
{
|
||||||
int item_length,i,length;
|
int item_length, i, length;
|
||||||
struct list_head *tmp;
|
struct list_head *tmp;
|
||||||
struct cifsTconInfo *tcon;
|
struct cifsTconInfo *tcon;
|
||||||
|
|
||||||
|
@ -314,44 +320,44 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
|
||||||
"Resources in use\nCIFS Session: %d\n",
|
"Resources in use\nCIFS Session: %d\n",
|
||||||
sesInfoAllocCount.counter);
|
sesInfoAllocCount.counter);
|
||||||
buf += length;
|
buf += length;
|
||||||
item_length =
|
item_length =
|
||||||
sprintf(buf,"Share (unique mount targets): %d\n",
|
sprintf(buf, "Share (unique mount targets): %d\n",
|
||||||
tconInfoAllocCount.counter);
|
tconInfoAllocCount.counter);
|
||||||
length += item_length;
|
length += item_length;
|
||||||
buf += item_length;
|
buf += item_length;
|
||||||
item_length =
|
item_length =
|
||||||
sprintf(buf,"SMB Request/Response Buffer: %d Pool size: %d\n",
|
sprintf(buf, "SMB Request/Response Buffer: %d Pool size: %d\n",
|
||||||
bufAllocCount.counter,
|
bufAllocCount.counter,
|
||||||
cifs_min_rcv + tcpSesAllocCount.counter);
|
cifs_min_rcv + tcpSesAllocCount.counter);
|
||||||
length += item_length;
|
length += item_length;
|
||||||
buf += item_length;
|
buf += item_length;
|
||||||
item_length =
|
item_length =
|
||||||
sprintf(buf,"SMB Small Req/Resp Buffer: %d Pool size: %d\n",
|
sprintf(buf, "SMB Small Req/Resp Buffer: %d Pool size: %d\n",
|
||||||
smBufAllocCount.counter,cifs_min_small);
|
smBufAllocCount.counter, cifs_min_small);
|
||||||
length += item_length;
|
length += item_length;
|
||||||
buf += item_length;
|
buf += item_length;
|
||||||
#ifdef CONFIG_CIFS_STATS2
|
#ifdef CONFIG_CIFS_STATS2
|
||||||
item_length = sprintf(buf, "Total Large %d Small %d Allocations\n",
|
item_length = sprintf(buf, "Total Large %d Small %d Allocations\n",
|
||||||
atomic_read(&totBufAllocCount),
|
atomic_read(&totBufAllocCount),
|
||||||
atomic_read(&totSmBufAllocCount));
|
atomic_read(&totSmBufAllocCount));
|
||||||
length += item_length;
|
length += item_length;
|
||||||
buf += item_length;
|
buf += item_length;
|
||||||
#endif /* CONFIG_CIFS_STATS2 */
|
#endif /* CONFIG_CIFS_STATS2 */
|
||||||
|
|
||||||
item_length =
|
item_length =
|
||||||
sprintf(buf,"Operations (MIDs): %d\n",
|
sprintf(buf, "Operations (MIDs): %d\n",
|
||||||
midCount.counter);
|
midCount.counter);
|
||||||
length += item_length;
|
length += item_length;
|
||||||
buf += item_length;
|
buf += item_length;
|
||||||
item_length = sprintf(buf,
|
item_length = sprintf(buf,
|
||||||
"\n%d session %d share reconnects\n",
|
"\n%d session %d share reconnects\n",
|
||||||
tcpSesReconnectCount.counter,tconInfoReconnectCount.counter);
|
tcpSesReconnectCount.counter, tconInfoReconnectCount.counter);
|
||||||
length += item_length;
|
length += item_length;
|
||||||
buf += item_length;
|
buf += item_length;
|
||||||
|
|
||||||
item_length = sprintf(buf,
|
item_length = sprintf(buf,
|
||||||
"Total vfs operations: %d maximum at one time: %d\n",
|
"Total vfs operations: %d maximum at one time: %d\n",
|
||||||
GlobalCurrentXid,GlobalMaxActiveXid);
|
GlobalCurrentXid, GlobalMaxActiveXid);
|
||||||
length += item_length;
|
length += item_length;
|
||||||
buf += item_length;
|
buf += item_length;
|
||||||
|
|
||||||
|
@ -360,10 +366,10 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
|
||||||
list_for_each(tmp, &GlobalTreeConnectionList) {
|
list_for_each(tmp, &GlobalTreeConnectionList) {
|
||||||
i++;
|
i++;
|
||||||
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
|
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
|
||||||
item_length = sprintf(buf,"\n%d) %s",i, tcon->treeName);
|
item_length = sprintf(buf, "\n%d) %s", i, tcon->treeName);
|
||||||
buf += item_length;
|
buf += item_length;
|
||||||
length += item_length;
|
length += item_length;
|
||||||
if(tcon->tidStatus == CifsNeedReconnect) {
|
if (tcon->tidStatus == CifsNeedReconnect) {
|
||||||
buf += sprintf(buf, "\tDISCONNECTED ");
|
buf += sprintf(buf, "\tDISCONNECTED ");
|
||||||
length += 14;
|
length += 14;
|
||||||
}
|
}
|
||||||
|
@ -380,15 +386,15 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
|
||||||
item_length = sprintf(buf, "\nWrites: %d Bytes: %lld",
|
item_length = sprintf(buf, "\nWrites: %d Bytes: %lld",
|
||||||
atomic_read(&tcon->num_writes),
|
atomic_read(&tcon->num_writes),
|
||||||
(long long)(tcon->bytes_written));
|
(long long)(tcon->bytes_written));
|
||||||
buf += item_length;
|
buf += item_length;
|
||||||
length += item_length;
|
length += item_length;
|
||||||
item_length = sprintf(buf,
|
item_length = sprintf(buf,
|
||||||
"\nLocks: %d HardLinks: %d Symlinks: %d",
|
"\nLocks: %d HardLinks: %d Symlinks: %d",
|
||||||
atomic_read(&tcon->num_locks),
|
atomic_read(&tcon->num_locks),
|
||||||
atomic_read(&tcon->num_hardlinks),
|
atomic_read(&tcon->num_hardlinks),
|
||||||
atomic_read(&tcon->num_symlinks));
|
atomic_read(&tcon->num_symlinks));
|
||||||
buf += item_length;
|
buf += item_length;
|
||||||
length += item_length;
|
length += item_length;
|
||||||
|
|
||||||
item_length = sprintf(buf, "\nOpens: %d Closes: %d Deletes: %d",
|
item_length = sprintf(buf, "\nOpens: %d Closes: %d Deletes: %d",
|
||||||
atomic_read(&tcon->num_opens),
|
atomic_read(&tcon->num_opens),
|
||||||
|
@ -415,12 +421,12 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
|
||||||
}
|
}
|
||||||
read_unlock(&GlobalSMBSeslock);
|
read_unlock(&GlobalSMBSeslock);
|
||||||
|
|
||||||
buf += sprintf(buf,"\n");
|
buf += sprintf(buf, "\n");
|
||||||
length++;
|
length++;
|
||||||
|
|
||||||
if(offset + count >= length)
|
if (offset + count >= length)
|
||||||
*eof = 1;
|
*eof = 1;
|
||||||
if(length < offset) {
|
if (length < offset) {
|
||||||
*eof = 1;
|
*eof = 1;
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -428,7 +434,7 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
|
||||||
}
|
}
|
||||||
if (length > count)
|
if (length > count)
|
||||||
length = count;
|
length = count;
|
||||||
|
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -547,11 +553,11 @@ cifs_proc_clean(void)
|
||||||
remove_proc_entry("MultiuserMount", proc_fs_cifs);
|
remove_proc_entry("MultiuserMount", proc_fs_cifs);
|
||||||
remove_proc_entry("OplockEnabled", proc_fs_cifs);
|
remove_proc_entry("OplockEnabled", proc_fs_cifs);
|
||||||
/* remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); */
|
/* remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); */
|
||||||
remove_proc_entry("SecurityFlags",proc_fs_cifs);
|
remove_proc_entry("SecurityFlags", proc_fs_cifs);
|
||||||
/* remove_proc_entry("PacketSigningEnabled",proc_fs_cifs); */
|
/* remove_proc_entry("PacketSigningEnabled", proc_fs_cifs); */
|
||||||
remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
|
remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
|
||||||
remove_proc_entry("Experimental",proc_fs_cifs);
|
remove_proc_entry("Experimental", proc_fs_cifs);
|
||||||
remove_proc_entry("LookupCacheEnabled",proc_fs_cifs);
|
remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
|
||||||
remove_proc_entry("cifs", proc_root_fs);
|
remove_proc_entry("cifs", proc_root_fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -590,7 +596,7 @@ cifsFYI_write(struct file *file, const char __user *buffer,
|
||||||
cifsFYI = 0;
|
cifsFYI = 0;
|
||||||
else if (c == '1' || c == 'y' || c == 'Y')
|
else if (c == '1' || c == 'y' || c == 'Y')
|
||||||
cifsFYI = 1;
|
cifsFYI = 1;
|
||||||
else if((c > '1') && (c <= '9'))
|
else if ((c > '1') && (c <= '9'))
|
||||||
cifsFYI = (int) (c - '0'); /* see cifs_debug.h for meanings */
|
cifsFYI = (int) (c - '0'); /* see cifs_debug.h for meanings */
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
@ -637,28 +643,28 @@ oplockEnabled_write(struct file *file, const char __user *buffer,
|
||||||
|
|
||||||
static int
|
static int
|
||||||
experimEnabled_read(char *page, char **start, off_t off,
|
experimEnabled_read(char *page, char **start, off_t off,
|
||||||
int count, int *eof, void *data)
|
int count, int *eof, void *data)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
len = sprintf(page, "%d\n", experimEnabled);
|
len = sprintf(page, "%d\n", experimEnabled);
|
||||||
|
|
||||||
len -= off;
|
len -= off;
|
||||||
*start = page + off;
|
*start = page + off;
|
||||||
|
|
||||||
if (len > count)
|
if (len > count)
|
||||||
len = count;
|
len = count;
|
||||||
else
|
else
|
||||||
*eof = 1;
|
*eof = 1;
|
||||||
|
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
len = 0;
|
len = 0;
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
static int
|
static int
|
||||||
experimEnabled_write(struct file *file, const char __user *buffer,
|
experimEnabled_write(struct file *file, const char __user *buffer,
|
||||||
unsigned long count, void *data)
|
unsigned long count, void *data)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -678,46 +684,46 @@ experimEnabled_write(struct file *file, const char __user *buffer,
|
||||||
|
|
||||||
static int
|
static int
|
||||||
linuxExtensionsEnabled_read(char *page, char **start, off_t off,
|
linuxExtensionsEnabled_read(char *page, char **start, off_t off,
|
||||||
int count, int *eof, void *data)
|
int count, int *eof, void *data)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
len = sprintf(page, "%d\n", linuxExtEnabled);
|
len = sprintf(page, "%d\n", linuxExtEnabled);
|
||||||
len -= off;
|
len -= off;
|
||||||
*start = page + off;
|
*start = page + off;
|
||||||
|
|
||||||
if (len > count)
|
if (len > count)
|
||||||
len = count;
|
len = count;
|
||||||
else
|
else
|
||||||
*eof = 1;
|
*eof = 1;
|
||||||
|
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
len = 0;
|
len = 0;
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
static int
|
static int
|
||||||
linuxExtensionsEnabled_write(struct file *file, const char __user *buffer,
|
linuxExtensionsEnabled_write(struct file *file, const char __user *buffer,
|
||||||
unsigned long count, void *data)
|
unsigned long count, void *data)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = get_user(c, buffer);
|
rc = get_user(c, buffer);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
if (c == '0' || c == 'n' || c == 'N')
|
if (c == '0' || c == 'n' || c == 'N')
|
||||||
linuxExtEnabled = 0;
|
linuxExtEnabled = 0;
|
||||||
else if (c == '1' || c == 'y' || c == 'Y')
|
else if (c == '1' || c == 'y' || c == 'Y')
|
||||||
linuxExtEnabled = 1;
|
linuxExtEnabled = 1;
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
lookupFlag_read(char *page, char **start, off_t off,
|
lookupFlag_read(char *page, char **start, off_t off,
|
||||||
int count, int *eof, void *data)
|
int count, int *eof, void *data)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
@ -860,15 +866,15 @@ security_flags_write(struct file *file, const char __user *buffer,
|
||||||
char flags_string[12];
|
char flags_string[12];
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
if((count < 1) || (count > 11))
|
if ((count < 1) || (count > 11))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
memset(flags_string, 0, 12);
|
memset(flags_string, 0, 12);
|
||||||
|
|
||||||
if(copy_from_user(flags_string, buffer, count))
|
if (copy_from_user(flags_string, buffer, count))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
if(count < 3) {
|
if (count < 3) {
|
||||||
/* single char or single char followed by null */
|
/* single char or single char followed by null */
|
||||||
c = flags_string[0];
|
c = flags_string[0];
|
||||||
if (c == '0' || c == 'n' || c == 'N')
|
if (c == '0' || c == 'n' || c == 'N')
|
||||||
|
@ -881,15 +887,15 @@ security_flags_write(struct file *file, const char __user *buffer,
|
||||||
|
|
||||||
flags = simple_strtoul(flags_string, NULL, 0);
|
flags = simple_strtoul(flags_string, NULL, 0);
|
||||||
|
|
||||||
cFYI(1,("sec flags 0x%x", flags));
|
cFYI(1, ("sec flags 0x%x", flags));
|
||||||
|
|
||||||
if(flags <= 0) {
|
if (flags <= 0) {
|
||||||
cERROR(1,("invalid security flags %s",flags_string));
|
cERROR(1, ("invalid security flags %s", flags_string));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(flags & ~CIFSSEC_MASK) {
|
if (flags & ~CIFSSEC_MASK) {
|
||||||
cERROR(1,("attempt to set unsupported security flags 0x%x",
|
cERROR(1, ("attempt to set unsupported security flags 0x%x",
|
||||||
flags & ~CIFSSEC_MASK));
|
flags & ~CIFSSEC_MASK));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,16 +6,16 @@
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||||
* the GNU General Public License for more details.
|
* the GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
cifs_strfromUCS_le(char *to, const __le16 * from,
|
cifs_strfromUCS_le(char *to, const __le16 * from,
|
||||||
int len, const struct nls_table *codepage)
|
int len, const struct nls_table *codepage)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -66,7 +66,7 @@ cifs_strtoUCS(__le16 * to, const char *from, int len,
|
||||||
{
|
{
|
||||||
int charlen;
|
int charlen;
|
||||||
int i;
|
int i;
|
||||||
wchar_t * wchar_to = (wchar_t *)to; /* needed to quiet sparse */
|
wchar_t * wchar_to = (wchar_t *)to; /* needed to quiet sparse */
|
||||||
|
|
||||||
for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
|
for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ cifs_strtoUCS(__le16 * to, const char *from, int len,
|
||||||
/* A question mark */
|
/* A question mark */
|
||||||
to[i] = cpu_to_le16(0x003f);
|
to[i] = cpu_to_le16(0x003f);
|
||||||
charlen = 1;
|
charlen = 1;
|
||||||
} else
|
} else
|
||||||
to[i] = cpu_to_le16(wchar_to[i]);
|
to[i] = cpu_to_le16(wchar_to[i]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -825,8 +825,8 @@ cifs_init_mids(void)
|
||||||
sizeof (struct oplock_q_entry), 0,
|
sizeof (struct oplock_q_entry), 0,
|
||||||
SLAB_HWCACHE_ALIGN, NULL, NULL);
|
SLAB_HWCACHE_ALIGN, NULL, NULL);
|
||||||
if (cifs_oplock_cachep == NULL) {
|
if (cifs_oplock_cachep == NULL) {
|
||||||
kmem_cache_destroy(cifs_mid_cachep);
|
|
||||||
mempool_destroy(cifs_mid_poolp);
|
mempool_destroy(cifs_mid_poolp);
|
||||||
|
kmem_cache_destroy(cifs_mid_cachep);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -433,8 +433,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
|
||||||
cFYI(1,("secFlags 0x%x",secFlags));
|
cFYI(1,("secFlags 0x%x",secFlags));
|
||||||
|
|
||||||
pSMB->hdr.Mid = GetNextMid(server);
|
pSMB->hdr.Mid = GetNextMid(server);
|
||||||
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
|
pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
|
||||||
if((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
|
if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
|
||||||
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
|
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
|
|
|
@ -2069,8 +2069,15 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
srvTcp->tcpStatus = CifsExiting;
|
srvTcp->tcpStatus = CifsExiting;
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
if (srvTcp->tsk) {
|
if (srvTcp->tsk) {
|
||||||
|
struct task_struct *tsk;
|
||||||
|
/* If we could verify that kthread_stop would
|
||||||
|
always wake up processes blocked in
|
||||||
|
tcp in recv_mesg then we could remove the
|
||||||
|
send_sig call */
|
||||||
send_sig(SIGKILL,srvTcp->tsk,1);
|
send_sig(SIGKILL,srvTcp->tsk,1);
|
||||||
kthread_stop(srvTcp->tsk);
|
tsk = srvTcp->tsk;
|
||||||
|
if(tsk)
|
||||||
|
kthread_stop(tsk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* If find_unc succeeded then rc == 0 so we can not end */
|
/* If find_unc succeeded then rc == 0 so we can not end */
|
||||||
|
@ -2085,8 +2092,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
/* if the socketUseCount is now zero */
|
/* if the socketUseCount is now zero */
|
||||||
if ((temp_rc == -ESHUTDOWN) &&
|
if ((temp_rc == -ESHUTDOWN) &&
|
||||||
(pSesInfo->server) && (pSesInfo->server->tsk)) {
|
(pSesInfo->server) && (pSesInfo->server->tsk)) {
|
||||||
|
struct task_struct *tsk;
|
||||||
send_sig(SIGKILL,pSesInfo->server->tsk,1);
|
send_sig(SIGKILL,pSesInfo->server->tsk,1);
|
||||||
kthread_stop(pSesInfo->server->tsk);
|
tsk = pSesInfo->server->tsk;
|
||||||
|
if (tsk)
|
||||||
|
kthread_stop(tsk);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
cFYI(1, ("No session or bad tcon"));
|
cFYI(1, ("No session or bad tcon"));
|
||||||
|
@ -3334,7 +3344,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
|
||||||
return 0;
|
return 0;
|
||||||
} else if (rc == -ESHUTDOWN) {
|
} else if (rc == -ESHUTDOWN) {
|
||||||
cFYI(1,("Waking up socket by sending it signal"));
|
cFYI(1,("Waking up socket by sending it signal"));
|
||||||
if(cifsd_task) {
|
if (cifsd_task) {
|
||||||
send_sig(SIGKILL,cifsd_task,1);
|
send_sig(SIGKILL,cifsd_task,1);
|
||||||
kthread_stop(cifsd_task);
|
kthread_stop(cifsd_task);
|
||||||
}
|
}
|
||||||
|
|
184
fs/cifs/dir.c
184
fs/cifs/dir.c
|
@ -2,7 +2,7 @@
|
||||||
* fs/cifs/dir.c
|
* fs/cifs/dir.c
|
||||||
*
|
*
|
||||||
* vfs operations that deal with dentries
|
* vfs operations that deal with dentries
|
||||||
*
|
*
|
||||||
* Copyright (C) International Business Machines Corp., 2002,2005
|
* Copyright (C) International Business Machines Corp., 2002,2005
|
||||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
*
|
*
|
||||||
|
@ -34,11 +34,12 @@
|
||||||
static void
|
static void
|
||||||
renew_parental_timestamps(struct dentry *direntry)
|
renew_parental_timestamps(struct dentry *direntry)
|
||||||
{
|
{
|
||||||
/* BB check if there is a way to get the kernel to do this or if we really need this */
|
/* BB check if there is a way to get the kernel to do this or if we
|
||||||
|
really need this */
|
||||||
do {
|
do {
|
||||||
direntry->d_time = jiffies;
|
direntry->d_time = jiffies;
|
||||||
direntry = direntry->d_parent;
|
direntry = direntry->d_parent;
|
||||||
} while (!IS_ROOT(direntry));
|
} while (!IS_ROOT(direntry));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: caller must free return buffer */
|
/* Note: caller must free return buffer */
|
||||||
|
@ -51,7 +52,7 @@ build_path_from_dentry(struct dentry *direntry)
|
||||||
char *full_path;
|
char *full_path;
|
||||||
char dirsep;
|
char dirsep;
|
||||||
|
|
||||||
if(direntry == NULL)
|
if (direntry == NULL)
|
||||||
return NULL; /* not much we can do if dentry is freed and
|
return NULL; /* not much we can do if dentry is freed and
|
||||||
we need to reopen the file after it was closed implicitly
|
we need to reopen the file after it was closed implicitly
|
||||||
when the server crashed */
|
when the server crashed */
|
||||||
|
@ -59,18 +60,18 @@ build_path_from_dentry(struct dentry *direntry)
|
||||||
dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
|
dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
|
||||||
pplen = CIFS_SB(direntry->d_sb)->prepathlen;
|
pplen = CIFS_SB(direntry->d_sb)->prepathlen;
|
||||||
cifs_bp_rename_retry:
|
cifs_bp_rename_retry:
|
||||||
namelen = pplen;
|
namelen = pplen;
|
||||||
for (temp = direntry; !IS_ROOT(temp);) {
|
for (temp = direntry; !IS_ROOT(temp);) {
|
||||||
namelen += (1 + temp->d_name.len);
|
namelen += (1 + temp->d_name.len);
|
||||||
temp = temp->d_parent;
|
temp = temp->d_parent;
|
||||||
if(temp == NULL) {
|
if (temp == NULL) {
|
||||||
cERROR(1,("corrupt dentry"));
|
cERROR(1, ("corrupt dentry"));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
full_path = kmalloc(namelen+1, GFP_KERNEL);
|
full_path = kmalloc(namelen+1, GFP_KERNEL);
|
||||||
if(full_path == NULL)
|
if (full_path == NULL)
|
||||||
return full_path;
|
return full_path;
|
||||||
full_path[namelen] = 0; /* trailing null */
|
full_path[namelen] = 0; /* trailing null */
|
||||||
for (temp = direntry; !IS_ROOT(temp);) {
|
for (temp = direntry; !IS_ROOT(temp);) {
|
||||||
|
@ -84,8 +85,8 @@ cifs_bp_rename_retry:
|
||||||
cFYI(0, ("name: %s", full_path + namelen));
|
cFYI(0, ("name: %s", full_path + namelen));
|
||||||
}
|
}
|
||||||
temp = temp->d_parent;
|
temp = temp->d_parent;
|
||||||
if(temp == NULL) {
|
if (temp == NULL) {
|
||||||
cERROR(1,("corrupt dentry"));
|
cERROR(1, ("corrupt dentry"));
|
||||||
kfree(full_path);
|
kfree(full_path);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -94,7 +95,7 @@ cifs_bp_rename_retry:
|
||||||
cERROR(1,
|
cERROR(1,
|
||||||
("did not end path lookup where expected namelen is %d",
|
("did not end path lookup where expected namelen is %d",
|
||||||
namelen));
|
namelen));
|
||||||
/* presumably this is only possible if racing with a rename
|
/* presumably this is only possible if racing with a rename
|
||||||
of one of the parent directories (we can not lock the dentries
|
of one of the parent directories (we can not lock the dentries
|
||||||
above us to prevent this, but retrying should be harmless) */
|
above us to prevent this, but retrying should be harmless) */
|
||||||
kfree(full_path);
|
kfree(full_path);
|
||||||
|
@ -106,7 +107,7 @@ cifs_bp_rename_retry:
|
||||||
since the '\' is a valid posix character so we can not switch
|
since the '\' is a valid posix character so we can not switch
|
||||||
those safely to '/' if any are found in the middle of the prepath */
|
those safely to '/' if any are found in the middle of the prepath */
|
||||||
/* BB test paths to Windows with '/' in the midst of prepath */
|
/* BB test paths to Windows with '/' in the midst of prepath */
|
||||||
strncpy(full_path,CIFS_SB(direntry->d_sb)->prepath,pplen);
|
strncpy(full_path, CIFS_SB(direntry->d_sb)->prepath, pplen);
|
||||||
return full_path;
|
return full_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,12 +148,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
pTcon = cifs_sb->tcon;
|
pTcon = cifs_sb->tcon;
|
||||||
|
|
||||||
full_path = build_path_from_dentry(direntry);
|
full_path = build_path_from_dentry(direntry);
|
||||||
if(full_path == NULL) {
|
if (full_path == NULL) {
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(nd && (nd->flags & LOOKUP_OPEN)) {
|
if (nd && (nd->flags & LOOKUP_OPEN)) {
|
||||||
int oflags = nd->intent.open.flags;
|
int oflags = nd->intent.open.flags;
|
||||||
|
|
||||||
desiredAccess = 0;
|
desiredAccess = 0;
|
||||||
|
@ -164,28 +165,29 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
write_only = TRUE;
|
write_only = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
|
if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
|
||||||
disposition = FILE_CREATE;
|
disposition = FILE_CREATE;
|
||||||
else if((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
|
else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
|
||||||
disposition = FILE_OVERWRITE_IF;
|
disposition = FILE_OVERWRITE_IF;
|
||||||
else if((oflags & O_CREAT) == O_CREAT)
|
else if ((oflags & O_CREAT) == O_CREAT)
|
||||||
disposition = FILE_OPEN_IF;
|
disposition = FILE_OPEN_IF;
|
||||||
else {
|
else {
|
||||||
cFYI(1,("Create flag not set in create function"));
|
cFYI(1, ("Create flag not set in create function"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BB add processing to set equivalent of mode - e.g. via CreateX with ACLs */
|
/* BB add processing to set equivalent of mode - e.g. via CreateX with
|
||||||
|
ACLs */
|
||||||
if (oplockEnabled)
|
if (oplockEnabled)
|
||||||
oplock = REQ_OPLOCK;
|
oplock = REQ_OPLOCK;
|
||||||
|
|
||||||
buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
|
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
|
||||||
if(buf == NULL) {
|
if (buf == NULL) {
|
||||||
kfree(full_path);
|
kfree(full_path);
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
|
if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
|
||||||
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
|
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
|
||||||
desiredAccess, CREATE_NOT_DIR,
|
desiredAccess, CREATE_NOT_DIR,
|
||||||
&fileHandle, &oplock, buf, cifs_sb->local_nls,
|
&fileHandle, &oplock, buf, cifs_sb->local_nls,
|
||||||
|
@ -193,27 +195,28 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
else
|
else
|
||||||
rc = -EIO; /* no NT SMB support fall into legacy open below */
|
rc = -EIO; /* no NT SMB support fall into legacy open below */
|
||||||
|
|
||||||
if(rc == -EIO) {
|
if (rc == -EIO) {
|
||||||
/* old server, retry the open legacy style */
|
/* old server, retry the open legacy style */
|
||||||
rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
|
rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
|
||||||
desiredAccess, CREATE_NOT_DIR,
|
desiredAccess, CREATE_NOT_DIR,
|
||||||
&fileHandle, &oplock, buf, cifs_sb->local_nls,
|
&fileHandle, &oplock, buf, cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
}
|
}
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cFYI(1, ("cifs_create returned 0x%x", rc));
|
cFYI(1, ("cifs_create returned 0x%x", rc));
|
||||||
} else {
|
} else {
|
||||||
/* If Open reported that we actually created a file
|
/* If Open reported that we actually created a file
|
||||||
then we now have to set the mode if possible */
|
then we now have to set the mode if possible */
|
||||||
if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
|
if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
|
||||||
(oplock & CIFS_CREATE_ACTION))
|
(oplock & CIFS_CREATE_ACTION)) {
|
||||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
mode &= ~current->fs->umask;
|
||||||
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||||
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
|
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
|
||||||
(__u64)current->fsuid,
|
(__u64)current->fsuid,
|
||||||
(__u64)current->fsgid,
|
(__u64)current->fsgid,
|
||||||
0 /* dev */,
|
0 /* dev */,
|
||||||
cifs_sb->local_nls,
|
cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
} else {
|
} else {
|
||||||
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
|
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
|
||||||
|
@ -221,26 +224,28 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
(__u64)-1,
|
(__u64)-1,
|
||||||
0 /* dev */,
|
0 /* dev */,
|
||||||
cifs_sb->local_nls,
|
cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
}
|
}
|
||||||
else {
|
} else {
|
||||||
/* BB implement mode setting via Windows security descriptors */
|
/* BB implement mode setting via Windows security
|
||||||
/* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
|
descriptors e.g. */
|
||||||
/* could set r/o dos attribute if mode & 0222 == 0 */
|
/* CIFSSMBWinSetPerms(xid,pTcon,path,mode,-1,-1,nls);*/
|
||||||
|
|
||||||
|
/* Could set r/o dos attribute if mode & 0222 == 0 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BB server might mask mode so we have to query for Unix case*/
|
/* BB server might mask mode so we have to query for Unix case*/
|
||||||
if (pTcon->ses->capabilities & CAP_UNIX)
|
if (pTcon->ses->capabilities & CAP_UNIX)
|
||||||
rc = cifs_get_inode_info_unix(&newinode, full_path,
|
rc = cifs_get_inode_info_unix(&newinode, full_path,
|
||||||
inode->i_sb,xid);
|
inode->i_sb, xid);
|
||||||
else {
|
else {
|
||||||
rc = cifs_get_inode_info(&newinode, full_path,
|
rc = cifs_get_inode_info(&newinode, full_path,
|
||||||
buf, inode->i_sb,xid);
|
buf, inode->i_sb, xid);
|
||||||
if(newinode) {
|
if (newinode) {
|
||||||
newinode->i_mode = mode;
|
newinode->i_mode = mode;
|
||||||
if((oplock & CIFS_CREATE_ACTION) &&
|
if ((oplock & CIFS_CREATE_ACTION) &&
|
||||||
(cifs_sb->mnt_cifs_flags &
|
(cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_SET_UID)) {
|
CIFS_MOUNT_SET_UID)) {
|
||||||
newinode->i_uid = current->fsuid;
|
newinode->i_uid = current->fsuid;
|
||||||
newinode->i_gid = current->fsgid;
|
newinode->i_gid = current->fsgid;
|
||||||
|
@ -259,14 +264,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
direntry->d_op = &cifs_dentry_ops;
|
direntry->d_op = &cifs_dentry_ops;
|
||||||
d_instantiate(direntry, newinode);
|
d_instantiate(direntry, newinode);
|
||||||
}
|
}
|
||||||
if((nd->flags & LOOKUP_OPEN) == FALSE) {
|
if ((nd->flags & LOOKUP_OPEN) == FALSE) {
|
||||||
/* mknod case - do not leave file open */
|
/* mknod case - do not leave file open */
|
||||||
CIFSSMBClose(xid, pTcon, fileHandle);
|
CIFSSMBClose(xid, pTcon, fileHandle);
|
||||||
} else if(newinode) {
|
} else if (newinode) {
|
||||||
pCifsFile =
|
pCifsFile =
|
||||||
kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
|
kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
|
||||||
|
|
||||||
if(pCifsFile == NULL)
|
if (pCifsFile == NULL)
|
||||||
goto cifs_create_out;
|
goto cifs_create_out;
|
||||||
pCifsFile->netfid = fileHandle;
|
pCifsFile->netfid = fileHandle;
|
||||||
pCifsFile->pid = current->tgid;
|
pCifsFile->pid = current->tgid;
|
||||||
|
@ -276,33 +281,33 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
init_MUTEX(&pCifsFile->fh_sem);
|
init_MUTEX(&pCifsFile->fh_sem);
|
||||||
mutex_init(&pCifsFile->lock_mutex);
|
mutex_init(&pCifsFile->lock_mutex);
|
||||||
INIT_LIST_HEAD(&pCifsFile->llist);
|
INIT_LIST_HEAD(&pCifsFile->llist);
|
||||||
atomic_set(&pCifsFile->wrtPending,0);
|
atomic_set(&pCifsFile->wrtPending, 0);
|
||||||
|
|
||||||
/* set the following in open now
|
/* set the following in open now
|
||||||
pCifsFile->pfile = file; */
|
pCifsFile->pfile = file; */
|
||||||
write_lock(&GlobalSMBSeslock);
|
write_lock(&GlobalSMBSeslock);
|
||||||
list_add(&pCifsFile->tlist,&pTcon->openFileList);
|
list_add(&pCifsFile->tlist, &pTcon->openFileList);
|
||||||
pCifsInode = CIFS_I(newinode);
|
pCifsInode = CIFS_I(newinode);
|
||||||
if(pCifsInode) {
|
if (pCifsInode) {
|
||||||
/* if readable file instance put first in list*/
|
/* if readable file instance put first in list*/
|
||||||
if (write_only == TRUE) {
|
if (write_only == TRUE) {
|
||||||
list_add_tail(&pCifsFile->flist,
|
list_add_tail(&pCifsFile->flist,
|
||||||
&pCifsInode->openFileList);
|
&pCifsInode->openFileList);
|
||||||
} else {
|
} else {
|
||||||
list_add(&pCifsFile->flist,
|
list_add(&pCifsFile->flist,
|
||||||
&pCifsInode->openFileList);
|
&pCifsInode->openFileList);
|
||||||
}
|
}
|
||||||
if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
|
if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
|
||||||
pCifsInode->clientCanCacheAll = TRUE;
|
pCifsInode->clientCanCacheAll = TRUE;
|
||||||
pCifsInode->clientCanCacheRead = TRUE;
|
pCifsInode->clientCanCacheRead = TRUE;
|
||||||
cFYI(1,("Exclusive Oplock for inode %p",
|
cFYI(1, ("Exclusive Oplock inode %p",
|
||||||
newinode));
|
newinode));
|
||||||
} else if((oplock & 0xF) == OPLOCK_READ)
|
} else if ((oplock & 0xF) == OPLOCK_READ)
|
||||||
pCifsInode->clientCanCacheRead = TRUE;
|
pCifsInode->clientCanCacheRead = TRUE;
|
||||||
}
|
}
|
||||||
write_unlock(&GlobalSMBSeslock);
|
write_unlock(&GlobalSMBSeslock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cifs_create_out:
|
cifs_create_out:
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
kfree(full_path);
|
kfree(full_path);
|
||||||
|
@ -310,8 +315,8 @@ cifs_create_out:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
|
int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
dev_t device_number)
|
dev_t device_number)
|
||||||
{
|
{
|
||||||
int rc = -EPERM;
|
int rc = -EPERM;
|
||||||
int xid;
|
int xid;
|
||||||
|
@ -329,43 +334,45 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
pTcon = cifs_sb->tcon;
|
pTcon = cifs_sb->tcon;
|
||||||
|
|
||||||
full_path = build_path_from_dentry(direntry);
|
full_path = build_path_from_dentry(direntry);
|
||||||
if(full_path == NULL)
|
if (full_path == NULL)
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
else if (pTcon->ses->capabilities & CAP_UNIX) {
|
else if (pTcon->ses->capabilities & CAP_UNIX) {
|
||||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
mode &= ~current->fs->umask;
|
||||||
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||||
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
|
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
|
||||||
mode,(__u64)current->fsuid,(__u64)current->fsgid,
|
mode, (__u64)current->fsuid,
|
||||||
|
(__u64)current->fsgid,
|
||||||
device_number, cifs_sb->local_nls,
|
device_number, cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
} else {
|
} else {
|
||||||
rc = CIFSSMBUnixSetPerms(xid, pTcon,
|
rc = CIFSSMBUnixSetPerms(xid, pTcon,
|
||||||
full_path, mode, (__u64)-1, (__u64)-1,
|
full_path, mode, (__u64)-1, (__u64)-1,
|
||||||
device_number, cifs_sb->local_nls,
|
device_number, cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!rc) {
|
if (!rc) {
|
||||||
rc = cifs_get_inode_info_unix(&newinode, full_path,
|
rc = cifs_get_inode_info_unix(&newinode, full_path,
|
||||||
inode->i_sb,xid);
|
inode->i_sb, xid);
|
||||||
if (pTcon->nocase)
|
if (pTcon->nocase)
|
||||||
direntry->d_op = &cifs_ci_dentry_ops;
|
direntry->d_op = &cifs_ci_dentry_ops;
|
||||||
else
|
else
|
||||||
direntry->d_op = &cifs_dentry_ops;
|
direntry->d_op = &cifs_dentry_ops;
|
||||||
if(rc == 0)
|
if (rc == 0)
|
||||||
d_instantiate(direntry, newinode);
|
d_instantiate(direntry, newinode);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
|
||||||
int oplock = 0;
|
int oplock = 0;
|
||||||
u16 fileHandle;
|
u16 fileHandle;
|
||||||
FILE_ALL_INFO * buf;
|
FILE_ALL_INFO * buf;
|
||||||
|
|
||||||
cFYI(1,("sfu compat create special file"));
|
cFYI(1, ("sfu compat create special file"));
|
||||||
|
|
||||||
buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
|
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
|
||||||
if(buf == NULL) {
|
if (buf == NULL) {
|
||||||
kfree(full_path);
|
kfree(full_path);
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -373,39 +380,38 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
|
|
||||||
rc = CIFSSMBOpen(xid, pTcon, full_path,
|
rc = CIFSSMBOpen(xid, pTcon, full_path,
|
||||||
FILE_CREATE, /* fail if exists */
|
FILE_CREATE, /* fail if exists */
|
||||||
GENERIC_WRITE /* BB would
|
GENERIC_WRITE /* BB would
|
||||||
WRITE_OWNER | WRITE_DAC be better? */,
|
WRITE_OWNER | WRITE_DAC be better? */,
|
||||||
/* Create a file and set the
|
/* Create a file and set the
|
||||||
file attribute to SYSTEM */
|
file attribute to SYSTEM */
|
||||||
CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
|
CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
|
||||||
&fileHandle, &oplock, buf,
|
&fileHandle, &oplock, buf,
|
||||||
cifs_sb->local_nls,
|
cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
|
|
||||||
/* BB FIXME - add handling for backlevel servers
|
/* BB FIXME - add handling for backlevel servers
|
||||||
which need legacy open and check for all
|
which need legacy open and check for all
|
||||||
calls to SMBOpen for fallback to
|
calls to SMBOpen for fallback to SMBLeagcyOpen */
|
||||||
SMBLeagcyOpen */
|
if (!rc) {
|
||||||
if(!rc) {
|
|
||||||
/* BB Do not bother to decode buf since no
|
/* BB Do not bother to decode buf since no
|
||||||
local inode yet to put timestamps in,
|
local inode yet to put timestamps in,
|
||||||
but we can reuse it safely */
|
but we can reuse it safely */
|
||||||
int bytes_written;
|
int bytes_written;
|
||||||
struct win_dev *pdev;
|
struct win_dev *pdev;
|
||||||
pdev = (struct win_dev *)buf;
|
pdev = (struct win_dev *)buf;
|
||||||
if(S_ISCHR(mode)) {
|
if (S_ISCHR(mode)) {
|
||||||
memcpy(pdev->type, "IntxCHR", 8);
|
memcpy(pdev->type, "IntxCHR", 8);
|
||||||
pdev->major =
|
pdev->major =
|
||||||
cpu_to_le64(MAJOR(device_number));
|
cpu_to_le64(MAJOR(device_number));
|
||||||
pdev->minor =
|
pdev->minor =
|
||||||
cpu_to_le64(MINOR(device_number));
|
cpu_to_le64(MINOR(device_number));
|
||||||
rc = CIFSSMBWrite(xid, pTcon,
|
rc = CIFSSMBWrite(xid, pTcon,
|
||||||
fileHandle,
|
fileHandle,
|
||||||
sizeof(struct win_dev),
|
sizeof(struct win_dev),
|
||||||
0, &bytes_written, (char *)pdev,
|
0, &bytes_written, (char *)pdev,
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
} else if(S_ISBLK(mode)) {
|
} else if (S_ISBLK(mode)) {
|
||||||
memcpy(pdev->type, "IntxBLK", 8);
|
memcpy(pdev->type, "IntxBLK", 8);
|
||||||
pdev->major =
|
pdev->major =
|
||||||
cpu_to_le64(MAJOR(device_number));
|
cpu_to_le64(MAJOR(device_number));
|
||||||
|
@ -432,7 +438,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
|
|
||||||
|
|
||||||
struct dentry *
|
struct dentry *
|
||||||
cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct nameidata *nd)
|
cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
|
||||||
|
struct nameidata *nd)
|
||||||
{
|
{
|
||||||
int xid;
|
int xid;
|
||||||
int rc = 0; /* to get around spurious gcc warning, set to zero here */
|
int rc = 0; /* to get around spurious gcc warning, set to zero here */
|
||||||
|
@ -447,8 +454,6 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
|
||||||
(" parent inode = 0x%p name is: %s and dentry = 0x%p",
|
(" parent inode = 0x%p name is: %s and dentry = 0x%p",
|
||||||
parent_dir_inode, direntry->d_name.name, direntry));
|
parent_dir_inode, direntry->d_name.name, direntry));
|
||||||
|
|
||||||
/* BB Add check of incoming data - e.g. frame not longer than maximum SMB - let server check the namelen BB */
|
|
||||||
|
|
||||||
/* check whether path exists */
|
/* check whether path exists */
|
||||||
|
|
||||||
cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
|
cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
|
||||||
|
@ -472,7 +477,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
|
||||||
deadlock in the cases (beginning of sys_rename itself)
|
deadlock in the cases (beginning of sys_rename itself)
|
||||||
in which we already have the sb rename sem */
|
in which we already have the sb rename sem */
|
||||||
full_path = build_path_from_dentry(direntry);
|
full_path = build_path_from_dentry(direntry);
|
||||||
if(full_path == NULL) {
|
if (full_path == NULL) {
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
}
|
}
|
||||||
|
@ -487,10 +492,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
|
||||||
|
|
||||||
if (pTcon->ses->capabilities & CAP_UNIX)
|
if (pTcon->ses->capabilities & CAP_UNIX)
|
||||||
rc = cifs_get_inode_info_unix(&newInode, full_path,
|
rc = cifs_get_inode_info_unix(&newInode, full_path,
|
||||||
parent_dir_inode->i_sb,xid);
|
parent_dir_inode->i_sb, xid);
|
||||||
else
|
else
|
||||||
rc = cifs_get_inode_info(&newInode, full_path, NULL,
|
rc = cifs_get_inode_info(&newInode, full_path, NULL,
|
||||||
parent_dir_inode->i_sb,xid);
|
parent_dir_inode->i_sb, xid);
|
||||||
|
|
||||||
if ((rc == 0) && (newInode != NULL)) {
|
if ((rc == 0) && (newInode != NULL)) {
|
||||||
if (pTcon->nocase)
|
if (pTcon->nocase)
|
||||||
|
@ -499,7 +504,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
|
||||||
direntry->d_op = &cifs_dentry_ops;
|
direntry->d_op = &cifs_dentry_ops;
|
||||||
d_add(direntry, newInode);
|
d_add(direntry, newInode);
|
||||||
|
|
||||||
/* since paths are not looked up by component - the parent
|
/* since paths are not looked up by component - the parent
|
||||||
directories are presumed to be good here */
|
directories are presumed to be good here */
|
||||||
renew_parental_timestamps(direntry);
|
renew_parental_timestamps(direntry);
|
||||||
|
|
||||||
|
@ -511,13 +516,13 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
|
||||||
else
|
else
|
||||||
direntry->d_op = &cifs_dentry_ops;
|
direntry->d_op = &cifs_dentry_ops;
|
||||||
d_add(direntry, NULL);
|
d_add(direntry, NULL);
|
||||||
/* if it was once a directory (but how can we tell?) we could do
|
/* if it was once a directory (but how can we tell?) we could do
|
||||||
shrink_dcache_parent(direntry); */
|
shrink_dcache_parent(direntry); */
|
||||||
} else {
|
} else {
|
||||||
cERROR(1,("Error 0x%x on cifs_get_inode_info in lookup of %s",
|
cERROR(1, ("Error 0x%x on cifs_get_inode_info in lookup of %s",
|
||||||
rc,full_path));
|
rc, full_path));
|
||||||
/* BB special case check for Access Denied - watch security
|
/* BB special case check for Access Denied - watch security
|
||||||
exposure of returning dir info implicitly via different rc
|
exposure of returning dir info implicitly via different rc
|
||||||
if file exists or not but no access BB */
|
if file exists or not but no access BB */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -538,11 +543,11 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
|
||||||
} else {
|
} else {
|
||||||
cFYI(1, ("neg dentry 0x%p name = %s",
|
cFYI(1, ("neg dentry 0x%p name = %s",
|
||||||
direntry, direntry->d_name.name));
|
direntry, direntry->d_name.name));
|
||||||
if(time_after(jiffies, direntry->d_time + HZ) ||
|
if (time_after(jiffies, direntry->d_time + HZ) ||
|
||||||
!lookupCacheEnabled) {
|
!lookupCacheEnabled) {
|
||||||
d_drop(direntry);
|
d_drop(direntry);
|
||||||
isValid = 0;
|
isValid = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return isValid;
|
return isValid;
|
||||||
|
@ -559,8 +564,7 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
|
||||||
|
|
||||||
struct dentry_operations cifs_dentry_ops = {
|
struct dentry_operations cifs_dentry_ops = {
|
||||||
.d_revalidate = cifs_d_revalidate,
|
.d_revalidate = cifs_d_revalidate,
|
||||||
/* d_delete: cifs_d_delete, *//* not needed except for debugging */
|
/* d_delete: cifs_d_delete, */ /* not needed except for debugging */
|
||||||
/* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
|
static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* fs/cifs/fcntl.c
|
* fs/cifs/fcntl.c
|
||||||
*
|
*
|
||||||
* vfs operations that deal with the file control API
|
* vfs operations that deal with the file control API
|
||||||
*
|
*
|
||||||
* Copyright (C) International Business Machines Corp., 2003,2004
|
* Copyright (C) International Business Machines Corp., 2003,2004
|
||||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
*
|
*
|
||||||
|
@ -35,35 +35,34 @@ static __u32 convert_to_cifs_notify_flags(unsigned long fcntl_notify_flags)
|
||||||
|
|
||||||
/* No way on Linux VFS to ask to monitor xattr
|
/* No way on Linux VFS to ask to monitor xattr
|
||||||
changes (and no stream support either */
|
changes (and no stream support either */
|
||||||
if(fcntl_notify_flags & DN_ACCESS) {
|
if (fcntl_notify_flags & DN_ACCESS) {
|
||||||
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
|
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
|
||||||
}
|
}
|
||||||
if(fcntl_notify_flags & DN_MODIFY) {
|
if (fcntl_notify_flags & DN_MODIFY) {
|
||||||
/* What does this mean on directories? */
|
/* What does this mean on directories? */
|
||||||
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE |
|
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE |
|
||||||
FILE_NOTIFY_CHANGE_SIZE;
|
FILE_NOTIFY_CHANGE_SIZE;
|
||||||
}
|
}
|
||||||
if(fcntl_notify_flags & DN_CREATE) {
|
if (fcntl_notify_flags & DN_CREATE) {
|
||||||
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_CREATION |
|
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_CREATION |
|
||||||
FILE_NOTIFY_CHANGE_LAST_WRITE;
|
FILE_NOTIFY_CHANGE_LAST_WRITE;
|
||||||
}
|
}
|
||||||
if(fcntl_notify_flags & DN_DELETE) {
|
if (fcntl_notify_flags & DN_DELETE) {
|
||||||
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE;
|
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE;
|
||||||
}
|
}
|
||||||
if(fcntl_notify_flags & DN_RENAME) {
|
if (fcntl_notify_flags & DN_RENAME) {
|
||||||
/* BB review this - checking various server behaviors */
|
/* BB review this - checking various server behaviors */
|
||||||
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_DIR_NAME |
|
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_DIR_NAME |
|
||||||
FILE_NOTIFY_CHANGE_FILE_NAME;
|
FILE_NOTIFY_CHANGE_FILE_NAME;
|
||||||
}
|
}
|
||||||
if(fcntl_notify_flags & DN_ATTRIB) {
|
if (fcntl_notify_flags & DN_ATTRIB) {
|
||||||
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_SECURITY |
|
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_SECURITY |
|
||||||
FILE_NOTIFY_CHANGE_ATTRIBUTES;
|
FILE_NOTIFY_CHANGE_ATTRIBUTES;
|
||||||
}
|
}
|
||||||
/* if(fcntl_notify_flags & DN_MULTISHOT) {
|
/* if (fcntl_notify_flags & DN_MULTISHOT) {
|
||||||
cifs_ntfy_flags |= ;
|
cifs_ntfy_flags |= ;
|
||||||
} */ /* BB fixme - not sure how to handle this with CIFS yet */
|
} */ /* BB fixme - not sure how to handle this with CIFS yet */
|
||||||
|
|
||||||
|
|
||||||
return cifs_ntfy_flags;
|
return cifs_ntfy_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,8 +77,7 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
|
||||||
__u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES;
|
__u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES;
|
||||||
__u16 netfid;
|
__u16 netfid;
|
||||||
|
|
||||||
|
if (experimEnabled == 0)
|
||||||
if(experimEnabled == 0)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
xid = GetXid();
|
xid = GetXid();
|
||||||
|
@ -88,21 +86,21 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
|
||||||
|
|
||||||
full_path = build_path_from_dentry(file->f_path.dentry);
|
full_path = build_path_from_dentry(file->f_path.dentry);
|
||||||
|
|
||||||
if(full_path == NULL) {
|
if (full_path == NULL) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
} else {
|
} else {
|
||||||
cFYI(1,("dir notify on file %s Arg 0x%lx",full_path,arg));
|
cFYI(1, ("dir notify on file %s Arg 0x%lx", full_path, arg));
|
||||||
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
|
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
|
||||||
GENERIC_READ | SYNCHRONIZE, 0 /* create options */,
|
GENERIC_READ | SYNCHRONIZE, 0 /* create options */,
|
||||||
&netfid, &oplock,NULL, cifs_sb->local_nls,
|
&netfid, &oplock, NULL, cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
/* BB fixme - add this handle to a notify handle list */
|
/* BB fixme - add this handle to a notify handle list */
|
||||||
if(rc) {
|
if (rc) {
|
||||||
cFYI(1,("Could not open directory for notify"));
|
cFYI(1, ("Could not open directory for notify"));
|
||||||
} else {
|
} else {
|
||||||
filter = convert_to_cifs_notify_flags(arg);
|
filter = convert_to_cifs_notify_flags(arg);
|
||||||
if(filter != 0) {
|
if (filter != 0) {
|
||||||
rc = CIFSSMBNotify(xid, pTcon,
|
rc = CIFSSMBNotify(xid, pTcon,
|
||||||
0 /* no subdirs */, netfid,
|
0 /* no subdirs */, netfid,
|
||||||
filter, file, arg & DN_MULTISHOT,
|
filter, file, arg & DN_MULTISHOT,
|
||||||
cifs_sb->local_nls);
|
cifs_sb->local_nls);
|
||||||
|
@ -113,10 +111,10 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
|
||||||
it would close automatically but may be a way
|
it would close automatically but may be a way
|
||||||
to do it easily when inode freed or when
|
to do it easily when inode freed or when
|
||||||
notify info is cleared/changed */
|
notify info is cleared/changed */
|
||||||
cFYI(1,("notify rc %d",rc));
|
cFYI(1, ("notify rc %d", rc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -986,7 +986,8 @@ mkdir_get_info:
|
||||||
* failed to get it from the server or was set bogus */
|
* failed to get it from the server or was set bogus */
|
||||||
if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
|
if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
|
||||||
direntry->d_inode->i_nlink = 2;
|
direntry->d_inode->i_nlink = 2;
|
||||||
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
|
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
|
||||||
|
mode &= ~current->fs->umask;
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||||
CIFSSMBUnixSetPerms(xid, pTcon, full_path,
|
CIFSSMBUnixSetPerms(xid, pTcon, full_path,
|
||||||
mode,
|
mode,
|
||||||
|
@ -1004,7 +1005,7 @@ mkdir_get_info:
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
}
|
}
|
||||||
else {
|
} else {
|
||||||
/* BB to be implemented via Windows secrty descriptors
|
/* BB to be implemented via Windows secrty descriptors
|
||||||
eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
|
eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
|
||||||
-1, -1, local_nls); */
|
-1, -1, local_nls); */
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
#define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2)
|
#define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2)
|
||||||
|
|
||||||
int cifs_ioctl (struct inode * inode, struct file * filep,
|
int cifs_ioctl (struct inode * inode, struct file * filep,
|
||||||
unsigned int command, unsigned long arg)
|
unsigned int command, unsigned long arg)
|
||||||
{
|
{
|
||||||
int rc = -ENOTTY; /* strange error - but the precedent */
|
int rc = -ENOTTY; /* strange error - but the precedent */
|
||||||
|
@ -47,13 +47,13 @@ int cifs_ioctl (struct inode * inode, struct file * filep,
|
||||||
|
|
||||||
xid = GetXid();
|
xid = GetXid();
|
||||||
|
|
||||||
cFYI(1,("ioctl file %p cmd %u arg %lu",filep,command,arg));
|
cFYI(1, ("ioctl file %p cmd %u arg %lu", filep, command, arg));
|
||||||
|
|
||||||
cifs_sb = CIFS_SB(inode->i_sb);
|
cifs_sb = CIFS_SB(inode->i_sb);
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_POSIX
|
#ifdef CONFIG_CIFS_POSIX
|
||||||
tcon = cifs_sb->tcon;
|
tcon = cifs_sb->tcon;
|
||||||
if(tcon)
|
if (tcon)
|
||||||
caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
|
caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
|
||||||
else {
|
else {
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
|
@ -62,24 +62,24 @@ int cifs_ioctl (struct inode * inode, struct file * filep,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_CIFS_POSIX */
|
#endif /* CONFIG_CIFS_POSIX */
|
||||||
|
|
||||||
switch(command) {
|
switch (command) {
|
||||||
case CIFS_IOC_CHECKUMOUNT:
|
case CIFS_IOC_CHECKUMOUNT:
|
||||||
cFYI(1,("User unmount attempted"));
|
cFYI(1, ("User unmount attempted"));
|
||||||
if(cifs_sb->mnt_uid == current->uid)
|
if (cifs_sb->mnt_uid == current->uid)
|
||||||
rc = 0;
|
rc = 0;
|
||||||
else {
|
else {
|
||||||
rc = -EACCES;
|
rc = -EACCES;
|
||||||
cFYI(1,("uids do not match"));
|
cFYI(1, ("uids do not match"));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#ifdef CONFIG_CIFS_POSIX
|
#ifdef CONFIG_CIFS_POSIX
|
||||||
case FS_IOC_GETFLAGS:
|
case FS_IOC_GETFLAGS:
|
||||||
if(CIFS_UNIX_EXTATTR_CAP & caps) {
|
if (CIFS_UNIX_EXTATTR_CAP & caps) {
|
||||||
if (pSMBFile == NULL)
|
if (pSMBFile == NULL)
|
||||||
break;
|
break;
|
||||||
rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid,
|
rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid,
|
||||||
&ExtAttrBits, &ExtAttrMask);
|
&ExtAttrBits, &ExtAttrMask);
|
||||||
if(rc == 0)
|
if (rc == 0)
|
||||||
rc = put_user(ExtAttrBits &
|
rc = put_user(ExtAttrBits &
|
||||||
FS_FL_USER_VISIBLE,
|
FS_FL_USER_VISIBLE,
|
||||||
(int __user *)arg);
|
(int __user *)arg);
|
||||||
|
@ -87,8 +87,8 @@ int cifs_ioctl (struct inode * inode, struct file * filep,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FS_IOC_SETFLAGS:
|
case FS_IOC_SETFLAGS:
|
||||||
if(CIFS_UNIX_EXTATTR_CAP & caps) {
|
if (CIFS_UNIX_EXTATTR_CAP & caps) {
|
||||||
if(get_user(ExtAttrBits,(int __user *)arg)) {
|
if (get_user(ExtAttrBits, (int __user *)arg)) {
|
||||||
rc = -EFAULT;
|
rc = -EFAULT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -96,16 +96,15 @@ int cifs_ioctl (struct inode * inode, struct file * filep,
|
||||||
break;
|
break;
|
||||||
/* rc= CIFSGetExtAttr(xid,tcon,pSMBFile->netfid,
|
/* rc= CIFSGetExtAttr(xid,tcon,pSMBFile->netfid,
|
||||||
extAttrBits, &ExtAttrMask);*/
|
extAttrBits, &ExtAttrMask);*/
|
||||||
|
|
||||||
}
|
}
|
||||||
cFYI(1,("set flags not implemented yet"));
|
cFYI(1, ("set flags not implemented yet"));
|
||||||
break;
|
break;
|
||||||
#endif /* CONFIG_CIFS_POSIX */
|
#endif /* CONFIG_CIFS_POSIX */
|
||||||
default:
|
default:
|
||||||
cFYI(1,("unsupported ioctl"));
|
cFYI(1, ("unsupported ioctl"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with this library; if not, write to the Free Software
|
* along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */
|
/* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */
|
||||||
|
|
Loading…
Add table
Reference in a new issue