The author wishes to express his appreciation and thanks to:
Andrew Tridgell (Samba team) for his early suggestions about smb/cifs VFS
-improvements. Thanks to IBM for allowing me the time and test resources to pursue
-this project. Jim McDonough from IBM (and the Samba Team) for his help.
-The IBM Linux JFS team for explaining many esoteric Linux filesystem features.
+improvements. Thanks to IBM for allowing me time and test resources to pursue
+this project, to Jim McDonough from IBM (and the Samba Team) for his help, to
+the IBM Linux JFS team for explaining many esoteric Linux filesystem features.
+Jeremy Allison of the Samba team has done invaluable work in adding the server
+side of the original CIFS Unix extensions and reviewing and implementing
+portions of the newer CIFS POSIX extensions into the Samba 3 file server. Thank
Dave Boutcher of IBM Rochester (author of the OS/400 smb/cifs filesystem client)
-for proving years ago that a very good smb/cifs client could be done on a Unix like
-operating system. Volker Lendecke, Andrew Tridgell, Urban Widmark, John Newbigin
-and others for their work on the Linux smbfs module over the years. Thanks to
+for proving years ago that very good smb/cifs clients could be done on Unix-like
+operating systems. Volker Lendecke, Andrew Tridgell, Urban Widmark, John
+Newbigin and others for their work on the Linux smbfs module. Thanks to
the other members of the Storage Network Industry Association CIFS Technical
Workgroup for their work specifying this highly complex protocol and finally
thanks to the Samba team for their technical advice and encouragement.
Sergey Vlasov
Richard Hughes
Yury Umanets
-Mark Hamzy
+Mark Hamzy (for some of the early cifs IPv6 work)
Domen Puncer
-Jesper Juhl
+Jesper Juhl (in particular for lots of whitespace/formatting cleanup)
+Vince Negri and Dave Stahl (for finding an important caching bug)
+Adrian Bunk (kcalloc cleanups)
Test case and Bug Report contributors
-------------------------------------
Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen,
Olaf Kirch, Kieron Briggs, Nick Millington and others. Also special
mention to the Stanford Checker (SWAT) which pointed out many minor
-bugs in error paths.
+bugs in error paths. Valuable suggestions also have come from Al Viro
+and Dave Miller.
And thanks to the IBM LTC and Power test teams and SuSE testers for
finding multiple bugs during excellent stress test runs.
*
* Directory search handling
*
- * Copyright (C) International Business Machines Corp., 2004
+ * Copyright (C) International Business Machines Corp., 2004, 2005
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
struct cifsTconInfo *pTcon;
int rc = 0;
- cFYI(1, ("For %s ", qstring->name));
+ cFYI(1, ("For %s", qstring->name));
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
pTcon = cifs_sb->tcon;
qstring->hash = full_name_hash(qstring->name, qstring->len);
tmp_dentry = d_lookup(file->f_dentry, qstring);
if (tmp_dentry) {
- cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode));
+ cFYI(0, ("existing dentry with inode 0x%p", tmp_dentry->d_inode));
*ptmp_inode = tmp_dentry->d_inode;
/* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/
if(*ptmp_inode == NULL) {
}
static void fill_in_inode(struct inode *tmp_inode,
- FILE_DIRECTORY_INFO *pfindData, int *pobject_type)
+ FILE_DIRECTORY_INFO *pfindData, int *pobject_type, int isNewInode)
{
+ loff_t local_size;
+ struct timespec local_mtime;
+
struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
__u32 attr = le32_to_cpu(pfindData->ExtFileAttributes);
cifsInfo->cifsAttrs = attr;
cifsInfo->time = jiffies;
+ /* save mtime and size */
+ local_mtime = tmp_inode->i_mtime;
+ local_size = tmp_inode->i_size;
+
/* Linux can not store file creation time unfortunately so ignore it */
tmp_inode->i_atime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
tmp_inode->i_mode = cifs_sb->mnt_file_mode;
}
- cFYI(0,("CIFS FFIRST: Attributes came in as 0x%x",attr));
if (attr & ATTR_DIRECTORY) {
*pobject_type = DT_DIR;
/* override default perms since we do not lock dirs */
(unsigned long)tmp_inode->i_size, tmp_inode->i_blocks,
tmp_inode->i_blksize));
if (S_ISREG(tmp_inode->i_mode)) {
- cFYI(1, (" File inode "));
+ cFYI(1, ("File inode"));
tmp_inode->i_op = &cifs_file_inode_ops;
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
tmp_inode->i_fop = &cifs_file_direct_ops;
else
tmp_inode->i_fop = &cifs_file_ops;
tmp_inode->i_data.a_ops = &cifs_addr_ops;
+
+ if(isNewInode)
+ return; /* No sense invalidating pages for new inode since we
+ have not started caching readahead file data yet */
+
+ if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
+ (local_size == tmp_inode->i_size)) {
+ cFYI(1, ("inode exists but unchanged"));
+ } else {
+ /* file may have changed on server */
+ cFYI(1, ("invalidate inode, readdir detected change"));
+ invalidate_remote_inode(tmp_inode);
+ }
} else if (S_ISDIR(tmp_inode->i_mode)) {
- cFYI(1, (" Directory inode"));
+ cFYI(1, ("Directory inode"));
tmp_inode->i_op = &cifs_dir_inode_ops;
tmp_inode->i_fop = &cifs_dir_ops;
} else if (S_ISLNK(tmp_inode->i_mode)) {
- cFYI(1, (" Symbolic Link inode "));
+ cFYI(1, ("Symbolic Link inode"));
tmp_inode->i_op = &cifs_symlink_inode_ops;
} else {
- cFYI(1, (" Init special inode "));
+ cFYI(1, ("Init special inode"));
init_special_inode(tmp_inode, tmp_inode->i_mode,
tmp_inode->i_rdev);
}
}
static void unix_fill_in_inode(struct inode *tmp_inode,
- FILE_UNIX_INFO *pfindData, int *pobject_type)
+ FILE_UNIX_INFO *pfindData, int *pobject_type, int isNewInode)
{
+ loff_t local_size;
+ struct timespec local_mtime;
+
struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
cifsInfo->time = jiffies;
atomic_inc(&cifsInfo->inUse);
+ /* save mtime and size */
+ local_mtime = tmp_inode->i_mtime;
+ local_size = tmp_inode->i_size;
+
tmp_inode->i_atime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
tmp_inode->i_mtime =
else
tmp_inode->i_fop = &cifs_file_ops;
tmp_inode->i_data.a_ops = &cifs_addr_ops;
+
+ if(isNewInode)
+ return; /* No sense invalidating pages for new inode since we
+ have not started caching readahead file data yet */
+
+ if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
+ (local_size == tmp_inode->i_size)) {
+ cFYI(1, ("inode exists but unchanged"));
+ } else {
+ /* file may have changed on server */
+ cFYI(1, ("invalidate inode, readdir detected change"));
+ invalidate_remote_inode(tmp_inode);
+ }
} else if (S_ISDIR(tmp_inode->i_mode)) {
cFYI(1, ("Directory inode"));
tmp_inode->i_op = &cifs_dir_inode_ops;
return -ENOMEM;
}
- cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos));
+ cFYI(1, ("Full path: %s start at: %lld", full_path, file->f_pos));
ffirst_retry:
/* test for Unix extensions */
insert_inode_hash(tmp_inode);
}
+ /* we pass in rc below, indicating whether it is a new inode,
+ so we can figure out whether to invalidate the inode cached
+ data if the file has changed */
if(pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
- unix_fill_in_inode(tmp_inode,(FILE_UNIX_INFO *)pfindEntry,&obj_type);
+ unix_fill_in_inode(tmp_inode,
+ (FILE_UNIX_INFO *)pfindEntry,&obj_type, rc);
} else {
- fill_in_inode(tmp_inode,(FILE_DIRECTORY_INFO *)pfindEntry,&obj_type);
+ fill_in_inode(tmp_inode,
+ (FILE_DIRECTORY_INFO *)pfindEntry,&obj_type, rc);
}
rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,tmp_inode->i_ino,obj_type);