diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/afs/Makefile | 1 | ||||
-rw-r--r-- | fs/afs/dir.c | 180 | ||||
-rw-r--r-- | fs/afs/dynroot.c | 209 | ||||
-rw-r--r-- | fs/afs/internal.h | 12 | ||||
-rw-r--r-- | fs/afs/super.c | 11 |
5 files changed, 228 insertions, 185 deletions
diff --git a/fs/afs/Makefile b/fs/afs/Makefile index 45b7fc405fa6..6a055423c192 100644 --- a/fs/afs/Makefile +++ b/fs/afs/Makefile | |||
@@ -12,6 +12,7 @@ kafs-objs := \ | |||
12 | cell.o \ | 12 | cell.o \ |
13 | cmservice.o \ | 13 | cmservice.o \ |
14 | dir.o \ | 14 | dir.o \ |
15 | dynroot.o \ | ||
15 | file.o \ | 16 | file.o \ |
16 | flock.o \ | 17 | flock.o \ |
17 | fsclient.o \ | 18 | fsclient.o \ |
diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 08b499504f63..405ebd609b87 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c | |||
@@ -10,25 +10,19 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
16 | #include <linux/namei.h> | 14 | #include <linux/namei.h> |
17 | #include <linux/pagemap.h> | 15 | #include <linux/pagemap.h> |
18 | #include <linux/ctype.h> | 16 | #include <linux/ctype.h> |
19 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
20 | #include <linux/dns_resolver.h> | ||
21 | #include "internal.h" | 18 | #include "internal.h" |
22 | 19 | ||
23 | static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, | 20 | static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, |
24 | unsigned int flags); | 21 | unsigned int flags); |
25 | static struct dentry *afs_dynroot_lookup(struct inode *dir, struct dentry *dentry, | ||
26 | unsigned int flags); | ||
27 | static int afs_dir_open(struct inode *inode, struct file *file); | 22 | static int afs_dir_open(struct inode *inode, struct file *file); |
28 | static int afs_readdir(struct file *file, struct dir_context *ctx); | 23 | static int afs_readdir(struct file *file, struct dir_context *ctx); |
29 | static int afs_d_revalidate(struct dentry *dentry, unsigned int flags); | 24 | static int afs_d_revalidate(struct dentry *dentry, unsigned int flags); |
30 | static int afs_d_delete(const struct dentry *dentry); | 25 | static int afs_d_delete(const struct dentry *dentry); |
31 | static void afs_d_release(struct dentry *dentry); | ||
32 | static int afs_lookup_one_filldir(struct dir_context *ctx, const char *name, int nlen, | 26 | static int afs_lookup_one_filldir(struct dir_context *ctx, const char *name, int nlen, |
33 | loff_t fpos, u64 ino, unsigned dtype); | 27 | loff_t fpos, u64 ino, unsigned dtype); |
34 | static int afs_lookup_filldir(struct dir_context *ctx, const char *name, int nlen, | 28 | static int afs_lookup_filldir(struct dir_context *ctx, const char *name, int nlen, |
@@ -69,17 +63,6 @@ const struct inode_operations afs_dir_inode_operations = { | |||
69 | .listxattr = afs_listxattr, | 63 | .listxattr = afs_listxattr, |
70 | }; | 64 | }; |
71 | 65 | ||
72 | const struct file_operations afs_dynroot_file_operations = { | ||
73 | .open = dcache_dir_open, | ||
74 | .release = dcache_dir_close, | ||
75 | .iterate_shared = dcache_readdir, | ||
76 | .llseek = dcache_dir_lseek, | ||
77 | }; | ||
78 | |||
79 | const struct inode_operations afs_dynroot_inode_operations = { | ||
80 | .lookup = afs_dynroot_lookup, | ||
81 | }; | ||
82 | |||
83 | const struct dentry_operations afs_fs_dentry_operations = { | 66 | const struct dentry_operations afs_fs_dentry_operations = { |
84 | .d_revalidate = afs_d_revalidate, | 67 | .d_revalidate = afs_d_revalidate, |
85 | .d_delete = afs_d_delete, | 68 | .d_delete = afs_d_delete, |
@@ -703,71 +686,6 @@ out: | |||
703 | } | 686 | } |
704 | 687 | ||
705 | /* | 688 | /* |
706 | * Probe to see if a cell may exist. This prevents positive dentries from | ||
707 | * being created unnecessarily. | ||
708 | */ | ||
709 | static int afs_probe_cell_name(struct dentry *dentry) | ||
710 | { | ||
711 | struct afs_cell *cell; | ||
712 | const char *name = dentry->d_name.name; | ||
713 | size_t len = dentry->d_name.len; | ||
714 | int ret; | ||
715 | |||
716 | /* Names prefixed with a dot are R/W mounts. */ | ||
717 | if (name[0] == '.') { | ||
718 | if (len == 1) | ||
719 | return -EINVAL; | ||
720 | name++; | ||
721 | len--; | ||
722 | } | ||
723 | |||
724 | cell = afs_lookup_cell_rcu(afs_d2net(dentry), name, len); | ||
725 | if (!IS_ERR(cell)) { | ||
726 | afs_put_cell(afs_d2net(dentry), cell); | ||
727 | return 0; | ||
728 | } | ||
729 | |||
730 | ret = dns_query("afsdb", name, len, "ipv4", NULL, NULL); | ||
731 | if (ret == -ENODATA) | ||
732 | ret = -EDESTADDRREQ; | ||
733 | return ret; | ||
734 | } | ||
735 | |||
736 | /* | ||
737 | * Try to auto mount the mountpoint with pseudo directory, if the autocell | ||
738 | * operation is setted. | ||
739 | */ | ||
740 | static struct inode *afs_try_auto_mntpt(struct dentry *dentry, struct inode *dir) | ||
741 | { | ||
742 | struct afs_vnode *vnode = AFS_FS_I(dir); | ||
743 | struct inode *inode; | ||
744 | int ret = -ENOENT; | ||
745 | |||
746 | _enter("%p{%pd}, {%x:%u}", | ||
747 | dentry, dentry, vnode->fid.vid, vnode->fid.vnode); | ||
748 | |||
749 | if (!test_bit(AFS_VNODE_AUTOCELL, &vnode->flags)) | ||
750 | goto out; | ||
751 | |||
752 | ret = afs_probe_cell_name(dentry); | ||
753 | if (ret < 0) | ||
754 | goto out; | ||
755 | |||
756 | inode = afs_iget_pseudo_dir(dir->i_sb, false); | ||
757 | if (IS_ERR(inode)) { | ||
758 | ret = PTR_ERR(inode); | ||
759 | goto out; | ||
760 | } | ||
761 | |||
762 | _leave("= %p", inode); | ||
763 | return inode; | ||
764 | |||
765 | out: | ||
766 | _leave("= %d", ret); | ||
767 | return ERR_PTR(ret); | ||
768 | } | ||
769 | |||
770 | /* | ||
771 | * Look up an entry in a directory with @sys substitution. | 689 | * Look up an entry in a directory with @sys substitution. |
772 | */ | 690 | */ |
773 | static struct dentry *afs_lookup_atsys(struct inode *dir, struct dentry *dentry, | 691 | static struct dentry *afs_lookup_atsys(struct inode *dir, struct dentry *dentry, |
@@ -911,105 +829,12 @@ success: | |||
911 | } | 829 | } |
912 | 830 | ||
913 | /* | 831 | /* |
914 | * Look up @cell in a dynroot directory. This is a substitution for the | ||
915 | * local cell name for the net namespace. | ||
916 | */ | ||
917 | static struct dentry *afs_lookup_atcell(struct dentry *dentry) | ||
918 | { | ||
919 | struct afs_cell *cell; | ||
920 | struct afs_net *net = afs_d2net(dentry); | ||
921 | struct dentry *ret; | ||
922 | unsigned int seq = 0; | ||
923 | char *name; | ||
924 | int len; | ||
925 | |||
926 | if (!net->ws_cell) | ||
927 | return ERR_PTR(-ENOENT); | ||
928 | |||
929 | ret = ERR_PTR(-ENOMEM); | ||
930 | name = kmalloc(AFS_MAXCELLNAME + 1, GFP_KERNEL); | ||
931 | if (!name) | ||
932 | goto out_p; | ||
933 | |||
934 | rcu_read_lock(); | ||
935 | do { | ||
936 | read_seqbegin_or_lock(&net->cells_lock, &seq); | ||
937 | cell = rcu_dereference_raw(net->ws_cell); | ||
938 | if (cell) { | ||
939 | len = cell->name_len; | ||
940 | memcpy(name, cell->name, len + 1); | ||
941 | } | ||
942 | } while (need_seqretry(&net->cells_lock, seq)); | ||
943 | done_seqretry(&net->cells_lock, seq); | ||
944 | rcu_read_unlock(); | ||
945 | |||
946 | ret = ERR_PTR(-ENOENT); | ||
947 | if (!cell) | ||
948 | goto out_n; | ||
949 | |||
950 | ret = lookup_one_len(name, dentry->d_parent, len); | ||
951 | |||
952 | /* We don't want to d_add() the @cell dentry here as we don't want to | ||
953 | * the cached dentry to hide changes to the local cell name. | ||
954 | */ | ||
955 | |||
956 | out_n: | ||
957 | kfree(name); | ||
958 | out_p: | ||
959 | return ret; | ||
960 | } | ||
961 | |||
962 | /* | ||
963 | * Look up an entry in a dynroot directory. | ||
964 | */ | ||
965 | static struct dentry *afs_dynroot_lookup(struct inode *dir, struct dentry *dentry, | ||
966 | unsigned int flags) | ||
967 | { | ||
968 | struct afs_vnode *vnode; | ||
969 | struct inode *inode; | ||
970 | int ret; | ||
971 | |||
972 | vnode = AFS_FS_I(dir); | ||
973 | |||
974 | _enter("%pd", dentry); | ||
975 | |||
976 | ASSERTCMP(d_inode(dentry), ==, NULL); | ||
977 | |||
978 | if (dentry->d_name.len >= AFSNAMEMAX) { | ||
979 | _leave(" = -ENAMETOOLONG"); | ||
980 | return ERR_PTR(-ENAMETOOLONG); | ||
981 | } | ||
982 | |||
983 | if (dentry->d_name.len == 5 && | ||
984 | memcmp(dentry->d_name.name, "@cell", 5) == 0) | ||
985 | return afs_lookup_atcell(dentry); | ||
986 | |||
987 | inode = afs_try_auto_mntpt(dentry, dir); | ||
988 | if (IS_ERR(inode)) { | ||
989 | ret = PTR_ERR(inode); | ||
990 | if (ret == -ENOENT) { | ||
991 | d_add(dentry, NULL); | ||
992 | _leave(" = NULL [negative]"); | ||
993 | return NULL; | ||
994 | } | ||
995 | _leave(" = %d [do]", ret); | ||
996 | return ERR_PTR(ret); | ||
997 | } | ||
998 | |||
999 | d_add(dentry, inode); | ||
1000 | _leave(" = 0 { ino=%lu v=%u }", | ||
1001 | d_inode(dentry)->i_ino, d_inode(dentry)->i_generation); | ||
1002 | return NULL; | ||
1003 | } | ||
1004 | |||
1005 | /* | ||
1006 | * check that a dentry lookup hit has found a valid entry | 832 | * check that a dentry lookup hit has found a valid entry |
1007 | * - NOTE! the hit can be a negative hit too, so we can't assume we have an | 833 | * - NOTE! the hit can be a negative hit too, so we can't assume we have an |
1008 | * inode | 834 | * inode |
1009 | */ | 835 | */ |
1010 | static int afs_d_revalidate(struct dentry *dentry, unsigned int flags) | 836 | static int afs_d_revalidate(struct dentry *dentry, unsigned int flags) |
1011 | { | 837 | { |
1012 | struct afs_super_info *as = dentry->d_sb->s_fs_info; | ||
1013 | struct afs_vnode *vnode, *dir; | 838 | struct afs_vnode *vnode, *dir; |
1014 | struct afs_fid uninitialized_var(fid); | 839 | struct afs_fid uninitialized_var(fid); |
1015 | struct dentry *parent; | 840 | struct dentry *parent; |
@@ -1021,9 +846,6 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags) | |||
1021 | if (flags & LOOKUP_RCU) | 846 | if (flags & LOOKUP_RCU) |
1022 | return -ECHILD; | 847 | return -ECHILD; |
1023 | 848 | ||
1024 | if (as->dyn_root) | ||
1025 | return 1; | ||
1026 | |||
1027 | if (d_really_is_positive(dentry)) { | 849 | if (d_really_is_positive(dentry)) { |
1028 | vnode = AFS_FS_I(d_inode(dentry)); | 850 | vnode = AFS_FS_I(d_inode(dentry)); |
1029 | _enter("{v={%x:%u} n=%pd fl=%lx},", | 851 | _enter("{v={%x:%u} n=%pd fl=%lx},", |
@@ -1181,7 +1003,7 @@ zap: | |||
1181 | /* | 1003 | /* |
1182 | * handle dentry release | 1004 | * handle dentry release |
1183 | */ | 1005 | */ |
1184 | static void afs_d_release(struct dentry *dentry) | 1006 | void afs_d_release(struct dentry *dentry) |
1185 | { | 1007 | { |
1186 | _enter("%pd", dentry); | 1008 | _enter("%pd", dentry); |
1187 | } | 1009 | } |
diff --git a/fs/afs/dynroot.c b/fs/afs/dynroot.c new file mode 100644 index 000000000000..983f3946ab57 --- /dev/null +++ b/fs/afs/dynroot.c | |||
@@ -0,0 +1,209 @@ | |||
1 | /* dir.c: AFS dynamic root handling | ||
2 | * | ||
3 | * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/fs.h> | ||
13 | #include <linux/namei.h> | ||
14 | #include <linux/dns_resolver.h> | ||
15 | #include "internal.h" | ||
16 | |||
17 | const struct file_operations afs_dynroot_file_operations = { | ||
18 | .open = dcache_dir_open, | ||
19 | .release = dcache_dir_close, | ||
20 | .iterate_shared = dcache_readdir, | ||
21 | .llseek = dcache_dir_lseek, | ||
22 | }; | ||
23 | |||
24 | /* | ||
25 | * Probe to see if a cell may exist. This prevents positive dentries from | ||
26 | * being created unnecessarily. | ||
27 | */ | ||
28 | static int afs_probe_cell_name(struct dentry *dentry) | ||
29 | { | ||
30 | struct afs_cell *cell; | ||
31 | const char *name = dentry->d_name.name; | ||
32 | size_t len = dentry->d_name.len; | ||
33 | int ret; | ||
34 | |||
35 | /* Names prefixed with a dot are R/W mounts. */ | ||
36 | if (name[0] == '.') { | ||
37 | if (len == 1) | ||
38 | return -EINVAL; | ||
39 | name++; | ||
40 | len--; | ||
41 | } | ||
42 | |||
43 | cell = afs_lookup_cell_rcu(afs_d2net(dentry), name, len); | ||
44 | if (!IS_ERR(cell)) { | ||
45 | afs_put_cell(afs_d2net(dentry), cell); | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | ret = dns_query("afsdb", name, len, "ipv4", NULL, NULL); | ||
50 | if (ret == -ENODATA) | ||
51 | ret = -EDESTADDRREQ; | ||
52 | return ret; | ||
53 | } | ||
54 | |||
55 | /* | ||
56 | * Try to auto mount the mountpoint with pseudo directory, if the autocell | ||
57 | * operation is setted. | ||
58 | */ | ||
59 | struct inode *afs_try_auto_mntpt(struct dentry *dentry, struct inode *dir) | ||
60 | { | ||
61 | struct afs_vnode *vnode = AFS_FS_I(dir); | ||
62 | struct inode *inode; | ||
63 | int ret = -ENOENT; | ||
64 | |||
65 | _enter("%p{%pd}, {%x:%u}", | ||
66 | dentry, dentry, vnode->fid.vid, vnode->fid.vnode); | ||
67 | |||
68 | if (!test_bit(AFS_VNODE_AUTOCELL, &vnode->flags)) | ||
69 | goto out; | ||
70 | |||
71 | ret = afs_probe_cell_name(dentry); | ||
72 | if (ret < 0) | ||
73 | goto out; | ||
74 | |||
75 | inode = afs_iget_pseudo_dir(dir->i_sb, false); | ||
76 | if (IS_ERR(inode)) { | ||
77 | ret = PTR_ERR(inode); | ||
78 | goto out; | ||
79 | } | ||
80 | |||
81 | _leave("= %p", inode); | ||
82 | return inode; | ||
83 | |||
84 | out: | ||
85 | _leave("= %d", ret); | ||
86 | return ERR_PTR(ret); | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * Look up @cell in a dynroot directory. This is a substitution for the | ||
91 | * local cell name for the net namespace. | ||
92 | */ | ||
93 | static struct dentry *afs_lookup_atcell(struct dentry *dentry) | ||
94 | { | ||
95 | struct afs_cell *cell; | ||
96 | struct afs_net *net = afs_d2net(dentry); | ||
97 | struct dentry *ret; | ||
98 | unsigned int seq = 0; | ||
99 | char *name; | ||
100 | int len; | ||
101 | |||
102 | if (!net->ws_cell) | ||
103 | return ERR_PTR(-ENOENT); | ||
104 | |||
105 | ret = ERR_PTR(-ENOMEM); | ||
106 | name = kmalloc(AFS_MAXCELLNAME + 1, GFP_KERNEL); | ||
107 | if (!name) | ||
108 | goto out_p; | ||
109 | |||
110 | rcu_read_lock(); | ||
111 | do { | ||
112 | read_seqbegin_or_lock(&net->cells_lock, &seq); | ||
113 | cell = rcu_dereference_raw(net->ws_cell); | ||
114 | if (cell) { | ||
115 | len = cell->name_len; | ||
116 | memcpy(name, cell->name, len + 1); | ||
117 | } | ||
118 | } while (need_seqretry(&net->cells_lock, seq)); | ||
119 | done_seqretry(&net->cells_lock, seq); | ||
120 | rcu_read_unlock(); | ||
121 | |||
122 | ret = ERR_PTR(-ENOENT); | ||
123 | if (!cell) | ||
124 | goto out_n; | ||
125 | |||
126 | ret = lookup_one_len(name, dentry->d_parent, len); | ||
127 | |||
128 | /* We don't want to d_add() the @cell dentry here as we don't want to | ||
129 | * the cached dentry to hide changes to the local cell name. | ||
130 | */ | ||
131 | |||
132 | out_n: | ||
133 | kfree(name); | ||
134 | out_p: | ||
135 | return ret; | ||
136 | } | ||
137 | |||
138 | /* | ||
139 | * Look up an entry in a dynroot directory. | ||
140 | */ | ||
141 | static struct dentry *afs_dynroot_lookup(struct inode *dir, struct dentry *dentry, | ||
142 | unsigned int flags) | ||
143 | { | ||
144 | struct afs_vnode *vnode; | ||
145 | struct inode *inode; | ||
146 | int ret; | ||
147 | |||
148 | vnode = AFS_FS_I(dir); | ||
149 | |||
150 | _enter("%pd", dentry); | ||
151 | |||
152 | ASSERTCMP(d_inode(dentry), ==, NULL); | ||
153 | |||
154 | if (dentry->d_name.len >= AFSNAMEMAX) { | ||
155 | _leave(" = -ENAMETOOLONG"); | ||
156 | return ERR_PTR(-ENAMETOOLONG); | ||
157 | } | ||
158 | |||
159 | if (dentry->d_name.len == 5 && | ||
160 | memcmp(dentry->d_name.name, "@cell", 5) == 0) | ||
161 | return afs_lookup_atcell(dentry); | ||
162 | |||
163 | inode = afs_try_auto_mntpt(dentry, dir); | ||
164 | if (IS_ERR(inode)) { | ||
165 | ret = PTR_ERR(inode); | ||
166 | if (ret == -ENOENT) { | ||
167 | d_add(dentry, NULL); | ||
168 | _leave(" = NULL [negative]"); | ||
169 | return NULL; | ||
170 | } | ||
171 | _leave(" = %d [do]", ret); | ||
172 | return ERR_PTR(ret); | ||
173 | } | ||
174 | |||
175 | d_add(dentry, inode); | ||
176 | _leave(" = 0 { ino=%lu v=%u }", | ||
177 | d_inode(dentry)->i_ino, d_inode(dentry)->i_generation); | ||
178 | return NULL; | ||
179 | } | ||
180 | |||
181 | const struct inode_operations afs_dynroot_inode_operations = { | ||
182 | .lookup = afs_dynroot_lookup, | ||
183 | }; | ||
184 | |||
185 | /* | ||
186 | * Dirs in the dynamic root don't need revalidation. | ||
187 | */ | ||
188 | static int afs_dynroot_d_revalidate(struct dentry *dentry, unsigned int flags) | ||
189 | { | ||
190 | return 1; | ||
191 | } | ||
192 | |||
193 | /* | ||
194 | * Allow the VFS to enquire as to whether a dentry should be unhashed (mustn't | ||
195 | * sleep) | ||
196 | * - called from dput() when d_count is going to 0. | ||
197 | * - return 1 to request dentry be unhashed, 0 otherwise | ||
198 | */ | ||
199 | static int afs_dynroot_d_delete(const struct dentry *dentry) | ||
200 | { | ||
201 | return d_really_is_positive(dentry); | ||
202 | } | ||
203 | |||
204 | const struct dentry_operations afs_dynroot_dentry_operations = { | ||
205 | .d_revalidate = afs_dynroot_d_revalidate, | ||
206 | .d_delete = afs_dynroot_d_delete, | ||
207 | .d_release = afs_d_release, | ||
208 | .d_automount = afs_d_automount, | ||
209 | }; | ||
diff --git a/fs/afs/internal.h b/fs/afs/internal.h index adf9b17d328c..b6ec46ae03c3 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h | |||
@@ -671,11 +671,19 @@ extern bool afs_cm_incoming_call(struct afs_call *); | |||
671 | */ | 671 | */ |
672 | extern const struct file_operations afs_dir_file_operations; | 672 | extern const struct file_operations afs_dir_file_operations; |
673 | extern const struct inode_operations afs_dir_inode_operations; | 673 | extern const struct inode_operations afs_dir_inode_operations; |
674 | extern const struct file_operations afs_dynroot_file_operations; | ||
675 | extern const struct inode_operations afs_dynroot_inode_operations; | ||
676 | extern const struct dentry_operations afs_fs_dentry_operations; | 674 | extern const struct dentry_operations afs_fs_dentry_operations; |
677 | 675 | ||
678 | extern bool afs_dir_check_page(struct inode *, struct page *); | 676 | extern bool afs_dir_check_page(struct inode *, struct page *); |
677 | extern void afs_d_release(struct dentry *); | ||
678 | |||
679 | /* | ||
680 | * dynroot.c | ||
681 | */ | ||
682 | extern const struct file_operations afs_dynroot_file_operations; | ||
683 | extern const struct inode_operations afs_dynroot_inode_operations; | ||
684 | extern const struct dentry_operations afs_dynroot_dentry_operations; | ||
685 | |||
686 | extern struct inode *afs_try_auto_mntpt(struct dentry *, struct inode *); | ||
679 | 687 | ||
680 | /* | 688 | /* |
681 | * file.c | 689 | * file.c |
diff --git a/fs/afs/super.c b/fs/afs/super.c index 3623c952b6ff..65081ec3c36e 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c | |||
@@ -154,7 +154,7 @@ static int afs_show_devname(struct seq_file *m, struct dentry *root) | |||
154 | seq_puts(m, "none"); | 154 | seq_puts(m, "none"); |
155 | return 0; | 155 | return 0; |
156 | } | 156 | } |
157 | 157 | ||
158 | switch (volume->type) { | 158 | switch (volume->type) { |
159 | case AFSVL_RWVOL: | 159 | case AFSVL_RWVOL: |
160 | break; | 160 | break; |
@@ -269,7 +269,7 @@ static int afs_parse_device_name(struct afs_mount_params *params, | |||
269 | int cellnamesz; | 269 | int cellnamesz; |
270 | 270 | ||
271 | _enter(",%s", name); | 271 | _enter(",%s", name); |
272 | 272 | ||
273 | if (!name) { | 273 | if (!name) { |
274 | printk(KERN_ERR "kAFS: no volume name specified\n"); | 274 | printk(KERN_ERR "kAFS: no volume name specified\n"); |
275 | return -EINVAL; | 275 | return -EINVAL; |
@@ -418,7 +418,10 @@ static int afs_fill_super(struct super_block *sb, | |||
418 | if (!sb->s_root) | 418 | if (!sb->s_root) |
419 | goto error; | 419 | goto error; |
420 | 420 | ||
421 | sb->s_d_op = &afs_fs_dentry_operations; | 421 | if (params->dyn_root) |
422 | sb->s_d_op = &afs_dynroot_dentry_operations; | ||
423 | else | ||
424 | sb->s_d_op = &afs_fs_dentry_operations; | ||
422 | 425 | ||
423 | _leave(" = 0"); | 426 | _leave(" = 0"); |
424 | return 0; | 427 | return 0; |
@@ -676,7 +679,7 @@ static int afs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
676 | buf->f_bfree = 0; | 679 | buf->f_bfree = 0; |
677 | return 0; | 680 | return 0; |
678 | } | 681 | } |
679 | 682 | ||
680 | key = afs_request_key(vnode->volume->cell); | 683 | key = afs_request_key(vnode->volume->cell); |
681 | if (IS_ERR(key)) | 684 | if (IS_ERR(key)) |
682 | return PTR_ERR(key); | 685 | return PTR_ERR(key); |