summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/CHANGES3
-rw-r--r--fs/cifs/cifs_dfs_ref.c2
-rw-r--r--fs/cifs/cifsacl.c14
-rw-r--r--fs/cifs/cifsacl.h1
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifsproto.h1
-rw-r--r--fs/cifs/cifssmb.c32
-rw-r--r--fs/cifs/connect.c1
-rw-r--r--fs/cifs/transport.c18
9 files changed, 50 insertions, 24 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index dbd9146..05c9da6 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -8,7 +8,8 @@ of second share to disconnected server session (autoreconnect on this).
Add ability to modify cifs acls for handling chmod (when mounted with
cifsacl flag). Fix prefixpath path separator so we can handle mounts
with prefixpaths longer than one directory (one path component) when
-mounted to Windows servers.
+mounted to Windows servers. Fix slow file open when cifsacl
+enabled.
Version 1.51
------------
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index 56c9240..f53f41f 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -23,7 +23,7 @@
#include "dns_resolve.h"
#include "cifs_debug.h"
-LIST_HEAD(cifs_dfs_automount_list);
+static LIST_HEAD(cifs_dfs_automount_list);
/*
* DFS functions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 1cb5b0a..e99d4fa 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -516,7 +516,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
/* Convert permission bits from mode to equivalent CIFS ACL */
static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
- int acl_len, struct inode *inode, __u64 nmode)
+ struct inode *inode, __u64 nmode)
{
int rc = 0;
__u32 dacloffset;
@@ -692,14 +692,14 @@ void acl_to_uid_mode(struct inode *inode, const char *path, const __u16 *pfid)
int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
{
int rc = 0;
- __u32 acllen = 0;
+ __u32 secdesclen = 0;
struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
cFYI(DBG2, ("set ACL from mode for %s", path));
/* Get the security descriptor */
- pntsd = get_cifs_acl(&acllen, inode, path, NULL);
+ pntsd = get_cifs_acl(&secdesclen, inode, path, NULL);
/* Add three ACEs for owner, group, everyone getting rid of
other ACEs as chmod disables ACEs and set the security descriptor */
@@ -709,20 +709,22 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
set security descriptor request security descriptor
parameters, and secuirty descriptor itself */
- pnntsd = kmalloc(acllen, GFP_KERNEL);
+ secdesclen = secdesclen < DEFSECDESCLEN ?
+ DEFSECDESCLEN : secdesclen;
+ pnntsd = kmalloc(secdesclen, GFP_KERNEL);
if (!pnntsd) {
cERROR(1, ("Unable to allocate security descriptor"));
kfree(pntsd);
return (-ENOMEM);
}
- rc = build_sec_desc(pntsd, pnntsd, acllen, inode, nmode);
+ rc = build_sec_desc(pntsd, pnntsd, inode, nmode);
cFYI(DBG2, ("build_sec_desc rc: %d", rc));
if (!rc) {
/* Set the security descriptor */
- rc = set_cifs_acl(pnntsd, acllen, inode, path);
+ rc = set_cifs_acl(pnntsd, secdesclen, inode, path);
cFYI(DBG2, ("set_cifs_acl rc: %d", rc));
}
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h
index 93a7c34..6c8096c 100644
--- a/fs/cifs/cifsacl.h
+++ b/fs/cifs/cifsacl.h
@@ -27,6 +27,7 @@
#define NUM_SUBAUTHS 5 /* number of sub authority fields */
#define NUM_WK_SIDS 7 /* number of well known sids */
#define SIDNAMELENGTH 20 /* long enough for the ones we care about */
+#define DEFSECDESCLEN 192 /* sec desc len contaiting a dacl with three aces */
#define READ_BIT 0x4
#define WRITE_BIT 0x2
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 6897830..e1dd9f3 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -62,11 +62,9 @@ extern int cifs_setattr(struct dentry *, struct iattr *);
extern const struct inode_operations cifs_file_inode_ops;
extern const struct inode_operations cifs_symlink_inode_ops;
-extern struct list_head cifs_dfs_automount_list;
extern struct inode_operations cifs_dfs_referral_inode_operations;
-
/* Functions related to files and directories */
extern const struct file_operations cifs_file_ops;
extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 7e5e0e7..0c83da4 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -84,6 +84,7 @@ extern __u16 GetNextMid(struct TCP_Server_Info *server);
extern struct oplock_q_entry *AllocOplockQEntry(struct inode *, u16,
struct cifsTconInfo *);
extern void DeleteOplockQEntry(struct oplock_q_entry *);
+extern void DeleteTconOplockQEntries(struct cifsTconInfo *);
extern struct timespec cifs_NTtimeToUnix(u64 utc_nanoseconds_since_1601);
extern u64 cifs_UnixTimeToNT(struct timespec);
extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 30bbe44..4728fa9 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -165,17 +165,19 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
rc = CIFSTCon(0, tcon->ses, tcon->treeName,
tcon, nls_codepage);
up(&tcon->ses->sesSem);
- /* tell server which Unix caps we support */
- if (tcon->ses->capabilities & CAP_UNIX)
- reset_cifs_unix_caps(0 /* no xid */,
- tcon,
- NULL /* we do not know sb */,
- NULL /* no vol info */);
/* BB FIXME add code to check if wsize needs
update due to negotiated smb buffer size
shrinking */
- if (rc == 0)
+ if (rc == 0) {
atomic_inc(&tconInfoReconnectCount);
+ /* tell server Unix caps we support */
+ if (tcon->ses->capabilities & CAP_UNIX)
+ reset_cifs_unix_caps(
+ 0 /* no xid */,
+ tcon,
+ NULL /* we do not know sb */,
+ NULL /* no vol info */);
+ }
cFYI(1, ("reconnect tcon rc = %d", rc));
/* Removed call to reopen open files here.
@@ -310,17 +312,19 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
rc = CIFSTCon(0, tcon->ses, tcon->treeName,
tcon, nls_codepage);
up(&tcon->ses->sesSem);
- /* tell server which Unix caps we support */
- if (tcon->ses->capabilities & CAP_UNIX)
- reset_cifs_unix_caps(0 /* no xid */,
- tcon,
- NULL /* do not know sb */,
- NULL /* no vol info */);
/* BB FIXME add code to check if wsize needs
update due to negotiated smb buffer size
shrinking */
- if (rc == 0)
+ if (rc == 0) {
atomic_inc(&tconInfoReconnectCount);
+ /* tell server Unix caps we support */
+ if (tcon->ses->capabilities & CAP_UNIX)
+ reset_cifs_unix_caps(
+ 0 /* no xid */,
+ tcon,
+ NULL /* do not know sb */,
+ NULL /* no vol info */);
+ }
cFYI(1, ("reconnect tcon rc = %d", rc));
/* Removed call to reopen open files here.
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 8dbfa97..e171067 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -3527,6 +3527,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
FreeXid(xid);
return 0;
}
+ DeleteTconOplockQEntries(cifs_sb->tcon);
tconInfoFree(cifs_sb->tcon);
if ((ses) && (ses->server)) {
/* save off task so we do not refer to ses later */
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 3612d6c..000ac50 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -142,6 +142,24 @@ void DeleteOplockQEntry(struct oplock_q_entry *oplockEntry)
kmem_cache_free(cifs_oplock_cachep, oplockEntry);
}
+
+void DeleteTconOplockQEntries(struct cifsTconInfo *tcon)
+{
+ struct oplock_q_entry *temp;
+
+ if (tcon == NULL)
+ return;
+
+ spin_lock(&GlobalMid_Lock);
+ list_for_each_entry(temp, &GlobalOplock_Q, qhead) {
+ if ((temp->tcon) && (temp->tcon == tcon)) {
+ list_del(&temp->qhead);
+ kmem_cache_free(cifs_oplock_cachep, temp);
+ }
+ }
+ spin_unlock(&GlobalMid_Lock);
+}
+
int
smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
unsigned int smb_buf_length, struct sockaddr *sin)
OpenPOWER on IntegriCloud