static void nfs_process_unlinkatend(void) { struct uae *p; //fprintf(stderr,"NFS_PROCESS_UNLINKATEND \n"); for (p = uae_base; p != NULL ; p = p->next) { //fprintf(stderr,"REMOVING %s\n",(char *)&p->name[0]); nfs_proc_remove(&p->fh,(char *)&p->name[0]); } }
void nfs_sillyrename_cleanup(struct inode *inode) { struct inode *dir = NFS_RENAMED_DIR(inode); char silly[14]; int error, slen; slen = sprintf(silly, ".nfs%ld", inode->i_ino); error = nfs_proc_remove(NFS_SERVER(dir), NFS_FH(dir), silly); nfs_lookup_cache_remove(dir, NULL, silly); if (error < 0) printk("NFS silly_rename cleanup failed (err = %d)\n", -error); NFS_RENAMED_DIR(inode) = NULL; iput(dir); }
static int nfs_unlink(struct inode *dir, const char *name, int len) { int error; if (!dir || !S_ISDIR(dir->i_mode)) { printk("nfs_unlink: inode is NULL or not a directory\n"); iput(dir); return -ENOENT; } if (len > NFS_MAXNAMLEN) { iput(dir); return -ENAMETOOLONG; } if ((error = nfs_sillyrename(dir, name, len)) < 0) { error = nfs_proc_remove(NFS_SERVER(dir), NFS_FH(dir), name); nfs_lookup_cache_remove(dir, NULL, name); } iput(dir); return error; }
/* The following X functions affect are the only ones that affect the name cache (and the directory cache): nfs_open (in file nfs_lookup_cache.c), nfs_lookup (in file nfs_lookup_cache.c), nfs_link, nfs_symlink, nfs_mkdir, nfs_rmdir, nfs_rename */ int nfs_unlink(struct file *dirp, const char *name) { nfsc_p d,f; int dev; struct nfs_fh *fhandle; int status,lookup_status; DPRINTF(CLU_LEVEL,("** nfs_unlink %s\n",name)); demand(dirp, bogus filp); d = GETNFSCE(dirp); fhandle = GETFHANDLE(dirp); dev = FHGETDEV(fhandle); lookup_status = nfs_cache_lookup(dev,GETNFSCEINO(d),name,&f); switch(lookup_status) { case -1: /* negative cache hit, treat it as a miss to be sure is properly removed */ case 0: /* cache miss */ { struct nfs_fh fhandle2; struct nfs_fattr temp_fattr; k2printf("nfs_unlink: nfs_proc_lookup %s\n",name); status = nfs_proc_lookup(fhandle, name, &fhandle2, &temp_fattr); if (status != 0) { errno = status; return -1; } f = nfsc_get(dev,temp_fattr.fileid); nfs_fill_stat(&temp_fattr, f); } /* fall-through now that we have setup f */ case 1: /* cache hit */ if (nfsc_get_refcnt(f) == 1) { /* last copy */ if (S_ISDIR(nfsc_get_mode(f))) { status = nfs_proc_rmdir(fhandle, name); //fprintf(stderr,"rmdir status %d\n",status); } else { status = nfs_proc_remove(fhandle,name); //fprintf(stderr,"remove status %d\n",status); } if (status == 0) { nfs_cache_remove(dirp,NULL); nfs_flush_filp(dirp); } nfsc_put(f); if (status != 0) { errno = status; return -1; } return 0; } else { /* has other references */ static int i = 0; char difname[NAME_MAX]; //fprintf(stderr,"removing a file that is still referenced: %s\n",name); demand (!(S_ISDIR(f->sb.st_mode)), removing last ref directory); if (i == 0) atexit(nfs_process_unlinkatend); sprintf(difname,".nfs%d%d.%s",time(0),i++,name); status = nfs_proc_rename(fhandle,name,fhandle,difname); if (status != 0) fprintf(stderr,"could not rename %s\n",name); nfs_cache_remove(dirp,name); nfs_flush_filp(dirp); nfs_unlinkatend(difname, fhandle); nfsc_put(f); /* since it will be unlinked we can avoid flushing on close */ nfsc_or_flags(f,NFSCE_WILLBEGONE); return 0; } default: PR; assert(0); return 0; } }