/* capfs_release() * * Called when the last open file reference for a given file is * finished. We use this as an opportunity to tell the daemon to close * the file when it wants to. */ int capfs_release(struct inode *inode, struct file *f) { int error = 0; struct capfs_inode *pinode; /* update the statistics */ if(capfs_collect_stats) capfs_vfs_stat.release++; PENTRY; update_atime(inode); if (S_ISDIR(inode->i_mode)) { return dcache_dir_close(inode, f); } pinode = CAPFS_I(inode); PDEBUG(D_FILE, "capfs_release called for %s (%ld) [atime: %lu] [mtime: %lu] [ctime: %lu]\n", pinode->name, (unsigned long) pinode->handle, inode->i_atime.tv_sec, inode->i_mtime.tv_sec, inode->i_ctime.tv_sec); error = ll_capfs_hint(pinode, HINT_CLOSE, NULL); /* * remove all associated inode pages from the page cache */ truncate_inode_pages(f->f_dentry->d_inode->i_mapping, 0); PEXIT; return error; }
static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir) { unsigned long pos = filp->f_pos; struct inode *inode = filp->f_dentry->d_inode; struct super_block *sb = inode->i_sb; unsigned offset = pos & ~PAGE_CACHE_MASK; unsigned long n = pos >> PAGE_CACHE_SHIFT; unsigned long npages = dir_pages(inode); lock_kernel(); pos = (pos + SYSV_DIRSIZE-1) & ~(SYSV_DIRSIZE-1); if (pos >= inode->i_size) goto done; for ( ; n < npages; n++, offset = 0) { char *kaddr, *limit; struct sysv_dir_entry *de; struct page *page = dir_get_page(inode, n); if (IS_ERR(page)) continue; kaddr = (char *)page_address(page); de = (struct sysv_dir_entry *)(kaddr+offset); limit = kaddr + PAGE_CACHE_SIZE - SYSV_DIRSIZE; for ( ;(char*)de <= limit; de++) { char *name = de->name; int over; if (!de->inode) continue; offset = (char *)de - kaddr; over = filldir(dirent, name, strnlen(name,SYSV_NAMELEN), (n<<PAGE_CACHE_SHIFT) | offset, fs16_to_cpu(SYSV_SB(sb), de->inode), DT_UNKNOWN); if (over) { dir_put_page(page); goto done; } } dir_put_page(page); } done: filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset; update_atime(inode); unlock_kernel(); return 0; }
/* Update usage from here to top of tree, so that scan of top-level directories will give a useful result */ static void autofs4_update_usage(struct dentry *dentry) { struct dentry *top = dentry->d_sb->s_root; for(; dentry != top; dentry = dentry->d_parent) { struct autofs_info *ino = autofs4_dentry_ino(dentry); if (ino) { update_atime(dentry->d_inode); ino->last_used = jiffies; } } }
extern int vnode_shadow_iop_readlink( DENT_T *dentry, char * buf, int buflen ) { DENT_T *real_dentry; INODE_T *real_inode; VNODE_T *cvp; int err = 0; real_dentry = REALDENTRY_LOCKED(dentry, &cvp); if (real_dentry == NULL) /* We lost a race with delete. */ return -ENOENT; VNODE_DGET(real_dentry); if (real_dentry->d_inode == NULL) { /* We lost a race with delete. */ err = -ENOENT; goto out; } real_inode = real_dentry->d_inode; if (real_inode->i_op && real_inode->i_op->readlink) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) /* In the 2.6.16 kernel update_atime is replaced by touch_atime * which takes a pointer to the vfsmount structure as well. We * don't have such a beast so we just punt since this will go * away when we get rid of the shadow filesystem. */ update_atime(real_inode); #endif /* Our caller has set the address space according to where the buffer is. */ err = (*real_inode->i_op->readlink)(real_dentry, buf, buflen); dentry->d_inode->i_atime = real_inode->i_atime; } else { err = -EINVAL; } out: VNODE_DPUT(real_dentry); REALDENTRY_UNLOCK(dentry, cvp); return(err); }
/* capfs_file_write(file, buf, count, ppos) * * Notes: * - generally the pointer to the position passed in is a pointer to * file->f_pos, so that doesn't need to be updated as well. */ static ssize_t capfs_file_write(struct file *file, const char *cbuf, size_t count, loff_t *ppos) { int error = 0, retsz = 0, kern_write = 0; struct inode *inode; capfs_off_t capfs_pos = *ppos; size_t xfersize; char *buf = (char *) cbuf; /* update the statistics */ if(capfs_collect_stats) { capfs_vfs_stat.write++; capfs_rwop_stats(1,count); } if(get_fs().seg == get_ds().seg) { kern_write = 1; } PENTRY; /* should we error check here? do we know for sure that the dentry is * there? */ inode = file->f_dentry->d_inode; /* Added by Alan Rainey 9-10-2003 */ if (strcmp(file->f_dentry->d_name.name, (char *)(strrchr(CAPFS_I(inode)->name, '/')+1))) { if ((error = capfs_inode_getattr(file->f_dentry)) < 0) { PEXIT; return error; } } PDEBUG(D_FILE, "capfs_file_write called for %s (%ld), offset %ld, size %ld\n", CAPFS_I(inode)->name, (unsigned long) CAPFS_I(inode)->handle, (long) capfs_pos, (long) count); if (access_ok(VERIFY_READ, (char *)buf, count) == 0){ PEXIT; return -EFAULT; } if (count == 0){ PEXIT; return 0; } /* split our operation into blocks of capfs_maxsz or smaller */ do { xfersize = (count < capfs_maxsz) ? count : capfs_maxsz; error = ll_capfs_file_write(CAPFS_I(inode), buf, xfersize, &capfs_pos, kern_write); if (error <= 0){ int err = error; PEXIT; return err; } retsz += error; /* position is updated by ll_capfs_file_write() */ count -= xfersize; buf += xfersize; } while (count > 0); *ppos = capfs_pos; if (capfs_pos > i_size_read(inode)) { i_size_write(inode, capfs_pos); } update_atime(inode); PEXIT; return retsz; }