GIT 8d142137b4fe87188f211042b16a5993964226f9 git+ssh://master.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git 8d142137b4fe87188f211042b16a5993964226f9 commit 8d142137b4fe87188f211042b16a5993964226f9 Author: Steve French Date: Wed Apr 16 03:56:51 2008 +0000 [CIFS] make cifs_dfs_automount_list_static This patch makes the needlessly global cifs_dfs_automount_list static. Signed-off-by: Adrian Bunk Signed-off-by: Steve French commit 5d941ca628a142f44d7a2440fe919f8e8691f590 Author: Steve French Date: Tue Apr 15 18:40:48 2008 +0000 [CIFS] Fix oops when slow oplock process races with unmount If a tcon is being freed in call tconInfoFree, clean up any entries that may exist in global oplock queue as the tcon structure hanging off of those entries will be invalid and can cause oops while accesing any elements in the tcon structure. Signed-off-by: Shirish Pargaonkar Signed-off-by: Steve French commit cce246ee5f3c7f4d3539ea41d13feb7a07859145 Author: Steve French Date: Wed Apr 9 20:55:31 2008 +0000 [CIFS] Fix acl length when very short ACL being modified by chmod Signed-off-by: Shirish Pargaonkar Signed-off-by: Steve French commit 35028d71116926008f5c19b8fcb00aacaabf5eab Author: Steve French Date: Wed Apr 9 20:32:42 2008 +0000 [CIFS] Fix looping on reconnect to Samba when unexpected tree connect fail on reconnect Signed-off-by: Shirish Pargaonkar Signed-off-by: Steve French commit 932e2d23c8529c39fe74549dcbe4b2c8b2d66ba4 Author: Steve French Date: Fri Apr 4 21:59:35 2008 +0000 [CIFS] minor update to change log Signed-off-by: Steve French fs/cifs/CHANGES | 3 ++- fs/cifs/cifs_dfs_ref.c | 2 +- fs/cifs/cifsacl.c | 14 ++++++++------ fs/cifs/cifsacl.h | 1 + fs/cifs/cifsfs.h | 2 -- fs/cifs/cifsproto.h | 1 + fs/cifs/cifssmb.c | 32 ++++++++++++++++++-------------- fs/cifs/connect.c | 1 + fs/cifs/transport.c | 18 ++++++++++++++++++ 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)