1 |
1275 |
phoenix |
/*
|
2 |
|
|
* linux/fs/nfs/dir.c
|
3 |
|
|
*
|
4 |
|
|
* Copyright (C) 1992 Rick Sladkey
|
5 |
|
|
*
|
6 |
|
|
* nfs directory handling functions
|
7 |
|
|
*
|
8 |
|
|
* 10 Apr 1996 Added silly rename for unlink --okir
|
9 |
|
|
* 28 Sep 1996 Improved directory cache --okir
|
10 |
|
|
* 23 Aug 1997 Claus Heine claus@momo.math.rwth-aachen.de
|
11 |
|
|
* Re-implemented silly rename for unlink, newly implemented
|
12 |
|
|
* silly rename for nfs_rename() following the suggestions
|
13 |
|
|
* of Olaf Kirch (okir) found in this file.
|
14 |
|
|
* Following Linus comments on my original hack, this version
|
15 |
|
|
* depends only on the dcache stuff and doesn't touch the inode
|
16 |
|
|
* layer (iput() and friends).
|
17 |
|
|
* 6 Jun 1999 Cache readdir lookups in the page cache. -DaveM
|
18 |
|
|
*/
|
19 |
|
|
|
20 |
|
|
#include <linux/sched.h>
|
21 |
|
|
#include <linux/errno.h>
|
22 |
|
|
#include <linux/stat.h>
|
23 |
|
|
#include <linux/fcntl.h>
|
24 |
|
|
#include <linux/string.h>
|
25 |
|
|
#include <linux/kernel.h>
|
26 |
|
|
#include <linux/slab.h>
|
27 |
|
|
#include <linux/mm.h>
|
28 |
|
|
#include <linux/sunrpc/clnt.h>
|
29 |
|
|
#include <linux/nfs_fs.h>
|
30 |
|
|
#include <linux/nfs_mount.h>
|
31 |
|
|
#include <linux/pagemap.h>
|
32 |
|
|
#include <linux/smp_lock.h>
|
33 |
|
|
|
34 |
|
|
#define NFS_PARANOIA 1
|
35 |
|
|
/* #define NFS_DEBUG_VERBOSE 1 */
|
36 |
|
|
|
37 |
|
|
static int nfs_readdir(struct file *, void *, filldir_t);
|
38 |
|
|
static struct dentry *nfs_lookup(struct inode *, struct dentry *);
|
39 |
|
|
static int nfs_create(struct inode *, struct dentry *, int);
|
40 |
|
|
static int nfs_mkdir(struct inode *, struct dentry *, int);
|
41 |
|
|
static int nfs_rmdir(struct inode *, struct dentry *);
|
42 |
|
|
static int nfs_unlink(struct inode *, struct dentry *);
|
43 |
|
|
static int nfs_symlink(struct inode *, struct dentry *, const char *);
|
44 |
|
|
static int nfs_link(struct dentry *, struct inode *, struct dentry *);
|
45 |
|
|
static int nfs_mknod(struct inode *, struct dentry *, int, int);
|
46 |
|
|
static int nfs_rename(struct inode *, struct dentry *,
|
47 |
|
|
struct inode *, struct dentry *);
|
48 |
|
|
static int nfs_fsync_dir(struct file *, struct dentry *, int);
|
49 |
|
|
|
50 |
|
|
struct file_operations nfs_dir_operations = {
|
51 |
|
|
read: generic_read_dir,
|
52 |
|
|
readdir: nfs_readdir,
|
53 |
|
|
open: nfs_open,
|
54 |
|
|
release: nfs_release,
|
55 |
|
|
fsync: nfs_fsync_dir
|
56 |
|
|
};
|
57 |
|
|
|
58 |
|
|
struct inode_operations nfs_dir_inode_operations = {
|
59 |
|
|
create: nfs_create,
|
60 |
|
|
lookup: nfs_lookup,
|
61 |
|
|
link: nfs_link,
|
62 |
|
|
unlink: nfs_unlink,
|
63 |
|
|
symlink: nfs_symlink,
|
64 |
|
|
mkdir: nfs_mkdir,
|
65 |
|
|
rmdir: nfs_rmdir,
|
66 |
|
|
mknod: nfs_mknod,
|
67 |
|
|
rename: nfs_rename,
|
68 |
|
|
permission: nfs_permission,
|
69 |
|
|
revalidate: nfs_revalidate,
|
70 |
|
|
setattr: nfs_notify_change,
|
71 |
|
|
};
|
72 |
|
|
|
73 |
|
|
typedef u32 * (*decode_dirent_t)(u32 *, struct nfs_entry *, int);
|
74 |
|
|
typedef struct {
|
75 |
|
|
struct file *file;
|
76 |
|
|
struct page *page;
|
77 |
|
|
unsigned long page_index;
|
78 |
|
|
u32 *ptr;
|
79 |
|
|
u64 target;
|
80 |
|
|
struct nfs_entry *entry;
|
81 |
|
|
decode_dirent_t decode;
|
82 |
|
|
int plus;
|
83 |
|
|
int error;
|
84 |
|
|
} nfs_readdir_descriptor_t;
|
85 |
|
|
|
86 |
|
|
/* Now we cache directories properly, by stuffing the dirent
|
87 |
|
|
* data directly in the page cache.
|
88 |
|
|
*
|
89 |
|
|
* Inode invalidation due to refresh etc. takes care of
|
90 |
|
|
* _everything_, no sloppy entry flushing logic, no extraneous
|
91 |
|
|
* copying, network direct to page cache, the way it was meant
|
92 |
|
|
* to be.
|
93 |
|
|
*
|
94 |
|
|
* NOTE: Dirent information verification is done always by the
|
95 |
|
|
* page-in of the RPC reply, nowhere else, this simplies
|
96 |
|
|
* things substantially.
|
97 |
|
|
*/
|
98 |
|
|
static
|
99 |
|
|
int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
|
100 |
|
|
{
|
101 |
|
|
struct file *file = desc->file;
|
102 |
|
|
struct inode *inode = file->f_dentry->d_inode;
|
103 |
|
|
struct rpc_cred *cred = nfs_file_cred(file);
|
104 |
|
|
int error;
|
105 |
|
|
|
106 |
|
|
dfprintk(VFS, "NFS: nfs_readdir_filler() reading cookie %Lu into page %lu.\n", (long long)desc->entry->cookie, page->index);
|
107 |
|
|
|
108 |
|
|
again:
|
109 |
|
|
error = NFS_PROTO(inode)->readdir(inode, cred, desc->entry->cookie, page,
|
110 |
|
|
NFS_SERVER(inode)->dtsize, desc->plus);
|
111 |
|
|
/* We requested READDIRPLUS, but the server doesn't grok it */
|
112 |
|
|
if (desc->plus && error == -ENOTSUPP) {
|
113 |
|
|
NFS_FLAGS(inode) &= ~NFS_INO_ADVISE_RDPLUS;
|
114 |
|
|
desc->plus = 0;
|
115 |
|
|
goto again;
|
116 |
|
|
}
|
117 |
|
|
if (error < 0)
|
118 |
|
|
goto error;
|
119 |
|
|
SetPageUptodate(page);
|
120 |
|
|
/* Ensure consistent page alignment of the data.
|
121 |
|
|
* Note: assumes we have exclusive access to this mapping either
|
122 |
|
|
* throught inode->i_sem or some other mechanism.
|
123 |
|
|
*/
|
124 |
|
|
if (page->index == 0)
|
125 |
|
|
invalidate_inode_pages(inode);
|
126 |
|
|
UnlockPage(page);
|
127 |
|
|
return 0;
|
128 |
|
|
error:
|
129 |
|
|
SetPageError(page);
|
130 |
|
|
UnlockPage(page);
|
131 |
|
|
invalidate_inode_pages(inode);
|
132 |
|
|
desc->error = error;
|
133 |
|
|
return -EIO;
|
134 |
|
|
}
|
135 |
|
|
|
136 |
|
|
static inline
|
137 |
|
|
int dir_decode(nfs_readdir_descriptor_t *desc)
|
138 |
|
|
{
|
139 |
|
|
u32 *p = desc->ptr;
|
140 |
|
|
p = desc->decode(p, desc->entry, desc->plus);
|
141 |
|
|
if (IS_ERR(p))
|
142 |
|
|
return PTR_ERR(p);
|
143 |
|
|
desc->ptr = p;
|
144 |
|
|
return 0;
|
145 |
|
|
}
|
146 |
|
|
|
147 |
|
|
static inline
|
148 |
|
|
void dir_page_release(nfs_readdir_descriptor_t *desc)
|
149 |
|
|
{
|
150 |
|
|
kunmap(desc->page);
|
151 |
|
|
page_cache_release(desc->page);
|
152 |
|
|
desc->page = NULL;
|
153 |
|
|
desc->ptr = NULL;
|
154 |
|
|
}
|
155 |
|
|
|
156 |
|
|
/*
|
157 |
|
|
* Given a pointer to a buffer that has already been filled by a call
|
158 |
|
|
* to readdir, find the next entry.
|
159 |
|
|
*
|
160 |
|
|
* If the end of the buffer has been reached, return -EAGAIN, if not,
|
161 |
|
|
* return the offset within the buffer of the next entry to be
|
162 |
|
|
* read.
|
163 |
|
|
*/
|
164 |
|
|
static inline
|
165 |
|
|
int find_dirent(nfs_readdir_descriptor_t *desc, struct page *page)
|
166 |
|
|
{
|
167 |
|
|
struct nfs_entry *entry = desc->entry;
|
168 |
|
|
int loop_count = 0,
|
169 |
|
|
status;
|
170 |
|
|
|
171 |
|
|
while((status = dir_decode(desc)) == 0) {
|
172 |
|
|
dfprintk(VFS, "NFS: found cookie %Lu\n", (long long)entry->cookie);
|
173 |
|
|
if (entry->prev_cookie == desc->target)
|
174 |
|
|
break;
|
175 |
|
|
if (loop_count++ > 200) {
|
176 |
|
|
loop_count = 0;
|
177 |
|
|
schedule();
|
178 |
|
|
}
|
179 |
|
|
}
|
180 |
|
|
dfprintk(VFS, "NFS: find_dirent() returns %d\n", status);
|
181 |
|
|
return status;
|
182 |
|
|
}
|
183 |
|
|
|
184 |
|
|
/*
|
185 |
|
|
* Find the given page, and call find_dirent() in order to try to
|
186 |
|
|
* return the next entry.
|
187 |
|
|
*/
|
188 |
|
|
static inline
|
189 |
|
|
int find_dirent_page(nfs_readdir_descriptor_t *desc)
|
190 |
|
|
{
|
191 |
|
|
struct inode *inode = desc->file->f_dentry->d_inode;
|
192 |
|
|
struct page *page;
|
193 |
|
|
int status;
|
194 |
|
|
|
195 |
|
|
dfprintk(VFS, "NFS: find_dirent_page() searching directory page %ld\n", desc->page_index);
|
196 |
|
|
|
197 |
|
|
desc->plus = NFS_USE_READDIRPLUS(inode);
|
198 |
|
|
page = read_cache_page(&inode->i_data, desc->page_index,
|
199 |
|
|
(filler_t *)nfs_readdir_filler, desc);
|
200 |
|
|
if (IS_ERR(page)) {
|
201 |
|
|
status = PTR_ERR(page);
|
202 |
|
|
goto out;
|
203 |
|
|
}
|
204 |
|
|
if (!Page_Uptodate(page))
|
205 |
|
|
goto read_error;
|
206 |
|
|
|
207 |
|
|
/* NOTE: Someone else may have changed the READDIRPLUS flag */
|
208 |
|
|
desc->page = page;
|
209 |
|
|
desc->ptr = kmap(page);
|
210 |
|
|
status = find_dirent(desc, page);
|
211 |
|
|
if (status < 0)
|
212 |
|
|
dir_page_release(desc);
|
213 |
|
|
out:
|
214 |
|
|
dfprintk(VFS, "NFS: find_dirent_page() returns %d\n", status);
|
215 |
|
|
return status;
|
216 |
|
|
read_error:
|
217 |
|
|
page_cache_release(page);
|
218 |
|
|
return -EIO;
|
219 |
|
|
}
|
220 |
|
|
|
221 |
|
|
/*
|
222 |
|
|
* Recurse through the page cache pages, and return a
|
223 |
|
|
* filled nfs_entry structure of the next directory entry if possible.
|
224 |
|
|
*
|
225 |
|
|
* The target for the search is 'desc->target'.
|
226 |
|
|
*/
|
227 |
|
|
static inline
|
228 |
|
|
int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
|
229 |
|
|
{
|
230 |
|
|
int loop_count = 0;
|
231 |
|
|
int res;
|
232 |
|
|
|
233 |
|
|
dfprintk(VFS, "NFS: readdir_search_pagecache() searching for cookie %Lu\n", (long long)desc->target);
|
234 |
|
|
for (;;) {
|
235 |
|
|
res = find_dirent_page(desc);
|
236 |
|
|
if (res != -EAGAIN)
|
237 |
|
|
break;
|
238 |
|
|
/* Align to beginning of next page */
|
239 |
|
|
desc->page_index ++;
|
240 |
|
|
if (loop_count++ > 200) {
|
241 |
|
|
loop_count = 0;
|
242 |
|
|
schedule();
|
243 |
|
|
}
|
244 |
|
|
}
|
245 |
|
|
dfprintk(VFS, "NFS: readdir_search_pagecache() returned %d\n", res);
|
246 |
|
|
return res;
|
247 |
|
|
}
|
248 |
|
|
|
249 |
|
|
/*
|
250 |
|
|
* Once we've found the start of the dirent within a page: fill 'er up...
|
251 |
|
|
*/
|
252 |
|
|
static
|
253 |
|
|
int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
|
254 |
|
|
filldir_t filldir)
|
255 |
|
|
{
|
256 |
|
|
struct file *file = desc->file;
|
257 |
|
|
struct nfs_entry *entry = desc->entry;
|
258 |
|
|
unsigned long fileid;
|
259 |
|
|
int loop_count = 0,
|
260 |
|
|
res;
|
261 |
|
|
|
262 |
|
|
dfprintk(VFS, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n", (long long)desc->target);
|
263 |
|
|
|
264 |
|
|
for(;;) {
|
265 |
|
|
/* Note: entry->prev_cookie contains the cookie for
|
266 |
|
|
* retrieving the current dirent on the server */
|
267 |
|
|
fileid = nfs_fileid_to_ino_t(entry->ino);
|
268 |
|
|
res = filldir(dirent, entry->name, entry->len,
|
269 |
|
|
entry->prev_cookie, fileid, DT_UNKNOWN);
|
270 |
|
|
if (res < 0)
|
271 |
|
|
break;
|
272 |
|
|
file->f_pos = desc->target = entry->cookie;
|
273 |
|
|
if (dir_decode(desc) != 0) {
|
274 |
|
|
desc->page_index ++;
|
275 |
|
|
break;
|
276 |
|
|
}
|
277 |
|
|
if (loop_count++ > 200) {
|
278 |
|
|
loop_count = 0;
|
279 |
|
|
schedule();
|
280 |
|
|
}
|
281 |
|
|
}
|
282 |
|
|
dir_page_release(desc);
|
283 |
|
|
|
284 |
|
|
dfprintk(VFS, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", (long long)desc->target, res);
|
285 |
|
|
return res;
|
286 |
|
|
}
|
287 |
|
|
|
288 |
|
|
/*
|
289 |
|
|
* If we cannot find a cookie in our cache, we suspect that this is
|
290 |
|
|
* because it points to a deleted file, so we ask the server to return
|
291 |
|
|
* whatever it thinks is the next entry. We then feed this to filldir.
|
292 |
|
|
* If all goes well, we should then be able to find our way round the
|
293 |
|
|
* cache on the next call to readdir_search_pagecache();
|
294 |
|
|
*
|
295 |
|
|
* NOTE: we cannot add the anonymous page to the pagecache because
|
296 |
|
|
* the data it contains might not be page aligned. Besides,
|
297 |
|
|
* we should already have a complete representation of the
|
298 |
|
|
* directory in the page cache by the time we get here.
|
299 |
|
|
*/
|
300 |
|
|
static inline
|
301 |
|
|
int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
|
302 |
|
|
filldir_t filldir)
|
303 |
|
|
{
|
304 |
|
|
struct file *file = desc->file;
|
305 |
|
|
struct inode *inode = file->f_dentry->d_inode;
|
306 |
|
|
struct rpc_cred *cred = nfs_file_cred(file);
|
307 |
|
|
struct page *page = NULL;
|
308 |
|
|
int status;
|
309 |
|
|
|
310 |
|
|
dfprintk(VFS, "NFS: uncached_readdir() searching for cookie %Lu\n", (long long)desc->target);
|
311 |
|
|
|
312 |
|
|
page = alloc_page(GFP_HIGHUSER);
|
313 |
|
|
if (!page) {
|
314 |
|
|
status = -ENOMEM;
|
315 |
|
|
goto out;
|
316 |
|
|
}
|
317 |
|
|
desc->error = NFS_PROTO(inode)->readdir(inode, cred, desc->target,
|
318 |
|
|
page,
|
319 |
|
|
NFS_SERVER(inode)->dtsize,
|
320 |
|
|
desc->plus);
|
321 |
|
|
desc->page = page;
|
322 |
|
|
desc->ptr = kmap(page);
|
323 |
|
|
if (desc->error >= 0) {
|
324 |
|
|
if ((status = dir_decode(desc)) == 0)
|
325 |
|
|
desc->entry->prev_cookie = desc->target;
|
326 |
|
|
} else
|
327 |
|
|
status = -EIO;
|
328 |
|
|
if (status < 0)
|
329 |
|
|
goto out_release;
|
330 |
|
|
|
331 |
|
|
status = nfs_do_filldir(desc, dirent, filldir);
|
332 |
|
|
|
333 |
|
|
/* Reset read descriptor so it searches the page cache from
|
334 |
|
|
* the start upon the next call to readdir_search_pagecache() */
|
335 |
|
|
desc->page_index = 0;
|
336 |
|
|
memset(desc->entry, 0, sizeof(*desc->entry));
|
337 |
|
|
out:
|
338 |
|
|
dfprintk(VFS, "NFS: uncached_readdir() returns %d\n", status);
|
339 |
|
|
return status;
|
340 |
|
|
out_release:
|
341 |
|
|
dir_page_release(desc);
|
342 |
|
|
goto out;
|
343 |
|
|
}
|
344 |
|
|
|
345 |
|
|
/* The file offset position is now represented as a true offset into the
|
346 |
|
|
* page cache as is the case in most of the other filesystems.
|
347 |
|
|
*/
|
348 |
|
|
static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
349 |
|
|
{
|
350 |
|
|
struct dentry *dentry = filp->f_dentry;
|
351 |
|
|
struct inode *inode = dentry->d_inode;
|
352 |
|
|
nfs_readdir_descriptor_t my_desc,
|
353 |
|
|
*desc = &my_desc;
|
354 |
|
|
struct nfs_entry my_entry;
|
355 |
|
|
long res;
|
356 |
|
|
|
357 |
|
|
res = nfs_revalidate(dentry);
|
358 |
|
|
if (res < 0)
|
359 |
|
|
return res;
|
360 |
|
|
|
361 |
|
|
/*
|
362 |
|
|
* filp->f_pos points to the file offset in the page cache.
|
363 |
|
|
* but if the cache has meanwhile been zapped, we need to
|
364 |
|
|
* read from the last dirent to revalidate f_pos
|
365 |
|
|
* itself.
|
366 |
|
|
*/
|
367 |
|
|
memset(desc, 0, sizeof(*desc));
|
368 |
|
|
memset(&my_entry, 0, sizeof(my_entry));
|
369 |
|
|
|
370 |
|
|
desc->file = filp;
|
371 |
|
|
desc->target = filp->f_pos;
|
372 |
|
|
desc->entry = &my_entry;
|
373 |
|
|
desc->decode = NFS_PROTO(inode)->decode_dirent;
|
374 |
|
|
|
375 |
|
|
while(!desc->entry->eof) {
|
376 |
|
|
res = readdir_search_pagecache(desc);
|
377 |
|
|
if (res == -EBADCOOKIE) {
|
378 |
|
|
/* This means either end of directory */
|
379 |
|
|
if (desc->entry->cookie != desc->target) {
|
380 |
|
|
/* Or that the server has 'lost' a cookie */
|
381 |
|
|
res = uncached_readdir(desc, dirent, filldir);
|
382 |
|
|
if (res >= 0)
|
383 |
|
|
continue;
|
384 |
|
|
}
|
385 |
|
|
res = 0;
|
386 |
|
|
break;
|
387 |
|
|
} else if (res < 0)
|
388 |
|
|
break;
|
389 |
|
|
|
390 |
|
|
res = nfs_do_filldir(desc, dirent, filldir);
|
391 |
|
|
if (res < 0) {
|
392 |
|
|
res = 0;
|
393 |
|
|
break;
|
394 |
|
|
}
|
395 |
|
|
}
|
396 |
|
|
if (desc->error < 0)
|
397 |
|
|
return desc->error;
|
398 |
|
|
if (res < 0)
|
399 |
|
|
return res;
|
400 |
|
|
return 0;
|
401 |
|
|
}
|
402 |
|
|
|
403 |
|
|
/*
|
404 |
|
|
* All directory operations under NFS are synchronous, so fsync()
|
405 |
|
|
* is a dummy operation.
|
406 |
|
|
*/
|
407 |
|
|
int nfs_fsync_dir(struct file *filp, struct dentry *dentry, int datasync)
|
408 |
|
|
{
|
409 |
|
|
return 0;
|
410 |
|
|
}
|
411 |
|
|
|
412 |
|
|
/*
|
413 |
|
|
* A check for whether or not the parent directory has changed.
|
414 |
|
|
* In the case it has, we assume that the dentries are untrustworthy
|
415 |
|
|
* and may need to be looked up again.
|
416 |
|
|
*/
|
417 |
|
|
static inline
|
418 |
|
|
int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
|
419 |
|
|
{
|
420 |
|
|
if (IS_ROOT(dentry))
|
421 |
|
|
return 1;
|
422 |
|
|
if (nfs_revalidate_inode(NFS_SERVER(dir), dir))
|
423 |
|
|
return 0;
|
424 |
|
|
return time_after(dentry->d_time, NFS_MTIME_UPDATE(dir));
|
425 |
|
|
}
|
426 |
|
|
|
427 |
|
|
/*
|
428 |
|
|
* Whenever an NFS operation succeeds, we know that the dentry
|
429 |
|
|
* is valid, so we update the revalidation timestamp.
|
430 |
|
|
*/
|
431 |
|
|
static inline void nfs_renew_times(struct dentry * dentry)
|
432 |
|
|
{
|
433 |
|
|
dentry->d_time = jiffies;
|
434 |
|
|
}
|
435 |
|
|
|
436 |
|
|
static inline
|
437 |
|
|
int nfs_lookup_verify_inode(struct inode *inode, int flags)
|
438 |
|
|
{
|
439 |
|
|
struct nfs_server *server = NFS_SERVER(inode);
|
440 |
|
|
/*
|
441 |
|
|
* If we're interested in close-to-open cache consistency,
|
442 |
|
|
* then we revalidate the inode upon lookup.
|
443 |
|
|
*/
|
444 |
|
|
if (!(server->flags & NFS_MOUNT_NOCTO) && !(flags & LOOKUP_CONTINUE))
|
445 |
|
|
NFS_CACHEINV(inode);
|
446 |
|
|
return nfs_revalidate_inode(server, inode);
|
447 |
|
|
}
|
448 |
|
|
|
449 |
|
|
/*
|
450 |
|
|
* We judge how long we want to trust negative
|
451 |
|
|
* dentries by looking at the parent inode mtime.
|
452 |
|
|
*
|
453 |
|
|
* If parent mtime has changed, we revalidate, else we wait for a
|
454 |
|
|
* period corresponding to the parent's attribute cache timeout value.
|
455 |
|
|
*/
|
456 |
|
|
static inline int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry)
|
457 |
|
|
{
|
458 |
|
|
if (!nfs_check_verifier(dir, dentry))
|
459 |
|
|
return 1;
|
460 |
|
|
return time_after(jiffies, dentry->d_time + NFS_ATTRTIMEO(dir));
|
461 |
|
|
}
|
462 |
|
|
|
463 |
|
|
/*
|
464 |
|
|
* This is called every time the dcache has a lookup hit,
|
465 |
|
|
* and we should check whether we can really trust that
|
466 |
|
|
* lookup.
|
467 |
|
|
*
|
468 |
|
|
* NOTE! The hit can be a negative hit too, don't assume
|
469 |
|
|
* we have an inode!
|
470 |
|
|
*
|
471 |
|
|
* If the parent directory is seen to have changed, we throw out the
|
472 |
|
|
* cached dentry and do a new lookup.
|
473 |
|
|
*/
|
474 |
|
|
static int nfs_lookup_revalidate(struct dentry * dentry, int flags)
|
475 |
|
|
{
|
476 |
|
|
struct inode *dir;
|
477 |
|
|
struct inode *inode;
|
478 |
|
|
int error;
|
479 |
|
|
struct nfs_fh fhandle;
|
480 |
|
|
struct nfs_fattr fattr;
|
481 |
|
|
|
482 |
|
|
lock_kernel();
|
483 |
|
|
dir = dentry->d_parent->d_inode;
|
484 |
|
|
inode = dentry->d_inode;
|
485 |
|
|
|
486 |
|
|
if (!inode) {
|
487 |
|
|
if (nfs_neg_need_reval(dir, dentry))
|
488 |
|
|
goto out_bad;
|
489 |
|
|
goto out_valid;
|
490 |
|
|
}
|
491 |
|
|
|
492 |
|
|
if (is_bad_inode(inode)) {
|
493 |
|
|
dfprintk(VFS, "nfs_lookup_validate: %s/%s has dud inode\n",
|
494 |
|
|
dentry->d_parent->d_name.name, dentry->d_name.name);
|
495 |
|
|
goto out_bad;
|
496 |
|
|
}
|
497 |
|
|
|
498 |
|
|
/* Force a full look up iff the parent directory has changed */
|
499 |
|
|
if (nfs_check_verifier(dir, dentry)) {
|
500 |
|
|
if (nfs_lookup_verify_inode(inode, flags))
|
501 |
|
|
goto out_bad;
|
502 |
|
|
goto out_valid;
|
503 |
|
|
}
|
504 |
|
|
|
505 |
|
|
if (NFS_STALE(inode))
|
506 |
|
|
goto out_bad;
|
507 |
|
|
|
508 |
|
|
error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
|
509 |
|
|
if (error)
|
510 |
|
|
goto out_bad;
|
511 |
|
|
if (memcmp(NFS_FH(inode), &fhandle, sizeof(struct nfs_fh))!= 0)
|
512 |
|
|
goto out_bad;
|
513 |
|
|
if ((error = nfs_refresh_inode(inode, &fattr)) != 0)
|
514 |
|
|
goto out_bad;
|
515 |
|
|
|
516 |
|
|
nfs_renew_times(dentry);
|
517 |
|
|
out_valid:
|
518 |
|
|
unlock_kernel();
|
519 |
|
|
return 1;
|
520 |
|
|
out_bad:
|
521 |
|
|
NFS_CACHEINV(dir);
|
522 |
|
|
if (inode && S_ISDIR(inode->i_mode)) {
|
523 |
|
|
/* Purge readdir caches. */
|
524 |
|
|
nfs_zap_caches(inode);
|
525 |
|
|
/* If we have submounts, don't unhash ! */
|
526 |
|
|
if (have_submounts(dentry))
|
527 |
|
|
goto out_valid;
|
528 |
|
|
shrink_dcache_parent(dentry);
|
529 |
|
|
}
|
530 |
|
|
d_drop(dentry);
|
531 |
|
|
unlock_kernel();
|
532 |
|
|
return 0;
|
533 |
|
|
}
|
534 |
|
|
|
535 |
|
|
/*
|
536 |
|
|
* This is called from dput() when d_count is going to 0.
|
537 |
|
|
*/
|
538 |
|
|
static int nfs_dentry_delete(struct dentry *dentry)
|
539 |
|
|
{
|
540 |
|
|
dfprintk(VFS, "NFS: dentry_delete(%s/%s, %x)\n",
|
541 |
|
|
dentry->d_parent->d_name.name, dentry->d_name.name,
|
542 |
|
|
dentry->d_flags);
|
543 |
|
|
|
544 |
|
|
if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
|
545 |
|
|
/* Unhash it, so that ->d_iput() would be called */
|
546 |
|
|
return 1;
|
547 |
|
|
}
|
548 |
|
|
if (!(dentry->d_sb->s_flags & MS_ACTIVE)) {
|
549 |
|
|
/* Unhash it, so that ancestors of killed async unlink
|
550 |
|
|
* files will be cleaned up during umount */
|
551 |
|
|
return 1;
|
552 |
|
|
}
|
553 |
|
|
return 0;
|
554 |
|
|
|
555 |
|
|
}
|
556 |
|
|
|
557 |
|
|
/*
|
558 |
|
|
* Called when the dentry loses inode.
|
559 |
|
|
* We use it to clean up silly-renamed files.
|
560 |
|
|
*/
|
561 |
|
|
static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode)
|
562 |
|
|
{
|
563 |
|
|
if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
|
564 |
|
|
lock_kernel();
|
565 |
|
|
nfs_complete_unlink(dentry);
|
566 |
|
|
unlock_kernel();
|
567 |
|
|
}
|
568 |
|
|
if (is_bad_inode(inode))
|
569 |
|
|
force_delete(inode);
|
570 |
|
|
iput(inode);
|
571 |
|
|
}
|
572 |
|
|
|
573 |
|
|
struct dentry_operations nfs_dentry_operations = {
|
574 |
|
|
d_revalidate: nfs_lookup_revalidate,
|
575 |
|
|
d_delete: nfs_dentry_delete,
|
576 |
|
|
d_iput: nfs_dentry_iput,
|
577 |
|
|
};
|
578 |
|
|
|
579 |
|
|
static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry)
|
580 |
|
|
{
|
581 |
|
|
struct inode *inode;
|
582 |
|
|
int error;
|
583 |
|
|
struct nfs_fh fhandle;
|
584 |
|
|
struct nfs_fattr fattr;
|
585 |
|
|
|
586 |
|
|
dfprintk(VFS, "NFS: lookup(%s/%s)\n",
|
587 |
|
|
dentry->d_parent->d_name.name, dentry->d_name.name);
|
588 |
|
|
|
589 |
|
|
error = -ENAMETOOLONG;
|
590 |
|
|
if (dentry->d_name.len > NFS_SERVER(dir)->namelen)
|
591 |
|
|
goto out;
|
592 |
|
|
|
593 |
|
|
error = -ENOMEM;
|
594 |
|
|
dentry->d_op = &nfs_dentry_operations;
|
595 |
|
|
|
596 |
|
|
error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
|
597 |
|
|
inode = NULL;
|
598 |
|
|
if (error == -ENOENT)
|
599 |
|
|
goto no_entry;
|
600 |
|
|
if (!error) {
|
601 |
|
|
error = -EACCES;
|
602 |
|
|
inode = nfs_fhget(dentry, &fhandle, &fattr);
|
603 |
|
|
if (inode) {
|
604 |
|
|
no_entry:
|
605 |
|
|
d_add(dentry, inode);
|
606 |
|
|
error = 0;
|
607 |
|
|
}
|
608 |
|
|
nfs_renew_times(dentry);
|
609 |
|
|
}
|
610 |
|
|
out:
|
611 |
|
|
return ERR_PTR(error);
|
612 |
|
|
}
|
613 |
|
|
|
614 |
|
|
/*
|
615 |
|
|
* Code common to create, mkdir, and mknod.
|
616 |
|
|
*/
|
617 |
|
|
static int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
|
618 |
|
|
struct nfs_fattr *fattr)
|
619 |
|
|
{
|
620 |
|
|
struct inode *inode;
|
621 |
|
|
int error = -EACCES;
|
622 |
|
|
|
623 |
|
|
if (fhandle->size == 0 || !(fattr->valid & NFS_ATTR_FATTR)) {
|
624 |
|
|
struct inode *dir = dentry->d_parent->d_inode;
|
625 |
|
|
error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
|
626 |
|
|
if (error)
|
627 |
|
|
goto out_err;
|
628 |
|
|
}
|
629 |
|
|
inode = nfs_fhget(dentry, fhandle, fattr);
|
630 |
|
|
if (inode) {
|
631 |
|
|
d_instantiate(dentry, inode);
|
632 |
|
|
nfs_renew_times(dentry);
|
633 |
|
|
error = 0;
|
634 |
|
|
}
|
635 |
|
|
return error;
|
636 |
|
|
out_err:
|
637 |
|
|
d_drop(dentry);
|
638 |
|
|
return error;
|
639 |
|
|
}
|
640 |
|
|
|
641 |
|
|
/*
|
642 |
|
|
* Following a failed create operation, we drop the dentry rather
|
643 |
|
|
* than retain a negative dentry. This avoids a problem in the event
|
644 |
|
|
* that the operation succeeded on the server, but an error in the
|
645 |
|
|
* reply path made it appear to have failed.
|
646 |
|
|
*/
|
647 |
|
|
static int nfs_create(struct inode *dir, struct dentry *dentry, int mode)
|
648 |
|
|
{
|
649 |
|
|
struct iattr attr;
|
650 |
|
|
struct nfs_fattr fattr;
|
651 |
|
|
struct nfs_fh fhandle;
|
652 |
|
|
int error;
|
653 |
|
|
|
654 |
|
|
dfprintk(VFS, "NFS: create(%x/%ld, %s\n",
|
655 |
|
|
dir->i_dev, dir->i_ino, dentry->d_name.name);
|
656 |
|
|
|
657 |
|
|
attr.ia_mode = mode;
|
658 |
|
|
attr.ia_valid = ATTR_MODE;
|
659 |
|
|
|
660 |
|
|
/*
|
661 |
|
|
* The 0 argument passed into the create function should one day
|
662 |
|
|
* contain the O_EXCL flag if requested. This allows NFSv3 to
|
663 |
|
|
* select the appropriate create strategy. Currently open_namei
|
664 |
|
|
* does not pass the create flags.
|
665 |
|
|
*/
|
666 |
|
|
nfs_zap_caches(dir);
|
667 |
|
|
error = NFS_PROTO(dir)->create(dir, &dentry->d_name,
|
668 |
|
|
&attr, 0, &fhandle, &fattr);
|
669 |
|
|
if (!error)
|
670 |
|
|
error = nfs_instantiate(dentry, &fhandle, &fattr);
|
671 |
|
|
else
|
672 |
|
|
d_drop(dentry);
|
673 |
|
|
return error;
|
674 |
|
|
}
|
675 |
|
|
|
676 |
|
|
/*
|
677 |
|
|
* See comments for nfs_proc_create regarding failed operations.
|
678 |
|
|
*/
|
679 |
|
|
static int nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev)
|
680 |
|
|
{
|
681 |
|
|
struct iattr attr;
|
682 |
|
|
struct nfs_fattr fattr;
|
683 |
|
|
struct nfs_fh fhandle;
|
684 |
|
|
int error;
|
685 |
|
|
|
686 |
|
|
dfprintk(VFS, "NFS: mknod(%x/%ld, %s\n",
|
687 |
|
|
dir->i_dev, dir->i_ino, dentry->d_name.name);
|
688 |
|
|
|
689 |
|
|
attr.ia_mode = mode;
|
690 |
|
|
attr.ia_valid = ATTR_MODE;
|
691 |
|
|
|
692 |
|
|
nfs_zap_caches(dir);
|
693 |
|
|
error = NFS_PROTO(dir)->mknod(dir, &dentry->d_name, &attr, rdev,
|
694 |
|
|
&fhandle, &fattr);
|
695 |
|
|
if (!error)
|
696 |
|
|
error = nfs_instantiate(dentry, &fhandle, &fattr);
|
697 |
|
|
else
|
698 |
|
|
d_drop(dentry);
|
699 |
|
|
return error;
|
700 |
|
|
}
|
701 |
|
|
|
702 |
|
|
/*
|
703 |
|
|
* See comments for nfs_proc_create regarding failed operations.
|
704 |
|
|
*/
|
705 |
|
|
static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
|
706 |
|
|
{
|
707 |
|
|
struct iattr attr;
|
708 |
|
|
struct nfs_fattr fattr;
|
709 |
|
|
struct nfs_fh fhandle;
|
710 |
|
|
int error;
|
711 |
|
|
|
712 |
|
|
dfprintk(VFS, "NFS: mkdir(%x/%ld, %s\n",
|
713 |
|
|
dir->i_dev, dir->i_ino, dentry->d_name.name);
|
714 |
|
|
|
715 |
|
|
attr.ia_valid = ATTR_MODE;
|
716 |
|
|
attr.ia_mode = mode | S_IFDIR;
|
717 |
|
|
|
718 |
|
|
#if 0
|
719 |
|
|
/*
|
720 |
|
|
* Always drop the dentry, we can't always depend on
|
721 |
|
|
* the fattr returned by the server (AIX seems to be
|
722 |
|
|
* broken). We're better off doing another lookup than
|
723 |
|
|
* depending on potentially bogus information.
|
724 |
|
|
*/
|
725 |
|
|
d_drop(dentry);
|
726 |
|
|
#endif
|
727 |
|
|
nfs_zap_caches(dir);
|
728 |
|
|
error = NFS_PROTO(dir)->mkdir(dir, &dentry->d_name, &attr, &fhandle,
|
729 |
|
|
&fattr);
|
730 |
|
|
if (!error)
|
731 |
|
|
error = nfs_instantiate(dentry, &fhandle, &fattr);
|
732 |
|
|
else
|
733 |
|
|
d_drop(dentry);
|
734 |
|
|
return error;
|
735 |
|
|
}
|
736 |
|
|
|
737 |
|
|
static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
|
738 |
|
|
{
|
739 |
|
|
int error;
|
740 |
|
|
|
741 |
|
|
dfprintk(VFS, "NFS: rmdir(%x/%ld, %s\n",
|
742 |
|
|
dir->i_dev, dir->i_ino, dentry->d_name.name);
|
743 |
|
|
|
744 |
|
|
nfs_zap_caches(dir);
|
745 |
|
|
error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
|
746 |
|
|
if (!error)
|
747 |
|
|
dentry->d_inode->i_nlink = 0;
|
748 |
|
|
|
749 |
|
|
return error;
|
750 |
|
|
}
|
751 |
|
|
|
752 |
|
|
static int nfs_sillyrename(struct inode *dir, struct dentry *dentry)
|
753 |
|
|
{
|
754 |
|
|
static unsigned int sillycounter;
|
755 |
|
|
const int i_inosize = sizeof(dir->i_ino)*2;
|
756 |
|
|
const int countersize = sizeof(sillycounter)*2;
|
757 |
|
|
const int slen = strlen(".nfs") + i_inosize + countersize;
|
758 |
|
|
char silly[slen+1];
|
759 |
|
|
struct qstr qsilly;
|
760 |
|
|
struct dentry *sdentry;
|
761 |
|
|
int error = -EIO;
|
762 |
|
|
|
763 |
|
|
dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n",
|
764 |
|
|
dentry->d_parent->d_name.name, dentry->d_name.name,
|
765 |
|
|
atomic_read(&dentry->d_count));
|
766 |
|
|
|
767 |
|
|
if (atomic_read(&dentry->d_count) == 1)
|
768 |
|
|
goto out; /* No need to silly rename. */
|
769 |
|
|
|
770 |
|
|
|
771 |
|
|
#ifdef NFS_PARANOIA
|
772 |
|
|
if (!dentry->d_inode)
|
773 |
|
|
printk("NFS: silly-renaming %s/%s, negative dentry??\n",
|
774 |
|
|
dentry->d_parent->d_name.name, dentry->d_name.name);
|
775 |
|
|
#endif
|
776 |
|
|
/*
|
777 |
|
|
* We don't allow a dentry to be silly-renamed twice.
|
778 |
|
|
*/
|
779 |
|
|
error = -EBUSY;
|
780 |
|
|
if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
|
781 |
|
|
goto out;
|
782 |
|
|
|
783 |
|
|
sprintf(silly, ".nfs%*.*lx",
|
784 |
|
|
i_inosize, i_inosize, dentry->d_inode->i_ino);
|
785 |
|
|
|
786 |
|
|
sdentry = NULL;
|
787 |
|
|
do {
|
788 |
|
|
char *suffix = silly + slen - countersize;
|
789 |
|
|
|
790 |
|
|
dput(sdentry);
|
791 |
|
|
sillycounter++;
|
792 |
|
|
sprintf(suffix, "%*.*x", countersize, countersize, sillycounter);
|
793 |
|
|
|
794 |
|
|
dfprintk(VFS, "trying to rename %s to %s\n",
|
795 |
|
|
dentry->d_name.name, silly);
|
796 |
|
|
|
797 |
|
|
sdentry = lookup_one_len(silly, dentry->d_parent, slen);
|
798 |
|
|
/*
|
799 |
|
|
* N.B. Better to return EBUSY here ... it could be
|
800 |
|
|
* dangerous to delete the file while it's in use.
|
801 |
|
|
*/
|
802 |
|
|
if (IS_ERR(sdentry))
|
803 |
|
|
goto out;
|
804 |
|
|
} while(sdentry->d_inode != NULL); /* need negative lookup */
|
805 |
|
|
|
806 |
|
|
nfs_zap_caches(dir);
|
807 |
|
|
qsilly.name = silly;
|
808 |
|
|
qsilly.len = strlen(silly);
|
809 |
|
|
error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, dir, &qsilly);
|
810 |
|
|
if (!error) {
|
811 |
|
|
nfs_renew_times(dentry);
|
812 |
|
|
d_move(dentry, sdentry);
|
813 |
|
|
error = nfs_async_unlink(dentry);
|
814 |
|
|
/* If we return 0 we don't unlink */
|
815 |
|
|
}
|
816 |
|
|
dput(sdentry);
|
817 |
|
|
out:
|
818 |
|
|
return error;
|
819 |
|
|
}
|
820 |
|
|
|
821 |
|
|
/*
|
822 |
|
|
* Remove a file after making sure there are no pending writes,
|
823 |
|
|
* and after checking that the file has only one user.
|
824 |
|
|
*
|
825 |
|
|
* We invalidate the attribute cache and free the inode prior to the operation
|
826 |
|
|
* to avoid possible races if the server reuses the inode.
|
827 |
|
|
*/
|
828 |
|
|
static int nfs_safe_remove(struct dentry *dentry)
|
829 |
|
|
{
|
830 |
|
|
struct inode *dir = dentry->d_parent->d_inode;
|
831 |
|
|
struct inode *inode = dentry->d_inode;
|
832 |
|
|
int error = -EBUSY, rehash = 0;
|
833 |
|
|
|
834 |
|
|
dfprintk(VFS, "NFS: safe_remove(%s/%s)\n",
|
835 |
|
|
dentry->d_parent->d_name.name, dentry->d_name.name);
|
836 |
|
|
|
837 |
|
|
/*
|
838 |
|
|
* Unhash the dentry while we remove the file ...
|
839 |
|
|
*/
|
840 |
|
|
if (!d_unhashed(dentry)) {
|
841 |
|
|
d_drop(dentry);
|
842 |
|
|
rehash = 1;
|
843 |
|
|
}
|
844 |
|
|
if (atomic_read(&dentry->d_count) > 1) {
|
845 |
|
|
#ifdef NFS_PARANOIA
|
846 |
|
|
printk("nfs_safe_remove: %s/%s busy, d_count=%d\n",
|
847 |
|
|
dentry->d_parent->d_name.name, dentry->d_name.name,
|
848 |
|
|
atomic_read(&dentry->d_count));
|
849 |
|
|
#endif
|
850 |
|
|
goto out;
|
851 |
|
|
}
|
852 |
|
|
|
853 |
|
|
/* If the dentry was sillyrenamed, we simply call d_delete() */
|
854 |
|
|
if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
|
855 |
|
|
error = 0;
|
856 |
|
|
goto out_delete;
|
857 |
|
|
}
|
858 |
|
|
|
859 |
|
|
nfs_zap_caches(dir);
|
860 |
|
|
if (inode)
|
861 |
|
|
NFS_CACHEINV(inode);
|
862 |
|
|
error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
|
863 |
|
|
if (error < 0)
|
864 |
|
|
goto out;
|
865 |
|
|
if (inode)
|
866 |
|
|
inode->i_nlink--;
|
867 |
|
|
|
868 |
|
|
out_delete:
|
869 |
|
|
/*
|
870 |
|
|
* Free the inode
|
871 |
|
|
*/
|
872 |
|
|
d_delete(dentry);
|
873 |
|
|
out:
|
874 |
|
|
if (rehash)
|
875 |
|
|
d_rehash(dentry);
|
876 |
|
|
return error;
|
877 |
|
|
}
|
878 |
|
|
|
879 |
|
|
/* We do silly rename. In case sillyrename() returns -EBUSY, the inode
|
880 |
|
|
* belongs to an active ".nfs..." file and we return -EBUSY.
|
881 |
|
|
*
|
882 |
|
|
* If sillyrename() returns 0, we do nothing, otherwise we unlink.
|
883 |
|
|
*/
|
884 |
|
|
static int nfs_unlink(struct inode *dir, struct dentry *dentry)
|
885 |
|
|
{
|
886 |
|
|
int error;
|
887 |
|
|
|
888 |
|
|
dfprintk(VFS, "NFS: unlink(%x/%ld, %s)\n",
|
889 |
|
|
dir->i_dev, dir->i_ino, dentry->d_name.name);
|
890 |
|
|
|
891 |
|
|
error = nfs_sillyrename(dir, dentry);
|
892 |
|
|
if (error && error != -EBUSY) {
|
893 |
|
|
error = nfs_safe_remove(dentry);
|
894 |
|
|
if (!error) {
|
895 |
|
|
nfs_renew_times(dentry);
|
896 |
|
|
}
|
897 |
|
|
}
|
898 |
|
|
return error;
|
899 |
|
|
}
|
900 |
|
|
|
901 |
|
|
static int
|
902 |
|
|
nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
|
903 |
|
|
{
|
904 |
|
|
struct iattr attr;
|
905 |
|
|
struct nfs_fattr sym_attr;
|
906 |
|
|
struct nfs_fh sym_fh;
|
907 |
|
|
struct qstr qsymname;
|
908 |
|
|
unsigned int maxlen;
|
909 |
|
|
int error;
|
910 |
|
|
|
911 |
|
|
dfprintk(VFS, "NFS: symlink(%x/%ld, %s, %s)\n",
|
912 |
|
|
dir->i_dev, dir->i_ino, dentry->d_name.name, symname);
|
913 |
|
|
|
914 |
|
|
error = -ENAMETOOLONG;
|
915 |
|
|
maxlen = (NFS_PROTO(dir)->version==2) ? NFS2_MAXPATHLEN : NFS3_MAXPATHLEN;
|
916 |
|
|
if (strlen(symname) > maxlen)
|
917 |
|
|
goto out;
|
918 |
|
|
|
919 |
|
|
#ifdef NFS_PARANOIA
|
920 |
|
|
if (dentry->d_inode)
|
921 |
|
|
printk("nfs_proc_symlink: %s/%s not negative!\n",
|
922 |
|
|
dentry->d_parent->d_name.name, dentry->d_name.name);
|
923 |
|
|
#endif
|
924 |
|
|
/*
|
925 |
|
|
* Fill in the sattr for the call.
|
926 |
|
|
* Note: SunOS 4.1.2 crashes if the mode isn't initialized!
|
927 |
|
|
*/
|
928 |
|
|
attr.ia_valid = ATTR_MODE;
|
929 |
|
|
attr.ia_mode = S_IFLNK | S_IRWXUGO;
|
930 |
|
|
|
931 |
|
|
qsymname.name = symname;
|
932 |
|
|
qsymname.len = strlen(symname);
|
933 |
|
|
|
934 |
|
|
nfs_zap_caches(dir);
|
935 |
|
|
error = NFS_PROTO(dir)->symlink(dir, &dentry->d_name, &qsymname,
|
936 |
|
|
&attr, &sym_fh, &sym_attr);
|
937 |
|
|
if (!error) {
|
938 |
|
|
error = nfs_instantiate(dentry, &sym_fh, &sym_attr);
|
939 |
|
|
} else {
|
940 |
|
|
if (error == -EEXIST)
|
941 |
|
|
printk("nfs_proc_symlink: %s/%s already exists??\n",
|
942 |
|
|
dentry->d_parent->d_name.name, dentry->d_name.name);
|
943 |
|
|
d_drop(dentry);
|
944 |
|
|
}
|
945 |
|
|
|
946 |
|
|
out:
|
947 |
|
|
return error;
|
948 |
|
|
}
|
949 |
|
|
|
950 |
|
|
static int
|
951 |
|
|
nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
|
952 |
|
|
{
|
953 |
|
|
struct inode *inode = old_dentry->d_inode;
|
954 |
|
|
int error;
|
955 |
|
|
|
956 |
|
|
dfprintk(VFS, "NFS: link(%s/%s -> %s/%s)\n",
|
957 |
|
|
old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
|
958 |
|
|
dentry->d_parent->d_name.name, dentry->d_name.name);
|
959 |
|
|
|
960 |
|
|
/*
|
961 |
|
|
* Drop the dentry in advance to force a new lookup.
|
962 |
|
|
* Since nfs_proc_link doesn't return a file handle,
|
963 |
|
|
* we can't use the existing dentry.
|
964 |
|
|
*/
|
965 |
|
|
d_drop(dentry);
|
966 |
|
|
nfs_zap_caches(dir);
|
967 |
|
|
NFS_CACHEINV(inode);
|
968 |
|
|
error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name);
|
969 |
|
|
return error;
|
970 |
|
|
}
|
971 |
|
|
|
972 |
|
|
/*
|
973 |
|
|
* RENAME
|
974 |
|
|
* FIXME: Some nfsds, like the Linux user space nfsd, may generate a
|
975 |
|
|
* different file handle for the same inode after a rename (e.g. when
|
976 |
|
|
* moving to a different directory). A fail-safe method to do so would
|
977 |
|
|
* be to look up old_dir/old_name, create a link to new_dir/new_name and
|
978 |
|
|
* rename the old file using the sillyrename stuff. This way, the original
|
979 |
|
|
* file in old_dir will go away when the last process iput()s the inode.
|
980 |
|
|
*
|
981 |
|
|
* FIXED.
|
982 |
|
|
*
|
983 |
|
|
* It actually works quite well. One needs to have the possibility for
|
984 |
|
|
* at least one ".nfs..." file in each directory the file ever gets
|
985 |
|
|
* moved or linked to which happens automagically with the new
|
986 |
|
|
* implementation that only depends on the dcache stuff instead of
|
987 |
|
|
* using the inode layer
|
988 |
|
|
*
|
989 |
|
|
* Unfortunately, things are a little more complicated than indicated
|
990 |
|
|
* above. For a cross-directory move, we want to make sure we can get
|
991 |
|
|
* rid of the old inode after the operation. This means there must be
|
992 |
|
|
* no pending writes (if it's a file), and the use count must be 1.
|
993 |
|
|
* If these conditions are met, we can drop the dentries before doing
|
994 |
|
|
* the rename.
|
995 |
|
|
*/
|
996 |
|
|
static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
997 |
|
|
struct inode *new_dir, struct dentry *new_dentry)
|
998 |
|
|
{
|
999 |
|
|
struct inode *old_inode = old_dentry->d_inode;
|
1000 |
|
|
struct inode *new_inode = new_dentry->d_inode;
|
1001 |
|
|
struct dentry *dentry = NULL, *rehash = NULL;
|
1002 |
|
|
int error = -EBUSY;
|
1003 |
|
|
|
1004 |
|
|
/*
|
1005 |
|
|
* To prevent any new references to the target during the rename,
|
1006 |
|
|
* we unhash the dentry and free the inode in advance.
|
1007 |
|
|
*/
|
1008 |
|
|
if (!d_unhashed(new_dentry)) {
|
1009 |
|
|
d_drop(new_dentry);
|
1010 |
|
|
rehash = new_dentry;
|
1011 |
|
|
}
|
1012 |
|
|
|
1013 |
|
|
dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n",
|
1014 |
|
|
old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
|
1015 |
|
|
new_dentry->d_parent->d_name.name, new_dentry->d_name.name,
|
1016 |
|
|
atomic_read(&new_dentry->d_count));
|
1017 |
|
|
|
1018 |
|
|
/*
|
1019 |
|
|
* First check whether the target is busy ... we can't
|
1020 |
|
|
* safely do _any_ rename if the target is in use.
|
1021 |
|
|
*
|
1022 |
|
|
* For files, make a copy of the dentry and then do a
|
1023 |
|
|
* silly-rename. If the silly-rename succeeds, the
|
1024 |
|
|
* copied dentry is hashed and becomes the new target.
|
1025 |
|
|
*/
|
1026 |
|
|
if (!new_inode)
|
1027 |
|
|
goto go_ahead;
|
1028 |
|
|
if (S_ISDIR(new_inode->i_mode))
|
1029 |
|
|
goto out;
|
1030 |
|
|
else if (atomic_read(&new_dentry->d_count) > 1) {
|
1031 |
|
|
int err;
|
1032 |
|
|
/* copy the target dentry's name */
|
1033 |
|
|
dentry = d_alloc(new_dentry->d_parent,
|
1034 |
|
|
&new_dentry->d_name);
|
1035 |
|
|
if (!dentry)
|
1036 |
|
|
goto out;
|
1037 |
|
|
|
1038 |
|
|
/* silly-rename the existing target ... */
|
1039 |
|
|
err = nfs_sillyrename(new_dir, new_dentry);
|
1040 |
|
|
if (!err) {
|
1041 |
|
|
new_dentry = rehash = dentry;
|
1042 |
|
|
new_inode = NULL;
|
1043 |
|
|
/* instantiate the replacement target */
|
1044 |
|
|
d_instantiate(new_dentry, NULL);
|
1045 |
|
|
}
|
1046 |
|
|
|
1047 |
|
|
/* dentry still busy? */
|
1048 |
|
|
if (atomic_read(&new_dentry->d_count) > 1) {
|
1049 |
|
|
#ifdef NFS_PARANOIA
|
1050 |
|
|
printk("nfs_rename: target %s/%s busy, d_count=%d\n",
|
1051 |
|
|
new_dentry->d_parent->d_name.name,
|
1052 |
|
|
new_dentry->d_name.name,
|
1053 |
|
|
atomic_read(&new_dentry->d_count));
|
1054 |
|
|
#endif
|
1055 |
|
|
goto out;
|
1056 |
|
|
}
|
1057 |
|
|
}
|
1058 |
|
|
|
1059 |
|
|
go_ahead:
|
1060 |
|
|
/*
|
1061 |
|
|
* ... prune child dentries and writebacks if needed.
|
1062 |
|
|
*/
|
1063 |
|
|
if (atomic_read(&old_dentry->d_count) > 1) {
|
1064 |
|
|
nfs_wb_all(old_inode);
|
1065 |
|
|
shrink_dcache_parent(old_dentry);
|
1066 |
|
|
}
|
1067 |
|
|
|
1068 |
|
|
if (new_inode)
|
1069 |
|
|
d_delete(new_dentry);
|
1070 |
|
|
|
1071 |
|
|
nfs_zap_caches(new_dir);
|
1072 |
|
|
nfs_zap_caches(old_dir);
|
1073 |
|
|
NFS_CACHEINV(old_inode);
|
1074 |
|
|
error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name,
|
1075 |
|
|
new_dir, &new_dentry->d_name);
|
1076 |
|
|
out:
|
1077 |
|
|
if (rehash)
|
1078 |
|
|
d_rehash(rehash);
|
1079 |
|
|
if (!error && !S_ISDIR(old_inode->i_mode))
|
1080 |
|
|
d_move(old_dentry, new_dentry);
|
1081 |
|
|
|
1082 |
|
|
/* new dentry created? */
|
1083 |
|
|
if (dentry)
|
1084 |
|
|
dput(dentry);
|
1085 |
|
|
return error;
|
1086 |
|
|
}
|
1087 |
|
|
|
1088 |
|
|
int
|
1089 |
|
|
nfs_permission(struct inode *inode, int mask)
|
1090 |
|
|
{
|
1091 |
|
|
int error = vfs_permission(inode, mask);
|
1092 |
|
|
|
1093 |
|
|
if (!NFS_PROTO(inode)->access)
|
1094 |
|
|
goto out;
|
1095 |
|
|
|
1096 |
|
|
if (error == -EROFS)
|
1097 |
|
|
goto out;
|
1098 |
|
|
|
1099 |
|
|
/*
|
1100 |
|
|
* Trust UNIX mode bits except:
|
1101 |
|
|
*
|
1102 |
|
|
* 1) When override capabilities may have been invoked
|
1103 |
|
|
* 2) When root squashing may be involved
|
1104 |
|
|
* 3) When ACLs may overturn a negative answer */
|
1105 |
|
|
if (!capable(CAP_DAC_OVERRIDE) && !capable(CAP_DAC_READ_SEARCH)
|
1106 |
|
|
&& (current->fsuid != 0) && (current->fsgid != 0)
|
1107 |
|
|
&& error != -EACCES)
|
1108 |
|
|
goto out;
|
1109 |
|
|
|
1110 |
|
|
error = NFS_PROTO(inode)->access(inode, mask, 0);
|
1111 |
|
|
|
1112 |
|
|
if (error == -EACCES && NFS_CLIENT(inode)->cl_droppriv &&
|
1113 |
|
|
current->uid != 0 && current->gid != 0 &&
|
1114 |
|
|
(current->fsuid != current->uid || current->fsgid != current->gid))
|
1115 |
|
|
error = NFS_PROTO(inode)->access(inode, mask, 1);
|
1116 |
|
|
|
1117 |
|
|
out:
|
1118 |
|
|
return error;
|
1119 |
|
|
}
|
1120 |
|
|
|
1121 |
|
|
/*
|
1122 |
|
|
* Local variables:
|
1123 |
|
|
* version-control: t
|
1124 |
|
|
* kept-new-versions: 5
|
1125 |
|
|
* End:
|
1126 |
|
|
*/
|