Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 53957
b: refs/heads/master
c: 2dd29d3
h: refs/heads/master
i:
  53955: 230f448
v: v3
  • Loading branch information
Steve French committed Apr 23, 2007
1 parent f31a527 commit aada694
Show file tree
Hide file tree
Showing 6 changed files with 341 additions and 16 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5268df2ead6def933ace27ab4d46f67d2989b905
refs/heads/master: 2dd29d3133ad4c7926ea03b8431e604373c4ad65
5 changes: 4 additions & 1 deletion trunk/fs/cifs/CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ when archive dos attribute not set and we are changing mode back to writeable
on server which does not support the Unix Extensions). Remove read only dos
attribute on chmod when adding any write permission (ie on any of
user/group/other (not all of user/group/other ie 0222) when
mounted to windows.
mounted to windows. Add support for POSIX MkDir (slight performance
enhancement and eliminates the network race between the mkdir and set
path info of the mode).


Version 1.47
------------
Expand Down
32 changes: 25 additions & 7 deletions trunk/fs/cifs/cifspdu.h
Original file line number Diff line number Diff line change
Expand Up @@ -1388,7 +1388,7 @@ struct smb_t2_rsp {
#define SMB_SET_POSIX_LOCK 0x208
#define SMB_POSIX_OPEN 0x209
#define SMB_POSIX_UNLINK 0x20a
#define SMB_SET_FILE_UNIX_INFO2
#define SMB_SET_FILE_UNIX_INFO2 0x20b
#define SMB_SET_FILE_BASIC_INFO2 0x3ec
#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo too */
#define SMB_FILE_ALL_INFO2 0x3fa
Expand Down Expand Up @@ -2109,22 +2109,40 @@ struct cifs_posix_acl { /* access conrol list (ACL) */

/* end of POSIX ACL definitions */

/* POSIX Open Flags */
#define SMB_O_RDONLY 0x1
#define SMB_O_WRONLY 0x2
#define SMB_O_RDWR 0x4
#define SMB_O_CREAT 0x10
#define SMB_O_EXCL 0x20
#define SMB_O_TRUNC 0x40
#define SMB_O_APPEND 0x80
#define SMB_O_SYNC 0x100
#define SMB_O_DIRECTORY 0x200
#define SMB_O_NOFOLLOW 0x400
#define SMB_O_DIRECT 0x800

typedef struct {
__u32 OpenFlags; /* same as NT CreateX */
__u32 PosixOpenFlags;
__u32 Mode;
__u16 Level; /* reply level requested (see QPathInfo levels) */
__u16 Pad; /* reserved - MBZ */
__le32 OpenFlags; /* same as NT CreateX */
__le32 PosixOpenFlags;
__le64 Permissions;
__le16 Level; /* reply level requested (see QPathInfo levels) */
} __attribute__((packed)) OPEN_PSX_REQ; /* level 0x209 SetPathInfo data */

typedef struct {
/* reply varies based on requested level */
__le16 OplockFlags;
__u16 Fid;
__le32 CreateAction;
__le16 ReturnedLevel;
__le16 Pad;
/* struct following varies based on requested level */
} __attribute__((packed)) OPEN_PSX_RSP; /* level 0x209 SetPathInfo data */


struct file_internal_info {
__u64 UniqueId; /* inode number */
} __attribute__((packed)); /* level 0x3ee */

struct file_mode_info {
__le32 Mode;
} __attribute__((packed)); /* level 0x3f8 */
Expand Down
7 changes: 6 additions & 1 deletion trunk/fs/cifs/cifsproto.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* fs/cifs/cifsproto.h
*
* Copyright (c) International Business Machines Corp., 2002,2006
* Copyright (c) International Business Machines Corp., 2002,2007
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
Expand Down Expand Up @@ -244,6 +244,11 @@ extern int SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
const int access_flags, const int omode,
__u16 * netfid, int *pOplock, FILE_ALL_INFO *,
const struct nls_table *nls_codepage, int remap);
extern int CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon,
u32 posix_flags, __u64 mode, __u16 * netfid,
FILE_UNIX_BASIC_INFO *pRetData,
__u32 *pOplock, const char *name,
const struct nls_table *nls_codepage, int remap);
extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
const int smb_file_id);

Expand Down
127 changes: 124 additions & 3 deletions trunk/fs/cifs/cifssmb.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* fs/cifs/cifssmb.c
*
* Copyright (C) International Business Machines Corp., 2002,2006
* Copyright (C) International Business Machines Corp., 2002,2007
* Author(s): Steve French (sfrench@us.ibm.com)
*
* Contains the routines for constructing the SMB PDUs themselves
Expand All @@ -24,8 +24,8 @@
/* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
/* These are mostly routines that operate on a pathname, or on a tree id */
/* (mounted volume), but there are eight handle based routines which must be */
/* treated slightly different for reconnection purposes since we never want */
/* to reuse a stale file handle and the caller knows the file handle */
/* treated slightly differently for reconnection purposes since we never */
/* want to reuse a stale file handle and only the caller knows the file info */

#include <linux/fs.h>
#include <linux/kernel.h>
Expand Down Expand Up @@ -913,6 +913,127 @@ CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
return rc;
}

int
CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
__u64 mode, __u16 * netfid, FILE_UNIX_BASIC_INFO *pRetData,
__u32 *pOplock, const char *name,
const struct nls_table *nls_codepage, int remap)
{
TRANSACTION2_SPI_REQ *pSMB = NULL;
TRANSACTION2_SPI_RSP *pSMBr = NULL;
int name_len;
int rc = 0;
int bytes_returned = 0;
char *data_offset;
__u16 params, param_offset, offset, byte_count, count;
OPEN_PSX_REQ * pdata;
OPEN_PSX_RSP * psx_rsp;

cFYI(1, ("In POSIX Create"));
PsxCreat:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
return rc;

if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
cifsConvertToUCS((__le16 *) pSMB->FileName, name,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
name_len = strnlen(name, PATH_MAX);
name_len++; /* trailing null */
strncpy(pSMB->FileName, name, name_len);
}

params = 6 + name_len;
count = sizeof(OPEN_PSX_REQ);
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
param_offset = offsetof(struct smb_com_transaction2_spi_req,
InformationLevel) - 4;
offset = param_offset + params;
data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
pdata->Level = SMB_QUERY_FILE_UNIX_BASIC;
pdata->Permissions = cpu_to_le64(mode);
pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
pdata->OpenFlags = cpu_to_le32(*pOplock);
pSMB->ParameterOffset = cpu_to_le16(param_offset);
pSMB->DataOffset = cpu_to_le16(offset);
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
byte_count = 3 /* pad */ + params + count;

pSMB->DataCount = cpu_to_le16(count);
pSMB->ParameterCount = cpu_to_le16(params);
pSMB->TotalDataCount = pSMB->DataCount;
pSMB->TotalParameterCount = pSMB->ParameterCount;
pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
pSMB->Reserved4 = 0;
pSMB->hdr.smb_buf_length += byte_count;
pSMB->ByteCount = cpu_to_le16(byte_count);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1, ("Posix create returned %d", rc));
goto psx_create_err;
}

cFYI(1,("copying inode info"));
rc = validate_t2((struct smb_t2_rsp *)pSMBr);

if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
rc = -EIO; /* bad smb */
goto psx_create_err;
}

/* copy return information to pRetData */
psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
+ le16_to_cpu(pSMBr->t2.DataOffset));

*pOplock = le16_to_cpu(psx_rsp->OplockFlags);
if(netfid)
*netfid = psx_rsp->Fid; /* cifs fid stays in le */
/* Let caller know file was created so we can set the mode. */
/* Do we care about the CreateAction in any other cases? */
if(cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
*pOplock |= CIFS_CREATE_ACTION;
/* check to make sure response data is there */
if(psx_rsp->ReturnedLevel != SMB_QUERY_FILE_UNIX_BASIC)
pRetData->Type = -1; /* unknown */
else {
if(pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
+ sizeof(FILE_UNIX_BASIC_INFO)) {
cERROR(1,("Open response data too small"));
pRetData->Type = -1;
goto psx_create_err;
}
memcpy((char *) pRetData,
(char *)&psx_rsp + sizeof(OPEN_PSX_RSP),
sizeof (FILE_UNIX_BASIC_INFO));
}


psx_create_err:
cifs_buf_release(pSMB);

cifs_stats_inc(&tcon->num_mkdirs);

if (rc == -EAGAIN)
goto PsxCreat;

return rc;
}

static __u16 convert_disposition(int disposition)
{
__u16 ofun = 0;
Expand Down
Loading

0 comments on commit aada694

Please sign in to comment.