public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] smbfs fsx'ed
@ 2002-01-03 12:20 Urban Widmark
  2002-01-03 21:37 ` Linus Torvalds
  0 siblings, 1 reply; 9+ messages in thread
From: Urban Widmark @ 2002-01-03 12:20 UTC (permalink / raw)
  To: Linus Torvalds, Dave Jones; +Cc: linux-kernel


Hello

Here are some updates for smbfs:
+ Drops kmap/kunmap from prepare_write/commit_write
+ Fixes two problems spotted by fsx-linux, leaving one unfixed
  - Shared mmaps must be written back before closing as smb does not allow
    you to write after the file is closed. Flushing written pages before
    closing makes smbfs do what the application wants.
  - On truncate, dirty pages need to be written out first because of the
    order of smb_proc_trunc and vmtruncate. I believe this is the same
    issue as NFS had.
  - I can still see one problem, but only with windows servers. When
    creating a hole in a file the hole does not always contain all zeroes.
    As far as I can tell the command to truncate is sent to the server,
    and then the page fsx errors on is re-read.
    Server issue? Don't know but I can't trigger it with a samba server.
+ Rene Scharfe has added options display for /proc/mounts.

Patch vs 2.5.2-pre5, but should work for 2.5.2-pre6 and 2.5.1-dj11.
Please apply.

/Urban


diff -urN -X exclude linux-2.5.2-pre5-orig/fs/smbfs/ChangeLog linux-2.5.2-pre5-smbfs/fs/smbfs/ChangeLog
--- linux-2.5.2-pre5-orig/fs/smbfs/ChangeLog	Thu Nov  8 19:01:00 2001
+++ linux-2.5.2-pre5-smbfs/fs/smbfs/ChangeLog	Thu Jan  3 11:33:52 2002
@@ -1,5 +1,15 @@
 ChangeLog for smbfs.
 
+2001-12-31 René Scharfe <l.s.r@web.de>
+
+	* inode.c: added smb_show_options to show mount options in /proc/mounts
+	* inode.c, getopt.c, getopt.h: merged flag and has_arg in struct option
+	* inode.c: use S_IRWXUGO where appropriate
+
+2001-12-22 Urban Widmark <urban@teststation.com>
+
+	* file.c, proc.c: Fix problems triggered by the "fsx test"
+
 2001-09-17 Urban Widmark <urban@teststation.com>
 
 	* proc.c: Use 4096 (was 512) as the blocksize for better write
diff -urN -X exclude linux-2.5.2-pre5-orig/fs/smbfs/file.c linux-2.5.2-pre5-smbfs/fs/smbfs/file.c
--- linux-2.5.2-pre5-orig/fs/smbfs/file.c	Thu Nov  8 19:01:00 2001
+++ linux-2.5.2-pre5-smbfs/fs/smbfs/file.c	Wed Jan  2 21:11:40 2002
@@ -270,7 +270,6 @@
 static int smb_prepare_write(struct file *file, struct page *page, 
 			     unsigned offset, unsigned to)
 {
-	kmap(page);
 	return 0;
 }
 
@@ -283,7 +282,6 @@
 	lock_kernel();
 	status = smb_updatepage(file, page, offset, to-offset);
 	unlock_kernel();
-	kunmap(page);
 	return status;
 }
 
@@ -349,8 +347,14 @@
 smb_file_release(struct inode *inode, struct file * file)
 {
 	lock_kernel();
-	if (!--inode->u.smbfs_i.openers)
+	if (!--inode->u.smbfs_i.openers) {
+		/* We must flush any dirty pages now as we won't be able to
+		   write anything after close. mmap can trigger this.
+		   "openers" should perhaps include mmap'ers ... */
+		filemap_fdatasync(inode->i_mapping);
+		filemap_fdatawait(inode->i_mapping);
 		smb_close(inode);
+	}
 	unlock_kernel();
 	return 0;
 }
diff -urN -X exclude linux-2.5.2-pre5-orig/fs/smbfs/getopt.c linux-2.5.2-pre5-smbfs/fs/smbfs/getopt.c
--- linux-2.5.2-pre5-orig/fs/smbfs/getopt.c	Sun Aug 19 12:08:09 2001
+++ linux-2.5.2-pre5-smbfs/fs/smbfs/getopt.c	Thu Jan  3 11:32:54 2002
@@ -46,7 +46,7 @@
 
 	for (i = 0; opts[i].name != NULL; i++) {
 		if (!strcmp(opts[i].name, token)) {
-			if (opts[i].has_arg && (!val || !*val)) {
+			if (!opts[i].flag && (!val || !*val)) {
 				printk("%s: the %s option requires an argument\n",
 				       caller, token);
 				return -1;
diff -urN -X exclude linux-2.5.2-pre5-orig/fs/smbfs/getopt.h linux-2.5.2-pre5-smbfs/fs/smbfs/getopt.h
--- linux-2.5.2-pre5-orig/fs/smbfs/getopt.h	Mon Aug 14 22:31:10 2000
+++ linux-2.5.2-pre5-smbfs/fs/smbfs/getopt.h	Thu Jan  3 11:32:54 2002
@@ -3,7 +3,6 @@
 
 struct option {
 	const char *name;
-	int has_arg;
 	unsigned long flag;
 	int val;
 };
diff -urN -X exclude linux-2.5.2-pre5-orig/fs/smbfs/inode.c linux-2.5.2-pre5-smbfs/fs/smbfs/inode.c
--- linux-2.5.2-pre5-orig/fs/smbfs/inode.c	Thu Nov  8 19:01:00 2001
+++ linux-2.5.2-pre5-smbfs/fs/smbfs/inode.c	Thu Jan  3 11:41:05 2002
@@ -22,6 +22,7 @@
 #include <linux/dcache.h>
 #include <linux/smp_lock.h>
 #include <linux/nls.h>
+#include <linux/seq_file.h>
 
 #include <linux/smb_fs.h>
 #include <linux/smbno.h>
@@ -41,9 +42,12 @@
 #define SMB_NLS_REMOTE ""
 #endif
 
+#define SMB_TTL_DEFAULT 1000
+
 static void smb_delete_inode(struct inode *);
 static void smb_put_super(struct super_block *);
 static int  smb_statfs(struct super_block *, struct statfs *);
+static int  smb_show_options(struct seq_file *, struct vfsmount *);
 
 static struct super_operations smb_sops =
 {
@@ -51,6 +55,7 @@
 	delete_inode:	smb_delete_inode,
 	put_super:	smb_put_super,
 	statfs:		smb_statfs,
+	show_options:	smb_show_options,
 };
 
 
@@ -259,21 +264,20 @@
 	clear_inode(ino);
 }
 
-/* FIXME: flags and has_arg could probably be merged. */
 static struct option opts[] = {
-	{ "version",	1, 0, 'v' },
-	{ "win95",	0, SMB_MOUNT_WIN95, 1 },
-	{ "oldattr",	0, SMB_MOUNT_OLDATTR, 1 },
-	{ "dirattr",	0, SMB_MOUNT_DIRATTR, 1 },
-	{ "case",	0, SMB_MOUNT_CASE, 1 },
-	{ "uid",	1, 0, 'u' },
-	{ "gid",	1, 0, 'g' },
-	{ "file_mode",	1, 0, 'f' },
-	{ "dir_mode",	1, 0, 'd' },
-	{ "iocharset",	1, 0, 'i' },
-	{ "codepage",	1, 0, 'c' },
-	{ "ttl",	1, 0, 't' },
-	{ NULL,		0, 0, 0}
+	{ "version",	0, 'v' },
+	{ "win95",	SMB_MOUNT_WIN95, 1 },
+	{ "oldattr",	SMB_MOUNT_OLDATTR, 1 },
+	{ "dirattr",	SMB_MOUNT_DIRATTR, 1 },
+	{ "case",	SMB_MOUNT_CASE, 1 },
+	{ "uid",	0, 'u' },
+	{ "gid",	0, 'g' },
+	{ "file_mode",	0, 'f' },
+	{ "dir_mode",	0, 'd' },
+	{ "iocharset",	0, 'i' },
+	{ "codepage",	0, 'c' },
+	{ "ttl",	0, 't' },
+	{ NULL,		0, 0}
 };
 
 static int
@@ -310,12 +314,10 @@
 			mnt->gid = value;
 			break;
 		case 'f':
-			mnt->file_mode = value & (S_IRWXU | S_IRWXG | S_IRWXO);
-			mnt->file_mode |= S_IFREG;
+			mnt->file_mode = (value & S_IRWXUGO) | S_IFREG;
 			break;
 		case 'd':
-			mnt->dir_mode = value & (S_IRWXU | S_IRWXG | S_IRWXO);
-			mnt->dir_mode |= S_IFDIR;
+			mnt->dir_mode = (value & S_IRWXUGO) | S_IFDIR;
 			break;
 		case 'i':
 			strncpy(mnt->codepage.local_name, optarg, 
@@ -338,6 +340,45 @@
 	return c;
 }
 
+/*
+ * smb_show_options() is for displaying mount options in /proc/mounts.
+ * It tries to avoid showing settings that were not changed from their
+ * defaults.
+ */
+static int
+smb_show_options(struct seq_file *s, struct vfsmount *m)
+{
+	struct smb_mount_data_kernel *mnt = m->mnt_sb->u.smbfs_sb.mnt;
+	int i;
+
+	for (i = 0; opts[i].name != NULL; i++)
+		if (mnt->flags & opts[i].flag)
+			seq_printf(s, ",%s", opts[i].name);
+
+	if (mnt->uid != 0)
+		seq_printf(s, ",uid=%d", mnt->uid);
+	if (mnt->gid != 0)
+		seq_printf(s, ",gid=%d", mnt->gid);
+	if (mnt->mounted_uid != 0)
+		seq_printf(s, ",mounted_uid=%d", mnt->mounted_uid);
+
+	/* 
+	 * Defaults for file_mode and dir_mode are unknown to us; they
+	 * depend on the current umask of the user doing the mount.
+	 */
+	seq_printf(s, ",file_mode=%04o", mnt->file_mode & S_IRWXUGO);
+	seq_printf(s, ",dir_mode=%04o", mnt->dir_mode & S_IRWXUGO);
+
+	if (strcmp(mnt->codepage.local_name, CONFIG_NLS_DEFAULT))
+		seq_printf(s, ",iocharset=%s", mnt->codepage.local_name);
+	if (strcmp(mnt->codepage.remote_name, SMB_NLS_REMOTE))
+		seq_printf(s, ",codepage=%s", mnt->codepage.remote_name);
+
+	if (mnt->ttl != SMB_TTL_DEFAULT)
+		seq_printf(s, ",ttl=%d", mnt->ttl);
+
+	return 0;
+}
 
 static void
 smb_put_super(struct super_block *sb)
@@ -425,7 +466,7 @@
 	strncpy(mnt->codepage.remote_name, SMB_NLS_REMOTE,
 		SMB_NLS_MAXNAMELEN);
 
-	mnt->ttl = 1000;
+	mnt->ttl = SMB_TTL_DEFAULT;
 	if (ver == SMB_MOUNT_OLDVERSION) {
 		mnt->version = oldmnt->version;
 
@@ -434,12 +475,8 @@
 		mnt->uid = oldmnt->uid;
 		mnt->gid = oldmnt->gid;
 
-		mnt->file_mode =
-			oldmnt->file_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
-		mnt->dir_mode =
-			oldmnt->dir_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
-		mnt->file_mode |= S_IFREG;
-		mnt->dir_mode  |= S_IFDIR;
+		mnt->file_mode = (oldmnt->file_mode & S_IRWXUGO) | S_IFREG;
+		mnt->dir_mode = (oldmnt->dir_mode & S_IRWXUGO) | S_IFDIR;
 
 		mnt->flags = (oldmnt->file_mode >> 9);
 	} else {
@@ -510,7 +547,7 @@
 {
 	struct inode *inode = dentry->d_inode;
 	struct smb_sb_info *server = server_from_dentry(dentry);
-	unsigned int mask = (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO);
+	unsigned int mask = (S_IFREG | S_IFDIR | S_IRWXUGO);
 	int error, changed, refresh = 0;
 	struct smb_fattr fattr;
 
@@ -535,6 +572,10 @@
 		VERBOSE("changing %s/%s, old size=%ld, new size=%ld\n",
 			DENTRY_PATH(dentry),
 			(long) inode->i_size, (long) attr->ia_size);
+
+		filemap_fdatasync(inode->i_mapping);
+		filemap_fdatawait(inode->i_mapping);
+
 		error = smb_open(dentry, O_WRONLY);
 		if (error)
 			goto out;


^ permalink raw reply	[flat|nested] 9+ messages in thread
* Re: [PATCH] smbfs fsx'ed
@ 2002-01-03 22:51 Dan Kegel
  2002-01-03 23:02 ` Urban Widmark
  0 siblings, 1 reply; 9+ messages in thread
From: Dan Kegel @ 2002-01-03 22:51 UTC (permalink / raw)
  To: linux-kernel@vger.kernel.org

Linus Torvalds <torvalds@transmeta.com> wrote:
> Btw, Urban, is anybody working on trying to do "{read|write}page()"
> asynchronously? I assume that IO performance on smbfs must be quite
> horrible with totally synchronous IO..

I use smbfs to mount a visual sourcesafe database,
and run ss via wine.  The combination is very slow.
Don't know how much of it is wine, and how much is smbfs,
but any speedup would be greatly appreciated.

(Eventually, wine will bundle its own smb code, but for
now if you want to access network shares, smbfs is the only way.)
- Dan

p.s. see http://www.kegel.com/linux/vss-howto.html

^ permalink raw reply	[flat|nested] 9+ messages in thread
* Re: [PATCH] smbfs fsx'ed
@ 2002-01-03 22:56 Petr Vandrovec
  2002-01-03 23:48 ` Urban Widmark
  0 siblings, 1 reply; 9+ messages in thread
From: Petr Vandrovec @ 2002-01-03 22:56 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Dave Jones, linux-kernel

On  3 Jan 02 at 13:37, Linus Torvalds wrote:
> 
> (Not as horrible as the NCPFS thing that doesn't understand about the page
> cache at all, but still..)

Unfortunately it is not easy for me to add pagecache support
to ncpfs, as couple of ncpfs users uses ncpfs in shared environment
with database record locking, and if I'll now read full 4KB instead of
128B record, it can clash with records locked by other clients.

I can for sure add `leases' like Novell Client for Windows does for
possibility of file caching, but I'm not sure whether size of code
needed for supporting this (and for supporting server driven
cache flushes) is worth of effort.
                                    Best regards,
                                        Petr Vandrovec
                                        vandrove@vc.cvut.cz
                                        
P.S.: And as NCP protocol is totally synchronous (even if it uses
TCP, I explicitly asked in Utah), only local file caching can increase
ncpfs performance, as there is no such thing like asynchronous file
read/write...

^ permalink raw reply	[flat|nested] 9+ messages in thread
* Re: [PATCH] smbfs fsx'ed
@ 2002-01-04 12:22 Petr Vandrovec
  0 siblings, 0 replies; 9+ messages in thread
From: Petr Vandrovec @ 2002-01-04 12:22 UTC (permalink / raw)
  To: Urban Widmark; +Cc: Linus Torvalds, Dave Jones, linux-kernel

On  4 Jan 02 at 0:48, Urban Widmark wrote:
> On Thu, 3 Jan 2002, Petr Vandrovec wrote:
> 
> > On  3 Jan 02 at 13:37, Linus Torvalds wrote:
> > > 
> > > (Not as horrible as the NCPFS thing that doesn't understand about the page
> > > cache at all, but still..)
> > 
> > Unfortunately it is not easy for me to add pagecache support
> > to ncpfs, as couple of ncpfs users uses ncpfs in shared environment
> > with database record locking, and if I'll now read full 4KB instead of
> > 128B record, it can clash with records locked by other clients.
> 
> Does the locks prevent you from even looking? You could read only the
> parts requested if the file has locks and fill the rest with 0. Only using
> the page cache if there are no locks. Not too pretty but ...

It results in short read when there is partial overlap, or error if
overlap is complete.

> A write of 128 bytes to a file cause a commit_write of 128 bytes, if I am
> reading generic_file_write correctly. So that should not cause it to write
> the full page and that would be ok for the locking case.

OK. Thanks.
 
> > I can for sure add `leases' like Novell Client for Windows does for
> > possibility of file caching, but I'm not sure whether size of code
> > needed for supporting this (and for supporting server driven
> > cache flushes) is worth of effort.
> 
> smbfs needs these for cooperating clients to work. It can only cache data
> if it has a lease. If someone else is also accessing the file then each
> smb_file_read must re-read the page.

It is same for Netware, with minor difference that NW4 refuses 'leases' 
by default, and on NW5 it should be disabled by default, as otherwise
server can go mad when some client errors happen.

> > P.S.: And as NCP protocol is totally synchronous (even if it uses
> > TCP, I explicitly asked in Utah), only local file caching can increase
> > ncpfs performance, as there is no such thing like asynchronous file
> > read/write...
> 
> SMB has no async read/write, but all requests are marked with an ID and it
> is allowed to have a certain number of simultaneous requests in transit.

That's difference. With NCP you can have only one request in flight.
For sure on IPX and UDP, and according to Novell even on TCP.
 
> Even without multiple requests you could let ncpfs accept one read
> request, send that to the server and return without waiting for the reply.

On IPX maximum compatible block size is 1024 bytes... so reading one page
requires 4 exchanges. On UDP/TCP it is easier, but unfortunately majority
of installed servers is still IPX-only (at least I have this feedback
from users).

> The readahead code may then queue up the next request for ncpfs, and ncpfs
> could process that while the previously read page is returned to the user.

It would require either another kernel thread doing readahead, or I have
to submit new request from IPX/UDP data_ready callbacks (for TCP it needs
another thread without discussion, as data_ready callback documentation
says that I cannot read data/send new data directly from it... or maybe
special ncpfs bottomhalf).
                                            Best regards,
                                                    Petr Vandrovec
                                                    vandrove@vc.cvut.cz
                                                    

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2002-01-04 12:24 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-01-03 12:20 [PATCH] smbfs fsx'ed Urban Widmark
2002-01-03 21:37 ` Linus Torvalds
2002-01-03 22:49   ` Urban Widmark
2002-01-04 11:43     ` Trond Myklebust
  -- strict thread matches above, loose matches on Subject: below --
2002-01-03 22:51 Dan Kegel
2002-01-03 23:02 ` Urban Widmark
2002-01-03 22:56 Petr Vandrovec
2002-01-03 23:48 ` Urban Widmark
2002-01-04 12:22 Petr Vandrovec

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox