patch-2.1.58 linux/fs/nfs/inode.c

Next file: linux/fs/nfs/nfs2xdr.c
Previous file: linux/fs/nfs/dir.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.57/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
@@ -34,6 +34,8 @@
 
 #define NFSDBG_FACILITY		NFSDBG_VFS
 
+extern void nfs_invalidate_dircache_sb(struct super_block *);
+
 static int nfs_notify_change(struct inode *, struct iattr *);
 static void nfs_put_inode(struct inode *);
 static void nfs_delete_inode(struct inode *);
@@ -67,6 +69,7 @@
 {
 	inode->i_blksize = inode->i_sb->s_blocksize;
 	inode->i_mode = 0;
+	inode->i_rdev = 0;
 	inode->i_op = NULL;
 	NFS_CACHEINV(inode);
 }
@@ -75,6 +78,11 @@
 nfs_put_inode(struct inode * inode)
 {
 	dprintk("NFS: put_inode(%x/%ld)\n", inode->i_dev, inode->i_ino);
+	/*
+	 * We want to get rid of unused inodes ...
+	 */
+	if (inode->i_count == 1)
+		inode->i_nlink = 0;
 }
 
 static void
@@ -90,13 +98,21 @@
 	struct nfs_server *server = &sb->u.nfs_sb.s_server;
 	struct rpc_clnt	*rpc;
 
+	/*
+	 * Lock the super block while we bring down the daemons.
+	 */
+	lock_super(sb);
 	if ((rpc = server->client) != NULL)
 		rpc_shutdown_client(rpc);
 
 	if (!(server->flags & NFS_MOUNT_NONLM))
 		lockd_down();	/* release rpc.lockd */
 	rpciod_down();		/* release rpciod */
-	lock_super(sb);
+	/*
+	 * Invalidate the dircache for this superblock.
+	 */
+	nfs_invalidate_dircache_sb(sb);
+
 	sb->s_dev = 0;
 	unlock_super(sb);
 	MOD_DEC_USE_COUNT;
@@ -147,14 +163,12 @@
 	unsigned int		authflavor;
 	int			tcp;
 	kdev_t			dev = sb->s_dev;
+	struct inode		*root_inode;
 
 	MOD_INC_USE_COUNT;
-	if (!data) {
-		printk("nfs_read_super: missing data argument\n");
-		sb->s_dev = 0;
-		MOD_DEC_USE_COUNT;
-		return NULL;
-	}
+	if (!data)
+		goto out_miss_args;
+
 	if (data->version != NFS_MOUNT_VERSION) {
 		printk("nfs warning: mount version %s than kernel\n",
 			data->version < NFS_MOUNT_VERSION ? "older" : "newer");
@@ -164,13 +178,19 @@
 			data->bsize  = 0;
 	}
 
+	/* We now require that the mount process passes the remote address */
+	memcpy(&srvaddr, &data->addr, sizeof(srvaddr));
+	if (srvaddr.sin_addr.s_addr == INADDR_ANY)
+		goto out_no_remote;
+
 	lock_super(sb);
 
-	server           = &sb->u.nfs_sb.s_server;
 	sb->s_magic      = NFS_SUPER_MAGIC;
 	sb->s_dev        = dev;
 	sb->s_op         = &nfs_sops;
 	sb->s_blocksize  = nfs_block_size(data->bsize, &sb->s_blocksize_bits);
+	sb->u.nfs_sb.s_root = data->root;
+	server           = &sb->u.nfs_sb.s_server;
 	server->rsize    = nfs_block_size(data->rsize, NULL);
 	server->wsize    = nfs_block_size(data->wsize, NULL);
 	server->flags    = data->flags;
@@ -179,15 +199,6 @@
 	server->acdirmin = data->acdirmin*HZ;
 	server->acdirmax = data->acdirmax*HZ;
 	strcpy(server->hostname, data->hostname);
-	sb->u.nfs_sb.s_root = data->root;
-
-	/* We now require that the mount process passes the remote address */
-	memcpy(&srvaddr, &data->addr, sizeof(srvaddr));
-	if (srvaddr.sin_addr.s_addr == INADDR_ANY) {
-		printk("NFS: mount program didn't pass remote address!\n");
-		MOD_DEC_USE_COUNT;
-		return NULL;
-	}
 
 	/* Which protocol do we use? */
 	tcp   = (data->flags & NFS_MOUNT_TCP);
@@ -210,18 +221,13 @@
 	/* Now create transport and client */
 	xprt = xprt_create_proto(tcp? IPPROTO_TCP : IPPROTO_UDP,
 						&srvaddr, &timeparms);
-	if (xprt == NULL) {
-		printk("NFS: cannot create RPC transport.\n");
-		goto failure;
-	}
+	if (xprt == NULL)
+		goto out_no_xprt;
 
 	clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
 						NFS_VERSION, authflavor);
-	if (clnt == NULL) {
-		printk("NFS: cannot create RPC client.\n");
-		xprt_destroy(xprt);
-		goto failure;
-	}
+	if (clnt == NULL)
+		goto out_no_client;
 
 	clnt->cl_intr     = (data->flags & NFS_MOUNT_INTR)? 1 : 0;
 	clnt->cl_softrtry = (data->flags & NFS_MOUNT_SOFT)? 1 : 0;
@@ -229,29 +235,67 @@
 	server->client    = clnt;
 
 	/* Fire up rpciod if not yet running */
+#ifdef RPCIOD_RESULT
+	if (rpciod_up())
+		goto out_no_iod;
+#else
 	rpciod_up();
+#endif
 
-	/* Unlock super block and try to get root fh attributes */
+	/*
+	 * Keep the super block locked while we try to get 
+	 * the root fh attributes.
+	 */
+	root_inode = nfs_fhget(sb, &data->root, NULL);
+	if (!root_inode)
+		goto out_no_root;
+	sb->s_root = d_alloc_root(root_inode, NULL);
+	if (!sb->s_root)
+		goto out_no_root;
+	/* We're airborne */
 	unlock_super(sb);
 
-	sb->s_root = d_alloc_root(nfs_fhget(sb, &data->root, NULL), NULL);
-	if (sb->s_root != NULL) {
-		/* We're airborne */
-		if (!(server->flags & NFS_MOUNT_NONLM))
-			lockd_up();
-		return sb;
-	}
+	/* Check whether to start the lockd process */
+	if (!(server->flags & NFS_MOUNT_NONLM))
+		lockd_up();
+	return sb;
 
 	/* Yargs. It didn't work out. */
+out_no_root:
 	printk("nfs_read_super: get root inode failed\n");
-	rpc_shutdown_client(server->client);
+	iput(root_inode);
 	rpciod_down();
+#ifdef RPCIOD_RESULT
+	goto out_shutdown;
 
-failure:
-	MOD_DEC_USE_COUNT;
-	if (sb->s_lock)
-		unlock_super(sb);
+out_no_iod:
+	printk("nfs_read_super: couldn't start rpciod!\n");
+out_shutdown:
+#endif
+	rpc_shutdown_client(server->client);
+	goto out_unlock;
+
+out_no_client:
+	printk("NFS: cannot create RPC client.\n");
+	xprt_destroy(xprt);
+	goto out_unlock;
+
+out_no_xprt:
+	printk("NFS: cannot create RPC transport.\n");
+out_unlock:
+	unlock_super(sb);
+	goto out_fail;
+
+out_no_remote:
+	printk("NFS: mount program didn't pass remote address!\n");
+	goto out_fail;
+
+out_miss_args:
+	printk("nfs_read_super: missing data argument\n");
+
+out_fail:
 	sb->s_dev = 0;
+	MOD_DEC_USE_COUNT;
 	return NULL;
 }
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov