aboutsummaryrefslogtreecommitdiff
path: root/fs/nfs/getroot.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-11-26 19:42:59 -0800
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-11-26 19:42:59 -0800
commit423eaf8f00d89ca79bb2c9d4d22e92c9774e2d8a (patch)
treee160521a6b059d50045ea47c3f730bf2c83c1f85 /fs/nfs/getroot.c
parent0685ab4fb8e527639d9867df60d49dccba85d842 (diff)
parent02fe494619d525ea803ab1f4f671186dc8a52f7a (diff)
Merge git://git.linux-nfs.org/pub/linux/nfs-2.6
* git://git.linux-nfs.org/pub/linux/nfs-2.6: NFS: Clean up new multi-segment direct I/O changes NFS: Ensure we return zero if applications attempt to write zero bytes NFS: Support multiple segment iovecs in the NFS direct I/O path NFS: Introduce iovec I/O helpers to fs/nfs/direct.c SUNRPC: Add missing "space" to net/sunrpc/auth_gss.c SUNRPC: make sunrpc/xprtsock.c:xs_setup_{udp,tcp}() static NFS: fs/nfs/dir.c should #include "internal.h" NFS: make nfs_wb_page_priority() static NFS: mount failure causes bad page state SUNRPC: remove NFS/RDMA client's binary sysctls kernel BUG at fs/nfs/namespace.c:108! - can be triggered by bad server sunrpc: rpc_pipe_poll may miss available data in some cases sunrpc: return error if unsupported enctype or cksumtype is encountered sunrpc: gss_pipe_downcall(), don't assume all errors are transient NFS: Fix the ustat() regression
Diffstat (limited to 'fs/nfs/getroot.c')
-rw-r--r--fs/nfs/getroot.c81
1 files changed, 27 insertions, 54 deletions
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index 522e5ad4d8a..0ee43843f4e 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -43,6 +43,25 @@
#define NFSDBG_FACILITY NFSDBG_CLIENT
/*
+ * Set the superblock root dentry.
+ * Note that this function frees the inode in case of error.
+ */
+static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *inode)
+{
+ /* The mntroot acts as the dummy root dentry for this superblock */
+ if (sb->s_root == NULL) {
+ sb->s_root = d_alloc_root(inode);
+ if (sb->s_root == NULL) {
+ iput(inode);
+ return -ENOMEM;
+ }
+ /* Circumvent igrab(): we know the inode is not being freed */
+ atomic_inc(&inode->i_count);
+ }
+ return 0;
+}
+
+/*
* get an NFS2/NFS3 root dentry from the root filehandle
*/
struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
@@ -54,33 +73,6 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
struct inode *inode;
int error;
- /* create a dummy root dentry with dummy inode for this superblock */
- if (!sb->s_root) {
- struct nfs_fh dummyfh;
- struct dentry *root;
- struct inode *iroot;
-
- memset(&dummyfh, 0, sizeof(dummyfh));
- memset(&fattr, 0, sizeof(fattr));
- nfs_fattr_init(&fattr);
- fattr.valid = NFS_ATTR_FATTR;
- fattr.type = NFDIR;
- fattr.mode = S_IFDIR | S_IRUSR | S_IWUSR;
- fattr.nlink = 2;
-
- iroot = nfs_fhget(sb, &dummyfh, &fattr);
- if (IS_ERR(iroot))
- return ERR_PTR(PTR_ERR(iroot));
-
- root = d_alloc_root(iroot);
- if (!root) {
- iput(iroot);
- return ERR_PTR(-ENOMEM);
- }
-
- sb->s_root = root;
- }
-
/* get the actual root for this mount */
fsinfo.fattr = &fattr;
@@ -96,6 +88,10 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
return ERR_PTR(PTR_ERR(inode));
}
+ error = nfs_superblock_set_dummy_root(sb, inode);
+ if (error != 0)
+ return ERR_PTR(error);
+
/* root dentries normally start off anonymous and get spliced in later
* if the dentry tree reaches them; however if the dentry already
* exists, we'll pick it up at this point and use it as the root
@@ -241,33 +237,6 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh)
dprintk("--> nfs4_get_root()\n");
- /* create a dummy root dentry with dummy inode for this superblock */
- if (!sb->s_root) {
- struct nfs_fh dummyfh;
- struct dentry *root;
- struct inode *iroot;
-
- memset(&dummyfh, 0, sizeof(dummyfh));
- memset(&fattr, 0, sizeof(fattr));
- nfs_fattr_init(&fattr);
- fattr.valid = NFS_ATTR_FATTR;
- fattr.type = NFDIR;
- fattr.mode = S_IFDIR | S_IRUSR | S_IWUSR;
- fattr.nlink = 2;
-
- iroot = nfs_fhget(sb, &dummyfh, &fattr);
- if (IS_ERR(iroot))
- return ERR_PTR(PTR_ERR(iroot));
-
- root = d_alloc_root(iroot);
- if (!root) {
- iput(iroot);
- return ERR_PTR(-ENOMEM);
- }
-
- sb->s_root = root;
- }
-
/* get the info about the server and filesystem */
error = nfs4_server_capabilities(server, mntfh);
if (error < 0) {
@@ -289,6 +258,10 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh)
return ERR_PTR(PTR_ERR(inode));
}
+ error = nfs_superblock_set_dummy_root(sb, inode);
+ if (error != 0)
+ return ERR_PTR(error);
+
/* root dentries normally start off anonymous and get spliced in later
* if the dentry tree reaches them; however if the dentry already
* exists, we'll pick it up at this point and use it as the root