smb2file.c 3.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
/*
 *   fs/cifs/smb2file.c
 *
 *   Copyright (C) International Business Machines  Corp., 2002, 2011
 *   Author(s): Steve French (sfrench@us.ibm.com),
 *              Pavel Shilovsky ((pshilovsky@samba.org) 2012
 *
 *   This library is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 *   the GNU Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public License
 *   along with this library; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/slab.h>
#include <linux/pagemap.h>
#include <asm/div64.h>
#include "cifsfs.h"
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsproto.h"
#include "cifs_debug.h"
#include "cifs_fs_sb.h"
#include "cifs_unicode.h"
#include "fscache.h"
#include "smb2proto.h"

P
Pavel Shilovsky 已提交
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
void
smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock)
{
	oplock &= 0xFF;
	if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE) {
		cinode->clientCanCacheAll = true;
		cinode->clientCanCacheRead = true;
		cFYI(1, "Exclusive Oplock granted on inode %p",
		     &cinode->vfs_inode);
	} else if (oplock == SMB2_OPLOCK_LEVEL_II) {
		cinode->clientCanCacheAll = false;
		cinode->clientCanCacheRead = true;
		cFYI(1, "Level II Oplock granted on inode %p",
		    &cinode->vfs_inode);
	} else {
		cinode->clientCanCacheAll = false;
		cinode->clientCanCacheRead = false;
	}
}

57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
int
smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon, const char *path,
	       int disposition, int desired_access, int create_options,
	       struct cifs_fid *fid, __u32 *oplock, FILE_ALL_INFO *buf,
	       struct cifs_sb_info *cifs_sb)
{
	int rc;
	__le16 *smb2_path;
	struct smb2_file_all_info *smb2_data = NULL;

	smb2_path = cifs_convert_path_to_utf16(path, cifs_sb);
	if (smb2_path == NULL) {
		rc = -ENOMEM;
		goto out;
	}

	smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2,
			    GFP_KERNEL);
	if (smb2_data == NULL) {
		rc = -ENOMEM;
		goto out;
	}

	desired_access |= FILE_READ_ATTRIBUTES;
P
Pavel Shilovsky 已提交
81
	*oplock = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
82 83 84

	rc = SMB2_open(xid, tcon, smb2_path, &fid->persistent_fid,
		       &fid->volatile_fid, desired_access, disposition,
P
Pavel Shilovsky 已提交
85
		       0, 0, (__u8 *)oplock, smb2_data);
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
	if (rc)
		goto out;

	if (buf) {
		/* open response does not have IndexNumber field - get it */
		rc = SMB2_get_srv_num(xid, tcon, fid->persistent_fid,
				      fid->volatile_fid,
				      &smb2_data->IndexNumber);
		if (rc) {
			/* let get_inode_info disable server inode numbers */
			smb2_data->IndexNumber = 0;
			rc = 0;
		}
		move_smb2_info_to_cifs(buf, smb2_data);
	}

out:
	kfree(smb2_data);
	kfree(smb2_path);
	return rc;
}