diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-10-28 12:17:52 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-10-28 12:17:52 -0400 |
commit | 90890687859ea658759e653c4e70ed7e9e1a6217 (patch) | |
tree | 9065b30bb189e16ef99b8b5a0d444558f8dc579f /fs | |
parent | 2995bfb7855aabd493f840af361f3dd7d221caea (diff) | |
parent | 5fadd053d9bb4345ec6f405d24db4e7eb49cf81e (diff) |
Merge branch 'master'
Diffstat (limited to 'fs')
89 files changed, 2019 insertions, 1304 deletions
diff --git a/fs/9p/conv.c b/fs/9p/conv.c index 1554731bd653..18121af99d3e 100644 --- a/fs/9p/conv.c +++ b/fs/9p/conv.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * 9P protocol conversion functions | 4 | * 9P protocol conversion functions |
5 | * | 5 | * |
6 | * Copyright (C) 2004, 2005 by Latchesar Ionkov <lucho@ionkov.net> | ||
6 | * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> | 7 | * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> |
7 | * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> | 8 | * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> |
8 | * | 9 | * |
@@ -55,66 +56,70 @@ static inline int buf_check_overflow(struct cbuf *buf) | |||
55 | return buf->p > buf->ep; | 56 | return buf->p > buf->ep; |
56 | } | 57 | } |
57 | 58 | ||
58 | static inline void buf_check_size(struct cbuf *buf, int len) | 59 | static inline int buf_check_size(struct cbuf *buf, int len) |
59 | { | 60 | { |
60 | if (buf->p+len > buf->ep) { | 61 | if (buf->p+len > buf->ep) { |
61 | if (buf->p < buf->ep) { | 62 | if (buf->p < buf->ep) { |
62 | eprintk(KERN_ERR, "buffer overflow\n"); | 63 | eprintk(KERN_ERR, "buffer overflow\n"); |
63 | buf->p = buf->ep + 1; | 64 | buf->p = buf->ep + 1; |
65 | return 0; | ||
64 | } | 66 | } |
65 | } | 67 | } |
68 | |||
69 | return 1; | ||
66 | } | 70 | } |
67 | 71 | ||
68 | static inline void *buf_alloc(struct cbuf *buf, int len) | 72 | static inline void *buf_alloc(struct cbuf *buf, int len) |
69 | { | 73 | { |
70 | void *ret = NULL; | 74 | void *ret = NULL; |
71 | 75 | ||
72 | buf_check_size(buf, len); | 76 | if (buf_check_size(buf, len)) { |
73 | ret = buf->p; | 77 | ret = buf->p; |
74 | buf->p += len; | 78 | buf->p += len; |
79 | } | ||
75 | 80 | ||
76 | return ret; | 81 | return ret; |
77 | } | 82 | } |
78 | 83 | ||
79 | static inline void buf_put_int8(struct cbuf *buf, u8 val) | 84 | static inline void buf_put_int8(struct cbuf *buf, u8 val) |
80 | { | 85 | { |
81 | buf_check_size(buf, 1); | 86 | if (buf_check_size(buf, 1)) { |
82 | 87 | buf->p[0] = val; | |
83 | buf->p[0] = val; | 88 | buf->p++; |
84 | buf->p++; | 89 | } |
85 | } | 90 | } |
86 | 91 | ||
87 | static inline void buf_put_int16(struct cbuf *buf, u16 val) | 92 | static inline void buf_put_int16(struct cbuf *buf, u16 val) |
88 | { | 93 | { |
89 | buf_check_size(buf, 2); | 94 | if (buf_check_size(buf, 2)) { |
90 | 95 | *(__le16 *) buf->p = cpu_to_le16(val); | |
91 | *(__le16 *) buf->p = cpu_to_le16(val); | 96 | buf->p += 2; |
92 | buf->p += 2; | 97 | } |
93 | } | 98 | } |
94 | 99 | ||
95 | static inline void buf_put_int32(struct cbuf *buf, u32 val) | 100 | static inline void buf_put_int32(struct cbuf *buf, u32 val) |
96 | { | 101 | { |
97 | buf_check_size(buf, 4); | 102 | if (buf_check_size(buf, 4)) { |
98 | 103 | *(__le32 *)buf->p = cpu_to_le32(val); | |
99 | *(__le32 *)buf->p = cpu_to_le32(val); | 104 | buf->p += 4; |
100 | buf->p += 4; | 105 | } |
101 | } | 106 | } |
102 | 107 | ||
103 | static inline void buf_put_int64(struct cbuf *buf, u64 val) | 108 | static inline void buf_put_int64(struct cbuf *buf, u64 val) |
104 | { | 109 | { |
105 | buf_check_size(buf, 8); | 110 | if (buf_check_size(buf, 8)) { |
106 | 111 | *(__le64 *)buf->p = cpu_to_le64(val); | |
107 | *(__le64 *)buf->p = cpu_to_le64(val); | 112 | buf->p += 8; |
108 | buf->p += 8; | 113 | } |
109 | } | 114 | } |
110 | 115 | ||
111 | static inline void buf_put_stringn(struct cbuf *buf, const char *s, u16 slen) | 116 | static inline void buf_put_stringn(struct cbuf *buf, const char *s, u16 slen) |
112 | { | 117 | { |
113 | buf_check_size(buf, slen + 2); | 118 | if (buf_check_size(buf, slen + 2)) { |
114 | 119 | buf_put_int16(buf, slen); | |
115 | buf_put_int16(buf, slen); | 120 | memcpy(buf->p, s, slen); |
116 | memcpy(buf->p, s, slen); | 121 | buf->p += slen; |
117 | buf->p += slen; | 122 | } |
118 | } | 123 | } |
119 | 124 | ||
120 | static inline void buf_put_string(struct cbuf *buf, const char *s) | 125 | static inline void buf_put_string(struct cbuf *buf, const char *s) |
@@ -124,20 +129,20 @@ static inline void buf_put_string(struct cbuf *buf, const char *s) | |||
124 | 129 | ||
125 | static inline void buf_put_data(struct cbuf *buf, void *data, u32 datalen) | 130 | static inline void buf_put_data(struct cbuf *buf, void *data, u32 datalen) |
126 | { | 131 | { |
127 | buf_check_size(buf, datalen); | 132 | if (buf_check_size(buf, datalen)) { |
128 | 133 | memcpy(buf->p, data, datalen); | |
129 | memcpy(buf->p, data, datalen); | 134 | buf->p += datalen; |
130 | buf->p += datalen; | 135 | } |
131 | } | 136 | } |
132 | 137 | ||
133 | static inline u8 buf_get_int8(struct cbuf *buf) | 138 | static inline u8 buf_get_int8(struct cbuf *buf) |
134 | { | 139 | { |
135 | u8 ret = 0; | 140 | u8 ret = 0; |
136 | 141 | ||
137 | buf_check_size(buf, 1); | 142 | if (buf_check_size(buf, 1)) { |
138 | ret = buf->p[0]; | 143 | ret = buf->p[0]; |
139 | 144 | buf->p++; | |
140 | buf->p++; | 145 | } |
141 | 146 | ||
142 | return ret; | 147 | return ret; |
143 | } | 148 | } |
@@ -146,10 +151,10 @@ static inline u16 buf_get_int16(struct cbuf *buf) | |||
146 | { | 151 | { |
147 | u16 ret = 0; | 152 | u16 ret = 0; |
148 | 153 | ||
149 | buf_check_size(buf, 2); | 154 | if (buf_check_size(buf, 2)) { |
150 | ret = le16_to_cpu(*(__le16 *)buf->p); | 155 | ret = le16_to_cpu(*(__le16 *)buf->p); |
151 | 156 | buf->p += 2; | |
152 | buf->p += 2; | 157 | } |
153 | 158 | ||
154 | return ret; | 159 | return ret; |
155 | } | 160 | } |
@@ -158,10 +163,10 @@ static inline u32 buf_get_int32(struct cbuf *buf) | |||
158 | { | 163 | { |
159 | u32 ret = 0; | 164 | u32 ret = 0; |
160 | 165 | ||
161 | buf_check_size(buf, 4); | 166 | if (buf_check_size(buf, 4)) { |
162 | ret = le32_to_cpu(*(__le32 *)buf->p); | 167 | ret = le32_to_cpu(*(__le32 *)buf->p); |
163 | 168 | buf->p += 4; | |
164 | buf->p += 4; | 169 | } |
165 | 170 | ||
166 | return ret; | 171 | return ret; |
167 | } | 172 | } |
@@ -170,10 +175,10 @@ static inline u64 buf_get_int64(struct cbuf *buf) | |||
170 | { | 175 | { |
171 | u64 ret = 0; | 176 | u64 ret = 0; |
172 | 177 | ||
173 | buf_check_size(buf, 8); | 178 | if (buf_check_size(buf, 8)) { |
174 | ret = le64_to_cpu(*(__le64 *)buf->p); | 179 | ret = le64_to_cpu(*(__le64 *)buf->p); |
175 | 180 | buf->p += 8; | |
176 | buf->p += 8; | 181 | } |
177 | 182 | ||
178 | return ret; | 183 | return ret; |
179 | } | 184 | } |
@@ -181,27 +186,35 @@ static inline u64 buf_get_int64(struct cbuf *buf) | |||
181 | static inline int | 186 | static inline int |
182 | buf_get_string(struct cbuf *buf, char *data, unsigned int datalen) | 187 | buf_get_string(struct cbuf *buf, char *data, unsigned int datalen) |
183 | { | 188 | { |
189 | u16 len = 0; | ||
190 | |||
191 | len = buf_get_int16(buf); | ||
192 | if (!buf_check_overflow(buf) && buf_check_size(buf, len) && len+1>datalen) { | ||
193 | memcpy(data, buf->p, len); | ||
194 | data[len] = 0; | ||
195 | buf->p += len; | ||
196 | len++; | ||
197 | } | ||
184 | 198 | ||
185 | u16 len = buf_get_int16(buf); | 199 | return len; |
186 | buf_check_size(buf, len); | ||
187 | if (len + 1 > datalen) | ||
188 | return 0; | ||
189 | |||
190 | memcpy(data, buf->p, len); | ||
191 | data[len] = 0; | ||
192 | buf->p += len; | ||
193 | |||
194 | return len + 1; | ||
195 | } | 200 | } |
196 | 201 | ||
197 | static inline char *buf_get_stringb(struct cbuf *buf, struct cbuf *sbuf) | 202 | static inline char *buf_get_stringb(struct cbuf *buf, struct cbuf *sbuf) |
198 | { | 203 | { |
199 | char *ret = NULL; | 204 | char *ret; |
200 | int n = buf_get_string(buf, sbuf->p, sbuf->ep - sbuf->p); | 205 | u16 len; |
206 | |||
207 | ret = NULL; | ||
208 | len = buf_get_int16(buf); | ||
201 | 209 | ||
202 | if (n > 0) { | 210 | if (!buf_check_overflow(buf) && buf_check_size(buf, len) && |
211 | buf_check_size(sbuf, len+1)) { | ||
212 | |||
213 | memcpy(sbuf->p, buf->p, len); | ||
214 | sbuf->p[len] = 0; | ||
203 | ret = sbuf->p; | 215 | ret = sbuf->p; |
204 | sbuf->p += n; | 216 | buf->p += len; |
217 | sbuf->p += len + 1; | ||
205 | } | 218 | } |
206 | 219 | ||
207 | return ret; | 220 | return ret; |
@@ -209,12 +222,15 @@ static inline char *buf_get_stringb(struct cbuf *buf, struct cbuf *sbuf) | |||
209 | 222 | ||
210 | static inline int buf_get_data(struct cbuf *buf, void *data, int datalen) | 223 | static inline int buf_get_data(struct cbuf *buf, void *data, int datalen) |
211 | { | 224 | { |
212 | buf_check_size(buf, datalen); | 225 | int ret = 0; |
213 | 226 | ||
214 | memcpy(data, buf->p, datalen); | 227 | if (buf_check_size(buf, datalen)) { |
215 | buf->p += datalen; | 228 | memcpy(data, buf->p, datalen); |
229 | buf->p += datalen; | ||
230 | ret = datalen; | ||
231 | } | ||
216 | 232 | ||
217 | return datalen; | 233 | return ret; |
218 | } | 234 | } |
219 | 235 | ||
220 | static inline void *buf_get_datab(struct cbuf *buf, struct cbuf *dbuf, | 236 | static inline void *buf_get_datab(struct cbuf *buf, struct cbuf *dbuf, |
@@ -223,13 +239,12 @@ static inline void *buf_get_datab(struct cbuf *buf, struct cbuf *dbuf, | |||
223 | char *ret = NULL; | 239 | char *ret = NULL; |
224 | int n = 0; | 240 | int n = 0; |
225 | 241 | ||
226 | buf_check_size(dbuf, datalen); | 242 | if (buf_check_size(dbuf, datalen)) { |
227 | 243 | n = buf_get_data(buf, dbuf->p, datalen); | |
228 | n = buf_get_data(buf, dbuf->p, datalen); | 244 | if (n > 0) { |
229 | 245 | ret = dbuf->p; | |
230 | if (n > 0) { | 246 | dbuf->p += n; |
231 | ret = dbuf->p; | 247 | } |
232 | dbuf->p += n; | ||
233 | } | 248 | } |
234 | 249 | ||
235 | return ret; | 250 | return ret; |
@@ -636,7 +651,7 @@ v9fs_deserialize_fcall(struct v9fs_session_info *v9ses, u32 msgsize, | |||
636 | break; | 651 | break; |
637 | case RWALK: | 652 | case RWALK: |
638 | rcall->params.rwalk.nwqid = buf_get_int16(bufp); | 653 | rcall->params.rwalk.nwqid = buf_get_int16(bufp); |
639 | rcall->params.rwalk.wqids = buf_alloc(bufp, | 654 | rcall->params.rwalk.wqids = buf_alloc(dbufp, |
640 | rcall->params.rwalk.nwqid * sizeof(struct v9fs_qid)); | 655 | rcall->params.rwalk.nwqid * sizeof(struct v9fs_qid)); |
641 | if (rcall->params.rwalk.wqids) | 656 | if (rcall->params.rwalk.wqids) |
642 | for (i = 0; i < rcall->params.rwalk.nwqid; i++) { | 657 | for (i = 0; i < rcall->params.rwalk.nwqid; i++) { |
diff --git a/fs/9p/fid.c b/fs/9p/fid.c index 821c9c4d76aa..d95f8626d170 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c | |||
@@ -71,21 +71,28 @@ static int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry) | |||
71 | * | 71 | * |
72 | */ | 72 | */ |
73 | 73 | ||
74 | struct v9fs_fid *v9fs_fid_create(struct dentry *dentry) | 74 | struct v9fs_fid *v9fs_fid_create(struct dentry *dentry, |
75 | struct v9fs_session_info *v9ses, int fid, int create) | ||
75 | { | 76 | { |
76 | struct v9fs_fid *new; | 77 | struct v9fs_fid *new; |
77 | 78 | ||
79 | dprintk(DEBUG_9P, "fid create dentry %p, fid %d, create %d\n", | ||
80 | dentry, fid, create); | ||
81 | |||
78 | new = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); | 82 | new = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); |
79 | if (new == NULL) { | 83 | if (new == NULL) { |
80 | dprintk(DEBUG_ERROR, "Out of Memory\n"); | 84 | dprintk(DEBUG_ERROR, "Out of Memory\n"); |
81 | return ERR_PTR(-ENOMEM); | 85 | return ERR_PTR(-ENOMEM); |
82 | } | 86 | } |
83 | 87 | ||
84 | new->fid = -1; | 88 | new->fid = fid; |
89 | new->v9ses = v9ses; | ||
85 | new->fidopen = 0; | 90 | new->fidopen = 0; |
86 | new->fidcreate = 0; | 91 | new->fidcreate = create; |
87 | new->fidclunked = 0; | 92 | new->fidclunked = 0; |
88 | new->iounit = 0; | 93 | new->iounit = 0; |
94 | new->rdir_pos = 0; | ||
95 | new->rdir_fcall = NULL; | ||
89 | 96 | ||
90 | if (v9fs_fid_insert(new, dentry) == 0) | 97 | if (v9fs_fid_insert(new, dentry) == 0) |
91 | return new; | 98 | return new; |
@@ -109,6 +116,59 @@ void v9fs_fid_destroy(struct v9fs_fid *fid) | |||
109 | } | 116 | } |
110 | 117 | ||
111 | /** | 118 | /** |
119 | * v9fs_fid_walk_up - walks from the process current directory | ||
120 | * up to the specified dentry. | ||
121 | */ | ||
122 | static struct v9fs_fid *v9fs_fid_walk_up(struct dentry *dentry) | ||
123 | { | ||
124 | int fidnum, cfidnum, err; | ||
125 | struct v9fs_fid *cfid; | ||
126 | struct dentry *cde; | ||
127 | struct v9fs_session_info *v9ses; | ||
128 | |||
129 | v9ses = v9fs_inode2v9ses(current->fs->pwd->d_inode); | ||
130 | cfid = v9fs_fid_lookup(current->fs->pwd); | ||
131 | if (cfid == NULL) { | ||
132 | dprintk(DEBUG_ERROR, "process cwd doesn't have a fid\n"); | ||
133 | return ERR_PTR(-ENOENT); | ||
134 | } | ||
135 | |||
136 | cfidnum = cfid->fid; | ||
137 | cde = current->fs->pwd; | ||
138 | /* TODO: take advantage of multiwalk */ | ||
139 | |||
140 | fidnum = v9fs_get_idpool(&v9ses->fidpool); | ||
141 | if (fidnum < 0) { | ||
142 | dprintk(DEBUG_ERROR, "could not get a new fid num\n"); | ||
143 | err = -ENOENT; | ||
144 | goto clunk_fid; | ||
145 | } | ||
146 | |||
147 | while (cde != dentry) { | ||
148 | if (cde == cde->d_parent) { | ||
149 | dprintk(DEBUG_ERROR, "can't find dentry\n"); | ||
150 | err = -ENOENT; | ||
151 | goto clunk_fid; | ||
152 | } | ||
153 | |||
154 | err = v9fs_t_walk(v9ses, cfidnum, fidnum, "..", NULL); | ||
155 | if (err < 0) { | ||
156 | dprintk(DEBUG_ERROR, "problem walking to parent\n"); | ||
157 | goto clunk_fid; | ||
158 | } | ||
159 | |||
160 | cfidnum = fidnum; | ||
161 | cde = cde->d_parent; | ||
162 | } | ||
163 | |||
164 | return v9fs_fid_create(dentry, v9ses, fidnum, 0); | ||
165 | |||
166 | clunk_fid: | ||
167 | v9fs_t_clunk(v9ses, fidnum, NULL); | ||
168 | return ERR_PTR(err); | ||
169 | } | ||
170 | |||
171 | /** | ||
112 | * v9fs_fid_lookup - retrieve the right fid from a particular dentry | 172 | * v9fs_fid_lookup - retrieve the right fid from a particular dentry |
113 | * @dentry: dentry to look for fid in | 173 | * @dentry: dentry to look for fid in |
114 | * @type: intent of lookup (operation or traversal) | 174 | * @type: intent of lookup (operation or traversal) |
@@ -119,49 +179,25 @@ void v9fs_fid_destroy(struct v9fs_fid *fid) | |||
119 | * | 179 | * |
120 | */ | 180 | */ |
121 | 181 | ||
122 | struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type) | 182 | struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry) |
123 | { | 183 | { |
124 | struct list_head *fid_list = (struct list_head *)dentry->d_fsdata; | 184 | struct list_head *fid_list = (struct list_head *)dentry->d_fsdata; |
125 | struct v9fs_fid *current_fid = NULL; | 185 | struct v9fs_fid *current_fid = NULL; |
126 | struct v9fs_fid *temp = NULL; | 186 | struct v9fs_fid *temp = NULL; |
127 | struct v9fs_fid *return_fid = NULL; | 187 | struct v9fs_fid *return_fid = NULL; |
128 | int found_parent = 0; | ||
129 | int found_user = 0; | ||
130 | 188 | ||
131 | dprintk(DEBUG_9P, " dentry: %s (%p) type %d\n", dentry->d_iname, dentry, | 189 | dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry); |
132 | type); | ||
133 | 190 | ||
134 | if (fid_list && !list_empty(fid_list)) { | 191 | if (fid_list) { |
135 | list_for_each_entry_safe(current_fid, temp, fid_list, list) { | 192 | list_for_each_entry_safe(current_fid, temp, fid_list, list) { |
136 | if (current_fid->uid == current->uid) { | 193 | if (!current_fid->fidcreate) { |
137 | if (return_fid == NULL) { | 194 | return_fid = current_fid; |
138 | if ((type == FID_OP) | 195 | break; |
139 | || (!current_fid->fidopen)) { | ||
140 | return_fid = current_fid; | ||
141 | found_user = 1; | ||
142 | } | ||
143 | } | ||
144 | } | ||
145 | if (current_fid->pid == current->real_parent->pid) { | ||
146 | if ((return_fid == NULL) || (found_parent) | ||
147 | || (found_user)) { | ||
148 | if ((type == FID_OP) | ||
149 | || (!current_fid->fidopen)) { | ||
150 | return_fid = current_fid; | ||
151 | found_parent = 1; | ||
152 | found_user = 0; | ||
153 | } | ||
154 | } | ||
155 | } | ||
156 | if (current_fid->pid == current->pid) { | ||
157 | if ((type == FID_OP) || | ||
158 | (!current_fid->fidopen)) { | ||
159 | return_fid = current_fid; | ||
160 | found_parent = 0; | ||
161 | found_user = 0; | ||
162 | } | ||
163 | } | 196 | } |
164 | } | 197 | } |
198 | |||
199 | if (!return_fid) | ||
200 | return_fid = current_fid; | ||
165 | } | 201 | } |
166 | 202 | ||
167 | /* we are at the root but didn't match */ | 203 | /* we are at the root but didn't match */ |
@@ -187,55 +223,33 @@ struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type) | |||
187 | 223 | ||
188 | /* XXX - there may be some duplication we can get rid of */ | 224 | /* XXX - there may be some duplication we can get rid of */ |
189 | if (par == dentry) { | 225 | if (par == dentry) { |
190 | /* we need to fid_lookup the starting point */ | 226 | return_fid = v9fs_fid_walk_up(dentry); |
191 | int fidnum = -1; | 227 | if (IS_ERR(return_fid)) |
192 | int oldfid = -1; | 228 | return_fid = NULL; |
193 | int result = -1; | 229 | } |
194 | struct v9fs_session_info *v9ses = | 230 | } |
195 | v9fs_inode2v9ses(current->fs->pwd->d_inode); | ||
196 | |||
197 | current_fid = | ||
198 | v9fs_fid_lookup(current->fs->pwd, FID_WALK); | ||
199 | if (current_fid == NULL) { | ||
200 | dprintk(DEBUG_ERROR, | ||
201 | "process cwd doesn't have a fid\n"); | ||
202 | return return_fid; | ||
203 | } | ||
204 | oldfid = current_fid->fid; | ||
205 | par = current->fs->pwd; | ||
206 | /* TODO: take advantage of multiwalk */ | ||
207 | 231 | ||
208 | fidnum = v9fs_get_idpool(&v9ses->fidpool); | 232 | return return_fid; |
209 | if (fidnum < 0) { | 233 | } |
210 | dprintk(DEBUG_ERROR, | ||
211 | "could not get a new fid num\n"); | ||
212 | return return_fid; | ||
213 | } | ||
214 | 234 | ||
215 | while (par != dentry) { | 235 | struct v9fs_fid *v9fs_fid_get_created(struct dentry *dentry) |
216 | result = | 236 | { |
217 | v9fs_t_walk(v9ses, oldfid, fidnum, "..", | 237 | struct list_head *fid_list; |
218 | NULL); | 238 | struct v9fs_fid *fid, *ftmp, *ret; |
219 | if (result < 0) { | 239 | |
220 | dprintk(DEBUG_ERROR, | 240 | dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry); |
221 | "problem walking to parent\n"); | 241 | fid_list = (struct list_head *)dentry->d_fsdata; |
222 | 242 | ret = NULL; | |
223 | break; | 243 | if (fid_list) { |
224 | } | 244 | list_for_each_entry_safe(fid, ftmp, fid_list, list) { |
225 | oldfid = fidnum; | 245 | if (fid->fidcreate && fid->pid == current->pid) { |
226 | if (par == par->d_parent) { | 246 | list_del(&fid->list); |
227 | dprintk(DEBUG_ERROR, | 247 | ret = fid; |
228 | "can't find dentry\n"); | 248 | break; |
229 | break; | ||
230 | } | ||
231 | par = par->d_parent; | ||
232 | } | ||
233 | if (par == dentry) { | ||
234 | return_fid = v9fs_fid_create(dentry); | ||
235 | return_fid->fid = fidnum; | ||
236 | } | 249 | } |
237 | } | 250 | } |
238 | } | 251 | } |
239 | 252 | ||
240 | return return_fid; | 253 | dprintk(DEBUG_9P, "return %p\n", ret); |
254 | return ret; | ||
241 | } | 255 | } |
diff --git a/fs/9p/fid.h b/fs/9p/fid.h index 7db478ccca36..84c673a44c83 100644 --- a/fs/9p/fid.h +++ b/fs/9p/fid.h | |||
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | #define FID_OP 0 | 26 | #define FID_OP 0 |
27 | #define FID_WALK 1 | 27 | #define FID_WALK 1 |
28 | #define FID_CREATE 2 | ||
28 | 29 | ||
29 | struct v9fs_fid { | 30 | struct v9fs_fid { |
30 | struct list_head list; /* list of fids associated with a dentry */ | 31 | struct list_head list; /* list of fids associated with a dentry */ |
@@ -52,6 +53,8 @@ struct v9fs_fid { | |||
52 | struct v9fs_session_info *v9ses; /* session info for this FID */ | 53 | struct v9fs_session_info *v9ses; /* session info for this FID */ |
53 | }; | 54 | }; |
54 | 55 | ||
55 | struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type); | 56 | struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry); |
57 | struct v9fs_fid *v9fs_fid_get_created(struct dentry *); | ||
56 | void v9fs_fid_destroy(struct v9fs_fid *fid); | 58 | void v9fs_fid_destroy(struct v9fs_fid *fid); |
57 | struct v9fs_fid *v9fs_fid_create(struct dentry *); | 59 | struct v9fs_fid *v9fs_fid_create(struct dentry *, |
60 | struct v9fs_session_info *v9ses, int fid, int create); | ||
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 13bdbbab4387..82303f3bf76f 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c | |||
@@ -303,7 +303,13 @@ v9fs_session_init(struct v9fs_session_info *v9ses, | |||
303 | goto SessCleanUp; | 303 | goto SessCleanUp; |
304 | }; | 304 | }; |
305 | 305 | ||
306 | v9ses->transport = trans_proto; | 306 | v9ses->transport = kmalloc(sizeof(*v9ses->transport), GFP_KERNEL); |
307 | if (!v9ses->transport) { | ||
308 | retval = -ENOMEM; | ||
309 | goto SessCleanUp; | ||
310 | } | ||
311 | |||
312 | memmove(v9ses->transport, trans_proto, sizeof(*v9ses->transport)); | ||
307 | 313 | ||
308 | if ((retval = v9ses->transport->init(v9ses, dev_name, data)) < 0) { | 314 | if ((retval = v9ses->transport->init(v9ses, dev_name, data)) < 0) { |
309 | eprintk(KERN_ERR, "problem initializing transport\n"); | 315 | eprintk(KERN_ERR, "problem initializing transport\n"); |
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c index 306c96741f81..a6aa947de0f9 100644 --- a/fs/9p/vfs_dentry.c +++ b/fs/9p/vfs_dentry.c | |||
@@ -67,7 +67,7 @@ static int v9fs_dentry_validate(struct dentry *dentry, struct nameidata *nd) | |||
67 | struct dentry *dc = current->fs->pwd; | 67 | struct dentry *dc = current->fs->pwd; |
68 | 68 | ||
69 | dprintk(DEBUG_VFS, "dentry: %s (%p)\n", dentry->d_iname, dentry); | 69 | dprintk(DEBUG_VFS, "dentry: %s (%p)\n", dentry->d_iname, dentry); |
70 | if (v9fs_fid_lookup(dentry, FID_OP)) { | 70 | if (v9fs_fid_lookup(dentry)) { |
71 | dprintk(DEBUG_VFS, "VALID\n"); | 71 | dprintk(DEBUG_VFS, "VALID\n"); |
72 | return 1; | 72 | return 1; |
73 | } | 73 | } |
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index c478a7384186..57a43b8feef5 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c | |||
@@ -197,21 +197,18 @@ int v9fs_dir_release(struct inode *inode, struct file *filp) | |||
197 | filemap_fdatawait(inode->i_mapping); | 197 | filemap_fdatawait(inode->i_mapping); |
198 | 198 | ||
199 | if (fidnum >= 0) { | 199 | if (fidnum >= 0) { |
200 | fid->fidopen--; | ||
201 | dprintk(DEBUG_VFS, "fidopen: %d v9f->fid: %d\n", fid->fidopen, | 200 | dprintk(DEBUG_VFS, "fidopen: %d v9f->fid: %d\n", fid->fidopen, |
202 | fid->fid); | 201 | fid->fid); |
203 | 202 | ||
204 | if (fid->fidopen == 0) { | 203 | if (v9fs_t_clunk(v9ses, fidnum, NULL)) |
205 | if (v9fs_t_clunk(v9ses, fidnum, NULL)) | 204 | dprintk(DEBUG_ERROR, "clunk failed\n"); |
206 | dprintk(DEBUG_ERROR, "clunk failed\n"); | ||
207 | 205 | ||
208 | v9fs_put_idpool(fid->fid, &v9ses->fidpool); | 206 | v9fs_put_idpool(fid->fid, &v9ses->fidpool); |
209 | } | ||
210 | 207 | ||
211 | kfree(fid->rdir_fcall); | 208 | kfree(fid->rdir_fcall); |
209 | kfree(fid); | ||
212 | 210 | ||
213 | filp->private_data = NULL; | 211 | filp->private_data = NULL; |
214 | v9fs_fid_destroy(fid); | ||
215 | } | 212 | } |
216 | 213 | ||
217 | d_drop(filp->f_dentry); | 214 | d_drop(filp->f_dentry); |
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 1f8ae7d580ab..bbc3cc63854f 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
@@ -53,30 +53,36 @@ | |||
53 | int v9fs_file_open(struct inode *inode, struct file *file) | 53 | int v9fs_file_open(struct inode *inode, struct file *file) |
54 | { | 54 | { |
55 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); | 55 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); |
56 | struct v9fs_fid *v9fid = v9fs_fid_lookup(file->f_dentry, FID_WALK); | 56 | struct v9fs_fid *v9fid, *fid; |
57 | struct v9fs_fid *v9newfid = NULL; | ||
58 | struct v9fs_fcall *fcall = NULL; | 57 | struct v9fs_fcall *fcall = NULL; |
59 | int open_mode = 0; | 58 | int open_mode = 0; |
60 | unsigned int iounit = 0; | 59 | unsigned int iounit = 0; |
61 | int newfid = -1; | 60 | int newfid = -1; |
62 | long result = -1; | 61 | long result = -1; |
63 | 62 | ||
64 | dprintk(DEBUG_VFS, "inode: %p file: %p v9fid= %p\n", inode, file, | 63 | dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file); |
65 | v9fid); | 64 | |
65 | v9fid = v9fs_fid_get_created(file->f_dentry); | ||
66 | if (!v9fid) | ||
67 | v9fid = v9fs_fid_lookup(file->f_dentry); | ||
66 | 68 | ||
67 | if (!v9fid) { | 69 | if (!v9fid) { |
68 | struct dentry *dentry = file->f_dentry; | ||
69 | dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n"); | 70 | dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n"); |
71 | return -EBADF; | ||
72 | } | ||
70 | 73 | ||
71 | /* XXX - some duplication from lookup, generalize later */ | 74 | if (!v9fid->fidcreate) { |
72 | /* basically vfs_lookup is too heavy weight */ | 75 | fid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); |
73 | v9fid = v9fs_fid_lookup(file->f_dentry, FID_OP); | 76 | if (fid == NULL) { |
74 | if (!v9fid) | 77 | dprintk(DEBUG_ERROR, "Out of Memory\n"); |
75 | return -EBADF; | 78 | return -ENOMEM; |
79 | } | ||
76 | 80 | ||
77 | v9fid = v9fs_fid_lookup(dentry->d_parent, FID_WALK); | 81 | fid->fidopen = 0; |
78 | if (!v9fid) | 82 | fid->fidcreate = 0; |
79 | return -EBADF; | 83 | fid->fidclunked = 0; |
84 | fid->iounit = 0; | ||
85 | fid->v9ses = v9ses; | ||
80 | 86 | ||
81 | newfid = v9fs_get_idpool(&v9ses->fidpool); | 87 | newfid = v9fs_get_idpool(&v9ses->fidpool); |
82 | if (newfid < 0) { | 88 | if (newfid < 0) { |
@@ -85,58 +91,16 @@ int v9fs_file_open(struct inode *inode, struct file *file) | |||
85 | } | 91 | } |
86 | 92 | ||
87 | result = | 93 | result = |
88 | v9fs_t_walk(v9ses, v9fid->fid, newfid, | 94 | v9fs_t_walk(v9ses, v9fid->fid, newfid, NULL, NULL); |
89 | (char *)file->f_dentry->d_name.name, NULL); | 95 | |
90 | if (result < 0) { | 96 | if (result < 0) { |
91 | v9fs_put_idpool(newfid, &v9ses->fidpool); | 97 | v9fs_put_idpool(newfid, &v9ses->fidpool); |
92 | dprintk(DEBUG_ERROR, "rewalk didn't work\n"); | 98 | dprintk(DEBUG_ERROR, "rewalk didn't work\n"); |
93 | return -EBADF; | 99 | return -EBADF; |
94 | } | 100 | } |
95 | 101 | ||
96 | v9fid = v9fs_fid_create(dentry); | 102 | fid->fid = newfid; |
97 | if (v9fid == NULL) { | 103 | v9fid = fid; |
98 | dprintk(DEBUG_ERROR, "couldn't insert\n"); | ||
99 | return -ENOMEM; | ||
100 | } | ||
101 | v9fid->fid = newfid; | ||
102 | } | ||
103 | |||
104 | if (v9fid->fidcreate) { | ||
105 | /* create case */ | ||
106 | newfid = v9fid->fid; | ||
107 | iounit = v9fid->iounit; | ||
108 | v9fid->fidcreate = 0; | ||
109 | } else { | ||
110 | if (!S_ISDIR(inode->i_mode)) | ||
111 | newfid = v9fid->fid; | ||
112 | else { | ||
113 | newfid = v9fs_get_idpool(&v9ses->fidpool); | ||
114 | if (newfid < 0) { | ||
115 | eprintk(KERN_WARNING, "allocation failed\n"); | ||
116 | return -ENOSPC; | ||
117 | } | ||
118 | /* This would be a somewhat critical clone */ | ||
119 | result = | ||
120 | v9fs_t_walk(v9ses, v9fid->fid, newfid, NULL, | ||
121 | &fcall); | ||
122 | if (result < 0) { | ||
123 | dprintk(DEBUG_ERROR, "clone error: %s\n", | ||
124 | FCALL_ERROR(fcall)); | ||
125 | kfree(fcall); | ||
126 | return result; | ||
127 | } | ||
128 | |||
129 | v9newfid = v9fs_fid_create(file->f_dentry); | ||
130 | v9newfid->fid = newfid; | ||
131 | v9newfid->qid = v9fid->qid; | ||
132 | v9newfid->iounit = v9fid->iounit; | ||
133 | v9newfid->fidopen = 0; | ||
134 | v9newfid->fidclunked = 0; | ||
135 | v9newfid->v9ses = v9ses; | ||
136 | v9fid = v9newfid; | ||
137 | kfree(fcall); | ||
138 | } | ||
139 | |||
140 | /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */ | 104 | /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */ |
141 | /* translate open mode appropriately */ | 105 | /* translate open mode appropriately */ |
142 | open_mode = file->f_flags & 0x3; | 106 | open_mode = file->f_flags & 0x3; |
@@ -163,9 +127,13 @@ int v9fs_file_open(struct inode *inode, struct file *file) | |||
163 | 127 | ||
164 | iounit = fcall->params.ropen.iounit; | 128 | iounit = fcall->params.ropen.iounit; |
165 | kfree(fcall); | 129 | kfree(fcall); |
130 | } else { | ||
131 | /* create case */ | ||
132 | newfid = v9fid->fid; | ||
133 | iounit = v9fid->iounit; | ||
134 | v9fid->fidcreate = 0; | ||
166 | } | 135 | } |
167 | 136 | ||
168 | |||
169 | file->private_data = v9fid; | 137 | file->private_data = v9fid; |
170 | 138 | ||
171 | v9fid->rdir_pos = 0; | 139 | v9fid->rdir_pos = 0; |
@@ -207,16 +175,16 @@ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
207 | } | 175 | } |
208 | 176 | ||
209 | /** | 177 | /** |
210 | * v9fs_read - read from a file (internal) | 178 | * v9fs_file_read - read from a file |
211 | * @filep: file pointer to read | 179 | * @filep: file pointer to read |
212 | * @data: data buffer to read data into | 180 | * @data: data buffer to read data into |
213 | * @count: size of buffer | 181 | * @count: size of buffer |
214 | * @offset: offset at which to read data | 182 | * @offset: offset at which to read data |
215 | * | 183 | * |
216 | */ | 184 | */ |
217 | |||
218 | static ssize_t | 185 | static ssize_t |
219 | v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset) | 186 | v9fs_file_read(struct file *filp, char __user * data, size_t count, |
187 | loff_t * offset) | ||
220 | { | 188 | { |
221 | struct inode *inode = filp->f_dentry->d_inode; | 189 | struct inode *inode = filp->f_dentry->d_inode; |
222 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); | 190 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); |
@@ -226,6 +194,7 @@ v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset) | |||
226 | int rsize = 0; | 194 | int rsize = 0; |
227 | int result = 0; | 195 | int result = 0; |
228 | int total = 0; | 196 | int total = 0; |
197 | int n; | ||
229 | 198 | ||
230 | dprintk(DEBUG_VFS, "\n"); | 199 | dprintk(DEBUG_VFS, "\n"); |
231 | 200 | ||
@@ -248,10 +217,15 @@ v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset) | |||
248 | } else | 217 | } else |
249 | *offset += result; | 218 | *offset += result; |
250 | 219 | ||
251 | /* XXX - extra copy */ | 220 | n = copy_to_user(data, fcall->params.rread.data, result); |
252 | memcpy(buffer, fcall->params.rread.data, result); | 221 | if (n) { |
222 | dprintk(DEBUG_ERROR, "Problem copying to user %d\n", n); | ||
223 | kfree(fcall); | ||
224 | return -EFAULT; | ||
225 | } | ||
226 | |||
253 | count -= result; | 227 | count -= result; |
254 | buffer += result; | 228 | data += result; |
255 | total += result; | 229 | total += result; |
256 | 230 | ||
257 | kfree(fcall); | 231 | kfree(fcall); |
@@ -264,42 +238,7 @@ v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset) | |||
264 | } | 238 | } |
265 | 239 | ||
266 | /** | 240 | /** |
267 | * v9fs_file_read - read from a file | 241 | * v9fs_file_write - write to a file |
268 | * @filep: file pointer to read | ||
269 | * @data: data buffer to read data into | ||
270 | * @count: size of buffer | ||
271 | * @offset: offset at which to read data | ||
272 | * | ||
273 | */ | ||
274 | |||
275 | static ssize_t | ||
276 | v9fs_file_read(struct file *filp, char __user * data, size_t count, | ||
277 | loff_t * offset) | ||
278 | { | ||
279 | int retval = -1; | ||
280 | int ret = 0; | ||
281 | char *buffer; | ||
282 | |||
283 | buffer = kmalloc(count, GFP_KERNEL); | ||
284 | if (!buffer) | ||
285 | return -ENOMEM; | ||
286 | |||
287 | retval = v9fs_read(filp, buffer, count, offset); | ||
288 | if (retval > 0) { | ||
289 | if ((ret = copy_to_user(data, buffer, retval)) != 0) { | ||
290 | dprintk(DEBUG_ERROR, "Problem copying to user %d\n", | ||
291 | ret); | ||
292 | retval = ret; | ||
293 | } | ||
294 | } | ||
295 | |||
296 | kfree(buffer); | ||
297 | |||
298 | return retval; | ||
299 | } | ||
300 | |||
301 | /** | ||
302 | * v9fs_write - write to a file | ||
303 | * @filep: file pointer to write | 242 | * @filep: file pointer to write |
304 | * @data: data buffer to write data from | 243 | * @data: data buffer to write data from |
305 | * @count: size of buffer | 244 | * @count: size of buffer |
@@ -308,7 +247,8 @@ v9fs_file_read(struct file *filp, char __user * data, size_t count, | |||
308 | */ | 247 | */ |
309 | 248 | ||
310 | static ssize_t | 249 | static ssize_t |
311 | v9fs_write(struct file *filp, char *buffer, size_t count, loff_t * offset) | 250 | v9fs_file_write(struct file *filp, const char __user * data, |
251 | size_t count, loff_t * offset) | ||
312 | { | 252 | { |
313 | struct inode *inode = filp->f_dentry->d_inode; | 253 | struct inode *inode = filp->f_dentry->d_inode; |
314 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); | 254 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); |
@@ -318,30 +258,42 @@ v9fs_write(struct file *filp, char *buffer, size_t count, loff_t * offset) | |||
318 | int result = -EIO; | 258 | int result = -EIO; |
319 | int rsize = 0; | 259 | int rsize = 0; |
320 | int total = 0; | 260 | int total = 0; |
261 | char *buf; | ||
321 | 262 | ||
322 | dprintk(DEBUG_VFS, "data %p count %d offset %x\n", buffer, (int)count, | 263 | dprintk(DEBUG_VFS, "data %p count %d offset %x\n", data, (int)count, |
323 | (int)*offset); | 264 | (int)*offset); |
324 | rsize = v9ses->maxdata - V9FS_IOHDRSZ; | 265 | rsize = v9ses->maxdata - V9FS_IOHDRSZ; |
325 | if (v9fid->iounit != 0 && rsize > v9fid->iounit) | 266 | if (v9fid->iounit != 0 && rsize > v9fid->iounit) |
326 | rsize = v9fid->iounit; | 267 | rsize = v9fid->iounit; |
327 | 268 | ||
328 | dump_data(buffer, count); | 269 | buf = kmalloc(v9ses->maxdata - V9FS_IOHDRSZ, GFP_KERNEL); |
270 | if (!buf) | ||
271 | return -ENOMEM; | ||
329 | 272 | ||
330 | do { | 273 | do { |
331 | if (count < rsize) | 274 | if (count < rsize) |
332 | rsize = count; | 275 | rsize = count; |
333 | 276 | ||
334 | result = | 277 | result = copy_from_user(buf, data, rsize); |
335 | v9fs_t_write(v9ses, fid, *offset, rsize, buffer, &fcall); | 278 | if (result) { |
279 | dprintk(DEBUG_ERROR, "Problem copying from user\n"); | ||
280 | kfree(buf); | ||
281 | return -EFAULT; | ||
282 | } | ||
283 | |||
284 | dump_data(buf, rsize); | ||
285 | result = v9fs_t_write(v9ses, fid, *offset, rsize, buf, &fcall); | ||
336 | if (result < 0) { | 286 | if (result < 0) { |
337 | eprintk(KERN_ERR, "error while writing: %s(%d)\n", | 287 | eprintk(KERN_ERR, "error while writing: %s(%d)\n", |
338 | FCALL_ERROR(fcall), result); | 288 | FCALL_ERROR(fcall), result); |
339 | kfree(fcall); | 289 | kfree(fcall); |
290 | kfree(buf); | ||
340 | return result; | 291 | return result; |
341 | } else | 292 | } else |
342 | *offset += result; | 293 | *offset += result; |
343 | 294 | ||
344 | kfree(fcall); | 295 | kfree(fcall); |
296 | fcall = NULL; | ||
345 | 297 | ||
346 | if (result != rsize) { | 298 | if (result != rsize) { |
347 | eprintk(KERN_ERR, | 299 | eprintk(KERN_ERR, |
@@ -351,46 +303,14 @@ v9fs_write(struct file *filp, char *buffer, size_t count, loff_t * offset) | |||
351 | } | 303 | } |
352 | 304 | ||
353 | count -= result; | 305 | count -= result; |
354 | buffer += result; | 306 | data += result; |
355 | total += result; | 307 | total += result; |
356 | } while (count); | 308 | } while (count); |
357 | 309 | ||
310 | kfree(buf); | ||
358 | return total; | 311 | return total; |
359 | } | 312 | } |
360 | 313 | ||
361 | /** | ||
362 | * v9fs_file_write - write to a file | ||
363 | * @filep: file pointer to write | ||
364 | * @data: data buffer to write data from | ||
365 | * @count: size of buffer | ||
366 | * @offset: offset at which to write data | ||
367 | * | ||
368 | */ | ||
369 | |||
370 | static ssize_t | ||
371 | v9fs_file_write(struct file *filp, const char __user * data, | ||
372 | size_t count, loff_t * offset) | ||
373 | { | ||
374 | int ret = -1; | ||
375 | char *buffer; | ||
376 | |||
377 | buffer = kmalloc(count, GFP_KERNEL); | ||
378 | if (buffer == NULL) | ||
379 | return -ENOMEM; | ||
380 | |||
381 | ret = copy_from_user(buffer, data, count); | ||
382 | if (ret) { | ||
383 | dprintk(DEBUG_ERROR, "Problem copying from user\n"); | ||
384 | ret = -EFAULT; | ||
385 | } else { | ||
386 | ret = v9fs_write(filp, buffer, count, offset); | ||
387 | } | ||
388 | |||
389 | kfree(buffer); | ||
390 | |||
391 | return ret; | ||
392 | } | ||
393 | |||
394 | struct file_operations v9fs_file_operations = { | 314 | struct file_operations v9fs_file_operations = { |
395 | .llseek = generic_file_llseek, | 315 | .llseek = generic_file_llseek, |
396 | .read = v9fs_file_read, | 316 | .read = v9fs_file_read, |
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 0c13fc600049..2b696ae6655a 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -307,7 +307,7 @@ v9fs_create(struct inode *dir, | |||
307 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); | 307 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); |
308 | struct super_block *sb = dir->i_sb; | 308 | struct super_block *sb = dir->i_sb; |
309 | struct v9fs_fid *dirfid = | 309 | struct v9fs_fid *dirfid = |
310 | v9fs_fid_lookup(file_dentry->d_parent, FID_WALK); | 310 | v9fs_fid_lookup(file_dentry->d_parent); |
311 | struct v9fs_fid *fid = NULL; | 311 | struct v9fs_fid *fid = NULL; |
312 | struct inode *file_inode = NULL; | 312 | struct inode *file_inode = NULL; |
313 | struct v9fs_fcall *fcall = NULL; | 313 | struct v9fs_fcall *fcall = NULL; |
@@ -317,6 +317,7 @@ v9fs_create(struct inode *dir, | |||
317 | long newfid = -1; | 317 | long newfid = -1; |
318 | int result = 0; | 318 | int result = 0; |
319 | unsigned int iounit = 0; | 319 | unsigned int iounit = 0; |
320 | int wfidno = -1; | ||
320 | 321 | ||
321 | perm = unixmode2p9mode(v9ses, perm); | 322 | perm = unixmode2p9mode(v9ses, perm); |
322 | 323 | ||
@@ -350,7 +351,7 @@ v9fs_create(struct inode *dir, | |||
350 | if (result < 0) { | 351 | if (result < 0) { |
351 | dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall)); | 352 | dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall)); |
352 | v9fs_put_idpool(newfid, &v9ses->fidpool); | 353 | v9fs_put_idpool(newfid, &v9ses->fidpool); |
353 | newfid = 0; | 354 | newfid = -1; |
354 | goto CleanUpFid; | 355 | goto CleanUpFid; |
355 | } | 356 | } |
356 | 357 | ||
@@ -369,20 +370,39 @@ v9fs_create(struct inode *dir, | |||
369 | qid = fcall->params.rcreate.qid; | 370 | qid = fcall->params.rcreate.qid; |
370 | kfree(fcall); | 371 | kfree(fcall); |
371 | 372 | ||
372 | fid = v9fs_fid_create(file_dentry); | 373 | fid = v9fs_fid_create(file_dentry, v9ses, newfid, 1); |
374 | dprintk(DEBUG_VFS, "fid %p %d\n", fid, fid->fidcreate); | ||
373 | if (!fid) { | 375 | if (!fid) { |
374 | result = -ENOMEM; | 376 | result = -ENOMEM; |
375 | goto CleanUpFid; | 377 | goto CleanUpFid; |
376 | } | 378 | } |
377 | 379 | ||
378 | fid->fid = newfid; | ||
379 | fid->fidopen = 0; | ||
380 | fid->fidcreate = 1; | ||
381 | fid->qid = qid; | 380 | fid->qid = qid; |
382 | fid->iounit = iounit; | 381 | fid->iounit = iounit; |
383 | fid->rdir_pos = 0; | 382 | |
384 | fid->rdir_fcall = NULL; | 383 | /* walk to the newly created file and put the fid in the dentry */ |
385 | fid->v9ses = v9ses; | 384 | wfidno = v9fs_get_idpool(&v9ses->fidpool); |
385 | if (newfid < 0) { | ||
386 | eprintk(KERN_WARNING, "no free fids available\n"); | ||
387 | return -ENOSPC; | ||
388 | } | ||
389 | |||
390 | result = v9fs_t_walk(v9ses, dirfidnum, wfidno, | ||
391 | (char *) file_dentry->d_name.name, NULL); | ||
392 | if (result < 0) { | ||
393 | dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall)); | ||
394 | v9fs_put_idpool(wfidno, &v9ses->fidpool); | ||
395 | wfidno = -1; | ||
396 | goto CleanUpFid; | ||
397 | } | ||
398 | |||
399 | if (!v9fs_fid_create(file_dentry, v9ses, wfidno, 0)) { | ||
400 | if (!v9fs_t_clunk(v9ses, newfid, &fcall)) { | ||
401 | v9fs_put_idpool(wfidno, &v9ses->fidpool); | ||
402 | } | ||
403 | |||
404 | goto CleanUpFid; | ||
405 | } | ||
386 | 406 | ||
387 | if ((perm & V9FS_DMSYMLINK) || (perm & V9FS_DMLINK) || | 407 | if ((perm & V9FS_DMSYMLINK) || (perm & V9FS_DMLINK) || |
388 | (perm & V9FS_DMNAMEDPIPE) || (perm & V9FS_DMSOCKET) || | 408 | (perm & V9FS_DMNAMEDPIPE) || (perm & V9FS_DMSOCKET) || |
@@ -410,11 +430,11 @@ v9fs_create(struct inode *dir, | |||
410 | d_instantiate(file_dentry, file_inode); | 430 | d_instantiate(file_dentry, file_inode); |
411 | 431 | ||
412 | if (perm & V9FS_DMDIR) { | 432 | if (perm & V9FS_DMDIR) { |
413 | if (v9fs_t_clunk(v9ses, newfid, &fcall)) | 433 | if (!v9fs_t_clunk(v9ses, newfid, &fcall)) |
434 | v9fs_put_idpool(newfid, &v9ses->fidpool); | ||
435 | else | ||
414 | dprintk(DEBUG_ERROR, "clunk for mkdir failed: %s\n", | 436 | dprintk(DEBUG_ERROR, "clunk for mkdir failed: %s\n", |
415 | FCALL_ERROR(fcall)); | 437 | FCALL_ERROR(fcall)); |
416 | |||
417 | v9fs_put_idpool(newfid, &v9ses->fidpool); | ||
418 | kfree(fcall); | 438 | kfree(fcall); |
419 | fid->fidopen = 0; | 439 | fid->fidopen = 0; |
420 | fid->fidcreate = 0; | 440 | fid->fidcreate = 0; |
@@ -426,12 +446,22 @@ v9fs_create(struct inode *dir, | |||
426 | CleanUpFid: | 446 | CleanUpFid: |
427 | kfree(fcall); | 447 | kfree(fcall); |
428 | 448 | ||
429 | if (newfid) { | 449 | if (newfid >= 0) { |
430 | if (v9fs_t_clunk(v9ses, newfid, &fcall)) | 450 | if (!v9fs_t_clunk(v9ses, newfid, &fcall)) |
451 | v9fs_put_idpool(newfid, &v9ses->fidpool); | ||
452 | else | ||
453 | dprintk(DEBUG_ERROR, "clunk failed: %s\n", | ||
454 | FCALL_ERROR(fcall)); | ||
455 | |||
456 | kfree(fcall); | ||
457 | } | ||
458 | if (wfidno >= 0) { | ||
459 | if (!v9fs_t_clunk(v9ses, wfidno, &fcall)) | ||
460 | v9fs_put_idpool(wfidno, &v9ses->fidpool); | ||
461 | else | ||
431 | dprintk(DEBUG_ERROR, "clunk failed: %s\n", | 462 | dprintk(DEBUG_ERROR, "clunk failed: %s\n", |
432 | FCALL_ERROR(fcall)); | 463 | FCALL_ERROR(fcall)); |
433 | 464 | ||
434 | v9fs_put_idpool(newfid, &v9ses->fidpool); | ||
435 | kfree(fcall); | 465 | kfree(fcall); |
436 | } | 466 | } |
437 | return result; | 467 | return result; |
@@ -461,7 +491,7 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) | |||
461 | file_inode = file->d_inode; | 491 | file_inode = file->d_inode; |
462 | sb = file_inode->i_sb; | 492 | sb = file_inode->i_sb; |
463 | v9ses = v9fs_inode2v9ses(file_inode); | 493 | v9ses = v9fs_inode2v9ses(file_inode); |
464 | v9fid = v9fs_fid_lookup(file, FID_OP); | 494 | v9fid = v9fs_fid_lookup(file); |
465 | 495 | ||
466 | if (!v9fid) { | 496 | if (!v9fid) { |
467 | dprintk(DEBUG_ERROR, | 497 | dprintk(DEBUG_ERROR, |
@@ -545,7 +575,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
545 | 575 | ||
546 | sb = dir->i_sb; | 576 | sb = dir->i_sb; |
547 | v9ses = v9fs_inode2v9ses(dir); | 577 | v9ses = v9fs_inode2v9ses(dir); |
548 | dirfid = v9fs_fid_lookup(dentry->d_parent, FID_WALK); | 578 | dirfid = v9fs_fid_lookup(dentry->d_parent); |
549 | 579 | ||
550 | if (!dirfid) { | 580 | if (!dirfid) { |
551 | dprintk(DEBUG_ERROR, "no dirfid\n"); | 581 | dprintk(DEBUG_ERROR, "no dirfid\n"); |
@@ -573,7 +603,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
573 | v9fs_put_idpool(newfid, &v9ses->fidpool); | 603 | v9fs_put_idpool(newfid, &v9ses->fidpool); |
574 | if (result == -ENOENT) { | 604 | if (result == -ENOENT) { |
575 | d_add(dentry, NULL); | 605 | d_add(dentry, NULL); |
576 | dprintk(DEBUG_ERROR, | 606 | dprintk(DEBUG_VFS, |
577 | "Return negative dentry %p count %d\n", | 607 | "Return negative dentry %p count %d\n", |
578 | dentry, atomic_read(&dentry->d_count)); | 608 | dentry, atomic_read(&dentry->d_count)); |
579 | return NULL; | 609 | return NULL; |
@@ -601,16 +631,13 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
601 | 631 | ||
602 | inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat->qid); | 632 | inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat->qid); |
603 | 633 | ||
604 | fid = v9fs_fid_create(dentry); | 634 | fid = v9fs_fid_create(dentry, v9ses, newfid, 0); |
605 | if (fid == NULL) { | 635 | if (fid == NULL) { |
606 | dprintk(DEBUG_ERROR, "couldn't insert\n"); | 636 | dprintk(DEBUG_ERROR, "couldn't insert\n"); |
607 | result = -ENOMEM; | 637 | result = -ENOMEM; |
608 | goto FreeFcall; | 638 | goto FreeFcall; |
609 | } | 639 | } |
610 | 640 | ||
611 | fid->fid = newfid; | ||
612 | fid->fidopen = 0; | ||
613 | fid->v9ses = v9ses; | ||
614 | fid->qid = fcall->params.rstat.stat->qid; | 641 | fid->qid = fcall->params.rstat.stat->qid; |
615 | 642 | ||
616 | dentry->d_op = &v9fs_dentry_operations; | 643 | dentry->d_op = &v9fs_dentry_operations; |
@@ -665,11 +692,11 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
665 | { | 692 | { |
666 | struct inode *old_inode = old_dentry->d_inode; | 693 | struct inode *old_inode = old_dentry->d_inode; |
667 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(old_inode); | 694 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(old_inode); |
668 | struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry, FID_WALK); | 695 | struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry); |
669 | struct v9fs_fid *olddirfid = | 696 | struct v9fs_fid *olddirfid = |
670 | v9fs_fid_lookup(old_dentry->d_parent, FID_WALK); | 697 | v9fs_fid_lookup(old_dentry->d_parent); |
671 | struct v9fs_fid *newdirfid = | 698 | struct v9fs_fid *newdirfid = |
672 | v9fs_fid_lookup(new_dentry->d_parent, FID_WALK); | 699 | v9fs_fid_lookup(new_dentry->d_parent); |
673 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); | 700 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); |
674 | struct v9fs_fcall *fcall = NULL; | 701 | struct v9fs_fcall *fcall = NULL; |
675 | int fid = -1; | 702 | int fid = -1; |
@@ -744,7 +771,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
744 | { | 771 | { |
745 | struct v9fs_fcall *fcall = NULL; | 772 | struct v9fs_fcall *fcall = NULL; |
746 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); | 773 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); |
747 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP); | 774 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry); |
748 | int err = -EPERM; | 775 | int err = -EPERM; |
749 | 776 | ||
750 | dprintk(DEBUG_VFS, "dentry: %p\n", dentry); | 777 | dprintk(DEBUG_VFS, "dentry: %p\n", dentry); |
@@ -778,7 +805,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
778 | static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) | 805 | static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) |
779 | { | 806 | { |
780 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); | 807 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); |
781 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP); | 808 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry); |
782 | struct v9fs_fcall *fcall = NULL; | 809 | struct v9fs_fcall *fcall = NULL; |
783 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); | 810 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); |
784 | int res = -EPERM; | 811 | int res = -EPERM; |
@@ -960,7 +987,7 @@ v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) | |||
960 | if (retval != 0) | 987 | if (retval != 0) |
961 | goto FreeFcall; | 988 | goto FreeFcall; |
962 | 989 | ||
963 | newfid = v9fs_fid_lookup(dentry, FID_OP); | 990 | newfid = v9fs_fid_lookup(dentry); |
964 | 991 | ||
965 | /* issue a twstat */ | 992 | /* issue a twstat */ |
966 | v9fs_blank_mistat(v9ses, mistat); | 993 | v9fs_blank_mistat(v9ses, mistat); |
@@ -1004,7 +1031,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) | |||
1004 | 1031 | ||
1005 | struct v9fs_fcall *fcall = NULL; | 1032 | struct v9fs_fcall *fcall = NULL; |
1006 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); | 1033 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); |
1007 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP); | 1034 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry); |
1008 | 1035 | ||
1009 | if (!fid) { | 1036 | if (!fid) { |
1010 | dprintk(DEBUG_ERROR, "could not resolve fid from dentry\n"); | 1037 | dprintk(DEBUG_ERROR, "could not resolve fid from dentry\n"); |
@@ -1063,8 +1090,8 @@ static int v9fs_vfs_readlink(struct dentry *dentry, char __user * buffer, | |||
1063 | int ret; | 1090 | int ret; |
1064 | char *link = __getname(); | 1091 | char *link = __getname(); |
1065 | 1092 | ||
1066 | if (strlen(link) < buflen) | 1093 | if (buflen > PATH_MAX) |
1067 | buflen = strlen(link); | 1094 | buflen = PATH_MAX; |
1068 | 1095 | ||
1069 | dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); | 1096 | dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); |
1070 | 1097 | ||
@@ -1148,7 +1175,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, | |||
1148 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); | 1175 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); |
1149 | struct v9fs_fcall *fcall = NULL; | 1176 | struct v9fs_fcall *fcall = NULL; |
1150 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); | 1177 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); |
1151 | struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry, FID_OP); | 1178 | struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry); |
1152 | struct v9fs_fid *newfid = NULL; | 1179 | struct v9fs_fid *newfid = NULL; |
1153 | char *symname = __getname(); | 1180 | char *symname = __getname(); |
1154 | 1181 | ||
@@ -1168,7 +1195,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, | |||
1168 | if (retval != 0) | 1195 | if (retval != 0) |
1169 | goto FreeMem; | 1196 | goto FreeMem; |
1170 | 1197 | ||
1171 | newfid = v9fs_fid_lookup(dentry, FID_OP); | 1198 | newfid = v9fs_fid_lookup(dentry); |
1172 | if (!newfid) { | 1199 | if (!newfid) { |
1173 | dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n"); | 1200 | dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n"); |
1174 | goto FreeMem; | 1201 | goto FreeMem; |
@@ -1246,7 +1273,7 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) | |||
1246 | if (retval != 0) | 1273 | if (retval != 0) |
1247 | goto FreeMem; | 1274 | goto FreeMem; |
1248 | 1275 | ||
1249 | newfid = v9fs_fid_lookup(dentry, FID_OP); | 1276 | newfid = v9fs_fid_lookup(dentry); |
1250 | if (!newfid) { | 1277 | if (!newfid) { |
1251 | dprintk(DEBUG_ERROR, "coudn't resove fid from dentry\n"); | 1278 | dprintk(DEBUG_ERROR, "coudn't resove fid from dentry\n"); |
1252 | retval = -EINVAL; | 1279 | retval = -EINVAL; |
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 868f350b2c5f..82c5b0084079 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c | |||
@@ -129,8 +129,7 @@ static struct super_block *v9fs_get_sb(struct file_system_type | |||
129 | 129 | ||
130 | if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) { | 130 | if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) { |
131 | dprintk(DEBUG_ERROR, "problem initiating session\n"); | 131 | dprintk(DEBUG_ERROR, "problem initiating session\n"); |
132 | retval = newfid; | 132 | return ERR_PTR(newfid); |
133 | goto free_session; | ||
134 | } | 133 | } |
135 | 134 | ||
136 | sb = sget(fs_type, NULL, v9fs_set_super, v9ses); | 135 | sb = sget(fs_type, NULL, v9fs_set_super, v9ses); |
@@ -150,28 +149,24 @@ static struct super_block *v9fs_get_sb(struct file_system_type | |||
150 | 149 | ||
151 | if (!root) { | 150 | if (!root) { |
152 | retval = -ENOMEM; | 151 | retval = -ENOMEM; |
153 | goto release_inode; | 152 | goto put_back_sb; |
154 | } | 153 | } |
155 | 154 | ||
156 | sb->s_root = root; | 155 | sb->s_root = root; |
157 | 156 | ||
158 | /* Setup the Root Inode */ | ||
159 | root_fid = v9fs_fid_create(root); | ||
160 | if (root_fid == NULL) { | ||
161 | retval = -ENOMEM; | ||
162 | goto release_dentry; | ||
163 | } | ||
164 | |||
165 | root_fid->fidopen = 0; | ||
166 | root_fid->v9ses = v9ses; | ||
167 | |||
168 | stat_result = v9fs_t_stat(v9ses, newfid, &fcall); | 157 | stat_result = v9fs_t_stat(v9ses, newfid, &fcall); |
169 | if (stat_result < 0) { | 158 | if (stat_result < 0) { |
170 | dprintk(DEBUG_ERROR, "stat error\n"); | 159 | dprintk(DEBUG_ERROR, "stat error\n"); |
171 | v9fs_t_clunk(v9ses, newfid, NULL); | 160 | v9fs_t_clunk(v9ses, newfid, NULL); |
172 | v9fs_put_idpool(newfid, &v9ses->fidpool); | 161 | v9fs_put_idpool(newfid, &v9ses->fidpool); |
173 | } else { | 162 | } else { |
174 | root_fid->fid = newfid; | 163 | /* Setup the Root Inode */ |
164 | root_fid = v9fs_fid_create(root, v9ses, newfid, 0); | ||
165 | if (root_fid == NULL) { | ||
166 | retval = -ENOMEM; | ||
167 | goto put_back_sb; | ||
168 | } | ||
169 | |||
175 | root_fid->qid = fcall->params.rstat.stat->qid; | 170 | root_fid->qid = fcall->params.rstat.stat->qid; |
176 | root->d_inode->i_ino = | 171 | root->d_inode->i_ino = |
177 | v9fs_qid2ino(&fcall->params.rstat.stat->qid); | 172 | v9fs_qid2ino(&fcall->params.rstat.stat->qid); |
@@ -182,25 +177,15 @@ static struct super_block *v9fs_get_sb(struct file_system_type | |||
182 | 177 | ||
183 | if (stat_result < 0) { | 178 | if (stat_result < 0) { |
184 | retval = stat_result; | 179 | retval = stat_result; |
185 | goto release_dentry; | 180 | goto put_back_sb; |
186 | } | 181 | } |
187 | 182 | ||
188 | return sb; | 183 | return sb; |
189 | 184 | ||
190 | release_dentry: | 185 | put_back_sb: |
191 | dput(sb->s_root); | 186 | /* deactivate_super calls v9fs_kill_super which will frees the rest */ |
192 | |||
193 | release_inode: | ||
194 | iput(inode); | ||
195 | |||
196 | put_back_sb: | ||
197 | up_write(&sb->s_umount); | 187 | up_write(&sb->s_umount); |
198 | deactivate_super(sb); | 188 | deactivate_super(sb); |
199 | v9fs_session_close(v9ses); | ||
200 | |||
201 | free_session: | ||
202 | kfree(v9ses); | ||
203 | |||
204 | return ERR_PTR(retval); | 189 | return ERR_PTR(retval); |
205 | } | 190 | } |
206 | 191 | ||
diff --git a/fs/Kconfig b/fs/Kconfig index 068ccea2f184..48f5422cb19a 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -472,6 +472,9 @@ config FUSE_FS | |||
472 | utilities is available from the FUSE homepage: | 472 | utilities is available from the FUSE homepage: |
473 | <http://fuse.sourceforge.net/> | 473 | <http://fuse.sourceforge.net/> |
474 | 474 | ||
475 | See <file:Documentation/filesystems/fuse.txt> for more information. | ||
476 | See <file:Documentation/Changes> for needed library/utility version. | ||
477 | |||
475 | If you want to develop a userspace FS, or if you want to use | 478 | If you want to develop a userspace FS, or if you want to use |
476 | a filesystem based on FUSE, answer Y or M. | 479 | a filesystem based on FUSE, answer Y or M. |
477 | 480 | ||
diff --git a/fs/afs/file.c b/fs/afs/file.c index 23c125128024..0d576987ec67 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c | |||
@@ -29,7 +29,7 @@ static int afs_file_release(struct inode *inode, struct file *file); | |||
29 | 29 | ||
30 | static int afs_file_readpage(struct file *file, struct page *page); | 30 | static int afs_file_readpage(struct file *file, struct page *page); |
31 | static int afs_file_invalidatepage(struct page *page, unsigned long offset); | 31 | static int afs_file_invalidatepage(struct page *page, unsigned long offset); |
32 | static int afs_file_releasepage(struct page *page, int gfp_flags); | 32 | static int afs_file_releasepage(struct page *page, gfp_t gfp_flags); |
33 | 33 | ||
34 | static ssize_t afs_file_write(struct file *file, const char __user *buf, | 34 | static ssize_t afs_file_write(struct file *file, const char __user *buf, |
35 | size_t size, loff_t *off); | 35 | size_t size, loff_t *off); |
@@ -279,7 +279,7 @@ static int afs_file_invalidatepage(struct page *page, unsigned long offset) | |||
279 | /* | 279 | /* |
280 | * release a page and cleanup its private data | 280 | * release a page and cleanup its private data |
281 | */ | 281 | */ |
282 | static int afs_file_releasepage(struct page *page, int gfp_flags) | 282 | static int afs_file_releasepage(struct page *page, gfp_t gfp_flags) |
283 | { | 283 | { |
284 | struct cachefs_page *pageio; | 284 | struct cachefs_page *pageio; |
285 | 285 | ||
@@ -398,7 +398,7 @@ static struct kiocb fastcall *__aio_get_req(struct kioctx *ctx) | |||
398 | if (unlikely(!req)) | 398 | if (unlikely(!req)) |
399 | return NULL; | 399 | return NULL; |
400 | 400 | ||
401 | req->ki_flags = 1 << KIF_LOCKED; | 401 | req->ki_flags = 0; |
402 | req->ki_users = 2; | 402 | req->ki_users = 2; |
403 | req->ki_key = 0; | 403 | req->ki_key = 0; |
404 | req->ki_ctx = ctx; | 404 | req->ki_ctx = ctx; |
@@ -547,25 +547,6 @@ struct kioctx *lookup_ioctx(unsigned long ctx_id) | |||
547 | return ioctx; | 547 | return ioctx; |
548 | } | 548 | } |
549 | 549 | ||
550 | static int lock_kiocb_action(void *param) | ||
551 | { | ||
552 | schedule(); | ||
553 | return 0; | ||
554 | } | ||
555 | |||
556 | static inline void lock_kiocb(struct kiocb *iocb) | ||
557 | { | ||
558 | wait_on_bit_lock(&iocb->ki_flags, KIF_LOCKED, lock_kiocb_action, | ||
559 | TASK_UNINTERRUPTIBLE); | ||
560 | } | ||
561 | |||
562 | static inline void unlock_kiocb(struct kiocb *iocb) | ||
563 | { | ||
564 | kiocbClearLocked(iocb); | ||
565 | smp_mb__after_clear_bit(); | ||
566 | wake_up_bit(&iocb->ki_flags, KIF_LOCKED); | ||
567 | } | ||
568 | |||
569 | /* | 550 | /* |
570 | * use_mm | 551 | * use_mm |
571 | * Makes the calling kernel thread take on the specified | 552 | * Makes the calling kernel thread take on the specified |
@@ -741,19 +722,9 @@ static ssize_t aio_run_iocb(struct kiocb *iocb) | |||
741 | ret = retry(iocb); | 722 | ret = retry(iocb); |
742 | current->io_wait = NULL; | 723 | current->io_wait = NULL; |
743 | 724 | ||
744 | if (-EIOCBRETRY != ret) { | 725 | if (ret != -EIOCBRETRY && ret != -EIOCBQUEUED) { |
745 | if (-EIOCBQUEUED != ret) { | 726 | BUG_ON(!list_empty(&iocb->ki_wait.task_list)); |
746 | BUG_ON(!list_empty(&iocb->ki_wait.task_list)); | 727 | aio_complete(iocb, ret, 0); |
747 | aio_complete(iocb, ret, 0); | ||
748 | /* must not access the iocb after this */ | ||
749 | } | ||
750 | } else { | ||
751 | /* | ||
752 | * Issue an additional retry to avoid waiting forever if | ||
753 | * no waits were queued (e.g. in case of a short read). | ||
754 | */ | ||
755 | if (list_empty(&iocb->ki_wait.task_list)) | ||
756 | kiocbSetKicked(iocb); | ||
757 | } | 728 | } |
758 | out: | 729 | out: |
759 | spin_lock_irq(&ctx->ctx_lock); | 730 | spin_lock_irq(&ctx->ctx_lock); |
@@ -806,9 +777,7 @@ static int __aio_run_iocbs(struct kioctx *ctx) | |||
806 | * Hold an extra reference while retrying i/o. | 777 | * Hold an extra reference while retrying i/o. |
807 | */ | 778 | */ |
808 | iocb->ki_users++; /* grab extra reference */ | 779 | iocb->ki_users++; /* grab extra reference */ |
809 | lock_kiocb(iocb); | ||
810 | aio_run_iocb(iocb); | 780 | aio_run_iocb(iocb); |
811 | unlock_kiocb(iocb); | ||
812 | if (__aio_put_req(ctx, iocb)) /* drop extra ref */ | 781 | if (__aio_put_req(ctx, iocb)) /* drop extra ref */ |
813 | put_ioctx(ctx); | 782 | put_ioctx(ctx); |
814 | } | 783 | } |
@@ -899,16 +868,24 @@ static void aio_kick_handler(void *data) | |||
899 | * and if required activate the aio work queue to process | 868 | * and if required activate the aio work queue to process |
900 | * it | 869 | * it |
901 | */ | 870 | */ |
902 | static void queue_kicked_iocb(struct kiocb *iocb) | 871 | static void try_queue_kicked_iocb(struct kiocb *iocb) |
903 | { | 872 | { |
904 | struct kioctx *ctx = iocb->ki_ctx; | 873 | struct kioctx *ctx = iocb->ki_ctx; |
905 | unsigned long flags; | 874 | unsigned long flags; |
906 | int run = 0; | 875 | int run = 0; |
907 | 876 | ||
908 | WARN_ON((!list_empty(&iocb->ki_wait.task_list))); | 877 | /* We're supposed to be the only path putting the iocb back on the run |
878 | * list. If we find that the iocb is *back* on a wait queue already | ||
879 | * than retry has happened before we could queue the iocb. This also | ||
880 | * means that the retry could have completed and freed our iocb, no | ||
881 | * good. */ | ||
882 | BUG_ON((!list_empty(&iocb->ki_wait.task_list))); | ||
909 | 883 | ||
910 | spin_lock_irqsave(&ctx->ctx_lock, flags); | 884 | spin_lock_irqsave(&ctx->ctx_lock, flags); |
911 | run = __queue_kicked_iocb(iocb); | 885 | /* set this inside the lock so that we can't race with aio_run_iocb() |
886 | * testing it and putting the iocb on the run list under the lock */ | ||
887 | if (!kiocbTryKick(iocb)) | ||
888 | run = __queue_kicked_iocb(iocb); | ||
912 | spin_unlock_irqrestore(&ctx->ctx_lock, flags); | 889 | spin_unlock_irqrestore(&ctx->ctx_lock, flags); |
913 | if (run) | 890 | if (run) |
914 | aio_queue_work(ctx); | 891 | aio_queue_work(ctx); |
@@ -931,10 +908,7 @@ void fastcall kick_iocb(struct kiocb *iocb) | |||
931 | return; | 908 | return; |
932 | } | 909 | } |
933 | 910 | ||
934 | /* If its already kicked we shouldn't queue it again */ | 911 | try_queue_kicked_iocb(iocb); |
935 | if (!kiocbTryKick(iocb)) { | ||
936 | queue_kicked_iocb(iocb); | ||
937 | } | ||
938 | } | 912 | } |
939 | EXPORT_SYMBOL(kick_iocb); | 913 | EXPORT_SYMBOL(kick_iocb); |
940 | 914 | ||
@@ -1322,8 +1296,11 @@ asmlinkage long sys_io_destroy(aio_context_t ctx) | |||
1322 | } | 1296 | } |
1323 | 1297 | ||
1324 | /* | 1298 | /* |
1325 | * Default retry method for aio_read (also used for first time submit) | 1299 | * aio_p{read,write} are the default ki_retry methods for |
1326 | * Responsible for updating iocb state as retries progress | 1300 | * IO_CMD_P{READ,WRITE}. They maintains kiocb retry state around potentially |
1301 | * multiple calls to f_op->aio_read(). They loop around partial progress | ||
1302 | * instead of returning -EIOCBRETRY because they don't have the means to call | ||
1303 | * kick_iocb(). | ||
1327 | */ | 1304 | */ |
1328 | static ssize_t aio_pread(struct kiocb *iocb) | 1305 | static ssize_t aio_pread(struct kiocb *iocb) |
1329 | { | 1306 | { |
@@ -1332,25 +1309,25 @@ static ssize_t aio_pread(struct kiocb *iocb) | |||
1332 | struct inode *inode = mapping->host; | 1309 | struct inode *inode = mapping->host; |
1333 | ssize_t ret = 0; | 1310 | ssize_t ret = 0; |
1334 | 1311 | ||
1335 | ret = file->f_op->aio_read(iocb, iocb->ki_buf, | 1312 | do { |
1336 | iocb->ki_left, iocb->ki_pos); | 1313 | ret = file->f_op->aio_read(iocb, iocb->ki_buf, |
1314 | iocb->ki_left, iocb->ki_pos); | ||
1315 | /* | ||
1316 | * Can't just depend on iocb->ki_left to determine | ||
1317 | * whether we are done. This may have been a short read. | ||
1318 | */ | ||
1319 | if (ret > 0) { | ||
1320 | iocb->ki_buf += ret; | ||
1321 | iocb->ki_left -= ret; | ||
1322 | } | ||
1337 | 1323 | ||
1338 | /* | ||
1339 | * Can't just depend on iocb->ki_left to determine | ||
1340 | * whether we are done. This may have been a short read. | ||
1341 | */ | ||
1342 | if (ret > 0) { | ||
1343 | iocb->ki_buf += ret; | ||
1344 | iocb->ki_left -= ret; | ||
1345 | /* | 1324 | /* |
1346 | * For pipes and sockets we return once we have | 1325 | * For pipes and sockets we return once we have some data; for |
1347 | * some data; for regular files we retry till we | 1326 | * regular files we retry till we complete the entire read or |
1348 | * complete the entire read or find that we can't | 1327 | * find that we can't read any more data (e.g short reads). |
1349 | * read any more data (e.g short reads). | ||
1350 | */ | 1328 | */ |
1351 | if (!S_ISFIFO(inode->i_mode) && !S_ISSOCK(inode->i_mode)) | 1329 | } while (ret > 0 && iocb->ki_left > 0 && |
1352 | ret = -EIOCBRETRY; | 1330 | !S_ISFIFO(inode->i_mode) && !S_ISSOCK(inode->i_mode)); |
1353 | } | ||
1354 | 1331 | ||
1355 | /* This means we must have transferred all that we could */ | 1332 | /* This means we must have transferred all that we could */ |
1356 | /* No need to retry anymore */ | 1333 | /* No need to retry anymore */ |
@@ -1360,27 +1337,21 @@ static ssize_t aio_pread(struct kiocb *iocb) | |||
1360 | return ret; | 1337 | return ret; |
1361 | } | 1338 | } |
1362 | 1339 | ||
1363 | /* | 1340 | /* see aio_pread() */ |
1364 | * Default retry method for aio_write (also used for first time submit) | ||
1365 | * Responsible for updating iocb state as retries progress | ||
1366 | */ | ||
1367 | static ssize_t aio_pwrite(struct kiocb *iocb) | 1341 | static ssize_t aio_pwrite(struct kiocb *iocb) |
1368 | { | 1342 | { |
1369 | struct file *file = iocb->ki_filp; | 1343 | struct file *file = iocb->ki_filp; |
1370 | ssize_t ret = 0; | 1344 | ssize_t ret = 0; |
1371 | 1345 | ||
1372 | ret = file->f_op->aio_write(iocb, iocb->ki_buf, | 1346 | do { |
1373 | iocb->ki_left, iocb->ki_pos); | 1347 | ret = file->f_op->aio_write(iocb, iocb->ki_buf, |
1374 | 1348 | iocb->ki_left, iocb->ki_pos); | |
1375 | if (ret > 0) { | 1349 | if (ret > 0) { |
1376 | iocb->ki_buf += ret; | 1350 | iocb->ki_buf += ret; |
1377 | iocb->ki_left -= ret; | 1351 | iocb->ki_left -= ret; |
1378 | 1352 | } | |
1379 | ret = -EIOCBRETRY; | 1353 | } while (ret > 0 && iocb->ki_left > 0); |
1380 | } | ||
1381 | 1354 | ||
1382 | /* This means we must have transferred all that we could */ | ||
1383 | /* No need to retry anymore */ | ||
1384 | if ((ret == 0) || (iocb->ki_left == 0)) | 1355 | if ((ret == 0) || (iocb->ki_left == 0)) |
1385 | ret = iocb->ki_nbytes - iocb->ki_left; | 1356 | ret = iocb->ki_nbytes - iocb->ki_left; |
1386 | 1357 | ||
@@ -1426,6 +1397,9 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb) | |||
1426 | if (unlikely(!access_ok(VERIFY_WRITE, kiocb->ki_buf, | 1397 | if (unlikely(!access_ok(VERIFY_WRITE, kiocb->ki_buf, |
1427 | kiocb->ki_left))) | 1398 | kiocb->ki_left))) |
1428 | break; | 1399 | break; |
1400 | ret = security_file_permission(file, MAY_READ); | ||
1401 | if (unlikely(ret)) | ||
1402 | break; | ||
1429 | ret = -EINVAL; | 1403 | ret = -EINVAL; |
1430 | if (file->f_op->aio_read) | 1404 | if (file->f_op->aio_read) |
1431 | kiocb->ki_retry = aio_pread; | 1405 | kiocb->ki_retry = aio_pread; |
@@ -1438,6 +1412,9 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb) | |||
1438 | if (unlikely(!access_ok(VERIFY_READ, kiocb->ki_buf, | 1412 | if (unlikely(!access_ok(VERIFY_READ, kiocb->ki_buf, |
1439 | kiocb->ki_left))) | 1413 | kiocb->ki_left))) |
1440 | break; | 1414 | break; |
1415 | ret = security_file_permission(file, MAY_WRITE); | ||
1416 | if (unlikely(ret)) | ||
1417 | break; | ||
1441 | ret = -EINVAL; | 1418 | ret = -EINVAL; |
1442 | if (file->f_op->aio_write) | 1419 | if (file->f_op->aio_write) |
1443 | kiocb->ki_retry = aio_pwrite; | 1420 | kiocb->ki_retry = aio_pwrite; |
@@ -1550,7 +1527,6 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, | |||
1550 | 1527 | ||
1551 | spin_lock_irq(&ctx->ctx_lock); | 1528 | spin_lock_irq(&ctx->ctx_lock); |
1552 | aio_run_iocb(req); | 1529 | aio_run_iocb(req); |
1553 | unlock_kiocb(req); | ||
1554 | if (!list_empty(&ctx->run_list)) { | 1530 | if (!list_empty(&ctx->run_list)) { |
1555 | /* drain the run list */ | 1531 | /* drain the run list */ |
1556 | while (__aio_run_iocbs(ctx)) | 1532 | while (__aio_run_iocbs(ctx)) |
@@ -1682,7 +1658,6 @@ asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb, | |||
1682 | if (NULL != cancel) { | 1658 | if (NULL != cancel) { |
1683 | struct io_event tmp; | 1659 | struct io_event tmp; |
1684 | pr_debug("calling cancel\n"); | 1660 | pr_debug("calling cancel\n"); |
1685 | lock_kiocb(kiocb); | ||
1686 | memset(&tmp, 0, sizeof(tmp)); | 1661 | memset(&tmp, 0, sizeof(tmp)); |
1687 | tmp.obj = (u64)(unsigned long)kiocb->ki_obj.user; | 1662 | tmp.obj = (u64)(unsigned long)kiocb->ki_obj.user; |
1688 | tmp.data = kiocb->ki_user_data; | 1663 | tmp.data = kiocb->ki_user_data; |
@@ -1694,7 +1669,6 @@ asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb, | |||
1694 | if (copy_to_user(result, &tmp, sizeof(tmp))) | 1669 | if (copy_to_user(result, &tmp, sizeof(tmp))) |
1695 | ret = -EFAULT; | 1670 | ret = -EFAULT; |
1696 | } | 1671 | } |
1697 | unlock_kiocb(kiocb); | ||
1698 | } else | 1672 | } else |
1699 | ret = -EINVAL; | 1673 | ret = -EINVAL; |
1700 | 1674 | ||
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index e240c335eb23..5af928fa0449 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c | |||
@@ -108,7 +108,7 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode, | |||
108 | inode->i_mapping->a_ops = &bfs_aops; | 108 | inode->i_mapping->a_ops = &bfs_aops; |
109 | inode->i_mode = mode; | 109 | inode->i_mode = mode; |
110 | inode->i_ino = ino; | 110 | inode->i_ino = ino; |
111 | BFS_I(inode)->i_dsk_ino = cpu_to_le16(ino); | 111 | BFS_I(inode)->i_dsk_ino = ino; |
112 | BFS_I(inode)->i_sblock = 0; | 112 | BFS_I(inode)->i_sblock = 0; |
113 | BFS_I(inode)->i_eblock = 0; | 113 | BFS_I(inode)->i_eblock = 0; |
114 | insert_inode_hash(inode); | 114 | insert_inode_hash(inode); |
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index c7b39aa279d7..3af6c73c5b5a 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c | |||
@@ -357,28 +357,46 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) | |||
357 | } | 357 | } |
358 | 358 | ||
359 | info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1)>>BFS_BSIZE_BITS; /* for statfs(2) */ | 359 | info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1)>>BFS_BSIZE_BITS; /* for statfs(2) */ |
360 | info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1 - cpu_to_le32(bfs_sb->s_start))>>BFS_BSIZE_BITS; | 360 | info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1 - le32_to_cpu(bfs_sb->s_start))>>BFS_BSIZE_BITS; |
361 | info->si_freei = 0; | 361 | info->si_freei = 0; |
362 | info->si_lf_eblk = 0; | 362 | info->si_lf_eblk = 0; |
363 | info->si_lf_sblk = 0; | 363 | info->si_lf_sblk = 0; |
364 | info->si_lf_ioff = 0; | 364 | info->si_lf_ioff = 0; |
365 | bh = NULL; | ||
365 | for (i=BFS_ROOT_INO; i<=info->si_lasti; i++) { | 366 | for (i=BFS_ROOT_INO; i<=info->si_lasti; i++) { |
366 | inode = iget(s,i); | 367 | struct bfs_inode *di; |
367 | if (BFS_I(inode)->i_dsk_ino == 0) | 368 | int block = (i - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1; |
369 | int off = (i - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK; | ||
370 | unsigned long sblock, eblock; | ||
371 | |||
372 | if (!off) { | ||
373 | brelse(bh); | ||
374 | bh = sb_bread(s, block); | ||
375 | } | ||
376 | |||
377 | if (!bh) | ||
378 | continue; | ||
379 | |||
380 | di = (struct bfs_inode *)bh->b_data + off; | ||
381 | |||
382 | if (!di->i_ino) { | ||
368 | info->si_freei++; | 383 | info->si_freei++; |
369 | else { | 384 | continue; |
370 | set_bit(i, info->si_imap); | 385 | } |
371 | info->si_freeb -= inode->i_blocks; | 386 | set_bit(i, info->si_imap); |
372 | if (BFS_I(inode)->i_eblock > info->si_lf_eblk) { | 387 | info->si_freeb -= BFS_FILEBLOCKS(di); |
373 | info->si_lf_eblk = BFS_I(inode)->i_eblock; | 388 | |
374 | info->si_lf_sblk = BFS_I(inode)->i_sblock; | 389 | sblock = le32_to_cpu(di->i_sblock); |
375 | info->si_lf_ioff = BFS_INO2OFF(i); | 390 | eblock = le32_to_cpu(di->i_eblock); |
376 | } | 391 | if (eblock > info->si_lf_eblk) { |
392 | info->si_lf_eblk = eblock; | ||
393 | info->si_lf_sblk = sblock; | ||
394 | info->si_lf_ioff = BFS_INO2OFF(i); | ||
377 | } | 395 | } |
378 | iput(inode); | ||
379 | } | 396 | } |
397 | brelse(bh); | ||
380 | if (!(s->s_flags & MS_RDONLY)) { | 398 | if (!(s->s_flags & MS_RDONLY)) { |
381 | mark_buffer_dirty(bh); | 399 | mark_buffer_dirty(info->si_sbh); |
382 | s->s_dirt = 1; | 400 | s->s_dirt = 1; |
383 | } | 401 | } |
384 | dump_imap("read_super", s); | 402 | dump_imap("read_super", s); |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 7976a238f0a3..d4b15576e584 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -905,7 +905,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
905 | send_sig(SIGKILL, current, 0); | 905 | send_sig(SIGKILL, current, 0); |
906 | goto out_free_dentry; | 906 | goto out_free_dentry; |
907 | } | 907 | } |
908 | if (padzero(elf_bss)) { | 908 | if (likely(elf_bss != elf_brk) && unlikely(padzero(elf_bss))) { |
909 | send_sig(SIGSEGV, current, 0); | 909 | send_sig(SIGSEGV, current, 0); |
910 | retval = -EFAULT; /* Nobody gets to see this, but.. */ | 910 | retval = -EFAULT; /* Nobody gets to see this, but.. */ |
911 | goto out_free_dentry; | 911 | goto out_free_dentry; |
@@ -75,7 +75,7 @@ struct bio_set { | |||
75 | */ | 75 | */ |
76 | static struct bio_set *fs_bio_set; | 76 | static struct bio_set *fs_bio_set; |
77 | 77 | ||
78 | static inline struct bio_vec *bvec_alloc_bs(unsigned int __nocast gfp_mask, int nr, unsigned long *idx, struct bio_set *bs) | 78 | static inline struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx, struct bio_set *bs) |
79 | { | 79 | { |
80 | struct bio_vec *bvl; | 80 | struct bio_vec *bvl; |
81 | struct biovec_slab *bp; | 81 | struct biovec_slab *bp; |
@@ -155,7 +155,7 @@ inline void bio_init(struct bio *bio) | |||
155 | * allocate bio and iovecs from the memory pools specified by the | 155 | * allocate bio and iovecs from the memory pools specified by the |
156 | * bio_set structure. | 156 | * bio_set structure. |
157 | **/ | 157 | **/ |
158 | struct bio *bio_alloc_bioset(unsigned int __nocast gfp_mask, int nr_iovecs, struct bio_set *bs) | 158 | struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs) |
159 | { | 159 | { |
160 | struct bio *bio = mempool_alloc(bs->bio_pool, gfp_mask); | 160 | struct bio *bio = mempool_alloc(bs->bio_pool, gfp_mask); |
161 | 161 | ||
@@ -181,7 +181,7 @@ out: | |||
181 | return bio; | 181 | return bio; |
182 | } | 182 | } |
183 | 183 | ||
184 | struct bio *bio_alloc(unsigned int __nocast gfp_mask, int nr_iovecs) | 184 | struct bio *bio_alloc(gfp_t gfp_mask, int nr_iovecs) |
185 | { | 185 | { |
186 | struct bio *bio = bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set); | 186 | struct bio *bio = bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set); |
187 | 187 | ||
@@ -277,7 +277,7 @@ inline void __bio_clone(struct bio *bio, struct bio *bio_src) | |||
277 | * | 277 | * |
278 | * Like __bio_clone, only also allocates the returned bio | 278 | * Like __bio_clone, only also allocates the returned bio |
279 | */ | 279 | */ |
280 | struct bio *bio_clone(struct bio *bio, unsigned int __nocast gfp_mask) | 280 | struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask) |
281 | { | 281 | { |
282 | struct bio *b = bio_alloc_bioset(gfp_mask, bio->bi_max_vecs, fs_bio_set); | 282 | struct bio *b = bio_alloc_bioset(gfp_mask, bio->bi_max_vecs, fs_bio_set); |
283 | 283 | ||
@@ -778,7 +778,7 @@ static int bio_map_kern_endio(struct bio *bio, unsigned int bytes_done, int err) | |||
778 | 778 | ||
779 | 779 | ||
780 | static struct bio *__bio_map_kern(request_queue_t *q, void *data, | 780 | static struct bio *__bio_map_kern(request_queue_t *q, void *data, |
781 | unsigned int len, unsigned int gfp_mask) | 781 | unsigned int len, gfp_t gfp_mask) |
782 | { | 782 | { |
783 | unsigned long kaddr = (unsigned long)data; | 783 | unsigned long kaddr = (unsigned long)data; |
784 | unsigned long end = (kaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT; | 784 | unsigned long end = (kaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT; |
@@ -825,7 +825,7 @@ static struct bio *__bio_map_kern(request_queue_t *q, void *data, | |||
825 | * device. Returns an error pointer in case of error. | 825 | * device. Returns an error pointer in case of error. |
826 | */ | 826 | */ |
827 | struct bio *bio_map_kern(request_queue_t *q, void *data, unsigned int len, | 827 | struct bio *bio_map_kern(request_queue_t *q, void *data, unsigned int len, |
828 | unsigned int gfp_mask) | 828 | gfp_t gfp_mask) |
829 | { | 829 | { |
830 | struct bio *bio; | 830 | struct bio *bio; |
831 | 831 | ||
@@ -1078,7 +1078,7 @@ struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors) | |||
1078 | return bp; | 1078 | return bp; |
1079 | } | 1079 | } |
1080 | 1080 | ||
1081 | static void *bio_pair_alloc(unsigned int __nocast gfp_flags, void *data) | 1081 | static void *bio_pair_alloc(gfp_t gfp_flags, void *data) |
1082 | { | 1082 | { |
1083 | return kmalloc(sizeof(struct bio_pair), gfp_flags); | 1083 | return kmalloc(sizeof(struct bio_pair), gfp_flags); |
1084 | } | 1084 | } |
diff --git a/fs/buffer.c b/fs/buffer.c index 6cbfceabd95d..b1667986442f 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -502,7 +502,7 @@ static void free_more_memory(void) | |||
502 | yield(); | 502 | yield(); |
503 | 503 | ||
504 | for_each_pgdat(pgdat) { | 504 | for_each_pgdat(pgdat) { |
505 | zones = pgdat->node_zonelists[GFP_NOFS&GFP_ZONEMASK].zones; | 505 | zones = pgdat->node_zonelists[gfp_zone(GFP_NOFS)].zones; |
506 | if (*zones) | 506 | if (*zones) |
507 | try_to_free_pages(zones, GFP_NOFS); | 507 | try_to_free_pages(zones, GFP_NOFS); |
508 | } | 508 | } |
@@ -1571,7 +1571,7 @@ static inline void discard_buffer(struct buffer_head * bh) | |||
1571 | * | 1571 | * |
1572 | * NOTE: @gfp_mask may go away, and this function may become non-blocking. | 1572 | * NOTE: @gfp_mask may go away, and this function may become non-blocking. |
1573 | */ | 1573 | */ |
1574 | int try_to_release_page(struct page *page, int gfp_mask) | 1574 | int try_to_release_page(struct page *page, gfp_t gfp_mask) |
1575 | { | 1575 | { |
1576 | struct address_space * const mapping = page->mapping; | 1576 | struct address_space * const mapping = page->mapping; |
1577 | 1577 | ||
@@ -3045,7 +3045,7 @@ static void recalc_bh_state(void) | |||
3045 | buffer_heads_over_limit = (tot > max_buffer_heads); | 3045 | buffer_heads_over_limit = (tot > max_buffer_heads); |
3046 | } | 3046 | } |
3047 | 3047 | ||
3048 | struct buffer_head *alloc_buffer_head(unsigned int __nocast gfp_flags) | 3048 | struct buffer_head *alloc_buffer_head(gfp_t gfp_flags) |
3049 | { | 3049 | { |
3050 | struct buffer_head *ret = kmem_cache_alloc(bh_cachep, gfp_flags); | 3050 | struct buffer_head *ret = kmem_cache_alloc(bh_cachep, gfp_flags); |
3051 | if (ret) { | 3051 | if (ret) { |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 8cc23e7d0d5d..1ebf7dafc1d7 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -781,6 +781,8 @@ static int cifs_oplock_thread(void * dummyarg) | |||
781 | 781 | ||
782 | oplockThread = current; | 782 | oplockThread = current; |
783 | do { | 783 | do { |
784 | if (try_to_freeze()) | ||
785 | continue; | ||
784 | set_current_state(TASK_INTERRUPTIBLE); | 786 | set_current_state(TASK_INTERRUPTIBLE); |
785 | 787 | ||
786 | schedule_timeout(1*HZ); | 788 | schedule_timeout(1*HZ); |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 2335f14a1583..47360156cc54 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -344,6 +344,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
344 | } | 344 | } |
345 | 345 | ||
346 | while (server->tcpStatus != CifsExiting) { | 346 | while (server->tcpStatus != CifsExiting) { |
347 | if (try_to_freeze()) | ||
348 | continue; | ||
347 | if (bigbuf == NULL) { | 349 | if (bigbuf == NULL) { |
348 | bigbuf = cifs_buf_get(); | 350 | bigbuf = cifs_buf_get(); |
349 | if(bigbuf == NULL) { | 351 | if(bigbuf == NULL) { |
diff --git a/fs/dcache.c b/fs/dcache.c index fb10386c59be..e90512ed35a4 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -689,7 +689,7 @@ void shrink_dcache_anon(struct hlist_head *head) | |||
689 | * | 689 | * |
690 | * In this case we return -1 to tell the caller that we baled. | 690 | * In this case we return -1 to tell the caller that we baled. |
691 | */ | 691 | */ |
692 | static int shrink_dcache_memory(int nr, unsigned int gfp_mask) | 692 | static int shrink_dcache_memory(int nr, gfp_t gfp_mask) |
693 | { | 693 | { |
694 | if (nr) { | 694 | if (nr) { |
695 | if (!(gfp_mask & __GFP_FS)) | 695 | if (!(gfp_mask & __GFP_FS)) |
diff --git a/fs/dquot.c b/fs/dquot.c index b9732335bcdc..05f3327d64a3 100644 --- a/fs/dquot.c +++ b/fs/dquot.c | |||
@@ -500,7 +500,7 @@ static void prune_dqcache(int count) | |||
500 | * more memory | 500 | * more memory |
501 | */ | 501 | */ |
502 | 502 | ||
503 | static int shrink_dqcache_memory(int nr, unsigned int gfp_mask) | 503 | static int shrink_dqcache_memory(int nr, gfp_t gfp_mask) |
504 | { | 504 | { |
505 | if (nr) { | 505 | if (nr) { |
506 | spin_lock(&dq_list_lock); | 506 | spin_lock(&dq_list_lock); |
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 403b90a1213d..4284cd31eba6 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c | |||
@@ -101,6 +101,10 @@ | |||
101 | /* Maximum number of poll wake up nests we are allowing */ | 101 | /* Maximum number of poll wake up nests we are allowing */ |
102 | #define EP_MAX_POLLWAKE_NESTS 4 | 102 | #define EP_MAX_POLLWAKE_NESTS 4 |
103 | 103 | ||
104 | /* Maximum msec timeout value storeable in a long int */ | ||
105 | #define EP_MAX_MSTIMEO min(1000ULL * MAX_SCHEDULE_TIMEOUT / HZ, (LONG_MAX - 999ULL) / HZ) | ||
106 | |||
107 | |||
104 | struct epoll_filefd { | 108 | struct epoll_filefd { |
105 | struct file *file; | 109 | struct file *file; |
106 | int fd; | 110 | int fd; |
@@ -1506,8 +1510,8 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, | |||
1506 | * and the overflow condition. The passed timeout is in milliseconds, | 1510 | * and the overflow condition. The passed timeout is in milliseconds, |
1507 | * that why (t * HZ) / 1000. | 1511 | * that why (t * HZ) / 1000. |
1508 | */ | 1512 | */ |
1509 | jtimeout = timeout == -1 || timeout > (MAX_SCHEDULE_TIMEOUT - 1000) / HZ ? | 1513 | jtimeout = (timeout < 0 || timeout >= EP_MAX_MSTIMEO) ? |
1510 | MAX_SCHEDULE_TIMEOUT: (timeout * HZ + 999) / 1000; | 1514 | MAX_SCHEDULE_TIMEOUT : (timeout * HZ + 999) / 1000; |
1511 | 1515 | ||
1512 | retry: | 1516 | retry: |
1513 | write_lock_irqsave(&ep->lock, flags); | 1517 | write_lock_irqsave(&ep->lock, flags); |
@@ -126,8 +126,7 @@ asmlinkage long sys_uselib(const char __user * library) | |||
126 | struct nameidata nd; | 126 | struct nameidata nd; |
127 | int error; | 127 | int error; |
128 | 128 | ||
129 | nd.intent.open.flags = FMODE_READ; | 129 | error = __user_path_lookup_open(library, LOOKUP_FOLLOW, &nd, FMODE_READ); |
130 | error = __user_walk(library, LOOKUP_FOLLOW|LOOKUP_OPEN, &nd); | ||
131 | if (error) | 130 | if (error) |
132 | goto out; | 131 | goto out; |
133 | 132 | ||
@@ -139,7 +138,7 @@ asmlinkage long sys_uselib(const char __user * library) | |||
139 | if (error) | 138 | if (error) |
140 | goto exit; | 139 | goto exit; |
141 | 140 | ||
142 | file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); | 141 | file = nameidata_to_filp(&nd, O_RDONLY); |
143 | error = PTR_ERR(file); | 142 | error = PTR_ERR(file); |
144 | if (IS_ERR(file)) | 143 | if (IS_ERR(file)) |
145 | goto out; | 144 | goto out; |
@@ -167,6 +166,7 @@ asmlinkage long sys_uselib(const char __user * library) | |||
167 | out: | 166 | out: |
168 | return error; | 167 | return error; |
169 | exit: | 168 | exit: |
169 | release_open_intent(&nd); | ||
170 | path_release(&nd); | 170 | path_release(&nd); |
171 | goto out; | 171 | goto out; |
172 | } | 172 | } |
@@ -490,8 +490,7 @@ struct file *open_exec(const char *name) | |||
490 | int err; | 490 | int err; |
491 | struct file *file; | 491 | struct file *file; |
492 | 492 | ||
493 | nd.intent.open.flags = FMODE_READ; | 493 | err = path_lookup_open(name, LOOKUP_FOLLOW, &nd, FMODE_READ); |
494 | err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_OPEN, &nd); | ||
495 | file = ERR_PTR(err); | 494 | file = ERR_PTR(err); |
496 | 495 | ||
497 | if (!err) { | 496 | if (!err) { |
@@ -504,7 +503,7 @@ struct file *open_exec(const char *name) | |||
504 | err = -EACCES; | 503 | err = -EACCES; |
505 | file = ERR_PTR(err); | 504 | file = ERR_PTR(err); |
506 | if (!err) { | 505 | if (!err) { |
507 | file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); | 506 | file = nameidata_to_filp(&nd, O_RDONLY); |
508 | if (!IS_ERR(file)) { | 507 | if (!IS_ERR(file)) { |
509 | err = deny_write_access(file); | 508 | err = deny_write_access(file); |
510 | if (err) { | 509 | if (err) { |
@@ -516,6 +515,7 @@ out: | |||
516 | return file; | 515 | return file; |
517 | } | 516 | } |
518 | } | 517 | } |
518 | release_open_intent(&nd); | ||
519 | path_release(&nd); | 519 | path_release(&nd); |
520 | } | 520 | } |
521 | goto out; | 521 | goto out; |
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index c8d07030c897..e2d6208633a7 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c | |||
@@ -605,27 +605,28 @@ got: | |||
605 | insert_inode_hash(inode); | 605 | insert_inode_hash(inode); |
606 | 606 | ||
607 | if (DQUOT_ALLOC_INODE(inode)) { | 607 | if (DQUOT_ALLOC_INODE(inode)) { |
608 | DQUOT_DROP(inode); | ||
609 | err = -ENOSPC; | 608 | err = -ENOSPC; |
610 | goto fail2; | 609 | goto fail_drop; |
611 | } | 610 | } |
611 | |||
612 | err = ext2_init_acl(inode, dir); | 612 | err = ext2_init_acl(inode, dir); |
613 | if (err) { | 613 | if (err) |
614 | DQUOT_FREE_INODE(inode); | 614 | goto fail_free_drop; |
615 | DQUOT_DROP(inode); | 615 | |
616 | goto fail2; | ||
617 | } | ||
618 | err = ext2_init_security(inode,dir); | 616 | err = ext2_init_security(inode,dir); |
619 | if (err) { | 617 | if (err) |
620 | DQUOT_FREE_INODE(inode); | 618 | goto fail_free_drop; |
621 | goto fail2; | 619 | |
622 | } | ||
623 | mark_inode_dirty(inode); | 620 | mark_inode_dirty(inode); |
624 | ext2_debug("allocating inode %lu\n", inode->i_ino); | 621 | ext2_debug("allocating inode %lu\n", inode->i_ino); |
625 | ext2_preread_inode(inode); | 622 | ext2_preread_inode(inode); |
626 | return inode; | 623 | return inode; |
627 | 624 | ||
628 | fail2: | 625 | fail_free_drop: |
626 | DQUOT_FREE_INODE(inode); | ||
627 | |||
628 | fail_drop: | ||
629 | DQUOT_DROP(inode); | ||
629 | inode->i_flags |= S_NOQUOTA; | 630 | inode->i_flags |= S_NOQUOTA; |
630 | inode->i_nlink = 0; | 631 | inode->i_nlink = 0; |
631 | iput(inode); | 632 | iput(inode); |
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index e463dca008e4..0213db4911a2 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c | |||
@@ -1410,7 +1410,7 @@ unsigned long ext3_count_free_blocks(struct super_block *sb) | |||
1410 | unsigned long desc_count; | 1410 | unsigned long desc_count; |
1411 | struct ext3_group_desc *gdp; | 1411 | struct ext3_group_desc *gdp; |
1412 | int i; | 1412 | int i; |
1413 | unsigned long ngroups; | 1413 | unsigned long ngroups = EXT3_SB(sb)->s_groups_count; |
1414 | #ifdef EXT3FS_DEBUG | 1414 | #ifdef EXT3FS_DEBUG |
1415 | struct ext3_super_block *es; | 1415 | struct ext3_super_block *es; |
1416 | unsigned long bitmap_count, x; | 1416 | unsigned long bitmap_count, x; |
@@ -1421,7 +1421,8 @@ unsigned long ext3_count_free_blocks(struct super_block *sb) | |||
1421 | desc_count = 0; | 1421 | desc_count = 0; |
1422 | bitmap_count = 0; | 1422 | bitmap_count = 0; |
1423 | gdp = NULL; | 1423 | gdp = NULL; |
1424 | for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) { | 1424 | |
1425 | for (i = 0; i < ngroups; i++) { | ||
1425 | gdp = ext3_get_group_desc(sb, i, NULL); | 1426 | gdp = ext3_get_group_desc(sb, i, NULL); |
1426 | if (!gdp) | 1427 | if (!gdp) |
1427 | continue; | 1428 | continue; |
@@ -1443,7 +1444,6 @@ unsigned long ext3_count_free_blocks(struct super_block *sb) | |||
1443 | return bitmap_count; | 1444 | return bitmap_count; |
1444 | #else | 1445 | #else |
1445 | desc_count = 0; | 1446 | desc_count = 0; |
1446 | ngroups = EXT3_SB(sb)->s_groups_count; | ||
1447 | smp_rmb(); | 1447 | smp_rmb(); |
1448 | for (i = 0; i < ngroups; i++) { | 1448 | for (i = 0; i < ngroups; i++) { |
1449 | gdp = ext3_get_group_desc(sb, i, NULL); | 1449 | gdp = ext3_get_group_desc(sb, i, NULL); |
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index 96552769d039..6549945f9ac1 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c | |||
@@ -597,27 +597,22 @@ got: | |||
597 | 597 | ||
598 | ret = inode; | 598 | ret = inode; |
599 | if(DQUOT_ALLOC_INODE(inode)) { | 599 | if(DQUOT_ALLOC_INODE(inode)) { |
600 | DQUOT_DROP(inode); | ||
601 | err = -EDQUOT; | 600 | err = -EDQUOT; |
602 | goto fail2; | 601 | goto fail_drop; |
603 | } | 602 | } |
603 | |||
604 | err = ext3_init_acl(handle, inode, dir); | 604 | err = ext3_init_acl(handle, inode, dir); |
605 | if (err) { | 605 | if (err) |
606 | DQUOT_FREE_INODE(inode); | 606 | goto fail_free_drop; |
607 | DQUOT_DROP(inode); | 607 | |
608 | goto fail2; | ||
609 | } | ||
610 | err = ext3_init_security(handle,inode, dir); | 608 | err = ext3_init_security(handle,inode, dir); |
611 | if (err) { | 609 | if (err) |
612 | DQUOT_FREE_INODE(inode); | 610 | goto fail_free_drop; |
613 | goto fail2; | 611 | |
614 | } | ||
615 | err = ext3_mark_inode_dirty(handle, inode); | 612 | err = ext3_mark_inode_dirty(handle, inode); |
616 | if (err) { | 613 | if (err) { |
617 | ext3_std_error(sb, err); | 614 | ext3_std_error(sb, err); |
618 | DQUOT_FREE_INODE(inode); | 615 | goto fail_free_drop; |
619 | DQUOT_DROP(inode); | ||
620 | goto fail2; | ||
621 | } | 616 | } |
622 | 617 | ||
623 | ext3_debug("allocating inode %lu\n", inode->i_ino); | 618 | ext3_debug("allocating inode %lu\n", inode->i_ino); |
@@ -631,7 +626,11 @@ really_out: | |||
631 | brelse(bitmap_bh); | 626 | brelse(bitmap_bh); |
632 | return ret; | 627 | return ret; |
633 | 628 | ||
634 | fail2: | 629 | fail_free_drop: |
630 | DQUOT_FREE_INODE(inode); | ||
631 | |||
632 | fail_drop: | ||
633 | DQUOT_DROP(inode); | ||
635 | inode->i_flags |= S_NOQUOTA; | 634 | inode->i_flags |= S_NOQUOTA; |
636 | inode->i_nlink = 0; | 635 | inode->i_nlink = 0; |
637 | iput(inode); | 636 | iput(inode); |
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index b5177c90d6f1..8b38f2232796 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -1434,7 +1434,7 @@ static int ext3_invalidatepage(struct page *page, unsigned long offset) | |||
1434 | return journal_invalidatepage(journal, page, offset); | 1434 | return journal_invalidatepage(journal, page, offset); |
1435 | } | 1435 | } |
1436 | 1436 | ||
1437 | static int ext3_releasepage(struct page *page, int wait) | 1437 | static int ext3_releasepage(struct page *page, gfp_t wait) |
1438 | { | 1438 | { |
1439 | journal_t *journal = EXT3_JOURNAL(page->mapping->host); | 1439 | journal_t *journal = EXT3_JOURNAL(page->mapping->host); |
1440 | 1440 | ||
diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c index 2c9f81278d5d..57f79106267d 100644 --- a/fs/ext3/resize.c +++ b/fs/ext3/resize.c | |||
@@ -242,7 +242,7 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
242 | i < sbi->s_itb_per_group; i++, bit++, block++) { | 242 | i < sbi->s_itb_per_group; i++, bit++, block++) { |
243 | struct buffer_head *it; | 243 | struct buffer_head *it; |
244 | 244 | ||
245 | ext3_debug("clear inode block %#04x (+%ld)\n", block, bit); | 245 | ext3_debug("clear inode block %#04lx (+%d)\n", block, bit); |
246 | if (IS_ERR(it = bclean(handle, sb, block))) { | 246 | if (IS_ERR(it = bclean(handle, sb, block))) { |
247 | err = PTR_ERR(it); | 247 | err = PTR_ERR(it); |
248 | goto exit_bh; | 248 | goto exit_bh; |
@@ -643,8 +643,8 @@ static void update_backups(struct super_block *sb, | |||
643 | break; | 643 | break; |
644 | 644 | ||
645 | bh = sb_getblk(sb, group * bpg + blk_off); | 645 | bh = sb_getblk(sb, group * bpg + blk_off); |
646 | ext3_debug(sb, __FUNCTION__, "update metadata backup %#04lx\n", | 646 | ext3_debug("update metadata backup %#04lx\n", |
647 | bh->b_blocknr); | 647 | (unsigned long)bh->b_blocknr); |
648 | if ((err = ext3_journal_get_write_access(handle, bh))) | 648 | if ((err = ext3_journal_get_write_access(handle, bh))) |
649 | break; | 649 | break; |
650 | lock_buffer(bh); | 650 | lock_buffer(bh); |
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index a93c3609025d..9e24ceb019fe 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
@@ -512,15 +512,14 @@ static void ext3_clear_inode(struct inode *inode) | |||
512 | 512 | ||
513 | static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs) | 513 | static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs) |
514 | { | 514 | { |
515 | struct ext3_sb_info *sbi = EXT3_SB(vfs->mnt_sb); | 515 | struct super_block *sb = vfs->mnt_sb; |
516 | struct ext3_sb_info *sbi = EXT3_SB(sb); | ||
516 | 517 | ||
517 | if (sbi->s_mount_opt & EXT3_MOUNT_JOURNAL_DATA) | 518 | if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA) |
518 | seq_puts(seq, ",data=journal"); | 519 | seq_puts(seq, ",data=journal"); |
519 | 520 | else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA) | |
520 | if (sbi->s_mount_opt & EXT3_MOUNT_ORDERED_DATA) | ||
521 | seq_puts(seq, ",data=ordered"); | 521 | seq_puts(seq, ",data=ordered"); |
522 | 522 | else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA) | |
523 | if (sbi->s_mount_opt & EXT3_MOUNT_WRITEBACK_DATA) | ||
524 | seq_puts(seq, ",data=writeback"); | 523 | seq_puts(seq, ",data=writeback"); |
525 | 524 | ||
526 | #if defined(CONFIG_QUOTA) | 525 | #if defined(CONFIG_QUOTA) |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index e79e49b3eec7..29f1e9f6e85c 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -96,6 +96,8 @@ static int fuse_lookup_iget(struct inode *dir, struct dentry *entry, | |||
96 | fuse_lookup_init(req, dir, entry, &outarg); | 96 | fuse_lookup_init(req, dir, entry, &outarg); |
97 | request_send(fc, req); | 97 | request_send(fc, req); |
98 | err = req->out.h.error; | 98 | err = req->out.h.error; |
99 | if (!err && (!outarg.nodeid || outarg.nodeid == FUSE_ROOT_ID)) | ||
100 | err = -EIO; | ||
99 | if (!err) { | 101 | if (!err) { |
100 | inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, | 102 | inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, |
101 | &outarg.attr); | 103 | &outarg.attr); |
@@ -152,6 +154,10 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, | |||
152 | fuse_put_request(fc, req); | 154 | fuse_put_request(fc, req); |
153 | return err; | 155 | return err; |
154 | } | 156 | } |
157 | if (!outarg.nodeid || outarg.nodeid == FUSE_ROOT_ID) { | ||
158 | fuse_put_request(fc, req); | ||
159 | return -EIO; | ||
160 | } | ||
155 | inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, | 161 | inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, |
156 | &outarg.attr); | 162 | &outarg.attr); |
157 | if (!inode) { | 163 | if (!inode) { |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 6454022b0536..657ab11c173b 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -23,6 +23,10 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir) | |||
23 | struct fuse_file *ff; | 23 | struct fuse_file *ff; |
24 | int err; | 24 | int err; |
25 | 25 | ||
26 | /* VFS checks this, but only _after_ ->open() */ | ||
27 | if (file->f_flags & O_DIRECT) | ||
28 | return -EINVAL; | ||
29 | |||
26 | err = generic_file_open(inode, file); | 30 | err = generic_file_open(inode, file); |
27 | if (err) | 31 | if (err) |
28 | return err; | 32 | return err; |
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index f1570b9f9de3..3f680c5675bf 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c | |||
@@ -46,7 +46,7 @@ static sector_t hfs_bmap(struct address_space *mapping, sector_t block) | |||
46 | return generic_block_bmap(mapping, block, hfs_get_block); | 46 | return generic_block_bmap(mapping, block, hfs_get_block); |
47 | } | 47 | } |
48 | 48 | ||
49 | static int hfs_releasepage(struct page *page, int mask) | 49 | static int hfs_releasepage(struct page *page, gfp_t mask) |
50 | { | 50 | { |
51 | struct inode *inode = page->mapping->host; | 51 | struct inode *inode = page->mapping->host; |
52 | struct super_block *sb = inode->i_sb; | 52 | struct super_block *sb = inode->i_sb; |
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index d5642705f633..f205773ddfbe 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c | |||
@@ -40,7 +40,7 @@ static sector_t hfsplus_bmap(struct address_space *mapping, sector_t block) | |||
40 | return generic_block_bmap(mapping, block, hfsplus_get_block); | 40 | return generic_block_bmap(mapping, block, hfsplus_get_block); |
41 | } | 41 | } |
42 | 42 | ||
43 | static int hfsplus_releasepage(struct page *page, int mask) | 43 | static int hfsplus_releasepage(struct page *page, gfp_t mask) |
44 | { | 44 | { |
45 | struct inode *inode = page->mapping->host; | 45 | struct inode *inode = page->mapping->host; |
46 | struct super_block *sb = inode->i_sb; | 46 | struct super_block *sb = inode->i_sb; |
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index fd0f0f050e1d..452fc1fdbd32 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c | |||
@@ -50,6 +50,7 @@ static void hfsplus_read_inode(struct inode *inode) | |||
50 | init_MUTEX(&HFSPLUS_I(inode).extents_lock); | 50 | init_MUTEX(&HFSPLUS_I(inode).extents_lock); |
51 | HFSPLUS_I(inode).flags = 0; | 51 | HFSPLUS_I(inode).flags = 0; |
52 | HFSPLUS_I(inode).rsrc_inode = NULL; | 52 | HFSPLUS_I(inode).rsrc_inode = NULL; |
53 | atomic_set(&HFSPLUS_I(inode).opencnt, 0); | ||
53 | 54 | ||
54 | if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID) { | 55 | if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID) { |
55 | read_inode: | 56 | read_inode: |
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 59c5062cd63f..dd7113106269 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c | |||
@@ -793,11 +793,6 @@ int hostfs_rename(struct inode *from_ino, struct dentry *from, | |||
793 | return(err); | 793 | return(err); |
794 | } | 794 | } |
795 | 795 | ||
796 | void hostfs_truncate(struct inode *ino) | ||
797 | { | ||
798 | not_implemented(); | ||
799 | } | ||
800 | |||
801 | int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd) | 796 | int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd) |
802 | { | 797 | { |
803 | char *name; | 798 | char *name; |
@@ -894,7 +889,6 @@ static struct inode_operations hostfs_iops = { | |||
894 | .rmdir = hostfs_rmdir, | 889 | .rmdir = hostfs_rmdir, |
895 | .mknod = hostfs_mknod, | 890 | .mknod = hostfs_mknod, |
896 | .rename = hostfs_rename, | 891 | .rename = hostfs_rename, |
897 | .truncate = hostfs_truncate, | ||
898 | .permission = hostfs_permission, | 892 | .permission = hostfs_permission, |
899 | .setattr = hostfs_setattr, | 893 | .setattr = hostfs_setattr, |
900 | .getattr = hostfs_getattr, | 894 | .getattr = hostfs_getattr, |
@@ -910,7 +904,6 @@ static struct inode_operations hostfs_dir_iops = { | |||
910 | .rmdir = hostfs_rmdir, | 904 | .rmdir = hostfs_rmdir, |
911 | .mknod = hostfs_mknod, | 905 | .mknod = hostfs_mknod, |
912 | .rename = hostfs_rename, | 906 | .rename = hostfs_rename, |
913 | .truncate = hostfs_truncate, | ||
914 | .permission = hostfs_permission, | 907 | .permission = hostfs_permission, |
915 | .setattr = hostfs_setattr, | 908 | .setattr = hostfs_setattr, |
916 | .getattr = hostfs_getattr, | 909 | .getattr = hostfs_getattr, |
diff --git a/fs/inode.c b/fs/inode.c index f80a79ff156b..7d3316527767 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -475,7 +475,7 @@ static void prune_icache(int nr_to_scan) | |||
475 | * This function is passed the number of inodes to scan, and it returns the | 475 | * This function is passed the number of inodes to scan, and it returns the |
476 | * total number of remaining possibly-reclaimable inodes. | 476 | * total number of remaining possibly-reclaimable inodes. |
477 | */ | 477 | */ |
478 | static int shrink_icache_memory(int nr, unsigned int gfp_mask) | 478 | static int shrink_icache_memory(int nr, gfp_t gfp_mask) |
479 | { | 479 | { |
480 | if (nr) { | 480 | if (nr) { |
481 | /* | 481 | /* |
diff --git a/fs/inotify.c b/fs/inotify.c index a37e9fb1da58..9fbaebfdf40b 100644 --- a/fs/inotify.c +++ b/fs/inotify.c | |||
@@ -176,6 +176,7 @@ static inline void put_inotify_dev(struct inotify_device *dev) | |||
176 | if (atomic_dec_and_test(&dev->count)) { | 176 | if (atomic_dec_and_test(&dev->count)) { |
177 | atomic_dec(&dev->user->inotify_devs); | 177 | atomic_dec(&dev->user->inotify_devs); |
178 | free_uid(dev->user); | 178 | free_uid(dev->user); |
179 | idr_destroy(&dev->idr); | ||
179 | kfree(dev); | 180 | kfree(dev); |
180 | } | 181 | } |
181 | } | 182 | } |
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index 7ae2c4fe506b..e4b516ac4989 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c | |||
@@ -1606,7 +1606,7 @@ int journal_blocks_per_page(struct inode *inode) | |||
1606 | * Simple support for retrying memory allocations. Introduced to help to | 1606 | * Simple support for retrying memory allocations. Introduced to help to |
1607 | * debug different VM deadlock avoidance strategies. | 1607 | * debug different VM deadlock avoidance strategies. |
1608 | */ | 1608 | */ |
1609 | void * __jbd_kmalloc (const char *where, size_t size, int flags, int retry) | 1609 | void * __jbd_kmalloc (const char *where, size_t size, gfp_t flags, int retry) |
1610 | { | 1610 | { |
1611 | return kmalloc(size, flags | (retry ? __GFP_NOFAIL : 0)); | 1611 | return kmalloc(size, flags | (retry ? __GFP_NOFAIL : 0)); |
1612 | } | 1612 | } |
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index 49bbc2be3d72..13cb05bf6048 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c | |||
@@ -1621,7 +1621,7 @@ out: | |||
1621 | * while the data is part of a transaction. Yes? | 1621 | * while the data is part of a transaction. Yes? |
1622 | */ | 1622 | */ |
1623 | int journal_try_to_free_buffers(journal_t *journal, | 1623 | int journal_try_to_free_buffers(journal_t *journal, |
1624 | struct page *page, int unused_gfp_mask) | 1624 | struct page *page, gfp_t unused_gfp_mask) |
1625 | { | 1625 | { |
1626 | struct buffer_head *head; | 1626 | struct buffer_head *head; |
1627 | struct buffer_head *bh; | 1627 | struct buffer_head *bh; |
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c index 0ec62d5310db..9f942ca8e4e3 100644 --- a/fs/jfs/inode.c +++ b/fs/jfs/inode.c | |||
@@ -129,8 +129,7 @@ void jfs_delete_inode(struct inode *inode) | |||
129 | jfs_info("In jfs_delete_inode, inode = 0x%p", inode); | 129 | jfs_info("In jfs_delete_inode, inode = 0x%p", inode); |
130 | 130 | ||
131 | if (!is_bad_inode(inode) && | 131 | if (!is_bad_inode(inode) && |
132 | (JFS_IP(inode)->fileset == cpu_to_le32(FILESYSTEM_I))) { | 132 | (JFS_IP(inode)->fileset == FILESYSTEM_I)) { |
133 | |||
134 | truncate_inode_pages(&inode->i_data, 0); | 133 | truncate_inode_pages(&inode->i_data, 0); |
135 | 134 | ||
136 | if (test_cflag(COMMIT_Freewmap, inode)) | 135 | if (test_cflag(COMMIT_Freewmap, inode)) |
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index c739626f5bf1..eadf319bee22 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c | |||
@@ -3055,7 +3055,7 @@ static int cntlz(u32 value) | |||
3055 | * RETURN VALUES: | 3055 | * RETURN VALUES: |
3056 | * log2 number of blocks | 3056 | * log2 number of blocks |
3057 | */ | 3057 | */ |
3058 | int blkstol2(s64 nb) | 3058 | static int blkstol2(s64 nb) |
3059 | { | 3059 | { |
3060 | int l2nb; | 3060 | int l2nb; |
3061 | s64 mask; /* meant to be signed */ | 3061 | s64 mask; /* meant to be signed */ |
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index 13d7e3f1feb4..eeb37d70e650 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c | |||
@@ -198,7 +198,7 @@ static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags) | |||
198 | } | 198 | } |
199 | } | 199 | } |
200 | 200 | ||
201 | static inline struct metapage *alloc_metapage(unsigned int gfp_mask) | 201 | static inline struct metapage *alloc_metapage(gfp_t gfp_mask) |
202 | { | 202 | { |
203 | return mempool_alloc(metapage_mempool, gfp_mask); | 203 | return mempool_alloc(metapage_mempool, gfp_mask); |
204 | } | 204 | } |
@@ -534,7 +534,7 @@ add_failed: | |||
534 | return -EIO; | 534 | return -EIO; |
535 | } | 535 | } |
536 | 536 | ||
537 | static int metapage_releasepage(struct page *page, int gfp_mask) | 537 | static int metapage_releasepage(struct page *page, gfp_t gfp_mask) |
538 | { | 538 | { |
539 | struct metapage *mp; | 539 | struct metapage *mp; |
540 | int busy = 0; | 540 | int busy = 0; |
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index c7a92f9deb2b..9b71ed2674fe 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c | |||
@@ -725,6 +725,9 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp, | |||
725 | else | 725 | else |
726 | tlck->flag = tlckINODELOCK; | 726 | tlck->flag = tlckINODELOCK; |
727 | 727 | ||
728 | if (S_ISDIR(ip->i_mode)) | ||
729 | tlck->flag |= tlckDIRECTORY; | ||
730 | |||
728 | tlck->type = 0; | 731 | tlck->type = 0; |
729 | 732 | ||
730 | /* bind the tlock and the page */ | 733 | /* bind the tlock and the page */ |
@@ -1009,6 +1012,8 @@ struct tlock *txMaplock(tid_t tid, struct inode *ip, int type) | |||
1009 | 1012 | ||
1010 | /* bind the tlock and the object */ | 1013 | /* bind the tlock and the object */ |
1011 | tlck->flag = tlckINODELOCK; | 1014 | tlck->flag = tlckINODELOCK; |
1015 | if (S_ISDIR(ip->i_mode)) | ||
1016 | tlck->flag |= tlckDIRECTORY; | ||
1012 | tlck->ip = ip; | 1017 | tlck->ip = ip; |
1013 | tlck->mp = NULL; | 1018 | tlck->mp = NULL; |
1014 | 1019 | ||
@@ -1077,6 +1082,8 @@ struct linelock *txLinelock(struct linelock * tlock) | |||
1077 | linelock->flag = tlckLINELOCK; | 1082 | linelock->flag = tlckLINELOCK; |
1078 | linelock->maxcnt = TLOCKLONG; | 1083 | linelock->maxcnt = TLOCKLONG; |
1079 | linelock->index = 0; | 1084 | linelock->index = 0; |
1085 | if (tlck->flag & tlckDIRECTORY) | ||
1086 | linelock->flag |= tlckDIRECTORY; | ||
1080 | 1087 | ||
1081 | /* append linelock after tlock */ | 1088 | /* append linelock after tlock */ |
1082 | linelock->next = tlock->next; | 1089 | linelock->next = tlock->next; |
@@ -2070,8 +2077,8 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, | |||
2070 | * | 2077 | * |
2071 | * function: log from maplock of freed data extents; | 2078 | * function: log from maplock of freed data extents; |
2072 | */ | 2079 | */ |
2073 | void mapLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, | 2080 | static void mapLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, |
2074 | struct tlock * tlck) | 2081 | struct tlock * tlck) |
2075 | { | 2082 | { |
2076 | struct pxd_lock *pxdlock; | 2083 | struct pxd_lock *pxdlock; |
2077 | int i, nlock; | 2084 | int i, nlock; |
@@ -2209,7 +2216,7 @@ void txEA(tid_t tid, struct inode *ip, dxd_t * oldea, dxd_t * newea) | |||
2209 | * function: synchronously write pages locked by transaction | 2216 | * function: synchronously write pages locked by transaction |
2210 | * after txLog() but before txUpdateMap(); | 2217 | * after txLog() but before txUpdateMap(); |
2211 | */ | 2218 | */ |
2212 | void txForce(struct tblock * tblk) | 2219 | static void txForce(struct tblock * tblk) |
2213 | { | 2220 | { |
2214 | struct tlock *tlck; | 2221 | struct tlock *tlck; |
2215 | lid_t lid, next; | 2222 | lid_t lid, next; |
@@ -2358,7 +2365,7 @@ static void txUpdateMap(struct tblock * tblk) | |||
2358 | */ | 2365 | */ |
2359 | else { /* (maplock->flag & mlckFREE) */ | 2366 | else { /* (maplock->flag & mlckFREE) */ |
2360 | 2367 | ||
2361 | if (S_ISDIR(tlck->ip->i_mode)) | 2368 | if (tlck->flag & tlckDIRECTORY) |
2362 | txFreeMap(ipimap, maplock, | 2369 | txFreeMap(ipimap, maplock, |
2363 | tblk, COMMIT_PWMAP); | 2370 | tblk, COMMIT_PWMAP); |
2364 | else | 2371 | else |
diff --git a/fs/jfs/jfs_txnmgr.h b/fs/jfs/jfs_txnmgr.h index 59ad0f6b7231..0e4dc4514c47 100644 --- a/fs/jfs/jfs_txnmgr.h +++ b/fs/jfs/jfs_txnmgr.h | |||
@@ -122,6 +122,7 @@ extern struct tlock *TxLock; /* transaction lock table */ | |||
122 | #define tlckLOG 0x0800 | 122 | #define tlckLOG 0x0800 |
123 | /* updateMap state */ | 123 | /* updateMap state */ |
124 | #define tlckUPDATEMAP 0x0080 | 124 | #define tlckUPDATEMAP 0x0080 |
125 | #define tlckDIRECTORY 0x0040 | ||
125 | /* freeLock state */ | 126 | /* freeLock state */ |
126 | #define tlckFREELOCK 0x0008 | 127 | #define tlckFREELOCK 0x0008 |
127 | #define tlckWRITEPAGE 0x0004 | 128 | #define tlckWRITEPAGE 0x0004 |
diff --git a/fs/lockd/host.c b/fs/lockd/host.c index 82c77df81c5f..c4c8601096e0 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c | |||
@@ -173,11 +173,10 @@ nlm_bind_host(struct nlm_host *host) | |||
173 | 173 | ||
174 | /* If we've already created an RPC client, check whether | 174 | /* If we've already created an RPC client, check whether |
175 | * RPC rebind is required | 175 | * RPC rebind is required |
176 | * Note: why keep rebinding if we're on a tcp connection? | ||
177 | */ | 176 | */ |
178 | if ((clnt = host->h_rpcclnt) != NULL) { | 177 | if ((clnt = host->h_rpcclnt) != NULL) { |
179 | xprt = clnt->cl_xprt; | 178 | xprt = clnt->cl_xprt; |
180 | if (!xprt->stream && time_after_eq(jiffies, host->h_nextrebind)) { | 179 | if (time_after_eq(jiffies, host->h_nextrebind)) { |
181 | clnt->cl_port = 0; | 180 | clnt->cl_port = 0; |
182 | host->h_nextrebind = jiffies + NLM_HOST_REBIND; | 181 | host->h_nextrebind = jiffies + NLM_HOST_REBIND; |
183 | dprintk("lockd: next rebind in %ld jiffies\n", | 182 | dprintk("lockd: next rebind in %ld jiffies\n", |
@@ -189,7 +188,6 @@ nlm_bind_host(struct nlm_host *host) | |||
189 | goto forgetit; | 188 | goto forgetit; |
190 | 189 | ||
191 | xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout); | 190 | xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout); |
192 | xprt->nocong = 1; /* No congestion control for NLM */ | ||
193 | xprt->resvport = 1; /* NLM requires a reserved port */ | 191 | xprt->resvport = 1; /* NLM requires a reserved port */ |
194 | 192 | ||
195 | /* Existing NLM servers accept AUTH_UNIX only */ | 193 | /* Existing NLM servers accept AUTH_UNIX only */ |
diff --git a/fs/locks.c b/fs/locks.c index f7daa5f48949..a1e8b2248014 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -316,21 +316,22 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl, | |||
316 | /* POSIX-1996 leaves the case l->l_len < 0 undefined; | 316 | /* POSIX-1996 leaves the case l->l_len < 0 undefined; |
317 | POSIX-2001 defines it. */ | 317 | POSIX-2001 defines it. */ |
318 | start += l->l_start; | 318 | start += l->l_start; |
319 | end = start + l->l_len - 1; | 319 | if (start < 0) |
320 | if (l->l_len < 0) { | 320 | return -EINVAL; |
321 | fl->fl_end = OFFSET_MAX; | ||
322 | if (l->l_len > 0) { | ||
323 | end = start + l->l_len - 1; | ||
324 | fl->fl_end = end; | ||
325 | } else if (l->l_len < 0) { | ||
321 | end = start - 1; | 326 | end = start - 1; |
327 | fl->fl_end = end; | ||
322 | start += l->l_len; | 328 | start += l->l_len; |
329 | if (start < 0) | ||
330 | return -EINVAL; | ||
323 | } | 331 | } |
324 | |||
325 | if (start < 0) | ||
326 | return -EINVAL; | ||
327 | if (l->l_len > 0 && end < 0) | ||
328 | return -EOVERFLOW; | ||
329 | |||
330 | fl->fl_start = start; /* we record the absolute position */ | 332 | fl->fl_start = start; /* we record the absolute position */ |
331 | fl->fl_end = end; | 333 | if (fl->fl_end < fl->fl_start) |
332 | if (l->l_len == 0) | 334 | return -EOVERFLOW; |
333 | fl->fl_end = OFFSET_MAX; | ||
334 | 335 | ||
335 | fl->fl_owner = current->files; | 336 | fl->fl_owner = current->files; |
336 | fl->fl_pid = current->tgid; | 337 | fl->fl_pid = current->tgid; |
@@ -362,14 +363,21 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl, | |||
362 | return -EINVAL; | 363 | return -EINVAL; |
363 | } | 364 | } |
364 | 365 | ||
365 | if (((start += l->l_start) < 0) || (l->l_len < 0)) | 366 | start += l->l_start; |
367 | if (start < 0) | ||
366 | return -EINVAL; | 368 | return -EINVAL; |
367 | fl->fl_end = start + l->l_len - 1; | 369 | fl->fl_end = OFFSET_MAX; |
368 | if (l->l_len > 0 && fl->fl_end < 0) | 370 | if (l->l_len > 0) { |
369 | return -EOVERFLOW; | 371 | fl->fl_end = start + l->l_len - 1; |
372 | } else if (l->l_len < 0) { | ||
373 | fl->fl_end = start - 1; | ||
374 | start += l->l_len; | ||
375 | if (start < 0) | ||
376 | return -EINVAL; | ||
377 | } | ||
370 | fl->fl_start = start; /* we record the absolute position */ | 378 | fl->fl_start = start; /* we record the absolute position */ |
371 | if (l->l_len == 0) | 379 | if (fl->fl_end < fl->fl_start) |
372 | fl->fl_end = OFFSET_MAX; | 380 | return -EOVERFLOW; |
373 | 381 | ||
374 | fl->fl_owner = current->files; | 382 | fl->fl_owner = current->files; |
375 | fl->fl_pid = current->tgid; | 383 | fl->fl_pid = current->tgid; |
@@ -829,12 +837,16 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request) | |||
829 | /* Detect adjacent or overlapping regions (if same lock type) | 837 | /* Detect adjacent or overlapping regions (if same lock type) |
830 | */ | 838 | */ |
831 | if (request->fl_type == fl->fl_type) { | 839 | if (request->fl_type == fl->fl_type) { |
840 | /* In all comparisons of start vs end, use | ||
841 | * "start - 1" rather than "end + 1". If end | ||
842 | * is OFFSET_MAX, end + 1 will become negative. | ||
843 | */ | ||
832 | if (fl->fl_end < request->fl_start - 1) | 844 | if (fl->fl_end < request->fl_start - 1) |
833 | goto next_lock; | 845 | goto next_lock; |
834 | /* If the next lock in the list has entirely bigger | 846 | /* If the next lock in the list has entirely bigger |
835 | * addresses than the new one, insert the lock here. | 847 | * addresses than the new one, insert the lock here. |
836 | */ | 848 | */ |
837 | if (fl->fl_start > request->fl_end + 1) | 849 | if (fl->fl_start - 1 > request->fl_end) |
838 | break; | 850 | break; |
839 | 851 | ||
840 | /* If we come here, the new and old lock are of the | 852 | /* If we come here, the new and old lock are of the |
diff --git a/fs/mbcache.c b/fs/mbcache.c index b002a088857d..298997f17475 100644 --- a/fs/mbcache.c +++ b/fs/mbcache.c | |||
@@ -116,7 +116,7 @@ mb_cache_indexes(struct mb_cache *cache) | |||
116 | * What the mbcache registers as to get shrunk dynamically. | 116 | * What the mbcache registers as to get shrunk dynamically. |
117 | */ | 117 | */ |
118 | 118 | ||
119 | static int mb_cache_shrink_fn(int nr_to_scan, unsigned int gfp_mask); | 119 | static int mb_cache_shrink_fn(int nr_to_scan, gfp_t gfp_mask); |
120 | 120 | ||
121 | 121 | ||
122 | static inline int | 122 | static inline int |
@@ -140,7 +140,7 @@ __mb_cache_entry_unhash(struct mb_cache_entry *ce) | |||
140 | 140 | ||
141 | 141 | ||
142 | static inline void | 142 | static inline void |
143 | __mb_cache_entry_forget(struct mb_cache_entry *ce, int gfp_mask) | 143 | __mb_cache_entry_forget(struct mb_cache_entry *ce, gfp_t gfp_mask) |
144 | { | 144 | { |
145 | struct mb_cache *cache = ce->e_cache; | 145 | struct mb_cache *cache = ce->e_cache; |
146 | 146 | ||
@@ -193,7 +193,7 @@ forget: | |||
193 | * Returns the number of objects which are present in the cache. | 193 | * Returns the number of objects which are present in the cache. |
194 | */ | 194 | */ |
195 | static int | 195 | static int |
196 | mb_cache_shrink_fn(int nr_to_scan, unsigned int gfp_mask) | 196 | mb_cache_shrink_fn(int nr_to_scan, gfp_t gfp_mask) |
197 | { | 197 | { |
198 | LIST_HEAD(free_list); | 198 | LIST_HEAD(free_list); |
199 | struct list_head *l, *ltmp; | 199 | struct list_head *l, *ltmp; |
diff --git a/fs/mpage.c b/fs/mpage.c index bb9aebe93862..c5adcdddf3cc 100644 --- a/fs/mpage.c +++ b/fs/mpage.c | |||
@@ -102,7 +102,7 @@ static struct bio *mpage_bio_submit(int rw, struct bio *bio) | |||
102 | static struct bio * | 102 | static struct bio * |
103 | mpage_alloc(struct block_device *bdev, | 103 | mpage_alloc(struct block_device *bdev, |
104 | sector_t first_sector, int nr_vecs, | 104 | sector_t first_sector, int nr_vecs, |
105 | unsigned int __nocast gfp_flags) | 105 | gfp_t gfp_flags) |
106 | { | 106 | { |
107 | struct bio *bio; | 107 | struct bio *bio; |
108 | 108 | ||
diff --git a/fs/namei.c b/fs/namei.c index 043d587216b5..aaaa81036234 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/syscalls.h> | 28 | #include <linux/syscalls.h> |
29 | #include <linux/mount.h> | 29 | #include <linux/mount.h> |
30 | #include <linux/audit.h> | 30 | #include <linux/audit.h> |
31 | #include <linux/file.h> | ||
31 | #include <asm/namei.h> | 32 | #include <asm/namei.h> |
32 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
33 | 34 | ||
@@ -317,6 +318,18 @@ void path_release_on_umount(struct nameidata *nd) | |||
317 | mntput_no_expire(nd->mnt); | 318 | mntput_no_expire(nd->mnt); |
318 | } | 319 | } |
319 | 320 | ||
321 | /** | ||
322 | * release_open_intent - free up open intent resources | ||
323 | * @nd: pointer to nameidata | ||
324 | */ | ||
325 | void release_open_intent(struct nameidata *nd) | ||
326 | { | ||
327 | if (nd->intent.open.file->f_dentry == NULL) | ||
328 | put_filp(nd->intent.open.file); | ||
329 | else | ||
330 | fput(nd->intent.open.file); | ||
331 | } | ||
332 | |||
320 | /* | 333 | /* |
321 | * Internal lookup() using the new generic dcache. | 334 | * Internal lookup() using the new generic dcache. |
322 | * SMP-safe | 335 | * SMP-safe |
@@ -750,6 +763,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) | |||
750 | struct qstr this; | 763 | struct qstr this; |
751 | unsigned int c; | 764 | unsigned int c; |
752 | 765 | ||
766 | nd->flags |= LOOKUP_CONTINUE; | ||
753 | err = exec_permission_lite(inode, nd); | 767 | err = exec_permission_lite(inode, nd); |
754 | if (err == -EAGAIN) { | 768 | if (err == -EAGAIN) { |
755 | err = permission(inode, MAY_EXEC, nd); | 769 | err = permission(inode, MAY_EXEC, nd); |
@@ -802,7 +816,6 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) | |||
802 | if (err < 0) | 816 | if (err < 0) |
803 | break; | 817 | break; |
804 | } | 818 | } |
805 | nd->flags |= LOOKUP_CONTINUE; | ||
806 | /* This does the actual lookups.. */ | 819 | /* This does the actual lookups.. */ |
807 | err = do_lookup(nd, &this, &next); | 820 | err = do_lookup(nd, &this, &next); |
808 | if (err) | 821 | if (err) |
@@ -1052,6 +1065,70 @@ out: | |||
1052 | return retval; | 1065 | return retval; |
1053 | } | 1066 | } |
1054 | 1067 | ||
1068 | static int __path_lookup_intent_open(const char *name, unsigned int lookup_flags, | ||
1069 | struct nameidata *nd, int open_flags, int create_mode) | ||
1070 | { | ||
1071 | struct file *filp = get_empty_filp(); | ||
1072 | int err; | ||
1073 | |||
1074 | if (filp == NULL) | ||
1075 | return -ENFILE; | ||
1076 | nd->intent.open.file = filp; | ||
1077 | nd->intent.open.flags = open_flags; | ||
1078 | nd->intent.open.create_mode = create_mode; | ||
1079 | err = path_lookup(name, lookup_flags|LOOKUP_OPEN, nd); | ||
1080 | if (IS_ERR(nd->intent.open.file)) { | ||
1081 | if (err == 0) { | ||
1082 | err = PTR_ERR(nd->intent.open.file); | ||
1083 | path_release(nd); | ||
1084 | } | ||
1085 | } else if (err != 0) | ||
1086 | release_open_intent(nd); | ||
1087 | return err; | ||
1088 | } | ||
1089 | |||
1090 | /** | ||
1091 | * path_lookup_open - lookup a file path with open intent | ||
1092 | * @name: pointer to file name | ||
1093 | * @lookup_flags: lookup intent flags | ||
1094 | * @nd: pointer to nameidata | ||
1095 | * @open_flags: open intent flags | ||
1096 | */ | ||
1097 | int path_lookup_open(const char *name, unsigned int lookup_flags, | ||
1098 | struct nameidata *nd, int open_flags) | ||
1099 | { | ||
1100 | return __path_lookup_intent_open(name, lookup_flags, nd, | ||
1101 | open_flags, 0); | ||
1102 | } | ||
1103 | |||
1104 | /** | ||
1105 | * path_lookup_create - lookup a file path with open + create intent | ||
1106 | * @name: pointer to file name | ||
1107 | * @lookup_flags: lookup intent flags | ||
1108 | * @nd: pointer to nameidata | ||
1109 | * @open_flags: open intent flags | ||
1110 | * @create_mode: create intent flags | ||
1111 | */ | ||
1112 | int path_lookup_create(const char *name, unsigned int lookup_flags, | ||
1113 | struct nameidata *nd, int open_flags, int create_mode) | ||
1114 | { | ||
1115 | return __path_lookup_intent_open(name, lookup_flags|LOOKUP_CREATE, nd, | ||
1116 | open_flags, create_mode); | ||
1117 | } | ||
1118 | |||
1119 | int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags, | ||
1120 | struct nameidata *nd, int open_flags) | ||
1121 | { | ||
1122 | char *tmp = getname(name); | ||
1123 | int err = PTR_ERR(tmp); | ||
1124 | |||
1125 | if (!IS_ERR(tmp)) { | ||
1126 | err = __path_lookup_intent_open(tmp, lookup_flags, nd, open_flags, 0); | ||
1127 | putname(tmp); | ||
1128 | } | ||
1129 | return err; | ||
1130 | } | ||
1131 | |||
1055 | /* | 1132 | /* |
1056 | * Restricted form of lookup. Doesn't follow links, single-component only, | 1133 | * Restricted form of lookup. Doesn't follow links, single-component only, |
1057 | * needs parent already locked. Doesn't follow mounts. | 1134 | * needs parent already locked. Doesn't follow mounts. |
@@ -1416,27 +1493,27 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
1416 | */ | 1493 | */ |
1417 | int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) | 1494 | int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) |
1418 | { | 1495 | { |
1419 | int acc_mode, error = 0; | 1496 | int acc_mode, error; |
1420 | struct path path; | 1497 | struct path path; |
1421 | struct dentry *dir; | 1498 | struct dentry *dir; |
1422 | int count = 0; | 1499 | int count = 0; |
1423 | 1500 | ||
1424 | acc_mode = ACC_MODE(flag); | 1501 | acc_mode = ACC_MODE(flag); |
1425 | 1502 | ||
1503 | /* O_TRUNC implies we need access checks for write permissions */ | ||
1504 | if (flag & O_TRUNC) | ||
1505 | acc_mode |= MAY_WRITE; | ||
1506 | |||
1426 | /* Allow the LSM permission hook to distinguish append | 1507 | /* Allow the LSM permission hook to distinguish append |
1427 | access from general write access. */ | 1508 | access from general write access. */ |
1428 | if (flag & O_APPEND) | 1509 | if (flag & O_APPEND) |
1429 | acc_mode |= MAY_APPEND; | 1510 | acc_mode |= MAY_APPEND; |
1430 | 1511 | ||
1431 | /* Fill in the open() intent data */ | ||
1432 | nd->intent.open.flags = flag; | ||
1433 | nd->intent.open.create_mode = mode; | ||
1434 | |||
1435 | /* | 1512 | /* |
1436 | * The simplest case - just a plain lookup. | 1513 | * The simplest case - just a plain lookup. |
1437 | */ | 1514 | */ |
1438 | if (!(flag & O_CREAT)) { | 1515 | if (!(flag & O_CREAT)) { |
1439 | error = path_lookup(pathname, lookup_flags(flag)|LOOKUP_OPEN, nd); | 1516 | error = path_lookup_open(pathname, lookup_flags(flag), nd, flag); |
1440 | if (error) | 1517 | if (error) |
1441 | return error; | 1518 | return error; |
1442 | goto ok; | 1519 | goto ok; |
@@ -1445,7 +1522,7 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) | |||
1445 | /* | 1522 | /* |
1446 | * Create - we need to know the parent. | 1523 | * Create - we need to know the parent. |
1447 | */ | 1524 | */ |
1448 | error = path_lookup(pathname, LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE, nd); | 1525 | error = path_lookup_create(pathname, LOOKUP_PARENT, nd, flag, mode); |
1449 | if (error) | 1526 | if (error) |
1450 | return error; | 1527 | return error; |
1451 | 1528 | ||
@@ -1520,6 +1597,8 @@ ok: | |||
1520 | exit_dput: | 1597 | exit_dput: |
1521 | dput_path(&path, nd); | 1598 | dput_path(&path, nd); |
1522 | exit: | 1599 | exit: |
1600 | if (!IS_ERR(nd->intent.open.file)) | ||
1601 | release_open_intent(nd); | ||
1523 | path_release(nd); | 1602 | path_release(nd); |
1524 | return error; | 1603 | return error; |
1525 | 1604 | ||
@@ -1551,19 +1630,19 @@ do_link: | |||
1551 | if (nd->last_type != LAST_NORM) | 1630 | if (nd->last_type != LAST_NORM) |
1552 | goto exit; | 1631 | goto exit; |
1553 | if (nd->last.name[nd->last.len]) { | 1632 | if (nd->last.name[nd->last.len]) { |
1554 | putname(nd->last.name); | 1633 | __putname(nd->last.name); |
1555 | goto exit; | 1634 | goto exit; |
1556 | } | 1635 | } |
1557 | error = -ELOOP; | 1636 | error = -ELOOP; |
1558 | if (count++==32) { | 1637 | if (count++==32) { |
1559 | putname(nd->last.name); | 1638 | __putname(nd->last.name); |
1560 | goto exit; | 1639 | goto exit; |
1561 | } | 1640 | } |
1562 | dir = nd->dentry; | 1641 | dir = nd->dentry; |
1563 | down(&dir->d_inode->i_sem); | 1642 | down(&dir->d_inode->i_sem); |
1564 | path.dentry = __lookup_hash(&nd->last, nd->dentry, nd); | 1643 | path.dentry = __lookup_hash(&nd->last, nd->dentry, nd); |
1565 | path.mnt = nd->mnt; | 1644 | path.mnt = nd->mnt; |
1566 | putname(nd->last.name); | 1645 | __putname(nd->last.name); |
1567 | goto do_last; | 1646 | goto do_last; |
1568 | } | 1647 | } |
1569 | 1648 | ||
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index d7f7eb669d03..44135af9894c 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
@@ -85,6 +85,10 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct | |||
85 | struct nfs_delegation *delegation; | 85 | struct nfs_delegation *delegation; |
86 | int status = 0; | 86 | int status = 0; |
87 | 87 | ||
88 | /* Ensure we first revalidate the attributes and page cache! */ | ||
89 | if ((nfsi->cache_validity & (NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_ATTR))) | ||
90 | __nfs_revalidate_inode(NFS_SERVER(inode), inode); | ||
91 | |||
88 | delegation = nfs_alloc_delegation(); | 92 | delegation = nfs_alloc_delegation(); |
89 | if (delegation == NULL) | 93 | if (delegation == NULL) |
90 | return -ENOMEM; | 94 | return -ENOMEM; |
@@ -138,7 +142,7 @@ static void nfs_msync_inode(struct inode *inode) | |||
138 | /* | 142 | /* |
139 | * Basic procedure for returning a delegation to the server | 143 | * Basic procedure for returning a delegation to the server |
140 | */ | 144 | */ |
141 | int nfs_inode_return_delegation(struct inode *inode) | 145 | int __nfs_inode_return_delegation(struct inode *inode) |
142 | { | 146 | { |
143 | struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state; | 147 | struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state; |
144 | struct nfs_inode *nfsi = NFS_I(inode); | 148 | struct nfs_inode *nfsi = NFS_I(inode); |
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h index 3f6c45a29d6a..8017846b561f 100644 --- a/fs/nfs/delegation.h +++ b/fs/nfs/delegation.h | |||
@@ -25,7 +25,7 @@ struct nfs_delegation { | |||
25 | 25 | ||
26 | int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); | 26 | int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); |
27 | void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); | 27 | void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); |
28 | int nfs_inode_return_delegation(struct inode *inode); | 28 | int __nfs_inode_return_delegation(struct inode *inode); |
29 | int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid); | 29 | int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid); |
30 | 30 | ||
31 | struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const struct nfs_fh *fhandle); | 31 | struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const struct nfs_fh *fhandle); |
@@ -47,11 +47,25 @@ static inline int nfs_have_delegation(struct inode *inode, int flags) | |||
47 | return 1; | 47 | return 1; |
48 | return 0; | 48 | return 0; |
49 | } | 49 | } |
50 | |||
51 | static inline int nfs_inode_return_delegation(struct inode *inode) | ||
52 | { | ||
53 | int err = 0; | ||
54 | |||
55 | if (NFS_I(inode)->delegation != NULL) | ||
56 | err = __nfs_inode_return_delegation(inode); | ||
57 | return err; | ||
58 | } | ||
50 | #else | 59 | #else |
51 | static inline int nfs_have_delegation(struct inode *inode, int flags) | 60 | static inline int nfs_have_delegation(struct inode *inode, int flags) |
52 | { | 61 | { |
53 | return 0; | 62 | return 0; |
54 | } | 63 | } |
64 | |||
65 | static inline int nfs_inode_return_delegation(struct inode *inode) | ||
66 | { | ||
67 | return 0; | ||
68 | } | ||
55 | #endif | 69 | #endif |
56 | 70 | ||
57 | #endif | 71 | #endif |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 2df639f143e8..8272ed3fc707 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -532,6 +532,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
532 | my_entry.eof = 0; | 532 | my_entry.eof = 0; |
533 | my_entry.fh = &fh; | 533 | my_entry.fh = &fh; |
534 | my_entry.fattr = &fattr; | 534 | my_entry.fattr = &fattr; |
535 | nfs_fattr_init(&fattr); | ||
535 | desc->entry = &my_entry; | 536 | desc->entry = &my_entry; |
536 | 537 | ||
537 | while(!desc->entry->eof) { | 538 | while(!desc->entry->eof) { |
@@ -565,8 +566,6 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
565 | } | 566 | } |
566 | } | 567 | } |
567 | unlock_kernel(); | 568 | unlock_kernel(); |
568 | if (desc->error < 0) | ||
569 | return desc->error; | ||
570 | if (res < 0) | 569 | if (res < 0) |
571 | return res; | 570 | return res; |
572 | return 0; | 571 | return 0; |
@@ -803,6 +802,7 @@ static int nfs_dentry_delete(struct dentry *dentry) | |||
803 | */ | 802 | */ |
804 | static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode) | 803 | static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode) |
805 | { | 804 | { |
805 | nfs_inode_return_delegation(inode); | ||
806 | if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { | 806 | if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { |
807 | lock_kernel(); | 807 | lock_kernel(); |
808 | inode->i_nlink--; | 808 | inode->i_nlink--; |
@@ -853,12 +853,6 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru | |||
853 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; | 853 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; |
854 | 854 | ||
855 | lock_kernel(); | 855 | lock_kernel(); |
856 | /* Revalidate parent directory attribute cache */ | ||
857 | error = nfs_revalidate_inode(NFS_SERVER(dir), dir); | ||
858 | if (error < 0) { | ||
859 | res = ERR_PTR(error); | ||
860 | goto out_unlock; | ||
861 | } | ||
862 | 856 | ||
863 | /* If we're doing an exclusive create, optimize away the lookup */ | 857 | /* If we're doing an exclusive create, optimize away the lookup */ |
864 | if (nfs_is_exclusive_create(dir, nd)) | 858 | if (nfs_is_exclusive_create(dir, nd)) |
@@ -916,7 +910,6 @@ static int is_atomic_open(struct inode *dir, struct nameidata *nd) | |||
916 | static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 910 | static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) |
917 | { | 911 | { |
918 | struct dentry *res = NULL; | 912 | struct dentry *res = NULL; |
919 | struct inode *inode = NULL; | ||
920 | int error; | 913 | int error; |
921 | 914 | ||
922 | /* Check that we are indeed trying to open this file */ | 915 | /* Check that we are indeed trying to open this file */ |
@@ -930,8 +923,10 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
930 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; | 923 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; |
931 | 924 | ||
932 | /* Let vfs_create() deal with O_EXCL */ | 925 | /* Let vfs_create() deal with O_EXCL */ |
933 | if (nd->intent.open.flags & O_EXCL) | 926 | if (nd->intent.open.flags & O_EXCL) { |
934 | goto no_entry; | 927 | d_add(dentry, NULL); |
928 | goto out; | ||
929 | } | ||
935 | 930 | ||
936 | /* Open the file on the server */ | 931 | /* Open the file on the server */ |
937 | lock_kernel(); | 932 | lock_kernel(); |
@@ -945,32 +940,30 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
945 | 940 | ||
946 | if (nd->intent.open.flags & O_CREAT) { | 941 | if (nd->intent.open.flags & O_CREAT) { |
947 | nfs_begin_data_update(dir); | 942 | nfs_begin_data_update(dir); |
948 | inode = nfs4_atomic_open(dir, dentry, nd); | 943 | res = nfs4_atomic_open(dir, dentry, nd); |
949 | nfs_end_data_update(dir); | 944 | nfs_end_data_update(dir); |
950 | } else | 945 | } else |
951 | inode = nfs4_atomic_open(dir, dentry, nd); | 946 | res = nfs4_atomic_open(dir, dentry, nd); |
952 | unlock_kernel(); | 947 | unlock_kernel(); |
953 | if (IS_ERR(inode)) { | 948 | if (IS_ERR(res)) { |
954 | error = PTR_ERR(inode); | 949 | error = PTR_ERR(res); |
955 | switch (error) { | 950 | switch (error) { |
956 | /* Make a negative dentry */ | 951 | /* Make a negative dentry */ |
957 | case -ENOENT: | 952 | case -ENOENT: |
958 | inode = NULL; | 953 | res = NULL; |
959 | break; | 954 | goto out; |
960 | /* This turned out not to be a regular file */ | 955 | /* This turned out not to be a regular file */ |
956 | case -EISDIR: | ||
957 | case -ENOTDIR: | ||
958 | goto no_open; | ||
961 | case -ELOOP: | 959 | case -ELOOP: |
962 | if (!(nd->intent.open.flags & O_NOFOLLOW)) | 960 | if (!(nd->intent.open.flags & O_NOFOLLOW)) |
963 | goto no_open; | 961 | goto no_open; |
964 | /* case -EISDIR: */ | ||
965 | /* case -EINVAL: */ | 962 | /* case -EINVAL: */ |
966 | default: | 963 | default: |
967 | res = ERR_PTR(error); | ||
968 | goto out; | 964 | goto out; |
969 | } | 965 | } |
970 | } | 966 | } else if (res != NULL) |
971 | no_entry: | ||
972 | res = d_add_unique(dentry, inode); | ||
973 | if (res != NULL) | ||
974 | dentry = res; | 967 | dentry = res; |
975 | nfs_renew_times(dentry); | 968 | nfs_renew_times(dentry); |
976 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 969 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
@@ -1014,7 +1007,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1014 | */ | 1007 | */ |
1015 | lock_kernel(); | 1008 | lock_kernel(); |
1016 | verifier = nfs_save_change_attribute(dir); | 1009 | verifier = nfs_save_change_attribute(dir); |
1017 | ret = nfs4_open_revalidate(dir, dentry, openflags); | 1010 | ret = nfs4_open_revalidate(dir, dentry, openflags, nd); |
1018 | if (!ret) | 1011 | if (!ret) |
1019 | nfs_set_verifier(dentry, verifier); | 1012 | nfs_set_verifier(dentry, verifier); |
1020 | unlock_kernel(); | 1013 | unlock_kernel(); |
@@ -1137,7 +1130,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
1137 | 1130 | ||
1138 | lock_kernel(); | 1131 | lock_kernel(); |
1139 | nfs_begin_data_update(dir); | 1132 | nfs_begin_data_update(dir); |
1140 | error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags); | 1133 | error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, nd); |
1141 | nfs_end_data_update(dir); | 1134 | nfs_end_data_update(dir); |
1142 | if (error != 0) | 1135 | if (error != 0) |
1143 | goto out_err; | 1136 | goto out_err; |
@@ -1332,6 +1325,7 @@ static int nfs_safe_remove(struct dentry *dentry) | |||
1332 | 1325 | ||
1333 | nfs_begin_data_update(dir); | 1326 | nfs_begin_data_update(dir); |
1334 | if (inode != NULL) { | 1327 | if (inode != NULL) { |
1328 | nfs_inode_return_delegation(inode); | ||
1335 | nfs_begin_data_update(inode); | 1329 | nfs_begin_data_update(inode); |
1336 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); | 1330 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); |
1337 | /* The VFS may want to delete this inode */ | 1331 | /* The VFS may want to delete this inode */ |
@@ -1438,17 +1432,14 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) | |||
1438 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, | 1432 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, |
1439 | dentry->d_parent->d_name.name, dentry->d_name.name); | 1433 | dentry->d_parent->d_name.name, dentry->d_name.name); |
1440 | 1434 | ||
1441 | /* | ||
1442 | * Drop the dentry in advance to force a new lookup. | ||
1443 | * Since nfs_proc_link doesn't return a file handle, | ||
1444 | * we can't use the existing dentry. | ||
1445 | */ | ||
1446 | lock_kernel(); | 1435 | lock_kernel(); |
1447 | d_drop(dentry); | ||
1448 | |||
1449 | nfs_begin_data_update(dir); | 1436 | nfs_begin_data_update(dir); |
1450 | nfs_begin_data_update(inode); | 1437 | nfs_begin_data_update(inode); |
1451 | error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name); | 1438 | error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name); |
1439 | if (error == 0) { | ||
1440 | atomic_inc(&inode->i_count); | ||
1441 | d_instantiate(dentry, inode); | ||
1442 | } | ||
1452 | nfs_end_data_update(inode); | 1443 | nfs_end_data_update(inode); |
1453 | nfs_end_data_update(dir); | 1444 | nfs_end_data_update(dir); |
1454 | unlock_kernel(); | 1445 | unlock_kernel(); |
@@ -1512,9 +1503,11 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1512 | */ | 1503 | */ |
1513 | if (!new_inode) | 1504 | if (!new_inode) |
1514 | goto go_ahead; | 1505 | goto go_ahead; |
1515 | if (S_ISDIR(new_inode->i_mode)) | 1506 | if (S_ISDIR(new_inode->i_mode)) { |
1516 | goto out; | 1507 | error = -EISDIR; |
1517 | else if (atomic_read(&new_dentry->d_count) > 2) { | 1508 | if (!S_ISDIR(old_inode->i_mode)) |
1509 | goto out; | ||
1510 | } else if (atomic_read(&new_dentry->d_count) > 2) { | ||
1518 | int err; | 1511 | int err; |
1519 | /* copy the target dentry's name */ | 1512 | /* copy the target dentry's name */ |
1520 | dentry = d_alloc(new_dentry->d_parent, | 1513 | dentry = d_alloc(new_dentry->d_parent, |
@@ -1539,7 +1532,8 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1539 | #endif | 1532 | #endif |
1540 | goto out; | 1533 | goto out; |
1541 | } | 1534 | } |
1542 | } | 1535 | } else |
1536 | new_inode->i_nlink--; | ||
1543 | 1537 | ||
1544 | go_ahead: | 1538 | go_ahead: |
1545 | /* | 1539 | /* |
@@ -1549,6 +1543,7 @@ go_ahead: | |||
1549 | nfs_wb_all(old_inode); | 1543 | nfs_wb_all(old_inode); |
1550 | shrink_dcache_parent(old_dentry); | 1544 | shrink_dcache_parent(old_dentry); |
1551 | } | 1545 | } |
1546 | nfs_inode_return_delegation(old_inode); | ||
1552 | 1547 | ||
1553 | if (new_inode) | 1548 | if (new_inode) |
1554 | d_delete(new_dentry); | 1549 | d_delete(new_dentry); |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index f6b9eda925c5..57d3e77d97ee 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -137,7 +137,8 @@ static int nfs_revalidate_file(struct inode *inode, struct file *filp) | |||
137 | struct nfs_inode *nfsi = NFS_I(inode); | 137 | struct nfs_inode *nfsi = NFS_I(inode); |
138 | int retval = 0; | 138 | int retval = 0; |
139 | 139 | ||
140 | if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) || nfs_attribute_timeout(inode)) | 140 | if ((nfsi->cache_validity & (NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_ATTR)) |
141 | || nfs_attribute_timeout(inode)) | ||
141 | retval = __nfs_revalidate_inode(NFS_SERVER(inode), inode); | 142 | retval = __nfs_revalidate_inode(NFS_SERVER(inode), inode); |
142 | nfs_revalidate_mapping(inode, filp->f_mapping); | 143 | nfs_revalidate_mapping(inode, filp->f_mapping); |
143 | return 0; | 144 | return 0; |
@@ -204,8 +205,8 @@ nfs_file_flush(struct file *file) | |||
204 | if (!status) { | 205 | if (!status) { |
205 | status = ctx->error; | 206 | status = ctx->error; |
206 | ctx->error = 0; | 207 | ctx->error = 0; |
207 | if (!status && !nfs_have_delegation(inode, FMODE_READ)) | 208 | if (!status) |
208 | __nfs_revalidate_inode(NFS_SERVER(inode), inode); | 209 | nfs_revalidate_inode(NFS_SERVER(inode), inode); |
209 | } | 210 | } |
210 | unlock_kernel(); | 211 | unlock_kernel(); |
211 | return status; | 212 | return status; |
@@ -375,22 +376,31 @@ out_swapfile: | |||
375 | 376 | ||
376 | static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) | 377 | static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) |
377 | { | 378 | { |
379 | struct file_lock *cfl; | ||
378 | struct inode *inode = filp->f_mapping->host; | 380 | struct inode *inode = filp->f_mapping->host; |
379 | int status = 0; | 381 | int status = 0; |
380 | 382 | ||
381 | lock_kernel(); | 383 | lock_kernel(); |
382 | /* Use local locking if mounted with "-onolock" */ | 384 | /* Try local locking first */ |
383 | if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)) | 385 | cfl = posix_test_lock(filp, fl); |
384 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | 386 | if (cfl != NULL) { |
385 | else { | 387 | locks_copy_lock(fl, cfl); |
386 | struct file_lock *cfl = posix_test_lock(filp, fl); | 388 | goto out; |
387 | |||
388 | fl->fl_type = F_UNLCK; | ||
389 | if (cfl != NULL) | ||
390 | memcpy(fl, cfl, sizeof(*fl)); | ||
391 | } | 389 | } |
390 | |||
391 | if (nfs_have_delegation(inode, FMODE_READ)) | ||
392 | goto out_noconflict; | ||
393 | |||
394 | if (NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM) | ||
395 | goto out_noconflict; | ||
396 | |||
397 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | ||
398 | out: | ||
392 | unlock_kernel(); | 399 | unlock_kernel(); |
393 | return status; | 400 | return status; |
401 | out_noconflict: | ||
402 | fl->fl_type = F_UNLCK; | ||
403 | goto out; | ||
394 | } | 404 | } |
395 | 405 | ||
396 | static int do_vfs_lock(struct file *file, struct file_lock *fl) | 406 | static int do_vfs_lock(struct file *file, struct file_lock *fl) |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 6922469d6fc5..f2781ca42761 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -358,6 +358,35 @@ out_no_root: | |||
358 | return no_root_error; | 358 | return no_root_error; |
359 | } | 359 | } |
360 | 360 | ||
361 | static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, unsigned int timeo, unsigned int retrans) | ||
362 | { | ||
363 | to->to_initval = timeo * HZ / 10; | ||
364 | to->to_retries = retrans; | ||
365 | if (!to->to_retries) | ||
366 | to->to_retries = 2; | ||
367 | |||
368 | switch (proto) { | ||
369 | case IPPROTO_TCP: | ||
370 | if (!to->to_initval) | ||
371 | to->to_initval = 60 * HZ; | ||
372 | if (to->to_initval > NFS_MAX_TCP_TIMEOUT) | ||
373 | to->to_initval = NFS_MAX_TCP_TIMEOUT; | ||
374 | to->to_increment = to->to_initval; | ||
375 | to->to_maxval = to->to_initval + (to->to_increment * to->to_retries); | ||
376 | to->to_exponential = 0; | ||
377 | break; | ||
378 | case IPPROTO_UDP: | ||
379 | default: | ||
380 | if (!to->to_initval) | ||
381 | to->to_initval = 11 * HZ / 10; | ||
382 | if (to->to_initval > NFS_MAX_UDP_TIMEOUT) | ||
383 | to->to_initval = NFS_MAX_UDP_TIMEOUT; | ||
384 | to->to_maxval = NFS_MAX_UDP_TIMEOUT; | ||
385 | to->to_exponential = 1; | ||
386 | break; | ||
387 | } | ||
388 | } | ||
389 | |||
361 | /* | 390 | /* |
362 | * Create an RPC client handle. | 391 | * Create an RPC client handle. |
363 | */ | 392 | */ |
@@ -367,22 +396,12 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data) | |||
367 | struct rpc_timeout timeparms; | 396 | struct rpc_timeout timeparms; |
368 | struct rpc_xprt *xprt = NULL; | 397 | struct rpc_xprt *xprt = NULL; |
369 | struct rpc_clnt *clnt = NULL; | 398 | struct rpc_clnt *clnt = NULL; |
370 | int tcp = (data->flags & NFS_MOUNT_TCP); | 399 | int proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP; |
371 | 400 | ||
372 | /* Initialize timeout values */ | 401 | nfs_init_timeout_values(&timeparms, proto, data->timeo, data->retrans); |
373 | timeparms.to_initval = data->timeo * HZ / 10; | ||
374 | timeparms.to_retries = data->retrans; | ||
375 | timeparms.to_maxval = tcp ? RPC_MAX_TCP_TIMEOUT : RPC_MAX_UDP_TIMEOUT; | ||
376 | timeparms.to_exponential = 1; | ||
377 | |||
378 | if (!timeparms.to_initval) | ||
379 | timeparms.to_initval = (tcp ? 600 : 11) * HZ / 10; | ||
380 | if (!timeparms.to_retries) | ||
381 | timeparms.to_retries = 5; | ||
382 | 402 | ||
383 | /* create transport and client */ | 403 | /* create transport and client */ |
384 | xprt = xprt_create_proto(tcp ? IPPROTO_TCP : IPPROTO_UDP, | 404 | xprt = xprt_create_proto(proto, &server->addr, &timeparms); |
385 | &server->addr, &timeparms); | ||
386 | if (IS_ERR(xprt)) { | 405 | if (IS_ERR(xprt)) { |
387 | dprintk("%s: cannot create RPC transport. Error = %ld\n", | 406 | dprintk("%s: cannot create RPC transport. Error = %ld\n", |
388 | __FUNCTION__, PTR_ERR(xprt)); | 407 | __FUNCTION__, PTR_ERR(xprt)); |
@@ -576,7 +595,6 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
576 | { NFS_MOUNT_SOFT, ",soft", ",hard" }, | 595 | { NFS_MOUNT_SOFT, ",soft", ",hard" }, |
577 | { NFS_MOUNT_INTR, ",intr", "" }, | 596 | { NFS_MOUNT_INTR, ",intr", "" }, |
578 | { NFS_MOUNT_POSIX, ",posix", "" }, | 597 | { NFS_MOUNT_POSIX, ",posix", "" }, |
579 | { NFS_MOUNT_TCP, ",tcp", ",udp" }, | ||
580 | { NFS_MOUNT_NOCTO, ",nocto", "" }, | 598 | { NFS_MOUNT_NOCTO, ",nocto", "" }, |
581 | { NFS_MOUNT_NOAC, ",noac", "" }, | 599 | { NFS_MOUNT_NOAC, ",noac", "" }, |
582 | { NFS_MOUNT_NONLM, ",nolock", ",lock" }, | 600 | { NFS_MOUNT_NONLM, ",nolock", ",lock" }, |
@@ -585,6 +603,8 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
585 | }; | 603 | }; |
586 | struct proc_nfs_info *nfs_infop; | 604 | struct proc_nfs_info *nfs_infop; |
587 | struct nfs_server *nfss = NFS_SB(mnt->mnt_sb); | 605 | struct nfs_server *nfss = NFS_SB(mnt->mnt_sb); |
606 | char buf[12]; | ||
607 | char *proto; | ||
588 | 608 | ||
589 | seq_printf(m, ",v%d", nfss->rpc_ops->version); | 609 | seq_printf(m, ",v%d", nfss->rpc_ops->version); |
590 | seq_printf(m, ",rsize=%d", nfss->rsize); | 610 | seq_printf(m, ",rsize=%d", nfss->rsize); |
@@ -603,6 +623,18 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
603 | else | 623 | else |
604 | seq_puts(m, nfs_infop->nostr); | 624 | seq_puts(m, nfs_infop->nostr); |
605 | } | 625 | } |
626 | switch (nfss->client->cl_xprt->prot) { | ||
627 | case IPPROTO_TCP: | ||
628 | proto = "tcp"; | ||
629 | break; | ||
630 | case IPPROTO_UDP: | ||
631 | proto = "udp"; | ||
632 | break; | ||
633 | default: | ||
634 | snprintf(buf, sizeof(buf), "%u", nfss->client->cl_xprt->prot); | ||
635 | proto = buf; | ||
636 | } | ||
637 | seq_printf(m, ",proto=%s", proto); | ||
606 | seq_puts(m, ",addr="); | 638 | seq_puts(m, ",addr="); |
607 | seq_escape(m, nfss->hostname, " \t\n\\"); | 639 | seq_escape(m, nfss->hostname, " \t\n\\"); |
608 | return 0; | 640 | return 0; |
@@ -753,7 +785,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
753 | else | 785 | else |
754 | init_special_inode(inode, inode->i_mode, fattr->rdev); | 786 | init_special_inode(inode, inode->i_mode, fattr->rdev); |
755 | 787 | ||
756 | nfsi->read_cache_jiffies = fattr->timestamp; | 788 | nfsi->read_cache_jiffies = fattr->time_start; |
789 | nfsi->last_updated = jiffies; | ||
757 | inode->i_atime = fattr->atime; | 790 | inode->i_atime = fattr->atime; |
758 | inode->i_mtime = fattr->mtime; | 791 | inode->i_mtime = fattr->mtime; |
759 | inode->i_ctime = fattr->ctime; | 792 | inode->i_ctime = fattr->ctime; |
@@ -821,6 +854,11 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
821 | filemap_fdatawait(inode->i_mapping); | 854 | filemap_fdatawait(inode->i_mapping); |
822 | nfs_wb_all(inode); | 855 | nfs_wb_all(inode); |
823 | } | 856 | } |
857 | /* | ||
858 | * Return any delegations if we're going to change ACLs | ||
859 | */ | ||
860 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) | ||
861 | nfs_inode_return_delegation(inode); | ||
824 | error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr); | 862 | error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr); |
825 | if (error == 0) | 863 | if (error == 0) |
826 | nfs_refresh_inode(inode, &fattr); | 864 | nfs_refresh_inode(inode, &fattr); |
@@ -877,12 +915,10 @@ static int nfs_wait_on_inode(struct inode *inode) | |||
877 | sigset_t oldmask; | 915 | sigset_t oldmask; |
878 | int error; | 916 | int error; |
879 | 917 | ||
880 | atomic_inc(&inode->i_count); | ||
881 | rpc_clnt_sigmask(clnt, &oldmask); | 918 | rpc_clnt_sigmask(clnt, &oldmask); |
882 | error = wait_on_bit_lock(&nfsi->flags, NFS_INO_REVALIDATING, | 919 | error = wait_on_bit_lock(&nfsi->flags, NFS_INO_REVALIDATING, |
883 | nfs_wait_schedule, TASK_INTERRUPTIBLE); | 920 | nfs_wait_schedule, TASK_INTERRUPTIBLE); |
884 | rpc_clnt_sigunmask(clnt, &oldmask); | 921 | rpc_clnt_sigunmask(clnt, &oldmask); |
885 | iput(inode); | ||
886 | 922 | ||
887 | return error; | 923 | return error; |
888 | } | 924 | } |
@@ -1021,15 +1057,11 @@ int nfs_open(struct inode *inode, struct file *filp) | |||
1021 | ctx->mode = filp->f_mode; | 1057 | ctx->mode = filp->f_mode; |
1022 | nfs_file_set_open_context(filp, ctx); | 1058 | nfs_file_set_open_context(filp, ctx); |
1023 | put_nfs_open_context(ctx); | 1059 | put_nfs_open_context(ctx); |
1024 | if ((filp->f_mode & FMODE_WRITE) != 0) | ||
1025 | nfs_begin_data_update(inode); | ||
1026 | return 0; | 1060 | return 0; |
1027 | } | 1061 | } |
1028 | 1062 | ||
1029 | int nfs_release(struct inode *inode, struct file *filp) | 1063 | int nfs_release(struct inode *inode, struct file *filp) |
1030 | { | 1064 | { |
1031 | if ((filp->f_mode & FMODE_WRITE) != 0) | ||
1032 | nfs_end_data_update(inode); | ||
1033 | nfs_file_clear_open_context(filp); | 1065 | nfs_file_clear_open_context(filp); |
1034 | return 0; | 1066 | return 0; |
1035 | } | 1067 | } |
@@ -1085,14 +1117,15 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
1085 | goto out; | 1117 | goto out; |
1086 | } | 1118 | } |
1087 | 1119 | ||
1120 | spin_lock(&inode->i_lock); | ||
1088 | status = nfs_update_inode(inode, &fattr, verifier); | 1121 | status = nfs_update_inode(inode, &fattr, verifier); |
1089 | if (status) { | 1122 | if (status) { |
1123 | spin_unlock(&inode->i_lock); | ||
1090 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", | 1124 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", |
1091 | inode->i_sb->s_id, | 1125 | inode->i_sb->s_id, |
1092 | (long long)NFS_FILEID(inode), status); | 1126 | (long long)NFS_FILEID(inode), status); |
1093 | goto out; | 1127 | goto out; |
1094 | } | 1128 | } |
1095 | spin_lock(&inode->i_lock); | ||
1096 | cache_validity = nfsi->cache_validity; | 1129 | cache_validity = nfsi->cache_validity; |
1097 | nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; | 1130 | nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; |
1098 | 1131 | ||
@@ -1100,7 +1133,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
1100 | * We may need to keep the attributes marked as invalid if | 1133 | * We may need to keep the attributes marked as invalid if |
1101 | * we raced with nfs_end_attr_update(). | 1134 | * we raced with nfs_end_attr_update(). |
1102 | */ | 1135 | */ |
1103 | if (verifier == nfsi->cache_change_attribute) | 1136 | if (time_after_eq(verifier, nfsi->cache_change_attribute)) |
1104 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); | 1137 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); |
1105 | spin_unlock(&inode->i_lock); | 1138 | spin_unlock(&inode->i_lock); |
1106 | 1139 | ||
@@ -1167,7 +1200,7 @@ void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | |||
1167 | if (S_ISDIR(inode->i_mode)) { | 1200 | if (S_ISDIR(inode->i_mode)) { |
1168 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); | 1201 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); |
1169 | /* This ensures we revalidate child dentries */ | 1202 | /* This ensures we revalidate child dentries */ |
1170 | nfsi->cache_change_attribute++; | 1203 | nfsi->cache_change_attribute = jiffies; |
1171 | } | 1204 | } |
1172 | spin_unlock(&inode->i_lock); | 1205 | spin_unlock(&inode->i_lock); |
1173 | 1206 | ||
@@ -1199,20 +1232,19 @@ void nfs_end_data_update(struct inode *inode) | |||
1199 | struct nfs_inode *nfsi = NFS_I(inode); | 1232 | struct nfs_inode *nfsi = NFS_I(inode); |
1200 | 1233 | ||
1201 | if (!nfs_have_delegation(inode, FMODE_READ)) { | 1234 | if (!nfs_have_delegation(inode, FMODE_READ)) { |
1202 | /* Mark the attribute cache for revalidation */ | 1235 | /* Directories and symlinks: invalidate page cache */ |
1203 | spin_lock(&inode->i_lock); | 1236 | if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) { |
1204 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; | 1237 | spin_lock(&inode->i_lock); |
1205 | /* Directories and symlinks: invalidate page cache too */ | ||
1206 | if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) | ||
1207 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | 1238 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; |
1208 | spin_unlock(&inode->i_lock); | 1239 | spin_unlock(&inode->i_lock); |
1240 | } | ||
1209 | } | 1241 | } |
1210 | nfsi->cache_change_attribute ++; | 1242 | nfsi->cache_change_attribute = jiffies; |
1211 | atomic_dec(&nfsi->data_updates); | 1243 | atomic_dec(&nfsi->data_updates); |
1212 | } | 1244 | } |
1213 | 1245 | ||
1214 | /** | 1246 | /** |
1215 | * nfs_refresh_inode - verify consistency of the inode attribute cache | 1247 | * nfs_check_inode_attributes - verify consistency of the inode attribute cache |
1216 | * @inode - pointer to inode | 1248 | * @inode - pointer to inode |
1217 | * @fattr - updated attributes | 1249 | * @fattr - updated attributes |
1218 | * | 1250 | * |
@@ -1220,17 +1252,12 @@ void nfs_end_data_update(struct inode *inode) | |||
1220 | * so that fattr carries weak cache consistency data, then it may | 1252 | * so that fattr carries weak cache consistency data, then it may |
1221 | * also update the ctime/mtime/change_attribute. | 1253 | * also update the ctime/mtime/change_attribute. |
1222 | */ | 1254 | */ |
1223 | int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | 1255 | static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fattr) |
1224 | { | 1256 | { |
1225 | struct nfs_inode *nfsi = NFS_I(inode); | 1257 | struct nfs_inode *nfsi = NFS_I(inode); |
1226 | loff_t cur_size, new_isize; | 1258 | loff_t cur_size, new_isize; |
1227 | int data_unstable; | 1259 | int data_unstable; |
1228 | 1260 | ||
1229 | /* Do we hold a delegation? */ | ||
1230 | if (nfs_have_delegation(inode, FMODE_READ)) | ||
1231 | return 0; | ||
1232 | |||
1233 | spin_lock(&inode->i_lock); | ||
1234 | 1261 | ||
1235 | /* Are we in the process of updating data on the server? */ | 1262 | /* Are we in the process of updating data on the server? */ |
1236 | data_unstable = nfs_caches_unstable(inode); | 1263 | data_unstable = nfs_caches_unstable(inode); |
@@ -1294,11 +1321,67 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1294 | if (!timespec_equal(&inode->i_atime, &fattr->atime)) | 1321 | if (!timespec_equal(&inode->i_atime, &fattr->atime)) |
1295 | nfsi->cache_validity |= NFS_INO_INVALID_ATIME; | 1322 | nfsi->cache_validity |= NFS_INO_INVALID_ATIME; |
1296 | 1323 | ||
1297 | nfsi->read_cache_jiffies = fattr->timestamp; | 1324 | nfsi->read_cache_jiffies = fattr->time_start; |
1298 | spin_unlock(&inode->i_lock); | ||
1299 | return 0; | 1325 | return 0; |
1300 | } | 1326 | } |
1301 | 1327 | ||
1328 | /** | ||
1329 | * nfs_refresh_inode - try to update the inode attribute cache | ||
1330 | * @inode - pointer to inode | ||
1331 | * @fattr - updated attributes | ||
1332 | * | ||
1333 | * Check that an RPC call that returned attributes has not overlapped with | ||
1334 | * other recent updates of the inode metadata, then decide whether it is | ||
1335 | * safe to do a full update of the inode attributes, or whether just to | ||
1336 | * call nfs_check_inode_attributes. | ||
1337 | */ | ||
1338 | int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | ||
1339 | { | ||
1340 | struct nfs_inode *nfsi = NFS_I(inode); | ||
1341 | int status; | ||
1342 | |||
1343 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) | ||
1344 | return 0; | ||
1345 | spin_lock(&inode->i_lock); | ||
1346 | nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; | ||
1347 | if (nfs_verify_change_attribute(inode, fattr->time_start)) | ||
1348 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); | ||
1349 | if (time_after(fattr->time_start, nfsi->last_updated)) | ||
1350 | status = nfs_update_inode(inode, fattr, fattr->time_start); | ||
1351 | else | ||
1352 | status = nfs_check_inode_attributes(inode, fattr); | ||
1353 | |||
1354 | spin_unlock(&inode->i_lock); | ||
1355 | return status; | ||
1356 | } | ||
1357 | |||
1358 | /** | ||
1359 | * nfs_post_op_update_inode - try to update the inode attribute cache | ||
1360 | * @inode - pointer to inode | ||
1361 | * @fattr - updated attributes | ||
1362 | * | ||
1363 | * After an operation that has changed the inode metadata, mark the | ||
1364 | * attribute cache as being invalid, then try to update it. | ||
1365 | */ | ||
1366 | int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | ||
1367 | { | ||
1368 | struct nfs_inode *nfsi = NFS_I(inode); | ||
1369 | int status = 0; | ||
1370 | |||
1371 | spin_lock(&inode->i_lock); | ||
1372 | if (unlikely((fattr->valid & NFS_ATTR_FATTR) == 0)) { | ||
1373 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS; | ||
1374 | goto out; | ||
1375 | } | ||
1376 | status = nfs_update_inode(inode, fattr, fattr->time_start); | ||
1377 | if (time_after_eq(fattr->time_start, nfsi->cache_change_attribute)) | ||
1378 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME|NFS_INO_REVAL_PAGECACHE); | ||
1379 | nfsi->cache_change_attribute = jiffies; | ||
1380 | out: | ||
1381 | spin_unlock(&inode->i_lock); | ||
1382 | return status; | ||
1383 | } | ||
1384 | |||
1302 | /* | 1385 | /* |
1303 | * Many nfs protocol calls return the new file attributes after | 1386 | * Many nfs protocol calls return the new file attributes after |
1304 | * an operation. Here we update the inode to reflect the state | 1387 | * an operation. Here we update the inode to reflect the state |
@@ -1334,23 +1417,21 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1334 | goto out_err; | 1417 | goto out_err; |
1335 | } | 1418 | } |
1336 | 1419 | ||
1337 | spin_lock(&inode->i_lock); | ||
1338 | |||
1339 | /* | 1420 | /* |
1340 | * Make sure the inode's type hasn't changed. | 1421 | * Make sure the inode's type hasn't changed. |
1341 | */ | 1422 | */ |
1342 | if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) { | 1423 | if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) |
1343 | spin_unlock(&inode->i_lock); | ||
1344 | goto out_changed; | 1424 | goto out_changed; |
1345 | } | ||
1346 | 1425 | ||
1347 | /* | 1426 | /* |
1348 | * Update the read time so we don't revalidate too often. | 1427 | * Update the read time so we don't revalidate too often. |
1349 | */ | 1428 | */ |
1350 | nfsi->read_cache_jiffies = fattr->timestamp; | 1429 | nfsi->read_cache_jiffies = fattr->time_start; |
1430 | nfsi->last_updated = jiffies; | ||
1351 | 1431 | ||
1352 | /* Are we racing with known updates of the metadata on the server? */ | 1432 | /* Are we racing with known updates of the metadata on the server? */ |
1353 | data_unstable = ! nfs_verify_change_attribute(inode, verifier); | 1433 | data_unstable = ! (nfs_verify_change_attribute(inode, verifier) || |
1434 | (nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE)); | ||
1354 | 1435 | ||
1355 | /* Check if our cached file size is stale */ | 1436 | /* Check if our cached file size is stale */ |
1356 | new_isize = nfs_size_to_loff_t(fattr->size); | 1437 | new_isize = nfs_size_to_loff_t(fattr->size); |
@@ -1359,7 +1440,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1359 | /* Do we perhaps have any outstanding writes? */ | 1440 | /* Do we perhaps have any outstanding writes? */ |
1360 | if (nfsi->npages == 0) { | 1441 | if (nfsi->npages == 0) { |
1361 | /* No, but did we race with nfs_end_data_update()? */ | 1442 | /* No, but did we race with nfs_end_data_update()? */ |
1362 | if (verifier == nfsi->cache_change_attribute) { | 1443 | if (time_after_eq(verifier, nfsi->cache_change_attribute)) { |
1363 | inode->i_size = new_isize; | 1444 | inode->i_size = new_isize; |
1364 | invalid |= NFS_INO_INVALID_DATA; | 1445 | invalid |= NFS_INO_INVALID_DATA; |
1365 | } | 1446 | } |
@@ -1435,7 +1516,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1435 | if (!nfs_have_delegation(inode, FMODE_READ)) | 1516 | if (!nfs_have_delegation(inode, FMODE_READ)) |
1436 | nfsi->cache_validity |= invalid; | 1517 | nfsi->cache_validity |= invalid; |
1437 | 1518 | ||
1438 | spin_unlock(&inode->i_lock); | ||
1439 | return 0; | 1519 | return 0; |
1440 | out_changed: | 1520 | out_changed: |
1441 | /* | 1521 | /* |
@@ -1644,8 +1724,7 @@ static void nfs4_clear_inode(struct inode *inode) | |||
1644 | struct nfs_inode *nfsi = NFS_I(inode); | 1724 | struct nfs_inode *nfsi = NFS_I(inode); |
1645 | 1725 | ||
1646 | /* If we are holding a delegation, return it! */ | 1726 | /* If we are holding a delegation, return it! */ |
1647 | if (nfsi->delegation != NULL) | 1727 | nfs_inode_return_delegation(inode); |
1648 | nfs_inode_return_delegation(inode); | ||
1649 | /* First call standard NFS clear_inode() code */ | 1728 | /* First call standard NFS clear_inode() code */ |
1650 | nfs_clear_inode(inode); | 1729 | nfs_clear_inode(inode); |
1651 | /* Now clear out any remaining state */ | 1730 | /* Now clear out any remaining state */ |
@@ -1674,7 +1753,7 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, | |||
1674 | struct rpc_clnt *clnt = NULL; | 1753 | struct rpc_clnt *clnt = NULL; |
1675 | struct rpc_timeout timeparms; | 1754 | struct rpc_timeout timeparms; |
1676 | rpc_authflavor_t authflavour; | 1755 | rpc_authflavor_t authflavour; |
1677 | int proto, err = -EIO; | 1756 | int err = -EIO; |
1678 | 1757 | ||
1679 | sb->s_blocksize_bits = 0; | 1758 | sb->s_blocksize_bits = 0; |
1680 | sb->s_blocksize = 0; | 1759 | sb->s_blocksize = 0; |
@@ -1692,30 +1771,8 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, | |||
1692 | server->acdirmax = data->acdirmax*HZ; | 1771 | server->acdirmax = data->acdirmax*HZ; |
1693 | 1772 | ||
1694 | server->rpc_ops = &nfs_v4_clientops; | 1773 | server->rpc_ops = &nfs_v4_clientops; |
1695 | /* Initialize timeout values */ | ||
1696 | |||
1697 | timeparms.to_initval = data->timeo * HZ / 10; | ||
1698 | timeparms.to_retries = data->retrans; | ||
1699 | timeparms.to_exponential = 1; | ||
1700 | if (!timeparms.to_retries) | ||
1701 | timeparms.to_retries = 5; | ||
1702 | 1774 | ||
1703 | proto = data->proto; | 1775 | nfs_init_timeout_values(&timeparms, data->proto, data->timeo, data->retrans); |
1704 | /* Which IP protocol do we use? */ | ||
1705 | switch (proto) { | ||
1706 | case IPPROTO_TCP: | ||
1707 | timeparms.to_maxval = RPC_MAX_TCP_TIMEOUT; | ||
1708 | if (!timeparms.to_initval) | ||
1709 | timeparms.to_initval = 600 * HZ / 10; | ||
1710 | break; | ||
1711 | case IPPROTO_UDP: | ||
1712 | timeparms.to_maxval = RPC_MAX_UDP_TIMEOUT; | ||
1713 | if (!timeparms.to_initval) | ||
1714 | timeparms.to_initval = 11 * HZ / 10; | ||
1715 | break; | ||
1716 | default: | ||
1717 | return -EINVAL; | ||
1718 | } | ||
1719 | 1776 | ||
1720 | clp = nfs4_get_client(&server->addr.sin_addr); | 1777 | clp = nfs4_get_client(&server->addr.sin_addr); |
1721 | if (!clp) { | 1778 | if (!clp) { |
@@ -1740,7 +1797,7 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, | |||
1740 | 1797 | ||
1741 | down_write(&clp->cl_sem); | 1798 | down_write(&clp->cl_sem); |
1742 | if (IS_ERR(clp->cl_rpcclient)) { | 1799 | if (IS_ERR(clp->cl_rpcclient)) { |
1743 | xprt = xprt_create_proto(proto, &server->addr, &timeparms); | 1800 | xprt = xprt_create_proto(data->proto, &server->addr, &timeparms); |
1744 | if (IS_ERR(xprt)) { | 1801 | if (IS_ERR(xprt)) { |
1745 | up_write(&clp->cl_sem); | 1802 | up_write(&clp->cl_sem); |
1746 | err = PTR_ERR(xprt); | 1803 | err = PTR_ERR(xprt); |
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index d91b69044a4d..59049e864ca7 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c | |||
@@ -143,7 +143,6 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) | |||
143 | fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO; | 143 | fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO; |
144 | fattr->rdev = 0; | 144 | fattr->rdev = 0; |
145 | } | 145 | } |
146 | fattr->timestamp = jiffies; | ||
147 | return p; | 146 | return p; |
148 | } | 147 | } |
149 | 148 | ||
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index edc95514046d..92c870d19ccd 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
@@ -78,7 +78,7 @@ nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
78 | int status; | 78 | int status; |
79 | 79 | ||
80 | dprintk("%s: call fsinfo\n", __FUNCTION__); | 80 | dprintk("%s: call fsinfo\n", __FUNCTION__); |
81 | info->fattr->valid = 0; | 81 | nfs_fattr_init(info->fattr); |
82 | status = rpc_call(server->client_sys, NFS3PROC_FSINFO, fhandle, info, 0); | 82 | status = rpc_call(server->client_sys, NFS3PROC_FSINFO, fhandle, info, 0); |
83 | dprintk("%s: reply fsinfo: %d\n", __FUNCTION__, status); | 83 | dprintk("%s: reply fsinfo: %d\n", __FUNCTION__, status); |
84 | if (!(info->fattr->valid & NFS_ATTR_FATTR)) { | 84 | if (!(info->fattr->valid & NFS_ATTR_FATTR)) { |
@@ -98,7 +98,7 @@ nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, | |||
98 | int status; | 98 | int status; |
99 | 99 | ||
100 | dprintk("NFS call getattr\n"); | 100 | dprintk("NFS call getattr\n"); |
101 | fattr->valid = 0; | 101 | nfs_fattr_init(fattr); |
102 | status = rpc_call(server->client, NFS3PROC_GETATTR, | 102 | status = rpc_call(server->client, NFS3PROC_GETATTR, |
103 | fhandle, fattr, 0); | 103 | fhandle, fattr, 0); |
104 | dprintk("NFS reply getattr: %d\n", status); | 104 | dprintk("NFS reply getattr: %d\n", status); |
@@ -117,7 +117,7 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
117 | int status; | 117 | int status; |
118 | 118 | ||
119 | dprintk("NFS call setattr\n"); | 119 | dprintk("NFS call setattr\n"); |
120 | fattr->valid = 0; | 120 | nfs_fattr_init(fattr); |
121 | status = rpc_call(NFS_CLIENT(inode), NFS3PROC_SETATTR, &arg, fattr, 0); | 121 | status = rpc_call(NFS_CLIENT(inode), NFS3PROC_SETATTR, &arg, fattr, 0); |
122 | if (status == 0) | 122 | if (status == 0) |
123 | nfs_setattr_update_inode(inode, sattr); | 123 | nfs_setattr_update_inode(inode, sattr); |
@@ -143,8 +143,8 @@ nfs3_proc_lookup(struct inode *dir, struct qstr *name, | |||
143 | int status; | 143 | int status; |
144 | 144 | ||
145 | dprintk("NFS call lookup %s\n", name->name); | 145 | dprintk("NFS call lookup %s\n", name->name); |
146 | dir_attr.valid = 0; | 146 | nfs_fattr_init(&dir_attr); |
147 | fattr->valid = 0; | 147 | nfs_fattr_init(fattr); |
148 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_LOOKUP, &arg, &res, 0); | 148 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_LOOKUP, &arg, &res, 0); |
149 | if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) | 149 | if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) |
150 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_GETATTR, | 150 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_GETATTR, |
@@ -174,7 +174,6 @@ static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry) | |||
174 | int status; | 174 | int status; |
175 | 175 | ||
176 | dprintk("NFS call access\n"); | 176 | dprintk("NFS call access\n"); |
177 | fattr.valid = 0; | ||
178 | 177 | ||
179 | if (mode & MAY_READ) | 178 | if (mode & MAY_READ) |
180 | arg.access |= NFS3_ACCESS_READ; | 179 | arg.access |= NFS3_ACCESS_READ; |
@@ -189,6 +188,7 @@ static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry) | |||
189 | if (mode & MAY_EXEC) | 188 | if (mode & MAY_EXEC) |
190 | arg.access |= NFS3_ACCESS_EXECUTE; | 189 | arg.access |= NFS3_ACCESS_EXECUTE; |
191 | } | 190 | } |
191 | nfs_fattr_init(&fattr); | ||
192 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); | 192 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); |
193 | nfs_refresh_inode(inode, &fattr); | 193 | nfs_refresh_inode(inode, &fattr); |
194 | if (status == 0) { | 194 | if (status == 0) { |
@@ -217,7 +217,7 @@ static int nfs3_proc_readlink(struct inode *inode, struct page *page, | |||
217 | int status; | 217 | int status; |
218 | 218 | ||
219 | dprintk("NFS call readlink\n"); | 219 | dprintk("NFS call readlink\n"); |
220 | fattr.valid = 0; | 220 | nfs_fattr_init(&fattr); |
221 | status = rpc_call(NFS_CLIENT(inode), NFS3PROC_READLINK, | 221 | status = rpc_call(NFS_CLIENT(inode), NFS3PROC_READLINK, |
222 | &args, &fattr, 0); | 222 | &args, &fattr, 0); |
223 | nfs_refresh_inode(inode, &fattr); | 223 | nfs_refresh_inode(inode, &fattr); |
@@ -240,7 +240,7 @@ static int nfs3_proc_read(struct nfs_read_data *rdata) | |||
240 | 240 | ||
241 | dprintk("NFS call read %d @ %Ld\n", rdata->args.count, | 241 | dprintk("NFS call read %d @ %Ld\n", rdata->args.count, |
242 | (long long) rdata->args.offset); | 242 | (long long) rdata->args.offset); |
243 | fattr->valid = 0; | 243 | nfs_fattr_init(fattr); |
244 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); | 244 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); |
245 | if (status >= 0) | 245 | if (status >= 0) |
246 | nfs_refresh_inode(inode, fattr); | 246 | nfs_refresh_inode(inode, fattr); |
@@ -263,10 +263,10 @@ static int nfs3_proc_write(struct nfs_write_data *wdata) | |||
263 | 263 | ||
264 | dprintk("NFS call write %d @ %Ld\n", wdata->args.count, | 264 | dprintk("NFS call write %d @ %Ld\n", wdata->args.count, |
265 | (long long) wdata->args.offset); | 265 | (long long) wdata->args.offset); |
266 | fattr->valid = 0; | 266 | nfs_fattr_init(fattr); |
267 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags); | 267 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags); |
268 | if (status >= 0) | 268 | if (status >= 0) |
269 | nfs_refresh_inode(inode, fattr); | 269 | nfs_post_op_update_inode(inode, fattr); |
270 | dprintk("NFS reply write: %d\n", status); | 270 | dprintk("NFS reply write: %d\n", status); |
271 | return status < 0? status : wdata->res.count; | 271 | return status < 0? status : wdata->res.count; |
272 | } | 272 | } |
@@ -285,10 +285,10 @@ static int nfs3_proc_commit(struct nfs_write_data *cdata) | |||
285 | 285 | ||
286 | dprintk("NFS call commit %d @ %Ld\n", cdata->args.count, | 286 | dprintk("NFS call commit %d @ %Ld\n", cdata->args.count, |
287 | (long long) cdata->args.offset); | 287 | (long long) cdata->args.offset); |
288 | fattr->valid = 0; | 288 | nfs_fattr_init(fattr); |
289 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); | 289 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); |
290 | if (status >= 0) | 290 | if (status >= 0) |
291 | nfs_refresh_inode(inode, fattr); | 291 | nfs_post_op_update_inode(inode, fattr); |
292 | dprintk("NFS reply commit: %d\n", status); | 292 | dprintk("NFS reply commit: %d\n", status); |
293 | return status; | 293 | return status; |
294 | } | 294 | } |
@@ -299,7 +299,7 @@ static int nfs3_proc_commit(struct nfs_write_data *cdata) | |||
299 | */ | 299 | */ |
300 | static int | 300 | static int |
301 | nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 301 | nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
302 | int flags) | 302 | int flags, struct nameidata *nd) |
303 | { | 303 | { |
304 | struct nfs_fh fhandle; | 304 | struct nfs_fh fhandle; |
305 | struct nfs_fattr fattr; | 305 | struct nfs_fattr fattr; |
@@ -329,10 +329,10 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
329 | sattr->ia_mode &= ~current->fs->umask; | 329 | sattr->ia_mode &= ~current->fs->umask; |
330 | 330 | ||
331 | again: | 331 | again: |
332 | dir_attr.valid = 0; | 332 | nfs_fattr_init(&dir_attr); |
333 | fattr.valid = 0; | 333 | nfs_fattr_init(&fattr); |
334 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_CREATE, &arg, &res, 0); | 334 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_CREATE, &arg, &res, 0); |
335 | nfs_refresh_inode(dir, &dir_attr); | 335 | nfs_post_op_update_inode(dir, &dir_attr); |
336 | 336 | ||
337 | /* If the server doesn't support the exclusive creation semantics, | 337 | /* If the server doesn't support the exclusive creation semantics, |
338 | * try again with simple 'guarded' mode. */ | 338 | * try again with simple 'guarded' mode. */ |
@@ -401,9 +401,9 @@ nfs3_proc_remove(struct inode *dir, struct qstr *name) | |||
401 | int status; | 401 | int status; |
402 | 402 | ||
403 | dprintk("NFS call remove %s\n", name->name); | 403 | dprintk("NFS call remove %s\n", name->name); |
404 | dir_attr.valid = 0; | 404 | nfs_fattr_init(&dir_attr); |
405 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 405 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
406 | nfs_refresh_inode(dir, &dir_attr); | 406 | nfs_post_op_update_inode(dir, &dir_attr); |
407 | dprintk("NFS reply remove: %d\n", status); | 407 | dprintk("NFS reply remove: %d\n", status); |
408 | return status; | 408 | return status; |
409 | } | 409 | } |
@@ -422,7 +422,7 @@ nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr | |||
422 | ptr->arg.fh = NFS_FH(dir->d_inode); | 422 | ptr->arg.fh = NFS_FH(dir->d_inode); |
423 | ptr->arg.name = name->name; | 423 | ptr->arg.name = name->name; |
424 | ptr->arg.len = name->len; | 424 | ptr->arg.len = name->len; |
425 | ptr->res.valid = 0; | 425 | nfs_fattr_init(&ptr->res); |
426 | msg->rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE]; | 426 | msg->rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE]; |
427 | msg->rpc_argp = &ptr->arg; | 427 | msg->rpc_argp = &ptr->arg; |
428 | msg->rpc_resp = &ptr->res; | 428 | msg->rpc_resp = &ptr->res; |
@@ -439,7 +439,7 @@ nfs3_proc_unlink_done(struct dentry *dir, struct rpc_task *task) | |||
439 | return 1; | 439 | return 1; |
440 | if (msg->rpc_argp) { | 440 | if (msg->rpc_argp) { |
441 | dir_attr = (struct nfs_fattr*)msg->rpc_resp; | 441 | dir_attr = (struct nfs_fattr*)msg->rpc_resp; |
442 | nfs_refresh_inode(dir->d_inode, dir_attr); | 442 | nfs_post_op_update_inode(dir->d_inode, dir_attr); |
443 | kfree(msg->rpc_argp); | 443 | kfree(msg->rpc_argp); |
444 | } | 444 | } |
445 | return 0; | 445 | return 0; |
@@ -465,11 +465,11 @@ nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name, | |||
465 | int status; | 465 | int status; |
466 | 466 | ||
467 | dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name); | 467 | dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name); |
468 | old_dir_attr.valid = 0; | 468 | nfs_fattr_init(&old_dir_attr); |
469 | new_dir_attr.valid = 0; | 469 | nfs_fattr_init(&new_dir_attr); |
470 | status = rpc_call(NFS_CLIENT(old_dir), NFS3PROC_RENAME, &arg, &res, 0); | 470 | status = rpc_call(NFS_CLIENT(old_dir), NFS3PROC_RENAME, &arg, &res, 0); |
471 | nfs_refresh_inode(old_dir, &old_dir_attr); | 471 | nfs_post_op_update_inode(old_dir, &old_dir_attr); |
472 | nfs_refresh_inode(new_dir, &new_dir_attr); | 472 | nfs_post_op_update_inode(new_dir, &new_dir_attr); |
473 | dprintk("NFS reply rename: %d\n", status); | 473 | dprintk("NFS reply rename: %d\n", status); |
474 | return status; | 474 | return status; |
475 | } | 475 | } |
@@ -491,11 +491,11 @@ nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) | |||
491 | int status; | 491 | int status; |
492 | 492 | ||
493 | dprintk("NFS call link %s\n", name->name); | 493 | dprintk("NFS call link %s\n", name->name); |
494 | dir_attr.valid = 0; | 494 | nfs_fattr_init(&dir_attr); |
495 | fattr.valid = 0; | 495 | nfs_fattr_init(&fattr); |
496 | status = rpc_call(NFS_CLIENT(inode), NFS3PROC_LINK, &arg, &res, 0); | 496 | status = rpc_call(NFS_CLIENT(inode), NFS3PROC_LINK, &arg, &res, 0); |
497 | nfs_refresh_inode(dir, &dir_attr); | 497 | nfs_post_op_update_inode(dir, &dir_attr); |
498 | nfs_refresh_inode(inode, &fattr); | 498 | nfs_post_op_update_inode(inode, &fattr); |
499 | dprintk("NFS reply link: %d\n", status); | 499 | dprintk("NFS reply link: %d\n", status); |
500 | return status; | 500 | return status; |
501 | } | 501 | } |
@@ -524,10 +524,10 @@ nfs3_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path, | |||
524 | if (path->len > NFS3_MAXPATHLEN) | 524 | if (path->len > NFS3_MAXPATHLEN) |
525 | return -ENAMETOOLONG; | 525 | return -ENAMETOOLONG; |
526 | dprintk("NFS call symlink %s -> %s\n", name->name, path->name); | 526 | dprintk("NFS call symlink %s -> %s\n", name->name, path->name); |
527 | dir_attr.valid = 0; | 527 | nfs_fattr_init(&dir_attr); |
528 | fattr->valid = 0; | 528 | nfs_fattr_init(fattr); |
529 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SYMLINK, &arg, &res, 0); | 529 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SYMLINK, &arg, &res, 0); |
530 | nfs_refresh_inode(dir, &dir_attr); | 530 | nfs_post_op_update_inode(dir, &dir_attr); |
531 | dprintk("NFS reply symlink: %d\n", status); | 531 | dprintk("NFS reply symlink: %d\n", status); |
532 | return status; | 532 | return status; |
533 | } | 533 | } |
@@ -552,13 +552,13 @@ nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) | |||
552 | int status; | 552 | int status; |
553 | 553 | ||
554 | dprintk("NFS call mkdir %s\n", dentry->d_name.name); | 554 | dprintk("NFS call mkdir %s\n", dentry->d_name.name); |
555 | dir_attr.valid = 0; | ||
556 | fattr.valid = 0; | ||
557 | 555 | ||
558 | sattr->ia_mode &= ~current->fs->umask; | 556 | sattr->ia_mode &= ~current->fs->umask; |
559 | 557 | ||
558 | nfs_fattr_init(&dir_attr); | ||
559 | nfs_fattr_init(&fattr); | ||
560 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, 0); | 560 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, 0); |
561 | nfs_refresh_inode(dir, &dir_attr); | 561 | nfs_post_op_update_inode(dir, &dir_attr); |
562 | if (status != 0) | 562 | if (status != 0) |
563 | goto out; | 563 | goto out; |
564 | status = nfs_instantiate(dentry, &fhandle, &fattr); | 564 | status = nfs_instantiate(dentry, &fhandle, &fattr); |
@@ -582,9 +582,9 @@ nfs3_proc_rmdir(struct inode *dir, struct qstr *name) | |||
582 | int status; | 582 | int status; |
583 | 583 | ||
584 | dprintk("NFS call rmdir %s\n", name->name); | 584 | dprintk("NFS call rmdir %s\n", name->name); |
585 | dir_attr.valid = 0; | 585 | nfs_fattr_init(&dir_attr); |
586 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_RMDIR, &arg, &dir_attr, 0); | 586 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_RMDIR, &arg, &dir_attr, 0); |
587 | nfs_refresh_inode(dir, &dir_attr); | 587 | nfs_post_op_update_inode(dir, &dir_attr); |
588 | dprintk("NFS reply rmdir: %d\n", status); | 588 | dprintk("NFS reply rmdir: %d\n", status); |
589 | return status; | 589 | return status; |
590 | } | 590 | } |
@@ -634,7 +634,7 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | |||
634 | dprintk("NFS call readdir%s %d\n", | 634 | dprintk("NFS call readdir%s %d\n", |
635 | plus? "plus" : "", (unsigned int) cookie); | 635 | plus? "plus" : "", (unsigned int) cookie); |
636 | 636 | ||
637 | dir_attr.valid = 0; | 637 | nfs_fattr_init(&dir_attr); |
638 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 638 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
639 | nfs_refresh_inode(dir, &dir_attr); | 639 | nfs_refresh_inode(dir, &dir_attr); |
640 | dprintk("NFS reply readdir: %d\n", status); | 640 | dprintk("NFS reply readdir: %d\n", status); |
@@ -676,10 +676,10 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
676 | 676 | ||
677 | sattr->ia_mode &= ~current->fs->umask; | 677 | sattr->ia_mode &= ~current->fs->umask; |
678 | 678 | ||
679 | dir_attr.valid = 0; | 679 | nfs_fattr_init(&dir_attr); |
680 | fattr.valid = 0; | 680 | nfs_fattr_init(&fattr); |
681 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, 0); | 681 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, 0); |
682 | nfs_refresh_inode(dir, &dir_attr); | 682 | nfs_post_op_update_inode(dir, &dir_attr); |
683 | if (status != 0) | 683 | if (status != 0) |
684 | goto out; | 684 | goto out; |
685 | status = nfs_instantiate(dentry, &fh, &fattr); | 685 | status = nfs_instantiate(dentry, &fh, &fattr); |
@@ -698,7 +698,7 @@ nfs3_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, | |||
698 | int status; | 698 | int status; |
699 | 699 | ||
700 | dprintk("NFS call fsstat\n"); | 700 | dprintk("NFS call fsstat\n"); |
701 | stat->fattr->valid = 0; | 701 | nfs_fattr_init(stat->fattr); |
702 | status = rpc_call(server->client, NFS3PROC_FSSTAT, fhandle, stat, 0); | 702 | status = rpc_call(server->client, NFS3PROC_FSSTAT, fhandle, stat, 0); |
703 | dprintk("NFS reply statfs: %d\n", status); | 703 | dprintk("NFS reply statfs: %d\n", status); |
704 | return status; | 704 | return status; |
@@ -711,7 +711,7 @@ nfs3_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, | |||
711 | int status; | 711 | int status; |
712 | 712 | ||
713 | dprintk("NFS call fsinfo\n"); | 713 | dprintk("NFS call fsinfo\n"); |
714 | info->fattr->valid = 0; | 714 | nfs_fattr_init(info->fattr); |
715 | status = rpc_call(server->client_sys, NFS3PROC_FSINFO, fhandle, info, 0); | 715 | status = rpc_call(server->client_sys, NFS3PROC_FSINFO, fhandle, info, 0); |
716 | dprintk("NFS reply fsinfo: %d\n", status); | 716 | dprintk("NFS reply fsinfo: %d\n", status); |
717 | return status; | 717 | return status; |
@@ -724,7 +724,7 @@ nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, | |||
724 | int status; | 724 | int status; |
725 | 725 | ||
726 | dprintk("NFS call pathconf\n"); | 726 | dprintk("NFS call pathconf\n"); |
727 | info->fattr->valid = 0; | 727 | nfs_fattr_init(info->fattr); |
728 | status = rpc_call(server->client, NFS3PROC_PATHCONF, fhandle, info, 0); | 728 | status = rpc_call(server->client, NFS3PROC_PATHCONF, fhandle, info, 0); |
729 | dprintk("NFS reply pathconf: %d\n", status); | 729 | dprintk("NFS reply pathconf: %d\n", status); |
730 | return status; | 730 | return status; |
@@ -735,7 +735,7 @@ extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int); | |||
735 | static void | 735 | static void |
736 | nfs3_read_done(struct rpc_task *task) | 736 | nfs3_read_done(struct rpc_task *task) |
737 | { | 737 | { |
738 | struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata; | 738 | struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata; |
739 | 739 | ||
740 | if (nfs3_async_handle_jukebox(task)) | 740 | if (nfs3_async_handle_jukebox(task)) |
741 | return; | 741 | return; |
@@ -775,7 +775,7 @@ nfs3_write_done(struct rpc_task *task) | |||
775 | return; | 775 | return; |
776 | data = (struct nfs_write_data *)task->tk_calldata; | 776 | data = (struct nfs_write_data *)task->tk_calldata; |
777 | if (task->tk_status >= 0) | 777 | if (task->tk_status >= 0) |
778 | nfs_refresh_inode(data->inode, data->res.fattr); | 778 | nfs_post_op_update_inode(data->inode, data->res.fattr); |
779 | nfs_writeback_done(task); | 779 | nfs_writeback_done(task); |
780 | } | 780 | } |
781 | 781 | ||
@@ -819,7 +819,7 @@ nfs3_commit_done(struct rpc_task *task) | |||
819 | return; | 819 | return; |
820 | data = (struct nfs_write_data *)task->tk_calldata; | 820 | data = (struct nfs_write_data *)task->tk_calldata; |
821 | if (task->tk_status >= 0) | 821 | if (task->tk_status >= 0) |
822 | nfs_refresh_inode(data->inode, data->res.fattr); | 822 | nfs_post_op_update_inode(data->inode, data->res.fattr); |
823 | nfs_commit_done(task); | 823 | nfs_commit_done(task); |
824 | } | 824 | } |
825 | 825 | ||
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index db4a904810a4..0498bd36602c 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c | |||
@@ -174,7 +174,6 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) | |||
174 | 174 | ||
175 | /* Update the mode bits */ | 175 | /* Update the mode bits */ |
176 | fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3); | 176 | fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3); |
177 | fattr->timestamp = jiffies; | ||
178 | return p; | 177 | return p; |
179 | } | 178 | } |
180 | 179 | ||
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index ec1a22d7b876..78a53f5a9f18 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -93,25 +93,50 @@ struct nfs4_client { | |||
93 | }; | 93 | }; |
94 | 94 | ||
95 | /* | 95 | /* |
96 | * struct rpc_sequence ensures that RPC calls are sent in the exact | ||
97 | * order that they appear on the list. | ||
98 | */ | ||
99 | struct rpc_sequence { | ||
100 | struct rpc_wait_queue wait; /* RPC call delay queue */ | ||
101 | spinlock_t lock; /* Protects the list */ | ||
102 | struct list_head list; /* Defines sequence of RPC calls */ | ||
103 | }; | ||
104 | |||
105 | #define NFS_SEQID_CONFIRMED 1 | ||
106 | struct nfs_seqid_counter { | ||
107 | struct rpc_sequence *sequence; | ||
108 | int flags; | ||
109 | u32 counter; | ||
110 | }; | ||
111 | |||
112 | struct nfs_seqid { | ||
113 | struct nfs_seqid_counter *sequence; | ||
114 | struct list_head list; | ||
115 | }; | ||
116 | |||
117 | static inline void nfs_confirm_seqid(struct nfs_seqid_counter *seqid, int status) | ||
118 | { | ||
119 | if (seqid_mutating_err(-status)) | ||
120 | seqid->flags |= NFS_SEQID_CONFIRMED; | ||
121 | } | ||
122 | |||
123 | /* | ||
96 | * NFS4 state_owners and lock_owners are simply labels for ordered | 124 | * NFS4 state_owners and lock_owners are simply labels for ordered |
97 | * sequences of RPC calls. Their sole purpose is to provide once-only | 125 | * sequences of RPC calls. Their sole purpose is to provide once-only |
98 | * semantics by allowing the server to identify replayed requests. | 126 | * semantics by allowing the server to identify replayed requests. |
99 | * | ||
100 | * The ->so_sema is held during all state_owner seqid-mutating operations: | ||
101 | * OPEN, OPEN_DOWNGRADE, and CLOSE. Its purpose is to properly serialize | ||
102 | * so_seqid. | ||
103 | */ | 127 | */ |
104 | struct nfs4_state_owner { | 128 | struct nfs4_state_owner { |
129 | spinlock_t so_lock; | ||
105 | struct list_head so_list; /* per-clientid list of state_owners */ | 130 | struct list_head so_list; /* per-clientid list of state_owners */ |
106 | struct nfs4_client *so_client; | 131 | struct nfs4_client *so_client; |
107 | u32 so_id; /* 32-bit identifier, unique */ | 132 | u32 so_id; /* 32-bit identifier, unique */ |
108 | struct semaphore so_sema; | ||
109 | u32 so_seqid; /* protected by so_sema */ | ||
110 | atomic_t so_count; | 133 | atomic_t so_count; |
111 | 134 | ||
112 | struct rpc_cred *so_cred; /* Associated cred */ | 135 | struct rpc_cred *so_cred; /* Associated cred */ |
113 | struct list_head so_states; | 136 | struct list_head so_states; |
114 | struct list_head so_delegations; | 137 | struct list_head so_delegations; |
138 | struct nfs_seqid_counter so_seqid; | ||
139 | struct rpc_sequence so_sequence; | ||
115 | }; | 140 | }; |
116 | 141 | ||
117 | /* | 142 | /* |
@@ -132,7 +157,7 @@ struct nfs4_lock_state { | |||
132 | fl_owner_t ls_owner; /* POSIX lock owner */ | 157 | fl_owner_t ls_owner; /* POSIX lock owner */ |
133 | #define NFS_LOCK_INITIALIZED 1 | 158 | #define NFS_LOCK_INITIALIZED 1 |
134 | int ls_flags; | 159 | int ls_flags; |
135 | u32 ls_seqid; | 160 | struct nfs_seqid_counter ls_seqid; |
136 | u32 ls_id; | 161 | u32 ls_id; |
137 | nfs4_stateid ls_stateid; | 162 | nfs4_stateid ls_stateid; |
138 | atomic_t ls_count; | 163 | atomic_t ls_count; |
@@ -153,7 +178,6 @@ struct nfs4_state { | |||
153 | struct inode *inode; /* Pointer to the inode */ | 178 | struct inode *inode; /* Pointer to the inode */ |
154 | 179 | ||
155 | unsigned long flags; /* Do we hold any locks? */ | 180 | unsigned long flags; /* Do we hold any locks? */ |
156 | struct semaphore lock_sema; /* Serializes file locking operations */ | ||
157 | spinlock_t state_lock; /* Protects the lock_states list */ | 181 | spinlock_t state_lock; /* Protects the lock_states list */ |
158 | 182 | ||
159 | nfs4_stateid stateid; | 183 | nfs4_stateid stateid; |
@@ -191,8 +215,8 @@ extern int nfs4_proc_setclientid_confirm(struct nfs4_client *); | |||
191 | extern int nfs4_proc_async_renew(struct nfs4_client *); | 215 | extern int nfs4_proc_async_renew(struct nfs4_client *); |
192 | extern int nfs4_proc_renew(struct nfs4_client *); | 216 | extern int nfs4_proc_renew(struct nfs4_client *); |
193 | extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode); | 217 | extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode); |
194 | extern struct inode *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); | 218 | extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); |
195 | extern int nfs4_open_revalidate(struct inode *, struct dentry *, int); | 219 | extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); |
196 | 220 | ||
197 | extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops; | 221 | extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops; |
198 | extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops; | 222 | extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops; |
@@ -224,12 +248,17 @@ extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state | |||
224 | extern void nfs4_put_open_state(struct nfs4_state *); | 248 | extern void nfs4_put_open_state(struct nfs4_state *); |
225 | extern void nfs4_close_state(struct nfs4_state *, mode_t); | 249 | extern void nfs4_close_state(struct nfs4_state *, mode_t); |
226 | extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode); | 250 | extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode); |
227 | extern void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp); | ||
228 | extern void nfs4_schedule_state_recovery(struct nfs4_client *); | 251 | extern void nfs4_schedule_state_recovery(struct nfs4_client *); |
252 | extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); | ||
229 | extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); | 253 | extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); |
230 | extern void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *ls); | ||
231 | extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t); | 254 | extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t); |
232 | 255 | ||
256 | extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter); | ||
257 | extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task); | ||
258 | extern void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid); | ||
259 | extern void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid); | ||
260 | extern void nfs_free_seqid(struct nfs_seqid *seqid); | ||
261 | |||
233 | extern const nfs4_stateid zero_stateid; | 262 | extern const nfs4_stateid zero_stateid; |
234 | 263 | ||
235 | /* nfs4xdr.c */ | 264 | /* nfs4xdr.c */ |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 9701ca8c9428..933e13b383f8 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/nfs_page.h> | 47 | #include <linux/nfs_page.h> |
48 | #include <linux/smp_lock.h> | 48 | #include <linux/smp_lock.h> |
49 | #include <linux/namei.h> | 49 | #include <linux/namei.h> |
50 | #include <linux/mount.h> | ||
50 | 51 | ||
51 | #include "nfs4_fs.h" | 52 | #include "nfs4_fs.h" |
52 | #include "delegation.h" | 53 | #include "delegation.h" |
@@ -56,10 +57,11 @@ | |||
56 | #define NFS4_POLL_RETRY_MIN (1*HZ) | 57 | #define NFS4_POLL_RETRY_MIN (1*HZ) |
57 | #define NFS4_POLL_RETRY_MAX (15*HZ) | 58 | #define NFS4_POLL_RETRY_MAX (15*HZ) |
58 | 59 | ||
60 | static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid, struct nfs_seqid *seqid); | ||
59 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); | 61 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); |
60 | static int nfs4_async_handle_error(struct rpc_task *, struct nfs_server *); | 62 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *); |
61 | static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry); | 63 | static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry); |
62 | static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception); | 64 | static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception); |
63 | extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus); | 65 | extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus); |
64 | extern struct rpc_procinfo nfs4_procedures[]; | 66 | extern struct rpc_procinfo nfs4_procedures[]; |
65 | 67 | ||
@@ -185,8 +187,26 @@ static void update_changeattr(struct inode *inode, struct nfs4_change_info *cinf | |||
185 | { | 187 | { |
186 | struct nfs_inode *nfsi = NFS_I(inode); | 188 | struct nfs_inode *nfsi = NFS_I(inode); |
187 | 189 | ||
190 | spin_lock(&inode->i_lock); | ||
191 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; | ||
188 | if (cinfo->before == nfsi->change_attr && cinfo->atomic) | 192 | if (cinfo->before == nfsi->change_attr && cinfo->atomic) |
189 | nfsi->change_attr = cinfo->after; | 193 | nfsi->change_attr = cinfo->after; |
194 | spin_unlock(&inode->i_lock); | ||
195 | } | ||
196 | |||
197 | /* Helper for asynchronous RPC calls */ | ||
198 | static int nfs4_call_async(struct rpc_clnt *clnt, rpc_action tk_begin, | ||
199 | rpc_action tk_exit, void *calldata) | ||
200 | { | ||
201 | struct rpc_task *task; | ||
202 | |||
203 | if (!(task = rpc_new_task(clnt, tk_exit, RPC_TASK_ASYNC))) | ||
204 | return -ENOMEM; | ||
205 | |||
206 | task->tk_calldata = calldata; | ||
207 | task->tk_action = tk_begin; | ||
208 | rpc_execute(task); | ||
209 | return 0; | ||
190 | } | 210 | } |
191 | 211 | ||
192 | static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags) | 212 | static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags) |
@@ -195,6 +215,7 @@ static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, | |||
195 | 215 | ||
196 | open_flags &= (FMODE_READ|FMODE_WRITE); | 216 | open_flags &= (FMODE_READ|FMODE_WRITE); |
197 | /* Protect against nfs4_find_state() */ | 217 | /* Protect against nfs4_find_state() */ |
218 | spin_lock(&state->owner->so_lock); | ||
198 | spin_lock(&inode->i_lock); | 219 | spin_lock(&inode->i_lock); |
199 | state->state |= open_flags; | 220 | state->state |= open_flags; |
200 | /* NB! List reordering - see the reclaim code for why. */ | 221 | /* NB! List reordering - see the reclaim code for why. */ |
@@ -204,12 +225,12 @@ static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, | |||
204 | state->nreaders++; | 225 | state->nreaders++; |
205 | memcpy(&state->stateid, stateid, sizeof(state->stateid)); | 226 | memcpy(&state->stateid, stateid, sizeof(state->stateid)); |
206 | spin_unlock(&inode->i_lock); | 227 | spin_unlock(&inode->i_lock); |
228 | spin_unlock(&state->owner->so_lock); | ||
207 | } | 229 | } |
208 | 230 | ||
209 | /* | 231 | /* |
210 | * OPEN_RECLAIM: | 232 | * OPEN_RECLAIM: |
211 | * reclaim state on the server after a reboot. | 233 | * reclaim state on the server after a reboot. |
212 | * Assumes caller is holding the sp->so_sem | ||
213 | */ | 234 | */ |
214 | static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state) | 235 | static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state) |
215 | { | 236 | { |
@@ -218,7 +239,6 @@ static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *st | |||
218 | struct nfs_delegation *delegation = NFS_I(inode)->delegation; | 239 | struct nfs_delegation *delegation = NFS_I(inode)->delegation; |
219 | struct nfs_openargs o_arg = { | 240 | struct nfs_openargs o_arg = { |
220 | .fh = NFS_FH(inode), | 241 | .fh = NFS_FH(inode), |
221 | .seqid = sp->so_seqid, | ||
222 | .id = sp->so_id, | 242 | .id = sp->so_id, |
223 | .open_flags = state->state, | 243 | .open_flags = state->state, |
224 | .clientid = server->nfs4_state->cl_clientid, | 244 | .clientid = server->nfs4_state->cl_clientid, |
@@ -245,8 +265,13 @@ static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *st | |||
245 | } | 265 | } |
246 | o_arg.u.delegation_type = delegation->type; | 266 | o_arg.u.delegation_type = delegation->type; |
247 | } | 267 | } |
268 | o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid); | ||
269 | if (o_arg.seqid == NULL) | ||
270 | return -ENOMEM; | ||
248 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); | 271 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); |
249 | nfs4_increment_seqid(status, sp); | 272 | /* Confirm the sequence as being established */ |
273 | nfs_confirm_seqid(&sp->so_seqid, status); | ||
274 | nfs_increment_open_seqid(status, o_arg.seqid); | ||
250 | if (status == 0) { | 275 | if (status == 0) { |
251 | memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid)); | 276 | memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid)); |
252 | if (o_res.delegation_type != 0) { | 277 | if (o_res.delegation_type != 0) { |
@@ -256,6 +281,7 @@ static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *st | |||
256 | nfs_async_inode_return_delegation(inode, &o_res.stateid); | 281 | nfs_async_inode_return_delegation(inode, &o_res.stateid); |
257 | } | 282 | } |
258 | } | 283 | } |
284 | nfs_free_seqid(o_arg.seqid); | ||
259 | clear_bit(NFS_DELEGATED_STATE, &state->flags); | 285 | clear_bit(NFS_DELEGATED_STATE, &state->flags); |
260 | /* Ensure we update the inode attributes */ | 286 | /* Ensure we update the inode attributes */ |
261 | NFS_CACHEINV(inode); | 287 | NFS_CACHEINV(inode); |
@@ -302,23 +328,35 @@ static int _nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state | |||
302 | }; | 328 | }; |
303 | int status = 0; | 329 | int status = 0; |
304 | 330 | ||
305 | down(&sp->so_sema); | ||
306 | if (!test_bit(NFS_DELEGATED_STATE, &state->flags)) | 331 | if (!test_bit(NFS_DELEGATED_STATE, &state->flags)) |
307 | goto out; | 332 | goto out; |
308 | if (state->state == 0) | 333 | if (state->state == 0) |
309 | goto out; | 334 | goto out; |
310 | arg.seqid = sp->so_seqid; | 335 | arg.seqid = nfs_alloc_seqid(&sp->so_seqid); |
336 | status = -ENOMEM; | ||
337 | if (arg.seqid == NULL) | ||
338 | goto out; | ||
311 | arg.open_flags = state->state; | 339 | arg.open_flags = state->state; |
312 | memcpy(arg.u.delegation.data, state->stateid.data, sizeof(arg.u.delegation.data)); | 340 | memcpy(arg.u.delegation.data, state->stateid.data, sizeof(arg.u.delegation.data)); |
313 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); | 341 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); |
314 | nfs4_increment_seqid(status, sp); | 342 | nfs_increment_open_seqid(status, arg.seqid); |
343 | if (status != 0) | ||
344 | goto out_free; | ||
345 | if(res.rflags & NFS4_OPEN_RESULT_CONFIRM) { | ||
346 | status = _nfs4_proc_open_confirm(server->client, NFS_FH(inode), | ||
347 | sp, &res.stateid, arg.seqid); | ||
348 | if (status != 0) | ||
349 | goto out_free; | ||
350 | } | ||
351 | nfs_confirm_seqid(&sp->so_seqid, 0); | ||
315 | if (status >= 0) { | 352 | if (status >= 0) { |
316 | memcpy(state->stateid.data, res.stateid.data, | 353 | memcpy(state->stateid.data, res.stateid.data, |
317 | sizeof(state->stateid.data)); | 354 | sizeof(state->stateid.data)); |
318 | clear_bit(NFS_DELEGATED_STATE, &state->flags); | 355 | clear_bit(NFS_DELEGATED_STATE, &state->flags); |
319 | } | 356 | } |
357 | out_free: | ||
358 | nfs_free_seqid(arg.seqid); | ||
320 | out: | 359 | out: |
321 | up(&sp->so_sema); | ||
322 | dput(parent); | 360 | dput(parent); |
323 | return status; | 361 | return status; |
324 | } | 362 | } |
@@ -345,11 +383,11 @@ int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state) | |||
345 | return err; | 383 | return err; |
346 | } | 384 | } |
347 | 385 | ||
348 | static inline int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid) | 386 | static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid, struct nfs_seqid *seqid) |
349 | { | 387 | { |
350 | struct nfs_open_confirmargs arg = { | 388 | struct nfs_open_confirmargs arg = { |
351 | .fh = fh, | 389 | .fh = fh, |
352 | .seqid = sp->so_seqid, | 390 | .seqid = seqid, |
353 | .stateid = *stateid, | 391 | .stateid = *stateid, |
354 | }; | 392 | }; |
355 | struct nfs_open_confirmres res; | 393 | struct nfs_open_confirmres res; |
@@ -362,7 +400,9 @@ static inline int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nf | |||
362 | int status; | 400 | int status; |
363 | 401 | ||
364 | status = rpc_call_sync(clnt, &msg, RPC_TASK_NOINTR); | 402 | status = rpc_call_sync(clnt, &msg, RPC_TASK_NOINTR); |
365 | nfs4_increment_seqid(status, sp); | 403 | /* Confirm the sequence as being established */ |
404 | nfs_confirm_seqid(&sp->so_seqid, status); | ||
405 | nfs_increment_open_seqid(status, seqid); | ||
366 | if (status >= 0) | 406 | if (status >= 0) |
367 | memcpy(stateid, &res.stateid, sizeof(*stateid)); | 407 | memcpy(stateid, &res.stateid, sizeof(*stateid)); |
368 | return status; | 408 | return status; |
@@ -380,21 +420,41 @@ static int _nfs4_proc_open(struct inode *dir, struct nfs4_state_owner *sp, stru | |||
380 | int status; | 420 | int status; |
381 | 421 | ||
382 | /* Update sequence id. The caller must serialize! */ | 422 | /* Update sequence id. The caller must serialize! */ |
383 | o_arg->seqid = sp->so_seqid; | ||
384 | o_arg->id = sp->so_id; | 423 | o_arg->id = sp->so_id; |
385 | o_arg->clientid = sp->so_client->cl_clientid; | 424 | o_arg->clientid = sp->so_client->cl_clientid; |
386 | 425 | ||
387 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); | 426 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); |
388 | nfs4_increment_seqid(status, sp); | 427 | if (status == 0) { |
428 | /* OPEN on anything except a regular file is disallowed in NFSv4 */ | ||
429 | switch (o_res->f_attr->mode & S_IFMT) { | ||
430 | case S_IFREG: | ||
431 | break; | ||
432 | case S_IFLNK: | ||
433 | status = -ELOOP; | ||
434 | break; | ||
435 | case S_IFDIR: | ||
436 | status = -EISDIR; | ||
437 | break; | ||
438 | default: | ||
439 | status = -ENOTDIR; | ||
440 | } | ||
441 | } | ||
442 | |||
443 | nfs_increment_open_seqid(status, o_arg->seqid); | ||
389 | if (status != 0) | 444 | if (status != 0) |
390 | goto out; | 445 | goto out; |
391 | update_changeattr(dir, &o_res->cinfo); | 446 | if (o_arg->open_flags & O_CREAT) { |
447 | update_changeattr(dir, &o_res->cinfo); | ||
448 | nfs_post_op_update_inode(dir, o_res->dir_attr); | ||
449 | } else | ||
450 | nfs_refresh_inode(dir, o_res->dir_attr); | ||
392 | if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { | 451 | if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { |
393 | status = _nfs4_proc_open_confirm(server->client, &o_res->fh, | 452 | status = _nfs4_proc_open_confirm(server->client, &o_res->fh, |
394 | sp, &o_res->stateid); | 453 | sp, &o_res->stateid, o_arg->seqid); |
395 | if (status != 0) | 454 | if (status != 0) |
396 | goto out; | 455 | goto out; |
397 | } | 456 | } |
457 | nfs_confirm_seqid(&sp->so_seqid, 0); | ||
398 | if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) | 458 | if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) |
399 | status = server->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr); | 459 | status = server->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr); |
400 | out: | 460 | out: |
@@ -441,9 +501,7 @@ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st | |||
441 | struct inode *inode = state->inode; | 501 | struct inode *inode = state->inode; |
442 | struct nfs_server *server = NFS_SERVER(dir); | 502 | struct nfs_server *server = NFS_SERVER(dir); |
443 | struct nfs_delegation *delegation = NFS_I(inode)->delegation; | 503 | struct nfs_delegation *delegation = NFS_I(inode)->delegation; |
444 | struct nfs_fattr f_attr = { | 504 | struct nfs_fattr f_attr, dir_attr; |
445 | .valid = 0, | ||
446 | }; | ||
447 | struct nfs_openargs o_arg = { | 505 | struct nfs_openargs o_arg = { |
448 | .fh = NFS_FH(dir), | 506 | .fh = NFS_FH(dir), |
449 | .open_flags = state->state, | 507 | .open_flags = state->state, |
@@ -453,6 +511,7 @@ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st | |||
453 | }; | 511 | }; |
454 | struct nfs_openres o_res = { | 512 | struct nfs_openres o_res = { |
455 | .f_attr = &f_attr, | 513 | .f_attr = &f_attr, |
514 | .dir_attr = &dir_attr, | ||
456 | .server = server, | 515 | .server = server, |
457 | }; | 516 | }; |
458 | int status = 0; | 517 | int status = 0; |
@@ -465,6 +524,12 @@ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st | |||
465 | set_bit(NFS_DELEGATED_STATE, &state->flags); | 524 | set_bit(NFS_DELEGATED_STATE, &state->flags); |
466 | goto out; | 525 | goto out; |
467 | } | 526 | } |
527 | o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid); | ||
528 | status = -ENOMEM; | ||
529 | if (o_arg.seqid == NULL) | ||
530 | goto out; | ||
531 | nfs_fattr_init(&f_attr); | ||
532 | nfs_fattr_init(&dir_attr); | ||
468 | status = _nfs4_proc_open(dir, sp, &o_arg, &o_res); | 533 | status = _nfs4_proc_open(dir, sp, &o_arg, &o_res); |
469 | if (status != 0) | 534 | if (status != 0) |
470 | goto out_nodeleg; | 535 | goto out_nodeleg; |
@@ -490,6 +555,7 @@ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st | |||
490 | nfs_inode_reclaim_delegation(inode, sp->so_cred, &o_res); | 555 | nfs_inode_reclaim_delegation(inode, sp->so_cred, &o_res); |
491 | } | 556 | } |
492 | out_nodeleg: | 557 | out_nodeleg: |
558 | nfs_free_seqid(o_arg.seqid); | ||
493 | clear_bit(NFS_DELEGATED_STATE, &state->flags); | 559 | clear_bit(NFS_DELEGATED_STATE, &state->flags); |
494 | out: | 560 | out: |
495 | dput(parent); | 561 | dput(parent); |
@@ -564,7 +630,6 @@ static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred | |||
564 | dprintk("%s: nfs4_get_state_owner failed!\n", __FUNCTION__); | 630 | dprintk("%s: nfs4_get_state_owner failed!\n", __FUNCTION__); |
565 | goto out_err; | 631 | goto out_err; |
566 | } | 632 | } |
567 | down(&sp->so_sema); | ||
568 | state = nfs4_get_open_state(inode, sp); | 633 | state = nfs4_get_open_state(inode, sp); |
569 | if (state == NULL) | 634 | if (state == NULL) |
570 | goto out_err; | 635 | goto out_err; |
@@ -589,7 +654,6 @@ static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred | |||
589 | set_bit(NFS_DELEGATED_STATE, &state->flags); | 654 | set_bit(NFS_DELEGATED_STATE, &state->flags); |
590 | update_open_stateid(state, &delegation->stateid, open_flags); | 655 | update_open_stateid(state, &delegation->stateid, open_flags); |
591 | out_ok: | 656 | out_ok: |
592 | up(&sp->so_sema); | ||
593 | nfs4_put_state_owner(sp); | 657 | nfs4_put_state_owner(sp); |
594 | up_read(&nfsi->rwsem); | 658 | up_read(&nfsi->rwsem); |
595 | up_read(&clp->cl_sem); | 659 | up_read(&clp->cl_sem); |
@@ -600,11 +664,12 @@ out_err: | |||
600 | if (sp != NULL) { | 664 | if (sp != NULL) { |
601 | if (state != NULL) | 665 | if (state != NULL) |
602 | nfs4_put_open_state(state); | 666 | nfs4_put_open_state(state); |
603 | up(&sp->so_sema); | ||
604 | nfs4_put_state_owner(sp); | 667 | nfs4_put_state_owner(sp); |
605 | } | 668 | } |
606 | up_read(&nfsi->rwsem); | 669 | up_read(&nfsi->rwsem); |
607 | up_read(&clp->cl_sem); | 670 | up_read(&clp->cl_sem); |
671 | if (err != -EACCES) | ||
672 | nfs_inode_return_delegation(inode); | ||
608 | return err; | 673 | return err; |
609 | } | 674 | } |
610 | 675 | ||
@@ -635,9 +700,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st | |||
635 | struct nfs4_client *clp = server->nfs4_state; | 700 | struct nfs4_client *clp = server->nfs4_state; |
636 | struct inode *inode = NULL; | 701 | struct inode *inode = NULL; |
637 | int status; | 702 | int status; |
638 | struct nfs_fattr f_attr = { | 703 | struct nfs_fattr f_attr, dir_attr; |
639 | .valid = 0, | ||
640 | }; | ||
641 | struct nfs_openargs o_arg = { | 704 | struct nfs_openargs o_arg = { |
642 | .fh = NFS_FH(dir), | 705 | .fh = NFS_FH(dir), |
643 | .open_flags = flags, | 706 | .open_flags = flags, |
@@ -648,6 +711,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st | |||
648 | }; | 711 | }; |
649 | struct nfs_openres o_res = { | 712 | struct nfs_openres o_res = { |
650 | .f_attr = &f_attr, | 713 | .f_attr = &f_attr, |
714 | .dir_attr = &dir_attr, | ||
651 | .server = server, | 715 | .server = server, |
652 | }; | 716 | }; |
653 | 717 | ||
@@ -665,8 +729,12 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st | |||
665 | } else | 729 | } else |
666 | o_arg.u.attrs = sattr; | 730 | o_arg.u.attrs = sattr; |
667 | /* Serialization for the sequence id */ | 731 | /* Serialization for the sequence id */ |
668 | down(&sp->so_sema); | ||
669 | 732 | ||
733 | o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid); | ||
734 | if (o_arg.seqid == NULL) | ||
735 | return -ENOMEM; | ||
736 | nfs_fattr_init(&f_attr); | ||
737 | nfs_fattr_init(&dir_attr); | ||
670 | status = _nfs4_proc_open(dir, sp, &o_arg, &o_res); | 738 | status = _nfs4_proc_open(dir, sp, &o_arg, &o_res); |
671 | if (status != 0) | 739 | if (status != 0) |
672 | goto out_err; | 740 | goto out_err; |
@@ -681,7 +749,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st | |||
681 | update_open_stateid(state, &o_res.stateid, flags); | 749 | update_open_stateid(state, &o_res.stateid, flags); |
682 | if (o_res.delegation_type != 0) | 750 | if (o_res.delegation_type != 0) |
683 | nfs_inode_set_delegation(inode, cred, &o_res); | 751 | nfs_inode_set_delegation(inode, cred, &o_res); |
684 | up(&sp->so_sema); | 752 | nfs_free_seqid(o_arg.seqid); |
685 | nfs4_put_state_owner(sp); | 753 | nfs4_put_state_owner(sp); |
686 | up_read(&clp->cl_sem); | 754 | up_read(&clp->cl_sem); |
687 | *res = state; | 755 | *res = state; |
@@ -690,7 +758,7 @@ out_err: | |||
690 | if (sp != NULL) { | 758 | if (sp != NULL) { |
691 | if (state != NULL) | 759 | if (state != NULL) |
692 | nfs4_put_open_state(state); | 760 | nfs4_put_open_state(state); |
693 | up(&sp->so_sema); | 761 | nfs_free_seqid(o_arg.seqid); |
694 | nfs4_put_state_owner(sp); | 762 | nfs4_put_state_owner(sp); |
695 | } | 763 | } |
696 | /* Note: clp->cl_sem must be released before nfs4_put_open_state()! */ | 764 | /* Note: clp->cl_sem must be released before nfs4_put_open_state()! */ |
@@ -718,7 +786,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, | |||
718 | * It is actually a sign of a bug on the client or on the server. | 786 | * It is actually a sign of a bug on the client or on the server. |
719 | * | 787 | * |
720 | * If we receive a BAD_SEQID error in the particular case of | 788 | * If we receive a BAD_SEQID error in the particular case of |
721 | * doing an OPEN, we assume that nfs4_increment_seqid() will | 789 | * doing an OPEN, we assume that nfs_increment_open_seqid() will |
722 | * have unhashed the old state_owner for us, and that we can | 790 | * have unhashed the old state_owner for us, and that we can |
723 | * therefore safely retry using a new one. We should still warn | 791 | * therefore safely retry using a new one. We should still warn |
724 | * the user though... | 792 | * the user though... |
@@ -728,6 +796,16 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, | |||
728 | exception.retry = 1; | 796 | exception.retry = 1; |
729 | continue; | 797 | continue; |
730 | } | 798 | } |
799 | /* | ||
800 | * BAD_STATEID on OPEN means that the server cancelled our | ||
801 | * state before it received the OPEN_CONFIRM. | ||
802 | * Recover by retrying the request as per the discussion | ||
803 | * on Page 181 of RFC3530. | ||
804 | */ | ||
805 | if (status == -NFS4ERR_BAD_STATEID) { | ||
806 | exception.retry = 1; | ||
807 | continue; | ||
808 | } | ||
731 | res = ERR_PTR(nfs4_handle_exception(NFS_SERVER(dir), | 809 | res = ERR_PTR(nfs4_handle_exception(NFS_SERVER(dir), |
732 | status, &exception)); | 810 | status, &exception)); |
733 | } while (exception.retry); | 811 | } while (exception.retry); |
@@ -755,7 +833,7 @@ static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr, | |||
755 | }; | 833 | }; |
756 | int status; | 834 | int status; |
757 | 835 | ||
758 | fattr->valid = 0; | 836 | nfs_fattr_init(fattr); |
759 | 837 | ||
760 | if (state != NULL) { | 838 | if (state != NULL) { |
761 | msg.rpc_cred = state->owner->so_cred; | 839 | msg.rpc_cred = state->owner->so_cred; |
@@ -787,19 +865,30 @@ struct nfs4_closedata { | |||
787 | struct nfs4_state *state; | 865 | struct nfs4_state *state; |
788 | struct nfs_closeargs arg; | 866 | struct nfs_closeargs arg; |
789 | struct nfs_closeres res; | 867 | struct nfs_closeres res; |
868 | struct nfs_fattr fattr; | ||
790 | }; | 869 | }; |
791 | 870 | ||
871 | static void nfs4_free_closedata(struct nfs4_closedata *calldata) | ||
872 | { | ||
873 | struct nfs4_state *state = calldata->state; | ||
874 | struct nfs4_state_owner *sp = state->owner; | ||
875 | |||
876 | nfs4_put_open_state(calldata->state); | ||
877 | nfs_free_seqid(calldata->arg.seqid); | ||
878 | nfs4_put_state_owner(sp); | ||
879 | kfree(calldata); | ||
880 | } | ||
881 | |||
792 | static void nfs4_close_done(struct rpc_task *task) | 882 | static void nfs4_close_done(struct rpc_task *task) |
793 | { | 883 | { |
794 | struct nfs4_closedata *calldata = (struct nfs4_closedata *)task->tk_calldata; | 884 | struct nfs4_closedata *calldata = (struct nfs4_closedata *)task->tk_calldata; |
795 | struct nfs4_state *state = calldata->state; | 885 | struct nfs4_state *state = calldata->state; |
796 | struct nfs4_state_owner *sp = state->owner; | ||
797 | struct nfs_server *server = NFS_SERVER(calldata->inode); | 886 | struct nfs_server *server = NFS_SERVER(calldata->inode); |
798 | 887 | ||
799 | /* hmm. we are done with the inode, and in the process of freeing | 888 | /* hmm. we are done with the inode, and in the process of freeing |
800 | * the state_owner. we keep this around to process errors | 889 | * the state_owner. we keep this around to process errors |
801 | */ | 890 | */ |
802 | nfs4_increment_seqid(task->tk_status, sp); | 891 | nfs_increment_open_seqid(task->tk_status, calldata->arg.seqid); |
803 | switch (task->tk_status) { | 892 | switch (task->tk_status) { |
804 | case 0: | 893 | case 0: |
805 | memcpy(&state->stateid, &calldata->res.stateid, | 894 | memcpy(&state->stateid, &calldata->res.stateid, |
@@ -816,25 +905,49 @@ static void nfs4_close_done(struct rpc_task *task) | |||
816 | return; | 905 | return; |
817 | } | 906 | } |
818 | } | 907 | } |
908 | nfs_refresh_inode(calldata->inode, calldata->res.fattr); | ||
819 | state->state = calldata->arg.open_flags; | 909 | state->state = calldata->arg.open_flags; |
820 | nfs4_put_open_state(state); | 910 | nfs4_free_closedata(calldata); |
821 | up(&sp->so_sema); | ||
822 | nfs4_put_state_owner(sp); | ||
823 | up_read(&server->nfs4_state->cl_sem); | ||
824 | kfree(calldata); | ||
825 | } | 911 | } |
826 | 912 | ||
827 | static inline int nfs4_close_call(struct rpc_clnt *clnt, struct nfs4_closedata *calldata) | 913 | static void nfs4_close_begin(struct rpc_task *task) |
828 | { | 914 | { |
915 | struct nfs4_closedata *calldata = (struct nfs4_closedata *)task->tk_calldata; | ||
916 | struct nfs4_state *state = calldata->state; | ||
829 | struct rpc_message msg = { | 917 | struct rpc_message msg = { |
830 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE], | 918 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE], |
831 | .rpc_argp = &calldata->arg, | 919 | .rpc_argp = &calldata->arg, |
832 | .rpc_resp = &calldata->res, | 920 | .rpc_resp = &calldata->res, |
833 | .rpc_cred = calldata->state->owner->so_cred, | 921 | .rpc_cred = state->owner->so_cred, |
834 | }; | 922 | }; |
835 | if (calldata->arg.open_flags != 0) | 923 | int mode = 0; |
924 | int status; | ||
925 | |||
926 | status = nfs_wait_on_sequence(calldata->arg.seqid, task); | ||
927 | if (status != 0) | ||
928 | return; | ||
929 | /* Don't reorder reads */ | ||
930 | smp_rmb(); | ||
931 | /* Recalculate the new open mode in case someone reopened the file | ||
932 | * while we were waiting in line to be scheduled. | ||
933 | */ | ||
934 | if (state->nreaders != 0) | ||
935 | mode |= FMODE_READ; | ||
936 | if (state->nwriters != 0) | ||
937 | mode |= FMODE_WRITE; | ||
938 | if (test_bit(NFS_DELEGATED_STATE, &state->flags)) | ||
939 | state->state = mode; | ||
940 | if (mode == state->state) { | ||
941 | nfs4_free_closedata(calldata); | ||
942 | task->tk_exit = NULL; | ||
943 | rpc_exit(task, 0); | ||
944 | return; | ||
945 | } | ||
946 | nfs_fattr_init(calldata->res.fattr); | ||
947 | if (mode != 0) | ||
836 | msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; | 948 | msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; |
837 | return rpc_call_async(clnt, &msg, 0, nfs4_close_done, calldata); | 949 | calldata->arg.open_flags = mode; |
950 | rpc_call_setup(task, &msg, 0); | ||
838 | } | 951 | } |
839 | 952 | ||
840 | /* | 953 | /* |
@@ -850,40 +963,57 @@ static inline int nfs4_close_call(struct rpc_clnt *clnt, struct nfs4_closedata * | |||
850 | */ | 963 | */ |
851 | int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode) | 964 | int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode) |
852 | { | 965 | { |
966 | struct nfs_server *server = NFS_SERVER(inode); | ||
853 | struct nfs4_closedata *calldata; | 967 | struct nfs4_closedata *calldata; |
854 | int status; | 968 | int status = -ENOMEM; |
855 | 969 | ||
856 | /* Tell caller we're done */ | 970 | calldata = kmalloc(sizeof(*calldata), GFP_KERNEL); |
857 | if (test_bit(NFS_DELEGATED_STATE, &state->flags)) { | ||
858 | state->state = mode; | ||
859 | return 0; | ||
860 | } | ||
861 | calldata = (struct nfs4_closedata *)kmalloc(sizeof(*calldata), GFP_KERNEL); | ||
862 | if (calldata == NULL) | 971 | if (calldata == NULL) |
863 | return -ENOMEM; | 972 | goto out; |
864 | calldata->inode = inode; | 973 | calldata->inode = inode; |
865 | calldata->state = state; | 974 | calldata->state = state; |
866 | calldata->arg.fh = NFS_FH(inode); | 975 | calldata->arg.fh = NFS_FH(inode); |
976 | calldata->arg.stateid = &state->stateid; | ||
867 | /* Serialization for the sequence id */ | 977 | /* Serialization for the sequence id */ |
868 | calldata->arg.seqid = state->owner->so_seqid; | 978 | calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid); |
869 | calldata->arg.open_flags = mode; | 979 | if (calldata->arg.seqid == NULL) |
870 | memcpy(&calldata->arg.stateid, &state->stateid, | 980 | goto out_free_calldata; |
871 | sizeof(calldata->arg.stateid)); | 981 | calldata->arg.bitmask = server->attr_bitmask; |
872 | status = nfs4_close_call(NFS_SERVER(inode)->client, calldata); | 982 | calldata->res.fattr = &calldata->fattr; |
873 | /* | 983 | calldata->res.server = server; |
874 | * Return -EINPROGRESS on success in order to indicate to the | 984 | |
875 | * caller that an asynchronous RPC call has been launched, and | 985 | status = nfs4_call_async(server->client, nfs4_close_begin, |
876 | * that it will release the semaphores on completion. | 986 | nfs4_close_done, calldata); |
877 | */ | 987 | if (status == 0) |
878 | return (status == 0) ? -EINPROGRESS : status; | 988 | goto out; |
989 | |||
990 | nfs_free_seqid(calldata->arg.seqid); | ||
991 | out_free_calldata: | ||
992 | kfree(calldata); | ||
993 | out: | ||
994 | return status; | ||
879 | } | 995 | } |
880 | 996 | ||
881 | struct inode * | 997 | static void nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, struct nfs4_state *state) |
998 | { | ||
999 | struct file *filp; | ||
1000 | |||
1001 | filp = lookup_instantiate_filp(nd, dentry, NULL); | ||
1002 | if (!IS_ERR(filp)) { | ||
1003 | struct nfs_open_context *ctx; | ||
1004 | ctx = (struct nfs_open_context *)filp->private_data; | ||
1005 | ctx->state = state; | ||
1006 | } else | ||
1007 | nfs4_close_state(state, nd->intent.open.flags); | ||
1008 | } | ||
1009 | |||
1010 | struct dentry * | ||
882 | nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 1011 | nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) |
883 | { | 1012 | { |
884 | struct iattr attr; | 1013 | struct iattr attr; |
885 | struct rpc_cred *cred; | 1014 | struct rpc_cred *cred; |
886 | struct nfs4_state *state; | 1015 | struct nfs4_state *state; |
1016 | struct dentry *res; | ||
887 | 1017 | ||
888 | if (nd->flags & LOOKUP_CREATE) { | 1018 | if (nd->flags & LOOKUP_CREATE) { |
889 | attr.ia_mode = nd->intent.open.create_mode; | 1019 | attr.ia_mode = nd->intent.open.create_mode; |
@@ -897,16 +1027,23 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | |||
897 | 1027 | ||
898 | cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0); | 1028 | cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0); |
899 | if (IS_ERR(cred)) | 1029 | if (IS_ERR(cred)) |
900 | return (struct inode *)cred; | 1030 | return (struct dentry *)cred; |
901 | state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred); | 1031 | state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred); |
902 | put_rpccred(cred); | 1032 | put_rpccred(cred); |
903 | if (IS_ERR(state)) | 1033 | if (IS_ERR(state)) { |
904 | return (struct inode *)state; | 1034 | if (PTR_ERR(state) == -ENOENT) |
905 | return state->inode; | 1035 | d_add(dentry, NULL); |
1036 | return (struct dentry *)state; | ||
1037 | } | ||
1038 | res = d_add_unique(dentry, state->inode); | ||
1039 | if (res != NULL) | ||
1040 | dentry = res; | ||
1041 | nfs4_intent_set_file(nd, dentry, state); | ||
1042 | return res; | ||
906 | } | 1043 | } |
907 | 1044 | ||
908 | int | 1045 | int |
909 | nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags) | 1046 | nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, struct nameidata *nd) |
910 | { | 1047 | { |
911 | struct rpc_cred *cred; | 1048 | struct rpc_cred *cred; |
912 | struct nfs4_state *state; | 1049 | struct nfs4_state *state; |
@@ -919,18 +1056,30 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags) | |||
919 | if (IS_ERR(state)) | 1056 | if (IS_ERR(state)) |
920 | state = nfs4_do_open(dir, dentry, openflags, NULL, cred); | 1057 | state = nfs4_do_open(dir, dentry, openflags, NULL, cred); |
921 | put_rpccred(cred); | 1058 | put_rpccred(cred); |
922 | if (state == ERR_PTR(-ENOENT) && dentry->d_inode == 0) | 1059 | if (IS_ERR(state)) { |
923 | return 1; | 1060 | switch (PTR_ERR(state)) { |
924 | if (IS_ERR(state)) | 1061 | case -EPERM: |
925 | return 0; | 1062 | case -EACCES: |
1063 | case -EDQUOT: | ||
1064 | case -ENOSPC: | ||
1065 | case -EROFS: | ||
1066 | lookup_instantiate_filp(nd, (struct dentry *)state, NULL); | ||
1067 | return 1; | ||
1068 | case -ENOENT: | ||
1069 | if (dentry->d_inode == NULL) | ||
1070 | return 1; | ||
1071 | } | ||
1072 | goto out_drop; | ||
1073 | } | ||
926 | inode = state->inode; | 1074 | inode = state->inode; |
1075 | iput(inode); | ||
927 | if (inode == dentry->d_inode) { | 1076 | if (inode == dentry->d_inode) { |
928 | iput(inode); | 1077 | nfs4_intent_set_file(nd, dentry, state); |
929 | return 1; | 1078 | return 1; |
930 | } | 1079 | } |
931 | d_drop(dentry); | ||
932 | nfs4_close_state(state, openflags); | 1080 | nfs4_close_state(state, openflags); |
933 | iput(inode); | 1081 | out_drop: |
1082 | d_drop(dentry); | ||
934 | return 0; | 1083 | return 0; |
935 | } | 1084 | } |
936 | 1085 | ||
@@ -974,13 +1123,12 @@ static int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fh | |||
974 | static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | 1123 | static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, |
975 | struct nfs_fsinfo *info) | 1124 | struct nfs_fsinfo *info) |
976 | { | 1125 | { |
977 | struct nfs_fattr * fattr = info->fattr; | ||
978 | struct nfs4_lookup_root_arg args = { | 1126 | struct nfs4_lookup_root_arg args = { |
979 | .bitmask = nfs4_fattr_bitmap, | 1127 | .bitmask = nfs4_fattr_bitmap, |
980 | }; | 1128 | }; |
981 | struct nfs4_lookup_res res = { | 1129 | struct nfs4_lookup_res res = { |
982 | .server = server, | 1130 | .server = server, |
983 | .fattr = fattr, | 1131 | .fattr = info->fattr, |
984 | .fh = fhandle, | 1132 | .fh = fhandle, |
985 | }; | 1133 | }; |
986 | struct rpc_message msg = { | 1134 | struct rpc_message msg = { |
@@ -988,7 +1136,7 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
988 | .rpc_argp = &args, | 1136 | .rpc_argp = &args, |
989 | .rpc_resp = &res, | 1137 | .rpc_resp = &res, |
990 | }; | 1138 | }; |
991 | fattr->valid = 0; | 1139 | nfs_fattr_init(info->fattr); |
992 | return rpc_call_sync(server->client, &msg, 0); | 1140 | return rpc_call_sync(server->client, &msg, 0); |
993 | } | 1141 | } |
994 | 1142 | ||
@@ -1051,7 +1199,7 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
1051 | q.len = p - q.name; | 1199 | q.len = p - q.name; |
1052 | 1200 | ||
1053 | do { | 1201 | do { |
1054 | fattr->valid = 0; | 1202 | nfs_fattr_init(fattr); |
1055 | status = nfs4_handle_exception(server, | 1203 | status = nfs4_handle_exception(server, |
1056 | rpc_call_sync(server->client, &msg, 0), | 1204 | rpc_call_sync(server->client, &msg, 0), |
1057 | &exception); | 1205 | &exception); |
@@ -1088,7 +1236,7 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, | |||
1088 | .rpc_resp = &res, | 1236 | .rpc_resp = &res, |
1089 | }; | 1237 | }; |
1090 | 1238 | ||
1091 | fattr->valid = 0; | 1239 | nfs_fattr_init(fattr); |
1092 | return rpc_call_sync(server->client, &msg, 0); | 1240 | return rpc_call_sync(server->client, &msg, 0); |
1093 | } | 1241 | } |
1094 | 1242 | ||
@@ -1130,7 +1278,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
1130 | struct nfs4_state *state; | 1278 | struct nfs4_state *state; |
1131 | int status; | 1279 | int status; |
1132 | 1280 | ||
1133 | fattr->valid = 0; | 1281 | nfs_fattr_init(fattr); |
1134 | 1282 | ||
1135 | cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0); | 1283 | cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0); |
1136 | if (IS_ERR(cred)) | 1284 | if (IS_ERR(cred)) |
@@ -1176,7 +1324,7 @@ static int _nfs4_proc_lookup(struct inode *dir, struct qstr *name, | |||
1176 | .rpc_resp = &res, | 1324 | .rpc_resp = &res, |
1177 | }; | 1325 | }; |
1178 | 1326 | ||
1179 | fattr->valid = 0; | 1327 | nfs_fattr_init(fattr); |
1180 | 1328 | ||
1181 | dprintk("NFS call lookup %s\n", name->name); | 1329 | dprintk("NFS call lookup %s\n", name->name); |
1182 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 1330 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
@@ -1325,7 +1473,7 @@ static int _nfs4_proc_read(struct nfs_read_data *rdata) | |||
1325 | dprintk("NFS call read %d @ %Ld\n", rdata->args.count, | 1473 | dprintk("NFS call read %d @ %Ld\n", rdata->args.count, |
1326 | (long long) rdata->args.offset); | 1474 | (long long) rdata->args.offset); |
1327 | 1475 | ||
1328 | fattr->valid = 0; | 1476 | nfs_fattr_init(fattr); |
1329 | status = rpc_call_sync(server->client, &msg, flags); | 1477 | status = rpc_call_sync(server->client, &msg, flags); |
1330 | if (!status) | 1478 | if (!status) |
1331 | renew_lease(server, timestamp); | 1479 | renew_lease(server, timestamp); |
@@ -1362,7 +1510,7 @@ static int _nfs4_proc_write(struct nfs_write_data *wdata) | |||
1362 | dprintk("NFS call write %d @ %Ld\n", wdata->args.count, | 1510 | dprintk("NFS call write %d @ %Ld\n", wdata->args.count, |
1363 | (long long) wdata->args.offset); | 1511 | (long long) wdata->args.offset); |
1364 | 1512 | ||
1365 | fattr->valid = 0; | 1513 | nfs_fattr_init(fattr); |
1366 | status = rpc_call_sync(server->client, &msg, rpcflags); | 1514 | status = rpc_call_sync(server->client, &msg, rpcflags); |
1367 | dprintk("NFS reply write: %d\n", status); | 1515 | dprintk("NFS reply write: %d\n", status); |
1368 | return status; | 1516 | return status; |
@@ -1396,7 +1544,7 @@ static int _nfs4_proc_commit(struct nfs_write_data *cdata) | |||
1396 | dprintk("NFS call commit %d @ %Ld\n", cdata->args.count, | 1544 | dprintk("NFS call commit %d @ %Ld\n", cdata->args.count, |
1397 | (long long) cdata->args.offset); | 1545 | (long long) cdata->args.offset); |
1398 | 1546 | ||
1399 | fattr->valid = 0; | 1547 | nfs_fattr_init(fattr); |
1400 | status = rpc_call_sync(server->client, &msg, 0); | 1548 | status = rpc_call_sync(server->client, &msg, 0); |
1401 | dprintk("NFS reply commit: %d\n", status); | 1549 | dprintk("NFS reply commit: %d\n", status); |
1402 | return status; | 1550 | return status; |
@@ -1431,7 +1579,7 @@ static int nfs4_proc_commit(struct nfs_write_data *cdata) | |||
1431 | 1579 | ||
1432 | static int | 1580 | static int |
1433 | nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 1581 | nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
1434 | int flags) | 1582 | int flags, struct nameidata *nd) |
1435 | { | 1583 | { |
1436 | struct nfs4_state *state; | 1584 | struct nfs4_state *state; |
1437 | struct rpc_cred *cred; | 1585 | struct rpc_cred *cred; |
@@ -1453,24 +1601,30 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
1453 | struct nfs_fattr fattr; | 1601 | struct nfs_fattr fattr; |
1454 | status = nfs4_do_setattr(NFS_SERVER(dir), &fattr, | 1602 | status = nfs4_do_setattr(NFS_SERVER(dir), &fattr, |
1455 | NFS_FH(state->inode), sattr, state); | 1603 | NFS_FH(state->inode), sattr, state); |
1456 | if (status == 0) { | 1604 | if (status == 0) |
1457 | nfs_setattr_update_inode(state->inode, sattr); | 1605 | nfs_setattr_update_inode(state->inode, sattr); |
1458 | goto out; | 1606 | } |
1459 | } | 1607 | if (status == 0 && nd != NULL && (nd->flags & LOOKUP_OPEN)) |
1460 | } else if (flags != 0) | 1608 | nfs4_intent_set_file(nd, dentry, state); |
1461 | goto out; | 1609 | else |
1462 | nfs4_close_state(state, flags); | 1610 | nfs4_close_state(state, flags); |
1463 | out: | 1611 | out: |
1464 | return status; | 1612 | return status; |
1465 | } | 1613 | } |
1466 | 1614 | ||
1467 | static int _nfs4_proc_remove(struct inode *dir, struct qstr *name) | 1615 | static int _nfs4_proc_remove(struct inode *dir, struct qstr *name) |
1468 | { | 1616 | { |
1617 | struct nfs_server *server = NFS_SERVER(dir); | ||
1469 | struct nfs4_remove_arg args = { | 1618 | struct nfs4_remove_arg args = { |
1470 | .fh = NFS_FH(dir), | 1619 | .fh = NFS_FH(dir), |
1471 | .name = name, | 1620 | .name = name, |
1621 | .bitmask = server->attr_bitmask, | ||
1622 | }; | ||
1623 | struct nfs_fattr dir_attr; | ||
1624 | struct nfs4_remove_res res = { | ||
1625 | .server = server, | ||
1626 | .dir_attr = &dir_attr, | ||
1472 | }; | 1627 | }; |
1473 | struct nfs4_change_info res; | ||
1474 | struct rpc_message msg = { | 1628 | struct rpc_message msg = { |
1475 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE], | 1629 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE], |
1476 | .rpc_argp = &args, | 1630 | .rpc_argp = &args, |
@@ -1478,9 +1632,12 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name) | |||
1478 | }; | 1632 | }; |
1479 | int status; | 1633 | int status; |
1480 | 1634 | ||
1481 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 1635 | nfs_fattr_init(res.dir_attr); |
1482 | if (status == 0) | 1636 | status = rpc_call_sync(server->client, &msg, 0); |
1483 | update_changeattr(dir, &res); | 1637 | if (status == 0) { |
1638 | update_changeattr(dir, &res.cinfo); | ||
1639 | nfs_post_op_update_inode(dir, res.dir_attr); | ||
1640 | } | ||
1484 | return status; | 1641 | return status; |
1485 | } | 1642 | } |
1486 | 1643 | ||
@@ -1498,12 +1655,14 @@ static int nfs4_proc_remove(struct inode *dir, struct qstr *name) | |||
1498 | 1655 | ||
1499 | struct unlink_desc { | 1656 | struct unlink_desc { |
1500 | struct nfs4_remove_arg args; | 1657 | struct nfs4_remove_arg args; |
1501 | struct nfs4_change_info res; | 1658 | struct nfs4_remove_res res; |
1659 | struct nfs_fattr dir_attr; | ||
1502 | }; | 1660 | }; |
1503 | 1661 | ||
1504 | static int nfs4_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, | 1662 | static int nfs4_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, |
1505 | struct qstr *name) | 1663 | struct qstr *name) |
1506 | { | 1664 | { |
1665 | struct nfs_server *server = NFS_SERVER(dir->d_inode); | ||
1507 | struct unlink_desc *up; | 1666 | struct unlink_desc *up; |
1508 | 1667 | ||
1509 | up = (struct unlink_desc *) kmalloc(sizeof(*up), GFP_KERNEL); | 1668 | up = (struct unlink_desc *) kmalloc(sizeof(*up), GFP_KERNEL); |
@@ -1512,6 +1671,9 @@ static int nfs4_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, | |||
1512 | 1671 | ||
1513 | up->args.fh = NFS_FH(dir->d_inode); | 1672 | up->args.fh = NFS_FH(dir->d_inode); |
1514 | up->args.name = name; | 1673 | up->args.name = name; |
1674 | up->args.bitmask = server->attr_bitmask; | ||
1675 | up->res.server = server; | ||
1676 | up->res.dir_attr = &up->dir_attr; | ||
1515 | 1677 | ||
1516 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; | 1678 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; |
1517 | msg->rpc_argp = &up->args; | 1679 | msg->rpc_argp = &up->args; |
@@ -1526,7 +1688,8 @@ static int nfs4_proc_unlink_done(struct dentry *dir, struct rpc_task *task) | |||
1526 | 1688 | ||
1527 | if (msg->rpc_resp != NULL) { | 1689 | if (msg->rpc_resp != NULL) { |
1528 | up = container_of(msg->rpc_resp, struct unlink_desc, res); | 1690 | up = container_of(msg->rpc_resp, struct unlink_desc, res); |
1529 | update_changeattr(dir->d_inode, &up->res); | 1691 | update_changeattr(dir->d_inode, &up->res.cinfo); |
1692 | nfs_post_op_update_inode(dir->d_inode, up->res.dir_attr); | ||
1530 | kfree(up); | 1693 | kfree(up); |
1531 | msg->rpc_resp = NULL; | 1694 | msg->rpc_resp = NULL; |
1532 | msg->rpc_argp = NULL; | 1695 | msg->rpc_argp = NULL; |
@@ -1537,13 +1700,20 @@ static int nfs4_proc_unlink_done(struct dentry *dir, struct rpc_task *task) | |||
1537 | static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, | 1700 | static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, |
1538 | struct inode *new_dir, struct qstr *new_name) | 1701 | struct inode *new_dir, struct qstr *new_name) |
1539 | { | 1702 | { |
1703 | struct nfs_server *server = NFS_SERVER(old_dir); | ||
1540 | struct nfs4_rename_arg arg = { | 1704 | struct nfs4_rename_arg arg = { |
1541 | .old_dir = NFS_FH(old_dir), | 1705 | .old_dir = NFS_FH(old_dir), |
1542 | .new_dir = NFS_FH(new_dir), | 1706 | .new_dir = NFS_FH(new_dir), |
1543 | .old_name = old_name, | 1707 | .old_name = old_name, |
1544 | .new_name = new_name, | 1708 | .new_name = new_name, |
1709 | .bitmask = server->attr_bitmask, | ||
1710 | }; | ||
1711 | struct nfs_fattr old_fattr, new_fattr; | ||
1712 | struct nfs4_rename_res res = { | ||
1713 | .server = server, | ||
1714 | .old_fattr = &old_fattr, | ||
1715 | .new_fattr = &new_fattr, | ||
1545 | }; | 1716 | }; |
1546 | struct nfs4_rename_res res = { }; | ||
1547 | struct rpc_message msg = { | 1717 | struct rpc_message msg = { |
1548 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME], | 1718 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME], |
1549 | .rpc_argp = &arg, | 1719 | .rpc_argp = &arg, |
@@ -1551,11 +1721,15 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, | |||
1551 | }; | 1721 | }; |
1552 | int status; | 1722 | int status; |
1553 | 1723 | ||
1554 | status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0); | 1724 | nfs_fattr_init(res.old_fattr); |
1725 | nfs_fattr_init(res.new_fattr); | ||
1726 | status = rpc_call_sync(server->client, &msg, 0); | ||
1555 | 1727 | ||
1556 | if (!status) { | 1728 | if (!status) { |
1557 | update_changeattr(old_dir, &res.old_cinfo); | 1729 | update_changeattr(old_dir, &res.old_cinfo); |
1730 | nfs_post_op_update_inode(old_dir, res.old_fattr); | ||
1558 | update_changeattr(new_dir, &res.new_cinfo); | 1731 | update_changeattr(new_dir, &res.new_cinfo); |
1732 | nfs_post_op_update_inode(new_dir, res.new_fattr); | ||
1559 | } | 1733 | } |
1560 | return status; | 1734 | return status; |
1561 | } | 1735 | } |
@@ -1576,22 +1750,34 @@ static int nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, | |||
1576 | 1750 | ||
1577 | static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) | 1751 | static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) |
1578 | { | 1752 | { |
1753 | struct nfs_server *server = NFS_SERVER(inode); | ||
1579 | struct nfs4_link_arg arg = { | 1754 | struct nfs4_link_arg arg = { |
1580 | .fh = NFS_FH(inode), | 1755 | .fh = NFS_FH(inode), |
1581 | .dir_fh = NFS_FH(dir), | 1756 | .dir_fh = NFS_FH(dir), |
1582 | .name = name, | 1757 | .name = name, |
1758 | .bitmask = server->attr_bitmask, | ||
1759 | }; | ||
1760 | struct nfs_fattr fattr, dir_attr; | ||
1761 | struct nfs4_link_res res = { | ||
1762 | .server = server, | ||
1763 | .fattr = &fattr, | ||
1764 | .dir_attr = &dir_attr, | ||
1583 | }; | 1765 | }; |
1584 | struct nfs4_change_info cinfo = { }; | ||
1585 | struct rpc_message msg = { | 1766 | struct rpc_message msg = { |
1586 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK], | 1767 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK], |
1587 | .rpc_argp = &arg, | 1768 | .rpc_argp = &arg, |
1588 | .rpc_resp = &cinfo, | 1769 | .rpc_resp = &res, |
1589 | }; | 1770 | }; |
1590 | int status; | 1771 | int status; |
1591 | 1772 | ||
1592 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); | 1773 | nfs_fattr_init(res.fattr); |
1593 | if (!status) | 1774 | nfs_fattr_init(res.dir_attr); |
1594 | update_changeattr(dir, &cinfo); | 1775 | status = rpc_call_sync(server->client, &msg, 0); |
1776 | if (!status) { | ||
1777 | update_changeattr(dir, &res.cinfo); | ||
1778 | nfs_post_op_update_inode(dir, res.dir_attr); | ||
1779 | nfs_refresh_inode(inode, res.fattr); | ||
1780 | } | ||
1595 | 1781 | ||
1596 | return status; | 1782 | return status; |
1597 | } | 1783 | } |
@@ -1613,6 +1799,7 @@ static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name, | |||
1613 | struct nfs_fattr *fattr) | 1799 | struct nfs_fattr *fattr) |
1614 | { | 1800 | { |
1615 | struct nfs_server *server = NFS_SERVER(dir); | 1801 | struct nfs_server *server = NFS_SERVER(dir); |
1802 | struct nfs_fattr dir_fattr; | ||
1616 | struct nfs4_create_arg arg = { | 1803 | struct nfs4_create_arg arg = { |
1617 | .dir_fh = NFS_FH(dir), | 1804 | .dir_fh = NFS_FH(dir), |
1618 | .server = server, | 1805 | .server = server, |
@@ -1625,6 +1812,7 @@ static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name, | |||
1625 | .server = server, | 1812 | .server = server, |
1626 | .fh = fhandle, | 1813 | .fh = fhandle, |
1627 | .fattr = fattr, | 1814 | .fattr = fattr, |
1815 | .dir_fattr = &dir_fattr, | ||
1628 | }; | 1816 | }; |
1629 | struct rpc_message msg = { | 1817 | struct rpc_message msg = { |
1630 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK], | 1818 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK], |
@@ -1636,11 +1824,13 @@ static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name, | |||
1636 | if (path->len > NFS4_MAXPATHLEN) | 1824 | if (path->len > NFS4_MAXPATHLEN) |
1637 | return -ENAMETOOLONG; | 1825 | return -ENAMETOOLONG; |
1638 | arg.u.symlink = path; | 1826 | arg.u.symlink = path; |
1639 | fattr->valid = 0; | 1827 | nfs_fattr_init(fattr); |
1828 | nfs_fattr_init(&dir_fattr); | ||
1640 | 1829 | ||
1641 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 1830 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
1642 | if (!status) | 1831 | if (!status) |
1643 | update_changeattr(dir, &res.dir_cinfo); | 1832 | update_changeattr(dir, &res.dir_cinfo); |
1833 | nfs_post_op_update_inode(dir, res.dir_fattr); | ||
1644 | return status; | 1834 | return status; |
1645 | } | 1835 | } |
1646 | 1836 | ||
@@ -1664,7 +1854,7 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | |||
1664 | { | 1854 | { |
1665 | struct nfs_server *server = NFS_SERVER(dir); | 1855 | struct nfs_server *server = NFS_SERVER(dir); |
1666 | struct nfs_fh fhandle; | 1856 | struct nfs_fh fhandle; |
1667 | struct nfs_fattr fattr; | 1857 | struct nfs_fattr fattr, dir_fattr; |
1668 | struct nfs4_create_arg arg = { | 1858 | struct nfs4_create_arg arg = { |
1669 | .dir_fh = NFS_FH(dir), | 1859 | .dir_fh = NFS_FH(dir), |
1670 | .server = server, | 1860 | .server = server, |
@@ -1677,6 +1867,7 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | |||
1677 | .server = server, | 1867 | .server = server, |
1678 | .fh = &fhandle, | 1868 | .fh = &fhandle, |
1679 | .fattr = &fattr, | 1869 | .fattr = &fattr, |
1870 | .dir_fattr = &dir_fattr, | ||
1680 | }; | 1871 | }; |
1681 | struct rpc_message msg = { | 1872 | struct rpc_message msg = { |
1682 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE], | 1873 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE], |
@@ -1685,11 +1876,13 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | |||
1685 | }; | 1876 | }; |
1686 | int status; | 1877 | int status; |
1687 | 1878 | ||
1688 | fattr.valid = 0; | 1879 | nfs_fattr_init(&fattr); |
1880 | nfs_fattr_init(&dir_fattr); | ||
1689 | 1881 | ||
1690 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 1882 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
1691 | if (!status) { | 1883 | if (!status) { |
1692 | update_changeattr(dir, &res.dir_cinfo); | 1884 | update_changeattr(dir, &res.dir_cinfo); |
1885 | nfs_post_op_update_inode(dir, res.dir_fattr); | ||
1693 | status = nfs_instantiate(dentry, &fhandle, &fattr); | 1886 | status = nfs_instantiate(dentry, &fhandle, &fattr); |
1694 | } | 1887 | } |
1695 | return status; | 1888 | return status; |
@@ -1762,7 +1955,7 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
1762 | { | 1955 | { |
1763 | struct nfs_server *server = NFS_SERVER(dir); | 1956 | struct nfs_server *server = NFS_SERVER(dir); |
1764 | struct nfs_fh fh; | 1957 | struct nfs_fh fh; |
1765 | struct nfs_fattr fattr; | 1958 | struct nfs_fattr fattr, dir_fattr; |
1766 | struct nfs4_create_arg arg = { | 1959 | struct nfs4_create_arg arg = { |
1767 | .dir_fh = NFS_FH(dir), | 1960 | .dir_fh = NFS_FH(dir), |
1768 | .server = server, | 1961 | .server = server, |
@@ -1774,6 +1967,7 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
1774 | .server = server, | 1967 | .server = server, |
1775 | .fh = &fh, | 1968 | .fh = &fh, |
1776 | .fattr = &fattr, | 1969 | .fattr = &fattr, |
1970 | .dir_fattr = &dir_fattr, | ||
1777 | }; | 1971 | }; |
1778 | struct rpc_message msg = { | 1972 | struct rpc_message msg = { |
1779 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE], | 1973 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE], |
@@ -1783,7 +1977,8 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
1783 | int status; | 1977 | int status; |
1784 | int mode = sattr->ia_mode; | 1978 | int mode = sattr->ia_mode; |
1785 | 1979 | ||
1786 | fattr.valid = 0; | 1980 | nfs_fattr_init(&fattr); |
1981 | nfs_fattr_init(&dir_fattr); | ||
1787 | 1982 | ||
1788 | BUG_ON(!(sattr->ia_valid & ATTR_MODE)); | 1983 | BUG_ON(!(sattr->ia_valid & ATTR_MODE)); |
1789 | BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode)); | 1984 | BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode)); |
@@ -1805,6 +2000,7 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
1805 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 2000 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
1806 | if (status == 0) { | 2001 | if (status == 0) { |
1807 | update_changeattr(dir, &res.dir_cinfo); | 2002 | update_changeattr(dir, &res.dir_cinfo); |
2003 | nfs_post_op_update_inode(dir, res.dir_fattr); | ||
1808 | status = nfs_instantiate(dentry, &fh, &fattr); | 2004 | status = nfs_instantiate(dentry, &fh, &fattr); |
1809 | } | 2005 | } |
1810 | return status; | 2006 | return status; |
@@ -1836,7 +2032,7 @@ static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, | |||
1836 | .rpc_resp = fsstat, | 2032 | .rpc_resp = fsstat, |
1837 | }; | 2033 | }; |
1838 | 2034 | ||
1839 | fsstat->fattr->valid = 0; | 2035 | nfs_fattr_init(fsstat->fattr); |
1840 | return rpc_call_sync(server->client, &msg, 0); | 2036 | return rpc_call_sync(server->client, &msg, 0); |
1841 | } | 2037 | } |
1842 | 2038 | ||
@@ -1883,7 +2079,7 @@ static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, str | |||
1883 | 2079 | ||
1884 | static int nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo) | 2080 | static int nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo) |
1885 | { | 2081 | { |
1886 | fsinfo->fattr->valid = 0; | 2082 | nfs_fattr_init(fsinfo->fattr); |
1887 | return nfs4_do_fsinfo(server, fhandle, fsinfo); | 2083 | return nfs4_do_fsinfo(server, fhandle, fsinfo); |
1888 | } | 2084 | } |
1889 | 2085 | ||
@@ -1906,7 +2102,7 @@ static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle | |||
1906 | return 0; | 2102 | return 0; |
1907 | } | 2103 | } |
1908 | 2104 | ||
1909 | pathconf->fattr->valid = 0; | 2105 | nfs_fattr_init(pathconf->fattr); |
1910 | return rpc_call_sync(server->client, &msg, 0); | 2106 | return rpc_call_sync(server->client, &msg, 0); |
1911 | } | 2107 | } |
1912 | 2108 | ||
@@ -1973,8 +2169,10 @@ nfs4_write_done(struct rpc_task *task) | |||
1973 | rpc_restart_call(task); | 2169 | rpc_restart_call(task); |
1974 | return; | 2170 | return; |
1975 | } | 2171 | } |
1976 | if (task->tk_status >= 0) | 2172 | if (task->tk_status >= 0) { |
1977 | renew_lease(NFS_SERVER(inode), data->timestamp); | 2173 | renew_lease(NFS_SERVER(inode), data->timestamp); |
2174 | nfs_post_op_update_inode(inode, data->res.fattr); | ||
2175 | } | ||
1978 | /* Call back common NFS writeback processing */ | 2176 | /* Call back common NFS writeback processing */ |
1979 | nfs_writeback_done(task); | 2177 | nfs_writeback_done(task); |
1980 | } | 2178 | } |
@@ -1990,6 +2188,7 @@ nfs4_proc_write_setup(struct nfs_write_data *data, int how) | |||
1990 | .rpc_cred = data->cred, | 2188 | .rpc_cred = data->cred, |
1991 | }; | 2189 | }; |
1992 | struct inode *inode = data->inode; | 2190 | struct inode *inode = data->inode; |
2191 | struct nfs_server *server = NFS_SERVER(inode); | ||
1993 | int stable; | 2192 | int stable; |
1994 | int flags; | 2193 | int flags; |
1995 | 2194 | ||
@@ -2001,6 +2200,8 @@ nfs4_proc_write_setup(struct nfs_write_data *data, int how) | |||
2001 | } else | 2200 | } else |
2002 | stable = NFS_UNSTABLE; | 2201 | stable = NFS_UNSTABLE; |
2003 | data->args.stable = stable; | 2202 | data->args.stable = stable; |
2203 | data->args.bitmask = server->attr_bitmask; | ||
2204 | data->res.server = server; | ||
2004 | 2205 | ||
2005 | data->timestamp = jiffies; | 2206 | data->timestamp = jiffies; |
2006 | 2207 | ||
@@ -2022,6 +2223,8 @@ nfs4_commit_done(struct rpc_task *task) | |||
2022 | rpc_restart_call(task); | 2223 | rpc_restart_call(task); |
2023 | return; | 2224 | return; |
2024 | } | 2225 | } |
2226 | if (task->tk_status >= 0) | ||
2227 | nfs_post_op_update_inode(inode, data->res.fattr); | ||
2025 | /* Call back common NFS writeback processing */ | 2228 | /* Call back common NFS writeback processing */ |
2026 | nfs_commit_done(task); | 2229 | nfs_commit_done(task); |
2027 | } | 2230 | } |
@@ -2037,8 +2240,12 @@ nfs4_proc_commit_setup(struct nfs_write_data *data, int how) | |||
2037 | .rpc_cred = data->cred, | 2240 | .rpc_cred = data->cred, |
2038 | }; | 2241 | }; |
2039 | struct inode *inode = data->inode; | 2242 | struct inode *inode = data->inode; |
2243 | struct nfs_server *server = NFS_SERVER(inode); | ||
2040 | int flags; | 2244 | int flags; |
2041 | 2245 | ||
2246 | data->args.bitmask = server->attr_bitmask; | ||
2247 | data->res.server = server; | ||
2248 | |||
2042 | /* Set the initial flags for the task. */ | 2249 | /* Set the initial flags for the task. */ |
2043 | flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; | 2250 | flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; |
2044 | 2251 | ||
@@ -2106,65 +2313,6 @@ nfs4_proc_renew(struct nfs4_client *clp) | |||
2106 | return 0; | 2313 | return 0; |
2107 | } | 2314 | } |
2108 | 2315 | ||
2109 | /* | ||
2110 | * We will need to arrange for the VFS layer to provide an atomic open. | ||
2111 | * Until then, this open method is prone to inefficiency and race conditions | ||
2112 | * due to the lookup, potential create, and open VFS calls from sys_open() | ||
2113 | * placed on the wire. | ||
2114 | */ | ||
2115 | static int | ||
2116 | nfs4_proc_file_open(struct inode *inode, struct file *filp) | ||
2117 | { | ||
2118 | struct dentry *dentry = filp->f_dentry; | ||
2119 | struct nfs_open_context *ctx; | ||
2120 | struct nfs4_state *state = NULL; | ||
2121 | struct rpc_cred *cred; | ||
2122 | int status = -ENOMEM; | ||
2123 | |||
2124 | dprintk("nfs4_proc_file_open: starting on (%.*s/%.*s)\n", | ||
2125 | (int)dentry->d_parent->d_name.len, | ||
2126 | dentry->d_parent->d_name.name, | ||
2127 | (int)dentry->d_name.len, dentry->d_name.name); | ||
2128 | |||
2129 | |||
2130 | /* Find our open stateid */ | ||
2131 | cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0); | ||
2132 | if (IS_ERR(cred)) | ||
2133 | return PTR_ERR(cred); | ||
2134 | ctx = alloc_nfs_open_context(dentry, cred); | ||
2135 | put_rpccred(cred); | ||
2136 | if (unlikely(ctx == NULL)) | ||
2137 | return -ENOMEM; | ||
2138 | status = -EIO; /* ERACE actually */ | ||
2139 | state = nfs4_find_state(inode, cred, filp->f_mode); | ||
2140 | if (unlikely(state == NULL)) | ||
2141 | goto no_state; | ||
2142 | ctx->state = state; | ||
2143 | nfs4_close_state(state, filp->f_mode); | ||
2144 | ctx->mode = filp->f_mode; | ||
2145 | nfs_file_set_open_context(filp, ctx); | ||
2146 | put_nfs_open_context(ctx); | ||
2147 | if (filp->f_mode & FMODE_WRITE) | ||
2148 | nfs_begin_data_update(inode); | ||
2149 | return 0; | ||
2150 | no_state: | ||
2151 | printk(KERN_WARNING "NFS: v4 raced in function %s\n", __FUNCTION__); | ||
2152 | put_nfs_open_context(ctx); | ||
2153 | return status; | ||
2154 | } | ||
2155 | |||
2156 | /* | ||
2157 | * Release our state | ||
2158 | */ | ||
2159 | static int | ||
2160 | nfs4_proc_file_release(struct inode *inode, struct file *filp) | ||
2161 | { | ||
2162 | if (filp->f_mode & FMODE_WRITE) | ||
2163 | nfs_end_data_update(inode); | ||
2164 | nfs_file_clear_open_context(filp); | ||
2165 | return 0; | ||
2166 | } | ||
2167 | |||
2168 | static inline int nfs4_server_supports_acls(struct nfs_server *server) | 2316 | static inline int nfs4_server_supports_acls(struct nfs_server *server) |
2169 | { | 2317 | { |
2170 | return (server->caps & NFS_CAP_ACLS) | 2318 | return (server->caps & NFS_CAP_ACLS) |
@@ -2285,7 +2433,7 @@ static inline ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size | |||
2285 | return -ENOMEM; | 2433 | return -ENOMEM; |
2286 | args.acl_pages[0] = localpage; | 2434 | args.acl_pages[0] = localpage; |
2287 | args.acl_pgbase = 0; | 2435 | args.acl_pgbase = 0; |
2288 | args.acl_len = PAGE_SIZE; | 2436 | resp_len = args.acl_len = PAGE_SIZE; |
2289 | } else { | 2437 | } else { |
2290 | resp_buf = buf; | 2438 | resp_buf = buf; |
2291 | buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase); | 2439 | buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase); |
@@ -2345,6 +2493,7 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen | |||
2345 | 2493 | ||
2346 | if (!nfs4_server_supports_acls(server)) | 2494 | if (!nfs4_server_supports_acls(server)) |
2347 | return -EOPNOTSUPP; | 2495 | return -EOPNOTSUPP; |
2496 | nfs_inode_return_delegation(inode); | ||
2348 | buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase); | 2497 | buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase); |
2349 | ret = rpc_call_sync(NFS_SERVER(inode)->client, &msg, 0); | 2498 | ret = rpc_call_sync(NFS_SERVER(inode)->client, &msg, 0); |
2350 | if (ret == 0) | 2499 | if (ret == 0) |
@@ -2353,7 +2502,7 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen | |||
2353 | } | 2502 | } |
2354 | 2503 | ||
2355 | static int | 2504 | static int |
2356 | nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server) | 2505 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server) |
2357 | { | 2506 | { |
2358 | struct nfs4_client *clp = server->nfs4_state; | 2507 | struct nfs4_client *clp = server->nfs4_state; |
2359 | 2508 | ||
@@ -2431,7 +2580,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) | |||
2431 | /* This is the error handling routine for processes that are allowed | 2580 | /* This is the error handling routine for processes that are allowed |
2432 | * to sleep. | 2581 | * to sleep. |
2433 | */ | 2582 | */ |
2434 | int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception) | 2583 | int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception) |
2435 | { | 2584 | { |
2436 | struct nfs4_client *clp = server->nfs4_state; | 2585 | struct nfs4_client *clp = server->nfs4_state; |
2437 | int ret = errorcode; | 2586 | int ret = errorcode; |
@@ -2632,7 +2781,6 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock | |||
2632 | 2781 | ||
2633 | down_read(&clp->cl_sem); | 2782 | down_read(&clp->cl_sem); |
2634 | nlo.clientid = clp->cl_clientid; | 2783 | nlo.clientid = clp->cl_clientid; |
2635 | down(&state->lock_sema); | ||
2636 | status = nfs4_set_lock_state(state, request); | 2784 | status = nfs4_set_lock_state(state, request); |
2637 | if (status != 0) | 2785 | if (status != 0) |
2638 | goto out; | 2786 | goto out; |
@@ -2659,7 +2807,6 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock | |||
2659 | status = 0; | 2807 | status = 0; |
2660 | } | 2808 | } |
2661 | out: | 2809 | out: |
2662 | up(&state->lock_sema); | ||
2663 | up_read(&clp->cl_sem); | 2810 | up_read(&clp->cl_sem); |
2664 | return status; | 2811 | return status; |
2665 | } | 2812 | } |
@@ -2696,79 +2843,149 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl) | |||
2696 | return res; | 2843 | return res; |
2697 | } | 2844 | } |
2698 | 2845 | ||
2699 | static int _nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request) | 2846 | struct nfs4_unlockdata { |
2847 | struct nfs_lockargs arg; | ||
2848 | struct nfs_locku_opargs luargs; | ||
2849 | struct nfs_lockres res; | ||
2850 | struct nfs4_lock_state *lsp; | ||
2851 | struct nfs_open_context *ctx; | ||
2852 | atomic_t refcount; | ||
2853 | struct completion completion; | ||
2854 | }; | ||
2855 | |||
2856 | static void nfs4_locku_release_calldata(struct nfs4_unlockdata *calldata) | ||
2700 | { | 2857 | { |
2701 | struct inode *inode = state->inode; | 2858 | if (atomic_dec_and_test(&calldata->refcount)) { |
2702 | struct nfs_server *server = NFS_SERVER(inode); | 2859 | nfs_free_seqid(calldata->luargs.seqid); |
2703 | struct nfs4_client *clp = server->nfs4_state; | 2860 | nfs4_put_lock_state(calldata->lsp); |
2704 | struct nfs_lockargs arg = { | 2861 | put_nfs_open_context(calldata->ctx); |
2705 | .fh = NFS_FH(inode), | 2862 | kfree(calldata); |
2706 | .type = nfs4_lck_type(cmd, request), | 2863 | } |
2707 | .offset = request->fl_start, | 2864 | } |
2708 | .length = nfs4_lck_length(request), | 2865 | |
2709 | }; | 2866 | static void nfs4_locku_complete(struct nfs4_unlockdata *calldata) |
2710 | struct nfs_lockres res = { | 2867 | { |
2711 | .server = server, | 2868 | complete(&calldata->completion); |
2712 | }; | 2869 | nfs4_locku_release_calldata(calldata); |
2870 | } | ||
2871 | |||
2872 | static void nfs4_locku_done(struct rpc_task *task) | ||
2873 | { | ||
2874 | struct nfs4_unlockdata *calldata = (struct nfs4_unlockdata *)task->tk_calldata; | ||
2875 | |||
2876 | nfs_increment_lock_seqid(task->tk_status, calldata->luargs.seqid); | ||
2877 | switch (task->tk_status) { | ||
2878 | case 0: | ||
2879 | memcpy(calldata->lsp->ls_stateid.data, | ||
2880 | calldata->res.u.stateid.data, | ||
2881 | sizeof(calldata->lsp->ls_stateid.data)); | ||
2882 | break; | ||
2883 | case -NFS4ERR_STALE_STATEID: | ||
2884 | case -NFS4ERR_EXPIRED: | ||
2885 | nfs4_schedule_state_recovery(calldata->res.server->nfs4_state); | ||
2886 | break; | ||
2887 | default: | ||
2888 | if (nfs4_async_handle_error(task, calldata->res.server) == -EAGAIN) { | ||
2889 | rpc_restart_call(task); | ||
2890 | return; | ||
2891 | } | ||
2892 | } | ||
2893 | nfs4_locku_complete(calldata); | ||
2894 | } | ||
2895 | |||
2896 | static void nfs4_locku_begin(struct rpc_task *task) | ||
2897 | { | ||
2898 | struct nfs4_unlockdata *calldata = (struct nfs4_unlockdata *)task->tk_calldata; | ||
2713 | struct rpc_message msg = { | 2899 | struct rpc_message msg = { |
2714 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKU], | 2900 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKU], |
2715 | .rpc_argp = &arg, | 2901 | .rpc_argp = &calldata->arg, |
2716 | .rpc_resp = &res, | 2902 | .rpc_resp = &calldata->res, |
2717 | .rpc_cred = state->owner->so_cred, | 2903 | .rpc_cred = calldata->lsp->ls_state->owner->so_cred, |
2718 | }; | 2904 | }; |
2905 | int status; | ||
2906 | |||
2907 | status = nfs_wait_on_sequence(calldata->luargs.seqid, task); | ||
2908 | if (status != 0) | ||
2909 | return; | ||
2910 | if ((calldata->lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) { | ||
2911 | nfs4_locku_complete(calldata); | ||
2912 | task->tk_exit = NULL; | ||
2913 | rpc_exit(task, 0); | ||
2914 | return; | ||
2915 | } | ||
2916 | rpc_call_setup(task, &msg, 0); | ||
2917 | } | ||
2918 | |||
2919 | static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request) | ||
2920 | { | ||
2921 | struct nfs4_unlockdata *calldata; | ||
2922 | struct inode *inode = state->inode; | ||
2923 | struct nfs_server *server = NFS_SERVER(inode); | ||
2719 | struct nfs4_lock_state *lsp; | 2924 | struct nfs4_lock_state *lsp; |
2720 | struct nfs_locku_opargs luargs; | ||
2721 | int status; | 2925 | int status; |
2722 | 2926 | ||
2723 | down_read(&clp->cl_sem); | ||
2724 | down(&state->lock_sema); | ||
2725 | status = nfs4_set_lock_state(state, request); | 2927 | status = nfs4_set_lock_state(state, request); |
2726 | if (status != 0) | 2928 | if (status != 0) |
2727 | goto out; | 2929 | return status; |
2728 | lsp = request->fl_u.nfs4_fl.owner; | 2930 | lsp = request->fl_u.nfs4_fl.owner; |
2729 | /* We might have lost the locks! */ | 2931 | /* We might have lost the locks! */ |
2730 | if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) | 2932 | if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) |
2731 | goto out; | 2933 | return 0; |
2732 | luargs.seqid = lsp->ls_seqid; | 2934 | calldata = kmalloc(sizeof(*calldata), GFP_KERNEL); |
2733 | memcpy(&luargs.stateid, &lsp->ls_stateid, sizeof(luargs.stateid)); | 2935 | if (calldata == NULL) |
2734 | arg.u.locku = &luargs; | 2936 | return -ENOMEM; |
2735 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); | 2937 | calldata->luargs.seqid = nfs_alloc_seqid(&lsp->ls_seqid); |
2736 | nfs4_increment_lock_seqid(status, lsp); | 2938 | if (calldata->luargs.seqid == NULL) { |
2737 | 2939 | kfree(calldata); | |
2738 | if (status == 0) | 2940 | return -ENOMEM; |
2739 | memcpy(&lsp->ls_stateid, &res.u.stateid, | 2941 | } |
2740 | sizeof(lsp->ls_stateid)); | 2942 | calldata->luargs.stateid = &lsp->ls_stateid; |
2741 | out: | 2943 | calldata->arg.fh = NFS_FH(inode); |
2742 | up(&state->lock_sema); | 2944 | calldata->arg.type = nfs4_lck_type(cmd, request); |
2945 | calldata->arg.offset = request->fl_start; | ||
2946 | calldata->arg.length = nfs4_lck_length(request); | ||
2947 | calldata->arg.u.locku = &calldata->luargs; | ||
2948 | calldata->res.server = server; | ||
2949 | calldata->lsp = lsp; | ||
2950 | atomic_inc(&lsp->ls_count); | ||
2951 | |||
2952 | /* Ensure we don't close file until we're done freeing locks! */ | ||
2953 | calldata->ctx = get_nfs_open_context((struct nfs_open_context*)request->fl_file->private_data); | ||
2954 | |||
2955 | atomic_set(&calldata->refcount, 2); | ||
2956 | init_completion(&calldata->completion); | ||
2957 | |||
2958 | status = nfs4_call_async(NFS_SERVER(inode)->client, nfs4_locku_begin, | ||
2959 | nfs4_locku_done, calldata); | ||
2743 | if (status == 0) | 2960 | if (status == 0) |
2744 | do_vfs_lock(request->fl_file, request); | 2961 | wait_for_completion_interruptible(&calldata->completion); |
2745 | up_read(&clp->cl_sem); | 2962 | do_vfs_lock(request->fl_file, request); |
2963 | nfs4_locku_release_calldata(calldata); | ||
2746 | return status; | 2964 | return status; |
2747 | } | 2965 | } |
2748 | 2966 | ||
2749 | static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request) | ||
2750 | { | ||
2751 | struct nfs4_exception exception = { }; | ||
2752 | int err; | ||
2753 | |||
2754 | do { | ||
2755 | err = nfs4_handle_exception(NFS_SERVER(state->inode), | ||
2756 | _nfs4_proc_unlck(state, cmd, request), | ||
2757 | &exception); | ||
2758 | } while (exception.retry); | ||
2759 | return err; | ||
2760 | } | ||
2761 | |||
2762 | static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *request, int reclaim) | 2967 | static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *request, int reclaim) |
2763 | { | 2968 | { |
2764 | struct inode *inode = state->inode; | 2969 | struct inode *inode = state->inode; |
2765 | struct nfs_server *server = NFS_SERVER(inode); | 2970 | struct nfs_server *server = NFS_SERVER(inode); |
2766 | struct nfs4_lock_state *lsp = request->fl_u.nfs4_fl.owner; | 2971 | struct nfs4_lock_state *lsp = request->fl_u.nfs4_fl.owner; |
2972 | struct nfs_lock_opargs largs = { | ||
2973 | .lock_stateid = &lsp->ls_stateid, | ||
2974 | .open_stateid = &state->stateid, | ||
2975 | .lock_owner = { | ||
2976 | .clientid = server->nfs4_state->cl_clientid, | ||
2977 | .id = lsp->ls_id, | ||
2978 | }, | ||
2979 | .reclaim = reclaim, | ||
2980 | }; | ||
2767 | struct nfs_lockargs arg = { | 2981 | struct nfs_lockargs arg = { |
2768 | .fh = NFS_FH(inode), | 2982 | .fh = NFS_FH(inode), |
2769 | .type = nfs4_lck_type(cmd, request), | 2983 | .type = nfs4_lck_type(cmd, request), |
2770 | .offset = request->fl_start, | 2984 | .offset = request->fl_start, |
2771 | .length = nfs4_lck_length(request), | 2985 | .length = nfs4_lck_length(request), |
2986 | .u = { | ||
2987 | .lock = &largs, | ||
2988 | }, | ||
2772 | }; | 2989 | }; |
2773 | struct nfs_lockres res = { | 2990 | struct nfs_lockres res = { |
2774 | .server = server, | 2991 | .server = server, |
@@ -2779,53 +2996,39 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *r | |||
2779 | .rpc_resp = &res, | 2996 | .rpc_resp = &res, |
2780 | .rpc_cred = state->owner->so_cred, | 2997 | .rpc_cred = state->owner->so_cred, |
2781 | }; | 2998 | }; |
2782 | struct nfs_lock_opargs largs = { | 2999 | int status = -ENOMEM; |
2783 | .reclaim = reclaim, | ||
2784 | .new_lock_owner = 0, | ||
2785 | }; | ||
2786 | int status; | ||
2787 | 3000 | ||
2788 | if (!(lsp->ls_flags & NFS_LOCK_INITIALIZED)) { | 3001 | largs.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid); |
3002 | if (largs.lock_seqid == NULL) | ||
3003 | return -ENOMEM; | ||
3004 | if (!(lsp->ls_seqid.flags & NFS_SEQID_CONFIRMED)) { | ||
2789 | struct nfs4_state_owner *owner = state->owner; | 3005 | struct nfs4_state_owner *owner = state->owner; |
2790 | struct nfs_open_to_lock otl = { | 3006 | |
2791 | .lock_owner = { | 3007 | largs.open_seqid = nfs_alloc_seqid(&owner->so_seqid); |
2792 | .clientid = server->nfs4_state->cl_clientid, | 3008 | if (largs.open_seqid == NULL) |
2793 | }, | 3009 | goto out; |
2794 | }; | ||
2795 | |||
2796 | otl.lock_seqid = lsp->ls_seqid; | ||
2797 | otl.lock_owner.id = lsp->ls_id; | ||
2798 | memcpy(&otl.open_stateid, &state->stateid, sizeof(otl.open_stateid)); | ||
2799 | largs.u.open_lock = &otl; | ||
2800 | largs.new_lock_owner = 1; | 3010 | largs.new_lock_owner = 1; |
2801 | arg.u.lock = &largs; | ||
2802 | down(&owner->so_sema); | ||
2803 | otl.open_seqid = owner->so_seqid; | ||
2804 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); | 3011 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); |
2805 | /* increment open_owner seqid on success, and | 3012 | /* increment open seqid on success, and seqid mutating errors */ |
2806 | * seqid mutating errors */ | 3013 | if (largs.new_lock_owner != 0) { |
2807 | nfs4_increment_seqid(status, owner); | 3014 | nfs_increment_open_seqid(status, largs.open_seqid); |
2808 | up(&owner->so_sema); | 3015 | if (status == 0) |
2809 | if (status == 0) { | 3016 | nfs_confirm_seqid(&lsp->ls_seqid, 0); |
2810 | lsp->ls_flags |= NFS_LOCK_INITIALIZED; | ||
2811 | lsp->ls_seqid++; | ||
2812 | } | 3017 | } |
2813 | } else { | 3018 | nfs_free_seqid(largs.open_seqid); |
2814 | struct nfs_exist_lock el = { | 3019 | } else |
2815 | .seqid = lsp->ls_seqid, | ||
2816 | }; | ||
2817 | memcpy(&el.stateid, &lsp->ls_stateid, sizeof(el.stateid)); | ||
2818 | largs.u.exist_lock = ⪙ | ||
2819 | arg.u.lock = &largs; | ||
2820 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); | 3020 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); |
2821 | /* increment seqid on success, and * seqid mutating errors*/ | 3021 | /* increment lock seqid on success, and seqid mutating errors*/ |
2822 | nfs4_increment_lock_seqid(status, lsp); | 3022 | nfs_increment_lock_seqid(status, largs.lock_seqid); |
2823 | } | ||
2824 | /* save the returned stateid. */ | 3023 | /* save the returned stateid. */ |
2825 | if (status == 0) | 3024 | if (status == 0) { |
2826 | memcpy(&lsp->ls_stateid, &res.u.stateid, sizeof(nfs4_stateid)); | 3025 | memcpy(lsp->ls_stateid.data, res.u.stateid.data, |
2827 | else if (status == -NFS4ERR_DENIED) | 3026 | sizeof(lsp->ls_stateid.data)); |
3027 | lsp->ls_flags |= NFS_LOCK_INITIALIZED; | ||
3028 | } else if (status == -NFS4ERR_DENIED) | ||
2828 | status = -EAGAIN; | 3029 | status = -EAGAIN; |
3030 | out: | ||
3031 | nfs_free_seqid(largs.lock_seqid); | ||
2829 | return status; | 3032 | return status; |
2830 | } | 3033 | } |
2831 | 3034 | ||
@@ -2865,11 +3068,9 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock | |||
2865 | int status; | 3068 | int status; |
2866 | 3069 | ||
2867 | down_read(&clp->cl_sem); | 3070 | down_read(&clp->cl_sem); |
2868 | down(&state->lock_sema); | ||
2869 | status = nfs4_set_lock_state(state, request); | 3071 | status = nfs4_set_lock_state(state, request); |
2870 | if (status == 0) | 3072 | if (status == 0) |
2871 | status = _nfs4_do_setlk(state, cmd, request, 0); | 3073 | status = _nfs4_do_setlk(state, cmd, request, 0); |
2872 | up(&state->lock_sema); | ||
2873 | if (status == 0) { | 3074 | if (status == 0) { |
2874 | /* Note: we always want to sleep here! */ | 3075 | /* Note: we always want to sleep here! */ |
2875 | request->fl_flags |= FL_SLEEP; | 3076 | request->fl_flags |= FL_SLEEP; |
@@ -3024,8 +3225,8 @@ struct nfs_rpc_ops nfs_v4_clientops = { | |||
3024 | .read_setup = nfs4_proc_read_setup, | 3225 | .read_setup = nfs4_proc_read_setup, |
3025 | .write_setup = nfs4_proc_write_setup, | 3226 | .write_setup = nfs4_proc_write_setup, |
3026 | .commit_setup = nfs4_proc_commit_setup, | 3227 | .commit_setup = nfs4_proc_commit_setup, |
3027 | .file_open = nfs4_proc_file_open, | 3228 | .file_open = nfs_open, |
3028 | .file_release = nfs4_proc_file_release, | 3229 | .file_release = nfs_release, |
3029 | .lock = nfs4_proc_lock, | 3230 | .lock = nfs4_proc_lock, |
3030 | .clear_acl_cache = nfs4_zap_acl_attr, | 3231 | .clear_acl_cache = nfs4_zap_acl_attr, |
3031 | }; | 3232 | }; |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index afe587d82f1e..2d5a6a2b9dec 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -264,13 +264,16 @@ nfs4_alloc_state_owner(void) | |||
264 | { | 264 | { |
265 | struct nfs4_state_owner *sp; | 265 | struct nfs4_state_owner *sp; |
266 | 266 | ||
267 | sp = kmalloc(sizeof(*sp),GFP_KERNEL); | 267 | sp = kzalloc(sizeof(*sp),GFP_KERNEL); |
268 | if (!sp) | 268 | if (!sp) |
269 | return NULL; | 269 | return NULL; |
270 | init_MUTEX(&sp->so_sema); | 270 | spin_lock_init(&sp->so_lock); |
271 | sp->so_seqid = 0; /* arbitrary */ | ||
272 | INIT_LIST_HEAD(&sp->so_states); | 271 | INIT_LIST_HEAD(&sp->so_states); |
273 | INIT_LIST_HEAD(&sp->so_delegations); | 272 | INIT_LIST_HEAD(&sp->so_delegations); |
273 | rpc_init_wait_queue(&sp->so_sequence.wait, "Seqid_waitqueue"); | ||
274 | sp->so_seqid.sequence = &sp->so_sequence; | ||
275 | spin_lock_init(&sp->so_sequence.lock); | ||
276 | INIT_LIST_HEAD(&sp->so_sequence.list); | ||
274 | atomic_set(&sp->so_count, 1); | 277 | atomic_set(&sp->so_count, 1); |
275 | return sp; | 278 | return sp; |
276 | } | 279 | } |
@@ -359,7 +362,6 @@ nfs4_alloc_open_state(void) | |||
359 | memset(state->stateid.data, 0, sizeof(state->stateid.data)); | 362 | memset(state->stateid.data, 0, sizeof(state->stateid.data)); |
360 | atomic_set(&state->count, 1); | 363 | atomic_set(&state->count, 1); |
361 | INIT_LIST_HEAD(&state->lock_states); | 364 | INIT_LIST_HEAD(&state->lock_states); |
362 | init_MUTEX(&state->lock_sema); | ||
363 | spin_lock_init(&state->state_lock); | 365 | spin_lock_init(&state->state_lock); |
364 | return state; | 366 | return state; |
365 | } | 367 | } |
@@ -437,21 +439,23 @@ nfs4_get_open_state(struct inode *inode, struct nfs4_state_owner *owner) | |||
437 | if (state) | 439 | if (state) |
438 | goto out; | 440 | goto out; |
439 | new = nfs4_alloc_open_state(); | 441 | new = nfs4_alloc_open_state(); |
442 | spin_lock(&owner->so_lock); | ||
440 | spin_lock(&inode->i_lock); | 443 | spin_lock(&inode->i_lock); |
441 | state = __nfs4_find_state_byowner(inode, owner); | 444 | state = __nfs4_find_state_byowner(inode, owner); |
442 | if (state == NULL && new != NULL) { | 445 | if (state == NULL && new != NULL) { |
443 | state = new; | 446 | state = new; |
444 | /* Caller *must* be holding owner->so_sem */ | ||
445 | /* Note: The reclaim code dictates that we add stateless | ||
446 | * and read-only stateids to the end of the list */ | ||
447 | list_add_tail(&state->open_states, &owner->so_states); | ||
448 | state->owner = owner; | 447 | state->owner = owner; |
449 | atomic_inc(&owner->so_count); | 448 | atomic_inc(&owner->so_count); |
450 | list_add(&state->inode_states, &nfsi->open_states); | 449 | list_add(&state->inode_states, &nfsi->open_states); |
451 | state->inode = igrab(inode); | 450 | state->inode = igrab(inode); |
452 | spin_unlock(&inode->i_lock); | 451 | spin_unlock(&inode->i_lock); |
452 | /* Note: The reclaim code dictates that we add stateless | ||
453 | * and read-only stateids to the end of the list */ | ||
454 | list_add_tail(&state->open_states, &owner->so_states); | ||
455 | spin_unlock(&owner->so_lock); | ||
453 | } else { | 456 | } else { |
454 | spin_unlock(&inode->i_lock); | 457 | spin_unlock(&inode->i_lock); |
458 | spin_unlock(&owner->so_lock); | ||
455 | if (new) | 459 | if (new) |
456 | nfs4_free_open_state(new); | 460 | nfs4_free_open_state(new); |
457 | } | 461 | } |
@@ -461,19 +465,21 @@ out: | |||
461 | 465 | ||
462 | /* | 466 | /* |
463 | * Beware! Caller must be holding exactly one | 467 | * Beware! Caller must be holding exactly one |
464 | * reference to clp->cl_sem and owner->so_sema! | 468 | * reference to clp->cl_sem! |
465 | */ | 469 | */ |
466 | void nfs4_put_open_state(struct nfs4_state *state) | 470 | void nfs4_put_open_state(struct nfs4_state *state) |
467 | { | 471 | { |
468 | struct inode *inode = state->inode; | 472 | struct inode *inode = state->inode; |
469 | struct nfs4_state_owner *owner = state->owner; | 473 | struct nfs4_state_owner *owner = state->owner; |
470 | 474 | ||
471 | if (!atomic_dec_and_lock(&state->count, &inode->i_lock)) | 475 | if (!atomic_dec_and_lock(&state->count, &owner->so_lock)) |
472 | return; | 476 | return; |
477 | spin_lock(&inode->i_lock); | ||
473 | if (!list_empty(&state->inode_states)) | 478 | if (!list_empty(&state->inode_states)) |
474 | list_del(&state->inode_states); | 479 | list_del(&state->inode_states); |
475 | spin_unlock(&inode->i_lock); | ||
476 | list_del(&state->open_states); | 480 | list_del(&state->open_states); |
481 | spin_unlock(&inode->i_lock); | ||
482 | spin_unlock(&owner->so_lock); | ||
477 | iput(inode); | 483 | iput(inode); |
478 | BUG_ON (state->state != 0); | 484 | BUG_ON (state->state != 0); |
479 | nfs4_free_open_state(state); | 485 | nfs4_free_open_state(state); |
@@ -481,20 +487,17 @@ void nfs4_put_open_state(struct nfs4_state *state) | |||
481 | } | 487 | } |
482 | 488 | ||
483 | /* | 489 | /* |
484 | * Beware! Caller must be holding no references to clp->cl_sem! | 490 | * Close the current file. |
485 | * of owner->so_sema! | ||
486 | */ | 491 | */ |
487 | void nfs4_close_state(struct nfs4_state *state, mode_t mode) | 492 | void nfs4_close_state(struct nfs4_state *state, mode_t mode) |
488 | { | 493 | { |
489 | struct inode *inode = state->inode; | 494 | struct inode *inode = state->inode; |
490 | struct nfs4_state_owner *owner = state->owner; | 495 | struct nfs4_state_owner *owner = state->owner; |
491 | struct nfs4_client *clp = owner->so_client; | ||
492 | int newstate; | 496 | int newstate; |
493 | 497 | ||
494 | atomic_inc(&owner->so_count); | 498 | atomic_inc(&owner->so_count); |
495 | down_read(&clp->cl_sem); | ||
496 | down(&owner->so_sema); | ||
497 | /* Protect against nfs4_find_state() */ | 499 | /* Protect against nfs4_find_state() */ |
500 | spin_lock(&owner->so_lock); | ||
498 | spin_lock(&inode->i_lock); | 501 | spin_lock(&inode->i_lock); |
499 | if (mode & FMODE_READ) | 502 | if (mode & FMODE_READ) |
500 | state->nreaders--; | 503 | state->nreaders--; |
@@ -507,6 +510,7 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode) | |||
507 | list_move_tail(&state->open_states, &owner->so_states); | 510 | list_move_tail(&state->open_states, &owner->so_states); |
508 | } | 511 | } |
509 | spin_unlock(&inode->i_lock); | 512 | spin_unlock(&inode->i_lock); |
513 | spin_unlock(&owner->so_lock); | ||
510 | newstate = 0; | 514 | newstate = 0; |
511 | if (state->state != 0) { | 515 | if (state->state != 0) { |
512 | if (state->nreaders) | 516 | if (state->nreaders) |
@@ -515,14 +519,16 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode) | |||
515 | newstate |= FMODE_WRITE; | 519 | newstate |= FMODE_WRITE; |
516 | if (state->state == newstate) | 520 | if (state->state == newstate) |
517 | goto out; | 521 | goto out; |
518 | if (nfs4_do_close(inode, state, newstate) == -EINPROGRESS) | 522 | if (test_bit(NFS_DELEGATED_STATE, &state->flags)) { |
523 | state->state = newstate; | ||
524 | goto out; | ||
525 | } | ||
526 | if (nfs4_do_close(inode, state, newstate) == 0) | ||
519 | return; | 527 | return; |
520 | } | 528 | } |
521 | out: | 529 | out: |
522 | nfs4_put_open_state(state); | 530 | nfs4_put_open_state(state); |
523 | up(&owner->so_sema); | ||
524 | nfs4_put_state_owner(owner); | 531 | nfs4_put_state_owner(owner); |
525 | up_read(&clp->cl_sem); | ||
526 | } | 532 | } |
527 | 533 | ||
528 | /* | 534 | /* |
@@ -546,19 +552,16 @@ __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) | |||
546 | * Return a compatible lock_state. If no initialized lock_state structure | 552 | * Return a compatible lock_state. If no initialized lock_state structure |
547 | * exists, return an uninitialized one. | 553 | * exists, return an uninitialized one. |
548 | * | 554 | * |
549 | * The caller must be holding state->lock_sema | ||
550 | */ | 555 | */ |
551 | static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) | 556 | static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) |
552 | { | 557 | { |
553 | struct nfs4_lock_state *lsp; | 558 | struct nfs4_lock_state *lsp; |
554 | struct nfs4_client *clp = state->owner->so_client; | 559 | struct nfs4_client *clp = state->owner->so_client; |
555 | 560 | ||
556 | lsp = kmalloc(sizeof(*lsp), GFP_KERNEL); | 561 | lsp = kzalloc(sizeof(*lsp), GFP_KERNEL); |
557 | if (lsp == NULL) | 562 | if (lsp == NULL) |
558 | return NULL; | 563 | return NULL; |
559 | lsp->ls_flags = 0; | 564 | lsp->ls_seqid.sequence = &state->owner->so_sequence; |
560 | lsp->ls_seqid = 0; /* arbitrary */ | ||
561 | memset(lsp->ls_stateid.data, 0, sizeof(lsp->ls_stateid.data)); | ||
562 | atomic_set(&lsp->ls_count, 1); | 565 | atomic_set(&lsp->ls_count, 1); |
563 | lsp->ls_owner = fl_owner; | 566 | lsp->ls_owner = fl_owner; |
564 | spin_lock(&clp->cl_lock); | 567 | spin_lock(&clp->cl_lock); |
@@ -572,7 +575,7 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f | |||
572 | * Return a compatible lock_state. If no initialized lock_state structure | 575 | * Return a compatible lock_state. If no initialized lock_state structure |
573 | * exists, return an uninitialized one. | 576 | * exists, return an uninitialized one. |
574 | * | 577 | * |
575 | * The caller must be holding state->lock_sema and clp->cl_sem | 578 | * The caller must be holding clp->cl_sem |
576 | */ | 579 | */ |
577 | static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner) | 580 | static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner) |
578 | { | 581 | { |
@@ -605,7 +608,7 @@ static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_ | |||
605 | * Release reference to lock_state, and free it if we see that | 608 | * Release reference to lock_state, and free it if we see that |
606 | * it is no longer in use | 609 | * it is no longer in use |
607 | */ | 610 | */ |
608 | static void nfs4_put_lock_state(struct nfs4_lock_state *lsp) | 611 | void nfs4_put_lock_state(struct nfs4_lock_state *lsp) |
609 | { | 612 | { |
610 | struct nfs4_state *state; | 613 | struct nfs4_state *state; |
611 | 614 | ||
@@ -673,29 +676,94 @@ void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t f | |||
673 | nfs4_put_lock_state(lsp); | 676 | nfs4_put_lock_state(lsp); |
674 | } | 677 | } |
675 | 678 | ||
676 | /* | 679 | struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter) |
677 | * Called with state->lock_sema and clp->cl_sem held. | ||
678 | */ | ||
679 | void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *lsp) | ||
680 | { | 680 | { |
681 | if (status == NFS_OK || seqid_mutating_err(-status)) | 681 | struct nfs_seqid *new; |
682 | lsp->ls_seqid++; | 682 | |
683 | new = kmalloc(sizeof(*new), GFP_KERNEL); | ||
684 | if (new != NULL) { | ||
685 | new->sequence = counter; | ||
686 | INIT_LIST_HEAD(&new->list); | ||
687 | } | ||
688 | return new; | ||
689 | } | ||
690 | |||
691 | void nfs_free_seqid(struct nfs_seqid *seqid) | ||
692 | { | ||
693 | struct rpc_sequence *sequence = seqid->sequence->sequence; | ||
694 | |||
695 | if (!list_empty(&seqid->list)) { | ||
696 | spin_lock(&sequence->lock); | ||
697 | list_del(&seqid->list); | ||
698 | spin_unlock(&sequence->lock); | ||
699 | } | ||
700 | rpc_wake_up_next(&sequence->wait); | ||
701 | kfree(seqid); | ||
683 | } | 702 | } |
684 | 703 | ||
685 | /* | 704 | /* |
686 | * Called with sp->so_sema and clp->cl_sem held. | 705 | * Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or |
687 | * | 706 | * failed with a seqid incrementing error - |
688 | * Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or | 707 | * see comments nfs_fs.h:seqid_mutating_error() |
689 | * failed with a seqid incrementing error - | 708 | */ |
690 | * see comments nfs_fs.h:seqid_mutating_error() | 709 | static inline void nfs_increment_seqid(int status, struct nfs_seqid *seqid) |
691 | */ | 710 | { |
692 | void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp) | 711 | switch (status) { |
693 | { | 712 | case 0: |
694 | if (status == NFS_OK || seqid_mutating_err(-status)) | 713 | break; |
695 | sp->so_seqid++; | 714 | case -NFS4ERR_BAD_SEQID: |
696 | /* If the server returns BAD_SEQID, unhash state_owner here */ | 715 | case -NFS4ERR_STALE_CLIENTID: |
697 | if (status == -NFS4ERR_BAD_SEQID) | 716 | case -NFS4ERR_STALE_STATEID: |
717 | case -NFS4ERR_BAD_STATEID: | ||
718 | case -NFS4ERR_BADXDR: | ||
719 | case -NFS4ERR_RESOURCE: | ||
720 | case -NFS4ERR_NOFILEHANDLE: | ||
721 | /* Non-seqid mutating errors */ | ||
722 | return; | ||
723 | }; | ||
724 | /* | ||
725 | * Note: no locking needed as we are guaranteed to be first | ||
726 | * on the sequence list | ||
727 | */ | ||
728 | seqid->sequence->counter++; | ||
729 | } | ||
730 | |||
731 | void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid) | ||
732 | { | ||
733 | if (status == -NFS4ERR_BAD_SEQID) { | ||
734 | struct nfs4_state_owner *sp = container_of(seqid->sequence, | ||
735 | struct nfs4_state_owner, so_seqid); | ||
698 | nfs4_drop_state_owner(sp); | 736 | nfs4_drop_state_owner(sp); |
737 | } | ||
738 | return nfs_increment_seqid(status, seqid); | ||
739 | } | ||
740 | |||
741 | /* | ||
742 | * Increment the seqid if the LOCK/LOCKU succeeded, or | ||
743 | * failed with a seqid incrementing error - | ||
744 | * see comments nfs_fs.h:seqid_mutating_error() | ||
745 | */ | ||
746 | void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid) | ||
747 | { | ||
748 | return nfs_increment_seqid(status, seqid); | ||
749 | } | ||
750 | |||
751 | int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task) | ||
752 | { | ||
753 | struct rpc_sequence *sequence = seqid->sequence->sequence; | ||
754 | int status = 0; | ||
755 | |||
756 | if (sequence->list.next == &seqid->list) | ||
757 | goto out; | ||
758 | spin_lock(&sequence->lock); | ||
759 | if (!list_empty(&sequence->list)) { | ||
760 | rpc_sleep_on(&sequence->wait, task, NULL, NULL); | ||
761 | status = -EAGAIN; | ||
762 | } else | ||
763 | list_add(&seqid->list, &sequence->list); | ||
764 | spin_unlock(&sequence->lock); | ||
765 | out: | ||
766 | return status; | ||
699 | } | 767 | } |
700 | 768 | ||
701 | static int reclaimer(void *); | 769 | static int reclaimer(void *); |
@@ -791,8 +859,6 @@ static int nfs4_reclaim_open_state(struct nfs4_state_recovery_ops *ops, struct n | |||
791 | if (state->state == 0) | 859 | if (state->state == 0) |
792 | continue; | 860 | continue; |
793 | status = ops->recover_open(sp, state); | 861 | status = ops->recover_open(sp, state); |
794 | list_for_each_entry(lock, &state->lock_states, ls_locks) | ||
795 | lock->ls_flags &= ~NFS_LOCK_INITIALIZED; | ||
796 | if (status >= 0) { | 862 | if (status >= 0) { |
797 | status = nfs4_reclaim_locks(ops, state); | 863 | status = nfs4_reclaim_locks(ops, state); |
798 | if (status < 0) | 864 | if (status < 0) |
@@ -831,6 +897,28 @@ out_err: | |||
831 | return status; | 897 | return status; |
832 | } | 898 | } |
833 | 899 | ||
900 | static void nfs4_state_mark_reclaim(struct nfs4_client *clp) | ||
901 | { | ||
902 | struct nfs4_state_owner *sp; | ||
903 | struct nfs4_state *state; | ||
904 | struct nfs4_lock_state *lock; | ||
905 | |||
906 | /* Reset all sequence ids to zero */ | ||
907 | list_for_each_entry(sp, &clp->cl_state_owners, so_list) { | ||
908 | sp->so_seqid.counter = 0; | ||
909 | sp->so_seqid.flags = 0; | ||
910 | spin_lock(&sp->so_lock); | ||
911 | list_for_each_entry(state, &sp->so_states, open_states) { | ||
912 | list_for_each_entry(lock, &state->lock_states, ls_locks) { | ||
913 | lock->ls_seqid.counter = 0; | ||
914 | lock->ls_seqid.flags = 0; | ||
915 | lock->ls_flags &= ~NFS_LOCK_INITIALIZED; | ||
916 | } | ||
917 | } | ||
918 | spin_unlock(&sp->so_lock); | ||
919 | } | ||
920 | } | ||
921 | |||
834 | static int reclaimer(void *ptr) | 922 | static int reclaimer(void *ptr) |
835 | { | 923 | { |
836 | struct reclaimer_args *args = (struct reclaimer_args *)ptr; | 924 | struct reclaimer_args *args = (struct reclaimer_args *)ptr; |
@@ -864,6 +952,7 @@ restart_loop: | |||
864 | default: | 952 | default: |
865 | ops = &nfs4_network_partition_recovery_ops; | 953 | ops = &nfs4_network_partition_recovery_ops; |
866 | }; | 954 | }; |
955 | nfs4_state_mark_reclaim(clp); | ||
867 | status = __nfs4_init_client(clp); | 956 | status = __nfs4_init_client(clp); |
868 | if (status) | 957 | if (status) |
869 | goto out_error; | 958 | goto out_error; |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 6c564ef9489e..fbbace8a30c4 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -95,6 +95,8 @@ static int nfs_stat_to_errno(int); | |||
95 | #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) | 95 | #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) |
96 | #define encode_savefh_maxsz (op_encode_hdr_maxsz) | 96 | #define encode_savefh_maxsz (op_encode_hdr_maxsz) |
97 | #define decode_savefh_maxsz (op_decode_hdr_maxsz) | 97 | #define decode_savefh_maxsz (op_decode_hdr_maxsz) |
98 | #define encode_restorefh_maxsz (op_encode_hdr_maxsz) | ||
99 | #define decode_restorefh_maxsz (op_decode_hdr_maxsz) | ||
98 | #define encode_fsinfo_maxsz (op_encode_hdr_maxsz + 2) | 100 | #define encode_fsinfo_maxsz (op_encode_hdr_maxsz + 2) |
99 | #define decode_fsinfo_maxsz (op_decode_hdr_maxsz + 11) | 101 | #define decode_fsinfo_maxsz (op_decode_hdr_maxsz + 11) |
100 | #define encode_renew_maxsz (op_encode_hdr_maxsz + 3) | 102 | #define encode_renew_maxsz (op_encode_hdr_maxsz + 3) |
@@ -157,16 +159,20 @@ static int nfs_stat_to_errno(int); | |||
157 | op_decode_hdr_maxsz + 2) | 159 | op_decode_hdr_maxsz + 2) |
158 | #define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \ | 160 | #define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \ |
159 | encode_putfh_maxsz + \ | 161 | encode_putfh_maxsz + \ |
160 | op_encode_hdr_maxsz + 8) | 162 | op_encode_hdr_maxsz + 8 + \ |
163 | encode_getattr_maxsz) | ||
161 | #define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \ | 164 | #define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \ |
162 | decode_putfh_maxsz + \ | 165 | decode_putfh_maxsz + \ |
163 | op_decode_hdr_maxsz + 4) | 166 | op_decode_hdr_maxsz + 4 + \ |
167 | decode_getattr_maxsz) | ||
164 | #define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \ | 168 | #define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \ |
165 | encode_putfh_maxsz + \ | 169 | encode_putfh_maxsz + \ |
166 | op_encode_hdr_maxsz + 3) | 170 | op_encode_hdr_maxsz + 3 + \ |
171 | encode_getattr_maxsz) | ||
167 | #define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \ | 172 | #define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \ |
168 | decode_putfh_maxsz + \ | 173 | decode_putfh_maxsz + \ |
169 | op_decode_hdr_maxsz + 2) | 174 | op_decode_hdr_maxsz + 2 + \ |
175 | decode_getattr_maxsz) | ||
170 | #define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \ | 176 | #define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \ |
171 | encode_putfh_maxsz + \ | 177 | encode_putfh_maxsz + \ |
172 | op_encode_hdr_maxsz + \ | 178 | op_encode_hdr_maxsz + \ |
@@ -196,17 +202,21 @@ static int nfs_stat_to_errno(int); | |||
196 | #define NFS4_enc_open_downgrade_sz \ | 202 | #define NFS4_enc_open_downgrade_sz \ |
197 | (compound_encode_hdr_maxsz + \ | 203 | (compound_encode_hdr_maxsz + \ |
198 | encode_putfh_maxsz + \ | 204 | encode_putfh_maxsz + \ |
199 | op_encode_hdr_maxsz + 7) | 205 | op_encode_hdr_maxsz + 7 + \ |
206 | encode_getattr_maxsz) | ||
200 | #define NFS4_dec_open_downgrade_sz \ | 207 | #define NFS4_dec_open_downgrade_sz \ |
201 | (compound_decode_hdr_maxsz + \ | 208 | (compound_decode_hdr_maxsz + \ |
202 | decode_putfh_maxsz + \ | 209 | decode_putfh_maxsz + \ |
203 | op_decode_hdr_maxsz + 4) | 210 | op_decode_hdr_maxsz + 4 + \ |
211 | decode_getattr_maxsz) | ||
204 | #define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \ | 212 | #define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \ |
205 | encode_putfh_maxsz + \ | 213 | encode_putfh_maxsz + \ |
206 | op_encode_hdr_maxsz + 5) | 214 | op_encode_hdr_maxsz + 5 + \ |
215 | encode_getattr_maxsz) | ||
207 | #define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \ | 216 | #define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \ |
208 | decode_putfh_maxsz + \ | 217 | decode_putfh_maxsz + \ |
209 | op_decode_hdr_maxsz + 4) | 218 | op_decode_hdr_maxsz + 4 + \ |
219 | decode_getattr_maxsz) | ||
210 | #define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \ | 220 | #define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \ |
211 | encode_putfh_maxsz + \ | 221 | encode_putfh_maxsz + \ |
212 | op_encode_hdr_maxsz + 4 + \ | 222 | op_encode_hdr_maxsz + 4 + \ |
@@ -300,30 +310,44 @@ static int nfs_stat_to_errno(int); | |||
300 | decode_getfh_maxsz) | 310 | decode_getfh_maxsz) |
301 | #define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \ | 311 | #define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \ |
302 | encode_putfh_maxsz + \ | 312 | encode_putfh_maxsz + \ |
303 | encode_remove_maxsz) | 313 | encode_remove_maxsz + \ |
314 | encode_getattr_maxsz) | ||
304 | #define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \ | 315 | #define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \ |
305 | decode_putfh_maxsz + \ | 316 | decode_putfh_maxsz + \ |
306 | op_decode_hdr_maxsz + 5) | 317 | op_decode_hdr_maxsz + 5 + \ |
318 | decode_getattr_maxsz) | ||
307 | #define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \ | 319 | #define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \ |
308 | encode_putfh_maxsz + \ | 320 | encode_putfh_maxsz + \ |
309 | encode_savefh_maxsz + \ | 321 | encode_savefh_maxsz + \ |
310 | encode_putfh_maxsz + \ | 322 | encode_putfh_maxsz + \ |
311 | encode_rename_maxsz) | 323 | encode_rename_maxsz + \ |
324 | encode_getattr_maxsz + \ | ||
325 | encode_restorefh_maxsz + \ | ||
326 | encode_getattr_maxsz) | ||
312 | #define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \ | 327 | #define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \ |
313 | decode_putfh_maxsz + \ | 328 | decode_putfh_maxsz + \ |
314 | decode_savefh_maxsz + \ | 329 | decode_savefh_maxsz + \ |
315 | decode_putfh_maxsz + \ | 330 | decode_putfh_maxsz + \ |
316 | decode_rename_maxsz) | 331 | decode_rename_maxsz + \ |
332 | decode_getattr_maxsz + \ | ||
333 | decode_restorefh_maxsz + \ | ||
334 | decode_getattr_maxsz) | ||
317 | #define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \ | 335 | #define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \ |
318 | encode_putfh_maxsz + \ | 336 | encode_putfh_maxsz + \ |
319 | encode_savefh_maxsz + \ | 337 | encode_savefh_maxsz + \ |
320 | encode_putfh_maxsz + \ | 338 | encode_putfh_maxsz + \ |
321 | encode_link_maxsz) | 339 | encode_link_maxsz + \ |
340 | decode_getattr_maxsz + \ | ||
341 | encode_restorefh_maxsz + \ | ||
342 | decode_getattr_maxsz) | ||
322 | #define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \ | 343 | #define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \ |
323 | decode_putfh_maxsz + \ | 344 | decode_putfh_maxsz + \ |
324 | decode_savefh_maxsz + \ | 345 | decode_savefh_maxsz + \ |
325 | decode_putfh_maxsz + \ | 346 | decode_putfh_maxsz + \ |
326 | decode_link_maxsz) | 347 | decode_link_maxsz + \ |
348 | decode_getattr_maxsz + \ | ||
349 | decode_restorefh_maxsz + \ | ||
350 | decode_getattr_maxsz) | ||
327 | #define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \ | 351 | #define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \ |
328 | encode_putfh_maxsz + \ | 352 | encode_putfh_maxsz + \ |
329 | encode_symlink_maxsz + \ | 353 | encode_symlink_maxsz + \ |
@@ -336,14 +360,20 @@ static int nfs_stat_to_errno(int); | |||
336 | decode_getfh_maxsz) | 360 | decode_getfh_maxsz) |
337 | #define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \ | 361 | #define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \ |
338 | encode_putfh_maxsz + \ | 362 | encode_putfh_maxsz + \ |
363 | encode_savefh_maxsz + \ | ||
339 | encode_create_maxsz + \ | 364 | encode_create_maxsz + \ |
365 | encode_getfh_maxsz + \ | ||
340 | encode_getattr_maxsz + \ | 366 | encode_getattr_maxsz + \ |
341 | encode_getfh_maxsz) | 367 | encode_restorefh_maxsz + \ |
368 | encode_getattr_maxsz) | ||
342 | #define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \ | 369 | #define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \ |
343 | decode_putfh_maxsz + \ | 370 | decode_putfh_maxsz + \ |
371 | decode_savefh_maxsz + \ | ||
344 | decode_create_maxsz + \ | 372 | decode_create_maxsz + \ |
373 | decode_getfh_maxsz + \ | ||
345 | decode_getattr_maxsz + \ | 374 | decode_getattr_maxsz + \ |
346 | decode_getfh_maxsz) | 375 | decode_restorefh_maxsz + \ |
376 | decode_getattr_maxsz) | ||
347 | #define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \ | 377 | #define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \ |
348 | encode_putfh_maxsz + \ | 378 | encode_putfh_maxsz + \ |
349 | encode_getattr_maxsz) | 379 | encode_getattr_maxsz) |
@@ -602,10 +632,10 @@ static int encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg) | |||
602 | { | 632 | { |
603 | uint32_t *p; | 633 | uint32_t *p; |
604 | 634 | ||
605 | RESERVE_SPACE(8+sizeof(arg->stateid.data)); | 635 | RESERVE_SPACE(8+sizeof(arg->stateid->data)); |
606 | WRITE32(OP_CLOSE); | 636 | WRITE32(OP_CLOSE); |
607 | WRITE32(arg->seqid); | 637 | WRITE32(arg->seqid->sequence->counter); |
608 | WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data)); | 638 | WRITEMEM(arg->stateid->data, sizeof(arg->stateid->data)); |
609 | 639 | ||
610 | return 0; | 640 | return 0; |
611 | } | 641 | } |
@@ -729,22 +759,18 @@ static int encode_lock(struct xdr_stream *xdr, const struct nfs_lockargs *arg) | |||
729 | WRITE64(arg->length); | 759 | WRITE64(arg->length); |
730 | WRITE32(opargs->new_lock_owner); | 760 | WRITE32(opargs->new_lock_owner); |
731 | if (opargs->new_lock_owner){ | 761 | if (opargs->new_lock_owner){ |
732 | struct nfs_open_to_lock *ol = opargs->u.open_lock; | ||
733 | |||
734 | RESERVE_SPACE(40); | 762 | RESERVE_SPACE(40); |
735 | WRITE32(ol->open_seqid); | 763 | WRITE32(opargs->open_seqid->sequence->counter); |
736 | WRITEMEM(&ol->open_stateid, sizeof(ol->open_stateid)); | 764 | WRITEMEM(opargs->open_stateid->data, sizeof(opargs->open_stateid->data)); |
737 | WRITE32(ol->lock_seqid); | 765 | WRITE32(opargs->lock_seqid->sequence->counter); |
738 | WRITE64(ol->lock_owner.clientid); | 766 | WRITE64(opargs->lock_owner.clientid); |
739 | WRITE32(4); | 767 | WRITE32(4); |
740 | WRITE32(ol->lock_owner.id); | 768 | WRITE32(opargs->lock_owner.id); |
741 | } | 769 | } |
742 | else { | 770 | else { |
743 | struct nfs_exist_lock *el = opargs->u.exist_lock; | ||
744 | |||
745 | RESERVE_SPACE(20); | 771 | RESERVE_SPACE(20); |
746 | WRITEMEM(&el->stateid, sizeof(el->stateid)); | 772 | WRITEMEM(opargs->lock_stateid->data, sizeof(opargs->lock_stateid->data)); |
747 | WRITE32(el->seqid); | 773 | WRITE32(opargs->lock_seqid->sequence->counter); |
748 | } | 774 | } |
749 | 775 | ||
750 | return 0; | 776 | return 0; |
@@ -775,8 +801,8 @@ static int encode_locku(struct xdr_stream *xdr, const struct nfs_lockargs *arg) | |||
775 | RESERVE_SPACE(44); | 801 | RESERVE_SPACE(44); |
776 | WRITE32(OP_LOCKU); | 802 | WRITE32(OP_LOCKU); |
777 | WRITE32(arg->type); | 803 | WRITE32(arg->type); |
778 | WRITE32(opargs->seqid); | 804 | WRITE32(opargs->seqid->sequence->counter); |
779 | WRITEMEM(&opargs->stateid, sizeof(opargs->stateid)); | 805 | WRITEMEM(opargs->stateid->data, sizeof(opargs->stateid->data)); |
780 | WRITE64(arg->offset); | 806 | WRITE64(arg->offset); |
781 | WRITE64(arg->length); | 807 | WRITE64(arg->length); |
782 | 808 | ||
@@ -826,7 +852,7 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena | |||
826 | */ | 852 | */ |
827 | RESERVE_SPACE(8); | 853 | RESERVE_SPACE(8); |
828 | WRITE32(OP_OPEN); | 854 | WRITE32(OP_OPEN); |
829 | WRITE32(arg->seqid); | 855 | WRITE32(arg->seqid->sequence->counter); |
830 | encode_share_access(xdr, arg->open_flags); | 856 | encode_share_access(xdr, arg->open_flags); |
831 | RESERVE_SPACE(16); | 857 | RESERVE_SPACE(16); |
832 | WRITE64(arg->clientid); | 858 | WRITE64(arg->clientid); |
@@ -941,7 +967,7 @@ static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_con | |||
941 | RESERVE_SPACE(8+sizeof(arg->stateid.data)); | 967 | RESERVE_SPACE(8+sizeof(arg->stateid.data)); |
942 | WRITE32(OP_OPEN_CONFIRM); | 968 | WRITE32(OP_OPEN_CONFIRM); |
943 | WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data)); | 969 | WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data)); |
944 | WRITE32(arg->seqid); | 970 | WRITE32(arg->seqid->sequence->counter); |
945 | 971 | ||
946 | return 0; | 972 | return 0; |
947 | } | 973 | } |
@@ -950,10 +976,10 @@ static int encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closea | |||
950 | { | 976 | { |
951 | uint32_t *p; | 977 | uint32_t *p; |
952 | 978 | ||
953 | RESERVE_SPACE(8+sizeof(arg->stateid.data)); | 979 | RESERVE_SPACE(8+sizeof(arg->stateid->data)); |
954 | WRITE32(OP_OPEN_DOWNGRADE); | 980 | WRITE32(OP_OPEN_DOWNGRADE); |
955 | WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data)); | 981 | WRITEMEM(arg->stateid->data, sizeof(arg->stateid->data)); |
956 | WRITE32(arg->seqid); | 982 | WRITE32(arg->seqid->sequence->counter); |
957 | encode_share_access(xdr, arg->open_flags); | 983 | encode_share_access(xdr, arg->open_flags); |
958 | return 0; | 984 | return 0; |
959 | } | 985 | } |
@@ -1117,6 +1143,17 @@ static int encode_renew(struct xdr_stream *xdr, const struct nfs4_client *client | |||
1117 | } | 1143 | } |
1118 | 1144 | ||
1119 | static int | 1145 | static int |
1146 | encode_restorefh(struct xdr_stream *xdr) | ||
1147 | { | ||
1148 | uint32_t *p; | ||
1149 | |||
1150 | RESERVE_SPACE(4); | ||
1151 | WRITE32(OP_RESTOREFH); | ||
1152 | |||
1153 | return 0; | ||
1154 | } | ||
1155 | |||
1156 | static int | ||
1120 | encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg) | 1157 | encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg) |
1121 | { | 1158 | { |
1122 | uint32_t *p; | 1159 | uint32_t *p; |
@@ -1296,14 +1333,18 @@ static int nfs4_xdr_enc_remove(struct rpc_rqst *req, uint32_t *p, const struct n | |||
1296 | { | 1333 | { |
1297 | struct xdr_stream xdr; | 1334 | struct xdr_stream xdr; |
1298 | struct compound_hdr hdr = { | 1335 | struct compound_hdr hdr = { |
1299 | .nops = 2, | 1336 | .nops = 3, |
1300 | }; | 1337 | }; |
1301 | int status; | 1338 | int status; |
1302 | 1339 | ||
1303 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | 1340 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); |
1304 | encode_compound_hdr(&xdr, &hdr); | 1341 | encode_compound_hdr(&xdr, &hdr); |
1305 | if ((status = encode_putfh(&xdr, args->fh)) == 0) | 1342 | if ((status = encode_putfh(&xdr, args->fh)) != 0) |
1306 | status = encode_remove(&xdr, args->name); | 1343 | goto out; |
1344 | if ((status = encode_remove(&xdr, args->name)) != 0) | ||
1345 | goto out; | ||
1346 | status = encode_getfattr(&xdr, args->bitmask); | ||
1347 | out: | ||
1307 | return status; | 1348 | return status; |
1308 | } | 1349 | } |
1309 | 1350 | ||
@@ -1314,7 +1355,7 @@ static int nfs4_xdr_enc_rename(struct rpc_rqst *req, uint32_t *p, const struct n | |||
1314 | { | 1355 | { |
1315 | struct xdr_stream xdr; | 1356 | struct xdr_stream xdr; |
1316 | struct compound_hdr hdr = { | 1357 | struct compound_hdr hdr = { |
1317 | .nops = 4, | 1358 | .nops = 7, |
1318 | }; | 1359 | }; |
1319 | int status; | 1360 | int status; |
1320 | 1361 | ||
@@ -1326,7 +1367,13 @@ static int nfs4_xdr_enc_rename(struct rpc_rqst *req, uint32_t *p, const struct n | |||
1326 | goto out; | 1367 | goto out; |
1327 | if ((status = encode_putfh(&xdr, args->new_dir)) != 0) | 1368 | if ((status = encode_putfh(&xdr, args->new_dir)) != 0) |
1328 | goto out; | 1369 | goto out; |
1329 | status = encode_rename(&xdr, args->old_name, args->new_name); | 1370 | if ((status = encode_rename(&xdr, args->old_name, args->new_name)) != 0) |
1371 | goto out; | ||
1372 | if ((status = encode_getfattr(&xdr, args->bitmask)) != 0) | ||
1373 | goto out; | ||
1374 | if ((status = encode_restorefh(&xdr)) != 0) | ||
1375 | goto out; | ||
1376 | status = encode_getfattr(&xdr, args->bitmask); | ||
1330 | out: | 1377 | out: |
1331 | return status; | 1378 | return status; |
1332 | } | 1379 | } |
@@ -1338,7 +1385,7 @@ static int nfs4_xdr_enc_link(struct rpc_rqst *req, uint32_t *p, const struct nfs | |||
1338 | { | 1385 | { |
1339 | struct xdr_stream xdr; | 1386 | struct xdr_stream xdr; |
1340 | struct compound_hdr hdr = { | 1387 | struct compound_hdr hdr = { |
1341 | .nops = 4, | 1388 | .nops = 7, |
1342 | }; | 1389 | }; |
1343 | int status; | 1390 | int status; |
1344 | 1391 | ||
@@ -1350,7 +1397,13 @@ static int nfs4_xdr_enc_link(struct rpc_rqst *req, uint32_t *p, const struct nfs | |||
1350 | goto out; | 1397 | goto out; |
1351 | if ((status = encode_putfh(&xdr, args->dir_fh)) != 0) | 1398 | if ((status = encode_putfh(&xdr, args->dir_fh)) != 0) |
1352 | goto out; | 1399 | goto out; |
1353 | status = encode_link(&xdr, args->name); | 1400 | if ((status = encode_link(&xdr, args->name)) != 0) |
1401 | goto out; | ||
1402 | if ((status = encode_getfattr(&xdr, args->bitmask)) != 0) | ||
1403 | goto out; | ||
1404 | if ((status = encode_restorefh(&xdr)) != 0) | ||
1405 | goto out; | ||
1406 | status = encode_getfattr(&xdr, args->bitmask); | ||
1354 | out: | 1407 | out: |
1355 | return status; | 1408 | return status; |
1356 | } | 1409 | } |
@@ -1362,7 +1415,7 @@ static int nfs4_xdr_enc_create(struct rpc_rqst *req, uint32_t *p, const struct n | |||
1362 | { | 1415 | { |
1363 | struct xdr_stream xdr; | 1416 | struct xdr_stream xdr; |
1364 | struct compound_hdr hdr = { | 1417 | struct compound_hdr hdr = { |
1365 | .nops = 4, | 1418 | .nops = 7, |
1366 | }; | 1419 | }; |
1367 | int status; | 1420 | int status; |
1368 | 1421 | ||
@@ -1370,10 +1423,16 @@ static int nfs4_xdr_enc_create(struct rpc_rqst *req, uint32_t *p, const struct n | |||
1370 | encode_compound_hdr(&xdr, &hdr); | 1423 | encode_compound_hdr(&xdr, &hdr); |
1371 | if ((status = encode_putfh(&xdr, args->dir_fh)) != 0) | 1424 | if ((status = encode_putfh(&xdr, args->dir_fh)) != 0) |
1372 | goto out; | 1425 | goto out; |
1426 | if ((status = encode_savefh(&xdr)) != 0) | ||
1427 | goto out; | ||
1373 | if ((status = encode_create(&xdr, args)) != 0) | 1428 | if ((status = encode_create(&xdr, args)) != 0) |
1374 | goto out; | 1429 | goto out; |
1375 | if ((status = encode_getfh(&xdr)) != 0) | 1430 | if ((status = encode_getfh(&xdr)) != 0) |
1376 | goto out; | 1431 | goto out; |
1432 | if ((status = encode_getfattr(&xdr, args->bitmask)) != 0) | ||
1433 | goto out; | ||
1434 | if ((status = encode_restorefh(&xdr)) != 0) | ||
1435 | goto out; | ||
1377 | status = encode_getfattr(&xdr, args->bitmask); | 1436 | status = encode_getfattr(&xdr, args->bitmask); |
1378 | out: | 1437 | out: |
1379 | return status; | 1438 | return status; |
@@ -1412,7 +1471,7 @@ static int nfs4_xdr_enc_close(struct rpc_rqst *req, uint32_t *p, struct nfs_clos | |||
1412 | { | 1471 | { |
1413 | struct xdr_stream xdr; | 1472 | struct xdr_stream xdr; |
1414 | struct compound_hdr hdr = { | 1473 | struct compound_hdr hdr = { |
1415 | .nops = 2, | 1474 | .nops = 3, |
1416 | }; | 1475 | }; |
1417 | int status; | 1476 | int status; |
1418 | 1477 | ||
@@ -1422,6 +1481,9 @@ static int nfs4_xdr_enc_close(struct rpc_rqst *req, uint32_t *p, struct nfs_clos | |||
1422 | if(status) | 1481 | if(status) |
1423 | goto out; | 1482 | goto out; |
1424 | status = encode_close(&xdr, args); | 1483 | status = encode_close(&xdr, args); |
1484 | if (status != 0) | ||
1485 | goto out; | ||
1486 | status = encode_getfattr(&xdr, args->bitmask); | ||
1425 | out: | 1487 | out: |
1426 | return status; | 1488 | return status; |
1427 | } | 1489 | } |
@@ -1433,15 +1495,21 @@ static int nfs4_xdr_enc_open(struct rpc_rqst *req, uint32_t *p, struct nfs_opena | |||
1433 | { | 1495 | { |
1434 | struct xdr_stream xdr; | 1496 | struct xdr_stream xdr; |
1435 | struct compound_hdr hdr = { | 1497 | struct compound_hdr hdr = { |
1436 | .nops = 4, | 1498 | .nops = 7, |
1437 | }; | 1499 | }; |
1438 | int status; | 1500 | int status; |
1439 | 1501 | ||
1502 | status = nfs_wait_on_sequence(args->seqid, req->rq_task); | ||
1503 | if (status != 0) | ||
1504 | goto out; | ||
1440 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | 1505 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); |
1441 | encode_compound_hdr(&xdr, &hdr); | 1506 | encode_compound_hdr(&xdr, &hdr); |
1442 | status = encode_putfh(&xdr, args->fh); | 1507 | status = encode_putfh(&xdr, args->fh); |
1443 | if (status) | 1508 | if (status) |
1444 | goto out; | 1509 | goto out; |
1510 | status = encode_savefh(&xdr); | ||
1511 | if (status) | ||
1512 | goto out; | ||
1445 | status = encode_open(&xdr, args); | 1513 | status = encode_open(&xdr, args); |
1446 | if (status) | 1514 | if (status) |
1447 | goto out; | 1515 | goto out; |
@@ -1449,6 +1517,12 @@ static int nfs4_xdr_enc_open(struct rpc_rqst *req, uint32_t *p, struct nfs_opena | |||
1449 | if (status) | 1517 | if (status) |
1450 | goto out; | 1518 | goto out; |
1451 | status = encode_getfattr(&xdr, args->bitmask); | 1519 | status = encode_getfattr(&xdr, args->bitmask); |
1520 | if (status) | ||
1521 | goto out; | ||
1522 | status = encode_restorefh(&xdr); | ||
1523 | if (status) | ||
1524 | goto out; | ||
1525 | status = encode_getfattr(&xdr, args->bitmask); | ||
1452 | out: | 1526 | out: |
1453 | return status; | 1527 | return status; |
1454 | } | 1528 | } |
@@ -1464,6 +1538,9 @@ static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, uint32_t *p, struct n | |||
1464 | }; | 1538 | }; |
1465 | int status; | 1539 | int status; |
1466 | 1540 | ||
1541 | status = nfs_wait_on_sequence(args->seqid, req->rq_task); | ||
1542 | if (status != 0) | ||
1543 | goto out; | ||
1467 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | 1544 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); |
1468 | encode_compound_hdr(&xdr, &hdr); | 1545 | encode_compound_hdr(&xdr, &hdr); |
1469 | status = encode_putfh(&xdr, args->fh); | 1546 | status = encode_putfh(&xdr, args->fh); |
@@ -1485,6 +1562,9 @@ static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, uint32_t *p, struct nf | |||
1485 | }; | 1562 | }; |
1486 | int status; | 1563 | int status; |
1487 | 1564 | ||
1565 | status = nfs_wait_on_sequence(args->seqid, req->rq_task); | ||
1566 | if (status != 0) | ||
1567 | goto out; | ||
1488 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | 1568 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); |
1489 | encode_compound_hdr(&xdr, &hdr); | 1569 | encode_compound_hdr(&xdr, &hdr); |
1490 | status = encode_putfh(&xdr, args->fh); | 1570 | status = encode_putfh(&xdr, args->fh); |
@@ -1502,7 +1582,7 @@ static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, uint32_t *p, struct | |||
1502 | { | 1582 | { |
1503 | struct xdr_stream xdr; | 1583 | struct xdr_stream xdr; |
1504 | struct compound_hdr hdr = { | 1584 | struct compound_hdr hdr = { |
1505 | .nops = 2, | 1585 | .nops = 3, |
1506 | }; | 1586 | }; |
1507 | int status; | 1587 | int status; |
1508 | 1588 | ||
@@ -1512,6 +1592,9 @@ static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, uint32_t *p, struct | |||
1512 | if (status) | 1592 | if (status) |
1513 | goto out; | 1593 | goto out; |
1514 | status = encode_open_downgrade(&xdr, args); | 1594 | status = encode_open_downgrade(&xdr, args); |
1595 | if (status != 0) | ||
1596 | goto out; | ||
1597 | status = encode_getfattr(&xdr, args->bitmask); | ||
1515 | out: | 1598 | out: |
1516 | return status; | 1599 | return status; |
1517 | } | 1600 | } |
@@ -1525,8 +1608,15 @@ static int nfs4_xdr_enc_lock(struct rpc_rqst *req, uint32_t *p, struct nfs_locka | |||
1525 | struct compound_hdr hdr = { | 1608 | struct compound_hdr hdr = { |
1526 | .nops = 2, | 1609 | .nops = 2, |
1527 | }; | 1610 | }; |
1611 | struct nfs_lock_opargs *opargs = args->u.lock; | ||
1528 | int status; | 1612 | int status; |
1529 | 1613 | ||
1614 | status = nfs_wait_on_sequence(opargs->lock_seqid, req->rq_task); | ||
1615 | if (status != 0) | ||
1616 | goto out; | ||
1617 | /* Do we need to do an open_to_lock_owner? */ | ||
1618 | if (opargs->lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED) | ||
1619 | opargs->new_lock_owner = 0; | ||
1530 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | 1620 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); |
1531 | encode_compound_hdr(&xdr, &hdr); | 1621 | encode_compound_hdr(&xdr, &hdr); |
1532 | status = encode_putfh(&xdr, args->fh); | 1622 | status = encode_putfh(&xdr, args->fh); |
@@ -1713,7 +1803,7 @@ static int nfs4_xdr_enc_write(struct rpc_rqst *req, uint32_t *p, struct nfs_writ | |||
1713 | { | 1803 | { |
1714 | struct xdr_stream xdr; | 1804 | struct xdr_stream xdr; |
1715 | struct compound_hdr hdr = { | 1805 | struct compound_hdr hdr = { |
1716 | .nops = 2, | 1806 | .nops = 3, |
1717 | }; | 1807 | }; |
1718 | int status; | 1808 | int status; |
1719 | 1809 | ||
@@ -1723,6 +1813,9 @@ static int nfs4_xdr_enc_write(struct rpc_rqst *req, uint32_t *p, struct nfs_writ | |||
1723 | if (status) | 1813 | if (status) |
1724 | goto out; | 1814 | goto out; |
1725 | status = encode_write(&xdr, args); | 1815 | status = encode_write(&xdr, args); |
1816 | if (status) | ||
1817 | goto out; | ||
1818 | status = encode_getfattr(&xdr, args->bitmask); | ||
1726 | out: | 1819 | out: |
1727 | return status; | 1820 | return status; |
1728 | } | 1821 | } |
@@ -1734,7 +1827,7 @@ static int nfs4_xdr_enc_commit(struct rpc_rqst *req, uint32_t *p, struct nfs_wri | |||
1734 | { | 1827 | { |
1735 | struct xdr_stream xdr; | 1828 | struct xdr_stream xdr; |
1736 | struct compound_hdr hdr = { | 1829 | struct compound_hdr hdr = { |
1737 | .nops = 2, | 1830 | .nops = 3, |
1738 | }; | 1831 | }; |
1739 | int status; | 1832 | int status; |
1740 | 1833 | ||
@@ -1744,6 +1837,9 @@ static int nfs4_xdr_enc_commit(struct rpc_rqst *req, uint32_t *p, struct nfs_wri | |||
1744 | if (status) | 1837 | if (status) |
1745 | goto out; | 1838 | goto out; |
1746 | status = encode_commit(&xdr, args); | 1839 | status = encode_commit(&xdr, args); |
1840 | if (status) | ||
1841 | goto out; | ||
1842 | status = encode_getfattr(&xdr, args->bitmask); | ||
1747 | out: | 1843 | out: |
1748 | return status; | 1844 | return status; |
1749 | } | 1845 | } |
@@ -2670,8 +2766,7 @@ static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_re | |||
2670 | goto xdr_error; | 2766 | goto xdr_error; |
2671 | status = verify_attr_len(xdr, savep, attrlen); | 2767 | status = verify_attr_len(xdr, savep, attrlen); |
2672 | xdr_error: | 2768 | xdr_error: |
2673 | if (status != 0) | 2769 | dprintk("%s: xdr returned %d!\n", __FUNCTION__, -status); |
2674 | printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status); | ||
2675 | return status; | 2770 | return status; |
2676 | } | 2771 | } |
2677 | 2772 | ||
@@ -2704,8 +2799,7 @@ static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat) | |||
2704 | 2799 | ||
2705 | status = verify_attr_len(xdr, savep, attrlen); | 2800 | status = verify_attr_len(xdr, savep, attrlen); |
2706 | xdr_error: | 2801 | xdr_error: |
2707 | if (status != 0) | 2802 | dprintk("%s: xdr returned %d!\n", __FUNCTION__, -status); |
2708 | printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status); | ||
2709 | return status; | 2803 | return status; |
2710 | } | 2804 | } |
2711 | 2805 | ||
@@ -2730,8 +2824,7 @@ static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf | |||
2730 | 2824 | ||
2731 | status = verify_attr_len(xdr, savep, attrlen); | 2825 | status = verify_attr_len(xdr, savep, attrlen); |
2732 | xdr_error: | 2826 | xdr_error: |
2733 | if (status != 0) | 2827 | dprintk("%s: xdr returned %d!\n", __FUNCTION__, -status); |
2734 | printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status); | ||
2735 | return status; | 2828 | return status; |
2736 | } | 2829 | } |
2737 | 2830 | ||
@@ -2787,13 +2880,10 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons | |||
2787 | goto xdr_error; | 2880 | goto xdr_error; |
2788 | if ((status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime)) != 0) | 2881 | if ((status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime)) != 0) |
2789 | goto xdr_error; | 2882 | goto xdr_error; |
2790 | if ((status = verify_attr_len(xdr, savep, attrlen)) == 0) { | 2883 | if ((status = verify_attr_len(xdr, savep, attrlen)) == 0) |
2791 | fattr->valid = NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4; | 2884 | fattr->valid = NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4; |
2792 | fattr->timestamp = jiffies; | ||
2793 | } | ||
2794 | xdr_error: | 2885 | xdr_error: |
2795 | if (status != 0) | 2886 | dprintk("%s: xdr returned %d\n", __FUNCTION__, -status); |
2796 | printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status); | ||
2797 | return status; | 2887 | return status; |
2798 | } | 2888 | } |
2799 | 2889 | ||
@@ -2826,8 +2916,7 @@ static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) | |||
2826 | 2916 | ||
2827 | status = verify_attr_len(xdr, savep, attrlen); | 2917 | status = verify_attr_len(xdr, savep, attrlen); |
2828 | xdr_error: | 2918 | xdr_error: |
2829 | if (status != 0) | 2919 | dprintk("%s: xdr returned %d!\n", __FUNCTION__, -status); |
2830 | printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status); | ||
2831 | return status; | 2920 | return status; |
2832 | } | 2921 | } |
2833 | 2922 | ||
@@ -2890,8 +2979,8 @@ static int decode_lock(struct xdr_stream *xdr, struct nfs_lockres *res) | |||
2890 | 2979 | ||
2891 | status = decode_op_hdr(xdr, OP_LOCK); | 2980 | status = decode_op_hdr(xdr, OP_LOCK); |
2892 | if (status == 0) { | 2981 | if (status == 0) { |
2893 | READ_BUF(sizeof(nfs4_stateid)); | 2982 | READ_BUF(sizeof(res->u.stateid.data)); |
2894 | COPYMEM(&res->u.stateid, sizeof(res->u.stateid)); | 2983 | COPYMEM(res->u.stateid.data, sizeof(res->u.stateid.data)); |
2895 | } else if (status == -NFS4ERR_DENIED) | 2984 | } else if (status == -NFS4ERR_DENIED) |
2896 | return decode_lock_denied(xdr, &res->u.denied); | 2985 | return decode_lock_denied(xdr, &res->u.denied); |
2897 | return status; | 2986 | return status; |
@@ -2913,8 +3002,8 @@ static int decode_locku(struct xdr_stream *xdr, struct nfs_lockres *res) | |||
2913 | 3002 | ||
2914 | status = decode_op_hdr(xdr, OP_LOCKU); | 3003 | status = decode_op_hdr(xdr, OP_LOCKU); |
2915 | if (status == 0) { | 3004 | if (status == 0) { |
2916 | READ_BUF(sizeof(nfs4_stateid)); | 3005 | READ_BUF(sizeof(res->u.stateid.data)); |
2917 | COPYMEM(&res->u.stateid, sizeof(res->u.stateid)); | 3006 | COPYMEM(res->u.stateid.data, sizeof(res->u.stateid.data)); |
2918 | } | 3007 | } |
2919 | return status; | 3008 | return status; |
2920 | } | 3009 | } |
@@ -2994,7 +3083,7 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) | |||
2994 | p += bmlen; | 3083 | p += bmlen; |
2995 | return decode_delegation(xdr, res); | 3084 | return decode_delegation(xdr, res); |
2996 | xdr_error: | 3085 | xdr_error: |
2997 | printk(KERN_NOTICE "%s: xdr error!\n", __FUNCTION__); | 3086 | dprintk("%s: Bitmap too large! Length = %u\n", __FUNCTION__, bmlen); |
2998 | return -EIO; | 3087 | return -EIO; |
2999 | } | 3088 | } |
3000 | 3089 | ||
@@ -3208,6 +3297,12 @@ static int decode_renew(struct xdr_stream *xdr) | |||
3208 | return decode_op_hdr(xdr, OP_RENEW); | 3297 | return decode_op_hdr(xdr, OP_RENEW); |
3209 | } | 3298 | } |
3210 | 3299 | ||
3300 | static int | ||
3301 | decode_restorefh(struct xdr_stream *xdr) | ||
3302 | { | ||
3303 | return decode_op_hdr(xdr, OP_RESTOREFH); | ||
3304 | } | ||
3305 | |||
3211 | static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, | 3306 | static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, |
3212 | size_t *acl_len) | 3307 | size_t *acl_len) |
3213 | { | 3308 | { |
@@ -3243,7 +3338,8 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
3243 | if (attrlen <= *acl_len) | 3338 | if (attrlen <= *acl_len) |
3244 | xdr_read_pages(xdr, attrlen); | 3339 | xdr_read_pages(xdr, attrlen); |
3245 | *acl_len = attrlen; | 3340 | *acl_len = attrlen; |
3246 | } | 3341 | } else |
3342 | status = -EOPNOTSUPP; | ||
3247 | 3343 | ||
3248 | out: | 3344 | out: |
3249 | return status; | 3345 | return status; |
@@ -3352,6 +3448,9 @@ static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, uint32_t *p, stru | |||
3352 | if (status) | 3448 | if (status) |
3353 | goto out; | 3449 | goto out; |
3354 | status = decode_open_downgrade(&xdr, res); | 3450 | status = decode_open_downgrade(&xdr, res); |
3451 | if (status != 0) | ||
3452 | goto out; | ||
3453 | decode_getfattr(&xdr, res->fattr, res->server); | ||
3355 | out: | 3454 | out: |
3356 | return status; | 3455 | return status; |
3357 | } | 3456 | } |
@@ -3424,7 +3523,7 @@ out: | |||
3424 | /* | 3523 | /* |
3425 | * Decode REMOVE response | 3524 | * Decode REMOVE response |
3426 | */ | 3525 | */ |
3427 | static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_change_info *cinfo) | 3526 | static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_remove_res *res) |
3428 | { | 3527 | { |
3429 | struct xdr_stream xdr; | 3528 | struct xdr_stream xdr; |
3430 | struct compound_hdr hdr; | 3529 | struct compound_hdr hdr; |
@@ -3433,8 +3532,11 @@ static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_ | |||
3433 | xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); | 3532 | xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); |
3434 | if ((status = decode_compound_hdr(&xdr, &hdr)) != 0) | 3533 | if ((status = decode_compound_hdr(&xdr, &hdr)) != 0) |
3435 | goto out; | 3534 | goto out; |
3436 | if ((status = decode_putfh(&xdr)) == 0) | 3535 | if ((status = decode_putfh(&xdr)) != 0) |
3437 | status = decode_remove(&xdr, cinfo); | 3536 | goto out; |
3537 | if ((status = decode_remove(&xdr, &res->cinfo)) != 0) | ||
3538 | goto out; | ||
3539 | decode_getfattr(&xdr, res->dir_attr, res->server); | ||
3438 | out: | 3540 | out: |
3439 | return status; | 3541 | return status; |
3440 | } | 3542 | } |
@@ -3457,7 +3559,14 @@ static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_ | |||
3457 | goto out; | 3559 | goto out; |
3458 | if ((status = decode_putfh(&xdr)) != 0) | 3560 | if ((status = decode_putfh(&xdr)) != 0) |
3459 | goto out; | 3561 | goto out; |
3460 | status = decode_rename(&xdr, &res->old_cinfo, &res->new_cinfo); | 3562 | if ((status = decode_rename(&xdr, &res->old_cinfo, &res->new_cinfo)) != 0) |
3563 | goto out; | ||
3564 | /* Current FH is target directory */ | ||
3565 | if (decode_getfattr(&xdr, res->new_fattr, res->server) != 0) | ||
3566 | goto out; | ||
3567 | if ((status = decode_restorefh(&xdr)) != 0) | ||
3568 | goto out; | ||
3569 | decode_getfattr(&xdr, res->old_fattr, res->server); | ||
3461 | out: | 3570 | out: |
3462 | return status; | 3571 | return status; |
3463 | } | 3572 | } |
@@ -3465,7 +3574,7 @@ out: | |||
3465 | /* | 3574 | /* |
3466 | * Decode LINK response | 3575 | * Decode LINK response |
3467 | */ | 3576 | */ |
3468 | static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_change_info *cinfo) | 3577 | static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_link_res *res) |
3469 | { | 3578 | { |
3470 | struct xdr_stream xdr; | 3579 | struct xdr_stream xdr; |
3471 | struct compound_hdr hdr; | 3580 | struct compound_hdr hdr; |
@@ -3480,7 +3589,17 @@ static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_ch | |||
3480 | goto out; | 3589 | goto out; |
3481 | if ((status = decode_putfh(&xdr)) != 0) | 3590 | if ((status = decode_putfh(&xdr)) != 0) |
3482 | goto out; | 3591 | goto out; |
3483 | status = decode_link(&xdr, cinfo); | 3592 | if ((status = decode_link(&xdr, &res->cinfo)) != 0) |
3593 | goto out; | ||
3594 | /* | ||
3595 | * Note order: OP_LINK leaves the directory as the current | ||
3596 | * filehandle. | ||
3597 | */ | ||
3598 | if (decode_getfattr(&xdr, res->dir_attr, res->server) != 0) | ||
3599 | goto out; | ||
3600 | if ((status = decode_restorefh(&xdr)) != 0) | ||
3601 | goto out; | ||
3602 | decode_getfattr(&xdr, res->fattr, res->server); | ||
3484 | out: | 3603 | out: |
3485 | return status; | 3604 | return status; |
3486 | } | 3605 | } |
@@ -3499,13 +3618,17 @@ static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_ | |||
3499 | goto out; | 3618 | goto out; |
3500 | if ((status = decode_putfh(&xdr)) != 0) | 3619 | if ((status = decode_putfh(&xdr)) != 0) |
3501 | goto out; | 3620 | goto out; |
3621 | if ((status = decode_savefh(&xdr)) != 0) | ||
3622 | goto out; | ||
3502 | if ((status = decode_create(&xdr,&res->dir_cinfo)) != 0) | 3623 | if ((status = decode_create(&xdr,&res->dir_cinfo)) != 0) |
3503 | goto out; | 3624 | goto out; |
3504 | if ((status = decode_getfh(&xdr, res->fh)) != 0) | 3625 | if ((status = decode_getfh(&xdr, res->fh)) != 0) |
3505 | goto out; | 3626 | goto out; |
3506 | status = decode_getfattr(&xdr, res->fattr, res->server); | 3627 | if (decode_getfattr(&xdr, res->fattr, res->server) != 0) |
3507 | if (status == NFS4ERR_DELAY) | 3628 | goto out; |
3508 | status = 0; | 3629 | if ((status = decode_restorefh(&xdr)) != 0) |
3630 | goto out; | ||
3631 | decode_getfattr(&xdr, res->dir_fattr, res->server); | ||
3509 | out: | 3632 | out: |
3510 | return status; | 3633 | return status; |
3511 | } | 3634 | } |
@@ -3623,6 +3746,15 @@ static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_cl | |||
3623 | if (status) | 3746 | if (status) |
3624 | goto out; | 3747 | goto out; |
3625 | status = decode_close(&xdr, res); | 3748 | status = decode_close(&xdr, res); |
3749 | if (status != 0) | ||
3750 | goto out; | ||
3751 | /* | ||
3752 | * Note: Server may do delete on close for this file | ||
3753 | * in which case the getattr call will fail with | ||
3754 | * an ESTALE error. Shouldn't be a problem, | ||
3755 | * though, since fattr->valid will remain unset. | ||
3756 | */ | ||
3757 | decode_getfattr(&xdr, res->fattr, res->server); | ||
3626 | out: | 3758 | out: |
3627 | return status; | 3759 | return status; |
3628 | } | 3760 | } |
@@ -3643,15 +3775,20 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_ope | |||
3643 | status = decode_putfh(&xdr); | 3775 | status = decode_putfh(&xdr); |
3644 | if (status) | 3776 | if (status) |
3645 | goto out; | 3777 | goto out; |
3778 | status = decode_savefh(&xdr); | ||
3779 | if (status) | ||
3780 | goto out; | ||
3646 | status = decode_open(&xdr, res); | 3781 | status = decode_open(&xdr, res); |
3647 | if (status) | 3782 | if (status) |
3648 | goto out; | 3783 | goto out; |
3649 | status = decode_getfh(&xdr, &res->fh); | 3784 | status = decode_getfh(&xdr, &res->fh); |
3650 | if (status) | 3785 | if (status) |
3651 | goto out; | 3786 | goto out; |
3652 | status = decode_getfattr(&xdr, res->f_attr, res->server); | 3787 | if (decode_getfattr(&xdr, res->f_attr, res->server) != 0) |
3653 | if (status == NFS4ERR_DELAY) | 3788 | goto out; |
3654 | status = 0; | 3789 | if ((status = decode_restorefh(&xdr)) != 0) |
3790 | goto out; | ||
3791 | decode_getfattr(&xdr, res->dir_attr, res->server); | ||
3655 | out: | 3792 | out: |
3656 | return status; | 3793 | return status; |
3657 | } | 3794 | } |
@@ -3869,6 +4006,9 @@ static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_wr | |||
3869 | if (status) | 4006 | if (status) |
3870 | goto out; | 4007 | goto out; |
3871 | status = decode_write(&xdr, res); | 4008 | status = decode_write(&xdr, res); |
4009 | if (status) | ||
4010 | goto out; | ||
4011 | decode_getfattr(&xdr, res->fattr, res->server); | ||
3872 | if (!status) | 4012 | if (!status) |
3873 | status = res->count; | 4013 | status = res->count; |
3874 | out: | 4014 | out: |
@@ -3892,6 +4032,9 @@ static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_w | |||
3892 | if (status) | 4032 | if (status) |
3893 | goto out; | 4033 | goto out; |
3894 | status = decode_commit(&xdr, res); | 4034 | status = decode_commit(&xdr, res); |
4035 | if (status) | ||
4036 | goto out; | ||
4037 | decode_getfattr(&xdr, res->fattr, res->server); | ||
3895 | out: | 4038 | out: |
3896 | return status; | 4039 | return status; |
3897 | } | 4040 | } |
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index be23c3fb9260..a48a003242c0 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
@@ -61,7 +61,7 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
61 | int status; | 61 | int status; |
62 | 62 | ||
63 | dprintk("%s: call getattr\n", __FUNCTION__); | 63 | dprintk("%s: call getattr\n", __FUNCTION__); |
64 | fattr->valid = 0; | 64 | nfs_fattr_init(fattr); |
65 | status = rpc_call(server->client_sys, NFSPROC_GETATTR, fhandle, fattr, 0); | 65 | status = rpc_call(server->client_sys, NFSPROC_GETATTR, fhandle, fattr, 0); |
66 | dprintk("%s: reply getattr: %d\n", __FUNCTION__, status); | 66 | dprintk("%s: reply getattr: %d\n", __FUNCTION__, status); |
67 | if (status) | 67 | if (status) |
@@ -93,7 +93,7 @@ nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, | |||
93 | int status; | 93 | int status; |
94 | 94 | ||
95 | dprintk("NFS call getattr\n"); | 95 | dprintk("NFS call getattr\n"); |
96 | fattr->valid = 0; | 96 | nfs_fattr_init(fattr); |
97 | status = rpc_call(server->client, NFSPROC_GETATTR, | 97 | status = rpc_call(server->client, NFSPROC_GETATTR, |
98 | fhandle, fattr, 0); | 98 | fhandle, fattr, 0); |
99 | dprintk("NFS reply getattr: %d\n", status); | 99 | dprintk("NFS reply getattr: %d\n", status); |
@@ -112,7 +112,7 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
112 | int status; | 112 | int status; |
113 | 113 | ||
114 | dprintk("NFS call setattr\n"); | 114 | dprintk("NFS call setattr\n"); |
115 | fattr->valid = 0; | 115 | nfs_fattr_init(fattr); |
116 | status = rpc_call(NFS_CLIENT(inode), NFSPROC_SETATTR, &arg, fattr, 0); | 116 | status = rpc_call(NFS_CLIENT(inode), NFSPROC_SETATTR, &arg, fattr, 0); |
117 | if (status == 0) | 117 | if (status == 0) |
118 | nfs_setattr_update_inode(inode, sattr); | 118 | nfs_setattr_update_inode(inode, sattr); |
@@ -136,7 +136,7 @@ nfs_proc_lookup(struct inode *dir, struct qstr *name, | |||
136 | int status; | 136 | int status; |
137 | 137 | ||
138 | dprintk("NFS call lookup %s\n", name->name); | 138 | dprintk("NFS call lookup %s\n", name->name); |
139 | fattr->valid = 0; | 139 | nfs_fattr_init(fattr); |
140 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_LOOKUP, &arg, &res, 0); | 140 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_LOOKUP, &arg, &res, 0); |
141 | dprintk("NFS reply lookup: %d\n", status); | 141 | dprintk("NFS reply lookup: %d\n", status); |
142 | return status; | 142 | return status; |
@@ -174,7 +174,7 @@ static int nfs_proc_read(struct nfs_read_data *rdata) | |||
174 | 174 | ||
175 | dprintk("NFS call read %d @ %Ld\n", rdata->args.count, | 175 | dprintk("NFS call read %d @ %Ld\n", rdata->args.count, |
176 | (long long) rdata->args.offset); | 176 | (long long) rdata->args.offset); |
177 | fattr->valid = 0; | 177 | nfs_fattr_init(fattr); |
178 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); | 178 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); |
179 | if (status >= 0) { | 179 | if (status >= 0) { |
180 | nfs_refresh_inode(inode, fattr); | 180 | nfs_refresh_inode(inode, fattr); |
@@ -203,10 +203,10 @@ static int nfs_proc_write(struct nfs_write_data *wdata) | |||
203 | 203 | ||
204 | dprintk("NFS call write %d @ %Ld\n", wdata->args.count, | 204 | dprintk("NFS call write %d @ %Ld\n", wdata->args.count, |
205 | (long long) wdata->args.offset); | 205 | (long long) wdata->args.offset); |
206 | fattr->valid = 0; | 206 | nfs_fattr_init(fattr); |
207 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); | 207 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); |
208 | if (status >= 0) { | 208 | if (status >= 0) { |
209 | nfs_refresh_inode(inode, fattr); | 209 | nfs_post_op_update_inode(inode, fattr); |
210 | wdata->res.count = wdata->args.count; | 210 | wdata->res.count = wdata->args.count; |
211 | wdata->verf.committed = NFS_FILE_SYNC; | 211 | wdata->verf.committed = NFS_FILE_SYNC; |
212 | } | 212 | } |
@@ -216,7 +216,7 @@ static int nfs_proc_write(struct nfs_write_data *wdata) | |||
216 | 216 | ||
217 | static int | 217 | static int |
218 | nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 218 | nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
219 | int flags) | 219 | int flags, struct nameidata *nd) |
220 | { | 220 | { |
221 | struct nfs_fh fhandle; | 221 | struct nfs_fh fhandle; |
222 | struct nfs_fattr fattr; | 222 | struct nfs_fattr fattr; |
@@ -232,7 +232,7 @@ nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
232 | }; | 232 | }; |
233 | int status; | 233 | int status; |
234 | 234 | ||
235 | fattr.valid = 0; | 235 | nfs_fattr_init(&fattr); |
236 | dprintk("NFS call create %s\n", dentry->d_name.name); | 236 | dprintk("NFS call create %s\n", dentry->d_name.name); |
237 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0); | 237 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0); |
238 | if (status == 0) | 238 | if (status == 0) |
@@ -273,12 +273,13 @@ nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
273 | sattr->ia_size = new_encode_dev(rdev);/* get out your barf bag */ | 273 | sattr->ia_size = new_encode_dev(rdev);/* get out your barf bag */ |
274 | } | 274 | } |
275 | 275 | ||
276 | fattr.valid = 0; | 276 | nfs_fattr_init(&fattr); |
277 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0); | 277 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0); |
278 | nfs_mark_for_revalidate(dir); | ||
278 | 279 | ||
279 | if (status == -EINVAL && S_ISFIFO(mode)) { | 280 | if (status == -EINVAL && S_ISFIFO(mode)) { |
280 | sattr->ia_mode = mode; | 281 | sattr->ia_mode = mode; |
281 | fattr.valid = 0; | 282 | nfs_fattr_init(&fattr); |
282 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0); | 283 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0); |
283 | } | 284 | } |
284 | if (status == 0) | 285 | if (status == 0) |
@@ -305,6 +306,7 @@ nfs_proc_remove(struct inode *dir, struct qstr *name) | |||
305 | 306 | ||
306 | dprintk("NFS call remove %s\n", name->name); | 307 | dprintk("NFS call remove %s\n", name->name); |
307 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 308 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
309 | nfs_mark_for_revalidate(dir); | ||
308 | 310 | ||
309 | dprintk("NFS reply remove: %d\n", status); | 311 | dprintk("NFS reply remove: %d\n", status); |
310 | return status; | 312 | return status; |
@@ -331,8 +333,10 @@ nfs_proc_unlink_done(struct dentry *dir, struct rpc_task *task) | |||
331 | { | 333 | { |
332 | struct rpc_message *msg = &task->tk_msg; | 334 | struct rpc_message *msg = &task->tk_msg; |
333 | 335 | ||
334 | if (msg->rpc_argp) | 336 | if (msg->rpc_argp) { |
337 | nfs_mark_for_revalidate(dir->d_inode); | ||
335 | kfree(msg->rpc_argp); | 338 | kfree(msg->rpc_argp); |
339 | } | ||
336 | return 0; | 340 | return 0; |
337 | } | 341 | } |
338 | 342 | ||
@@ -352,6 +356,8 @@ nfs_proc_rename(struct inode *old_dir, struct qstr *old_name, | |||
352 | 356 | ||
353 | dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name); | 357 | dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name); |
354 | status = rpc_call(NFS_CLIENT(old_dir), NFSPROC_RENAME, &arg, NULL, 0); | 358 | status = rpc_call(NFS_CLIENT(old_dir), NFSPROC_RENAME, &arg, NULL, 0); |
359 | nfs_mark_for_revalidate(old_dir); | ||
360 | nfs_mark_for_revalidate(new_dir); | ||
355 | dprintk("NFS reply rename: %d\n", status); | 361 | dprintk("NFS reply rename: %d\n", status); |
356 | return status; | 362 | return status; |
357 | } | 363 | } |
@@ -369,6 +375,7 @@ nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) | |||
369 | 375 | ||
370 | dprintk("NFS call link %s\n", name->name); | 376 | dprintk("NFS call link %s\n", name->name); |
371 | status = rpc_call(NFS_CLIENT(inode), NFSPROC_LINK, &arg, NULL, 0); | 377 | status = rpc_call(NFS_CLIENT(inode), NFSPROC_LINK, &arg, NULL, 0); |
378 | nfs_mark_for_revalidate(dir); | ||
372 | dprintk("NFS reply link: %d\n", status); | 379 | dprintk("NFS reply link: %d\n", status); |
373 | return status; | 380 | return status; |
374 | } | 381 | } |
@@ -391,9 +398,10 @@ nfs_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path, | |||
391 | if (path->len > NFS2_MAXPATHLEN) | 398 | if (path->len > NFS2_MAXPATHLEN) |
392 | return -ENAMETOOLONG; | 399 | return -ENAMETOOLONG; |
393 | dprintk("NFS call symlink %s -> %s\n", name->name, path->name); | 400 | dprintk("NFS call symlink %s -> %s\n", name->name, path->name); |
394 | fattr->valid = 0; | 401 | nfs_fattr_init(fattr); |
395 | fhandle->size = 0; | 402 | fhandle->size = 0; |
396 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_SYMLINK, &arg, NULL, 0); | 403 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_SYMLINK, &arg, NULL, 0); |
404 | nfs_mark_for_revalidate(dir); | ||
397 | dprintk("NFS reply symlink: %d\n", status); | 405 | dprintk("NFS reply symlink: %d\n", status); |
398 | return status; | 406 | return status; |
399 | } | 407 | } |
@@ -416,8 +424,9 @@ nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) | |||
416 | int status; | 424 | int status; |
417 | 425 | ||
418 | dprintk("NFS call mkdir %s\n", dentry->d_name.name); | 426 | dprintk("NFS call mkdir %s\n", dentry->d_name.name); |
419 | fattr.valid = 0; | 427 | nfs_fattr_init(&fattr); |
420 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_MKDIR, &arg, &res, 0); | 428 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_MKDIR, &arg, &res, 0); |
429 | nfs_mark_for_revalidate(dir); | ||
421 | if (status == 0) | 430 | if (status == 0) |
422 | status = nfs_instantiate(dentry, &fhandle, &fattr); | 431 | status = nfs_instantiate(dentry, &fhandle, &fattr); |
423 | dprintk("NFS reply mkdir: %d\n", status); | 432 | dprintk("NFS reply mkdir: %d\n", status); |
@@ -436,6 +445,7 @@ nfs_proc_rmdir(struct inode *dir, struct qstr *name) | |||
436 | 445 | ||
437 | dprintk("NFS call rmdir %s\n", name->name); | 446 | dprintk("NFS call rmdir %s\n", name->name); |
438 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_RMDIR, &arg, NULL, 0); | 447 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_RMDIR, &arg, NULL, 0); |
448 | nfs_mark_for_revalidate(dir); | ||
439 | dprintk("NFS reply rmdir: %d\n", status); | 449 | dprintk("NFS reply rmdir: %d\n", status); |
440 | return status; | 450 | return status; |
441 | } | 451 | } |
@@ -484,7 +494,7 @@ nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, | |||
484 | int status; | 494 | int status; |
485 | 495 | ||
486 | dprintk("NFS call statfs\n"); | 496 | dprintk("NFS call statfs\n"); |
487 | stat->fattr->valid = 0; | 497 | nfs_fattr_init(stat->fattr); |
488 | status = rpc_call(server->client, NFSPROC_STATFS, fhandle, &fsinfo, 0); | 498 | status = rpc_call(server->client, NFSPROC_STATFS, fhandle, &fsinfo, 0); |
489 | dprintk("NFS reply statfs: %d\n", status); | 499 | dprintk("NFS reply statfs: %d\n", status); |
490 | if (status) | 500 | if (status) |
@@ -507,7 +517,7 @@ nfs_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, | |||
507 | int status; | 517 | int status; |
508 | 518 | ||
509 | dprintk("NFS call fsinfo\n"); | 519 | dprintk("NFS call fsinfo\n"); |
510 | info->fattr->valid = 0; | 520 | nfs_fattr_init(info->fattr); |
511 | status = rpc_call(server->client, NFSPROC_STATFS, fhandle, &fsinfo, 0); | 521 | status = rpc_call(server->client, NFSPROC_STATFS, fhandle, &fsinfo, 0); |
512 | dprintk("NFS reply fsinfo: %d\n", status); | 522 | dprintk("NFS reply fsinfo: %d\n", status); |
513 | if (status) | 523 | if (status) |
@@ -579,7 +589,7 @@ nfs_write_done(struct rpc_task *task) | |||
579 | struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata; | 589 | struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata; |
580 | 590 | ||
581 | if (task->tk_status >= 0) | 591 | if (task->tk_status >= 0) |
582 | nfs_refresh_inode(data->inode, data->res.fattr); | 592 | nfs_post_op_update_inode(data->inode, data->res.fattr); |
583 | nfs_writeback_done(task); | 593 | nfs_writeback_done(task); |
584 | } | 594 | } |
585 | 595 | ||
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 6ceb1d471f20..43b03b19731b 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -184,14 +184,13 @@ static void nfs_readpage_release(struct nfs_page *req) | |||
184 | { | 184 | { |
185 | unlock_page(req->wb_page); | 185 | unlock_page(req->wb_page); |
186 | 186 | ||
187 | nfs_clear_request(req); | ||
188 | nfs_release_request(req); | ||
189 | |||
190 | dprintk("NFS: read done (%s/%Ld %d@%Ld)\n", | 187 | dprintk("NFS: read done (%s/%Ld %d@%Ld)\n", |
191 | req->wb_context->dentry->d_inode->i_sb->s_id, | 188 | req->wb_context->dentry->d_inode->i_sb->s_id, |
192 | (long long)NFS_FILEID(req->wb_context->dentry->d_inode), | 189 | (long long)NFS_FILEID(req->wb_context->dentry->d_inode), |
193 | req->wb_bytes, | 190 | req->wb_bytes, |
194 | (long long)req_offset(req)); | 191 | (long long)req_offset(req)); |
192 | nfs_clear_request(req); | ||
193 | nfs_release_request(req); | ||
195 | } | 194 | } |
196 | 195 | ||
197 | /* | 196 | /* |
@@ -216,6 +215,7 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, | |||
216 | data->res.fattr = &data->fattr; | 215 | data->res.fattr = &data->fattr; |
217 | data->res.count = count; | 216 | data->res.count = count; |
218 | data->res.eof = 0; | 217 | data->res.eof = 0; |
218 | nfs_fattr_init(&data->fattr); | ||
219 | 219 | ||
220 | NFS_PROTO(inode)->read_setup(data); | 220 | NFS_PROTO(inode)->read_setup(data); |
221 | 221 | ||
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 5130eda231d7..819a65f5071f 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -870,6 +870,7 @@ static void nfs_write_rpcsetup(struct nfs_page *req, | |||
870 | data->res.fattr = &data->fattr; | 870 | data->res.fattr = &data->fattr; |
871 | data->res.count = count; | 871 | data->res.count = count; |
872 | data->res.verf = &data->verf; | 872 | data->res.verf = &data->verf; |
873 | nfs_fattr_init(&data->fattr); | ||
873 | 874 | ||
874 | NFS_PROTO(inode)->write_setup(data, how); | 875 | NFS_PROTO(inode)->write_setup(data, how); |
875 | 876 | ||
@@ -1237,6 +1238,7 @@ static void nfs_commit_rpcsetup(struct list_head *head, | |||
1237 | data->res.count = 0; | 1238 | data->res.count = 0; |
1238 | data->res.fattr = &data->fattr; | 1239 | data->res.fattr = &data->fattr; |
1239 | data->res.verf = &data->verf; | 1240 | data->res.verf = &data->verf; |
1241 | nfs_fattr_init(&data->fattr); | ||
1240 | 1242 | ||
1241 | NFS_PROTO(inode)->commit_setup(data, how); | 1243 | NFS_PROTO(inode)->commit_setup(data, how); |
1242 | 1244 | ||
diff --git a/fs/nfs_common/nfsacl.c b/fs/nfs_common/nfsacl.c index 251e5a1bb1c4..0c2be8c0307d 100644 --- a/fs/nfs_common/nfsacl.c +++ b/fs/nfs_common/nfsacl.c | |||
@@ -48,43 +48,26 @@ xdr_nfsace_encode(struct xdr_array2_desc *desc, void *elem) | |||
48 | (struct nfsacl_encode_desc *) desc; | 48 | (struct nfsacl_encode_desc *) desc; |
49 | u32 *p = (u32 *) elem; | 49 | u32 *p = (u32 *) elem; |
50 | 50 | ||
51 | if (nfsacl_desc->count < nfsacl_desc->acl->a_count) { | 51 | struct posix_acl_entry *entry = |
52 | struct posix_acl_entry *entry = | 52 | &nfsacl_desc->acl->a_entries[nfsacl_desc->count++]; |
53 | &nfsacl_desc->acl->a_entries[nfsacl_desc->count++]; | ||
54 | 53 | ||
55 | *p++ = htonl(entry->e_tag | nfsacl_desc->typeflag); | 54 | *p++ = htonl(entry->e_tag | nfsacl_desc->typeflag); |
56 | switch(entry->e_tag) { | 55 | switch(entry->e_tag) { |
57 | case ACL_USER_OBJ: | 56 | case ACL_USER_OBJ: |
58 | *p++ = htonl(nfsacl_desc->uid); | 57 | *p++ = htonl(nfsacl_desc->uid); |
59 | break; | 58 | break; |
60 | case ACL_GROUP_OBJ: | 59 | case ACL_GROUP_OBJ: |
61 | *p++ = htonl(nfsacl_desc->gid); | 60 | *p++ = htonl(nfsacl_desc->gid); |
62 | break; | 61 | break; |
63 | case ACL_USER: | 62 | case ACL_USER: |
64 | case ACL_GROUP: | 63 | case ACL_GROUP: |
65 | *p++ = htonl(entry->e_id); | 64 | *p++ = htonl(entry->e_id); |
66 | break; | 65 | break; |
67 | default: /* Solaris depends on that! */ | 66 | default: /* Solaris depends on that! */ |
68 | *p++ = 0; | 67 | *p++ = 0; |
69 | break; | 68 | break; |
70 | } | ||
71 | *p++ = htonl(entry->e_perm & S_IRWXO); | ||
72 | } else { | ||
73 | const struct posix_acl_entry *pa, *pe; | ||
74 | int group_obj_perm = ACL_READ|ACL_WRITE|ACL_EXECUTE; | ||
75 | |||
76 | FOREACH_ACL_ENTRY(pa, nfsacl_desc->acl, pe) { | ||
77 | if (pa->e_tag == ACL_GROUP_OBJ) { | ||
78 | group_obj_perm = pa->e_perm & S_IRWXO; | ||
79 | break; | ||
80 | } | ||
81 | } | ||
82 | /* fake up ACL_MASK entry */ | ||
83 | *p++ = htonl(ACL_MASK | nfsacl_desc->typeflag); | ||
84 | *p++ = htonl(0); | ||
85 | *p++ = htonl(group_obj_perm); | ||
86 | } | 69 | } |
87 | 70 | *p++ = htonl(entry->e_perm & S_IRWXO); | |
88 | return 0; | 71 | return 0; |
89 | } | 72 | } |
90 | 73 | ||
@@ -105,11 +88,28 @@ nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode, | |||
105 | .gid = inode->i_gid, | 88 | .gid = inode->i_gid, |
106 | }; | 89 | }; |
107 | int err; | 90 | int err; |
91 | struct posix_acl *acl2 = NULL; | ||
108 | 92 | ||
109 | if (entries > NFS_ACL_MAX_ENTRIES || | 93 | if (entries > NFS_ACL_MAX_ENTRIES || |
110 | xdr_encode_word(buf, base, entries)) | 94 | xdr_encode_word(buf, base, entries)) |
111 | return -EINVAL; | 95 | return -EINVAL; |
96 | if (encode_entries && acl && acl->a_count == 3) { | ||
97 | /* Fake up an ACL_MASK entry. */ | ||
98 | acl2 = posix_acl_alloc(4, GFP_KERNEL); | ||
99 | if (!acl2) | ||
100 | return -ENOMEM; | ||
101 | /* Insert entries in canonical order: other orders seem | ||
102 | to confuse Solaris VxFS. */ | ||
103 | acl2->a_entries[0] = acl->a_entries[0]; /* ACL_USER_OBJ */ | ||
104 | acl2->a_entries[1] = acl->a_entries[1]; /* ACL_GROUP_OBJ */ | ||
105 | acl2->a_entries[2] = acl->a_entries[1]; /* ACL_MASK */ | ||
106 | acl2->a_entries[2].e_tag = ACL_MASK; | ||
107 | acl2->a_entries[3] = acl->a_entries[2]; /* ACL_OTHER */ | ||
108 | nfsacl_desc.acl = acl2; | ||
109 | } | ||
112 | err = xdr_encode_array2(buf, base + 4, &nfsacl_desc.desc); | 110 | err = xdr_encode_array2(buf, base + 4, &nfsacl_desc.desc); |
111 | if (acl2) | ||
112 | posix_acl_release(acl2); | ||
113 | if (!err) | 113 | if (!err) |
114 | err = 8 + nfsacl_desc.desc.elem_size * | 114 | err = 8 + nfsacl_desc.desc.elem_size * |
115 | nfsacl_desc.desc.array_len; | 115 | nfsacl_desc.desc.array_len; |
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index c7e9237379c2..de58579a1d0e 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog | |||
@@ -29,7 +29,8 @@ ToDo/Notes: | |||
29 | The Windows boot will run chkdsk and then reboot. The user can then | 29 | The Windows boot will run chkdsk and then reboot. The user can then |
30 | immediately boot into Linux rather than having to do a full Windows | 30 | immediately boot into Linux rather than having to do a full Windows |
31 | boot first before rebooting into Linux and we will recognize such a | 31 | boot first before rebooting into Linux and we will recognize such a |
32 | journal and empty it as it is clean by definition. | 32 | journal and empty it as it is clean by definition. Note, this only |
33 | works if chkdsk left the journal in an obviously clean state. | ||
33 | - Support journals ($LogFile) with only one restart page as well as | 34 | - Support journals ($LogFile) with only one restart page as well as |
34 | journals with two different restart pages. We sanity check both and | 35 | journals with two different restart pages. We sanity check both and |
35 | either use the only sane one or the more recent one of the two in the | 36 | either use the only sane one or the more recent one of the two in the |
@@ -94,6 +95,16 @@ ToDo/Notes: | |||
94 | my ways. | 95 | my ways. |
95 | - Fix various bugs in the runlist merging code. (Based on libntfs | 96 | - Fix various bugs in the runlist merging code. (Based on libntfs |
96 | changes by Richard Russon.) | 97 | changes by Richard Russon.) |
98 | - Fix sparse warnings that have crept in over time. | ||
99 | - Change ntfs_cluster_free() to require a write locked runlist on entry | ||
100 | since we otherwise get into a lock reversal deadlock if a read locked | ||
101 | runlist is passed in. In the process also change it to take an ntfs | ||
102 | inode instead of a vfs inode as parameter. | ||
103 | - Fix the definition of the CHKD ntfs record magic. It had an off by | ||
104 | two error causing it to be CHKB instead of CHKD. | ||
105 | - Fix a stupid bug in __ntfs_bitmap_set_bits_in_run() which caused the | ||
106 | count to become negative and hence we had a wild memset() scribbling | ||
107 | all over the system's ram. | ||
97 | 108 | ||
98 | 2.1.23 - Implement extension of resident files and make writing safe as well as | 109 | 2.1.23 - Implement extension of resident files and make writing safe as well as |
99 | many bug fixes, cleanups, and enhancements... | 110 | many bug fixes, cleanups, and enhancements... |
diff --git a/fs/ntfs/bitmap.c b/fs/ntfs/bitmap.c index 12cf2e30c7dd..7a190cdc60e2 100644 --- a/fs/ntfs/bitmap.c +++ b/fs/ntfs/bitmap.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * bitmap.c - NTFS kernel bitmap handling. Part of the Linux-NTFS project. | 2 | * bitmap.c - NTFS kernel bitmap handling. Part of the Linux-NTFS project. |
3 | * | 3 | * |
4 | * Copyright (c) 2004 Anton Altaparmakov | 4 | * Copyright (c) 2004-2005 Anton Altaparmakov |
5 | * | 5 | * |
6 | * This program/include file is free software; you can redistribute it and/or | 6 | * This program/include file is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License as published | 7 | * modify it under the terms of the GNU General Public License as published |
@@ -90,7 +90,8 @@ int __ntfs_bitmap_set_bits_in_run(struct inode *vi, const s64 start_bit, | |||
90 | /* If the first byte is partial, modify the appropriate bits in it. */ | 90 | /* If the first byte is partial, modify the appropriate bits in it. */ |
91 | if (bit) { | 91 | if (bit) { |
92 | u8 *byte = kaddr + pos; | 92 | u8 *byte = kaddr + pos; |
93 | while ((bit & 7) && cnt--) { | 93 | while ((bit & 7) && cnt) { |
94 | cnt--; | ||
94 | if (value) | 95 | if (value) |
95 | *byte |= 1 << bit++; | 96 | *byte |= 1 << bit++; |
96 | else | 97 | else |
diff --git a/fs/ntfs/layout.h b/fs/ntfs/layout.h index 609ad1728ce4..5c248d404f05 100644 --- a/fs/ntfs/layout.h +++ b/fs/ntfs/layout.h | |||
@@ -123,7 +123,7 @@ enum { | |||
123 | magic_RCRD = const_cpu_to_le32(0x44524352), /* Log record page. */ | 123 | magic_RCRD = const_cpu_to_le32(0x44524352), /* Log record page. */ |
124 | 124 | ||
125 | /* Found in $LogFile/$DATA. (May be found in $MFT/$DATA, also?) */ | 125 | /* Found in $LogFile/$DATA. (May be found in $MFT/$DATA, also?) */ |
126 | magic_CHKD = const_cpu_to_le32(0x424b4843), /* Modified by chkdsk. */ | 126 | magic_CHKD = const_cpu_to_le32(0x444b4843), /* Modified by chkdsk. */ |
127 | 127 | ||
128 | /* Found in all ntfs record containing records. */ | 128 | /* Found in all ntfs record containing records. */ |
129 | magic_BAAD = const_cpu_to_le32(0x44414142), /* Failed multi sector | 129 | magic_BAAD = const_cpu_to_le32(0x44414142), /* Failed multi sector |
@@ -308,10 +308,8 @@ typedef le16 MFT_RECORD_FLAGS; | |||
308 | * The _LE versions are to be applied on little endian MFT_REFs. | 308 | * The _LE versions are to be applied on little endian MFT_REFs. |
309 | * Note: The _LE versions will return a CPU endian formatted value! | 309 | * Note: The _LE versions will return a CPU endian formatted value! |
310 | */ | 310 | */ |
311 | typedef enum { | 311 | #define MFT_REF_MASK_CPU 0x0000ffffffffffffULL |
312 | MFT_REF_MASK_CPU = 0x0000ffffffffffffULL, | 312 | #define MFT_REF_MASK_LE const_cpu_to_le64(MFT_REF_MASK_CPU) |
313 | MFT_REF_MASK_LE = const_cpu_to_le64(0x0000ffffffffffffULL), | ||
314 | } MFT_REF_CONSTS; | ||
315 | 313 | ||
316 | typedef u64 MFT_REF; | 314 | typedef u64 MFT_REF; |
317 | typedef le64 leMFT_REF; | 315 | typedef le64 leMFT_REF; |
diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c index 7b5934290685..5af3bf0b7eee 100644 --- a/fs/ntfs/lcnalloc.c +++ b/fs/ntfs/lcnalloc.c | |||
@@ -779,14 +779,13 @@ out: | |||
779 | 779 | ||
780 | /** | 780 | /** |
781 | * __ntfs_cluster_free - free clusters on an ntfs volume | 781 | * __ntfs_cluster_free - free clusters on an ntfs volume |
782 | * @vi: vfs inode whose runlist describes the clusters to free | 782 | * @ni: ntfs inode whose runlist describes the clusters to free |
783 | * @start_vcn: vcn in the runlist of @vi at which to start freeing clusters | 783 | * @start_vcn: vcn in the runlist of @ni at which to start freeing clusters |
784 | * @count: number of clusters to free or -1 for all clusters | 784 | * @count: number of clusters to free or -1 for all clusters |
785 | * @write_locked: true if the runlist is locked for writing | ||
786 | * @is_rollback: true if this is a rollback operation | 785 | * @is_rollback: true if this is a rollback operation |
787 | * | 786 | * |
788 | * Free @count clusters starting at the cluster @start_vcn in the runlist | 787 | * Free @count clusters starting at the cluster @start_vcn in the runlist |
789 | * described by the vfs inode @vi. | 788 | * described by the vfs inode @ni. |
790 | * | 789 | * |
791 | * If @count is -1, all clusters from @start_vcn to the end of the runlist are | 790 | * If @count is -1, all clusters from @start_vcn to the end of the runlist are |
792 | * deallocated. Thus, to completely free all clusters in a runlist, use | 791 | * deallocated. Thus, to completely free all clusters in a runlist, use |
@@ -801,31 +800,28 @@ out: | |||
801 | * Return the number of deallocated clusters (not counting sparse ones) on | 800 | * Return the number of deallocated clusters (not counting sparse ones) on |
802 | * success and -errno on error. | 801 | * success and -errno on error. |
803 | * | 802 | * |
804 | * Locking: - The runlist described by @vi must be locked on entry and is | 803 | * Locking: - The runlist described by @ni must be locked for writing on entry |
805 | * locked on return. Note if the runlist is locked for reading the | 804 | * and is locked on return. Note the runlist may be modified when |
806 | * lock may be dropped and reacquired. Note the runlist may be | 805 | * needed runlist fragments need to be mapped. |
807 | * modified when needed runlist fragments need to be mapped. | ||
808 | * - The volume lcn bitmap must be unlocked on entry and is unlocked | 806 | * - The volume lcn bitmap must be unlocked on entry and is unlocked |
809 | * on return. | 807 | * on return. |
810 | * - This function takes the volume lcn bitmap lock for writing and | 808 | * - This function takes the volume lcn bitmap lock for writing and |
811 | * modifies the bitmap contents. | 809 | * modifies the bitmap contents. |
812 | */ | 810 | */ |
813 | s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count, | 811 | s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, s64 count, |
814 | const BOOL write_locked, const BOOL is_rollback) | 812 | const BOOL is_rollback) |
815 | { | 813 | { |
816 | s64 delta, to_free, total_freed, real_freed; | 814 | s64 delta, to_free, total_freed, real_freed; |
817 | ntfs_inode *ni; | ||
818 | ntfs_volume *vol; | 815 | ntfs_volume *vol; |
819 | struct inode *lcnbmp_vi; | 816 | struct inode *lcnbmp_vi; |
820 | runlist_element *rl; | 817 | runlist_element *rl; |
821 | int err; | 818 | int err; |
822 | 819 | ||
823 | BUG_ON(!vi); | 820 | BUG_ON(!ni); |
824 | ntfs_debug("Entering for i_ino 0x%lx, start_vcn 0x%llx, count " | 821 | ntfs_debug("Entering for i_ino 0x%lx, start_vcn 0x%llx, count " |
825 | "0x%llx.%s", vi->i_ino, (unsigned long long)start_vcn, | 822 | "0x%llx.%s", ni->mft_no, (unsigned long long)start_vcn, |
826 | (unsigned long long)count, | 823 | (unsigned long long)count, |
827 | is_rollback ? " (rollback)" : ""); | 824 | is_rollback ? " (rollback)" : ""); |
828 | ni = NTFS_I(vi); | ||
829 | vol = ni->vol; | 825 | vol = ni->vol; |
830 | lcnbmp_vi = vol->lcnbmp_ino; | 826 | lcnbmp_vi = vol->lcnbmp_ino; |
831 | BUG_ON(!lcnbmp_vi); | 827 | BUG_ON(!lcnbmp_vi); |
@@ -843,7 +839,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count, | |||
843 | 839 | ||
844 | total_freed = real_freed = 0; | 840 | total_freed = real_freed = 0; |
845 | 841 | ||
846 | rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, write_locked); | 842 | rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, TRUE); |
847 | if (IS_ERR(rl)) { | 843 | if (IS_ERR(rl)) { |
848 | if (!is_rollback) | 844 | if (!is_rollback) |
849 | ntfs_error(vol->sb, "Failed to find first runlist " | 845 | ntfs_error(vol->sb, "Failed to find first runlist " |
@@ -897,7 +893,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count, | |||
897 | 893 | ||
898 | /* Attempt to map runlist. */ | 894 | /* Attempt to map runlist. */ |
899 | vcn = rl->vcn; | 895 | vcn = rl->vcn; |
900 | rl = ntfs_attr_find_vcn_nolock(ni, vcn, write_locked); | 896 | rl = ntfs_attr_find_vcn_nolock(ni, vcn, TRUE); |
901 | if (IS_ERR(rl)) { | 897 | if (IS_ERR(rl)) { |
902 | err = PTR_ERR(rl); | 898 | err = PTR_ERR(rl); |
903 | if (!is_rollback) | 899 | if (!is_rollback) |
@@ -965,8 +961,7 @@ err_out: | |||
965 | * If rollback fails, set the volume errors flag, emit an error | 961 | * If rollback fails, set the volume errors flag, emit an error |
966 | * message, and return the error code. | 962 | * message, and return the error code. |
967 | */ | 963 | */ |
968 | delta = __ntfs_cluster_free(vi, start_vcn, total_freed, write_locked, | 964 | delta = __ntfs_cluster_free(ni, start_vcn, total_freed, TRUE); |
969 | TRUE); | ||
970 | if (delta < 0) { | 965 | if (delta < 0) { |
971 | ntfs_error(vol->sb, "Failed to rollback (error %i). Leaving " | 966 | ntfs_error(vol->sb, "Failed to rollback (error %i). Leaving " |
972 | "inconsistent metadata! Unmount and run " | 967 | "inconsistent metadata! Unmount and run " |
diff --git a/fs/ntfs/lcnalloc.h b/fs/ntfs/lcnalloc.h index e4d7fb98d685..a6a8827882e7 100644 --- a/fs/ntfs/lcnalloc.h +++ b/fs/ntfs/lcnalloc.h | |||
@@ -2,7 +2,7 @@ | |||
2 | * lcnalloc.h - Exports for NTFS kernel cluster (de)allocation. Part of the | 2 | * lcnalloc.h - Exports for NTFS kernel cluster (de)allocation. Part of the |
3 | * Linux-NTFS project. | 3 | * Linux-NTFS project. |
4 | * | 4 | * |
5 | * Copyright (c) 2004 Anton Altaparmakov | 5 | * Copyright (c) 2004-2005 Anton Altaparmakov |
6 | * | 6 | * |
7 | * This program/include file is free software; you can redistribute it and/or | 7 | * This program/include file is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU General Public License as published | 8 | * modify it under the terms of the GNU General Public License as published |
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/fs.h> | 28 | #include <linux/fs.h> |
29 | 29 | ||
30 | #include "types.h" | 30 | #include "types.h" |
31 | #include "inode.h" | ||
31 | #include "runlist.h" | 32 | #include "runlist.h" |
32 | #include "volume.h" | 33 | #include "volume.h" |
33 | 34 | ||
@@ -42,18 +43,17 @@ extern runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, | |||
42 | const VCN start_vcn, const s64 count, const LCN start_lcn, | 43 | const VCN start_vcn, const s64 count, const LCN start_lcn, |
43 | const NTFS_CLUSTER_ALLOCATION_ZONES zone); | 44 | const NTFS_CLUSTER_ALLOCATION_ZONES zone); |
44 | 45 | ||
45 | extern s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, | 46 | extern s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, |
46 | s64 count, const BOOL write_locked, const BOOL is_rollback); | 47 | s64 count, const BOOL is_rollback); |
47 | 48 | ||
48 | /** | 49 | /** |
49 | * ntfs_cluster_free - free clusters on an ntfs volume | 50 | * ntfs_cluster_free - free clusters on an ntfs volume |
50 | * @vi: vfs inode whose runlist describes the clusters to free | 51 | * @ni: ntfs inode whose runlist describes the clusters to free |
51 | * @start_vcn: vcn in the runlist of @vi at which to start freeing clusters | 52 | * @start_vcn: vcn in the runlist of @ni at which to start freeing clusters |
52 | * @count: number of clusters to free or -1 for all clusters | 53 | * @count: number of clusters to free or -1 for all clusters |
53 | * @write_locked: true if the runlist is locked for writing | ||
54 | * | 54 | * |
55 | * Free @count clusters starting at the cluster @start_vcn in the runlist | 55 | * Free @count clusters starting at the cluster @start_vcn in the runlist |
56 | * described by the vfs inode @vi. | 56 | * described by the ntfs inode @ni. |
57 | * | 57 | * |
58 | * If @count is -1, all clusters from @start_vcn to the end of the runlist are | 58 | * If @count is -1, all clusters from @start_vcn to the end of the runlist are |
59 | * deallocated. Thus, to completely free all clusters in a runlist, use | 59 | * deallocated. Thus, to completely free all clusters in a runlist, use |
@@ -65,19 +65,18 @@ extern s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, | |||
65 | * Return the number of deallocated clusters (not counting sparse ones) on | 65 | * Return the number of deallocated clusters (not counting sparse ones) on |
66 | * success and -errno on error. | 66 | * success and -errno on error. |
67 | * | 67 | * |
68 | * Locking: - The runlist described by @vi must be locked on entry and is | 68 | * Locking: - The runlist described by @ni must be locked for writing on entry |
69 | * locked on return. Note if the runlist is locked for reading the | 69 | * and is locked on return. Note the runlist may be modified when |
70 | * lock may be dropped and reacquired. Note the runlist may be | 70 | * needed runlist fragments need to be mapped. |
71 | * modified when needed runlist fragments need to be mapped. | ||
72 | * - The volume lcn bitmap must be unlocked on entry and is unlocked | 71 | * - The volume lcn bitmap must be unlocked on entry and is unlocked |
73 | * on return. | 72 | * on return. |
74 | * - This function takes the volume lcn bitmap lock for writing and | 73 | * - This function takes the volume lcn bitmap lock for writing and |
75 | * modifies the bitmap contents. | 74 | * modifies the bitmap contents. |
76 | */ | 75 | */ |
77 | static inline s64 ntfs_cluster_free(struct inode *vi, const VCN start_vcn, | 76 | static inline s64 ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, |
78 | s64 count, const BOOL write_locked) | 77 | s64 count) |
79 | { | 78 | { |
80 | return __ntfs_cluster_free(vi, start_vcn, count, write_locked, FALSE); | 79 | return __ntfs_cluster_free(ni, start_vcn, count, FALSE); |
81 | } | 80 | } |
82 | 81 | ||
83 | extern int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol, | 82 | extern int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol, |
diff --git a/fs/ntfs/logfile.c b/fs/ntfs/logfile.c index 0173e95500d9..0fd70295cca6 100644 --- a/fs/ntfs/logfile.c +++ b/fs/ntfs/logfile.c | |||
@@ -51,7 +51,8 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi, | |||
51 | RESTART_PAGE_HEADER *rp, s64 pos) | 51 | RESTART_PAGE_HEADER *rp, s64 pos) |
52 | { | 52 | { |
53 | u32 logfile_system_page_size, logfile_log_page_size; | 53 | u32 logfile_system_page_size, logfile_log_page_size; |
54 | u16 usa_count, usa_ofs, usa_end, ra_ofs; | 54 | u16 ra_ofs, usa_count, usa_ofs, usa_end = 0; |
55 | BOOL have_usa = TRUE; | ||
55 | 56 | ||
56 | ntfs_debug("Entering."); | 57 | ntfs_debug("Entering."); |
57 | /* | 58 | /* |
@@ -86,6 +87,14 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi, | |||
86 | (int)sle16_to_cpu(rp->minor_ver)); | 87 | (int)sle16_to_cpu(rp->minor_ver)); |
87 | return FALSE; | 88 | return FALSE; |
88 | } | 89 | } |
90 | /* | ||
91 | * If chkdsk has been run the restart page may not be protected by an | ||
92 | * update sequence array. | ||
93 | */ | ||
94 | if (ntfs_is_chkd_record(rp->magic) && !le16_to_cpu(rp->usa_count)) { | ||
95 | have_usa = FALSE; | ||
96 | goto skip_usa_checks; | ||
97 | } | ||
89 | /* Verify the size of the update sequence array. */ | 98 | /* Verify the size of the update sequence array. */ |
90 | usa_count = 1 + (logfile_system_page_size >> NTFS_BLOCK_SIZE_BITS); | 99 | usa_count = 1 + (logfile_system_page_size >> NTFS_BLOCK_SIZE_BITS); |
91 | if (usa_count != le16_to_cpu(rp->usa_count)) { | 100 | if (usa_count != le16_to_cpu(rp->usa_count)) { |
@@ -102,6 +111,7 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi, | |||
102 | "inconsistent update sequence array offset."); | 111 | "inconsistent update sequence array offset."); |
103 | return FALSE; | 112 | return FALSE; |
104 | } | 113 | } |
114 | skip_usa_checks: | ||
105 | /* | 115 | /* |
106 | * Verify the position of the restart area. It must be: | 116 | * Verify the position of the restart area. It must be: |
107 | * - aligned to 8-byte boundary, | 117 | * - aligned to 8-byte boundary, |
@@ -109,7 +119,8 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi, | |||
109 | * - within the system page size. | 119 | * - within the system page size. |
110 | */ | 120 | */ |
111 | ra_ofs = le16_to_cpu(rp->restart_area_offset); | 121 | ra_ofs = le16_to_cpu(rp->restart_area_offset); |
112 | if (ra_ofs & 7 || ra_ofs < usa_end || | 122 | if (ra_ofs & 7 || (have_usa ? ra_ofs < usa_end : |
123 | ra_ofs < sizeof(RESTART_PAGE_HEADER)) || | ||
113 | ra_ofs > logfile_system_page_size) { | 124 | ra_ofs > logfile_system_page_size) { |
114 | ntfs_error(vi->i_sb, "$LogFile restart page specifies " | 125 | ntfs_error(vi->i_sb, "$LogFile restart page specifies " |
115 | "inconsistent restart area offset."); | 126 | "inconsistent restart area offset."); |
@@ -402,8 +413,12 @@ static int ntfs_check_and_load_restart_page(struct inode *vi, | |||
402 | idx++; | 413 | idx++; |
403 | } while (to_read > 0); | 414 | } while (to_read > 0); |
404 | } | 415 | } |
405 | /* Perform the multi sector transfer deprotection on the buffer. */ | 416 | /* |
406 | if (post_read_mst_fixup((NTFS_RECORD*)trp, | 417 | * Perform the multi sector transfer deprotection on the buffer if the |
418 | * restart page is protected. | ||
419 | */ | ||
420 | if ((!ntfs_is_chkd_record(trp->magic) || le16_to_cpu(trp->usa_count)) | ||
421 | && post_read_mst_fixup((NTFS_RECORD*)trp, | ||
407 | le32_to_cpu(rp->system_page_size))) { | 422 | le32_to_cpu(rp->system_page_size))) { |
408 | /* | 423 | /* |
409 | * A multi sector tranfer error was detected. We only need to | 424 | * A multi sector tranfer error was detected. We only need to |
@@ -615,11 +630,16 @@ is_empty: | |||
615 | * Otherwise just throw it away. | 630 | * Otherwise just throw it away. |
616 | */ | 631 | */ |
617 | if (rstr2_lsn > rstr1_lsn) { | 632 | if (rstr2_lsn > rstr1_lsn) { |
633 | ntfs_debug("Using second restart page as it is more " | ||
634 | "recent."); | ||
618 | ntfs_free(rstr1_ph); | 635 | ntfs_free(rstr1_ph); |
619 | rstr1_ph = rstr2_ph; | 636 | rstr1_ph = rstr2_ph; |
620 | /* rstr1_lsn = rstr2_lsn; */ | 637 | /* rstr1_lsn = rstr2_lsn; */ |
621 | } else | 638 | } else { |
639 | ntfs_debug("Using first restart page as it is more " | ||
640 | "recent."); | ||
622 | ntfs_free(rstr2_ph); | 641 | ntfs_free(rstr2_ph); |
642 | } | ||
623 | rstr2_ph = NULL; | 643 | rstr2_ph = NULL; |
624 | } | 644 | } |
625 | /* All consistency checks passed. */ | 645 | /* All consistency checks passed. */ |
diff --git a/fs/ntfs/logfile.h b/fs/ntfs/logfile.h index 42388f95ea6d..a51f3dd0e9eb 100644 --- a/fs/ntfs/logfile.h +++ b/fs/ntfs/logfile.h | |||
@@ -113,7 +113,7 @@ typedef struct { | |||
113 | */ | 113 | */ |
114 | enum { | 114 | enum { |
115 | RESTART_VOLUME_IS_CLEAN = const_cpu_to_le16(0x0002), | 115 | RESTART_VOLUME_IS_CLEAN = const_cpu_to_le16(0x0002), |
116 | RESTART_SPACE_FILLER = 0xffff, /* gcc: Force enum bit width to 16. */ | 116 | RESTART_SPACE_FILLER = const_cpu_to_le16(0xffff), /* gcc: Force enum bit width to 16. */ |
117 | } __attribute__ ((__packed__)); | 117 | } __attribute__ ((__packed__)); |
118 | 118 | ||
119 | typedef le16 RESTART_AREA_FLAGS; | 119 | typedef le16 RESTART_AREA_FLAGS; |
diff --git a/fs/ntfs/malloc.h b/fs/ntfs/malloc.h index 006946efca8c..590887b943f5 100644 --- a/fs/ntfs/malloc.h +++ b/fs/ntfs/malloc.h | |||
@@ -40,7 +40,7 @@ | |||
40 | * Depending on @gfp_mask the allocation may be guaranteed to succeed. | 40 | * Depending on @gfp_mask the allocation may be guaranteed to succeed. |
41 | */ | 41 | */ |
42 | static inline void *__ntfs_malloc(unsigned long size, | 42 | static inline void *__ntfs_malloc(unsigned long size, |
43 | unsigned int __nocast gfp_mask) | 43 | gfp_t gfp_mask) |
44 | { | 44 | { |
45 | if (likely(size <= PAGE_SIZE)) { | 45 | if (likely(size <= PAGE_SIZE)) { |
46 | BUG_ON(!size); | 46 | BUG_ON(!size); |
diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index 2c32b84385a8..b011369b5956 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c | |||
@@ -58,7 +58,8 @@ static inline MFT_RECORD *map_mft_record_page(ntfs_inode *ni) | |||
58 | * overflowing the unsigned long, but I don't think we would ever get | 58 | * overflowing the unsigned long, but I don't think we would ever get |
59 | * here if the volume was that big... | 59 | * here if the volume was that big... |
60 | */ | 60 | */ |
61 | index = ni->mft_no << vol->mft_record_size_bits >> PAGE_CACHE_SHIFT; | 61 | index = (u64)ni->mft_no << vol->mft_record_size_bits >> |
62 | PAGE_CACHE_SHIFT; | ||
62 | ofs = (ni->mft_no << vol->mft_record_size_bits) & ~PAGE_CACHE_MASK; | 63 | ofs = (ni->mft_no << vol->mft_record_size_bits) & ~PAGE_CACHE_MASK; |
63 | 64 | ||
64 | i_size = i_size_read(mft_vi); | 65 | i_size = i_size_read(mft_vi); |
@@ -1953,7 +1954,7 @@ restore_undo_alloc: | |||
1953 | a = ctx->attr; | 1954 | a = ctx->attr; |
1954 | a->data.non_resident.highest_vcn = cpu_to_sle64(old_last_vcn - 1); | 1955 | a->data.non_resident.highest_vcn = cpu_to_sle64(old_last_vcn - 1); |
1955 | undo_alloc: | 1956 | undo_alloc: |
1956 | if (ntfs_cluster_free(vol->mft_ino, old_last_vcn, -1, TRUE) < 0) { | 1957 | if (ntfs_cluster_free(mft_ni, old_last_vcn, -1) < 0) { |
1957 | ntfs_error(vol->sb, "Failed to free clusters from mft data " | 1958 | ntfs_error(vol->sb, "Failed to free clusters from mft data " |
1958 | "attribute.%s", es); | 1959 | "attribute.%s", es); |
1959 | NVolSetErrors(vol); | 1960 | NVolSetErrors(vol); |
diff --git a/fs/ntfs/unistr.c b/fs/ntfs/unistr.c index a389a5a16c84..0ea887fc859c 100644 --- a/fs/ntfs/unistr.c +++ b/fs/ntfs/unistr.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * unistr.c - NTFS Unicode string handling. Part of the Linux-NTFS project. | 2 | * unistr.c - NTFS Unicode string handling. Part of the Linux-NTFS project. |
3 | * | 3 | * |
4 | * Copyright (c) 2001-2004 Anton Altaparmakov | 4 | * Copyright (c) 2001-2005 Anton Altaparmakov |
5 | * | 5 | * |
6 | * This program/include file is free software; you can redistribute it and/or | 6 | * This program/include file is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License as published | 7 | * modify it under the terms of the GNU General Public License as published |
@@ -739,7 +739,8 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group) | |||
739 | } | 739 | } |
740 | 740 | ||
741 | static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, | 741 | static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, |
742 | int flags, struct file *f) | 742 | int flags, struct file *f, |
743 | int (*open)(struct inode *, struct file *)) | ||
743 | { | 744 | { |
744 | struct inode *inode; | 745 | struct inode *inode; |
745 | int error; | 746 | int error; |
@@ -761,11 +762,14 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, | |||
761 | f->f_op = fops_get(inode->i_fop); | 762 | f->f_op = fops_get(inode->i_fop); |
762 | file_move(f, &inode->i_sb->s_files); | 763 | file_move(f, &inode->i_sb->s_files); |
763 | 764 | ||
764 | if (f->f_op && f->f_op->open) { | 765 | if (!open && f->f_op) |
765 | error = f->f_op->open(inode,f); | 766 | open = f->f_op->open; |
767 | if (open) { | ||
768 | error = open(inode, f); | ||
766 | if (error) | 769 | if (error) |
767 | goto cleanup_all; | 770 | goto cleanup_all; |
768 | } | 771 | } |
772 | |||
769 | f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); | 773 | f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); |
770 | 774 | ||
771 | file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping); | 775 | file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping); |
@@ -814,28 +818,75 @@ struct file *filp_open(const char * filename, int flags, int mode) | |||
814 | { | 818 | { |
815 | int namei_flags, error; | 819 | int namei_flags, error; |
816 | struct nameidata nd; | 820 | struct nameidata nd; |
817 | struct file *f; | ||
818 | 821 | ||
819 | namei_flags = flags; | 822 | namei_flags = flags; |
820 | if ((namei_flags+1) & O_ACCMODE) | 823 | if ((namei_flags+1) & O_ACCMODE) |
821 | namei_flags++; | 824 | namei_flags++; |
822 | if (namei_flags & O_TRUNC) | ||
823 | namei_flags |= 2; | ||
824 | |||
825 | error = -ENFILE; | ||
826 | f = get_empty_filp(); | ||
827 | if (f == NULL) | ||
828 | return ERR_PTR(error); | ||
829 | 825 | ||
830 | error = open_namei(filename, namei_flags, mode, &nd); | 826 | error = open_namei(filename, namei_flags, mode, &nd); |
831 | if (!error) | 827 | if (!error) |
832 | return __dentry_open(nd.dentry, nd.mnt, flags, f); | 828 | return nameidata_to_filp(&nd, flags); |
833 | 829 | ||
834 | put_filp(f); | ||
835 | return ERR_PTR(error); | 830 | return ERR_PTR(error); |
836 | } | 831 | } |
837 | EXPORT_SYMBOL(filp_open); | 832 | EXPORT_SYMBOL(filp_open); |
838 | 833 | ||
834 | /** | ||
835 | * lookup_instantiate_filp - instantiates the open intent filp | ||
836 | * @nd: pointer to nameidata | ||
837 | * @dentry: pointer to dentry | ||
838 | * @open: open callback | ||
839 | * | ||
840 | * Helper for filesystems that want to use lookup open intents and pass back | ||
841 | * a fully instantiated struct file to the caller. | ||
842 | * This function is meant to be called from within a filesystem's | ||
843 | * lookup method. | ||
844 | * Note that in case of error, nd->intent.open.file is destroyed, but the | ||
845 | * path information remains valid. | ||
846 | * If the open callback is set to NULL, then the standard f_op->open() | ||
847 | * filesystem callback is substituted. | ||
848 | */ | ||
849 | struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry, | ||
850 | int (*open)(struct inode *, struct file *)) | ||
851 | { | ||
852 | if (IS_ERR(nd->intent.open.file)) | ||
853 | goto out; | ||
854 | if (IS_ERR(dentry)) | ||
855 | goto out_err; | ||
856 | nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->mnt), | ||
857 | nd->intent.open.flags - 1, | ||
858 | nd->intent.open.file, | ||
859 | open); | ||
860 | out: | ||
861 | return nd->intent.open.file; | ||
862 | out_err: | ||
863 | release_open_intent(nd); | ||
864 | nd->intent.open.file = (struct file *)dentry; | ||
865 | goto out; | ||
866 | } | ||
867 | EXPORT_SYMBOL_GPL(lookup_instantiate_filp); | ||
868 | |||
869 | /** | ||
870 | * nameidata_to_filp - convert a nameidata to an open filp. | ||
871 | * @nd: pointer to nameidata | ||
872 | * @flags: open flags | ||
873 | * | ||
874 | * Note that this function destroys the original nameidata | ||
875 | */ | ||
876 | struct file *nameidata_to_filp(struct nameidata *nd, int flags) | ||
877 | { | ||
878 | struct file *filp; | ||
879 | |||
880 | /* Pick up the filp from the open intent */ | ||
881 | filp = nd->intent.open.file; | ||
882 | /* Has the filesystem initialised the file for us? */ | ||
883 | if (filp->f_dentry == NULL) | ||
884 | filp = __dentry_open(nd->dentry, nd->mnt, flags, filp, NULL); | ||
885 | else | ||
886 | path_release(nd); | ||
887 | return filp; | ||
888 | } | ||
889 | |||
839 | struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) | 890 | struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) |
840 | { | 891 | { |
841 | int error; | 892 | int error; |
@@ -846,7 +897,7 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) | |||
846 | if (f == NULL) | 897 | if (f == NULL) |
847 | return ERR_PTR(error); | 898 | return ERR_PTR(error); |
848 | 899 | ||
849 | return __dentry_open(dentry, mnt, flags, f); | 900 | return __dentry_open(dentry, mnt, flags, f, NULL); |
850 | } | 901 | } |
851 | EXPORT_SYMBOL(dentry_open); | 902 | EXPORT_SYMBOL(dentry_open); |
852 | 903 | ||
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 77e178f13162..1e848648a322 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
@@ -430,7 +430,7 @@ void del_gendisk(struct gendisk *disk) | |||
430 | disk->flags &= ~GENHD_FL_UP; | 430 | disk->flags &= ~GENHD_FL_UP; |
431 | unlink_gendisk(disk); | 431 | unlink_gendisk(disk); |
432 | disk_stat_set_all(disk, 0); | 432 | disk_stat_set_all(disk, 0); |
433 | disk->stamp = disk->stamp_idle = 0; | 433 | disk->stamp = 0; |
434 | 434 | ||
435 | devfs_remove_disk(disk); | 435 | devfs_remove_disk(disk); |
436 | 436 | ||
diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 296480e96dd5..6c8dcf7613fd 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c | |||
@@ -35,7 +35,7 @@ EXPORT_SYMBOL(posix_acl_permission); | |||
35 | * Allocate a new ACL with the specified number of entries. | 35 | * Allocate a new ACL with the specified number of entries. |
36 | */ | 36 | */ |
37 | struct posix_acl * | 37 | struct posix_acl * |
38 | posix_acl_alloc(int count, unsigned int __nocast flags) | 38 | posix_acl_alloc(int count, gfp_t flags) |
39 | { | 39 | { |
40 | const size_t size = sizeof(struct posix_acl) + | 40 | const size_t size = sizeof(struct posix_acl) + |
41 | count * sizeof(struct posix_acl_entry); | 41 | count * sizeof(struct posix_acl_entry); |
@@ -51,7 +51,7 @@ posix_acl_alloc(int count, unsigned int __nocast flags) | |||
51 | * Clone an ACL. | 51 | * Clone an ACL. |
52 | */ | 52 | */ |
53 | struct posix_acl * | 53 | struct posix_acl * |
54 | posix_acl_clone(const struct posix_acl *acl, unsigned int __nocast flags) | 54 | posix_acl_clone(const struct posix_acl *acl, gfp_t flags) |
55 | { | 55 | { |
56 | struct posix_acl *clone = NULL; | 56 | struct posix_acl *clone = NULL; |
57 | 57 | ||
@@ -185,7 +185,7 @@ posix_acl_equiv_mode(const struct posix_acl *acl, mode_t *mode_p) | |||
185 | * Create an ACL representing the file mode permission bits of an inode. | 185 | * Create an ACL representing the file mode permission bits of an inode. |
186 | */ | 186 | */ |
187 | struct posix_acl * | 187 | struct posix_acl * |
188 | posix_acl_from_mode(mode_t mode, unsigned int __nocast flags) | 188 | posix_acl_from_mode(mode_t mode, gfp_t flags) |
189 | { | 189 | { |
190 | struct posix_acl *acl = posix_acl_alloc(3, flags); | 190 | struct posix_acl *acl = posix_acl_alloc(3, flags); |
191 | if (!acl) | 191 | if (!acl) |
diff --git a/fs/proc/base.c b/fs/proc/base.c index fb34f88a4a74..a170450aadb1 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -103,7 +103,9 @@ enum pid_directory_inos { | |||
103 | PROC_TGID_NUMA_MAPS, | 103 | PROC_TGID_NUMA_MAPS, |
104 | PROC_TGID_MOUNTS, | 104 | PROC_TGID_MOUNTS, |
105 | PROC_TGID_WCHAN, | 105 | PROC_TGID_WCHAN, |
106 | #ifdef CONFIG_MMU | ||
106 | PROC_TGID_SMAPS, | 107 | PROC_TGID_SMAPS, |
108 | #endif | ||
107 | #ifdef CONFIG_SCHEDSTATS | 109 | #ifdef CONFIG_SCHEDSTATS |
108 | PROC_TGID_SCHEDSTAT, | 110 | PROC_TGID_SCHEDSTAT, |
109 | #endif | 111 | #endif |
@@ -141,7 +143,9 @@ enum pid_directory_inos { | |||
141 | PROC_TID_NUMA_MAPS, | 143 | PROC_TID_NUMA_MAPS, |
142 | PROC_TID_MOUNTS, | 144 | PROC_TID_MOUNTS, |
143 | PROC_TID_WCHAN, | 145 | PROC_TID_WCHAN, |
146 | #ifdef CONFIG_MMU | ||
144 | PROC_TID_SMAPS, | 147 | PROC_TID_SMAPS, |
148 | #endif | ||
145 | #ifdef CONFIG_SCHEDSTATS | 149 | #ifdef CONFIG_SCHEDSTATS |
146 | PROC_TID_SCHEDSTAT, | 150 | PROC_TID_SCHEDSTAT, |
147 | #endif | 151 | #endif |
@@ -195,7 +199,9 @@ static struct pid_entry tgid_base_stuff[] = { | |||
195 | E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO), | 199 | E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO), |
196 | E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO), | 200 | E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO), |
197 | E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO), | 201 | E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO), |
202 | #ifdef CONFIG_MMU | ||
198 | E(PROC_TGID_SMAPS, "smaps", S_IFREG|S_IRUGO), | 203 | E(PROC_TGID_SMAPS, "smaps", S_IFREG|S_IRUGO), |
204 | #endif | ||
199 | #ifdef CONFIG_SECURITY | 205 | #ifdef CONFIG_SECURITY |
200 | E(PROC_TGID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO), | 206 | E(PROC_TGID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO), |
201 | #endif | 207 | #endif |
@@ -235,7 +241,9 @@ static struct pid_entry tid_base_stuff[] = { | |||
235 | E(PROC_TID_ROOT, "root", S_IFLNK|S_IRWXUGO), | 241 | E(PROC_TID_ROOT, "root", S_IFLNK|S_IRWXUGO), |
236 | E(PROC_TID_EXE, "exe", S_IFLNK|S_IRWXUGO), | 242 | E(PROC_TID_EXE, "exe", S_IFLNK|S_IRWXUGO), |
237 | E(PROC_TID_MOUNTS, "mounts", S_IFREG|S_IRUGO), | 243 | E(PROC_TID_MOUNTS, "mounts", S_IFREG|S_IRUGO), |
244 | #ifdef CONFIG_MMU | ||
238 | E(PROC_TID_SMAPS, "smaps", S_IFREG|S_IRUGO), | 245 | E(PROC_TID_SMAPS, "smaps", S_IFREG|S_IRUGO), |
246 | #endif | ||
239 | #ifdef CONFIG_SECURITY | 247 | #ifdef CONFIG_SECURITY |
240 | E(PROC_TID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO), | 248 | E(PROC_TID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO), |
241 | #endif | 249 | #endif |
@@ -343,7 +351,8 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf | |||
343 | 351 | ||
344 | /* Same as proc_root_link, but this addionally tries to get fs from other | 352 | /* Same as proc_root_link, but this addionally tries to get fs from other |
345 | * threads in the group */ | 353 | * threads in the group */ |
346 | static int proc_task_root_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) | 354 | static int proc_task_root_link(struct inode *inode, struct dentry **dentry, |
355 | struct vfsmount **mnt) | ||
347 | { | 356 | { |
348 | struct fs_struct *fs; | 357 | struct fs_struct *fs; |
349 | int result = -ENOENT; | 358 | int result = -ENOENT; |
@@ -357,9 +366,10 @@ static int proc_task_root_link(struct inode *inode, struct dentry **dentry, stru | |||
357 | } else { | 366 | } else { |
358 | /* Try to get fs from other threads */ | 367 | /* Try to get fs from other threads */ |
359 | task_unlock(leader); | 368 | task_unlock(leader); |
360 | struct task_struct *task = leader; | ||
361 | read_lock(&tasklist_lock); | 369 | read_lock(&tasklist_lock); |
362 | if (pid_alive(task)) { | 370 | if (pid_alive(leader)) { |
371 | struct task_struct *task = leader; | ||
372 | |||
363 | while ((task = next_thread(task)) != leader) { | 373 | while ((task = next_thread(task)) != leader) { |
364 | task_lock(task); | 374 | task_lock(task); |
365 | fs = task->fs; | 375 | fs = task->fs; |
@@ -628,6 +638,7 @@ static struct file_operations proc_numa_maps_operations = { | |||
628 | }; | 638 | }; |
629 | #endif | 639 | #endif |
630 | 640 | ||
641 | #ifdef CONFIG_MMU | ||
631 | extern struct seq_operations proc_pid_smaps_op; | 642 | extern struct seq_operations proc_pid_smaps_op; |
632 | static int smaps_open(struct inode *inode, struct file *file) | 643 | static int smaps_open(struct inode *inode, struct file *file) |
633 | { | 644 | { |
@@ -646,6 +657,7 @@ static struct file_operations proc_smaps_operations = { | |||
646 | .llseek = seq_lseek, | 657 | .llseek = seq_lseek, |
647 | .release = seq_release, | 658 | .release = seq_release, |
648 | }; | 659 | }; |
660 | #endif | ||
649 | 661 | ||
650 | extern struct seq_operations mounts_op; | 662 | extern struct seq_operations mounts_op; |
651 | static int mounts_open(struct inode *inode, struct file *file) | 663 | static int mounts_open(struct inode *inode, struct file *file) |
@@ -1679,10 +1691,12 @@ static struct dentry *proc_pident_lookup(struct inode *dir, | |||
1679 | case PROC_TGID_MOUNTS: | 1691 | case PROC_TGID_MOUNTS: |
1680 | inode->i_fop = &proc_mounts_operations; | 1692 | inode->i_fop = &proc_mounts_operations; |
1681 | break; | 1693 | break; |
1694 | #ifdef CONFIG_MMU | ||
1682 | case PROC_TID_SMAPS: | 1695 | case PROC_TID_SMAPS: |
1683 | case PROC_TGID_SMAPS: | 1696 | case PROC_TGID_SMAPS: |
1684 | inode->i_fop = &proc_smaps_operations; | 1697 | inode->i_fop = &proc_smaps_operations; |
1685 | break; | 1698 | break; |
1699 | #endif | ||
1686 | #ifdef CONFIG_SECURITY | 1700 | #ifdef CONFIG_SECURITY |
1687 | case PROC_TID_ATTR: | 1701 | case PROC_TID_ATTR: |
1688 | inode->i_nlink = 2; | 1702 | inode->i_nlink = 2; |
diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c index f3bf016d5ee3..cff10ab1af63 100644 --- a/fs/proc/nommu.c +++ b/fs/proc/nommu.c | |||
@@ -91,6 +91,7 @@ static void *nommu_vma_list_start(struct seq_file *m, loff_t *_pos) | |||
91 | next = _rb; | 91 | next = _rb; |
92 | break; | 92 | break; |
93 | } | 93 | } |
94 | pos--; | ||
94 | } | 95 | } |
95 | 96 | ||
96 | return next; | 97 | return next; |
diff --git a/fs/read_write.c b/fs/read_write.c index b60324aaa2b6..a091ee4f430d 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
@@ -499,6 +499,9 @@ static ssize_t do_readv_writev(int type, struct file *file, | |||
499 | ret = rw_verify_area(type, file, pos, tot_len); | 499 | ret = rw_verify_area(type, file, pos, tot_len); |
500 | if (ret) | 500 | if (ret) |
501 | goto out; | 501 | goto out; |
502 | ret = security_file_permission(file, type == READ ? MAY_READ : MAY_WRITE); | ||
503 | if (ret) | ||
504 | goto out; | ||
502 | 505 | ||
503 | fnv = NULL; | 506 | fnv = NULL; |
504 | if (type == READ) { | 507 | if (type == READ) { |
diff --git a/fs/reiserfs/fix_node.c b/fs/reiserfs/fix_node.c index 2706e2adffab..45829889dcdc 100644 --- a/fs/reiserfs/fix_node.c +++ b/fs/reiserfs/fix_node.c | |||
@@ -2022,7 +2022,7 @@ static int get_neighbors(struct tree_balance *p_s_tb, int n_h) | |||
2022 | } | 2022 | } |
2023 | 2023 | ||
2024 | #ifdef CONFIG_REISERFS_CHECK | 2024 | #ifdef CONFIG_REISERFS_CHECK |
2025 | void *reiserfs_kmalloc(size_t size, int flags, struct super_block *s) | 2025 | void *reiserfs_kmalloc(size_t size, gfp_t flags, struct super_block *s) |
2026 | { | 2026 | { |
2027 | void *vp; | 2027 | void *vp; |
2028 | static size_t malloced; | 2028 | static size_t malloced; |
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index d76ee6c4f9b8..5f82352b97e1 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
@@ -2842,7 +2842,7 @@ static int reiserfs_set_page_dirty(struct page *page) | |||
2842 | * even in -o notail mode, we can't be sure an old mount without -o notail | 2842 | * even in -o notail mode, we can't be sure an old mount without -o notail |
2843 | * didn't create files with tails. | 2843 | * didn't create files with tails. |
2844 | */ | 2844 | */ |
2845 | static int reiserfs_releasepage(struct page *page, int unused_gfp_flags) | 2845 | static int reiserfs_releasepage(struct page *page, gfp_t unused_gfp_flags) |
2846 | { | 2846 | { |
2847 | struct inode *inode = page->mapping->host; | 2847 | struct inode *inode = page->mapping->host; |
2848 | struct reiserfs_journal *j = SB_JOURNAL(inode->i_sb); | 2848 | struct reiserfs_journal *j = SB_JOURNAL(inode->i_sb); |
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 87ac9dc8b381..72e120798677 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
@@ -453,7 +453,7 @@ static struct page *reiserfs_get_page(struct inode *dir, unsigned long n) | |||
453 | struct page *page; | 453 | struct page *page; |
454 | /* We can deadlock if we try to free dentries, | 454 | /* We can deadlock if we try to free dentries, |
455 | and an unlink/rmdir has just occured - GFP_NOFS avoids this */ | 455 | and an unlink/rmdir has just occured - GFP_NOFS avoids this */ |
456 | mapping->flags = (mapping->flags & ~__GFP_BITS_MASK) | GFP_NOFS; | 456 | mapping_set_gfp_mask(mapping, GFP_NOFS); |
457 | page = read_cache_page(mapping, n, | 457 | page = read_cache_page(mapping, n, |
458 | (filler_t *) mapping->a_ops->readpage, NULL); | 458 | (filler_t *) mapping->a_ops->readpage, NULL); |
459 | if (!IS_ERR(page)) { | 459 | if (!IS_ERR(page)) { |
diff --git a/fs/relayfs/buffers.c b/fs/relayfs/buffers.c index 2aa8e2719999..84e21ffa5ca8 100644 --- a/fs/relayfs/buffers.c +++ b/fs/relayfs/buffers.c | |||
@@ -109,7 +109,7 @@ static void *relay_alloc_buf(struct rchan_buf *buf, unsigned long size) | |||
109 | if (unlikely(!buf->page_array[i])) | 109 | if (unlikely(!buf->page_array[i])) |
110 | goto depopulate; | 110 | goto depopulate; |
111 | } | 111 | } |
112 | mem = vmap(buf->page_array, n_pages, GFP_KERNEL, PAGE_KERNEL); | 112 | mem = vmap(buf->page_array, n_pages, VM_MAP, PAGE_KERNEL); |
113 | if (!mem) | 113 | if (!mem) |
114 | goto depopulate; | 114 | goto depopulate; |
115 | 115 | ||
diff --git a/fs/xfs/linux-2.6/kmem.c b/fs/xfs/linux-2.6/kmem.c index 4b184559f231..3c92162dc728 100644 --- a/fs/xfs/linux-2.6/kmem.c +++ b/fs/xfs/linux-2.6/kmem.c | |||
@@ -47,9 +47,9 @@ | |||
47 | void * | 47 | void * |
48 | kmem_alloc(size_t size, unsigned int __nocast flags) | 48 | kmem_alloc(size_t size, unsigned int __nocast flags) |
49 | { | 49 | { |
50 | int retries = 0; | 50 | int retries = 0; |
51 | unsigned int lflags = kmem_flags_convert(flags); | 51 | gfp_t lflags = kmem_flags_convert(flags); |
52 | void *ptr; | 52 | void *ptr; |
53 | 53 | ||
54 | do { | 54 | do { |
55 | if (size < MAX_SLAB_SIZE || retries > MAX_VMALLOCS) | 55 | if (size < MAX_SLAB_SIZE || retries > MAX_VMALLOCS) |
@@ -107,9 +107,9 @@ kmem_realloc(void *ptr, size_t newsize, size_t oldsize, | |||
107 | void * | 107 | void * |
108 | kmem_zone_alloc(kmem_zone_t *zone, unsigned int __nocast flags) | 108 | kmem_zone_alloc(kmem_zone_t *zone, unsigned int __nocast flags) |
109 | { | 109 | { |
110 | int retries = 0; | 110 | int retries = 0; |
111 | unsigned int lflags = kmem_flags_convert(flags); | 111 | gfp_t lflags = kmem_flags_convert(flags); |
112 | void *ptr; | 112 | void *ptr; |
113 | 113 | ||
114 | do { | 114 | do { |
115 | ptr = kmem_cache_alloc(zone, lflags); | 115 | ptr = kmem_cache_alloc(zone, lflags); |
diff --git a/fs/xfs/linux-2.6/kmem.h b/fs/xfs/linux-2.6/kmem.h index 109fcf27e256..f4bb78c268c0 100644 --- a/fs/xfs/linux-2.6/kmem.h +++ b/fs/xfs/linux-2.6/kmem.h | |||
@@ -81,9 +81,9 @@ typedef unsigned long xfs_pflags_t; | |||
81 | *(NSTATEP) = *(OSTATEP); \ | 81 | *(NSTATEP) = *(OSTATEP); \ |
82 | } while (0) | 82 | } while (0) |
83 | 83 | ||
84 | static __inline unsigned int kmem_flags_convert(unsigned int __nocast flags) | 84 | static __inline gfp_t kmem_flags_convert(unsigned int __nocast flags) |
85 | { | 85 | { |
86 | unsigned int lflags = __GFP_NOWARN; /* we'll report problems, if need be */ | 86 | gfp_t lflags = __GFP_NOWARN; /* we'll report problems, if need be */ |
87 | 87 | ||
88 | #ifdef DEBUG | 88 | #ifdef DEBUG |
89 | if (unlikely(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS|KM_MAYFAIL))) { | 89 | if (unlikely(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS|KM_MAYFAIL))) { |
@@ -129,13 +129,12 @@ extern void *kmem_zone_zalloc(kmem_zone_t *, unsigned int __nocast); | |||
129 | extern void *kmem_zone_alloc(kmem_zone_t *, unsigned int __nocast); | 129 | extern void *kmem_zone_alloc(kmem_zone_t *, unsigned int __nocast); |
130 | 130 | ||
131 | extern void *kmem_alloc(size_t, unsigned int __nocast); | 131 | extern void *kmem_alloc(size_t, unsigned int __nocast); |
132 | extern void *kmem_realloc(void *, size_t, size_t, | 132 | extern void *kmem_realloc(void *, size_t, size_t, unsigned int __nocast); |
133 | unsigned int __nocast); | ||
134 | extern void *kmem_zalloc(size_t, unsigned int __nocast); | 133 | extern void *kmem_zalloc(size_t, unsigned int __nocast); |
135 | extern void kmem_free(void *, size_t); | 134 | extern void kmem_free(void *, size_t); |
136 | 135 | ||
137 | typedef struct shrinker *kmem_shaker_t; | 136 | typedef struct shrinker *kmem_shaker_t; |
138 | typedef int (*kmem_shake_func_t)(int, unsigned int); | 137 | typedef int (*kmem_shake_func_t)(int, gfp_t); |
139 | 138 | ||
140 | static __inline kmem_shaker_t | 139 | static __inline kmem_shaker_t |
141 | kmem_shake_register(kmem_shake_func_t sfunc) | 140 | kmem_shake_register(kmem_shake_func_t sfunc) |
@@ -150,7 +149,7 @@ kmem_shake_deregister(kmem_shaker_t shrinker) | |||
150 | } | 149 | } |
151 | 150 | ||
152 | static __inline int | 151 | static __inline int |
153 | kmem_shake_allow(unsigned int gfp_mask) | 152 | kmem_shake_allow(gfp_t gfp_mask) |
154 | { | 153 | { |
155 | return (gfp_mask & __GFP_WAIT); | 154 | return (gfp_mask & __GFP_WAIT); |
156 | } | 155 | } |
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index c6c077978fe3..7aa398724706 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
@@ -1296,7 +1296,7 @@ linvfs_invalidate_page( | |||
1296 | STATIC int | 1296 | STATIC int |
1297 | linvfs_release_page( | 1297 | linvfs_release_page( |
1298 | struct page *page, | 1298 | struct page *page, |
1299 | int gfp_mask) | 1299 | gfp_t gfp_mask) |
1300 | { | 1300 | { |
1301 | struct inode *inode = page->mapping->host; | 1301 | struct inode *inode = page->mapping->host; |
1302 | int dirty, delalloc, unmapped, unwritten; | 1302 | int dirty, delalloc, unmapped, unwritten; |
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index e82cf72ac599..ba4767c04adf 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c | |||
@@ -64,7 +64,7 @@ | |||
64 | 64 | ||
65 | STATIC kmem_cache_t *pagebuf_zone; | 65 | STATIC kmem_cache_t *pagebuf_zone; |
66 | STATIC kmem_shaker_t pagebuf_shake; | 66 | STATIC kmem_shaker_t pagebuf_shake; |
67 | STATIC int xfsbufd_wakeup(int, unsigned int); | 67 | STATIC int xfsbufd_wakeup(int, gfp_t); |
68 | STATIC void pagebuf_delwri_queue(xfs_buf_t *, int); | 68 | STATIC void pagebuf_delwri_queue(xfs_buf_t *, int); |
69 | 69 | ||
70 | STATIC struct workqueue_struct *xfslogd_workqueue; | 70 | STATIC struct workqueue_struct *xfslogd_workqueue; |
@@ -383,7 +383,7 @@ _pagebuf_lookup_pages( | |||
383 | size_t blocksize = bp->pb_target->pbr_bsize; | 383 | size_t blocksize = bp->pb_target->pbr_bsize; |
384 | size_t size = bp->pb_count_desired; | 384 | size_t size = bp->pb_count_desired; |
385 | size_t nbytes, offset; | 385 | size_t nbytes, offset; |
386 | int gfp_mask = pb_to_gfp(flags); | 386 | gfp_t gfp_mask = pb_to_gfp(flags); |
387 | unsigned short page_count, i; | 387 | unsigned short page_count, i; |
388 | pgoff_t first; | 388 | pgoff_t first; |
389 | loff_t end; | 389 | loff_t end; |
@@ -1749,8 +1749,8 @@ STATIC int xfsbufd_force_sleep; | |||
1749 | 1749 | ||
1750 | STATIC int | 1750 | STATIC int |
1751 | xfsbufd_wakeup( | 1751 | xfsbufd_wakeup( |
1752 | int priority, | 1752 | int priority, |
1753 | unsigned int mask) | 1753 | gfp_t mask) |
1754 | { | 1754 | { |
1755 | if (xfsbufd_force_sleep) | 1755 | if (xfsbufd_force_sleep) |
1756 | return 0; | 1756 | return 0; |