/* We do silly rename. In case sillyrename() returns -EBUSY, the inode * belongs to an active ".nfs..." file and we return -EBUSY. * * If sillyrename() returns 0, we do nothing, otherwise we unlink. */ static int nfs_unlink(struct inode *dir, struct dentry *dentry) { int error; int need_rehash = 0; dfprintk(VFS, "NFS: unlink(%s/%ld, %s)\n", dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); lock_kernel(); spin_lock(&dcache_lock); spin_lock(&dentry->d_lock); if (atomic_read(&dentry->d_count) > 1) { spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); error = nfs_sillyrename(dir, dentry); unlock_kernel(); return error; } if (!d_unhashed(dentry)) { __d_drop(dentry); need_rehash = 1; } spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); error = nfs_safe_remove(dentry); if (!error) { nfs_renew_times(dentry); nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); } else if (need_rehash) d_rehash(dentry); unlock_kernel(); return error; }
/* * Remove a file after making sure there are no pending writes, * and after checking that the file has only one user. * * We invalidate the attribute cache and free the inode prior to the operation * to avoid possible races if the server reuses the inode. */ static int nfs_safe_remove(struct dentry *dentry) { struct inode *dir = dentry->d_parent->d_inode; struct inode *inode = dentry->d_inode; int error = -EBUSY; dfprintk(VFS, "NFS: safe_remove(%s/%s)\n", dentry->d_parent->d_name.name, dentry->d_name.name); /* If the dentry was sillyrenamed, we simply call d_delete() */ if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { error = 0; goto out; } nfs_begin_data_update(dir); if (inode != NULL) { nfs_begin_data_update(inode); error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); /* The VFS may want to delete this inode */ if (error == 0) inode->i_nlink--; nfs_end_data_update(inode); } else error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); nfs_end_data_update(dir); out: return error; }
/* * Attempt to release the private state associated with a page * - Called if either PG_private or PG_fscache is set on the page * - Caller holds page lock * - Return true (may release page) or false (may not) */ static int nfs_release_page(struct page *page, gfp_t gfp) { struct address_space *mapping = page->mapping; dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); /* Always try to initiate a 'commit' if relevant, but only * wait for it if __GFP_WAIT is set. Even then, only wait 1 * second and only if the 'bdi' is not congested. * Waiting indefinitely can cause deadlocks when the NFS * server is on this machine, when a new TCP connection is * needed and in other rare cases. There is no particular * need to wait extensively here. A short wait has the * benefit that someone else can worry about the freezer. */ if (mapping) { struct nfs_server *nfss = NFS_SERVER(mapping->host); nfs_commit_inode(mapping->host, 0); if ((gfp & __GFP_WAIT) && !bdi_write_congested(&nfss->backing_dev_info)) { wait_on_page_bit_killable_timeout(page, PG_private, HZ); if (PagePrivate(page)) set_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC); } } /* If PagePrivate() is set, then the page is not freeable */ if (PagePrivate(page)) return 0; return nfs_fscache_release_page(page, gfp); }
/* * See comments for nfs_proc_create regarding failed operations. */ static int nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) { struct iattr attr; struct nfs_fattr fattr; struct nfs_fh fhandle; int error; dfprintk(VFS, "NFS: mknod(%s/%ld, %s\n", dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); if (!new_valid_dev(rdev)) return -EINVAL; attr.ia_mode = mode; attr.ia_valid = ATTR_MODE; lock_kernel(); nfs_begin_data_update(dir); error = NFS_PROTO(dir)->mknod(dir, &dentry->d_name, &attr, rdev, &fhandle, &fattr); nfs_end_data_update(dir); if (!error) error = nfs_instantiate(dentry, &fhandle, &fattr); else d_drop(dentry); unlock_kernel(); return error; }
/* * See comments for nfs_proc_create regarding failed operations. */ static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) { struct iattr attr; struct nfs_fattr fattr; struct nfs_fh fhandle; int error; dfprintk(VFS, "NFS: mkdir(%s/%ld, %s\n", dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); attr.ia_valid = ATTR_MODE; attr.ia_mode = mode | S_IFDIR; lock_kernel(); #if 0 /* * Always drop the dentry, we can't always depend on * the fattr returned by the server (AIX seems to be * broken). We're better off doing another lookup than * depending on potentially bogus information. */ d_drop(dentry); #endif nfs_begin_data_update(dir); error = NFS_PROTO(dir)->mkdir(dir, &dentry->d_name, &attr, &fhandle, &fattr); nfs_end_data_update(dir); if (!error) error = nfs_instantiate(dentry, &fhandle, &fattr); else d_drop(dentry); unlock_kernel(); return error; }
static int nfs_release_page(struct page *page, gfp_t gfp) { dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); /* If PagePrivate() is set, then the page is not freeable */ return 0; }
/* * This does the "real" work of the write. We must allocate and lock the * page to be sent back to the generic routine, which then copies the * data from user space. * * If the writer ends up delaying the write, the writer needs to * increment the page use counts until he is done with the page. */ static int nfs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { int ret; pgoff_t index; struct page *page; index = pos >> PAGE_CACHE_SHIFT; dfprintk(PAGECACHE, "NFS: write_begin(%s/%s(%ld), %u@%lld)\n", file->f_path.dentry->d_parent->d_name.name, file->f_path.dentry->d_name.name, mapping->host->i_ino, len, (long long) pos); /* * Prevent starvation issues if someone is doing a consistency * sync-to-disk */ ret = wait_on_bit(&NFS_I(mapping->host)->flags, NFS_INO_FLUSHING, nfs_wait_bit_killable, TASK_KILLABLE); if (ret) return ret; page = grab_cache_page_write_begin(mapping, index, flags); if (!page) return -ENOMEM; *pagep = page; ret = nfs_flush_incompatible(file, page); if (ret) { unlock_page(page); page_cache_release(page); } return ret; }
/* * This does the "real" work of the write. We must allocate and lock the * page to be sent back to the generic routine, which then copies the * data from user space. * * If the writer ends up delaying the write, the writer needs to * increment the page use counts until he is done with the page. */ static int nfs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { int ret; pgoff_t index; struct page *page; index = pos >> PAGE_CACHE_SHIFT; dfprintk(PAGECACHE, "NFS: write_begin(%s/%s(%ld), %u@%lld)\n", file->f_path.dentry->d_parent->d_name.name, file->f_path.dentry->d_name.name, mapping->host->i_ino, len, (long long) pos); page = grab_cache_page_write_begin(mapping, index, flags); if (!page) return -ENOMEM; *pagep = page; ret = nfs_flush_incompatible(file, page); if (ret) { unlock_page(page); page_cache_release(page); } return ret; }
/* * Write to a file (through the page cache). */ static ssize_t nfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { struct dentry * dentry = file->f_dentry; struct inode * inode = dentry->d_inode; ssize_t result; dfprintk(VFS, "nfs: write(%s/%s(%ld), %lu@%lu)\n", dentry->d_parent->d_name.name, dentry->d_name.name, inode->i_ino, (unsigned long) count, (unsigned long) *ppos); result = -EBUSY; if (IS_SWAPFILE(inode)) goto out_swapfile; result = nfs_revalidate_inode(NFS_DSERVER(dentry), dentry); if (result) goto out; result = count; if (!count) goto out; result = generic_file_write(file, buf, count, ppos); out: return result; out_swapfile: printk(KERN_INFO "NFS: attempt to write to active swap file!\n"); goto out; }
static int nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { struct inode *inode = old_dentry->d_inode; int error; dfprintk(VFS, "NFS: link(%s/%s -> %s/%s)\n", old_dentry->d_parent->d_name.name, old_dentry->d_name.name, dentry->d_parent->d_name.name, dentry->d_name.name); /* * Drop the dentry in advance to force a new lookup. * Since nfs_proc_link doesn't return a file handle, * we can't use the existing dentry. */ lock_kernel(); d_drop(dentry); nfs_begin_data_update(dir); nfs_begin_data_update(inode); error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name); nfs_end_data_update(inode); nfs_end_data_update(dir); unlock_kernel(); return error; }
/* * This is called every time the dcache has a lookup hit, * and we should check whether we can really trust that * lookup. * * NOTE! The hit can be a negative hit too, don't assume * we have an inode! * * If the parent directory is seen to have changed, we throw out the * cached dentry and do a new lookup. */ static int nfs_lookup_revalidate(struct dentry * dentry, int flags) { struct inode *dir; struct inode *inode; int error; struct nfs_fh fhandle; struct nfs_fattr fattr; lock_kernel(); dir = dentry->d_parent->d_inode; inode = dentry->d_inode; if (!inode) { if (nfs_neg_need_reval(dir, dentry)) goto out_bad; goto out_valid; } if (is_bad_inode(inode)) { dfprintk(VFS, "nfs_lookup_validate: %s/%s has dud inode\n", dentry->d_parent->d_name.name, dentry->d_name.name); goto out_bad; } /* Force a full look up iff the parent directory has changed */ if (nfs_check_verifier(dir, dentry)) { if (nfs_lookup_verify_inode(inode, flags)) goto out_bad; goto out_valid; } if (NFS_STALE(inode)) goto out_bad; error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); if (error) goto out_bad; if (memcmp(NFS_FH(inode), &fhandle, sizeof(struct nfs_fh))!= 0) goto out_bad; if ((error = nfs_refresh_inode(inode, &fattr)) != 0) goto out_bad; nfs_renew_times(dentry); out_valid: unlock_kernel(); return 1; out_bad: NFS_CACHEINV(dir); if (inode && S_ISDIR(inode->i_mode)) { /* Purge readdir caches. */ nfs_zap_caches(inode); /* If we have submounts, don't unhash ! */ if (have_submounts(dentry)) goto out_valid; shrink_dcache_parent(dentry); } d_drop(dentry); unlock_kernel(); return 0; }
/* * Following a failed create operation, we drop the dentry rather * than retain a negative dentry. This avoids a problem in the event * that the operation succeeded on the server, but an error in the * reply path made it appear to have failed. */ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode) { struct iattr attr; struct nfs_fattr fattr; struct nfs_fh fhandle; int error; dfprintk(VFS, "NFS: create(%x/%ld, %s\n", dir->i_dev, dir->i_ino, dentry->d_name.name); attr.ia_mode = mode; attr.ia_valid = ATTR_MODE; /* * The 0 argument passed into the create function should one day * contain the O_EXCL flag if requested. This allows NFSv3 to * select the appropriate create strategy. Currently open_namei * does not pass the create flags. */ nfs_zap_caches(dir); error = NFS_PROTO(dir)->create(dir, &dentry->d_name, &attr, 0, &fhandle, &fattr); if (!error) error = nfs_instantiate(dentry, &fhandle, &fattr); else d_drop(dentry); return error; }
static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) { struct page *page = vmf->page; struct file *filp = vma->vm_file; struct dentry *dentry = filp->f_path.dentry; unsigned pagelen; int ret = -EINVAL; struct address_space *mapping; dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%s/%s(%ld), offset %lld)\n", dentry->d_parent->d_name.name, dentry->d_name.name, filp->f_mapping->host->i_ino, (long long)page_offset(page)); lock_page(page); mapping = page->mapping; if (mapping != dentry->d_inode->i_mapping) goto out_unlock; ret = 0; pagelen = nfs_page_length(page); if (pagelen == 0) goto out_unlock; ret = nfs_flush_incompatible(filp, page); if (ret != 0) goto out_unlock; ret = nfs_updatepage(filp, page, 0, pagelen); out_unlock: if (!ret) return VM_FAULT_LOCKED; unlock_page(page); return VM_FAULT_SIGBUS; }
static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry) { struct inode *inode; int error; struct nfs_fh fhandle; struct nfs_fattr fattr; dfprintk(VFS, "NFS: lookup(%s/%s)\n", dentry->d_parent->d_name.name, dentry->d_name.name); error = -ENAMETOOLONG; if (dentry->d_name.len > NFS_SERVER(dir)->namelen) goto out; error = -ENOMEM; dentry->d_op = &nfs_dentry_operations; error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); inode = NULL; if (error == -ENOENT) goto no_entry; if (!error) { error = -EACCES; inode = nfs_fhget(dentry, &fhandle, &fattr); if (inode) { no_entry: d_add(dentry, inode); error = 0; } nfs_renew_times(dentry); } out: return ERR_PTR(error); }
/* * Dispose of a per-client cookie */ void nfs_fscache_release_client_cookie(struct nfs_client *clp) { dfprintk(FSCACHE, "NFS: releasing client cookie (0x%p/0x%p)\n", clp, clp->fscache); fscache_relinquish_cookie(clp->fscache, 0); clp->fscache = NULL; }
/* * If we cannot find a cookie in our cache, we suspect that this is * because it points to a deleted file, so we ask the server to return * whatever it thinks is the next entry. We then feed this to filldir. * If all goes well, we should then be able to find our way round the * cache on the next call to readdir_search_pagecache(); * * NOTE: we cannot add the anonymous page to the pagecache because * the data it contains might not be page aligned. Besides, * we should already have a complete representation of the * directory in the page cache by the time we get here. */ static inline int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, filldir_t filldir) { struct file *file = desc->file; struct inode *inode = file->f_dentry->d_inode; struct rpc_cred *cred = nfs_file_cred(file); struct page *page = NULL; int status; dfprintk(VFS, "NFS: uncached_readdir() searching for cookie %Lu\n", (long long)desc->target); page = alloc_page(GFP_HIGHUSER); if (!page) { status = -ENOMEM; goto out; } desc->error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, desc->target, page, NFS_SERVER(inode)->dtsize, desc->plus); NFS_FLAGS(inode) |= NFS_INO_INVALID_ATIME; desc->page = page; desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */ if (desc->error >= 0) { if ((status = dir_decode(desc)) == 0) desc->entry->prev_cookie = desc->target; } else status = -EIO; if (status < 0) goto out_release; status = nfs_do_filldir(desc, dirent, filldir); /* Reset read descriptor so it searches the page cache from * the start upon the next call to readdir_search_pagecache() */ desc->page_index = 0; desc->entry->cookie = desc->entry->prev_cookie = 0; desc->entry->eof = 0; out: dfprintk(VFS, "NFS: uncached_readdir() returns %d\n", status); return status; out_release: dir_page_release(desc); goto out; }
static int nfs_verify_server_address(struct sockaddr *addr) { switch (addr->sa_family) { case AF_INET: { struct sockaddr_in *sa = (struct sockaddr_in *)addr; return sa->sin_addr.s_addr != htonl(INADDR_ANY); } case AF_INET6: { struct in6_addr *sa = &((struct sockaddr_in6 *)addr)->sin6_addr; dfprintk(MOUNT, "zql: nfs_verify_server_address AF_INET6 error\n"); return !ipv6_addr_any(sa); } } dfprintk(MOUNT, "NFS: Invalid IP address specified\n"); return 0; }
/* * Retrieve a set of pages from fscache */ int __nfs_readpages_from_fscache(struct nfs_open_context *ctx, struct inode *inode, struct address_space *mapping, struct list_head *pages, unsigned *nr_pages) { unsigned npages = *nr_pages; int ret; dfprintk(FSCACHE, "NFS: nfs_getpages_from_fscache (0x%p/%u/0x%p)\n", NFS_I(inode)->fscache, npages, inode); ret = fscache_read_or_alloc_pages(NFS_I(inode)->fscache, mapping, pages, nr_pages, nfs_readpage_from_fscache_complete, ctx, mapping_gfp_mask(mapping)); if (*nr_pages < npages) nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_OK, npages); if (*nr_pages > 0) nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_FAIL, *nr_pages); switch (ret) { case 0: /* read submitted to the cache for all pages */ BUG_ON(!list_empty(pages)); BUG_ON(*nr_pages != 0); dfprintk(FSCACHE, "NFS: nfs_getpages_from_fscache: submitted\n"); return ret; case -ENOBUFS: /* some pages aren't cached and can't be */ case -ENODATA: /* some pages aren't cached */ dfprintk(FSCACHE, "NFS: nfs_getpages_from_fscache: no page: %d\n", ret); return 1; default: dfprintk(FSCACHE, "NFS: nfs_getpages_from_fscache: ret %d\n", ret); } return ret; }
static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { struct iattr attr; struct nfs_fattr sym_attr; struct nfs_fh sym_fh; struct qstr qsymname; int error; dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s)\n", dir->i_sb->s_id, dir->i_ino, dentry->d_name.name, symname); error = -ENAMETOOLONG; switch (NFS_PROTO(dir)->version) { case 2: if (strlen(symname) > NFS2_MAXPATHLEN) goto out; break; case 3: if (strlen(symname) > NFS3_MAXPATHLEN) goto out; default: break; } #ifdef NFS_PARANOIA if (dentry->d_inode) printk("nfs_proc_symlink: %s/%s not negative!\n", dentry->d_parent->d_name.name, dentry->d_name.name); #endif /* * Fill in the sattr for the call. * Note: SunOS 4.1.2 crashes if the mode isn't initialized! */ attr.ia_valid = ATTR_MODE; attr.ia_mode = S_IFLNK | S_IRWXUGO; qsymname.name = symname; qsymname.len = strlen(symname); lock_kernel(); nfs_begin_data_update(dir); error = NFS_PROTO(dir)->symlink(dir, &dentry->d_name, &qsymname, &attr, &sym_fh, &sym_attr); nfs_end_data_update(dir); if (!error) { error = nfs_instantiate(dentry, &sym_fh, &sym_attr); } else { if (error == -EEXIST) printk("nfs_proc_symlink: %s/%s already exists??\n", dentry->d_parent->d_name.name, dentry->d_name.name); d_drop(dentry); } unlock_kernel(); out: return error; }
/* * Get the per-client index cookie for an NFS client if the appropriate mount * flag was set * - We always try and get an index cookie for the client, but get filehandle * cookies on a per-superblock basis, depending on the mount flags */ void nfs_fscache_get_client_cookie(struct nfs_client *clp) { /* create a cache index for looking up filehandles */ clp->fscache = fscache_acquire_cookie(nfs_fscache_netfs.primary_index, &nfs_fscache_server_index_def, clp); dfprintk(FSCACHE, "NFS: get client cookie (0x%p/0x%p)\n", clp, clp->fscache); }
static int nfs_launder_page(struct page *page) { struct inode *inode = page->mapping->host; dfprintk(PAGECACHE, "NFS: launder_page(%ld, %llu)\n", inode->i_ino, (long long)page_offset(page)); return nfs_wb_page(inode, page); }
static void nfs_invalidate_page(struct page *page, unsigned long offset) { dfprintk(PAGECACHE, "NFS: invalidate_page(%p, %lu)\n", page, offset); if (offset != 0) return; /* Cancel any unstarted writes on this page */ nfs_wb_page_cancel(page->mapping->host, page); }
static int migrate_nfs_set_client(struct nfs_server *server, const char *hostname, const struct sockaddr *addr, const size_t addrlen, const char *ip_addr, rpc_authflavor_t authflavour, int proto, const struct rpc_timeout *timeparms, u32 minorversion, struct net *net) { struct nfs_client_initdata cl_init = { .hostname = hostname, .addr = addr, .addrlen = addrlen, .nfs_mod = &nfs_v3, .proto = proto, .minorversion = minorversion, .net = net, }; struct nfs_client *clp; int error; dfprintk(MOUNT, "zql: migrate_nfs_set_client\n"); if (server->flags & NFS_MOUNT_NORESVPORT) set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags); //if (server->options & NFS_OPTION_MIGRATION) //set_bit(NFS_CS_MIGRATION, &cl_init.init_flags); clp = nfs_get_client(&cl_init, timeparms, ip_addr, authflavour); if (IS_ERR(clp)) { error = PTR_ERR(clp); dfprintk(MOUNT, "zql: nfs_get_client error\n"); goto error; } set_bit(NFS_CS_CHECK_LEASE_TIME, &clp->cl_res_state); server->nfs_client = clp; dfprintk(MOUNT, "zql: <-- migrate_nfs_set_client() = 0 [new %p]\n", clp); return 0; error: dfprintk(MOUNT, "zql: <-- migrate_nfs_set_client() = xerror %d\n", error); return error; }
/* * Given a pointer to a buffer that has already been filled by a call * to readdir, find the next entry. * * If the end of the buffer has been reached, return -EAGAIN, if not, * return the offset within the buffer of the next entry to be * read. */ static inline int find_dirent(nfs_readdir_descriptor_t *desc, struct page *page) { struct nfs_entry *entry = desc->entry; int loop_count = 0, status; while((status = dir_decode(desc)) == 0) { dfprintk(VFS, "NFS: found cookie %Lu\n", (long long)entry->cookie); if (entry->prev_cookie == desc->target) break; if (loop_count++ > 200) { loop_count = 0; schedule(); } } dfprintk(VFS, "NFS: find_dirent() returns %d\n", status); return status; }
/* * Retire a per-inode cookie, destroying the data attached to it. */ void nfs_fscache_zap_inode_cookie(struct inode *inode) { struct nfs_inode *nfsi = NFS_I(inode); dfprintk(FSCACHE, "NFS: zapping cookie (0x%p/0x%p)\n", nfsi, nfsi->fscache); fscache_relinquish_cookie(nfsi->fscache, 1); nfsi->fscache = NULL; }
/* * Attempt to clear the private state associated with a page when an error * occurs that requires the cached contents of an inode to be written back or * destroyed * - Called if either PG_private or fscache is set on the page * - Caller holds page lock * - Return 0 if successful, -error otherwise */ static int nfs_launder_page(struct page *page) { struct inode *inode = page->mapping->host; struct nfs_inode *nfsi = NFS_I(inode); dfprintk(PAGECACHE, "NFS: launder_page(%ld, %llu)\n", inode->i_ino, (long long)page_offset(page)); nfs_fscache_wait_on_page_write(nfsi, page); return nfs_wb_page(inode, page); }
/* * Attempt to release the private state associated with a page * - Called if either PG_private or PG_fscache is set on the page * - Caller holds page lock * - Return true (may release page) or false (may not) */ static int nfs_release_page(struct page *page, gfp_t gfp) { dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); if (gfp & __GFP_WAIT) nfs_wb_page(page->mapping->host, page); /* If PagePrivate() is set, then the page is not freeable */ if (PagePrivate(page)) return 0; return nfs_fscache_release_page(page, gfp); }
/* * Flush any dirty pages for this process, and check for write errors. * The return status from this call provides a reliable indication of * whether any write errors occurred for this process. */ static int nfs_fsync(struct file *file, struct dentry *dentry, int datasync) { struct nfs_open_context *ctx = nfs_file_open_context(file); struct inode *inode = dentry->d_inode; dfprintk(VFS, "nfs: fsync(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino); nfs_inc_stats(inode, NFSIOS_VFSFSYNC); return nfs_do_fsync(ctx, inode); }
/* * Once we've found the start of the dirent within a page: fill 'er up... */ static int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, filldir_t filldir) { struct file *file = desc->file; struct nfs_entry *entry = desc->entry; unsigned long fileid; int loop_count = 0, res; dfprintk(VFS, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n", (long long)desc->target); for(;;) { unsigned d_type = DT_UNKNOWN; /* Note: entry->prev_cookie contains the cookie for * retrieving the current dirent on the server */ fileid = nfs_fileid_to_ino_t(entry->ino); /* Use readdirplus info */ if (desc->plus && (entry->fattr->valid & NFS_ATTR_FATTR)) d_type = nfs_type_to_d_type(entry->fattr->type); res = filldir(dirent, entry->name, entry->len, entry->prev_cookie, fileid, d_type); if (res < 0) break; file->f_pos = desc->target = entry->cookie; if (dir_decode(desc) != 0) { desc->page_index ++; break; } if (loop_count++ > 200) { loop_count = 0; schedule(); } } dir_page_release(desc); dfprintk(VFS, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", (long long)desc->target, res); return res; }
/* * Recurse through the page cache pages, and return a * filled nfs_entry structure of the next directory entry if possible. * * The target for the search is 'desc->target'. */ static inline int readdir_search_pagecache(nfs_readdir_descriptor_t *desc) { int loop_count = 0; int res; dfprintk(VFS, "NFS: readdir_search_pagecache() searching for cookie %Lu\n", (long long)desc->target); for (;;) { res = find_dirent_page(desc); if (res != -EAGAIN) break; /* Align to beginning of next page */ desc->page_index ++; if (loop_count++ > 200) { loop_count = 0; schedule(); } } dfprintk(VFS, "NFS: readdir_search_pagecache() returned %d\n", res); return res; }