summaryrefslogtreecommitdiffstats
path: root/fs/cifs/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/dir.c')
-rw-r--r--fs/cifs/dir.c124
1 files changed, 75 insertions, 49 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 781025be48bc..7c0a81283645 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -160,17 +160,18 @@ check_name(struct dentry *direntry)
static int
cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
struct tcon_link *tlink, unsigned oflags, umode_t mode,
- __u32 *oplock, __u16 *fileHandle, int *created)
+ __u32 *oplock, struct cifs_fid *fid, int *created)
{
int rc = -ENOENT;
int create_options = CREATE_NOT_DIR;
- int desiredAccess;
+ int desired_access;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifs_tcon *tcon = tlink_tcon(tlink);
char *full_path = NULL;
FILE_ALL_INFO *buf = NULL;
struct inode *newinode = NULL;
int disposition;
+ struct TCP_Server_Info *server = tcon->ses->server;
*oplock = 0;
if (tcon->ses->server->oplocks)
@@ -185,8 +186,8 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
if (tcon->unix_ext && cap_unix(tcon->ses) && !tcon->broken_posix_open &&
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
- rc = cifs_posix_open(full_path, &newinode,
- inode->i_sb, mode, oflags, oplock, fileHandle, xid);
+ rc = cifs_posix_open(full_path, &newinode, inode->i_sb, mode,
+ oflags, oplock, &fid->netfid, xid);
switch (rc) {
case 0:
if (newinode == NULL) {
@@ -202,7 +203,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
* close it and proceed as if it were a normal
* lookup.
*/
- CIFSSMBClose(xid, tcon, *fileHandle);
+ CIFSSMBClose(xid, tcon, fid->netfid);
goto cifs_create_get_file_info;
}
/* success, no need to query */
@@ -244,11 +245,11 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
*/
}
- desiredAccess = 0;
+ desired_access = 0;
if (OPEN_FMODE(oflags) & FMODE_READ)
- desiredAccess |= GENERIC_READ; /* is this too little? */
+ desired_access |= GENERIC_READ; /* is this too little? */
if (OPEN_FMODE(oflags) & FMODE_WRITE)
- desiredAccess |= GENERIC_WRITE;
+ desired_access |= GENERIC_WRITE;
disposition = FILE_OVERWRITE_IF;
if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
@@ -260,8 +261,15 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
else
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 (!server->ops->open) {
+ rc = -ENOSYS;
+ goto out;
+ }
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
if (buf == NULL) {
@@ -279,28 +287,18 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
if (backup_cred(cifs_sb))
create_options |= CREATE_OPEN_BACKUP_INTENT;
- if (tcon->ses->capabilities & CAP_NT_SMBS)
- rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
- desiredAccess, create_options,
- fileHandle, oplock, buf, cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
- else
- rc = -EIO; /* no NT SMB support fall into legacy open below */
-
- if (rc == -EIO) {
- /* old server, retry the open legacy style */
- rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
- desiredAccess, create_options,
- fileHandle, oplock, buf, cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
- }
+ rc = server->ops->open(xid, tcon, full_path, disposition,
+ desired_access, create_options, fid, oplock,
+ buf, cifs_sb);
if (rc) {
cFYI(1, "cifs_create returned 0x%x", rc);
goto out;
}
- /* If Open reported that we actually created a file
- then we now have to set the mode if possible */
+ /*
+ * If Open reported that we actually created a file then we now have to
+ * set the mode if possible.
+ */
if ((tcon->unix_ext) && (*oplock & CIFS_CREATE_ACTION)) {
struct cifs_unix_set_info_args args = {
.mode = mode,
@@ -321,11 +319,13 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
args.uid = NO_CHANGE_64;
args.gid = NO_CHANGE_64;
}
- CIFSSMBUnixSetFileInfo(xid, tcon, &args, *fileHandle,
- current->tgid);
+ CIFSSMBUnixSetFileInfo(xid, tcon, &args, fid->netfid,
+ current->tgid);
} else {
- /* BB implement mode setting via Windows security
- descriptors e.g. */
+ /*
+ * BB implement mode setting via Windows security
+ * descriptors e.g.
+ */
/* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
/* Could set r/o dos attribute if mode & 0222 == 0 */
@@ -334,12 +334,14 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
cifs_create_get_file_info:
/* server might mask mode so we have to query for it */
if (tcon->unix_ext)
- rc = cifs_get_inode_info_unix(&newinode, full_path,
- inode->i_sb, xid);
+ rc = cifs_get_inode_info_unix(&newinode, full_path, inode->i_sb,
+ xid);
else {
- rc = cifs_get_inode_info(&newinode, full_path, buf,
- inode->i_sb, xid, fileHandle);
+ rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb,
+ xid, &fid->netfid);
if (newinode) {
+ if (server->ops->set_lease_key)
+ server->ops->set_lease_key(newinode, fid);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
newinode->i_mode = mode;
if ((*oplock & CIFS_CREATE_ACTION) &&
@@ -356,7 +358,8 @@ cifs_create_get_file_info:
cifs_create_set_dentry:
if (rc != 0) {
cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
- CIFSSMBClose(xid, tcon, *fileHandle);
+ if (server->ops->close)
+ server->ops->close(xid, tcon, fid);
goto out;
}
d_drop(direntry);
@@ -377,11 +380,14 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
unsigned int xid;
struct tcon_link *tlink;
struct cifs_tcon *tcon;
- __u16 fileHandle;
+ struct TCP_Server_Info *server;
+ struct cifs_fid fid;
+ struct cifs_pending_open open;
__u32 oplock;
- struct cifsFileInfo *pfile_info;
+ struct cifsFileInfo *file_info;
- /* Posix open is only called (at lookup time) for file create now. For
+ /*
+ * Posix open is only called (at lookup time) for file create now. For
* opens (rather than creates), because we do not know if it is a file
* or directory yet, and current Samba no longer allows us to do posix
* open on dirs, we could end up wasting an open call on what turns out
@@ -413,22 +419,34 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
goto out_free_xid;
tcon = tlink_tcon(tlink);
+ server = tcon->ses->server;
+
+ if (server->ops->new_lease_key)
+ server->ops->new_lease_key(&fid);
+
+ cifs_add_pending_open(&fid, tlink, &open);
rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
- &oplock, &fileHandle, opened);
+ &oplock, &fid, opened);
- if (rc)
+ if (rc) {
+ cifs_del_pending_open(&open);
goto out;
+ }
rc = finish_open(file, direntry, generic_file_open, opened);
if (rc) {
- CIFSSMBClose(xid, tcon, fileHandle);
+ if (server->ops->close)
+ server->ops->close(xid, tcon, &fid);
+ cifs_del_pending_open(&open);
goto out;
}
- pfile_info = cifs_new_fileinfo(fileHandle, file, tlink, oplock);
- if (pfile_info == NULL) {
- CIFSSMBClose(xid, tcon, fileHandle);
+ file_info = cifs_new_fileinfo(&fid, file, tlink, oplock);
+ if (file_info == NULL) {
+ if (server->ops->close)
+ server->ops->close(xid, tcon, &fid);
+ cifs_del_pending_open(&open);
rc = -ENOMEM;
}
@@ -453,7 +471,9 @@ int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
*/
unsigned oflags = O_EXCL | O_CREAT | O_RDWR;
struct tcon_link *tlink;
- __u16 fileHandle;
+ struct cifs_tcon *tcon;
+ struct TCP_Server_Info *server;
+ struct cifs_fid fid;
__u32 oplock;
int created = FILE_CREATED;
@@ -465,10 +485,16 @@ int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
if (IS_ERR(tlink))
goto out_free_xid;
+ tcon = tlink_tcon(tlink);
+ server = tcon->ses->server;
+
+ if (server->ops->new_lease_key)
+ server->ops->new_lease_key(&fid);
+
rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
- &oplock, &fileHandle, &created);
- if (!rc)
- CIFSSMBClose(xid, tlink_tcon(tlink), fileHandle);
+ &oplock, &fid, &created);
+ if (!rc && server->ops->close)
+ server->ops->close(xid, tcon, &fid);
cifs_put_tlink(tlink);
out_free_xid: