1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * linux/fs/nfs/dir.c 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * Copyright (C) 1992 Rick Sladkey 5*1da177e4SLinus Torvalds * 6*1da177e4SLinus Torvalds * nfs directory handling functions 7*1da177e4SLinus Torvalds * 8*1da177e4SLinus Torvalds * 10 Apr 1996 Added silly rename for unlink --okir 9*1da177e4SLinus Torvalds * 28 Sep 1996 Improved directory cache --okir 10*1da177e4SLinus Torvalds * 23 Aug 1997 Claus Heine claus@momo.math.rwth-aachen.de 11*1da177e4SLinus Torvalds * Re-implemented silly rename for unlink, newly implemented 12*1da177e4SLinus Torvalds * silly rename for nfs_rename() following the suggestions 13*1da177e4SLinus Torvalds * of Olaf Kirch (okir) found in this file. 14*1da177e4SLinus Torvalds * Following Linus comments on my original hack, this version 15*1da177e4SLinus Torvalds * depends only on the dcache stuff and doesn't touch the inode 16*1da177e4SLinus Torvalds * layer (iput() and friends). 17*1da177e4SLinus Torvalds * 6 Jun 1999 Cache readdir lookups in the page cache. -DaveM 18*1da177e4SLinus Torvalds */ 19*1da177e4SLinus Torvalds 20*1da177e4SLinus Torvalds #include <linux/time.h> 21*1da177e4SLinus Torvalds #include <linux/errno.h> 22*1da177e4SLinus Torvalds #include <linux/stat.h> 23*1da177e4SLinus Torvalds #include <linux/fcntl.h> 24*1da177e4SLinus Torvalds #include <linux/string.h> 25*1da177e4SLinus Torvalds #include <linux/kernel.h> 26*1da177e4SLinus Torvalds #include <linux/slab.h> 27*1da177e4SLinus Torvalds #include <linux/mm.h> 28*1da177e4SLinus Torvalds #include <linux/sunrpc/clnt.h> 29*1da177e4SLinus Torvalds #include <linux/nfs_fs.h> 30*1da177e4SLinus Torvalds #include <linux/nfs_mount.h> 31*1da177e4SLinus Torvalds #include <linux/pagemap.h> 32*1da177e4SLinus Torvalds #include <linux/smp_lock.h> 33*1da177e4SLinus Torvalds #include <linux/namei.h> 34*1da177e4SLinus Torvalds 35*1da177e4SLinus Torvalds #include "delegation.h" 36*1da177e4SLinus Torvalds 37*1da177e4SLinus Torvalds #define NFS_PARANOIA 1 38*1da177e4SLinus Torvalds /* #define NFS_DEBUG_VERBOSE 1 */ 39*1da177e4SLinus Torvalds 40*1da177e4SLinus Torvalds static int nfs_opendir(struct inode *, struct file *); 41*1da177e4SLinus Torvalds static int nfs_readdir(struct file *, void *, filldir_t); 42*1da177e4SLinus Torvalds static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *); 43*1da177e4SLinus Torvalds static int nfs_create(struct inode *, struct dentry *, int, struct nameidata *); 44*1da177e4SLinus Torvalds static int nfs_mkdir(struct inode *, struct dentry *, int); 45*1da177e4SLinus Torvalds static int nfs_rmdir(struct inode *, struct dentry *); 46*1da177e4SLinus Torvalds static int nfs_unlink(struct inode *, struct dentry *); 47*1da177e4SLinus Torvalds static int nfs_symlink(struct inode *, struct dentry *, const char *); 48*1da177e4SLinus Torvalds static int nfs_link(struct dentry *, struct inode *, struct dentry *); 49*1da177e4SLinus Torvalds static int nfs_mknod(struct inode *, struct dentry *, int, dev_t); 50*1da177e4SLinus Torvalds static int nfs_rename(struct inode *, struct dentry *, 51*1da177e4SLinus Torvalds struct inode *, struct dentry *); 52*1da177e4SLinus Torvalds static int nfs_fsync_dir(struct file *, struct dentry *, int); 53*1da177e4SLinus Torvalds 54*1da177e4SLinus Torvalds struct file_operations nfs_dir_operations = { 55*1da177e4SLinus Torvalds .read = generic_read_dir, 56*1da177e4SLinus Torvalds .readdir = nfs_readdir, 57*1da177e4SLinus Torvalds .open = nfs_opendir, 58*1da177e4SLinus Torvalds .release = nfs_release, 59*1da177e4SLinus Torvalds .fsync = nfs_fsync_dir, 60*1da177e4SLinus Torvalds }; 61*1da177e4SLinus Torvalds 62*1da177e4SLinus Torvalds struct inode_operations nfs_dir_inode_operations = { 63*1da177e4SLinus Torvalds .create = nfs_create, 64*1da177e4SLinus Torvalds .lookup = nfs_lookup, 65*1da177e4SLinus Torvalds .link = nfs_link, 66*1da177e4SLinus Torvalds .unlink = nfs_unlink, 67*1da177e4SLinus Torvalds .symlink = nfs_symlink, 68*1da177e4SLinus Torvalds .mkdir = nfs_mkdir, 69*1da177e4SLinus Torvalds .rmdir = nfs_rmdir, 70*1da177e4SLinus Torvalds .mknod = nfs_mknod, 71*1da177e4SLinus Torvalds .rename = nfs_rename, 72*1da177e4SLinus Torvalds .permission = nfs_permission, 73*1da177e4SLinus Torvalds .getattr = nfs_getattr, 74*1da177e4SLinus Torvalds .setattr = nfs_setattr, 75*1da177e4SLinus Torvalds }; 76*1da177e4SLinus Torvalds 77*1da177e4SLinus Torvalds #ifdef CONFIG_NFS_V4 78*1da177e4SLinus Torvalds 79*1da177e4SLinus Torvalds static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *); 80*1da177e4SLinus Torvalds struct inode_operations nfs4_dir_inode_operations = { 81*1da177e4SLinus Torvalds .create = nfs_create, 82*1da177e4SLinus Torvalds .lookup = nfs_atomic_lookup, 83*1da177e4SLinus Torvalds .link = nfs_link, 84*1da177e4SLinus Torvalds .unlink = nfs_unlink, 85*1da177e4SLinus Torvalds .symlink = nfs_symlink, 86*1da177e4SLinus Torvalds .mkdir = nfs_mkdir, 87*1da177e4SLinus Torvalds .rmdir = nfs_rmdir, 88*1da177e4SLinus Torvalds .mknod = nfs_mknod, 89*1da177e4SLinus Torvalds .rename = nfs_rename, 90*1da177e4SLinus Torvalds .permission = nfs_permission, 91*1da177e4SLinus Torvalds .getattr = nfs_getattr, 92*1da177e4SLinus Torvalds .setattr = nfs_setattr, 93*1da177e4SLinus Torvalds }; 94*1da177e4SLinus Torvalds 95*1da177e4SLinus Torvalds #endif /* CONFIG_NFS_V4 */ 96*1da177e4SLinus Torvalds 97*1da177e4SLinus Torvalds /* 98*1da177e4SLinus Torvalds * Open file 99*1da177e4SLinus Torvalds */ 100*1da177e4SLinus Torvalds static int 101*1da177e4SLinus Torvalds nfs_opendir(struct inode *inode, struct file *filp) 102*1da177e4SLinus Torvalds { 103*1da177e4SLinus Torvalds int res = 0; 104*1da177e4SLinus Torvalds 105*1da177e4SLinus Torvalds lock_kernel(); 106*1da177e4SLinus Torvalds /* Call generic open code in order to cache credentials */ 107*1da177e4SLinus Torvalds if (!res) 108*1da177e4SLinus Torvalds res = nfs_open(inode, filp); 109*1da177e4SLinus Torvalds unlock_kernel(); 110*1da177e4SLinus Torvalds return res; 111*1da177e4SLinus Torvalds } 112*1da177e4SLinus Torvalds 113*1da177e4SLinus Torvalds typedef u32 * (*decode_dirent_t)(u32 *, struct nfs_entry *, int); 114*1da177e4SLinus Torvalds typedef struct { 115*1da177e4SLinus Torvalds struct file *file; 116*1da177e4SLinus Torvalds struct page *page; 117*1da177e4SLinus Torvalds unsigned long page_index; 118*1da177e4SLinus Torvalds u32 *ptr; 119*1da177e4SLinus Torvalds u64 target; 120*1da177e4SLinus Torvalds struct nfs_entry *entry; 121*1da177e4SLinus Torvalds decode_dirent_t decode; 122*1da177e4SLinus Torvalds int plus; 123*1da177e4SLinus Torvalds int error; 124*1da177e4SLinus Torvalds } nfs_readdir_descriptor_t; 125*1da177e4SLinus Torvalds 126*1da177e4SLinus Torvalds /* Now we cache directories properly, by stuffing the dirent 127*1da177e4SLinus Torvalds * data directly in the page cache. 128*1da177e4SLinus Torvalds * 129*1da177e4SLinus Torvalds * Inode invalidation due to refresh etc. takes care of 130*1da177e4SLinus Torvalds * _everything_, no sloppy entry flushing logic, no extraneous 131*1da177e4SLinus Torvalds * copying, network direct to page cache, the way it was meant 132*1da177e4SLinus Torvalds * to be. 133*1da177e4SLinus Torvalds * 134*1da177e4SLinus Torvalds * NOTE: Dirent information verification is done always by the 135*1da177e4SLinus Torvalds * page-in of the RPC reply, nowhere else, this simplies 136*1da177e4SLinus Torvalds * things substantially. 137*1da177e4SLinus Torvalds */ 138*1da177e4SLinus Torvalds static 139*1da177e4SLinus Torvalds int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) 140*1da177e4SLinus Torvalds { 141*1da177e4SLinus Torvalds struct file *file = desc->file; 142*1da177e4SLinus Torvalds struct inode *inode = file->f_dentry->d_inode; 143*1da177e4SLinus Torvalds struct rpc_cred *cred = nfs_file_cred(file); 144*1da177e4SLinus Torvalds unsigned long timestamp; 145*1da177e4SLinus Torvalds int error; 146*1da177e4SLinus Torvalds 147*1da177e4SLinus Torvalds dfprintk(VFS, "NFS: nfs_readdir_filler() reading cookie %Lu into page %lu.\n", (long long)desc->entry->cookie, page->index); 148*1da177e4SLinus Torvalds 149*1da177e4SLinus Torvalds again: 150*1da177e4SLinus Torvalds timestamp = jiffies; 151*1da177e4SLinus Torvalds error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, desc->entry->cookie, page, 152*1da177e4SLinus Torvalds NFS_SERVER(inode)->dtsize, desc->plus); 153*1da177e4SLinus Torvalds if (error < 0) { 154*1da177e4SLinus Torvalds /* We requested READDIRPLUS, but the server doesn't grok it */ 155*1da177e4SLinus Torvalds if (error == -ENOTSUPP && desc->plus) { 156*1da177e4SLinus Torvalds NFS_SERVER(inode)->caps &= ~NFS_CAP_READDIRPLUS; 157*1da177e4SLinus Torvalds NFS_FLAGS(inode) &= ~NFS_INO_ADVISE_RDPLUS; 158*1da177e4SLinus Torvalds desc->plus = 0; 159*1da177e4SLinus Torvalds goto again; 160*1da177e4SLinus Torvalds } 161*1da177e4SLinus Torvalds goto error; 162*1da177e4SLinus Torvalds } 163*1da177e4SLinus Torvalds SetPageUptodate(page); 164*1da177e4SLinus Torvalds NFS_FLAGS(inode) |= NFS_INO_INVALID_ATIME; 165*1da177e4SLinus Torvalds /* Ensure consistent page alignment of the data. 166*1da177e4SLinus Torvalds * Note: assumes we have exclusive access to this mapping either 167*1da177e4SLinus Torvalds * throught inode->i_sem or some other mechanism. 168*1da177e4SLinus Torvalds */ 169*1da177e4SLinus Torvalds if (page->index == 0) { 170*1da177e4SLinus Torvalds invalidate_inode_pages(inode->i_mapping); 171*1da177e4SLinus Torvalds NFS_I(inode)->readdir_timestamp = timestamp; 172*1da177e4SLinus Torvalds } 173*1da177e4SLinus Torvalds unlock_page(page); 174*1da177e4SLinus Torvalds return 0; 175*1da177e4SLinus Torvalds error: 176*1da177e4SLinus Torvalds SetPageError(page); 177*1da177e4SLinus Torvalds unlock_page(page); 178*1da177e4SLinus Torvalds nfs_zap_caches(inode); 179*1da177e4SLinus Torvalds desc->error = error; 180*1da177e4SLinus Torvalds return -EIO; 181*1da177e4SLinus Torvalds } 182*1da177e4SLinus Torvalds 183*1da177e4SLinus Torvalds static inline 184*1da177e4SLinus Torvalds int dir_decode(nfs_readdir_descriptor_t *desc) 185*1da177e4SLinus Torvalds { 186*1da177e4SLinus Torvalds u32 *p = desc->ptr; 187*1da177e4SLinus Torvalds p = desc->decode(p, desc->entry, desc->plus); 188*1da177e4SLinus Torvalds if (IS_ERR(p)) 189*1da177e4SLinus Torvalds return PTR_ERR(p); 190*1da177e4SLinus Torvalds desc->ptr = p; 191*1da177e4SLinus Torvalds return 0; 192*1da177e4SLinus Torvalds } 193*1da177e4SLinus Torvalds 194*1da177e4SLinus Torvalds static inline 195*1da177e4SLinus Torvalds void dir_page_release(nfs_readdir_descriptor_t *desc) 196*1da177e4SLinus Torvalds { 197*1da177e4SLinus Torvalds kunmap(desc->page); 198*1da177e4SLinus Torvalds page_cache_release(desc->page); 199*1da177e4SLinus Torvalds desc->page = NULL; 200*1da177e4SLinus Torvalds desc->ptr = NULL; 201*1da177e4SLinus Torvalds } 202*1da177e4SLinus Torvalds 203*1da177e4SLinus Torvalds /* 204*1da177e4SLinus Torvalds * Given a pointer to a buffer that has already been filled by a call 205*1da177e4SLinus Torvalds * to readdir, find the next entry. 206*1da177e4SLinus Torvalds * 207*1da177e4SLinus Torvalds * If the end of the buffer has been reached, return -EAGAIN, if not, 208*1da177e4SLinus Torvalds * return the offset within the buffer of the next entry to be 209*1da177e4SLinus Torvalds * read. 210*1da177e4SLinus Torvalds */ 211*1da177e4SLinus Torvalds static inline 212*1da177e4SLinus Torvalds int find_dirent(nfs_readdir_descriptor_t *desc, struct page *page) 213*1da177e4SLinus Torvalds { 214*1da177e4SLinus Torvalds struct nfs_entry *entry = desc->entry; 215*1da177e4SLinus Torvalds int loop_count = 0, 216*1da177e4SLinus Torvalds status; 217*1da177e4SLinus Torvalds 218*1da177e4SLinus Torvalds while((status = dir_decode(desc)) == 0) { 219*1da177e4SLinus Torvalds dfprintk(VFS, "NFS: found cookie %Lu\n", (long long)entry->cookie); 220*1da177e4SLinus Torvalds if (entry->prev_cookie == desc->target) 221*1da177e4SLinus Torvalds break; 222*1da177e4SLinus Torvalds if (loop_count++ > 200) { 223*1da177e4SLinus Torvalds loop_count = 0; 224*1da177e4SLinus Torvalds schedule(); 225*1da177e4SLinus Torvalds } 226*1da177e4SLinus Torvalds } 227*1da177e4SLinus Torvalds dfprintk(VFS, "NFS: find_dirent() returns %d\n", status); 228*1da177e4SLinus Torvalds return status; 229*1da177e4SLinus Torvalds } 230*1da177e4SLinus Torvalds 231*1da177e4SLinus Torvalds /* 232*1da177e4SLinus Torvalds * Find the given page, and call find_dirent() in order to try to 233*1da177e4SLinus Torvalds * return the next entry. 234*1da177e4SLinus Torvalds */ 235*1da177e4SLinus Torvalds static inline 236*1da177e4SLinus Torvalds int find_dirent_page(nfs_readdir_descriptor_t *desc) 237*1da177e4SLinus Torvalds { 238*1da177e4SLinus Torvalds struct inode *inode = desc->file->f_dentry->d_inode; 239*1da177e4SLinus Torvalds struct page *page; 240*1da177e4SLinus Torvalds int status; 241*1da177e4SLinus Torvalds 242*1da177e4SLinus Torvalds dfprintk(VFS, "NFS: find_dirent_page() searching directory page %ld\n", desc->page_index); 243*1da177e4SLinus Torvalds 244*1da177e4SLinus Torvalds page = read_cache_page(inode->i_mapping, desc->page_index, 245*1da177e4SLinus Torvalds (filler_t *)nfs_readdir_filler, desc); 246*1da177e4SLinus Torvalds if (IS_ERR(page)) { 247*1da177e4SLinus Torvalds status = PTR_ERR(page); 248*1da177e4SLinus Torvalds goto out; 249*1da177e4SLinus Torvalds } 250*1da177e4SLinus Torvalds if (!PageUptodate(page)) 251*1da177e4SLinus Torvalds goto read_error; 252*1da177e4SLinus Torvalds 253*1da177e4SLinus Torvalds /* NOTE: Someone else may have changed the READDIRPLUS flag */ 254*1da177e4SLinus Torvalds desc->page = page; 255*1da177e4SLinus Torvalds desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */ 256*1da177e4SLinus Torvalds status = find_dirent(desc, page); 257*1da177e4SLinus Torvalds if (status < 0) 258*1da177e4SLinus Torvalds dir_page_release(desc); 259*1da177e4SLinus Torvalds out: 260*1da177e4SLinus Torvalds dfprintk(VFS, "NFS: find_dirent_page() returns %d\n", status); 261*1da177e4SLinus Torvalds return status; 262*1da177e4SLinus Torvalds read_error: 263*1da177e4SLinus Torvalds page_cache_release(page); 264*1da177e4SLinus Torvalds return -EIO; 265*1da177e4SLinus Torvalds } 266*1da177e4SLinus Torvalds 267*1da177e4SLinus Torvalds /* 268*1da177e4SLinus Torvalds * Recurse through the page cache pages, and return a 269*1da177e4SLinus Torvalds * filled nfs_entry structure of the next directory entry if possible. 270*1da177e4SLinus Torvalds * 271*1da177e4SLinus Torvalds * The target for the search is 'desc->target'. 272*1da177e4SLinus Torvalds */ 273*1da177e4SLinus Torvalds static inline 274*1da177e4SLinus Torvalds int readdir_search_pagecache(nfs_readdir_descriptor_t *desc) 275*1da177e4SLinus Torvalds { 276*1da177e4SLinus Torvalds int loop_count = 0; 277*1da177e4SLinus Torvalds int res; 278*1da177e4SLinus Torvalds 279*1da177e4SLinus Torvalds dfprintk(VFS, "NFS: readdir_search_pagecache() searching for cookie %Lu\n", (long long)desc->target); 280*1da177e4SLinus Torvalds for (;;) { 281*1da177e4SLinus Torvalds res = find_dirent_page(desc); 282*1da177e4SLinus Torvalds if (res != -EAGAIN) 283*1da177e4SLinus Torvalds break; 284*1da177e4SLinus Torvalds /* Align to beginning of next page */ 285*1da177e4SLinus Torvalds desc->page_index ++; 286*1da177e4SLinus Torvalds if (loop_count++ > 200) { 287*1da177e4SLinus Torvalds loop_count = 0; 288*1da177e4SLinus Torvalds schedule(); 289*1da177e4SLinus Torvalds } 290*1da177e4SLinus Torvalds } 291*1da177e4SLinus Torvalds dfprintk(VFS, "NFS: readdir_search_pagecache() returned %d\n", res); 292*1da177e4SLinus Torvalds return res; 293*1da177e4SLinus Torvalds } 294*1da177e4SLinus Torvalds 295*1da177e4SLinus Torvalds static inline unsigned int dt_type(struct inode *inode) 296*1da177e4SLinus Torvalds { 297*1da177e4SLinus Torvalds return (inode->i_mode >> 12) & 15; 298*1da177e4SLinus Torvalds } 299*1da177e4SLinus Torvalds 300*1da177e4SLinus Torvalds static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc); 301*1da177e4SLinus Torvalds 302*1da177e4SLinus Torvalds /* 303*1da177e4SLinus Torvalds * Once we've found the start of the dirent within a page: fill 'er up... 304*1da177e4SLinus Torvalds */ 305*1da177e4SLinus Torvalds static 306*1da177e4SLinus Torvalds int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, 307*1da177e4SLinus Torvalds filldir_t filldir) 308*1da177e4SLinus Torvalds { 309*1da177e4SLinus Torvalds struct file *file = desc->file; 310*1da177e4SLinus Torvalds struct nfs_entry *entry = desc->entry; 311*1da177e4SLinus Torvalds struct dentry *dentry = NULL; 312*1da177e4SLinus Torvalds unsigned long fileid; 313*1da177e4SLinus Torvalds int loop_count = 0, 314*1da177e4SLinus Torvalds res; 315*1da177e4SLinus Torvalds 316*1da177e4SLinus Torvalds dfprintk(VFS, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n", (long long)desc->target); 317*1da177e4SLinus Torvalds 318*1da177e4SLinus Torvalds for(;;) { 319*1da177e4SLinus Torvalds unsigned d_type = DT_UNKNOWN; 320*1da177e4SLinus Torvalds /* Note: entry->prev_cookie contains the cookie for 321*1da177e4SLinus Torvalds * retrieving the current dirent on the server */ 322*1da177e4SLinus Torvalds fileid = nfs_fileid_to_ino_t(entry->ino); 323*1da177e4SLinus Torvalds 324*1da177e4SLinus Torvalds /* Get a dentry if we have one */ 325*1da177e4SLinus Torvalds if (dentry != NULL) 326*1da177e4SLinus Torvalds dput(dentry); 327*1da177e4SLinus Torvalds dentry = nfs_readdir_lookup(desc); 328*1da177e4SLinus Torvalds 329*1da177e4SLinus Torvalds /* Use readdirplus info */ 330*1da177e4SLinus Torvalds if (dentry != NULL && dentry->d_inode != NULL) { 331*1da177e4SLinus Torvalds d_type = dt_type(dentry->d_inode); 332*1da177e4SLinus Torvalds fileid = dentry->d_inode->i_ino; 333*1da177e4SLinus Torvalds } 334*1da177e4SLinus Torvalds 335*1da177e4SLinus Torvalds res = filldir(dirent, entry->name, entry->len, 336*1da177e4SLinus Torvalds entry->prev_cookie, fileid, d_type); 337*1da177e4SLinus Torvalds if (res < 0) 338*1da177e4SLinus Torvalds break; 339*1da177e4SLinus Torvalds file->f_pos = desc->target = entry->cookie; 340*1da177e4SLinus Torvalds if (dir_decode(desc) != 0) { 341*1da177e4SLinus Torvalds desc->page_index ++; 342*1da177e4SLinus Torvalds break; 343*1da177e4SLinus Torvalds } 344*1da177e4SLinus Torvalds if (loop_count++ > 200) { 345*1da177e4SLinus Torvalds loop_count = 0; 346*1da177e4SLinus Torvalds schedule(); 347*1da177e4SLinus Torvalds } 348*1da177e4SLinus Torvalds } 349*1da177e4SLinus Torvalds dir_page_release(desc); 350*1da177e4SLinus Torvalds if (dentry != NULL) 351*1da177e4SLinus Torvalds dput(dentry); 352*1da177e4SLinus Torvalds dfprintk(VFS, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", (long long)desc->target, res); 353*1da177e4SLinus Torvalds return res; 354*1da177e4SLinus Torvalds } 355*1da177e4SLinus Torvalds 356*1da177e4SLinus Torvalds /* 357*1da177e4SLinus Torvalds * If we cannot find a cookie in our cache, we suspect that this is 358*1da177e4SLinus Torvalds * because it points to a deleted file, so we ask the server to return 359*1da177e4SLinus Torvalds * whatever it thinks is the next entry. We then feed this to filldir. 360*1da177e4SLinus Torvalds * If all goes well, we should then be able to find our way round the 361*1da177e4SLinus Torvalds * cache on the next call to readdir_search_pagecache(); 362*1da177e4SLinus Torvalds * 363*1da177e4SLinus Torvalds * NOTE: we cannot add the anonymous page to the pagecache because 364*1da177e4SLinus Torvalds * the data it contains might not be page aligned. Besides, 365*1da177e4SLinus Torvalds * we should already have a complete representation of the 366*1da177e4SLinus Torvalds * directory in the page cache by the time we get here. 367*1da177e4SLinus Torvalds */ 368*1da177e4SLinus Torvalds static inline 369*1da177e4SLinus Torvalds int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, 370*1da177e4SLinus Torvalds filldir_t filldir) 371*1da177e4SLinus Torvalds { 372*1da177e4SLinus Torvalds struct file *file = desc->file; 373*1da177e4SLinus Torvalds struct inode *inode = file->f_dentry->d_inode; 374*1da177e4SLinus Torvalds struct rpc_cred *cred = nfs_file_cred(file); 375*1da177e4SLinus Torvalds struct page *page = NULL; 376*1da177e4SLinus Torvalds int status; 377*1da177e4SLinus Torvalds 378*1da177e4SLinus Torvalds dfprintk(VFS, "NFS: uncached_readdir() searching for cookie %Lu\n", (long long)desc->target); 379*1da177e4SLinus Torvalds 380*1da177e4SLinus Torvalds page = alloc_page(GFP_HIGHUSER); 381*1da177e4SLinus Torvalds if (!page) { 382*1da177e4SLinus Torvalds status = -ENOMEM; 383*1da177e4SLinus Torvalds goto out; 384*1da177e4SLinus Torvalds } 385*1da177e4SLinus Torvalds desc->error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, desc->target, 386*1da177e4SLinus Torvalds page, 387*1da177e4SLinus Torvalds NFS_SERVER(inode)->dtsize, 388*1da177e4SLinus Torvalds desc->plus); 389*1da177e4SLinus Torvalds NFS_FLAGS(inode) |= NFS_INO_INVALID_ATIME; 390*1da177e4SLinus Torvalds desc->page = page; 391*1da177e4SLinus Torvalds desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */ 392*1da177e4SLinus Torvalds if (desc->error >= 0) { 393*1da177e4SLinus Torvalds if ((status = dir_decode(desc)) == 0) 394*1da177e4SLinus Torvalds desc->entry->prev_cookie = desc->target; 395*1da177e4SLinus Torvalds } else 396*1da177e4SLinus Torvalds status = -EIO; 397*1da177e4SLinus Torvalds if (status < 0) 398*1da177e4SLinus Torvalds goto out_release; 399*1da177e4SLinus Torvalds 400*1da177e4SLinus Torvalds status = nfs_do_filldir(desc, dirent, filldir); 401*1da177e4SLinus Torvalds 402*1da177e4SLinus Torvalds /* Reset read descriptor so it searches the page cache from 403*1da177e4SLinus Torvalds * the start upon the next call to readdir_search_pagecache() */ 404*1da177e4SLinus Torvalds desc->page_index = 0; 405*1da177e4SLinus Torvalds desc->entry->cookie = desc->entry->prev_cookie = 0; 406*1da177e4SLinus Torvalds desc->entry->eof = 0; 407*1da177e4SLinus Torvalds out: 408*1da177e4SLinus Torvalds dfprintk(VFS, "NFS: uncached_readdir() returns %d\n", status); 409*1da177e4SLinus Torvalds return status; 410*1da177e4SLinus Torvalds out_release: 411*1da177e4SLinus Torvalds dir_page_release(desc); 412*1da177e4SLinus Torvalds goto out; 413*1da177e4SLinus Torvalds } 414*1da177e4SLinus Torvalds 415*1da177e4SLinus Torvalds /* The file offset position is now represented as a true offset into the 416*1da177e4SLinus Torvalds * page cache as is the case in most of the other filesystems. 417*1da177e4SLinus Torvalds */ 418*1da177e4SLinus Torvalds static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) 419*1da177e4SLinus Torvalds { 420*1da177e4SLinus Torvalds struct dentry *dentry = filp->f_dentry; 421*1da177e4SLinus Torvalds struct inode *inode = dentry->d_inode; 422*1da177e4SLinus Torvalds nfs_readdir_descriptor_t my_desc, 423*1da177e4SLinus Torvalds *desc = &my_desc; 424*1da177e4SLinus Torvalds struct nfs_entry my_entry; 425*1da177e4SLinus Torvalds struct nfs_fh fh; 426*1da177e4SLinus Torvalds struct nfs_fattr fattr; 427*1da177e4SLinus Torvalds long res; 428*1da177e4SLinus Torvalds 429*1da177e4SLinus Torvalds lock_kernel(); 430*1da177e4SLinus Torvalds 431*1da177e4SLinus Torvalds res = nfs_revalidate_inode(NFS_SERVER(inode), inode); 432*1da177e4SLinus Torvalds if (res < 0) { 433*1da177e4SLinus Torvalds unlock_kernel(); 434*1da177e4SLinus Torvalds return res; 435*1da177e4SLinus Torvalds } 436*1da177e4SLinus Torvalds 437*1da177e4SLinus Torvalds /* 438*1da177e4SLinus Torvalds * filp->f_pos points to the file offset in the page cache. 439*1da177e4SLinus Torvalds * but if the cache has meanwhile been zapped, we need to 440*1da177e4SLinus Torvalds * read from the last dirent to revalidate f_pos 441*1da177e4SLinus Torvalds * itself. 442*1da177e4SLinus Torvalds */ 443*1da177e4SLinus Torvalds memset(desc, 0, sizeof(*desc)); 444*1da177e4SLinus Torvalds 445*1da177e4SLinus Torvalds desc->file = filp; 446*1da177e4SLinus Torvalds desc->target = filp->f_pos; 447*1da177e4SLinus Torvalds desc->decode = NFS_PROTO(inode)->decode_dirent; 448*1da177e4SLinus Torvalds desc->plus = NFS_USE_READDIRPLUS(inode); 449*1da177e4SLinus Torvalds 450*1da177e4SLinus Torvalds my_entry.cookie = my_entry.prev_cookie = 0; 451*1da177e4SLinus Torvalds my_entry.eof = 0; 452*1da177e4SLinus Torvalds my_entry.fh = &fh; 453*1da177e4SLinus Torvalds my_entry.fattr = &fattr; 454*1da177e4SLinus Torvalds desc->entry = &my_entry; 455*1da177e4SLinus Torvalds 456*1da177e4SLinus Torvalds while(!desc->entry->eof) { 457*1da177e4SLinus Torvalds res = readdir_search_pagecache(desc); 458*1da177e4SLinus Torvalds if (res == -EBADCOOKIE) { 459*1da177e4SLinus Torvalds /* This means either end of directory */ 460*1da177e4SLinus Torvalds if (desc->entry->cookie != desc->target) { 461*1da177e4SLinus Torvalds /* Or that the server has 'lost' a cookie */ 462*1da177e4SLinus Torvalds res = uncached_readdir(desc, dirent, filldir); 463*1da177e4SLinus Torvalds if (res >= 0) 464*1da177e4SLinus Torvalds continue; 465*1da177e4SLinus Torvalds } 466*1da177e4SLinus Torvalds res = 0; 467*1da177e4SLinus Torvalds break; 468*1da177e4SLinus Torvalds } 469*1da177e4SLinus Torvalds if (res == -ETOOSMALL && desc->plus) { 470*1da177e4SLinus Torvalds NFS_FLAGS(inode) &= ~NFS_INO_ADVISE_RDPLUS; 471*1da177e4SLinus Torvalds nfs_zap_caches(inode); 472*1da177e4SLinus Torvalds desc->plus = 0; 473*1da177e4SLinus Torvalds desc->entry->eof = 0; 474*1da177e4SLinus Torvalds continue; 475*1da177e4SLinus Torvalds } 476*1da177e4SLinus Torvalds if (res < 0) 477*1da177e4SLinus Torvalds break; 478*1da177e4SLinus Torvalds 479*1da177e4SLinus Torvalds res = nfs_do_filldir(desc, dirent, filldir); 480*1da177e4SLinus Torvalds if (res < 0) { 481*1da177e4SLinus Torvalds res = 0; 482*1da177e4SLinus Torvalds break; 483*1da177e4SLinus Torvalds } 484*1da177e4SLinus Torvalds } 485*1da177e4SLinus Torvalds unlock_kernel(); 486*1da177e4SLinus Torvalds if (desc->error < 0) 487*1da177e4SLinus Torvalds return desc->error; 488*1da177e4SLinus Torvalds if (res < 0) 489*1da177e4SLinus Torvalds return res; 490*1da177e4SLinus Torvalds return 0; 491*1da177e4SLinus Torvalds } 492*1da177e4SLinus Torvalds 493*1da177e4SLinus Torvalds /* 494*1da177e4SLinus Torvalds * All directory operations under NFS are synchronous, so fsync() 495*1da177e4SLinus Torvalds * is a dummy operation. 496*1da177e4SLinus Torvalds */ 497*1da177e4SLinus Torvalds int nfs_fsync_dir(struct file *filp, struct dentry *dentry, int datasync) 498*1da177e4SLinus Torvalds { 499*1da177e4SLinus Torvalds return 0; 500*1da177e4SLinus Torvalds } 501*1da177e4SLinus Torvalds 502*1da177e4SLinus Torvalds /* 503*1da177e4SLinus Torvalds * A check for whether or not the parent directory has changed. 504*1da177e4SLinus Torvalds * In the case it has, we assume that the dentries are untrustworthy 505*1da177e4SLinus Torvalds * and may need to be looked up again. 506*1da177e4SLinus Torvalds */ 507*1da177e4SLinus Torvalds static inline int nfs_check_verifier(struct inode *dir, struct dentry *dentry) 508*1da177e4SLinus Torvalds { 509*1da177e4SLinus Torvalds if (IS_ROOT(dentry)) 510*1da177e4SLinus Torvalds return 1; 511*1da177e4SLinus Torvalds if ((NFS_FLAGS(dir) & NFS_INO_INVALID_ATTR) != 0 512*1da177e4SLinus Torvalds || nfs_attribute_timeout(dir)) 513*1da177e4SLinus Torvalds return 0; 514*1da177e4SLinus Torvalds return nfs_verify_change_attribute(dir, (unsigned long)dentry->d_fsdata); 515*1da177e4SLinus Torvalds } 516*1da177e4SLinus Torvalds 517*1da177e4SLinus Torvalds static inline void nfs_set_verifier(struct dentry * dentry, unsigned long verf) 518*1da177e4SLinus Torvalds { 519*1da177e4SLinus Torvalds dentry->d_fsdata = (void *)verf; 520*1da177e4SLinus Torvalds } 521*1da177e4SLinus Torvalds 522*1da177e4SLinus Torvalds /* 523*1da177e4SLinus Torvalds * Whenever an NFS operation succeeds, we know that the dentry 524*1da177e4SLinus Torvalds * is valid, so we update the revalidation timestamp. 525*1da177e4SLinus Torvalds */ 526*1da177e4SLinus Torvalds static inline void nfs_renew_times(struct dentry * dentry) 527*1da177e4SLinus Torvalds { 528*1da177e4SLinus Torvalds dentry->d_time = jiffies; 529*1da177e4SLinus Torvalds } 530*1da177e4SLinus Torvalds 531*1da177e4SLinus Torvalds static inline 532*1da177e4SLinus Torvalds int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd) 533*1da177e4SLinus Torvalds { 534*1da177e4SLinus Torvalds struct nfs_server *server = NFS_SERVER(inode); 535*1da177e4SLinus Torvalds 536*1da177e4SLinus Torvalds if (nd != NULL) { 537*1da177e4SLinus Torvalds int ndflags = nd->flags; 538*1da177e4SLinus Torvalds /* VFS wants an on-the-wire revalidation */ 539*1da177e4SLinus Torvalds if (ndflags & LOOKUP_REVAL) 540*1da177e4SLinus Torvalds goto out_force; 541*1da177e4SLinus Torvalds /* This is an open(2) */ 542*1da177e4SLinus Torvalds if ((ndflags & LOOKUP_OPEN) && 543*1da177e4SLinus Torvalds !(ndflags & LOOKUP_CONTINUE) && 544*1da177e4SLinus Torvalds !(server->flags & NFS_MOUNT_NOCTO)) 545*1da177e4SLinus Torvalds goto out_force; 546*1da177e4SLinus Torvalds } 547*1da177e4SLinus Torvalds return nfs_revalidate_inode(server, inode); 548*1da177e4SLinus Torvalds out_force: 549*1da177e4SLinus Torvalds return __nfs_revalidate_inode(server, inode); 550*1da177e4SLinus Torvalds } 551*1da177e4SLinus Torvalds 552*1da177e4SLinus Torvalds /* 553*1da177e4SLinus Torvalds * We judge how long we want to trust negative 554*1da177e4SLinus Torvalds * dentries by looking at the parent inode mtime. 555*1da177e4SLinus Torvalds * 556*1da177e4SLinus Torvalds * If parent mtime has changed, we revalidate, else we wait for a 557*1da177e4SLinus Torvalds * period corresponding to the parent's attribute cache timeout value. 558*1da177e4SLinus Torvalds */ 559*1da177e4SLinus Torvalds static inline 560*1da177e4SLinus Torvalds int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry, 561*1da177e4SLinus Torvalds struct nameidata *nd) 562*1da177e4SLinus Torvalds { 563*1da177e4SLinus Torvalds int ndflags = 0; 564*1da177e4SLinus Torvalds 565*1da177e4SLinus Torvalds if (nd) 566*1da177e4SLinus Torvalds ndflags = nd->flags; 567*1da177e4SLinus Torvalds /* Don't revalidate a negative dentry if we're creating a new file */ 568*1da177e4SLinus Torvalds if ((ndflags & LOOKUP_CREATE) && !(ndflags & LOOKUP_CONTINUE)) 569*1da177e4SLinus Torvalds return 0; 570*1da177e4SLinus Torvalds return !nfs_check_verifier(dir, dentry); 571*1da177e4SLinus Torvalds } 572*1da177e4SLinus Torvalds 573*1da177e4SLinus Torvalds /* 574*1da177e4SLinus Torvalds * This is called every time the dcache has a lookup hit, 575*1da177e4SLinus Torvalds * and we should check whether we can really trust that 576*1da177e4SLinus Torvalds * lookup. 577*1da177e4SLinus Torvalds * 578*1da177e4SLinus Torvalds * NOTE! The hit can be a negative hit too, don't assume 579*1da177e4SLinus Torvalds * we have an inode! 580*1da177e4SLinus Torvalds * 581*1da177e4SLinus Torvalds * If the parent directory is seen to have changed, we throw out the 582*1da177e4SLinus Torvalds * cached dentry and do a new lookup. 583*1da177e4SLinus Torvalds */ 584*1da177e4SLinus Torvalds static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) 585*1da177e4SLinus Torvalds { 586*1da177e4SLinus Torvalds struct inode *dir; 587*1da177e4SLinus Torvalds struct inode *inode; 588*1da177e4SLinus Torvalds struct dentry *parent; 589*1da177e4SLinus Torvalds int error; 590*1da177e4SLinus Torvalds struct nfs_fh fhandle; 591*1da177e4SLinus Torvalds struct nfs_fattr fattr; 592*1da177e4SLinus Torvalds unsigned long verifier; 593*1da177e4SLinus Torvalds 594*1da177e4SLinus Torvalds parent = dget_parent(dentry); 595*1da177e4SLinus Torvalds lock_kernel(); 596*1da177e4SLinus Torvalds dir = parent->d_inode; 597*1da177e4SLinus Torvalds inode = dentry->d_inode; 598*1da177e4SLinus Torvalds 599*1da177e4SLinus Torvalds if (!inode) { 600*1da177e4SLinus Torvalds if (nfs_neg_need_reval(dir, dentry, nd)) 601*1da177e4SLinus Torvalds goto out_bad; 602*1da177e4SLinus Torvalds goto out_valid; 603*1da177e4SLinus Torvalds } 604*1da177e4SLinus Torvalds 605*1da177e4SLinus Torvalds if (is_bad_inode(inode)) { 606*1da177e4SLinus Torvalds dfprintk(VFS, "nfs_lookup_validate: %s/%s has dud inode\n", 607*1da177e4SLinus Torvalds dentry->d_parent->d_name.name, dentry->d_name.name); 608*1da177e4SLinus Torvalds goto out_bad; 609*1da177e4SLinus Torvalds } 610*1da177e4SLinus Torvalds 611*1da177e4SLinus Torvalds /* Revalidate parent directory attribute cache */ 612*1da177e4SLinus Torvalds if (nfs_revalidate_inode(NFS_SERVER(dir), dir) < 0) 613*1da177e4SLinus Torvalds goto out_zap_parent; 614*1da177e4SLinus Torvalds 615*1da177e4SLinus Torvalds /* Force a full look up iff the parent directory has changed */ 616*1da177e4SLinus Torvalds if (nfs_check_verifier(dir, dentry)) { 617*1da177e4SLinus Torvalds if (nfs_lookup_verify_inode(inode, nd)) 618*1da177e4SLinus Torvalds goto out_zap_parent; 619*1da177e4SLinus Torvalds goto out_valid; 620*1da177e4SLinus Torvalds } 621*1da177e4SLinus Torvalds 622*1da177e4SLinus Torvalds if (NFS_STALE(inode)) 623*1da177e4SLinus Torvalds goto out_bad; 624*1da177e4SLinus Torvalds 625*1da177e4SLinus Torvalds verifier = nfs_save_change_attribute(dir); 626*1da177e4SLinus Torvalds error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); 627*1da177e4SLinus Torvalds if (error) 628*1da177e4SLinus Torvalds goto out_bad; 629*1da177e4SLinus Torvalds if (nfs_compare_fh(NFS_FH(inode), &fhandle)) 630*1da177e4SLinus Torvalds goto out_bad; 631*1da177e4SLinus Torvalds if ((error = nfs_refresh_inode(inode, &fattr)) != 0) 632*1da177e4SLinus Torvalds goto out_bad; 633*1da177e4SLinus Torvalds 634*1da177e4SLinus Torvalds nfs_renew_times(dentry); 635*1da177e4SLinus Torvalds nfs_set_verifier(dentry, verifier); 636*1da177e4SLinus Torvalds out_valid: 637*1da177e4SLinus Torvalds unlock_kernel(); 638*1da177e4SLinus Torvalds dput(parent); 639*1da177e4SLinus Torvalds return 1; 640*1da177e4SLinus Torvalds out_zap_parent: 641*1da177e4SLinus Torvalds nfs_zap_caches(dir); 642*1da177e4SLinus Torvalds out_bad: 643*1da177e4SLinus Torvalds NFS_CACHEINV(dir); 644*1da177e4SLinus Torvalds if (inode && S_ISDIR(inode->i_mode)) { 645*1da177e4SLinus Torvalds /* Purge readdir caches. */ 646*1da177e4SLinus Torvalds nfs_zap_caches(inode); 647*1da177e4SLinus Torvalds /* If we have submounts, don't unhash ! */ 648*1da177e4SLinus Torvalds if (have_submounts(dentry)) 649*1da177e4SLinus Torvalds goto out_valid; 650*1da177e4SLinus Torvalds shrink_dcache_parent(dentry); 651*1da177e4SLinus Torvalds } 652*1da177e4SLinus Torvalds d_drop(dentry); 653*1da177e4SLinus Torvalds unlock_kernel(); 654*1da177e4SLinus Torvalds dput(parent); 655*1da177e4SLinus Torvalds return 0; 656*1da177e4SLinus Torvalds } 657*1da177e4SLinus Torvalds 658*1da177e4SLinus Torvalds /* 659*1da177e4SLinus Torvalds * This is called from dput() when d_count is going to 0. 660*1da177e4SLinus Torvalds */ 661*1da177e4SLinus Torvalds static int nfs_dentry_delete(struct dentry *dentry) 662*1da177e4SLinus Torvalds { 663*1da177e4SLinus Torvalds dfprintk(VFS, "NFS: dentry_delete(%s/%s, %x)\n", 664*1da177e4SLinus Torvalds dentry->d_parent->d_name.name, dentry->d_name.name, 665*1da177e4SLinus Torvalds dentry->d_flags); 666*1da177e4SLinus Torvalds 667*1da177e4SLinus Torvalds if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { 668*1da177e4SLinus Torvalds /* Unhash it, so that ->d_iput() would be called */ 669*1da177e4SLinus Torvalds return 1; 670*1da177e4SLinus Torvalds } 671*1da177e4SLinus Torvalds if (!(dentry->d_sb->s_flags & MS_ACTIVE)) { 672*1da177e4SLinus Torvalds /* Unhash it, so that ancestors of killed async unlink 673*1da177e4SLinus Torvalds * files will be cleaned up during umount */ 674*1da177e4SLinus Torvalds return 1; 675*1da177e4SLinus Torvalds } 676*1da177e4SLinus Torvalds return 0; 677*1da177e4SLinus Torvalds 678*1da177e4SLinus Torvalds } 679*1da177e4SLinus Torvalds 680*1da177e4SLinus Torvalds /* 681*1da177e4SLinus Torvalds * Called when the dentry loses inode. 682*1da177e4SLinus Torvalds * We use it to clean up silly-renamed files. 683*1da177e4SLinus Torvalds */ 684*1da177e4SLinus Torvalds static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode) 685*1da177e4SLinus Torvalds { 686*1da177e4SLinus Torvalds if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { 687*1da177e4SLinus Torvalds lock_kernel(); 688*1da177e4SLinus Torvalds inode->i_nlink--; 689*1da177e4SLinus Torvalds nfs_complete_unlink(dentry); 690*1da177e4SLinus Torvalds unlock_kernel(); 691*1da177e4SLinus Torvalds } 692*1da177e4SLinus Torvalds /* When creating a negative dentry, we want to renew d_time */ 693*1da177e4SLinus Torvalds nfs_renew_times(dentry); 694*1da177e4SLinus Torvalds iput(inode); 695*1da177e4SLinus Torvalds } 696*1da177e4SLinus Torvalds 697*1da177e4SLinus Torvalds struct dentry_operations nfs_dentry_operations = { 698*1da177e4SLinus Torvalds .d_revalidate = nfs_lookup_revalidate, 699*1da177e4SLinus Torvalds .d_delete = nfs_dentry_delete, 700*1da177e4SLinus Torvalds .d_iput = nfs_dentry_iput, 701*1da177e4SLinus Torvalds }; 702*1da177e4SLinus Torvalds 703*1da177e4SLinus Torvalds static inline 704*1da177e4SLinus Torvalds int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd) 705*1da177e4SLinus Torvalds { 706*1da177e4SLinus Torvalds if (NFS_PROTO(dir)->version == 2) 707*1da177e4SLinus Torvalds return 0; 708*1da177e4SLinus Torvalds if (!nd || (nd->flags & LOOKUP_CONTINUE) || !(nd->flags & LOOKUP_CREATE)) 709*1da177e4SLinus Torvalds return 0; 710*1da177e4SLinus Torvalds return (nd->intent.open.flags & O_EXCL) != 0; 711*1da177e4SLinus Torvalds } 712*1da177e4SLinus Torvalds 713*1da177e4SLinus Torvalds static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) 714*1da177e4SLinus Torvalds { 715*1da177e4SLinus Torvalds struct dentry *res; 716*1da177e4SLinus Torvalds struct inode *inode = NULL; 717*1da177e4SLinus Torvalds int error; 718*1da177e4SLinus Torvalds struct nfs_fh fhandle; 719*1da177e4SLinus Torvalds struct nfs_fattr fattr; 720*1da177e4SLinus Torvalds 721*1da177e4SLinus Torvalds dfprintk(VFS, "NFS: lookup(%s/%s)\n", 722*1da177e4SLinus Torvalds dentry->d_parent->d_name.name, dentry->d_name.name); 723*1da177e4SLinus Torvalds 724*1da177e4SLinus Torvalds res = ERR_PTR(-ENAMETOOLONG); 725*1da177e4SLinus Torvalds if (dentry->d_name.len > NFS_SERVER(dir)->namelen) 726*1da177e4SLinus Torvalds goto out; 727*1da177e4SLinus Torvalds 728*1da177e4SLinus Torvalds res = ERR_PTR(-ENOMEM); 729*1da177e4SLinus Torvalds dentry->d_op = NFS_PROTO(dir)->dentry_ops; 730*1da177e4SLinus Torvalds 731*1da177e4SLinus Torvalds lock_kernel(); 732*1da177e4SLinus Torvalds /* Revalidate parent directory attribute cache */ 733*1da177e4SLinus Torvalds error = nfs_revalidate_inode(NFS_SERVER(dir), dir); 734*1da177e4SLinus Torvalds if (error < 0) { 735*1da177e4SLinus Torvalds res = ERR_PTR(error); 736*1da177e4SLinus Torvalds goto out_unlock; 737*1da177e4SLinus Torvalds } 738*1da177e4SLinus Torvalds 739*1da177e4SLinus Torvalds /* If we're doing an exclusive create, optimize away the lookup */ 740*1da177e4SLinus Torvalds if (nfs_is_exclusive_create(dir, nd)) 741*1da177e4SLinus Torvalds goto no_entry; 742*1da177e4SLinus Torvalds 743*1da177e4SLinus Torvalds error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); 744*1da177e4SLinus Torvalds if (error == -ENOENT) 745*1da177e4SLinus Torvalds goto no_entry; 746*1da177e4SLinus Torvalds if (error < 0) { 747*1da177e4SLinus Torvalds res = ERR_PTR(error); 748*1da177e4SLinus Torvalds goto out_unlock; 749*1da177e4SLinus Torvalds } 750*1da177e4SLinus Torvalds res = ERR_PTR(-EACCES); 751*1da177e4SLinus Torvalds inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr); 752*1da177e4SLinus Torvalds if (!inode) 753*1da177e4SLinus Torvalds goto out_unlock; 754*1da177e4SLinus Torvalds no_entry: 755*1da177e4SLinus Torvalds res = d_add_unique(dentry, inode); 756*1da177e4SLinus Torvalds if (res != NULL) 757*1da177e4SLinus Torvalds dentry = res; 758*1da177e4SLinus Torvalds nfs_renew_times(dentry); 759*1da177e4SLinus Torvalds nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); 760*1da177e4SLinus Torvalds out_unlock: 761*1da177e4SLinus Torvalds unlock_kernel(); 762*1da177e4SLinus Torvalds out: 763*1da177e4SLinus Torvalds return res; 764*1da177e4SLinus Torvalds } 765*1da177e4SLinus Torvalds 766*1da177e4SLinus Torvalds #ifdef CONFIG_NFS_V4 767*1da177e4SLinus Torvalds static int nfs_open_revalidate(struct dentry *, struct nameidata *); 768*1da177e4SLinus Torvalds 769*1da177e4SLinus Torvalds struct dentry_operations nfs4_dentry_operations = { 770*1da177e4SLinus Torvalds .d_revalidate = nfs_open_revalidate, 771*1da177e4SLinus Torvalds .d_delete = nfs_dentry_delete, 772*1da177e4SLinus Torvalds .d_iput = nfs_dentry_iput, 773*1da177e4SLinus Torvalds }; 774*1da177e4SLinus Torvalds 775*1da177e4SLinus Torvalds static int is_atomic_open(struct inode *dir, struct nameidata *nd) 776*1da177e4SLinus Torvalds { 777*1da177e4SLinus Torvalds if (!nd) 778*1da177e4SLinus Torvalds return 0; 779*1da177e4SLinus Torvalds /* Check that we are indeed trying to open this file */ 780*1da177e4SLinus Torvalds if ((nd->flags & LOOKUP_CONTINUE) || !(nd->flags & LOOKUP_OPEN)) 781*1da177e4SLinus Torvalds return 0; 782*1da177e4SLinus Torvalds /* NFS does not (yet) have a stateful open for directories */ 783*1da177e4SLinus Torvalds if (nd->flags & LOOKUP_DIRECTORY) 784*1da177e4SLinus Torvalds return 0; 785*1da177e4SLinus Torvalds /* Are we trying to write to a read only partition? */ 786*1da177e4SLinus Torvalds if (IS_RDONLY(dir) && (nd->intent.open.flags & (O_CREAT|O_TRUNC|FMODE_WRITE))) 787*1da177e4SLinus Torvalds return 0; 788*1da177e4SLinus Torvalds return 1; 789*1da177e4SLinus Torvalds } 790*1da177e4SLinus Torvalds 791*1da177e4SLinus Torvalds static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) 792*1da177e4SLinus Torvalds { 793*1da177e4SLinus Torvalds struct dentry *res = NULL; 794*1da177e4SLinus Torvalds struct inode *inode = NULL; 795*1da177e4SLinus Torvalds int error; 796*1da177e4SLinus Torvalds 797*1da177e4SLinus Torvalds /* Check that we are indeed trying to open this file */ 798*1da177e4SLinus Torvalds if (!is_atomic_open(dir, nd)) 799*1da177e4SLinus Torvalds goto no_open; 800*1da177e4SLinus Torvalds 801*1da177e4SLinus Torvalds if (dentry->d_name.len > NFS_SERVER(dir)->namelen) { 802*1da177e4SLinus Torvalds res = ERR_PTR(-ENAMETOOLONG); 803*1da177e4SLinus Torvalds goto out; 804*1da177e4SLinus Torvalds } 805*1da177e4SLinus Torvalds dentry->d_op = NFS_PROTO(dir)->dentry_ops; 806*1da177e4SLinus Torvalds 807*1da177e4SLinus Torvalds /* Let vfs_create() deal with O_EXCL */ 808*1da177e4SLinus Torvalds if (nd->intent.open.flags & O_EXCL) 809*1da177e4SLinus Torvalds goto no_entry; 810*1da177e4SLinus Torvalds 811*1da177e4SLinus Torvalds /* Open the file on the server */ 812*1da177e4SLinus Torvalds lock_kernel(); 813*1da177e4SLinus Torvalds /* Revalidate parent directory attribute cache */ 814*1da177e4SLinus Torvalds error = nfs_revalidate_inode(NFS_SERVER(dir), dir); 815*1da177e4SLinus Torvalds if (error < 0) { 816*1da177e4SLinus Torvalds res = ERR_PTR(error); 817*1da177e4SLinus Torvalds goto out; 818*1da177e4SLinus Torvalds } 819*1da177e4SLinus Torvalds 820*1da177e4SLinus Torvalds if (nd->intent.open.flags & O_CREAT) { 821*1da177e4SLinus Torvalds nfs_begin_data_update(dir); 822*1da177e4SLinus Torvalds inode = nfs4_atomic_open(dir, dentry, nd); 823*1da177e4SLinus Torvalds nfs_end_data_update(dir); 824*1da177e4SLinus Torvalds } else 825*1da177e4SLinus Torvalds inode = nfs4_atomic_open(dir, dentry, nd); 826*1da177e4SLinus Torvalds unlock_kernel(); 827*1da177e4SLinus Torvalds if (IS_ERR(inode)) { 828*1da177e4SLinus Torvalds error = PTR_ERR(inode); 829*1da177e4SLinus Torvalds switch (error) { 830*1da177e4SLinus Torvalds /* Make a negative dentry */ 831*1da177e4SLinus Torvalds case -ENOENT: 832*1da177e4SLinus Torvalds inode = NULL; 833*1da177e4SLinus Torvalds break; 834*1da177e4SLinus Torvalds /* This turned out not to be a regular file */ 835*1da177e4SLinus Torvalds case -ELOOP: 836*1da177e4SLinus Torvalds if (!(nd->intent.open.flags & O_NOFOLLOW)) 837*1da177e4SLinus Torvalds goto no_open; 838*1da177e4SLinus Torvalds /* case -EISDIR: */ 839*1da177e4SLinus Torvalds /* case -EINVAL: */ 840*1da177e4SLinus Torvalds default: 841*1da177e4SLinus Torvalds res = ERR_PTR(error); 842*1da177e4SLinus Torvalds goto out; 843*1da177e4SLinus Torvalds } 844*1da177e4SLinus Torvalds } 845*1da177e4SLinus Torvalds no_entry: 846*1da177e4SLinus Torvalds res = d_add_unique(dentry, inode); 847*1da177e4SLinus Torvalds if (res != NULL) 848*1da177e4SLinus Torvalds dentry = res; 849*1da177e4SLinus Torvalds nfs_renew_times(dentry); 850*1da177e4SLinus Torvalds nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); 851*1da177e4SLinus Torvalds out: 852*1da177e4SLinus Torvalds return res; 853*1da177e4SLinus Torvalds no_open: 854*1da177e4SLinus Torvalds return nfs_lookup(dir, dentry, nd); 855*1da177e4SLinus Torvalds } 856*1da177e4SLinus Torvalds 857*1da177e4SLinus Torvalds static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) 858*1da177e4SLinus Torvalds { 859*1da177e4SLinus Torvalds struct dentry *parent = NULL; 860*1da177e4SLinus Torvalds struct inode *inode = dentry->d_inode; 861*1da177e4SLinus Torvalds struct inode *dir; 862*1da177e4SLinus Torvalds unsigned long verifier; 863*1da177e4SLinus Torvalds int openflags, ret = 0; 864*1da177e4SLinus Torvalds 865*1da177e4SLinus Torvalds parent = dget_parent(dentry); 866*1da177e4SLinus Torvalds dir = parent->d_inode; 867*1da177e4SLinus Torvalds if (!is_atomic_open(dir, nd)) 868*1da177e4SLinus Torvalds goto no_open; 869*1da177e4SLinus Torvalds /* We can't create new files in nfs_open_revalidate(), so we 870*1da177e4SLinus Torvalds * optimize away revalidation of negative dentries. 871*1da177e4SLinus Torvalds */ 872*1da177e4SLinus Torvalds if (inode == NULL) 873*1da177e4SLinus Torvalds goto out; 874*1da177e4SLinus Torvalds /* NFS only supports OPEN on regular files */ 875*1da177e4SLinus Torvalds if (!S_ISREG(inode->i_mode)) 876*1da177e4SLinus Torvalds goto no_open; 877*1da177e4SLinus Torvalds openflags = nd->intent.open.flags; 878*1da177e4SLinus Torvalds /* We cannot do exclusive creation on a positive dentry */ 879*1da177e4SLinus Torvalds if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) 880*1da177e4SLinus Torvalds goto no_open; 881*1da177e4SLinus Torvalds /* We can't create new files, or truncate existing ones here */ 882*1da177e4SLinus Torvalds openflags &= ~(O_CREAT|O_TRUNC); 883*1da177e4SLinus Torvalds 884*1da177e4SLinus Torvalds /* 885*1da177e4SLinus Torvalds * Note: we're not holding inode->i_sem and so may be racing with 886*1da177e4SLinus Torvalds * operations that change the directory. We therefore save the 887*1da177e4SLinus Torvalds * change attribute *before* we do the RPC call. 888*1da177e4SLinus Torvalds */ 889*1da177e4SLinus Torvalds lock_kernel(); 890*1da177e4SLinus Torvalds verifier = nfs_save_change_attribute(dir); 891*1da177e4SLinus Torvalds ret = nfs4_open_revalidate(dir, dentry, openflags); 892*1da177e4SLinus Torvalds if (!ret) 893*1da177e4SLinus Torvalds nfs_set_verifier(dentry, verifier); 894*1da177e4SLinus Torvalds unlock_kernel(); 895*1da177e4SLinus Torvalds out: 896*1da177e4SLinus Torvalds dput(parent); 897*1da177e4SLinus Torvalds if (!ret) 898*1da177e4SLinus Torvalds d_drop(dentry); 899*1da177e4SLinus Torvalds return ret; 900*1da177e4SLinus Torvalds no_open: 901*1da177e4SLinus Torvalds dput(parent); 902*1da177e4SLinus Torvalds if (inode != NULL && nfs_have_delegation(inode, FMODE_READ)) 903*1da177e4SLinus Torvalds return 1; 904*1da177e4SLinus Torvalds return nfs_lookup_revalidate(dentry, nd); 905*1da177e4SLinus Torvalds } 906*1da177e4SLinus Torvalds #endif /* CONFIG_NFSV4 */ 907*1da177e4SLinus Torvalds 908*1da177e4SLinus Torvalds static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc) 909*1da177e4SLinus Torvalds { 910*1da177e4SLinus Torvalds struct dentry *parent = desc->file->f_dentry; 911*1da177e4SLinus Torvalds struct inode *dir = parent->d_inode; 912*1da177e4SLinus Torvalds struct nfs_entry *entry = desc->entry; 913*1da177e4SLinus Torvalds struct dentry *dentry, *alias; 914*1da177e4SLinus Torvalds struct qstr name = { 915*1da177e4SLinus Torvalds .name = entry->name, 916*1da177e4SLinus Torvalds .len = entry->len, 917*1da177e4SLinus Torvalds }; 918*1da177e4SLinus Torvalds struct inode *inode; 919*1da177e4SLinus Torvalds 920*1da177e4SLinus Torvalds switch (name.len) { 921*1da177e4SLinus Torvalds case 2: 922*1da177e4SLinus Torvalds if (name.name[0] == '.' && name.name[1] == '.') 923*1da177e4SLinus Torvalds return dget_parent(parent); 924*1da177e4SLinus Torvalds break; 925*1da177e4SLinus Torvalds case 1: 926*1da177e4SLinus Torvalds if (name.name[0] == '.') 927*1da177e4SLinus Torvalds return dget(parent); 928*1da177e4SLinus Torvalds } 929*1da177e4SLinus Torvalds name.hash = full_name_hash(name.name, name.len); 930*1da177e4SLinus Torvalds dentry = d_lookup(parent, &name); 931*1da177e4SLinus Torvalds if (dentry != NULL) 932*1da177e4SLinus Torvalds return dentry; 933*1da177e4SLinus Torvalds if (!desc->plus || !(entry->fattr->valid & NFS_ATTR_FATTR)) 934*1da177e4SLinus Torvalds return NULL; 935*1da177e4SLinus Torvalds /* Note: caller is already holding the dir->i_sem! */ 936*1da177e4SLinus Torvalds dentry = d_alloc(parent, &name); 937*1da177e4SLinus Torvalds if (dentry == NULL) 938*1da177e4SLinus Torvalds return NULL; 939*1da177e4SLinus Torvalds dentry->d_op = NFS_PROTO(dir)->dentry_ops; 940*1da177e4SLinus Torvalds inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr); 941*1da177e4SLinus Torvalds if (!inode) { 942*1da177e4SLinus Torvalds dput(dentry); 943*1da177e4SLinus Torvalds return NULL; 944*1da177e4SLinus Torvalds } 945*1da177e4SLinus Torvalds alias = d_add_unique(dentry, inode); 946*1da177e4SLinus Torvalds if (alias != NULL) { 947*1da177e4SLinus Torvalds dput(dentry); 948*1da177e4SLinus Torvalds dentry = alias; 949*1da177e4SLinus Torvalds } 950*1da177e4SLinus Torvalds nfs_renew_times(dentry); 951*1da177e4SLinus Torvalds nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); 952*1da177e4SLinus Torvalds return dentry; 953*1da177e4SLinus Torvalds } 954*1da177e4SLinus Torvalds 955*1da177e4SLinus Torvalds /* 956*1da177e4SLinus Torvalds * Code common to create, mkdir, and mknod. 957*1da177e4SLinus Torvalds */ 958*1da177e4SLinus Torvalds int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, 959*1da177e4SLinus Torvalds struct nfs_fattr *fattr) 960*1da177e4SLinus Torvalds { 961*1da177e4SLinus Torvalds struct inode *inode; 962*1da177e4SLinus Torvalds int error = -EACCES; 963*1da177e4SLinus Torvalds 964*1da177e4SLinus Torvalds /* We may have been initialized further down */ 965*1da177e4SLinus Torvalds if (dentry->d_inode) 966*1da177e4SLinus Torvalds return 0; 967*1da177e4SLinus Torvalds if (fhandle->size == 0) { 968*1da177e4SLinus Torvalds struct inode *dir = dentry->d_parent->d_inode; 969*1da177e4SLinus Torvalds error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); 970*1da177e4SLinus Torvalds if (error) 971*1da177e4SLinus Torvalds goto out_err; 972*1da177e4SLinus Torvalds } 973*1da177e4SLinus Torvalds if (!(fattr->valid & NFS_ATTR_FATTR)) { 974*1da177e4SLinus Torvalds struct nfs_server *server = NFS_SB(dentry->d_sb); 975*1da177e4SLinus Torvalds error = server->rpc_ops->getattr(server, fhandle, fattr); 976*1da177e4SLinus Torvalds if (error < 0) 977*1da177e4SLinus Torvalds goto out_err; 978*1da177e4SLinus Torvalds } 979*1da177e4SLinus Torvalds error = -ENOMEM; 980*1da177e4SLinus Torvalds inode = nfs_fhget(dentry->d_sb, fhandle, fattr); 981*1da177e4SLinus Torvalds if (inode == NULL) 982*1da177e4SLinus Torvalds goto out_err; 983*1da177e4SLinus Torvalds d_instantiate(dentry, inode); 984*1da177e4SLinus Torvalds return 0; 985*1da177e4SLinus Torvalds out_err: 986*1da177e4SLinus Torvalds d_drop(dentry); 987*1da177e4SLinus Torvalds return error; 988*1da177e4SLinus Torvalds } 989*1da177e4SLinus Torvalds 990*1da177e4SLinus Torvalds /* 991*1da177e4SLinus Torvalds * Following a failed create operation, we drop the dentry rather 992*1da177e4SLinus Torvalds * than retain a negative dentry. This avoids a problem in the event 993*1da177e4SLinus Torvalds * that the operation succeeded on the server, but an error in the 994*1da177e4SLinus Torvalds * reply path made it appear to have failed. 995*1da177e4SLinus Torvalds */ 996*1da177e4SLinus Torvalds static int nfs_create(struct inode *dir, struct dentry *dentry, int mode, 997*1da177e4SLinus Torvalds struct nameidata *nd) 998*1da177e4SLinus Torvalds { 999*1da177e4SLinus Torvalds struct iattr attr; 1000*1da177e4SLinus Torvalds int error; 1001*1da177e4SLinus Torvalds int open_flags = 0; 1002*1da177e4SLinus Torvalds 1003*1da177e4SLinus Torvalds dfprintk(VFS, "NFS: create(%s/%ld, %s\n", dir->i_sb->s_id, 1004*1da177e4SLinus Torvalds dir->i_ino, dentry->d_name.name); 1005*1da177e4SLinus Torvalds 1006*1da177e4SLinus Torvalds attr.ia_mode = mode; 1007*1da177e4SLinus Torvalds attr.ia_valid = ATTR_MODE; 1008*1da177e4SLinus Torvalds 1009*1da177e4SLinus Torvalds if (nd && (nd->flags & LOOKUP_CREATE)) 1010*1da177e4SLinus Torvalds open_flags = nd->intent.open.flags; 1011*1da177e4SLinus Torvalds 1012*1da177e4SLinus Torvalds lock_kernel(); 1013*1da177e4SLinus Torvalds nfs_begin_data_update(dir); 1014*1da177e4SLinus Torvalds error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags); 1015*1da177e4SLinus Torvalds nfs_end_data_update(dir); 1016*1da177e4SLinus Torvalds if (error != 0) 1017*1da177e4SLinus Torvalds goto out_err; 1018*1da177e4SLinus Torvalds nfs_renew_times(dentry); 1019*1da177e4SLinus Torvalds nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); 1020*1da177e4SLinus Torvalds unlock_kernel(); 1021*1da177e4SLinus Torvalds return 0; 1022*1da177e4SLinus Torvalds out_err: 1023*1da177e4SLinus Torvalds unlock_kernel(); 1024*1da177e4SLinus Torvalds d_drop(dentry); 1025*1da177e4SLinus Torvalds return error; 1026*1da177e4SLinus Torvalds } 1027*1da177e4SLinus Torvalds 1028*1da177e4SLinus Torvalds /* 1029*1da177e4SLinus Torvalds * See comments for nfs_proc_create regarding failed operations. 1030*1da177e4SLinus Torvalds */ 1031*1da177e4SLinus Torvalds static int 1032*1da177e4SLinus Torvalds nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) 1033*1da177e4SLinus Torvalds { 1034*1da177e4SLinus Torvalds struct iattr attr; 1035*1da177e4SLinus Torvalds int status; 1036*1da177e4SLinus Torvalds 1037*1da177e4SLinus Torvalds dfprintk(VFS, "NFS: mknod(%s/%ld, %s\n", dir->i_sb->s_id, 1038*1da177e4SLinus Torvalds dir->i_ino, dentry->d_name.name); 1039*1da177e4SLinus Torvalds 1040*1da177e4SLinus Torvalds if (!new_valid_dev(rdev)) 1041*1da177e4SLinus Torvalds return -EINVAL; 1042*1da177e4SLinus Torvalds 1043*1da177e4SLinus Torvalds attr.ia_mode = mode; 1044*1da177e4SLinus Torvalds attr.ia_valid = ATTR_MODE; 1045*1da177e4SLinus Torvalds 1046*1da177e4SLinus Torvalds lock_kernel(); 1047*1da177e4SLinus Torvalds nfs_begin_data_update(dir); 1048*1da177e4SLinus Torvalds status = NFS_PROTO(dir)->mknod(dir, dentry, &attr, rdev); 1049*1da177e4SLinus Torvalds nfs_end_data_update(dir); 1050*1da177e4SLinus Torvalds if (status != 0) 1051*1da177e4SLinus Torvalds goto out_err; 1052*1da177e4SLinus Torvalds nfs_renew_times(dentry); 1053*1da177e4SLinus Torvalds nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); 1054*1da177e4SLinus Torvalds unlock_kernel(); 1055*1da177e4SLinus Torvalds return 0; 1056*1da177e4SLinus Torvalds out_err: 1057*1da177e4SLinus Torvalds unlock_kernel(); 1058*1da177e4SLinus Torvalds d_drop(dentry); 1059*1da177e4SLinus Torvalds return status; 1060*1da177e4SLinus Torvalds } 1061*1da177e4SLinus Torvalds 1062*1da177e4SLinus Torvalds /* 1063*1da177e4SLinus Torvalds * See comments for nfs_proc_create regarding failed operations. 1064*1da177e4SLinus Torvalds */ 1065*1da177e4SLinus Torvalds static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) 1066*1da177e4SLinus Torvalds { 1067*1da177e4SLinus Torvalds struct iattr attr; 1068*1da177e4SLinus Torvalds int error; 1069*1da177e4SLinus Torvalds 1070*1da177e4SLinus Torvalds dfprintk(VFS, "NFS: mkdir(%s/%ld, %s\n", dir->i_sb->s_id, 1071*1da177e4SLinus Torvalds dir->i_ino, dentry->d_name.name); 1072*1da177e4SLinus Torvalds 1073*1da177e4SLinus Torvalds attr.ia_valid = ATTR_MODE; 1074*1da177e4SLinus Torvalds attr.ia_mode = mode | S_IFDIR; 1075*1da177e4SLinus Torvalds 1076*1da177e4SLinus Torvalds lock_kernel(); 1077*1da177e4SLinus Torvalds nfs_begin_data_update(dir); 1078*1da177e4SLinus Torvalds error = NFS_PROTO(dir)->mkdir(dir, dentry, &attr); 1079*1da177e4SLinus Torvalds nfs_end_data_update(dir); 1080*1da177e4SLinus Torvalds if (error != 0) 1081*1da177e4SLinus Torvalds goto out_err; 1082*1da177e4SLinus Torvalds nfs_renew_times(dentry); 1083*1da177e4SLinus Torvalds nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); 1084*1da177e4SLinus Torvalds unlock_kernel(); 1085*1da177e4SLinus Torvalds return 0; 1086*1da177e4SLinus Torvalds out_err: 1087*1da177e4SLinus Torvalds d_drop(dentry); 1088*1da177e4SLinus Torvalds unlock_kernel(); 1089*1da177e4SLinus Torvalds return error; 1090*1da177e4SLinus Torvalds } 1091*1da177e4SLinus Torvalds 1092*1da177e4SLinus Torvalds static int nfs_rmdir(struct inode *dir, struct dentry *dentry) 1093*1da177e4SLinus Torvalds { 1094*1da177e4SLinus Torvalds int error; 1095*1da177e4SLinus Torvalds 1096*1da177e4SLinus Torvalds dfprintk(VFS, "NFS: rmdir(%s/%ld, %s\n", dir->i_sb->s_id, 1097*1da177e4SLinus Torvalds dir->i_ino, dentry->d_name.name); 1098*1da177e4SLinus Torvalds 1099*1da177e4SLinus Torvalds lock_kernel(); 1100*1da177e4SLinus Torvalds nfs_begin_data_update(dir); 1101*1da177e4SLinus Torvalds error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name); 1102*1da177e4SLinus Torvalds /* Ensure the VFS deletes this inode */ 1103*1da177e4SLinus Torvalds if (error == 0 && dentry->d_inode != NULL) 1104*1da177e4SLinus Torvalds dentry->d_inode->i_nlink = 0; 1105*1da177e4SLinus Torvalds nfs_end_data_update(dir); 1106*1da177e4SLinus Torvalds unlock_kernel(); 1107*1da177e4SLinus Torvalds 1108*1da177e4SLinus Torvalds return error; 1109*1da177e4SLinus Torvalds } 1110*1da177e4SLinus Torvalds 1111*1da177e4SLinus Torvalds static int nfs_sillyrename(struct inode *dir, struct dentry *dentry) 1112*1da177e4SLinus Torvalds { 1113*1da177e4SLinus Torvalds static unsigned int sillycounter; 1114*1da177e4SLinus Torvalds const int i_inosize = sizeof(dir->i_ino)*2; 1115*1da177e4SLinus Torvalds const int countersize = sizeof(sillycounter)*2; 1116*1da177e4SLinus Torvalds const int slen = sizeof(".nfs") + i_inosize + countersize - 1; 1117*1da177e4SLinus Torvalds char silly[slen+1]; 1118*1da177e4SLinus Torvalds struct qstr qsilly; 1119*1da177e4SLinus Torvalds struct dentry *sdentry; 1120*1da177e4SLinus Torvalds int error = -EIO; 1121*1da177e4SLinus Torvalds 1122*1da177e4SLinus Torvalds dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n", 1123*1da177e4SLinus Torvalds dentry->d_parent->d_name.name, dentry->d_name.name, 1124*1da177e4SLinus Torvalds atomic_read(&dentry->d_count)); 1125*1da177e4SLinus Torvalds 1126*1da177e4SLinus Torvalds #ifdef NFS_PARANOIA 1127*1da177e4SLinus Torvalds if (!dentry->d_inode) 1128*1da177e4SLinus Torvalds printk("NFS: silly-renaming %s/%s, negative dentry??\n", 1129*1da177e4SLinus Torvalds dentry->d_parent->d_name.name, dentry->d_name.name); 1130*1da177e4SLinus Torvalds #endif 1131*1da177e4SLinus Torvalds /* 1132*1da177e4SLinus Torvalds * We don't allow a dentry to be silly-renamed twice. 1133*1da177e4SLinus Torvalds */ 1134*1da177e4SLinus Torvalds error = -EBUSY; 1135*1da177e4SLinus Torvalds if (dentry->d_flags & DCACHE_NFSFS_RENAMED) 1136*1da177e4SLinus Torvalds goto out; 1137*1da177e4SLinus Torvalds 1138*1da177e4SLinus Torvalds sprintf(silly, ".nfs%*.*lx", 1139*1da177e4SLinus Torvalds i_inosize, i_inosize, dentry->d_inode->i_ino); 1140*1da177e4SLinus Torvalds 1141*1da177e4SLinus Torvalds sdentry = NULL; 1142*1da177e4SLinus Torvalds do { 1143*1da177e4SLinus Torvalds char *suffix = silly + slen - countersize; 1144*1da177e4SLinus Torvalds 1145*1da177e4SLinus Torvalds dput(sdentry); 1146*1da177e4SLinus Torvalds sillycounter++; 1147*1da177e4SLinus Torvalds sprintf(suffix, "%*.*x", countersize, countersize, sillycounter); 1148*1da177e4SLinus Torvalds 1149*1da177e4SLinus Torvalds dfprintk(VFS, "trying to rename %s to %s\n", 1150*1da177e4SLinus Torvalds dentry->d_name.name, silly); 1151*1da177e4SLinus Torvalds 1152*1da177e4SLinus Torvalds sdentry = lookup_one_len(silly, dentry->d_parent, slen); 1153*1da177e4SLinus Torvalds /* 1154*1da177e4SLinus Torvalds * N.B. Better to return EBUSY here ... it could be 1155*1da177e4SLinus Torvalds * dangerous to delete the file while it's in use. 1156*1da177e4SLinus Torvalds */ 1157*1da177e4SLinus Torvalds if (IS_ERR(sdentry)) 1158*1da177e4SLinus Torvalds goto out; 1159*1da177e4SLinus Torvalds } while(sdentry->d_inode != NULL); /* need negative lookup */ 1160*1da177e4SLinus Torvalds 1161*1da177e4SLinus Torvalds qsilly.name = silly; 1162*1da177e4SLinus Torvalds qsilly.len = strlen(silly); 1163*1da177e4SLinus Torvalds nfs_begin_data_update(dir); 1164*1da177e4SLinus Torvalds if (dentry->d_inode) { 1165*1da177e4SLinus Torvalds nfs_begin_data_update(dentry->d_inode); 1166*1da177e4SLinus Torvalds error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, 1167*1da177e4SLinus Torvalds dir, &qsilly); 1168*1da177e4SLinus Torvalds nfs_end_data_update(dentry->d_inode); 1169*1da177e4SLinus Torvalds } else 1170*1da177e4SLinus Torvalds error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, 1171*1da177e4SLinus Torvalds dir, &qsilly); 1172*1da177e4SLinus Torvalds nfs_end_data_update(dir); 1173*1da177e4SLinus Torvalds if (!error) { 1174*1da177e4SLinus Torvalds nfs_renew_times(dentry); 1175*1da177e4SLinus Torvalds nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); 1176*1da177e4SLinus Torvalds d_move(dentry, sdentry); 1177*1da177e4SLinus Torvalds error = nfs_async_unlink(dentry); 1178*1da177e4SLinus Torvalds /* If we return 0 we don't unlink */ 1179*1da177e4SLinus Torvalds } 1180*1da177e4SLinus Torvalds dput(sdentry); 1181*1da177e4SLinus Torvalds out: 1182*1da177e4SLinus Torvalds return error; 1183*1da177e4SLinus Torvalds } 1184*1da177e4SLinus Torvalds 1185*1da177e4SLinus Torvalds /* 1186*1da177e4SLinus Torvalds * Remove a file after making sure there are no pending writes, 1187*1da177e4SLinus Torvalds * and after checking that the file has only one user. 1188*1da177e4SLinus Torvalds * 1189*1da177e4SLinus Torvalds * We invalidate the attribute cache and free the inode prior to the operation 1190*1da177e4SLinus Torvalds * to avoid possible races if the server reuses the inode. 1191*1da177e4SLinus Torvalds */ 1192*1da177e4SLinus Torvalds static int nfs_safe_remove(struct dentry *dentry) 1193*1da177e4SLinus Torvalds { 1194*1da177e4SLinus Torvalds struct inode *dir = dentry->d_parent->d_inode; 1195*1da177e4SLinus Torvalds struct inode *inode = dentry->d_inode; 1196*1da177e4SLinus Torvalds int error = -EBUSY; 1197*1da177e4SLinus Torvalds 1198*1da177e4SLinus Torvalds dfprintk(VFS, "NFS: safe_remove(%s/%s)\n", 1199*1da177e4SLinus Torvalds dentry->d_parent->d_name.name, dentry->d_name.name); 1200*1da177e4SLinus Torvalds 1201*1da177e4SLinus Torvalds /* If the dentry was sillyrenamed, we simply call d_delete() */ 1202*1da177e4SLinus Torvalds if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { 1203*1da177e4SLinus Torvalds error = 0; 1204*1da177e4SLinus Torvalds goto out; 1205*1da177e4SLinus Torvalds } 1206*1da177e4SLinus Torvalds 1207*1da177e4SLinus Torvalds nfs_begin_data_update(dir); 1208*1da177e4SLinus Torvalds if (inode != NULL) { 1209*1da177e4SLinus Torvalds nfs_begin_data_update(inode); 1210*1da177e4SLinus Torvalds error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); 1211*1da177e4SLinus Torvalds /* The VFS may want to delete this inode */ 1212*1da177e4SLinus Torvalds if (error == 0) 1213*1da177e4SLinus Torvalds inode->i_nlink--; 1214*1da177e4SLinus Torvalds nfs_end_data_update(inode); 1215*1da177e4SLinus Torvalds } else 1216*1da177e4SLinus Torvalds error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); 1217*1da177e4SLinus Torvalds nfs_end_data_update(dir); 1218*1da177e4SLinus Torvalds out: 1219*1da177e4SLinus Torvalds return error; 1220*1da177e4SLinus Torvalds } 1221*1da177e4SLinus Torvalds 1222*1da177e4SLinus Torvalds /* We do silly rename. In case sillyrename() returns -EBUSY, the inode 1223*1da177e4SLinus Torvalds * belongs to an active ".nfs..." file and we return -EBUSY. 1224*1da177e4SLinus Torvalds * 1225*1da177e4SLinus Torvalds * If sillyrename() returns 0, we do nothing, otherwise we unlink. 1226*1da177e4SLinus Torvalds */ 1227*1da177e4SLinus Torvalds static int nfs_unlink(struct inode *dir, struct dentry *dentry) 1228*1da177e4SLinus Torvalds { 1229*1da177e4SLinus Torvalds int error; 1230*1da177e4SLinus Torvalds int need_rehash = 0; 1231*1da177e4SLinus Torvalds 1232*1da177e4SLinus Torvalds dfprintk(VFS, "NFS: unlink(%s/%ld, %s)\n", dir->i_sb->s_id, 1233*1da177e4SLinus Torvalds dir->i_ino, dentry->d_name.name); 1234*1da177e4SLinus Torvalds 1235*1da177e4SLinus Torvalds lock_kernel(); 1236*1da177e4SLinus Torvalds spin_lock(&dcache_lock); 1237*1da177e4SLinus Torvalds spin_lock(&dentry->d_lock); 1238*1da177e4SLinus Torvalds if (atomic_read(&dentry->d_count) > 1) { 1239*1da177e4SLinus Torvalds spin_unlock(&dentry->d_lock); 1240*1da177e4SLinus Torvalds spin_unlock(&dcache_lock); 1241*1da177e4SLinus Torvalds error = nfs_sillyrename(dir, dentry); 1242*1da177e4SLinus Torvalds unlock_kernel(); 1243*1da177e4SLinus Torvalds return error; 1244*1da177e4SLinus Torvalds } 1245*1da177e4SLinus Torvalds if (!d_unhashed(dentry)) { 1246*1da177e4SLinus Torvalds __d_drop(dentry); 1247*1da177e4SLinus Torvalds need_rehash = 1; 1248*1da177e4SLinus Torvalds } 1249*1da177e4SLinus Torvalds spin_unlock(&dentry->d_lock); 1250*1da177e4SLinus Torvalds spin_unlock(&dcache_lock); 1251*1da177e4SLinus Torvalds error = nfs_safe_remove(dentry); 1252*1da177e4SLinus Torvalds if (!error) { 1253*1da177e4SLinus Torvalds nfs_renew_times(dentry); 1254*1da177e4SLinus Torvalds nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); 1255*1da177e4SLinus Torvalds } else if (need_rehash) 1256*1da177e4SLinus Torvalds d_rehash(dentry); 1257*1da177e4SLinus Torvalds unlock_kernel(); 1258*1da177e4SLinus Torvalds return error; 1259*1da177e4SLinus Torvalds } 1260*1da177e4SLinus Torvalds 1261*1da177e4SLinus Torvalds static int 1262*1da177e4SLinus Torvalds nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) 1263*1da177e4SLinus Torvalds { 1264*1da177e4SLinus Torvalds struct iattr attr; 1265*1da177e4SLinus Torvalds struct nfs_fattr sym_attr; 1266*1da177e4SLinus Torvalds struct nfs_fh sym_fh; 1267*1da177e4SLinus Torvalds struct qstr qsymname; 1268*1da177e4SLinus Torvalds int error; 1269*1da177e4SLinus Torvalds 1270*1da177e4SLinus Torvalds dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s)\n", dir->i_sb->s_id, 1271*1da177e4SLinus Torvalds dir->i_ino, dentry->d_name.name, symname); 1272*1da177e4SLinus Torvalds 1273*1da177e4SLinus Torvalds #ifdef NFS_PARANOIA 1274*1da177e4SLinus Torvalds if (dentry->d_inode) 1275*1da177e4SLinus Torvalds printk("nfs_proc_symlink: %s/%s not negative!\n", 1276*1da177e4SLinus Torvalds dentry->d_parent->d_name.name, dentry->d_name.name); 1277*1da177e4SLinus Torvalds #endif 1278*1da177e4SLinus Torvalds /* 1279*1da177e4SLinus Torvalds * Fill in the sattr for the call. 1280*1da177e4SLinus Torvalds * Note: SunOS 4.1.2 crashes if the mode isn't initialized! 1281*1da177e4SLinus Torvalds */ 1282*1da177e4SLinus Torvalds attr.ia_valid = ATTR_MODE; 1283*1da177e4SLinus Torvalds attr.ia_mode = S_IFLNK | S_IRWXUGO; 1284*1da177e4SLinus Torvalds 1285*1da177e4SLinus Torvalds qsymname.name = symname; 1286*1da177e4SLinus Torvalds qsymname.len = strlen(symname); 1287*1da177e4SLinus Torvalds 1288*1da177e4SLinus Torvalds lock_kernel(); 1289*1da177e4SLinus Torvalds nfs_begin_data_update(dir); 1290*1da177e4SLinus Torvalds error = NFS_PROTO(dir)->symlink(dir, &dentry->d_name, &qsymname, 1291*1da177e4SLinus Torvalds &attr, &sym_fh, &sym_attr); 1292*1da177e4SLinus Torvalds nfs_end_data_update(dir); 1293*1da177e4SLinus Torvalds if (!error) { 1294*1da177e4SLinus Torvalds error = nfs_instantiate(dentry, &sym_fh, &sym_attr); 1295*1da177e4SLinus Torvalds } else { 1296*1da177e4SLinus Torvalds if (error == -EEXIST) 1297*1da177e4SLinus Torvalds printk("nfs_proc_symlink: %s/%s already exists??\n", 1298*1da177e4SLinus Torvalds dentry->d_parent->d_name.name, dentry->d_name.name); 1299*1da177e4SLinus Torvalds d_drop(dentry); 1300*1da177e4SLinus Torvalds } 1301*1da177e4SLinus Torvalds unlock_kernel(); 1302*1da177e4SLinus Torvalds return error; 1303*1da177e4SLinus Torvalds } 1304*1da177e4SLinus Torvalds 1305*1da177e4SLinus Torvalds static int 1306*1da177e4SLinus Torvalds nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) 1307*1da177e4SLinus Torvalds { 1308*1da177e4SLinus Torvalds struct inode *inode = old_dentry->d_inode; 1309*1da177e4SLinus Torvalds int error; 1310*1da177e4SLinus Torvalds 1311*1da177e4SLinus Torvalds dfprintk(VFS, "NFS: link(%s/%s -> %s/%s)\n", 1312*1da177e4SLinus Torvalds old_dentry->d_parent->d_name.name, old_dentry->d_name.name, 1313*1da177e4SLinus Torvalds dentry->d_parent->d_name.name, dentry->d_name.name); 1314*1da177e4SLinus Torvalds 1315*1da177e4SLinus Torvalds /* 1316*1da177e4SLinus Torvalds * Drop the dentry in advance to force a new lookup. 1317*1da177e4SLinus Torvalds * Since nfs_proc_link doesn't return a file handle, 1318*1da177e4SLinus Torvalds * we can't use the existing dentry. 1319*1da177e4SLinus Torvalds */ 1320*1da177e4SLinus Torvalds lock_kernel(); 1321*1da177e4SLinus Torvalds d_drop(dentry); 1322*1da177e4SLinus Torvalds 1323*1da177e4SLinus Torvalds nfs_begin_data_update(dir); 1324*1da177e4SLinus Torvalds nfs_begin_data_update(inode); 1325*1da177e4SLinus Torvalds error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name); 1326*1da177e4SLinus Torvalds nfs_end_data_update(inode); 1327*1da177e4SLinus Torvalds nfs_end_data_update(dir); 1328*1da177e4SLinus Torvalds unlock_kernel(); 1329*1da177e4SLinus Torvalds return error; 1330*1da177e4SLinus Torvalds } 1331*1da177e4SLinus Torvalds 1332*1da177e4SLinus Torvalds /* 1333*1da177e4SLinus Torvalds * RENAME 1334*1da177e4SLinus Torvalds * FIXME: Some nfsds, like the Linux user space nfsd, may generate a 1335*1da177e4SLinus Torvalds * different file handle for the same inode after a rename (e.g. when 1336*1da177e4SLinus Torvalds * moving to a different directory). A fail-safe method to do so would 1337*1da177e4SLinus Torvalds * be to look up old_dir/old_name, create a link to new_dir/new_name and 1338*1da177e4SLinus Torvalds * rename the old file using the sillyrename stuff. This way, the original 1339*1da177e4SLinus Torvalds * file in old_dir will go away when the last process iput()s the inode. 1340*1da177e4SLinus Torvalds * 1341*1da177e4SLinus Torvalds * FIXED. 1342*1da177e4SLinus Torvalds * 1343*1da177e4SLinus Torvalds * It actually works quite well. One needs to have the possibility for 1344*1da177e4SLinus Torvalds * at least one ".nfs..." file in each directory the file ever gets 1345*1da177e4SLinus Torvalds * moved or linked to which happens automagically with the new 1346*1da177e4SLinus Torvalds * implementation that only depends on the dcache stuff instead of 1347*1da177e4SLinus Torvalds * using the inode layer 1348*1da177e4SLinus Torvalds * 1349*1da177e4SLinus Torvalds * Unfortunately, things are a little more complicated than indicated 1350*1da177e4SLinus Torvalds * above. For a cross-directory move, we want to make sure we can get 1351*1da177e4SLinus Torvalds * rid of the old inode after the operation. This means there must be 1352*1da177e4SLinus Torvalds * no pending writes (if it's a file), and the use count must be 1. 1353*1da177e4SLinus Torvalds * If these conditions are met, we can drop the dentries before doing 1354*1da177e4SLinus Torvalds * the rename. 1355*1da177e4SLinus Torvalds */ 1356*1da177e4SLinus Torvalds static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, 1357*1da177e4SLinus Torvalds struct inode *new_dir, struct dentry *new_dentry) 1358*1da177e4SLinus Torvalds { 1359*1da177e4SLinus Torvalds struct inode *old_inode = old_dentry->d_inode; 1360*1da177e4SLinus Torvalds struct inode *new_inode = new_dentry->d_inode; 1361*1da177e4SLinus Torvalds struct dentry *dentry = NULL, *rehash = NULL; 1362*1da177e4SLinus Torvalds int error = -EBUSY; 1363*1da177e4SLinus Torvalds 1364*1da177e4SLinus Torvalds /* 1365*1da177e4SLinus Torvalds * To prevent any new references to the target during the rename, 1366*1da177e4SLinus Torvalds * we unhash the dentry and free the inode in advance. 1367*1da177e4SLinus Torvalds */ 1368*1da177e4SLinus Torvalds lock_kernel(); 1369*1da177e4SLinus Torvalds if (!d_unhashed(new_dentry)) { 1370*1da177e4SLinus Torvalds d_drop(new_dentry); 1371*1da177e4SLinus Torvalds rehash = new_dentry; 1372*1da177e4SLinus Torvalds } 1373*1da177e4SLinus Torvalds 1374*1da177e4SLinus Torvalds dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n", 1375*1da177e4SLinus Torvalds old_dentry->d_parent->d_name.name, old_dentry->d_name.name, 1376*1da177e4SLinus Torvalds new_dentry->d_parent->d_name.name, new_dentry->d_name.name, 1377*1da177e4SLinus Torvalds atomic_read(&new_dentry->d_count)); 1378*1da177e4SLinus Torvalds 1379*1da177e4SLinus Torvalds /* 1380*1da177e4SLinus Torvalds * First check whether the target is busy ... we can't 1381*1da177e4SLinus Torvalds * safely do _any_ rename if the target is in use. 1382*1da177e4SLinus Torvalds * 1383*1da177e4SLinus Torvalds * For files, make a copy of the dentry and then do a 1384*1da177e4SLinus Torvalds * silly-rename. If the silly-rename succeeds, the 1385*1da177e4SLinus Torvalds * copied dentry is hashed and becomes the new target. 1386*1da177e4SLinus Torvalds */ 1387*1da177e4SLinus Torvalds if (!new_inode) 1388*1da177e4SLinus Torvalds goto go_ahead; 1389*1da177e4SLinus Torvalds if (S_ISDIR(new_inode->i_mode)) 1390*1da177e4SLinus Torvalds goto out; 1391*1da177e4SLinus Torvalds else if (atomic_read(&new_dentry->d_count) > 2) { 1392*1da177e4SLinus Torvalds int err; 1393*1da177e4SLinus Torvalds /* copy the target dentry's name */ 1394*1da177e4SLinus Torvalds dentry = d_alloc(new_dentry->d_parent, 1395*1da177e4SLinus Torvalds &new_dentry->d_name); 1396*1da177e4SLinus Torvalds if (!dentry) 1397*1da177e4SLinus Torvalds goto out; 1398*1da177e4SLinus Torvalds 1399*1da177e4SLinus Torvalds /* silly-rename the existing target ... */ 1400*1da177e4SLinus Torvalds err = nfs_sillyrename(new_dir, new_dentry); 1401*1da177e4SLinus Torvalds if (!err) { 1402*1da177e4SLinus Torvalds new_dentry = rehash = dentry; 1403*1da177e4SLinus Torvalds new_inode = NULL; 1404*1da177e4SLinus Torvalds /* instantiate the replacement target */ 1405*1da177e4SLinus Torvalds d_instantiate(new_dentry, NULL); 1406*1da177e4SLinus Torvalds } else if (atomic_read(&new_dentry->d_count) > 1) { 1407*1da177e4SLinus Torvalds /* dentry still busy? */ 1408*1da177e4SLinus Torvalds #ifdef NFS_PARANOIA 1409*1da177e4SLinus Torvalds printk("nfs_rename: target %s/%s busy, d_count=%d\n", 1410*1da177e4SLinus Torvalds new_dentry->d_parent->d_name.name, 1411*1da177e4SLinus Torvalds new_dentry->d_name.name, 1412*1da177e4SLinus Torvalds atomic_read(&new_dentry->d_count)); 1413*1da177e4SLinus Torvalds #endif 1414*1da177e4SLinus Torvalds goto out; 1415*1da177e4SLinus Torvalds } 1416*1da177e4SLinus Torvalds } 1417*1da177e4SLinus Torvalds 1418*1da177e4SLinus Torvalds go_ahead: 1419*1da177e4SLinus Torvalds /* 1420*1da177e4SLinus Torvalds * ... prune child dentries and writebacks if needed. 1421*1da177e4SLinus Torvalds */ 1422*1da177e4SLinus Torvalds if (atomic_read(&old_dentry->d_count) > 1) { 1423*1da177e4SLinus Torvalds nfs_wb_all(old_inode); 1424*1da177e4SLinus Torvalds shrink_dcache_parent(old_dentry); 1425*1da177e4SLinus Torvalds } 1426*1da177e4SLinus Torvalds 1427*1da177e4SLinus Torvalds if (new_inode) 1428*1da177e4SLinus Torvalds d_delete(new_dentry); 1429*1da177e4SLinus Torvalds 1430*1da177e4SLinus Torvalds nfs_begin_data_update(old_dir); 1431*1da177e4SLinus Torvalds nfs_begin_data_update(new_dir); 1432*1da177e4SLinus Torvalds nfs_begin_data_update(old_inode); 1433*1da177e4SLinus Torvalds error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name, 1434*1da177e4SLinus Torvalds new_dir, &new_dentry->d_name); 1435*1da177e4SLinus Torvalds nfs_end_data_update(old_inode); 1436*1da177e4SLinus Torvalds nfs_end_data_update(new_dir); 1437*1da177e4SLinus Torvalds nfs_end_data_update(old_dir); 1438*1da177e4SLinus Torvalds out: 1439*1da177e4SLinus Torvalds if (rehash) 1440*1da177e4SLinus Torvalds d_rehash(rehash); 1441*1da177e4SLinus Torvalds if (!error) { 1442*1da177e4SLinus Torvalds if (!S_ISDIR(old_inode->i_mode)) 1443*1da177e4SLinus Torvalds d_move(old_dentry, new_dentry); 1444*1da177e4SLinus Torvalds nfs_renew_times(new_dentry); 1445*1da177e4SLinus Torvalds nfs_set_verifier(new_dentry, nfs_save_change_attribute(new_dir)); 1446*1da177e4SLinus Torvalds } 1447*1da177e4SLinus Torvalds 1448*1da177e4SLinus Torvalds /* new dentry created? */ 1449*1da177e4SLinus Torvalds if (dentry) 1450*1da177e4SLinus Torvalds dput(dentry); 1451*1da177e4SLinus Torvalds unlock_kernel(); 1452*1da177e4SLinus Torvalds return error; 1453*1da177e4SLinus Torvalds } 1454*1da177e4SLinus Torvalds 1455*1da177e4SLinus Torvalds int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs_access_entry *res) 1456*1da177e4SLinus Torvalds { 1457*1da177e4SLinus Torvalds struct nfs_access_entry *cache = &NFS_I(inode)->cache_access; 1458*1da177e4SLinus Torvalds 1459*1da177e4SLinus Torvalds if (cache->cred != cred 1460*1da177e4SLinus Torvalds || time_after(jiffies, cache->jiffies + NFS_ATTRTIMEO(inode)) 1461*1da177e4SLinus Torvalds || (NFS_FLAGS(inode) & NFS_INO_INVALID_ACCESS)) 1462*1da177e4SLinus Torvalds return -ENOENT; 1463*1da177e4SLinus Torvalds memcpy(res, cache, sizeof(*res)); 1464*1da177e4SLinus Torvalds return 0; 1465*1da177e4SLinus Torvalds } 1466*1da177e4SLinus Torvalds 1467*1da177e4SLinus Torvalds void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set) 1468*1da177e4SLinus Torvalds { 1469*1da177e4SLinus Torvalds struct nfs_access_entry *cache = &NFS_I(inode)->cache_access; 1470*1da177e4SLinus Torvalds 1471*1da177e4SLinus Torvalds if (cache->cred != set->cred) { 1472*1da177e4SLinus Torvalds if (cache->cred) 1473*1da177e4SLinus Torvalds put_rpccred(cache->cred); 1474*1da177e4SLinus Torvalds cache->cred = get_rpccred(set->cred); 1475*1da177e4SLinus Torvalds } 1476*1da177e4SLinus Torvalds NFS_FLAGS(inode) &= ~NFS_INO_INVALID_ACCESS; 1477*1da177e4SLinus Torvalds cache->jiffies = set->jiffies; 1478*1da177e4SLinus Torvalds cache->mask = set->mask; 1479*1da177e4SLinus Torvalds } 1480*1da177e4SLinus Torvalds 1481*1da177e4SLinus Torvalds static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask) 1482*1da177e4SLinus Torvalds { 1483*1da177e4SLinus Torvalds struct nfs_access_entry cache; 1484*1da177e4SLinus Torvalds int status; 1485*1da177e4SLinus Torvalds 1486*1da177e4SLinus Torvalds status = nfs_access_get_cached(inode, cred, &cache); 1487*1da177e4SLinus Torvalds if (status == 0) 1488*1da177e4SLinus Torvalds goto out; 1489*1da177e4SLinus Torvalds 1490*1da177e4SLinus Torvalds /* Be clever: ask server to check for all possible rights */ 1491*1da177e4SLinus Torvalds cache.mask = MAY_EXEC | MAY_WRITE | MAY_READ; 1492*1da177e4SLinus Torvalds cache.cred = cred; 1493*1da177e4SLinus Torvalds cache.jiffies = jiffies; 1494*1da177e4SLinus Torvalds status = NFS_PROTO(inode)->access(inode, &cache); 1495*1da177e4SLinus Torvalds if (status != 0) 1496*1da177e4SLinus Torvalds return status; 1497*1da177e4SLinus Torvalds nfs_access_add_cache(inode, &cache); 1498*1da177e4SLinus Torvalds out: 1499*1da177e4SLinus Torvalds if ((cache.mask & mask) == mask) 1500*1da177e4SLinus Torvalds return 0; 1501*1da177e4SLinus Torvalds return -EACCES; 1502*1da177e4SLinus Torvalds } 1503*1da177e4SLinus Torvalds 1504*1da177e4SLinus Torvalds int nfs_permission(struct inode *inode, int mask, struct nameidata *nd) 1505*1da177e4SLinus Torvalds { 1506*1da177e4SLinus Torvalds struct rpc_cred *cred; 1507*1da177e4SLinus Torvalds int res = 0; 1508*1da177e4SLinus Torvalds 1509*1da177e4SLinus Torvalds if (mask == 0) 1510*1da177e4SLinus Torvalds goto out; 1511*1da177e4SLinus Torvalds /* Is this sys_access() ? */ 1512*1da177e4SLinus Torvalds if (nd != NULL && (nd->flags & LOOKUP_ACCESS)) 1513*1da177e4SLinus Torvalds goto force_lookup; 1514*1da177e4SLinus Torvalds 1515*1da177e4SLinus Torvalds switch (inode->i_mode & S_IFMT) { 1516*1da177e4SLinus Torvalds case S_IFLNK: 1517*1da177e4SLinus Torvalds goto out; 1518*1da177e4SLinus Torvalds case S_IFREG: 1519*1da177e4SLinus Torvalds /* NFSv4 has atomic_open... */ 1520*1da177e4SLinus Torvalds if (nfs_server_capable(inode, NFS_CAP_ATOMIC_OPEN) 1521*1da177e4SLinus Torvalds && nd != NULL 1522*1da177e4SLinus Torvalds && (nd->flags & LOOKUP_OPEN)) 1523*1da177e4SLinus Torvalds goto out; 1524*1da177e4SLinus Torvalds break; 1525*1da177e4SLinus Torvalds case S_IFDIR: 1526*1da177e4SLinus Torvalds /* 1527*1da177e4SLinus Torvalds * Optimize away all write operations, since the server 1528*1da177e4SLinus Torvalds * will check permissions when we perform the op. 1529*1da177e4SLinus Torvalds */ 1530*1da177e4SLinus Torvalds if ((mask & MAY_WRITE) && !(mask & MAY_READ)) 1531*1da177e4SLinus Torvalds goto out; 1532*1da177e4SLinus Torvalds } 1533*1da177e4SLinus Torvalds 1534*1da177e4SLinus Torvalds force_lookup: 1535*1da177e4SLinus Torvalds lock_kernel(); 1536*1da177e4SLinus Torvalds 1537*1da177e4SLinus Torvalds if (!NFS_PROTO(inode)->access) 1538*1da177e4SLinus Torvalds goto out_notsup; 1539*1da177e4SLinus Torvalds 1540*1da177e4SLinus Torvalds cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0); 1541*1da177e4SLinus Torvalds if (!IS_ERR(cred)) { 1542*1da177e4SLinus Torvalds res = nfs_do_access(inode, cred, mask); 1543*1da177e4SLinus Torvalds put_rpccred(cred); 1544*1da177e4SLinus Torvalds } else 1545*1da177e4SLinus Torvalds res = PTR_ERR(cred); 1546*1da177e4SLinus Torvalds unlock_kernel(); 1547*1da177e4SLinus Torvalds out: 1548*1da177e4SLinus Torvalds return res; 1549*1da177e4SLinus Torvalds out_notsup: 1550*1da177e4SLinus Torvalds res = nfs_revalidate_inode(NFS_SERVER(inode), inode); 1551*1da177e4SLinus Torvalds if (res == 0) 1552*1da177e4SLinus Torvalds res = generic_permission(inode, mask, NULL); 1553*1da177e4SLinus Torvalds unlock_kernel(); 1554*1da177e4SLinus Torvalds return res; 1555*1da177e4SLinus Torvalds } 1556*1da177e4SLinus Torvalds 1557*1da177e4SLinus Torvalds /* 1558*1da177e4SLinus Torvalds * Local variables: 1559*1da177e4SLinus Torvalds * version-control: t 1560*1da177e4SLinus Torvalds * kept-new-versions: 5 1561*1da177e4SLinus Torvalds * End: 1562*1da177e4SLinus Torvalds */ 1563